ステージ3-2: タームを素性とする特徴ベクトル生成の例(日本語編), 文分割 + トークン化 + ステミング + ストップワード除去 (情報工学実験 3 : データマイニング班)
目次- 想定環境
- 文書集合からターム素性集合(コードブック)を作る
文分割 + トークン化 + ステミング + ストップワード除去を含んだ例
- case 1:コードブックを素性とする文書ベクトルを作る(直接ベクトル生成)
- case 2 (辞書型->DictVectorizer) は省略。
- case 3 (疎行列) は省略。
想定環境
- OS: Mac OS X 10.8.x (10.7.x以降であれば同じ方法で問題無いはず)
- Python: 2.7.x
- Mercurial: 2.2
- NLTK: 2.0.4 (nltk.__version__)
- MeCab: 0.993 (MeCab.VERSION)
文書集合からターム素性集合(コードブック)を作る
- nltk.RegexpTokenizer(): 文章(doc)をパターンマッチングで文(sentence)に分割
- mecab.parseToNode(): 形態素解析結果を双方向連結リストとして出力。表層=surface, 解析結果=feature, 双方向ポインタnext <-> prev.
docs = [] docs.append(u"会場には車で行きます。") docs.append(u"会場には自動車で行きます。") docs.append(u"会場には自転車で行きます。") docs.append(u"お店には自転車で行きます。") # doc -> sentences分割処理の例。 import nltk from prettyprint import pp jp_sent_tokenizer = nltk.RegexpTokenizer(u'[^ 「」!?。]*[!?。]') sents = jp_sent_tokenizer.tokenize( docs[0] ) pp(sents) # sentence -> words 分割処理の例。トークン化。 # (注意) MeCabに渡すテキストは UTF-8 でエンコード必須。 # 最初から全てを UTF-8 化しておくと良さそうだが、 # 一方、NLTKの一部は UTF-8 では正しく処理できないこともあるため、 # ここでは docs に文書を保存する際には unicode 指定している。 # もし文書 dcos を utf-8 保存するなら、NLTKへは unicode 変換して渡そう。 import MeCab mecab = MeCab.Tagger('-Ochasen') node = mecab.parseToNode(docs[0].encode('utf-8')) while node: print "surface=%s -> feature=%s" % (node.surface, node.feature) node = node.next # token を基本形に修正する例。ステミング。 node = mecab.parseToNode(docs[0].encode('utf-8')) while node: fs = node.feature.split(",") print "surface=%s -> fs[6]=%s" % (node.surface, fs[6]) node = node.next def collect_words_jp(docs): u'''日本語文書集合 docs からの単語コードブック作成例。 シンプルに文書集合を予め決めうちした方式で処理する。 必要に応じて指定できるようにしていた方が使い易いかも。 <使用しているライブラリの説明> nltk.RegexpTokenizer: 文章(doc)をパターンマッチングで文(sentence)に分割する。 mecab.parseToNode: 形態素解析結果を双方向連結リストとして出力。node.next <-> node.prev ''' codebook = [] pos = ['形容詞', '形容動詞','感動詞','副詞','連体詞','名詞','動詞'] jp_sent_tokenizer = nltk.RegexpTokenizer(u'[^ 「」!?。]*[!?。]') stopwords = [u"", u"*", u"これ", u"あれ", u"は", u"が", u"の", u"を", u"です", u"、", u"。"] for doc in docs: for sent in jp_sent_tokenizer.tokenize(doc): node = mecab.parseToNode(sent.encode('utf-8')) 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 codebook = collect_words_jp(docs) codebook.sort() pp(codebook)
コードブックを素性とする文書ベクトルを作る (直接ベクトル生成)
def make_vectors_jp(docs, codebook): u'''コードブックを素性とする文書ベクトルを作る(直接ベクトル生成) n-gramモデルの例と流れは一緒。 「doc=1文とは限らない」ケースにも対応するよう拡張。 ''' vectors = [] jp_sent_tokenizer = nltk.RegexpTokenizer(u'[^ 「」!?。]*[!?。]') for doc in docs: this_vector = [] fdist = nltk.FreqDist() for sent in jp_sent_tokenizer.tokenize(doc): node = mecab.parseToNode(sent.encode('utf-8')) while node: fs = node.feature.split(",") this_word = fs[6] fdist.inc(this_word) node = node.next for word in codebook: this_vector.append(fdist[word]) vectors.append(this_vector) return vectors data = make_vectors_jp(docs, codebook) data