[groonga-dev,01793] Re: mecabトークナイザでのtoo long sentenceの回避方法について

Back to archive index

Kouhei Sutou kou****@clear*****
2013年 9月 20日 (金) 16:12:19 JST


須藤です。

In <CANM+Hhcu=Y--BsHq3nfiJPaJ1N2Rhu0XFTeb54ms=HA0dn****@mail*****>
  "[groonga-dev,01791] mecabトークナイザでのtoo long sentenceの回避方法について" on Fri, 20 Sep 2013 08:43:32 +0900,
  Naoya Murakami <visio****@gmail*****> wrote:

> mecabのtoo long sentenceについて、なにかいい回避方法案はないでしょうか?

今回の入力は改行を越えて意味が繋がっていないんですよね。例え
ば、

私の
名前は
中野です。

とあったときに本当は「私の名前は中野です。」という意味だけど
横に長くなるので開業している、ということはないですよね、とい
うことです。(私が書くメールの本文は30文字くらいずつで改行し
ていますが、そのような改行の使い方ではないですよね、というこ
とです。)

であれば、mecab_sparse_tostr2()に渡す直前で改行で区切って、n
回mecab_sparse_tostr2()を呼ぶのがよいのではないかと思いました。

    s = mecab_sparse_tostr2(tokenizer->mecab,
                            normalized_string,
                            normalized_string_length);
    ...

というのを

  char **normalized_lines = split_to_lines(normalized_string, normalized_string_length);
  for (; *normalized_lines; normalized_lines++) {
    s = mecab_sparse_tostr2(tokenizer->mecab,
                            *normalized_lines,
                            strlen(*normalized_lines));
    ...
  }

みたいな感じにするイメージです。(実際はchar **を作らないで
mecab_sparse_tostr2()に渡す文字列の長さを調整してメモリを割り
当てないようにすると思います。)

n回mecab_sparse_tostr2()すると、↑でいうsをぜんぶ結合しない
といけないのが面倒なところです。もともとは
GRN_PLUGIN_MALLOC()していたのですが、そうすると結合するとき
にメモリを拡張してとかしないといけなくて面倒なので
GRN_TEXT_PUTS()でそこらへんを気にせずに追加できるようにして
おきました。

https://github.com/groonga/groonga/blob/master/plugins/tokenizers/mecab.c#L157


ただ、問題があって。。。
NormalizerAutoは改行を削除するので正規化後は改行があった位置
がわからなくなるのです。しかーし、今回のケースでは必ず「<BR>」
が入っているようなので、正規化後の文字列を「<BR>」で区切って
mecab_sparse_tostr2()をn回呼ぶようにするのがいいんじゃないか
と思います。


> なお、コマンドラインからMecabに直接渡せば、too long sentenseは
> 発生しませんでした。

mecabコマンドのソースをながめてみたところ、mecabコマンドでは
改行毎にmecab_sparse_tostr2()相当の処理をしていました。その
ため、「too long sentence.」なエラーにはならないのだと思いま
す。また、1行が長すぎるときは

  input-buffer overflow. The line is split. use -b #SIZE option.

というエラーがでます。(最後の2行ででている)

  % mecab -Owakati < mecab_too_long_sentense_CRchar.sql  > /dev/null
  CREATE DATABASE IF NOT EXISTS mecab _ too _ long _ sentense ; 
  use mecab _ too _ long _ sentense ; 
  drop table ftext ; 
  CREATE TABLE IF NOT EXISTS ` ftext ` ( 
  ` id ` int ( 10 ) NOT NULL , 
  ` description ` longtext NOT NULL , 
  PRIMARY KEY (` id `), 
  FULLTEXT KEY ` description ` (` description `) COMMENT ' parser " TokenMecab ", normalizer " NormalizerAuto "' 
  ) ENGINE = mroonga DEFAULT CHARSET = utf 8 ; 
  INSERT INTO ` ftext ` (` id `, ` description `) VALUES 
  input-buffer overflow. The line is split. use -b #SIZE option.
  input-buffer overflow. The line is split. use -b #SIZE option.

このチェックはmecab_sparse_tostr2()相当の処理に渡す前に実行
しているので、やはり「too long sentence.」なエラーにはならな
いのだと思います。


> <環境>
> CentOS6.4
> groonga 最新マスタ
> Mecab 0.994 (groongaのyumリポジトリのもの)
> unidic
> 
> <再現可能なデータ>
> https://github.com/naoa/groonga-saigen

ありがとうございます!
データがあってとても助かりました!
CentOS 6でWINGリポジトリをつかったやつだと再現したのですが、
Debian GNU/Linuxのパッケージでは再現しなかったのがなぞです
が。。。


-- 
須藤 功平 <kou****@clear*****>
株式会社クリアコード <http://www.clear-code.com/> (03-6231-7270)

groongaサポート:
  http://groonga.org/ja/support/
パッチ採用はじめました:
  http://www.clear-code.com/recruitment/
コミットへのコメントサービスはじめました:
  http://www.clear-code.com/services/commit-comment.html




groonga-dev メーリングリストの案内
Back to archive index