Issue32について(4096の壁)(Jugemより移植)

Posted by johtani on Wednesday, June 6, 2012

目次

昨晩に引き続き、情けない内容のブログになってしまいますが。。。

昨晩、書いた記事の調査をしていた時に気づいた、問題になるケースがあったので調査をしていました。 Issue32に登録した内容になります。 拙い英語を振り絞って書いた英語なので、伝わらないかもしれないのでブログに残しておきます。 昨晩の問題点となったクラス(StreamTagger2.java)の内部処理についてです。 lucene-gosenのLucene向けのTokenizerの内部処理では入力文字列の処理を行うのに、「char buffer[]」を用いて 入力文字列をReaderから読み込むときにバッファリングしています。 このバッファリングにて、特定のケースにて、想定していない場所を単語の切れ目と認識してしまう問題が実装上存在しました。 Issue32に記載した内容は次のようになります。

上記バッファは4096文字というサイズで固定になっています。 StreamTagger2クラスでは、この4096文字をオーバーするような文字列の場合に、つぎの処理により、4096文字以下の場所に文章の区切りを探そうとします。

  1. 4096文字以上の文字列が入力される
  2. バッファに入れられるだけの文字(4096文字)をバッファにコピーする。
  3. バッファの後ろから、つぎの5種類の文字を探索し、見つかった場合(場所をkとし、k>0の場合)は、その場所を文章の切れ目と判定して、0からk+1文字目までの文字をStringTaggerを利用して形態素解析する。
  4. あとは、繰り返し
  5. 上記条件に合致しない場合は、4096文字を文章とみなして形態素解析を行います。

ここで、5種類の文字は以下のとおり。


0x000D:CARRIAGE RETURN(CR)
0x000A:LINE FEED(LF)
0x0085:NEXT LINE (NEL)
0x2028:LINE SEPARATOR
0x2029:PARAGRAPH SEPARATOR

見ての通り、制御文字ばかりです。 この5文字以外は切れ目と判断してくれません。 ということで、4097文字の文字列が存在し、上記5種類の文字が一度も出てこない場合、バッファのサイズで文字列が途切れてしまい、想定しない区切り位置で区切られた文章に対して形態素解析が実行されてしまいます. HTMLから文字列を抜き出して解析したり、長い文書を解析する場合に、改行文字を削除して処理するといったことも考えられます。 上記5種類の文字列のみで文章の区切り位置を判断してしまうのは問題ではないかと。 まずは、4096文字内に「。」句点が存在した場合に、その部分を区切り位置として認識するようなパッチを記載して、Issue32に添付しました。

「。」句点を採用した理由はつぎのとおりです。 StreamTagger2では、上記バッファリングした文字列を更に、BreakIterator.getSentenceIterator(Locale.JAPANESE)にて取得したBreakIteratorにて文節単位に区切ってから、各文節ごとに形態素解析を実施しています。 ということは、BraekIteratorにて分節の区切りとして判断される文字については、上記の文字種に追加しても問題無いという判断からです。 ただし、この修正でも、純粋に4096文字以上、句点が出てこない場合には区切り位置がおかしなことになってしまいますが。。。 もう少し、BreakIteratorの挙動を調べて、他にも利用可能な区切り文字が存在しないかを調査していく予定です。。。

1年以上コミッターをやっているのに、こんなことも理解していないのかよいうツッコミを受けてしまいそうでなんとも情けない話です。。。 まずは、現状報告でした。


comments powered by Disqus

See Also by Hugo


Related by prelims-cli