日本語には単語の間に空白がありません。検索するには、まずどこで切るかを決める必要があります。
3通りの切り方を同じ検索で測りました。単語で区切ると索引に入る語が445個から273個に減り、それでいてnDCGは0.775から0.907に上がりました。
3通りの切り方を同じ検索で測りました。単語で区切ると索引が小さくなり、成績も落ちません。
日本語トークナイザで切り方を変えると何が起きるのかを、実際に走らせて測りました。使ったのは社内規程を模した文書13件と、問い5件です。
単語で区切る処理にはNodeに標準で入っている区切りの仕組みを使いました。追加の導入をせずに動かせます。
const seg = new Intl.Segmenter('ja', { granularity: 'word' });
const WAYS = [
['1文字ずつ', (s) => [...s.replace(/[。、\s]/g, '')]],
['2文字ずつ', (s) => bigrams(s)],
['単語で区切る', (s) => [...seg.segment(s)].filter((x) => x.isWordLike).map((x) => x.segment)],
];
区切り方 語の種類 索引に入る語数 適合率@3 再現率@3 nDCG@3 1文字ずつ 155種 458個 0.467 0.900 0.923 2文字ずつ 307種 445個 0.467 0.900 0.775 単語で区切る 122種 273個 0.467 0.900 0.907 同じ一文を、3通りで区切ったところ 1文字ずつ 18個 宿|泊|費|の|上|限|は|1|泊|1|2|0|… 2文字ずつ 17個 宿泊|泊費|費の|の上|上限|限は|は1|1泊|泊1|12|20|00|… 単語で区切る 11個 宿泊|費|の|上限|は|1|泊|12000|円|と|する
上の表を見てください。単語で区切ると索引に入る語が445個から273個になりました。語の種類は307種から122種です。
下の例を見ると理由が分かります。2文字ずつだと「泊費」「費の」「の上」のような、語として意味のない組み合わせまで索引に入ります。
単語で区切れば「宿泊」「上限」だけが残ります。数字の12000も1語にまとまります。2文字ずつだと12と20と00に割れます。
索引が小さくなってもnDCGは下がりません。0.775から0.907に上がりました。
1文字ずつが0.923で最も高くなりましたが、索引の語数は458個です。文書13件という小ささでは、1文字ずつでも紛れが起きにくいという条件も効いています。
索引は小さく、成績は落ちない。
For scripts that use the East Asian or Brahmic styles of context analysis, the default word boundary detection is not adequate; it needs tailoring.原文Unicode「UAX #29: Unicode Text Segmentation」 この内容の有効期限2027-02-18
文章を、検索や集計の単位になる語に切ります。日本語には空白がないので、辞書を引いて切る位置を決めます。
日本語トークナイザは、文章を語の単位に切る仕組みです。形態素解析と呼ばれることもあります。
英語なら空白で切れば済みます。日本語には空白がないので、どこが語の切れ目かを別に判断する必要があります。
Unicodeの仕様も、タイ語・ラオ語・中国語・日本語のような言語で語の境界を確実に検出するには、辞書の参照などの仕組みが必要になるとしています。規則だけでは決まりません。
同じ仕様は、東アジアの様式を使う文字では、既定の語境界の検出は十分でなく、調整が要るとも述べています。
前の節で使った標準の仕組みも、この調整が入ったものです。辞書を持たない素朴な規則では日本語は切れません。
3番目が実務では効きます。自社固有の語は、既定の辞書には載っていません。辞書に足すかどうかの判断が要ります。
単語の区切りにはNode標準の仕組みを使いました。専用の解析器とは切り方が違うことがあります。品詞の情報も取れません。品詞まで要る用途では、専用の解析器を入れることになります。表記のゆれの話は表記ゆれの記事で扱っています。
reliable detection of word boundaries in languages such as Thai, Lao, Chinese, or Japanese requires the use of dictionary lookup or other mechanisms原文Unicode「UAX #29: Unicode Text Segmentation」 この内容の有効期限2027-02-18
切り方を変えれば検索が良くなると考えることです。語そのものが違う問いには、切り方では届きません。
日本語トークナイザの切り方を変えると、たしかに索引は変わります。ところが効かない場面もはっきりしています。
区切り方 適合率@3 再現率@3 nDCG@3 1文字ずつ 0.333 0.600 0.600 2文字ずつ 0.400 0.700 0.542 単語で区切る 0.333 0.600 0.584
「宿泊費」を「ホテル代」と聞かれた場合の結果です。どの切り方でも0.6前後まで落ちます。
切り方は、同じ語をどう区切るかの話でしかありません。語そのものが違えば、どう切っても当たりません。ここは別の手立てが要ります。
自社の製品名や社内の略語は、既定の辞書には入っていません。途中で割れて、意図しない語として索引に入ります。
Unicodeの仕様も、実装は既定の結果を上書きして、環境ごとの要件に合わせて調整してよいとしています。辞書を足すのは想定された使い方です。
4番目を忘れないでください。索引を作ったときの切り方と、検索するときの切り方が違うと当たりません。作り直しの話は増分インデックスの記事で扱っています。
切り方で直せるものと、直せないものがある。
As with the other default specifications, implementations are free to override (tailor) the results to meet the requirements of different environments原文Unicode「UAX #29: Unicode Text Segmentation」 この内容の有効期限2027-02-18
同じ課題を持つ会社にとって、動いている設定は「作る時間」を買えるということです。ServiceDockは自作のワークフローやテンプレートを出品できるマーケットプレイスです。手数料や出品の流れは出品者向けページにまとまっています。
出品の仕組みを見る