Tomite-parserを使用してテキストを文に分割する

さらなる分析のためにロシア語のテキストを準備するために、私はかつてそれらを文章に分解する必要がありました。 もちろん、自動的に。 テキストを文章に分割する必要がある場合、最初に思い浮かぶのは何ですか? ポイントで分類-推測?



これを始めると、ピリオドは必ずしも文章の区切り文字ではないという事実にすぐに気付くでしょう(「から」、「など」、「など」、「など」、「ストーカー」 」)。 さらに、これらのトークンは、テキストを文に分割するときに常に例外とは限りません。 たとえば、「など」は文の途中にある場合もあれば、末尾にある場合もあります。



質問と感嘆符も、テキストを必ずしも文章に分割するとは限りません。 たとえば、「Yahoo!」 文は、コロンなどの他の文字で区切ることができます(個々のステートメントのリストが続く場合)。



そのため、長い間考えずに完成したツールを探し、YandexのTomitaパーサーに落ち着きました。 彼についてお話します。





一般的に、富田パーサーはテキストから事実を抽出するための強力なツールです。 その中のセグメンター(テキストを文章に分解する)は、プロジェクトの一部にすぎません。 Tomita-parserは、バイナリとしてすぐにダウンロードし、コマンドラインから実行できます。 このシステムは、ルールに基づいて機能し、リソースに対して気まぐれではなく、セグメンテーションプロセスをカスタマイズできるという点で気に入っています。 そして、私の観察によると、ほとんどの場合、それは素晴らしい仕事をします。



また、質問がある場合は、 githubで質問したり、時には回答を得ることもできます。



打ち上げ



富田パーサーはこうして始まります



$ echo "p,  ... ,   ..  .   .    STALKER ." | ./tomita-linux64 config.proto
      
      





つまり、読み取りは標準入力から行われ、出力は標準出力から行われます。

結果は次のようになります。



 [10:01:17 17:06:37] - Start. (Processing files.)  ,   . . .  ,   . .   .    .    STALKER  . [10:01:17 17:06:37] - End. (Processing files.)
      
      







1行-1文。 この例は、内訳が正しいことを示しています。



特徴



私たちが注意を払うもの。



これらの機能は、受信したテキストで次に何をするかに応じて、プラスとマイナスの両方にすることができます。 たとえば、SyntaxNetを使用して結果のテキストのさらに下に構文ツリーを構築します。句読点はスペースで区切る必要があるため、私にとってはプラスです。



設定



アドレスを含むオファーを分析するときに、システムがそれらを誤って分割するという事実に直面しました。 例:



 $ echo "   .       ." | ./tomita-linux64 config.proto [10:01:17 18:00:38] - Start. (Processing files.)     .        . [10:01:17 18:00:38] - End. (Processing files.)
      
      





ご覧のとおり、内訳は間違っていました。 幸いにも、そのようなものはカスタマイズできます。 このために、gztファイルに書き込みます



 TAbbreviation "." { key = { "abbreviation_." type = CUSTOM } text = "." type = NewerEOS }
      
      





つまり、「st。」の後も検討するようお願いします。提案は常に続きます。 私達は試みます:



 $ echo "   .       ." | ./tomita-linux64 config.proto [10:01:17 18:20:59] - Start. (Processing files.)    .        . [10:01:17 18:20:59] - End. (Processing files.)
      
      





今ではすべてが順調です。 githubに投稿した設定の例。



短所は何ですか



上記のいくつかの機能について言及しました。 現時点でのツールの不利な点についてのいくつかの言葉。



最初はドキュメントです。 ですが、すべてが記載されているわけではありません。 上記の設定を検索しようとしましたが、見つかりませんでした。



2つ目は、デーモンモードでパーサーを操作する簡単な機能がないことです。 システム全体をメモリにロードすることを考慮して、0.3〜0.4秒で1つのテキストを処理することは重要ではありません。すべての処理はバックグラウンドプロセスで行われ、致命的なタスクがはるかに多いためです。 一部の人にとって、これはボトルネックになる可能性があります。



PHP呼び出しの例



上で言ったように、入力をstdinに送り、stdoutから読み取ります。 以下の例はgithub.com/makhov/php-tomitaに基づいています

 <?php class TomitaParser { /** * @var string Path to Yandex`s Tomita-parser binary */ protected $execPath; /** * @var string Path to Yandex`s Tomita-parser configuration file */ protected $configPath; /** * @param string $execPath Path to Yandex`s Tomita-parser binary * @param string $configPath Path to Yandex`s Tomita-parser configuration file */ public function __construct($execPath, $configPath) { $this->execPath = $execPath; $this->configPath = $configPath; } public function run($text) { $descriptors = array( 0 => array('pipe', 'r'), // stdin 1 => array('pipe', 'w'), // stdout 2 => array('pipe', 'w') // stderr ); $cmd = sprintf('%s %s', $this->execPath, $this->configPath); $process = proc_open($cmd, $descriptors, $pipes, dirname($this->configPath)); if (is_resource($process)) { fwrite($pipes[0], $text); fclose($pipes[0]); $output = stream_get_contents($pipes[1]); fclose($pipes[1]); fclose($pipes[2]); proc_close($process); return $this->processTextResult($output); } throw new \Exception('proc_open fails'); } /** *    * @param string $text * @return string[] */ public function processTextResult($text) { return array_filter(explode("\n", $text)); } } $parser = new TomitaParser('/home/mnv/tmp/tomita/tomita-linux64', '/home/mnv/tmp/tomita/config.proto'); var_dump($parser->run(' .  .'));
      
      





私たちはチェックします:



 $ php example.php /home/mnv/tmp/tomita/example.php:66: array(2) { [0] => string(32) "  . " [1] => string(32) "  . " }
      
      







結論として



テキストの作業の過程で、著者が自分でセグメンターを作成するプロジェクトに定期的に出くわします。 おそらく、タスクは一見すると実際よりも少し簡単に見えるためです。 この記事が、プロジェクトの一部として次のセグメンターを作成し、完成したオプションを選択することで時間を節約しようとしている人々に役立つことを願っています。



コメントを使用して、テキストを使用する文章に分解するツールを知ってうれしいですか?



All Articles