web-dev-qa-db-ja.com

Spacyの名前付きエンティティの認識を高速化

私はspacyを使用してWebページの住所を認識しています。

私のモデルは基本的に、ここにあるspacyの新しいエンティティタイプのサンプルコードを使用して初期化されます: https://github.com/explosion/spaCy/blob/master/examples/training/train_new_entity_type.py

私のトレーニングデータは、対応する番地エンティティと文字位置を含むプレーンテキストのWebページで構成されています。

迅速にモデルを構築して予測を開始することができましたが、予測速度が非常に遅いことがわかりました。

私のコードは、サーバーの生のHTMLページを反復処理し、反復処理中に各ページのプレーンテキストバージョンをspacyにフィードすることで機能します。入り込めない理由で、反復ループ内で、ページごとにSpacyを使用して予測を行う必要があります。

モデルがロードされた後、私は予測を行う標準的な方法を使用しています。これを予測/評価フェーズと呼びます。

  doc = nlp(plain_text_webpage)

  if len(doc.ents) > 0:

         print ("found entity")

質問:

  1. エンティティの予測/認識フェーズをどのようにスピードアップできますか? AWSでc4.8xlargeインスタンスを使用していますが、spacyがデータを評価しているとき、36個のコアすべてが常に最大になっています。 Spacyは、数百万のWebページの処理を1分のジョブから1時間以上のジョブに変えています。

  2. モデルがより正確になるにつれて、エンティティ認識の速度は向上しますか?

  3. このフェーズでタガーのようなパイプラインを削除する方法はありますか?ERをそのように分離しても正確ですか?他のパイプラインを削除すると、モデル自体に影響しますか、それとも一時的なものですか?

  4. ERトレーニングフェーズでGPUを使用できることを確認しましたが、コードのこの評価フェーズでも使用して、予測を高速化できますか?


更新:

次の方法で処理時間を大幅に短縮できました。

  1. カスタムトークナイザーの使用(ドキュメントにあるものを使用)

  2. 名前付きエンティティ認識用ではない他のパイプラインを無効にする

  3. 各ウェブページからスペイシーにテキスト全体をフィードする代わりに、最大5,000文字以上しか送信しません

モデルをロードするために更新したコード:

nlp = spacy.load('test_model/', disable=['parser', 'tagger', 'textcat'])
nlp.tokenizer = WhitespaceTokenizer(nlp.vocab)
doc = nlp(text)

ただし、まだ遅すぎます(必要な速度の20倍遅い)

質問:

  1. 固有表現抽出を高速化するために他に改善できる点はありますか?スペイシーからカットできる脂肪はありますか?

  2. GPUベースのソリューションが役立つかどうかをまだ探しています-GPUの使用は、名前付きエンティティの認識トレーニングフェーズでサポートされていますが、コードのこの評価フェーズでも使用して、予測を高速化できますか?

9
podcastguy

速度のトラブルシューティングの詳細については、こちらをご覧ください: https://github.com/explosion/spaCy/issues/1508

最も重要なこと:

1)どのBLASライブラリnumpyがリンクされているかを確認し、マシンに合わせて適切にコンパイルされていることを確認します。 condaを使用すると、Intelのmklを入手できるので便利です。

2)

spacyがデータを評価しているとき、AWSと36コアすべてのc4.8xlargeインスタンスは常に最大になります。

それはおそらく悪いことです。 numpyを使用しているため、現時点では行列の乗算を実際に並列化することしかできません。したがって、より大きなチャンクをスレッド化する方法はありません。これは、BLASライブラリが起動するスレッドが多すぎることを意味します。一般に、プロセスごとに3〜4コアしか有益に使用できません。 BLASライブラリの環境変数を設定して、スレッドの数を制限してみてください。

3)nlp.pipe()を使用して、データのバッチを処理します。これにより、行列の乗算が大きくなり、処理がより効率的になります。

4)「処理パイプラインを介したフィードデータ」の外側のループは、おそらく驚異的並列です。だから、それを並列化します。 Pythonのマルチプロセッシング、joblibなど、Sparkなどを使用するか、10個のbashスクリプトを並行して起動します。ただし、可能な限り最も外側の最高レベルの作業を行い、可能な限り独立して実行します。

通常は、1つの大きなVMではなく、複数の小さなVMを実行することをお勧めします。運用上は煩わしいですが、リソース共有が少なくなることを意味します。

4
syllogism_