読者です 読者をやめる 読者になる 読者になる

望月いちろうのREADME.md

書き溜めておいた技術記事や旅行記のバックアップです。

機械学習で文章を分類するには? - TF-IDF特徴量を使えばいい

文章をカテゴリやテーマ別に分類できたらよいと思うことはありませんか?

例えば、プログラミングやインターネットサービス全般に興味がある一方で、芸能やスポーツに興味がない。

そんな人であれば、ニュースの中から、自分の関心のあるニュースだけをピックアップできれば便利ですよね

今回はそんな願いを叶えるために、機械学習を使って文章を分類する方法を紹介します。

そのために必要な道具は2つ

TF-IDF特徴量

TF(Term Frequency、単語の出現頻度)とIDF(Inverse Document Frequency、逆文書頻度)と呼ばれる

2つの特徴量の掛け算からなることからそう呼ばれます。

その定義は以下のようになります {}

$$ TF_{dv} = \frac{N_dv}{N_d} $$

$$ IDF_{v} = log \frac{ D }{ D_v } $$

ここで

$$ N_dv $$

は文書d中の単語vの出現数

N_d

は文書d中の単語総数

Dは分析対象の文書数

$$ D_v $$

は単語vが含まれている文章数です。

sklearnなどのライブラリではIDF値の定義が変更されていて

$$ IDF_{v} = log \frac{ D }{ D_v } + 1 $$

またはスムージングを設定している場合があります。

その場合のTF-IDF 値の定義は以下のように変更されます。

$$ IDF_{v} = log \frac{ D }{ D_v + 1} + 1 $$

まあ、これだけでは、なぜテキスト分類に役に立つのかよくわかりませんね。

まずTFについてみてみるとすべての単語数にたいしてのある単語の割合となっています。

そしてそれにかけられるIDFは偏りのある単語に対して大きな数値が出るようになっています。

つまり、文章集合全体から見て、ある文書に限定して高頻度で出てくる単語に対して、大きな数値が出るのがTF-IDF特徴量の特徴です。

もし、インターネットサービスについての記事であれば以下のような単語がよく出てくると容易に推測できます。

Twitter, 投稿, ブログ,Google

など

もしその他の記事であれば、このような単語はほとんど出てこないと予測できます。

実際には特徴的な単語について、個々のTF-IDFを計算して、文章ごとの特徴ベクトルを計算してSVMにかけて文章の分類を行います。

たとえば

文章A

投稿 ます です ます です 投稿 ブログ 感動 ます

文章B

野球 ドーム ます です ます です 野球 監督

と2つの文章があります。

この2つの文章を全体集合として各文書に対してTF-IDF特徴ベクトルを算出してみたいと思います。

使うのはPython用機械学習ライブラリのscikit-learnです。

まず、単語を半角スペースで分かち書きして配列に格納

data = ["投稿 ます です ます です 投稿 ブログ 感動 ます","野球 ドーム ます です ます です 野球 監督"]

sklearnのライブラリを呼び出します。

from sklearn.feature_extraction.text import TfidfVectorizer
vectorizer = TfidfVectorizer()

データを投入してTF-IDF値を計算

tfidf = vectorizer.fit_transform(data)

結果を取り出します

tfidf.toarray()

array([[ 0.40118934,  0.60178401,  0.        ,  0.28192881,  0.28192881,

         0.56385762,  0.        ,  0.        ],

       [ 0.44887761,  0.44887761,  0.31544091,  0.        ,  0.        ,

         0.        ,  0.31544091,  0.63088181]])

そして各文書ごとにTF-IDF特徴ベクトルが算出できます。

それぞれの文章に対して

'です', 'ます', 'ドーム', 'ブログ', '感動', '投稿', '監督', '野球'

の順番に、各文書ごとにおける各単語のTF-IDF値が格納されています。

文章AのTF-IDF特徴ベクトル

T_a = [ 0.40118934,  0.60178401,  0.        ,  0.28192881,  0.28192881,
         0.56385762,  0.        ,  0.        ],

文章BのTF-IDF特徴ベクトル

T_b = [ 0.44887761,  0.44887761,  0.31544091,  0.        ,  0.        ,
         0.        ,  0.31544091,  0.63088181]

同様の手法で文章ごとにTF-IDF特徴ベクトルを作成してある程度の規模のデータに対してSVMにかければ文章分類ができると思います。