scikit-learnのtf-idfについて


機械学習のツールとして、scikit-learnは非常に使いやすいPythonのパッケージとされています。
このパッケージには、例えば交差検定の評価を繰り返して、
分類器に良さそうなパラメータを「検索」してくれるGridSearchなど、
研究をスムーズに進行させるための便利な機能がたくさん搭載されています。

一方、言語処理におけるクラスタリングやクラス分類問題の手がかりとして、
文書にある単語がよく使われます。
これらの単語は、文書/文によって頻度分布に偏りがあるため、
単語頻度からなる素性ベクトルに対してtf-idfによる正規化を行うことが普通です。

scikit-learnでtf-idfを計算

scikit-learnでは、テキスト群に対してtf-idf値を計算する機能が用意されており、
TfidfVectorizerと呼ばれるクラスによりこの機能を簡単に実現できます。

例えば、[1]に挙げられた例文(以下、例文1)

>>> data = ["Human machine interface for ABC computer applications",
            "A survey of user opinion of computer system response time",
            "The EPS user interface management system",
            "System and human system engineering testing of EPS",
            "Relation of user perceived response time to error measurement"]

のtf-idfを計算するために、

>>> from sklearn.feature_extraction.text import TfidfVectorizer
>>> vectorizer = TfidfVectorizer(lowercase=False, token_pattern=u'(?u)\\b\\w+\\b')
>>> tfidf = vectorizer.fit_transform(data)

が使えます。
※lowercase=False:大文字、小文字を区別します。
※token_pattern=u'(?u)\\b\\w+\\b':1文字の単語も考慮(デフォルトは“token_pattern=u'\\b\\w\\w+\\b'”)。

term frequencyの正規化の話

文書の分類問題を解決する際に、
規模が異なる文書をうまく処理するために、
tf-idfのtfを文書にある単語の総頻度で正規化します。
計算方法は以下の通りです。

tf(t,d) = \frac{o_{t,d}}{\sum_{w \in d}^{n_{w,d}}}

うち、
tf(t,d)は単語tが文書dにおけるtf値
o_{t,d}は単語tが文書dにおける生起頻度
\sum_{w \in d}^{n_{w,d}}は文書dにおけるすべての単語の生起頻度の合計になります。

それに対して、scikit-learnのTfidfVectorizerにtfidfを計算する機能を担うTfidfTransformerでは、
tf(t,d)に対して文書にある単語の総頻度で正規化せずに、そのままo_{t,d}を使っています。
その代わりに、算出したtf-idf値に対して正規化をnormパラメータの指定することで実現可能です。

その他の注意点

TfidfTransformerを用いてtf-idfを計算する際に、
公式サイトに書かれているように、
4つのパラメータの調整が可能です。
そのうち、デフォルトでは、"l2 normalization"で正規化されたtf-idf値が出力されます。
なお、tf-idf値の計算は、以下のように行われます。

tfidf(t,d) = tf(t,d) * (1+idf(t))

うち、tf(t,d)は単語tが文書dにおける生起頻度です。
idf(t)は、

idf(t) = log\frac{|D| + 1}{df(t) + 1}

により算出されます。
|D|は文書の数、df(t)は単語tが出現した文書の数になります。
+ 1”は、“Prevents zero divisions”のためです。

tf-idfの計算結果

上述のように、scikit-learnではtf-idfの計算について、いろいろな補正をかけているため、
算出されたtf-idf値は、例えばWikipediaに書かれている式の計算結果とは数値的に異なっています。
以下に、例文1に対するWikipediaに書かれている式(wiki)とscikit-learnのTfidfTransformer(sklearn)による計算結果(抜粋)を示します。

単語 文書1
(wiki / sklearn)
文書2
(wiki / sklearn)
文書3
(wiki / sklearn)
    computer     0.13 / 0.32 0.09 / 0.30 0.00 / 0.00
    interface     0.13 / 0.32 0.00 / 0.00 0.15 / 0.39
    user     0.00 / 0.00 0.05 / 0.24 0.09 / 0.33

上表に示したように、scikit-learnのTfidfTransformerにより算出したtf-idf値は、
数値的に普段使われる式(例えば、Wikipediaに掲載されている式)による計算結果と異なりますが、
単語重要度の傾向(単語tがどの文書に対して重要なのか)は一緒です。


[1] Scott Deerwester, Susan T. Dumais, George W. Furnas, Thomas K. Landauer, and Richard Harshman. 1990. Indexing by Latent Semantic Analysis. Journal of the American Society for Information Science, 41(6):391–407.


This entry was posted in 機械学習, 自然言語処理, 自然言語処理(NLP). Bookmark the permalink.