
テキストの分類がアパートを見つけるのにどのように役立ったか、また、正規表現とニューラルネットワークを拒否し、字句解析器を使用し始めた理由を説明します。
約1年前、賃貸用のアパートを見つける必要がありました。 個人からの広告の大部分はソーシャルネットワークに公開されており、広告は自由な形式で記述されており、検索用のフィルターはありません。 さまざまなコミュニティの出版物を手動で表示するのは長く、非効率的です。
当時、ソーシャルネットワークから広告を収集してサイトに公開するサービスが既にいくつかありました。 したがって、すべての広告を1か所で見ることができました。 残念ながら、広告の種類、価格によるフィルターもありませんでした。 そのため、しばらくして、必要な機能を備えた独自のサービスを作成したいと考えました。
テキスト分類
最初の試行(RegExp)
最初は、 正規表現で問題を真正面から解決しようと考えました。
正規表現自体を書くことに加えて、結果をさらに処理する必要がありました。 発生回数と互いの相対的な位置を考慮する必要がありました。 問題は、文のテキストを処理することでした。1つの文を別の文から分離することは不可能であり、テキストは一度に処理されました。
正規表現がより複雑になり、結果が処理されるにつれて、テストサンプルの正解の割合を増やすことがますます困難になりました。
テストで使用される正規表現
- '/(|\d.{0,10}[^])/u' - '/(\D{4})/u' - '/(((^|\D)1\D{0,30}(\.||)||)|(\D{0,3}1(\D).{0,10}))/u' - '/(((^|\D)2\D{0,30}(\.||)|.{0,5}||.{5,10}(\.||))|(\D{0,3}2(\D).{0,10}))/u' - '/(((^|\D)3\D{0,30}(\.||)|(|).{0,5}|(|)|(|).{5,10}(\.||))|(\D{0,3}3(\D).{0,10}))/u' - '/(((^|\D)4\D{0,30}(\.||)|\S)|(\D{0,3}4(\D).{0,10}))/u' - '/()/u' - '/(.{1,5})/u' - '/(|||(|))/u' - '/(\?)$/u'
このテストスイートの方法では、正解の72.61%が得られました 。
2回目の試行(ニューラルネットワーク)
最近、あらゆるものに機械学習を使用することが非常にファッショナブルになりました。 ネットワークを訓練した後、なぜそのように決定したかを言うことは困難または不可能ですらありますが、これはテキストの分類におけるニューラルネットワークの使用の成功を妨げません。 テストでは、 バックパースペクティブエラートレーニング法で多層パーセプトロンを使用しました。
既成のニューラルネットワークのライブラリが使用されたため:
FANNは C で書かれています
脳は JavsScript で書かれています
一定の入力数でニューラルネットワークの入力に入力できるように、異なる長さのテキストを変換する必要がありました。
このため、テストサンプルのすべてのテキストから、テキストの15%以上で繰り返される2文字以上のn-gramが明らかになりました。 彼らは200人強でした 。
N-gramの例
- //u - //u - //u - //u - //u - //u - //u - //u - //u
1つの広告を分類するために、テキスト内でn-gramが検索され、その場所が検出された後、このデータがニューラルネットワークの入力に送られ、値が0から1の範囲になるようにしました。
テストスイートのこの方法では、 77.13%の正解が得られました(トレーニングが実行されたのと同じサンプルでテストが実行されたという事実にもかかわらず)。
数桁高いテストスイートとフィードバックネットワークを使用すると、はるかに優れた結果を達成できると確信しています 。
3回目の試行(パーサー)
同時に、 自然言語処理に関する記事を読み始め、Yandexの素晴らしいTomitaパーサーに出会いました。 他の同様のプログラムに対するその主な利点は、ロシア語で動作し、かなり明確なドキュメントがあることです。 設定には正規表現を使用できます。正規表現の一部はすでに記述されているため、非常に便利です。
基本的に、これは正規表現オプションのはるかに高度なバージョンですが、はるかに強力で便利です。 また、テキストの予備処理なしではできませんでした。 ソーシャルネットワーク上でユーザーが書くテキストは、言語の文法や構文の規範を満たさないことが多いため、パーサーはそれを処理するのが困難です。テキストを文に分割する、文を語彙単位に分割する、単語を標準形式に変換する
構成例
#encoding "utf8" #GRAMMAR_ROOT ROOT Rent -> Word<kwset=[rent, populate]>; Flat -> Word<kwset=[flat]> interp (+FactRent.Type=""); AnyWordFlat -> AnyWord<kwset=~[rent, populate, studio, flat, room, neighbor, search, number, numeric]>; ROOT -> Rent AnyWordFlat* Flat { weight=1 };
すべての構成はここで見つけることができます 。 このテストスイートの方法では、正解の93.40%が得られました 。 テキストの分類に加えて、レンタル価格、アパートエリア、地下鉄駅、電話などの事実もそこから強調表示されます。
パーサーをオンラインで試す
リクエスト:
答えは:
広告タイプ:
0-部屋
1-1ベッドルームアパートメント
2-2ベッドルームアパートメント
3-3ベッドルームアパートメント
4-4 +ルームアパートメント
curl -X POST -d ' 50.4 . 30 . + 7 999 999 9999' 'http://api.socrent.ru/parse'
答えは:
{"type":2,"phone":["9999999999"],"area":50.4,"price":30000}
広告タイプ:
0-部屋
1-1ベッドルームアパートメント
2-2ベッドルームアパートメント
3-3ベッドルームアパートメント
4-4 +ルームアパートメント
その結果、小さなテストスイートと高精度が必要なため、アルゴリズムを手動で記述する方が収益性が高いことがわかりました。

サービス開発
テキスト分類の問題の解決と並行して、広告を収集してユーザーフレンドリーな形式で表示するためにいくつかのサービスが作成されました。
github.com/mrsuh/rent-view
表示を担当するサービス。
NodeJSで記述されています。 テンプレートエンジンdoT.jsとMongoデータベースが使用されました。
github.com/mrsuh/rent-collector
広告の収集を担当するサービス。 PHPで書かれています 。 Symfony3フレームワークとMongoデータベースを使用します。
さまざまなソースからデータを収集することを期待して書いたが、判明したように、ほとんどすべての広告はソーシャルネットワークVkontakteに投稿されています。 このソーシャルネットワークには優れたAPIがあるため、公共グループの壁やディスカッションから広告を収集することは難しくありませんでした。
github.com/mrsuh/rent-parser
広告の分類を担当するサービス。 Golangで書かれています 。 富田パーサーを使用します。 本質的には、パーサーのラッパーですが、テキストの予備処理と解析結果の後続処理も実行します。
すべてのサービスで、CIはTravis-CIとAnsibleを使用して構成されます(自動展開の構成方法については、 この記事で説明します )。
統計
このサービスはサンクトペテルブルク市で約2か月間機能しており、この期間中に8000件を超える広告を収集することができました。 期間全体の広告に関する興味深い統計を以下に示します。
平均して、 1日あたり131.2の広告が追加されます(より正確には、広告として分類されたテキスト)。

最もアクティブな時間は12日間です。

最も人気のある地下鉄駅Devyatkino

結論 :ネットワークをトレーニングできる大きなテストサンプルがなく、同時に高い精度が必要な場合は、手書きのアルゴリズムを使用するのが最適です。
誰かが同様の問題を自分で解決したい場合、 8000個のテキストとそのタイプのテストスイートがあります。