1

次のような行が与えられた場合

1ポンドの牛肉

成分を抽出したい。最初は成分名だけに興味があります。

ruby の有名な時刻パーサー Chronic を見て、その正規表現の使用が気に入りました。

 def self.scan_for_month_names(token)
scanner = {/^jan\.?(uary)?$/ => :january,
           /^feb\.?(ruary)?$/ => :february,
           /^mar\.?(ch)?$/ => :march,
           /^apr\.?(il)?$/ => :april,
           /^may$/ => :may,
           /^jun\.?e?$/ => :june,
           /^jul\.?y?$/ => :july,
           /^aug\.?(ust)?$/ => :august,
           /^sep\.?(tember)?$/ => :september,
           /^oct\.?(ober)?$/ => :october,
           /^nov\.?(ember)?$/ => :november,
           /^dec\.?(ember)?$/ => :december}
scanner.keys.each do |scanner_item|
  return Chronic::RepeaterMonthName.new(scanner[scanner_item]) if scanner_item =~ token.word
end
return nil

終わり

ただし、私の場合、おそらく個々の成分ごとに 300 以上の正規表現を作成する必要があります。

また、コリアンダーやコリアンダー リーフなどの同義語も考慮する必要があります。

これまで解析を行ったことはありませんが、ここで正規表現を使用するのが最善の方法です。他に合理的な代替案が思い浮かびません。

4

3 に答える 3

4

まず、成分が常に次の形式をとるとは限らないと想定していますQUANTITY UNIT of INGREDIENT-そうでない場合、これは非常に簡単な作業になります(of

これは難しい問題です。解決策は簡単ではありません。

ここでは、正規表現を使用するのが最善の方法ではない可能性があると思います。

  • あなたが言及したように、各成分に対して多くの式を書く必要があります
  • 可能な成分のリストは常に正規表現リストによって制限され、さらにコンパイルしないと新しい成分を検出できません。
  • 一部の成分を解析するのは非常に困難です( cheese, 1 pound (parmesan))

私は自然言語処理がここに行く方法だと思います。構造化されていない入力がありますが、非常に制限されたコンテキストにあります。

おそらく直観に反するかもしれませんが、成分を見つける最良の方法は、それを探すのではなく、他のすべてのものを探すことだと思います. 行が常にあると仮定すると

  • 数値 (数量)
  • 単位 (ポンド、ティースプーンなど)
  • 成分

数字と単位を検出するのは非常に簡単であるため、最初にそれらを認識してから成分を抽出するのは簡単なはずです.

品詞タガーを使用すると、関連する単語を簡単に識別できます。 [('1', 'LS'), ('pound', 'NN'), ('of', 'IN'), ('Beef', 'NNP')]

そこから、classifierを使用することができます。そのためには、大量の行 (たとえば、数百行) で材料に手動でラベルを付ける必要があります。使用するのに適したいくつかの機能:

  • 行内の単語の位置
  • 事前に計算された成分辞書への存在
  • 品詞タガーの出力
  • 直前と直後の単語(単語の前に「の」がある場合、それは食材である可能性が高いです

いくつかの行に取り組んだ後、数え切れないほどの他の人を見つけることができると確信しています.

最後に、一部の行は作業が非常に難しいと予想しています。1 pound of parmesan cheese, 1 pound of emmentaler: 2 番目の材料もチーズであると推測する必要があります。

ソフトウェアに関しては、使用する言語を選択できる場合、python には素晴らしいNatural Language Toolkitがあります。他の言語のツールキットを保証することはできませんが、他の誰かがそうするかもしれません。

于 2012-12-22T15:42:28.247 に答える
1

まず、各行に対して一連の正規表現チェックを実行し、解析されたテキストを調整していきます。例(擬似コード):

まず、指示を確認します。

/^(add|fold in|stir in|etc...)/

命令を見つけたら、それを行から削除し、フラグを設定して、次の手順を実行します。

instruction = $1
this_line = this_line.substring(instruction.length())

指示が見つかった場合は、後続の指示があったかどうかを確認します(「およびカバー」または「および脇に置いておく」など)

/\b(and\s)(.*)$/

見つかった場合は、それを取り除き、レシピの次の行の前に挿入します

instruction = instruction.substring(0, instuction.length - $1.length - $2.length)
splice $2 into the array of lines immediately following this one

次に、前置詞をチェックします。

/((?in)to\s(.+)/

見つかった場合は、それを使用して機器名、ボウル、計量カップなどを確認できます。使用しない場合でも、解析している文字列から削除して、一致を改善することができます。

最後に、実際の作業は、残っているテキストを使用して行われます。

Check against /^(\d+\s+(?a\s)?\w+)\s*(?of\s*)?(.+)$/

これ$1により、測定単位と$2成分が含まれるようになります。

泡。リンス。繰り返す。その後、アプリがこの情報を使って行う魔法をすべて実行します。

于 2012-12-22T11:42:46.820 に答える