ステージ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_