WEB+DB PRESS (ウェブDBプレス) Vol.100「文書の表現」(P.30)をやってみた

WEB+DB PRESS Vol.100(技術評論社)の「文書の表現」(P.30)をやってみました。ここは、PythonからMeCabを使って、名詞だけを取り出してみるところですね。

  • 記事の内容や、操作を理解するための概念などは、このページには書きません。上のリンクから雑誌を購入してご覧ください。

この記事は、以下の記事の続きです。

WEB+DB PRESS (ウェブDBプレス) Vol.100「係り受け解析」(P.28)をやってみた

文書の表現

Windows PowerShellを起動し、以下の記事で準備したDockerコンテナに接続して操作します。ここでは、Dockerコンテナに接続するまでの操作は省略します。

WEB+DB PRESS (ウェブDBプレス) Vol.100「第2章 自然言語処理」(P.24)をやってみた

「おじいさんは山へ芝刈りに、おばあさんは川へ洗濯に行きました。」の分かち書き表現

  1. ここまでと同様にDockerコンテナに接続し、「cd /webdb100/02」と入力して、Enterキーを押します。
  2. 雑誌記事(P.30)の「wakati.pyの実行」の1行目のコマンドを入力し、Enterキーを押します。
    なお、記載されているコマンドの先頭にある「$」は、入力しません。

    名詞のみを取り出した分かち書きが表示されます。

文書のベクトル表現

(手元でtf-idf表現を計算した結果が、雑誌記事のとおりになりませんでしたので、問い合わせ中です)

tf-idfの計算は、以下の記事のコードを使用しました。なお、雑誌記事の値に近づけるため「math.log10()」を使用していた箇所を「math.log()」に置き換えています。

def tf(terms, document):
    """
    TF値の計算。単語リストと文章を渡す
    :param terms:
    :param document:
    :return:
    """
    tf_values = [document.count(term) for term in terms]
    return list(map(lambda x: x/sum(tf_values), tf_values))


def idf(terms, documents):
    """
    IDF値の計算。単語リストと全文章を渡す
    :param terms:
    :param documents:
    :return:
    """
    import math
    return [math.log(len(documents)/sum([bool(term in document) for document in documents])) for term in terms]


def tf_idf(terms, documents):
    """
    TF-IDF値を計算。文章毎にTF-IDF値を計算
    :param terms:
    :param documents:
    :return:
    """
    return [[_tf*_idf for _tf, _idf in zip(tf(terms, document), idf(terms, documents))] for document in documents]


documents = [
    "私はRubyとPythonではRubyが好きです",
    "私は機械学習をしている",
    "機械学習をするのでPythonが好きです",
]

import MeCab
mecab = MeCab.Tagger("-d /usr/local/lib/mecab/dic/mecab-ipadic-neologd/")
allwords = []

for document in documents:
    node = mecab.parseToNode(document)
    words = []
    while node:
        if node.feature.split(',')[0] == '名詞':
            word = node.feature.split(",")[6]
            words.append(word)
            if word not in allwords:
                allwords.append(word)
        node = node.next

tf_idf_array = tf_idf(allwords, documents)

print ()
print ("出現単語:" + ", ".join(allwords))
print ()
for i in range(len(documents)):
    print ("文書"+str(i+1)+":" + documents[i])
    print (", ".join(['{:.2f}'.format(tf_idf_item) for tf_idf_item in tf_idf_array[i]]))
    print ()

出力結果は以下のとおりでした。赤字部分の値が一致しませんでした。

出現単語:私, Ruby, Python, 好き, 機械学習

文書1:私はRubyとPythonではRubyが好きです
0.08, 0.44, 0.08, 0.08, 0.00

文書2:私は機械学習をしている
0.20, 0.00, 0.00, 0.00, 0.20

文書3:機械学習をするのでPythonが好きです
0.00, 0.00, 0.14, 0.14, 0.14