毎日テキストマイニング

180日間、毎日テキストマイニングをするブログです

2018/7/6【14日目】AKBの呟やきをtf-idfで分析していく

Scikit-learnの使い方も大方わかり始めたので、AKBメンバーの呟きに適用していきたいと思います。

ファイルの読み込み

tf-idfで分析をするのに、複数のドキュメントが必要なので、Pythonで複数のファイルを読み込めるようにしたいと思います。

Pythonでファイルの読込み→別のファイルに書き出し、の動作を行うにはosモジュールを使えば良さそうなので今回はosモジュールを調べてみました。

osモジュールの基本的な使い方

まずはimportから。

import os

importができたら、Pythonの公式ドキュメントから拾ってきた適当な関数を実行してみます。

test = os.name
print(test)

実行結果

posix

posixがよくわからないですが、実行できました。一応、Posixとは次のようなものだそうです。

POSIX(ポシックス、ポジックス、英: Portable operating system interface)は、各種UNIXを始めとする異なるオペレーティングシステム (OS) 実装に共通のアプリケーションプログラミングインタフェース (API) を定め、移植性の高いアプリケーションソフトウェアの開発を容易にすることを目的としてIEEEが策定したAPI規格である。

続いて、ディレクトリを作ってみます。

os.mkdir('test_dir')

簡単ですね。

ファイルの読み込み

os.listdir(path=‘.’)を使えばできそうです。

path で指定されたディレクトリ内のエントリ名が入ったリストを返します。リスト内の順番は不定です。特殊エントリ '.' および '..' は、それらがディレクトリ内に存在してもリストには含められません。

さっき作ったtest_dirフォルダーにAKBの呟きを3日分入れておきましたので、 os.listdir('test_dir’)で中身をみてみます。

os.listdir('test_dir')
['20180704.csv', '20180702.csv', '20180703.csv']

リスト形式でできたので、これをfor文で順に読み込んでいいような気がします。 readとwriteを同時に行うのは,で区切って並列に書けばいいので、こんなコードになりました。csvファイルを読み込んだら、MeCabtagger.parse(‘’)を使って単語ごとに分解していきます。

for content in os.listdir('test'):
    with open('test/' + content, 'r') as read_file, open('henkan/' + content, 'w') as write_file:
        for line in read_file:
            tagger = MeCab.Tagger()
            tagger.parse('')
            node = tagger.parseToNode(line)
            while node:
                if node.feature.startswith('名詞'):
                    write_file.write(node.surface + '\n')
                node = node.next

実行結果のcsvファイル

tweet
"
今日
#
山根
涼
羽
カフェ
買い物
☕??
大切
同期
時間

全てのcsvファイルが1個1個ちゃんと単語に分解されています。これで、ドキュメント数と単語を確保できたはずです。 これを昨日勉強したscikit-learnのチュートリアルに沿ってデータを入力していきます。まずはimportからやっていきます。

from sklearn.feature_extraction.text import CountVectorizer
count_vectorizer = CountVectorizer(input='filename')

CountVectorizer関数に渡した引数は生のテキストを詠みこむのに必要だそう です。

’filename'の場合、fitの引数として渡されるシーケンスは、解析するための生のコンテンツを取得するために読み込みが必要なファイル名のリストになると予想されます。

count_vectorizer.fit_transformにデータを入れるためのファイル名が欲しいので、1行1行分解したcsvのファイル名を取得するためにfor文で回して用意します。その変数をcount_vectorizerに引数として渡します。

files = ['henkan/' + content for content in os.listdir('test')]
X_train_counts = count_vectorizer.fit_transform(files)
X_train_counts.shape

実行結果

(4, 552)

お、数は少ないですが、チュートリアル通りに返ってきてますね。 これをTfidfTransformerに入れてみます。

from sklearn.feature_extraction.text import TfidfTransformer

tf_transformer = TfidfTransformer(use_idf=False).fit(X_train_counts)
X_train_tf = tf_transformer.transform(X_train_counts)
print(X_train_tf)

実行結果

  (0, 469)   0.0816496580928
  (0, 229)    0.0816496580928
  (0, 228)    0.0816496580928
  (0, 311)    0.0816496580928
  (0, 519)    0.0816496580928
  (0, 94) 0.0816496580928
  (0, 26) 0.0816496580928
  (0, 42) 0.0816496580928
  (0, 471)    0.0816496580928
  (0, 468)    0.0816496580928
  (0, 445)    0.0816496580928
  (0, 464)    0.163299316186

どうやらtf-idf分析ができたらしいです。 試しにぱっと見でスコアが高いものを見てみます。 数値化した単語を戻すにはcount_vectorizer.get_feature_names()を使えばいいそうです。それを[]で番号を指定してあげれば単語が戻ってきます。

terms = count_vectorizer.get_feature_names()
terms[464] #(0, 68)   0.163299316186
'最後'
terms[68]     #(0, 68)   0.163299316186
'express'
terms[20]     #(3, 20)   0.707106781187
’34’

うーん、”最後”が重要そうなのはわかりますが、'express’、’34’が重要というのは明らかに間違いぽいですね。明日はもう少し精度を上げて、AKBの呟きを分析したいと思います。

今日の結果

今日の呟きは40件でした。呟かれた言葉はこんな感じです。

'いい': 4, '嬉しい': 3, '楽しい': 2, 'すごい': 2, '可愛い': 2, '面白い': 2, '良い': 2, 'かっこいい': 1, 'かわいい': 1, 'おもしろい': 1, 'たのしい': 1, '切ない': 1, '寂しい': 1, 'ない': 1, '優しい': 1, 'いたい': 1, '恥ずかしい': 1, 'うれしい': 1, '多い': 1, '新しい': 1})

'公演': 16, 'チーム': 13, '初日': 10, 'さん': 10, '込山': 9, 'こと': 7, '今日': 6, '配信': 5, 'よう': 5, 'いい': 4, 'の': 4, '時': 4, '無事': 4, '嬉しい': 3, 'ユニット': 3, '全部': 3, '前': 3, '方': 3, '私': 3, 'たくさん': 3, '怜': 3, 'ちゃん': 3, 'ゴリラ': 3, 'ん': 3, '一緒': 3,

'する': 29, '公演': 16, 'チーム': 13, '初日': 10, 'さん': 10, '込山': 9, 'てる': 9, '見る': 9, 'こと': 7, '今日': 6, 'くださる': 6, 'いただく': 6, '配信': 5, 'よう': 5, '終わる': 5, 'やる': 5, 'せる': 5, 'なる': 5,

今日勉強したこと

  • osモジュールの基本的な使い方
  • readとwriteを同時に行う方法