NINのブログ

主に機械学習とか統計モデリングとか金融とか

Python-MeCabでtf-idf法の実装

こんにちは。
今回はMeCab形態素解析をした後に、tf-idf法で文章の特徴語検出をする方法を紹介します。

tf-idf法についてWikipediaより引用します。
tf-idfは、文書中の単語に関する重みの一種であり、主に情報検索や文章要約などの分野で利用される。
tf-idfは、tf(単語の出現頻度)とidf(逆文書頻度)の二つの指標にもとづいて計算される。
f:id:RYNIN:20140804174516p:plain
n_{i,j} は単語iの文書jにおける出現回数、 |D| は総ドキュメント数、|{d: d ∋ ti }|は単語iを含むドキュメント数である。そのため、idfは一種の一般語フィルタとして働き、多くのドキュメントに出現する語(一般的な語)は重要度が下がり、特定のドキュメントにしか出現しない単語の重要度を上げる役割を果たす。

それでは実装します。

#coding:utf-8

import MeCab
import math

sentence = ["えびを食べる","えびがえびを食べる","朝食を食べる"]

num = len(sentence)
result = []

for i in range(num):         #文章の分解
    tagger = MeCab.Tagger()
    result.append(tagger.parse(sentence[i]))


wordCount = {}
allCount = {}
sub_tfstore = {}
tfcounter = {}
tfstore = {}
sub_idf = {}
idfstore = {}
merge_idf = {}
tfidf = {}
merge_tfidf = {}
wordList = []
sum = 0

for i in range(num):
    wordList.append(result[i].split()[:-1:2])    #wordListに分解された単語要素のみを格納

for i in range(num):
    for word in wordList[i]:
        allCount[i] = wordCount.setdefault(word,0)
        wordCount[word]+=1
    allCount[i] = wordCount       #単語出現回数を文章ごとに格納。tfの分母に相当
    wordCount = {}

for i in range(num):                             # tfの分母を計算
    for word in allCount[i]:
        sum = sum + allCount[i][word]
    sub_tfstore[i] = sum
    sum = 0

for i in range(num):                     # tf値を計算し文章ごとに辞書に格納
    for word in allCount[i]:
        tfcounter[word] = allCount[i][word]*1.0/sub_tfstore[i]
    tfstore[i] = tfcounter
    tfcounter = {}

for i in range(num):
    for word in wordList[i]:
        wordCount.setdefault(word,0)
    for word in allCount[i]:
        wordCount[word] += 1
    sub_idf = wordCount                  #ある単語の文章あたりの出現回数を辞書に格納

for i in range(num):
    for word in allCount[i]:
        idfstore[word] = math.log(1.0*math.fabs(num)/math.fabs(sub_idf[word]))
    merge_idf[i] = idfstore
    idfstore = {}

for i in range(num):           #tfidfの計算
    for word in allCount[i]:
        tfidf[word] = tfstore[i][word]*merge_idf[i][word]
    merge_tfidf[i] = tfidf
    tfidf = {}

for i in range(num):          #降順に出力する
    for word,count in sorted(merge_tfidf[i].items(),key = lambda x:x[1],reverse = True):
        print 'text%d: %-16s %2.3f' % (i+1,word,count)
実行結果
text1: えび           0.135
text1: を              0.000
text1: 食べる        0.000
text2: が              0.220
text2: えび           0.162
text2: を              0.000
text2: 食べる        0.000
text3: 朝食           0.366
text3: を              0.000
text3: 食べる        0.000

3つのセンテンスの特徴が捉えられていますね!