先月ぐらいから自然言語処理頑張ろうとして入門っぽいTF-IDFをPythonから理解しようとしたけど使いどころわからんくて無事死亡。
今日は式から理解しようとしてやってみた。
対数がわからん
やさしく学ぶ 機械学習を理解するための数学のきほん ~アヤノ&ミオと一緒に学ぶ 機械学習の理論と数学、実装まで~
- 作者: LINE Fukuoka株式会社立石賢吾
- 出版社/メーカー: マイナビ出版
- 発売日: 2017/09/21
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (2件) を見る
ぐぐってもいいけど、この本もっていたので軽く理解。
式がわからん
Python機械学習プログラミング 達人データサイエンティストによる理論と実践 (impress top gear)
- 作者: Sebastian Raschka,株式会社クイープ,福島真太朗
- 出版社/メーカー: インプレス
- 発売日: 2016/06/30
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (4件) を見る
※tf-idfって書きたいのにハイフンが引き算になるのでつらい
tf
はあるドキュメントd
の単語の出現頻度idf
は逆文章頻度
- はドキュメントの総数
df(t, d)
は単語t
を含んでいるドキュメントd
の個数を表す。分母の1
はdf
が0の場合ゼロ除算を防ぐため
scikit-learnに実装されている式は下記らしい
tfidfはこちら
- ある文章
d
で出現頻度が大きいt
は重要である可能性が高い - しかし、とある文章を感情分析したい場合、肯定的、否定的な文章どちらにも同じ単語が出現することはよくある
- そこで多くの文章中
d
に存在する単語t
は、1つの文章の特徴としてはなりづらくしよう -> idf
ってな感じかな
idf
は分母と分子が同じだと1になり、対数で計算すると0になるので、値は小さくなる(はず
なるほど。
scikit-learnで試す
from sklearn.feature_extraction.text import TfidfVectorizer import pandas as pd # 形態素解析した文章毎の半角スペース区切りの単語 # surfaces = [['映画 エイリアン レビュー あらすじ'], ...] vectorizer = TfidfVectorizer() x = vectorizer.fit_transform(surfaces) # ベクトル器から単語リストを取得 terms = vectorizer.get_feature_names() # 全単語数が確認できる print(len(terms)) # 文章毎に単語のベクトルを取得 vec_matrix = x.toarray() # (全文章数, 全単語数)のベクトル # vec_matrix.shape # tfidf値が0より大きいものだけ取得する words = [] for doc in range(len(surfaces)): feature_index = x.toarray()[doc, :].nonzero()[0] tfidf_scores = zip(feature_index, [vec_matrix[doc, x] for x in feature_index]) for w, s in [(terms[i], s) for (i, s) in tfidf_scores]: words.append(w) # 単語のカウント word_dict = {} for w in words: if w in word_dict.keys(): word_dict[w] += 1 else: word_dict[w] = 1 word_df = pd.DataFrame([[k, v] for k, v in word_dict.items()], columns=['word', 'count']) word_df.head()
これで重要そうな単語を確認することができる?
(ちなみにこれを実装したときに確認した単語リストは前処理が甘くjs,css,htmlのタグ名が多く上がっていた。。。orz)