2017-07-16 31 views
32

tôi đang làm việc trên hai NLP-dự án bằng Python, và cả hai đều có nhiệm vụ tương tự để trích xuất các giá trị và toán tử so sánh từ câu như:Làm thế nào để trích xuất số (cùng với các tính từ so sánh hoặc dãy)

"... greater than $10 ... ", 
"... weight not more than 200lbs ...", 
"... height in 5-7 feets ...", 
"... faster than 30 seconds ... " 

tôi thấy hai cách khác nhau để giải quyết vấn đề này, một cách sử dụng các biểu thức chính quy rất phức tạp, và một cách sử dụng NER (và một số regex cũng vậy).

Tôi làm cách nào để phân tích giá trị của các câu như vậy? Tôi cho rằng đây là một nhiệm vụ phổ biến trong NLP.


Kết quả mong muốn sẽ là một cái gì đó như:

Input:

"lớn hơn $ 10"

Output:

{'value': 10, 'unit': 'dollar', 'relation': 'gt', 'position': 3} 
+0

Sử dụng gói CogComp-lượng hóa: https: // github.com/CogComp/cogcomp-nlp/tree/master/pipeline Nó có thể trích xuất số lượng và chuẩn hóa đơn vị của chúng. – Daniel

+1

Facebook vịt con là tốt cho nhiệm vụ này https://github.com/facebookincubator/duckling –

Trả lời

24

Tôi có lẽ sẽ tiếp cận điều này như là một nhiệm vụ chunking và sử dụng một phần của tagger lời nói kết hợp với chunker biểu thức chính quy của nó nltk. Điều này sẽ cho phép bạn xác định một biểu thức chính quy dựa trên một phần của lời nói của các từ trong câu của bạn thay vì trên các từ chính mình. Đối với một câu nhất định, bạn có thể thực hiện như sau:

import nltk 

# example sentence 
sent = 'send me a table with a price greater than $100' 

Điều đầu tiên tôi cần làm là sửa đổi các câu của bạn một chút để bạn không nhầm lẫn một phần của trình gắn thẻ lời nói quá nhiều. Dưới đây là một số ví dụ về những thay đổi mà bạn có thể thực hiện (với biểu thức thông thường rất đơn giản) nhưng bạn có thể thử nghiệm và xem nếu có những người khác:

$10 -> 10 dollars 
200lbs -> 200 lbs 
5-7 -> 5 - 7 OR 5 to 7 

vì vậy chúng tôi nhận được:

sent = 'send me a table with a price greater than 100 dollars' 

bây giờ bạn có thể nhận được các bộ phận của bài diễn văn từ câu của bạn:

sent_pos = nltk.pos_tag(sent.split()) 
print(sent_pos) 

[('send', 'VB'), ('me', 'PRP'), ('a', 'DT'), ('table', 'NN'), ('with', 'IN'), ('a', 'DT'), ('price', 'NN'), ('greater', 'JJR'), ('than', 'IN'), ('100', 'CD'), ('dollars', 'NNS')] 

Chúng tôi bây giờ có thể tạo ra một chunker mà sẽ đoạn POS của bạn được gắn thẻ văn bản theo một biểu thức chính quy (tương đối) đơn giản:

grammar = 'NumericalPhrase: {<NN|NNS>?<RB>?<JJR><IN><CD><NN|NNS>?}' 
parser = nltk.RegexpParser(grammar) 

Điều này định nghĩa một trình phân tích cú pháp theo cụm từ số (chúng tôi gọi loại cụm từ của bạn). Nó định nghĩa cụm từ số của bạn là: một danh từ tùy chọn, theo sau là một trạng từ tùy chọn, theo sau là một tính từ so sánh, một giới từ, một số và một danh từ tùy chọn. Đây chỉ là gợi ý về cách bạn có thể muốn xác định các cụm từ của mình, nhưng tôi nghĩ rằng điều này sẽ đơn giản hơn nhiều so với việc sử dụng cụm từ thông dụng trên các từ.

Để có được cụm từ của bạn, bạn có thể làm:

print(parser.parse(sent_pos)) 
(S 
    send/VB 
    me/PRP 
    a/DT 
    table/NN 
    with/IN 
    a/DT 
    (NumericalPhrase price/NN greater/JJR than/IN 100/CD dollars/NNS)) 

Hoặc để có được chỉ cụm từ của bạn, bạn có thể làm:

print([tree.leaves() for tree in parser.parse(sent_pos).subtrees() if tree.label() == 'NumericalPhrase']) 

[[('price', 'NN'), 
    ('greater', 'JJR'), 
    ('than', 'IN'), 
    ('100', 'CD'), 
    ('dollars', 'NNS')]] 
Các vấn đề liên quan