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

SPSSで簡単テキストマイニング

プログラミング Python テキストマイニング


 SPSSPythonと連携することが出来ます。SPSSは大変多機能ですが、業務で実際扱うデータは一筋縄にはいきません。様々な前処理が必要です。SPSSに落とし込めるよう、データの整備やクリーニングをPythonで簡単にやってしまいましょう。今回はテキストをSVMにかけるための下準備をPythonで行います。形態素解析にはMeCab-野良ビルドを用います。まずは頻度カウントしてみます

#coding:utf-8
import sys
import MeCab #MeCabを呼んで使えるようにする

tagger = MeCab.Tagger("-Owakati") #分かち書きをする指定
read_file = sys.argv[1] #コマンドラインから読み込むデータファイルを指定する
all_text = open(read_file).read() #指定したファイルを読み込む
word_list = tagger.parse(all_text).split() #読み込んだファイルを分かち書きし、生成された配列をword_listに格納
dictionary ={} #空の辞書作成

for word in word_list: #dictionaryに単語が登録されていれば頻度を+1し、登録されていなければ辞書に単語を登録し、その頻度を1とする
	if word in dictionary:
		dictionary[word] = dictionary[word] + 1
	else:
		dictionary[word] = 1

for word, count in sorted(dictionary.items(), key = lambda x:x[1], reverse = True): #dictionaryに登録された単語を頻度降順で表示
	print word + "\t -> " + str(count)

 これで頻度カウントが出来ました。このデータを用いてSPSSで単語のヒストグラムを描くなどしてみるといいでしょう(SPSSお持ちの方は)。
 次はテキストをSVMにかけてみましょう。SVMにかけるためには、テキストをID化しなければなりません。SVMで処理できるデータは、クラスとIDとIDの値という形式です。例"+1 :: ID1:12, ID2:4, ID3:9 ID4:4"
テキストのID化は色々なやり方がありますので、その一例を示します。「犬を連れて散歩」というテキストが与えられ、ID群が犬=ID1、猫=ID2、散歩=ID3と割り振られていた場合(そして「連れて」という単語にID振られてなければ)、「犬を連れて散歩」→「ID1:1, ID2:0, ID3:1」となります。このようなデータ形式に落とし込めるようなPythonコードを書きましょう。

#coding:utf-8
import sys
import MeCab

tagger = MeCab.Tagger("-Owakati")
read_file = sys.argv[1]
read_dictionary = sys.argv[2] #ID群が振り当てられた単語辞書

text_list = open(read_file).read().split('\n')
dictionary = open(read_dictionary).read().split('\n')
print ',' + ','.join(dictionary)

def set_id(text):
	count = 0
	id = []
	for word in dictionary:
		count += 1
		id.append(str(text.count(word)))
	return text + ',' + ','.join(id)

for text in text_list:
	print set_id(text)

 これでテキストデータをSVMに放り込めるようID化出来ます。今のはIDが事前割り振られていたという前提でしたが、実際はID辞書も自作する必要があります。面倒くさいのでそれも自動化してしまいましょう(目的に合わせて手作業した方が精度良いですが)。サンプルデータを食わせ、指定した下限値より出現頻度高い単語だけを抽出します。

#coding:utf-8
import sys
import MeCab
tagger = MeCab.Tagger("-Owakati")
read_file = sys.argv[1]
all_text = open(read_file).read()
word_list = tagger.parse(all_text).split()
dictionary = {}
for word in word_list:
	if word in dictionary:
		dictionary[word] = dictionary[word] + 1
	else:
		dictionary[word] = 1
#ここまでは同じ

min = sys.argv[2] #頻度下限
for word, count in dictionary.items():
	if int(count) >= int(min):	#設定した下限以上出現した単語だけを出力
		print word	#出力結果をリダイレクトで取得するなど

 この結果吐いたファイルを先ほどのコードの第二引数に指定します。実行するとこんな感じになります。

#ID辞書
犯罪

セックス
援助
交際

殺す
ドラッグ
シンナー
麻薬

#ID化

原文 犯罪 セックス 援助 交際 殺す ドラッグ シンナー 麻薬
援助交際してくれる人募集中〜 0 0 0 1 1 0 0 0 0 0
風邪気味なので風邪薬買いに薬局へ行ってきた 0 0 0 0 0 0 0 0 0 0
渋谷にドラッグの密売人がいるらしい 0 0 0 0 0 0 0 1 0 0
ふざけたこと言ってると殺すぞ、絶対殺す 0 0 0 0 0 0 2 0 0 0
麻薬体験ブログ公開中! 0 0 0 0 0 0 0 0 0 1

 というわけで、こうやってテキストID化するとSPSSで簡単にSVMとかに放り込めて楽しいですね(SPSSお持ちの方は)。是非やってみましょう。といってもテキストデータ十分にお持ちではないケースもあると思うので、twitterからツイートを取ってくるコードも掲載しておきます。

# -*- coding: utf-8 -*-

#■これは何?
#twitterからパブリックなツイートを取得するツールです。
#取得する内容はツイートした時間、ツイートしたIDと名前、ツイート内容です。
#自分のアカウントとパスを書いたsetting.txtを用意して下さい
#ストリーミングフローとして閲覧するだけではなく、DBファイル(tweet.db)に格納します。
#tweet.dbはPupSQLiteなどで中身を見ることが出来ます。
#https://www.eonet.ne.jp/~pup/software.html

import base64
import simplejson
import urllib2
import datetime
import sqlite3
import os

# ツイッターアカウント設定読み取り
with open("setting.txt") as f:
 userID = f.readline().replace('\r','').replace('\n','')
 userPassword = f.readline().replace('\r','').replace('\n','')
 commitDoNum = int(f.readline().replace('\r','').replace('\n',''))

#日本語のツイートだけ収集するため、ツイートが日本語かどうかチェック
def is_japanese(text):
	def check_chr(x):
	    return ((x >= 0x3040 and x <= 0x309f) or (x >= 0x30a0 and x <= 0x30ff))
	return [ch for ch in text if check_chr(ord(ch))]

#SQLite3のDB用意。既にDBファイルがある場合はそれを利用、無い場合は新規で作成する。Python2.5以上はSQLiteが組み込まれているため、通常はインストール作業不要
if os.path.exists('tweet.db'):
	connection = sqlite3.connect('tweet.db')
	cursor = connection.cursor()
else:
	connection = sqlite3.connect('tweet.db')
	cursor = connection.cursor()
	cursor.execute("create table twitter (tweetTime text, create_dt text, user_screen_id text, user_name text, tweet text);")

# Streaming APIに接続
streamingAPIURI = 'https://stream.twitter.com/1/statuses/sample.json'
req = urllib2.Request(streamingAPIURI, headers={'Authorization': 'Basic %s' % (base64.encodestring('%s:%s' % (userID, userPassword))[:-1])})
streamingData = urllib2.urlopen(req)

commitCnt = 0 #「commitDoNum個ツイートをinsertしたらDBにCommitする」という用途に用意したカウンタ
for line in streamingData:
	data = simplejson.loads(line)
	text = data.get('text')
	if text and is_japanese(text):
		tweetTime = datetime.datetime.today()
		create_dt = data.get('created_at')
		user_screen_id = data['user']['screen_name']
		user_name = data['user']['name']
		try:
			tpl = (str(tweetTime), create_dt, user_screen_id, user_name, text)
			cursor.execute("insert into twitter values(?,?,?,?,?)", tpl)
			print str(tweetTime) + ":"+ user_name + "\n" + text + "\n"
			commitCnt += 1
			if commitCnt == commitDoNum:	#commitDoNum個ツイートをinsertしたらDBにCommitする
				connection.commit()
				commitCnt = 0
		except:
			print "*** insert miss... ***"

 さぁ、皆さんもコピペからテキストマイニングを始めてみましょう(SPSSお持ちの方は)。