私はPythonで2つのNLPプロジェクトに取り組んでおり、どちらも次のように、文から数値を抽出し、比較演算子と同様のタスクを実行します。
"... greater than $10 ... ",
"... weight not more than 200lbs ...",
"... height in 5-7 feets ...",
"... faster than 30 seconds ... "
この問題を解決するための2つの異なるアプローチが見つかりました。
このような文から数値を解析するにはどうすればよいですか?これはNLPの一般的なタスクだと思います。
望ましい出力は次のようになります。
入力:
「10ドル超」
出力:
{'value': 10, 'unit': 'dollar', 'relation': 'gt', 'position': 3}
私はおそらくこれをチャンクタスクとしてアプローチし、nltk
の品詞タガーとその正規表現チャンカーを組み合わせて使用します。これにより、単語そのものではなく、文中の単語の品詞に基づいて正規表現を定義できます。特定の文について、次のことができます。
import nltk
# example sentence
sent = 'send me a table with a price greater than $100'
私が最初に行うことは、品詞タガーをあまり混乱させないように文を少し修正することです。 (非常に単純な正規表現を使用して)実行できる変更の例をいくつか示しますが、他に変更がないかどうかを実験して確認できます。
$10 -> 10 dollars
200lbs -> 200 lbs
5-7 -> 5 - 7 OR 5 to 7
だから私たちは得る:
sent = 'send me a table with a price greater than 100 dollars'
これで、文章から品詞を取得できます。
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')]
chunker を作成して、(比較的)単純な正規表現に従ってPOSタグ付きテキストをチャンク化します。
grammar = 'NumericalPhrase: {<NN|NNS>?<RB>?<JJR><IN><CD><NN|NNS>?}'
parser = nltk.RegexpParser(grammar)
これは、数値フレーズ(ここではフレーズタイプと呼びます)を分割する文法を使用してパーサーを定義します。これは、数値フレーズを次のように定義します。オプションの名詞、オプションの副詞、比較形容詞、前置詞、数字、オプションの名詞。これは、フレーズを定義する方法の提案にすぎませんが、これは、単語自体に正規表現を使用するよりもはるかに簡単だと思います。
あなたができるあなたのフレーズを取得するには:
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))
または、あなたができるあなたのフレーズだけを得るために:
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')]]