ノート/テキストマイニング
訪問者数 7455      最終更新 2015-01-05 (月) 13:21:33

参照 2014-03-12の項

これの、最後の項: LSIやLDAを手軽に試せるGensimを使った自然言語処理入門 を参照しながらやってみる。

2014-07-11 gensimの導入

対象はmint

pythonは既に入っているので、numpy, scipy等を導入したい。そのためにはBLAS等が必要。

参考=Centos6.0上のインストール例

なお、CUDAはデバイスが無いので、無し。

これで、gensimが入れられるので、gensimのHPのインストールマニュアル に従ってインストール

pip install --upgrade gensim

word2vecを試してみたい(models.word2vec – Deep learning with word2vec、 Word2vec Tutorial のだが、入力コーパスデータをどうするか。

models.word2vec – Deep learning with word2vec にある説明だとBrownCorpus (NLTKからパクれる)、Text8Corpus(C版のWord2Vecの時にダウンロード済み)があるが、text8で試すと、有名な

model.most_similar(positive=['woman', 'king'], negative=['man'], topn=1)
[('queen', 0.50882536)]

が出てこない。

もう少し挑戦を要する。別途日本語データを試してみたい。たとえば ニューラルネットによる単語のベクトル表現の学習 〜 Twitterのデータでword2vecしてみた の辺を再現してみたい。

あとは、ニューラルネットによる単語のベクトル表現の学習 〜 Twitterのデータでword2vecしてみた のように、しこしこやるか。   追記: 日本語対象ではないが、Gensimを使ったトピック単語抽出 LSAを使ったトピック語抽出まで にやはりgensimを援用した例がある。ペルシャ語だそうな。

ここから、LSIやLDAを手軽に試せるGensimを使った自然言語処理入門 に従う

Wikipediaからコーパスを作成する

まずjawikiの内容を持ってくる。大分前(ファイル日付は2013-05-08になっている)にダウンロードしたものがあるので、それを使う。

このページLSIやLDAを手軽に試せるGensimを使った自然言語処理入門にあるjawikicorpus.pyは、

python jawikicorpus.py jawiki-latest-pages-articles.xml.bz2 jawiki

ではエラーが出てうまく動かなかった。⇒

このエラーの原因は、gensimのバージョンが現時点最新が0.10.0であり、

pip install gensim

でインストールするとこれが入る。ところが、jawikicorpus.pyは0.7.2見当をベースにしてオーバーライドしているので、そもそも中身のメソッド名が変わっているし、引数も変わっている。そこで、

pip install "gensim<0.7.4"

ぐらいのことをして、gensimの古いバージョンを再インストールすると、動いた。

出来た3つのファイルを、

wp2txtを使う方法

wp2txtでウィキペディアダンプファイル(XML形式)からXMLタグやその他の不要部分を取り除いて、テキストのみにすることができる。rubyで動く。(最新バージョン環境では動かず、動くまで結構面倒だったが、ruby 2.0.0のバージョンで動いた。)

まずrubyをインストールする。以下の方法だと個人ユーザごとにインストールする。

ではなくて、システムワイドにrubyをインストールするには、

これで、wp2txtのインストールができるようになった

wp2txtのありかはgithubのここ だが、知らなくても済む。

wp2txtのインストールは、

追加で、

gem install bundler

が必要になる。

ここでようやく、プログラムwp2txtが使えるのだが、その前に、自ユーザの環境で、実際に使う作業ディレクトリ下で、bundleの設定(ruby使用時の最初)

bundle init

ファイル (作業ディレクトリ)/Bundleを、テキストエディタで編集し、使うgemを登録。書き方はこんな感じ (参考 Ruby書くならBundler使え

source 'https://rubygems.org'
gem 'bzip2-ruby-rb20'
gem 'nokogiri'
gem 'sanitize'
gem 'trollop'

#gem 'json', '~> 1.7'     バージョンを指定したい時
#gem 'tw', :git => 'git@github.com:shokai/tw.git'  取ってくる元を指定したいとき

こうしておいて、後はwp2txtを起動して処理すればよい。-oは出力ディレクトリ指定

wp2txt --input-file jawiki-latest-pages-articles.xml.bz2 -o ./

出力のイメージは、以下のようなファイルができて、

jawiki-latest-pages-articles.xml-001.txt
jawiki-latest-pages-articles.xml-002.txt
...
jawiki-latest-pages-articles.xml-379.txt
jawiki-latest-pages-articles.xml-380.txt

その内容は、たとえばfilewp2txt_output_sample.txtのような形になっている。

更にここから、

追加

2014-08-14付けの(少し新しい)記事  wp2txtでwikipediaのコーパスを作るまでの道のり

追加

英文用だが、NLTK向けのウィキペディアコーパスのパッケージとして、pavlobaron/wpcorpus がある。


別にページを立てて、日本語Wiki Corpusをさらに追求する(2015-01-08)

 >> ノート/テキストマイニング/gensim-word2vecでベクトル空間を試す
 >> ノート/テキストマイニング/gensim-word2vecでベクトル空間を試す2?


自前でtwitterからコーパスファイルを作ってみる

参考にしたのは、自然言語処理の最新手法"word2vec"で艦これ加賀さんから乳を引いてみる

やり方は、

まず、twitterデータをファイルに落としておく。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import codecs
import time
import MySQLdb
import string
import time
import datetime
from dbinit import dbinit
sys.stdout = codecs.getwriter('utf_8')(sys.stdout)

def generatefile(year, month, day):
  df = datetime.datetime(year, month, day)
  filename = 'data/' + u'tw' + df.strftime("%y%m%d")  # file per day
  outf = open(filename, 'w')

  for hour in range(0, 24):
    d = datetime.datetime(year, month, day, hour)  # DB table per hour
    tablename = u'tw' + d.strftime("%y%m%d%H")

    con = dbinit()
    cur = con.cursor()
    s = ("SELECT text FROM " + tablename ).encode('utf_8')
    cur.execute(s)

    r = cur.fetchone()
    while r != None:
        outf.write((r[0].replace('\n',''))+'\n')  #内部の\nは抜く、最後に\nを付ける
        r = cur.fetchone()
    cur.close()
    con.close()

  outf.close()

year = 2014;  month = 6; day = 1
argvs = sys.argv
if len(argvs) < 2:
    print 'Usage: python %s day' % argvs[0]
    quit()
lastday = int(argvs[1])
for day in range(1,lastday+1):
  generatefile(year, month, day)

結果はたとえば

午前零時丁度です!
今日お父さんとお兄の子供が誕生日だおめでとう

みたいな感じのファイルになる。

次に、いま仮に、形態素解析で問題になりそうな(余分な名詞等を生成する)文字を先に取り除いてしまう。これがいいかどうかはよくわからない。その後、MeCabで単語に分ける。分かち書き指定でもよいが、どうせあとで「名詞だけ」とかやりたくなるので、丁寧に通しておく。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import sys
import re
import codecs
import MeCab
import string
import datetime
sys.stdout = codecs.getwriter('utf_8')(sys.stdout)
argvs = sys.argv
if len(argvs) < 2:
    print 'Usage: python %s directory' % argvs[0]
    quit()

mt = MeCab.Tagger()
r = re.compile(u'[a-zA-Z0-9a-zA-Z0-9_@:/\?#\(\)\*\^\.ヾ∀´▽←→⇒●○◎ ■□◇∧+∩><\/ 『  』「」@?♪人`≧≦☆★ωД【】! ノ・゚]|(笑)|(笑)')

for infname in  os.listdir(argvs[1]):
    inf = open(argvs[1]+'/'+infname, "r")
    outfname = infname + '.out'
    outf = open(outfname, "w")
    for ll in inf.readlines():
        l = ll.decode('utf-8')
        lout = r.sub('', l, re.U)
        lout = r.sub('', lout, re.U)
        lout = r.sub('', lout, re.U)
        lout = r.sub('', lout, re.U)

        outstr = ''
        m = mt.parseToNode(lout.encode('utf_8'))
        while m:
             #print "m.surface\t", m.surface, "\t", m.feature
             mm = m.feature.split(',')
             hinshi = mm[0]; hinshi2 = mm[1]; hinshi3 = mm[2]
             #print "surface", m.surface, "hinshi", hinshi, "hinshi2", hinshi2
             #if hinshi2==u'固有名詞' and hinshi3==u'人名':
                 #print hinshi2, hinshi3, m.surface, m.feature
             tango = (m.surface).decode('utf-8')
             outstr = outstr + ' ' + tango 

             m = m.next
        outf.write((outstr+'\n').encode('utf-8'))

    inf.close(); outf.close()

結果は、

 午前 零 時 丁度 です
 今日 お父さん と お 兄 の 子供 が 誕生 日 だ おめでとう

みたいな感じのファイルになる。

本当は、もっと丁寧にスクリーンすべきだろう。いまは英数字の小文字はすべて消しているが、残すものはないか? 1文字の単語は除いたほうがいいのか?(そういう記述もどこかで見たような気がする) 形態素解析後の除外単語リストを用意したほうがいいのではないか? など。

次に、これを入力として、コーパスを作り学習させる。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import codecs, sys
import gensim, logging
import glob

sys.stdout = codecs.getwriter('utf_8')(sys.stdout)
logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)

#sentences = [['first', 'sentence'], ['second', 'sentence']]
sentences = []
argvs = sys.argv
if len(argvs) < 2:
    print 'Usage: python %s directory' % argvs[0]
    quit()
if glob.glob(argvs[1]+'tw*.out') == []:
    print 'No file found'
    quit()
for infname in  glob.glob(argvs[1]+'/tw*.out'):
    inf = open(infname, "r")

    lines = inf.readlines()
    print len(lines)
    for l in lines:
        ll = l.decode('utf-8')
        u = ll.split()
        sentences.append(u)
# train word2vec on the two sentences
#model = gensim.models.word2vec.Word2Vec(sentences, size=5, min_count=1)
model = gensim.models.word2vec.Word2Vec(sentences, size=200)

def s(posi, nega=[], n=5):
    cnt = 1
    result = model.most_similar(positive = posi, negative = nega, topn = n)
    print u'順位', u'語', u'類似度'
    for r in result:
        print cnt, r[0], r[1]
        cnt += 1

これを、python -i <このファイル> ./ で実行し、最後にプログラムを終了させずにインタラクティブモードにする(-i指定)

それで、pythonのプロンプトが返ってきたら、sを呼び出して、similarityを試す。

s([u'単語'])
s([u'単語1'], [u'単語2'])  単語1はプラスする側、単語2はマイナスする側らしい

など。

>>> s([u'俺'])
順位 語 類似度
1 お前 0.744944870472
2 オレ 0.688959181309
3 あたし 0.664245307446
4 私 0.636135101318
5 あいつ 0.625858306885

>>> s([u'終電',u'飲み'])
順位 語 類似度
1 カフェオレ 0.514149785042
2 ノンストップ 0.487345725298
3 夜勤 0.482436865568
4 休憩 0.477039635181
5 自習 0.466827243567

>>> s([u'新幹線',u'東京'],[u'帰り'])
順位 語 類似度
1 台東 0.608730196953
2 墨田 0.606704652309
3 大田 0.605434894562
4 世田谷 0.600871801376
5 港南 0.589032173157
>>> s([u'ビール'])
2014-07-22 14:00:36,899 : INFO : precomputing L2-norms of word weight vectors 
順位 語 類似度
1 酒 0.69725757187
2 コーヒー 0.57643532753
3 飲ん 0.553569257259
4 ワイン 0.549029290676
5 焼酎 0.547343611717

>>> s([u'ビール',u'甘味'],[u'苦味'])
順位 語 類似度
1 酒 0.539837956429
2 リキュール 0.483482539654
3 ワイン 0.463366270065
4 小さじ 0.455082446337
5 ビア・スプリッツァービール 0.441155195236

>>> s([u'ビール',u'食後'],[u'最初'])
順位 語 類似度
1 コーヒー 0.564417600632
2 糖分 0.545417428017
3 酒 0.540220439434
4 豚肉 0.524781763554
5 カフェイン 0.517480552197

>>> s([u'アルタ',u'大阪'],[u'東京'])
順位 語 類似度
1 難波 0.510343253613
2 郡山 0.509273350239
3 ペデストリアンデッキ 0.508496820927
4 豊中 0.501317083836
5 バスターミナル 0.488690584898

>>> s([u'ヒルズ',u'大阪'],[u'東京'])
順位 語 類似度
1 泉佐野 0.57211792469
2 豊中 0.554686248302
3 フェスティバルホール 0.53991407156
4 大館 0.535022377968
5 西部 0.526072919369

>>> s([u'丸の内',u'大阪'],[u'東京'])
順位 語 類似度
1 心斎橋 0.697996973991
2 和食 0.614294946194
3 六本木 0.583541929722
4 つぶやい 0.58198171854
5 焼き鳥 0.570201039314

>>> s([u'豊洲',u'大阪'],[u'東京'])
順位 語 類似度
1 東大阪 0.599119186401
2 下京 0.593882799149
3 京都 0.592132568359
4 泉佐野 0.586484372616
5 豊中 0.580929577351

上手く行かない例

>>> s([u'表参道',u'大阪'],[u'東京'])
順位 語 類似度
1 東急 0.565302491188
2 プラザ 0.563798010349
3 吉祥寺 0.520717322826
4 元町 0.512206435204
5 原宿 0.473855346441

>>> s([u'銀座',u'大阪'],[u'東京'])
順位 語 類似度
1 吉祥寺 0.539390444756
2 京都 0.495363503695
3 都島 0.49504378438
4 新橋 0.489007294178
5 梅田 0.488498836756

自前でコーパスファイルを作るには

おまけ MeCabの辞書に単語を登録する方法

おまけ NLP参照ページ

NLP論文

おまけ twitter解析のまとめ論文


添付ファイル: filewp2txt_output_sample.txt 461件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2015-01-05 (月) 13:21:33 (902d)