TfidfVectorizerのよく使いそうなオプションまとめ

TfidfVectorizerとは

文章内に出現する単語の出現頻度と希少性を掛け合わせた値Tfidfを算出するアルゴリズム。文章を特徴づける単語を探したりできる。

例えば、Twitterの投稿テキストを読み込んで、気分が「Happy」か「Unhappy」かを判別する機械学習モデルを作ろうと思った時に、テキスト内の単語の出現頻度を元に判別するという方法が考えられる。
しかし、どの投稿でもよく出現する助詞などの単語の出現頻度によって「Happy」か「Unhappy」かの判別基準が変わるのは望ましくない。
出現頻度だけではなく、その希少性も考慮に入れて判別を行いたいはずで、そのような場合にTfidVectorizerというアルゴリズムを使うと良い。

TfidfVectorizerの使用方法

Pythonのscikit-learnからクラスを使う時、以下のようにすれば使える。

# scikit-learnからTfidfVectorizerを読み込む
from sklearn.feature_extraction.text import TfidfVectorizer

# 文章内に10回まで出現する単語のTfidf値を求めるためのTfidfVectorizerを作る
vec = TfidfVectorizer(max_df=10) # ここでオプションを指定

# 単語の出現回数を数える文章を作成
docs = ["I have a pen", "I have an apple", "Ugh, apple pen", "I have a pen", "I have an pineapple", "Ugh, Pineapple pen"]

# 文章内の単語のTfidf値を取得
term_doc = vec.fit_transform(docs)

# 単語に割り当てられている序数を表示
vec.vocabulary_
=> {'an': 0, 'apple': 1, 'have': 2, 'pen': 3, 'pineapple': 4, 'ugh': 5}

# 単語毎のtfidf値を取得
term_doc.toarray()
=>
array([[ 0.             ,  0.             ,  0.70710678,  0.70710678,  0.            ,  0.        ],
       [ 0.62951441,  0.62951441,  0.4554374 ,  0.             ,  0.            , 0.        ],
       [ 0.             ,  0.62951441,  0.            ,  0.4554374 ,  0.             ,  0.62951441],
       [ 0.             ,  0.             ,  0.70710678,  0.70710678,  0.            ,  0.        ],
       [ 0.62951441,  0.                 ,  0.4554374 ,  0.             ,  0.62951441, 0.        ],
       [ 0.             ,  0.             ,  0.             ,  0.4554374 ,  0.62951441, 0.62951441]])

この結果を見ると、配列の1行目(1つ目の文章"I have a pen")は3列目(have)と4列目(pen)のTfidf値が高く、 6行目(5つ目の文章"Ugh, Pineapple pen")は4列目(pineapple)と5列目(pen)、6列目(ugh)のTdidf値が高くなっていることがわかります。 頻出のIanといった単語はTdidf値が0で重要度が低いことがわかり、Tdidf値の高い単語が文章を特徴づける重要な単語としてみなすことができます。

tokenizer

トークン化するためのコールバックを指定する。 例えば以下のようにすれば、!"#$%&\'(+)*,-./:;<=>?@\\\[\]^_{|}~“”¨«»®´·º½¾¿¡§£₤‘’`のような単語を区切り文字に使える。

import re
def tokenize(s): return re.split('[ !"#$%&\'(+)*,-./:;<=>?@\\\[\]^_`{|}~“”¨«»®´·º½¾¿¡§£₤‘’]', s)
TfidfVectorizer(tokenizer=tokenize)

ngram_range

n-gramの最小値と最大値をタプルで指定します。例えば、1gramと2gramの頻出を調べる場合には(1, 2)のように指定します。 上記の例でオプションにngram_range=(1, 2)を指定すると、以下の単語(単語列)のTdidf値を算出します。

vec.vocabulary_
=> {'an': 0, 'an apple': 1, 'an pineapple': 2, 'apple': 3, 'apple pen': 4, 'have': 5, 'have an': 6, 'have pen': 7, 'pen': 8, 'pineapple': 9,'pineapple pen': 10, 'ugh': 11, 'ugh apple': 12, 'ugh pineapple': 13}

max_features

抽出する単語数を指定します。tfidf値の降順で単語が返ってくる。 デフォルトはNoneなので、指定しない場合は全件取得する。

max_df

intで指定された場合には、指定された出現回数までの単語のみを抽出。
floatで指定された場合には、指定された出現割合までの単語のみを抽出。
デフォルトは1.0なので、指定しない場合全ての文章にこの単語があっても抽出する。

min_df

intで指定された場合には、指定された出現回数以上の単語のみを抽出。
floatで指定された場合には、指定された出現割合以上の単語のみを抽出。
デフォルトは1なので、指定しない場合1回以上出現した単語を抽出。

strip_accents

前処理の段階でアクセント記号があれば、アクセント(è、ò、ù ⇦ こういうの)を取り除く。 'ascii'が指定されている場合はASCIIコードマッピングで取り除き、‘unicode’、Unicodeのコードマッピングで取り除く。 Noneが指定されている場合には取り除かない。

アクセント記号って日本人だと普段使わないから意識しないけど、ASCIIコードの中にもあるんですよね。

smooth_idf

単語の出現回数に1足すかどうかを指定する。idf値の計算式の分母で単語の出現回数を使っていて、0になる場合は0割が発生するので、それを防ぐために入れる。 デフォルトはTrueのため、0割防止のために1を足している。

あまり出現回数にばらつきがないような文章でそれぞれ出現回数が少ない場合には全部に1が足されてしまうので、多くの単語の優位性が上がってしまう気がした。

stop_words

Tfidf値を求めなたくない単語のリストを指定する。 例えば上記の例では、Ihave, anといった単語が文書を特徴づけるものではないとわかっている単語を指定して、不要な項目の計算を省くことができる。

sublinear_tf

単語の出現頻度(Term Freequency)に対数変換するどうかを指定する。 Trueにするとtfを1 + log(tf)に置き換える。 デフォルトはFalseのため、対数変換しない。

あまりにも出現頻度が高い単語があった時に他の単語よりtfidf値が上がってしまうので、あまり影響を受けないようにすることができそう。

sklearn.feature_extraction.text.TfidfVectorizer — scikit-learn 0.19.1 documentation