ステージ3: タームを素性とする特徴ベクトル生成の例(日本語編), 文分割 + トークン化 + ステミング + ストップワード除去 (情報工学実験 4 : データマイニング班)
目次- 想定環境
- 文書集合からターム素性集合(コードブック)を作る
文分割 + トークン化 + ステミング + ストップワード除去を含んだ例
- コードブックを素性とする文書ベクトルを作る(直接ベクトル生成)
- クラスタリング(K-means)してみる
想定環境
- OS: Mac OS X 10.9.x (10.7.x以降であれば同じ方法で問題無いはず)
- Python: 3.4.x
- numpy: 1.9.0 (numpy.version)
- scipy: 0.14.0 (scipy.version)
- NLTK: 3.0.0 (nltk.__version__)
文書集合からターム素性集合(コードブック)を作る
- nltk.RegexpTokenizer(): 文章(doc)をパターンマッチングで文(sentence)に分割
- mecab.parseToNode(): 形態素解析結果を双方向連結リストとして出力。表層=surface, 解析結果=feature, 双方向ポインタnext <-> prev.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import nltk
import MeCab
docs = []
docs.append('会場には車で行きます。行きます。')
docs.append('会場には自動車で行きます。')
docs.append('会場には自転車で行きます。')
docs.append('お店には自転車で行きます。')
# doc -> sentences分割処理の例。
jp_sent_tokenizer = nltk.RegexpTokenizer('[^ 「」!?。]*[!?。]')
sents = jp_sent_tokenizer.tokenize( docs[0] )
print('# doc -> sentences分割処理の例。')
print(sents)
# sentence -> words 分割処理の例。トークン化。
mecab = MeCab.Tagger('-Ochasen')
mecab.parse(docs[0])
node = mecab.parseToNode(docs[0])
print('\n# sentence -> words 分割処理の例。トークン化。')
while node:
print(node.surface, node.feature, sep='\t')
node = node.next
# token を基本形に修正する例。ステミング。
mecab.parse(docs[0])
node = mecab.parseToNode(docs[0])
print('\n# token を基本形に修正する例。ステミング。')
while node:
fs = node.feature.split(",")
print("surface={0} -> fs[6]={1}".format(node.surface, fs[6]))
node = node.next
def collect_words_jp(docs):
'''日本語文書集合 docs からの単語コードブック作成例。
シンプルに文書集合を予め決めうちした方式で処理する。
必要に応じて指定できるようにしていた方が使い易いかも。
<使用しているライブラリの説明>
nltk.RegexpTokenizer: 文章(doc)をパターンマッチングで文(sentence)に分割する。
mecab.parseToNode: 形態素解析結果を双方向連結リストとして出力。node.next <-> node.prev
'''
jp_sent_tokenizer = nltk.RegexpTokenizer('[^ 「」!?。]*[!?。]')
mecab = MeCab.Tagger('-Ochasen')
codebook = []
pos = ['形容詞', '形容動詞','感動詞','副詞','連体詞','名詞','動詞']
jp_sent_tokenizer = nltk.RegexpTokenizer(u'[^ 「」!?。]*[!?。]')
stopwords = ["", "*", "これ", "あれ", "は", "が", "の", "を", "です", "、", "。"]
for doc in docs:
for sent in jp_sent_tokenizer.tokenize(doc):
mecab.parse(sent)
node = mecab.parseToNode(sent)
while node:
fs = node.feature.split(",")
if fs[0] in pos:
this_word = fs[6]
if this_word not in codebook and this_word not in stopwords:
codebook.append(this_word)
node = node.next
return codebook
print('\n# 日本語文書集合 docs からの単語コードブック作成例。')
codebook = collect_words_jp(docs)
codebook.sort()
print(codebook)
コードブックを素性とする文書ベクトルを作る (直接ベクトル生成)
def make_vectors_jp(docs, codebook):
'''コードブックを素性とする文書ベクトルを作る(直接ベクトル生成)
n-gramモデルの例と流れは一緒。
「doc=1文とは限らない」ケースにも対応するよう拡張。
'''
vectors = []
jp_sent_tokenizer = nltk.RegexpTokenizer('[^ 「」!?。]*[!?。]')
for doc in docs:
this_vector = []
fdist = nltk.FreqDist()
for sent in jp_sent_tokenizer.tokenize(doc):
mecab.parse(sent)
node = mecab.parseToNode(sent)
while node:
fs = node.feature.split(",")
this_word = fs[6]
fdist[this_word] += 1
node = node.next
for word in codebook:
this_vector.append(fdist[word])
vectors.append(this_vector)
return vectors
print('\n#コードブックを素性とする文書ベクトルを作る(直接ベクトル生成)')
data = make_vectors_jp(docs, codebook)
print(data)
print('\n# 元の文書集合')
print(docs)
クラスタリング(K-means)してみる
#教師無し学習(K-means)で2クラスタに分類してみる from sklearn import cluster k_means = cluster.KMeans(n_clusters=2) k_means.fit(data) k_means.labels_