都内で働くSEの技術的なひとりごと / Technical soliloquy of System Engineer working in Tokyo

都内でサラリーマンやってます。SQL Server を中心とした (2023年からは Azure も。) マイクロソフト系(たまに、OSS系などマイクロソフト以外の技術も...)の技術的なことについて書いています。日々の仕事の中で、気になったことを技術要素関係なく気まぐれに選んでいるので記事内容は開発言語、インフラ等ばらばらです。なお、当ブログで発信、発言は私個人のものであり、所属する組織、企業、団体等とは何のかかわりもございません。ブログの内容もきちんと検証して使用してください。英語の勉強のため、英語の

TF-IDF についてちょっとだけ語ってみる

 顧客先で文書内容の検索について色々聞かせてもらいました。文書内容の検索といえば、全文検索かなぁと単純に思っていましたが、最近はやりの検索手法はそんなに単純なものではないんですね。(自分がこの分野にかなり疎いだけだと思いますが。) tf-idf についてなんとなく理解はできたので、記事にしておこうかと思います。

 Wiki では以下のように説明しています。

tf-idfは、文書中の単語に関する重みの一種であり、主に情報検索文章要約などの分野で利用される。

tf-idfは、tf(単語の出現頻度)とidf(逆文書頻度)の二つの指標にもとづいて計算される。

 \mathrm{tfidf} = \mathrm{tf} \cdot  \mathrm{idf}

 \mathrm{tf_{i,j}} = \frac{n_{i,j}}{\sum_k n_{k,j}}

 \mathrm{idf_i} =  \log \frac{|D|}{|\{d: d \ni t_{i}\}|}

 n_{i,j} は単語iの文書jにおける出現回数、 |D| は総ドキュメント数、|\{d: d \ni t_{i}\}|は単語iを含むドキュメント数である。そのため、idfは一種の一般語フィルタとして働き、多くのドキュメントに出現する語(一般的な語)は重要度が下がり、特定のドキュメントにしか出現しない単語の重要度を上げる役割を果たす。

  • tf とは、Term Frequency すなわち単語出現頻度です。文書内容中にある単語が出現する頻度のことです。上記のWiki の説明文章であれば、『文書』という単語は、3つ出現しています。
  • idf とは、Inverse Document Frequency すなわち逆文書出現頻度です。ある単語が大量の文書に出現するのは、情報として価値がないということのようです。(理解があってるのかな?)検索のシチュエーションにもよりますね。

 

 \mathrm{tf_{i,j}} = \frac{n_{i,j}}{\sum_k n_{k,j}}

 tf は上記の算出式から判断すると、分子は ある文書内に特定の単語がいくつ入っているかを表しているんですね。分母はある文書内に出現するすべての単語の総和ですかね?この辺りは、MeCab あたりを使って分かちき検索で解決できます。

 

 \mathrm{idf_i} =  \log \frac{|D|}{|\{d: d \ni t_{i}\}|}

 idf は 分子は 総文書数で、分母は対象とする単語が含まれている文書数を表します。その対数をとったものです。この2つの値をかけたものが、tf-idf の値です。

 

 SQL Server で tf-idf をやろうとしている人もいますね。(単語解析と出現数のみですが。)ここのページにありました。 

WITH testTable AS
(
SELECT 1 AS Id, N'how now brown cow' AS txt UNION ALL
SELECT 2, N'she sells sea shells upon the sea shore' UNION ALL
SELECT 3, N'red lorry yellow lorry' UNION ALL
SELECT 4, N'the quick brown fox jumped over the lazy dog'
)

SELECT display_term, COUNT(*) As Cnt
FROM testTable
CROSS APPLY sys.dm_fts_parser('"' + REPLACE(txt,'"','""') + '"', 1033, 0,0)
WHERE TXT IS NOT NULL
GROUP BY display_term
HAVING COUNT(*) > 1
ORDER BY Cnt DESC

Returns

display_term                   Cnt
------------------------------ -----------
the                            3
brown                          2
lorry                          2
sea                            2

分かちきの部分を sys.dm_fts_parser でやっていますね。ただ、sys.dm_fts_parser はカタカナや漢字対する解析がかなり苦手(というか専門的用語はどうしようもないかな。認識させるのに何か方法はないのかなぁ。)なので、日本語においては上記のパターンは厳しそうです。SQL Server 2012 ではどうなったいるんだろう。fulltext 部分はかなりの改善があったので、実験してみる価値はありそうです。

 大量の文書から目的の文書を探すのに、テキストインデックスを使った全文検索でいいかと思っていましたが、今回のtf-idf法を始めとして、ランキングアルゴリズム、検索結果を工夫するクラスタリングなど検索手法は多岐に渡ります。検索手法の組み込みに関しては、ちょっと考えが甘かったですね。