簡単で効率的♪ Pythonをつかって、Nグラム表をささっと作成する
前回に引き続き、Nグラムの話です。タイトルをクックパッドぽくしてみました。nグラム表を作って、そこからフレーズを取り出してみます。以下の文献を参考にしました。
長尾眞, 森信介, 1993, 「大規模日本語テキストのnグラム統計の作り方と語句の自動抽出」, 情報処理学会研究報告. 自然言語処理研究会報告 93(61), 1-8
1993年の文献だけあって、「処理能力が向上」、「64MBのメモリ」などなど懐かしさこみあげる文言が踊っています。それだけあって、いかに効率的にやるかという点に焦点があてられています。やはり、人の営為を研ぎ澄ませるのはいつでも制約条件ですね。
まずは下ごしらえです。L文字の文章資源を、i=1,2..文字目からL文字目までのL本の文字列にして、それを辞書順にソート、前後の文字列が何文字目まで同一かを調べます。
from collections import defaultdict raw_string = お手元の文章資源(ここでは参院選期間中の候補者のツイートを使用) # 改行コードと半角スペースをなきものにしちゃったけどいいのかな…。 raw_string = raw_string.replace(u"\n",u"").replace(u" ",u"") # 下ごしらえ # i文字目からlen(raw_string)文字目までのlen(raw_string)本の文字列をつくる strings = [] for i in range(len(raw_string)): strings.append([raw_string[i:], i]) # 辞書順で並び替え(時間掛かる) strings = sorted(strings, key=lambda x:x[0]) # i番目の文字列とi+1番目の文字列は、なん文字目まで一致するか?(最大MAX_N文字に設定) MAX_N = 12 for i in range(len(strings)-1): count, _MAX_N = 0, MAX_N if len(strings[i][0]) < MAX_N or len(strings[i+1][0]) < MAX_N: # 文字列の長さがMAX_N未満の場合 if len(strings[i][0]) < len(strings[i+1][0]): _MAX_N = len(strings[i][0])-2 else: _MAX_N = len(strings[i+1][0])-2 for j in range(_MAX_N): if strings[i][0][j] == strings[i+1][0][j]: count += 1 else: break strings[i].append(count) #if len(strings[i]) < 3: strings[i].append(count) #else: strings[i][2] = count
nグラム表をつくる関数を定義して、試しに10グラム表を出力してみます。論文を読んでいて、ここが一番美しかった!
# nグラム表と、n文字列の左右の1文字辞書(あとで使う)の作成 l_str, r_str = defaultdict(list), defaultdict(list) def make_ngram_table(raw, strs, n_gram, l_str=l_str, r_str=r_str): ngram_table = defaultdict(int) for i in range(len(strs)-1): if len(strs[i][0]) < n_gram: continue # 文字列の長さがn数未満の場合はスルー if strs[i][2] >= n_gram: ngram_table[strs[i][0][:n_gram]] += 1 # nグラム表(dict)を作成 if strs[i][1] != 0: l_str[strs[i][0][:n_gram]].append(raw[strs[i][1]-1]) # 左の1文字辞書へ追記 r_str[strs[i][0][:n_gram]].append(strs[i][0][n_gram]) # 右の1文字辞書へ追記 return ngram_table # 試しに10グラム表を作ってみる ngram_table = make_ngram_table(raw_string, strings, 10) # 頻度30回以上に絞り込んで、頻度が高い順にソート ngram_table_30 = sorted([n for n in ngram_table.items() if n[1] >= 30], key=lambda x:x[1], reverse=True) # 10文字列|頻度 となるように出力 for nstring in ngram_table_30: print u"%s|%s" % (nstring[0], nstring[1]) # tp://t.co/|252 # ttp://t.co|252 # http://t.c|252 # (BOT)#石田まさ|124 # OT)#石田まさひろ|124 # BOT)#石田まさひ|124 # す(BOT)#石田ま|85 # 。http://t.|79 # ます(BOT)#石田|66 # ブログを更新しました|45 # ログを更新しました。|45 # ...http://|42 # .http://t.|42 # ..http://t|42 # 』http://t.|40 # す。http://t|37 # グを更新しました。『|36 # ます。http://|31
続いて、n文字列の左右の1文字のレパートリが多い場合に、そのn文字列がひとつの塊である可能性が高いという仮説のもと、先ほど作ったl_str, r_strを利用して、塊の可能性が高いものを出力してみます。
# n文字列の左右の1文字のレパートリが多いとき、単語の可能性が高いと仮定し、それを出力する def extract_words(ngram_table, freq_thres, lr_thres, l_str=l_str, r_str=r_str): for w in ngram_table.items(): if w[1] >= freq_thres: lr_count = len(list(set(l_str[w[0]]))) + len(list(set(r_str[w[0]]))) if lr_count >= lr_thres: print u"%s|%s|%s" % (w[0], w[1], lr_count) # In [329]: extract_words(make_ngram_table(raw_string, strings, 10), 10, 10) # Out [329]: # 単語(候補)|頻度|左右の文字の種類数 # ありがとうございます|24|20 # (BOT)#石田まさ|124|10 # ブログを更新しました|45|30 # tp://t.co/|252|61 # ...http://|42|16 # 』http://t.|40|23 # OT)#石田まさひろ|124|50 # 次の@YouTube|12|12 # りがとうございます。|14|12 # 。http://t.|79|15 # 新しい写真をFace|17|13 # グを更新しました。『|36|15 # http://t.c|252|35 # せていただきました。|12|12
このあと論文は、塊をうまく取り出す方法を幾つか提案しているのですが、それはまた後日ということで今日はここまで。
Nグラムを使った未知語の抽出(仮)
n-gramsってどう使うのかよく分かんないなー、どうしてGoogle IMEは「灼眼のシャナ」とか「やはり俺の青春ラブコメはまちがっている。」とかをひとつのフレーズとして認識しているのだろう・・・とググっていたら、こんな論文をみつけた。
森信介, 長尾眞, 1998, 「nグラム統計によるコーパスからの未知語抽出」, 『情報処理学会論文誌』, 39:7, 2093-2100.
「品詞ごとに、前後にくる文字にはパターンがある」という仮定に基いて未知語を探すらしい。
名詞の場合、コーパスを分析すると「ご<名詞>の」とか「、<名詞>し」とかいうパターンが多かった、みたいな。
この論文だと、このパターンの辞書を各品詞について作成したあとに、各単語についても同様のパターンを作成して、なんだか最適化問題を解いているのだけど、まず、各単語についてそれぞれ辞書をつくるほどコストを掛けていたら朝になってしまいそうなので、この論文を数リットルの水で薄めたようなコードを書いてみた。
コーパスには、手元にあった、先の参院選のときの候補者のツイートを使った。
※mecab_libraryについてはこちらを参照してください。
import mecab_library from collections import defaultdict corpus = 先の参院選のときの候補者のツイート tokens = mecab_library.Tokens(corpus.encode("utf-8")).tokens #In [103]: len(tokens) #Out[103]: 104666 # 名詞の環境構築 # 名詞の前後にくる文字をひらがなと括弧だけに限定した(reでやるのめんどくさかった) hiragana = [h for h in u"あぁいぃうぅえぇおぉかがきぎくぐけげこごさざしじすずせぜそぞただちぢつづってでとどなにぬねのはばぱひびぴふぶぷへべぺほぼぽまみむめもやゃゆゅよょらりるれろわゎをん、。「」【】『』()”"] pos = "名詞" lr_str = defaultdict(int) pos_tokens = [token.surface for token in tokens if token.pos == pos] # 各名詞をコーパスから探して、その前後のひらがなをキーにした辞書を作成(値は頻度) for pos_token in pos_tokens: index = 0 len_token = len(pos_token.decode("utf-8")) _corpus = corpus index = _corpus.find(pos_token.decode("utf-8")) if index > 0 and index+len_token < len(_corpus) and _corpus[index-1] in hiragana and _corpus[index+len_token] in hiragana: lr_str[(_corpus[index-1], _corpus[index+len_token])] += 1 _corpus = _corpus[index+len_token:] # なんとなく頻度で並び替えて、前後の文字の組み合わせが生じる確率とか出してみる lr_sorted = {} for k, v in sorted(lr_str.items(), key=lambda x:x[1], reverse=True): lr_sorted[k] = 1.0*v/len(pos_tokens) # 左右の文字の組み合わせを使って、それに挟まれた文字列を取り出す lrs = [(k[0], k[1]) for k, v in lr_sorted.items()] surfaces = [token.surface.decode("utf-8") for token in tokens] newwords = defaultdict(int) for lr in lrs: lindex = 0 _corpus = corpus.replace(u"\n",u" ").replace(u" ",u"").replace(u" ",u"") while lindex != -1: lindex = _corpus.find(lr[0]) _corpus = _corpus[lindex+1:] r = u"" i = 0 # 組み合わせの右の文字に当たるまで一文字ずつ文字列を増やしていく while i <= 7 and i < len(_corpus): # 7文字のフレーズまで探すことにした r = _corpus[i] if i == 0 and r in hiragana: # もうこの辺、ぐっちゃぐちゃ・・・ break if r != lr[1] and r in hiragana: # フレーズにひらがながはいらないようにしちゃった・・・ break if r == lr[1]: # 7文字以内に右側の文字がみつかったよ! newword = _corpus[0:i] if len(newword) != 1 and newword.find(u"/") == -1 and newword not in surfaces: newwords[newword] += 1 break i += 1 # 頻度順に並べ替えて出力(これを確率とかにして閾値とか設定したらいいんじゃないかな・・・) newwords2 = sorted([(k, v) for k, v in newwords.items()], key=lambda x:x[1], reverse=True) for newword2 in newwords2[:10]: print u"%s\t%s" % (newword2[0], newword2[1])
結果は、↓みたいな感じになった。まぁ、そこまでひどくないけど、ひらがなや括弧を含まないようにしたせいで、微妙なのも混じってしまって、決してよいとは言えない感じだ。それにこれでは、「灼眼のシャナ」とか「やはり俺の青春ラブコメはまちがっている。」はやはり取り出せない・・・。
看護職 22 街頭演説 12 加盟組合 11 目指 10 投票日 10 公式サイト 9 選挙戦 9 一日 9 看護師 8 個人演説会 7 見直 7 夜勤体制 6 定期大会 6 人材確保 6 医療現場 6 看護・介護職 6 利用者 6 義務教育 5
まだまだだなぁ・・・。
Django1.5でGoogle App Engineのチュートリアルをやったときのメモ
Google App Engine上のDjangoでのチュートリアル、「Using Django with Appengine」邦訳 - WebOS Goodiesをやろうとしたところ、チュートリアルで使われているDjangoとGAEのバージョンが古くそのままでは動きませんでした。
色々なサイトを参考にしながら動くところまでこぎつけたので、そのメモです。
※どのディレクトリのファイルか分かりづらかったのでパスも書きました。
参考サイト
GAE - GoogleAppEngine/PythonでDjangoを使う方法 - Qiita
まず、GAEに付属しているDjango1.5のあるディレクトリにパスを通します。
$ vim ~/.bash_profile PYTHONPATH = "/usr/local/google_appengine/lib/django-1.5:$PYTHONPATH" export PYTHONPATH
Creating a project
ホームディレクトリにGAEというフォルダを作成し、プロジェクトを開始します。
$ cd ~ $ mkdir GAE $ cd GAE $ /usr/local/google_appengine/lib/django-1.5/django/bin/django-admin.py startproject appproject
これで、~/GAE以下にappprojectという名前のディレクトリが作成されます。チュートリアルにある、main.pyを作成する必要はありませんが、代わりに~/GAE/appproject/にappengine_config.pyを作成します。
$ cd appproject $ vim appengine_config.py # -*- coding: utf-8 -*- import os import sys if os.environ.get('SERVER_SOFTWARE','').startswith('Dev'): sys.path.append('/Users/あなたのユーザ名/GAE/appproject/appproject') os.environ.setdefault("DJANGO_SETTINGS_MODULE", "appproject.settings")
つづいて、~/GAE/appproject/にapp.yamlを作成します。
application: appproject version: 1 runtime: python27 api_version: 1 threadsafe: yes libraries: - name: django version: "1.5" builtins: - django_wsgi: on
続いて、チュートリアルにしたがって、以下のコマンドを打ちます。
$ python manage.py startapp poll
Editing the settings.py file
ここでは、~/GAE/appproject/appproject/settings.pyを編集していきます。
110 import os 111 ROOT_PATH = os.path.dirname(__file__) 112 113 TEMPLATE_DIRS = ( 114 # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". 115 # Always use forward slashes, even on Windows. 116 # Don't forget to use absolute paths, not relative paths. 117 ROOT_PATH + '/templates', 118 ) 119 120 INSTALLED_APPS = ( 121 'django.contrib.auth', 122 'django.contrib.contenttypes', 123 'django.contrib.sessions', 124 'django.contrib.sites', 125 'django.contrib.messages', 126 'django.contrib.staticfiles', 127 # Uncomment the next line to enable the admin: 128 # 'django.contrib.admin', 129 # Uncomment the next line to enable admin documentation: 130 # 'django.contrib.admindocs', 131 'poll', 132 )
Write the URL configuration file
~/GAE/appproject/appproject/urls.pyを編集します。
7 urlpatterns = patterns('', 8 # Examples: 9 # url(r'^$', 'appproject.views.home', name='home'), 10 # url(r'^appproject/', include('appproject.foo.urls')), 11 12 # Uncomment the admin/doc line below to enable admin documentation: 13 # url(r'^admin/doc/', include('django.contrib.admindocs.urls')), 14 15 # Uncomment the next line to enable the admin: 16 # url(r'^admin/', include(admin.site.urls)), 17 (r'^$', 'poll.views.index'), 18 (r'^create/$', 'poll.views.create'), 19 (r'^poll/(?P<poll_key>[^\.^/]+)/$', 'poll.views.poll_detail'), 20 (r'^poll/(?P<poll_key>[^\.^/]+)/results/$', 'poll.views.poll_results'),
Write the models.py file.
~/GAE/appproject/poll/models.pyはそのままで動きました。
Writing the forms
~/GAE/appproject/poll/bforms.pyを作成します。
from django import newforms as forms
とありますが、newformsはformsに統一されたようなので、
from django import forms
で問題ありません。
また、crean_dataをcreaned_dataに変更します。
def save(self): choice = models.Choice(poll = self.poll, choice = self.cleaned_data['choice']) choice.put()
Write the view
~/GAE/appproject/poll/views.pyを編集します。
モジュールのインポートが少し違います。CSRFはフォーム送信関係のセキュリティ対策のようです。
1 from django.http import HttpResponse, HttpResponseRedirect 2 import models 3 import bforms 4 from django.shortcuts import render_to_response 5 from django.core.context_processors import csrf 35 payload = dict(pollform=pollform, choiceforms=choiceforms) 36 payload.update(csrf(request)) 37 return render('create.html', payload)
Writing the templates
~/GAE/appproject/poll/に、templatesディレクトリを作成し、そこにテンプレートファイル(.html)を作成していきます。チュートリアルではファイル名が分かりづらいですが、一個目のコードがindex.html、二個目のコードがbase.htmlです。
create.htmlに先ほどのCSRF関係のコードを書き足します。
{% extends 'base.html' %} {% block contents %} <form action="." method="post"> {% csrf_token %} {{pollform.as_p}} {% for form in choiceforms %} {{form.as_p}} {% endfor %} <input type="submit" name="createpoll" value="createpoll" /> </form> {% endblock %}
これで、サーバーを立ち上げ、http://localhost:8080にアクセスすれば動いている(はず)です。
$ cd ~/GAE/appproject
$ dev_appserver.py .
それで、Applications OverviewでCreate Applicationして、
$ cd ~/GAE/appproject $ appcfg.py --oauth2 -A プロジェクト名 update プロジェクトのディレクトリ
とやればデプロイされ、http://プロジェクト名.appspot.comでアクセスできるらしいです(このプロジェクト名だともう使われているだろうけど…)。
ただ、このチュートリアルのコードだとどうがんばっても投票数が増えていかないと思うんですが、どうなんだろう…。
「客観的に」認められたいとい欲望は、結局は自尊の相関だ。
「客観的」なんて純粋にはあり得ない。神の視点なんてない。あったとしても、その視点から見える私はちっぽけでどうでもよいものだろう。客観性のニヒリズムだ。
そうではない。客観的な見方の第一歩は、「もし相手だったらどう思うか?」という私の主観だったはずだ。そして二歩目以降もそれは変わらない。
つまり、「客観的」は、私の主観から出発している以上、私の性向と必要性の上にある。
すなわち、「相手だったら?」「みんなから見たら?」と考えずにはいられない性向と、その視点から見ても自分はマトモだと思いたいという必要性だ。
そうして、私は、私の延長線にある遠い視点からも、私のことを大切な存在と思いたい、そんなわがままな思いを抱いて、見えないなにかと闘い続けるのです。
生きることは、主体と対象の理想的時間の闘争だ
ハイデッガーが言っているのはこういうことだ。私たちは何かによって退屈させられている時、その何かがもつ時間にうまく適合していないと言っているのである。
つまりある物とそれに接する人間がいるとして、両者の間の時間のギャップによってこの第一形式の退屈(引用者注―何かによって退屈させられること)が生じるのである。何かによって退屈させられるという現象の根源には、物と主体との間の時間のギャップが存在している。それによって〈引きとめ〉が生じ、〈空虚放置〉される。
國分功一郎『暇と退屈の倫理学』(p.216)からの引用だ。この引用部分の直前で、物にはそれ特有の時間があり、例えば駅舎に特有の時間とは駅舎の理想的時間、すなわち、列車発車の直前であると述べている。
この箇所が、この本を通読した後、妙に頭に残っている。なぜだろうか。おそらく、私の中に、なんらかの物との時間のギャップによって生じる苦悩*1があるからではないか。
たとえば、病で長く床に臥せるとき、私は私の所属している社会に置いて行かれる感覚に苦悩する。社会のもつ理想的時間に病の身はうまく適合できない。このとき、社会の理想的時間は朝9時の出社と十数時間の労働が5日間連続でなされることだ。病の身はこの時間に着いていけない。
一方で、病がその治療に数年の時間を要することが判明したとしよう。このとき、私は苦悩する。しかしそれは先ほどとは異なった不適合によってである。なぜならば、このとき病者は、病者の時間とでも言いうる時間を生きようとしているからだ。すなわち、治療を最大の目的に置き、時間の流れをできるだけ遅くするような時間だ。私がこのような時間を生きるとき、病者の時間と社会の時間の間のせめぎあいが生じる。このせめぎあいが、苦悩となる。社会の時間に着いていけないのではない。重篤な病は、主体が社会の時間に束縛され、奴隷状態となることから解き放つ。
ただ、このせめぎあいに病者が勝利を収めることはなかなかに難しい。結局は社会の時間に変更を迫るのではなく、一度そこから退出し、現在とは異なる社会に新たに所属するようにするしかない場合がほとんどだろう。
私が苦悩しているのは、これまで私が所属していた社会と、最適な時間が異なり、私は社会の側の時間の非柔軟性故に闘いを挑むことすら叶わないという様相なのだ。
- 作者: 國分功一郎
- 出版社/メーカー: 朝日出版社
- 発売日: 2011/10/18
- メディア: 単行本(ソフトカバー)
- 購入: 13人 クリック: 146回
- この商品を含むブログ (128件) を見る
Unicode型とstr型。Pythonさん、勝手にasciiでデコードしないでください。
Pythonは便利ですが、日本語の取り扱いになると突然面倒になる。
Traceback (most recent call last): File "<stdin>", line 1, in ? UnicodeDecodeError: 'ascii' codec can't decode byte 0xe3 in position 0: ordinal not in range(128)
ってなエラーが出る度に日本語圏に生まれたことを呪う…とまではいかないけど、結構いらいらする。
PythonのUnicodeEncodeErrorを知る - HDEラボ
http://lab.hde.co.jp/2008/08/pythonunicodeencodeerror.html
を参考に、忘備録的に記録します。
上記サイト様によれば、最初のエラーは、
str型を文字コード'ascii'でデコードしてunicode型にしようとしたのですが、できませんでした、というエラーです。
また、
encodeは、「Unicode型を特定の文字コードのバイト列(のstr型)にエンコードする」ためのメソッドです。
decodeは、「特定の文字コードのバイト列(のstr型)をデコードしてUnicode型にする」ためのメソッドです。
とのこと。
In [115]: u"あ" Out[115]: u'\u3042' In [116]: "あ" Out[116]: '\xe3\x81\x82' In [117]: type("あ") Out[117]: str In [118]: type(u"あ") Out[118]: unicode In [119]: "あ".decode("utf-8") Out[119]: u'\u3042' In [120]: u"あ".encode("utf-8") Out[120]: '\xe3\x81\x82'
MeCabとNLTKを使って最瀕語と共起関係を出力する
MecabとNLTKを使って最瀕語と共起関係を出力するコードを書きました。
Mecabのインストールについては、Windowsなら結構難なく行くようですが、Mac OSX Lionだととても躓きました。
その辺りの経緯は、mecab-pythonをMac OSX 10.7 Lion、Python2.7にインストールする - Men talking over coffee with smoking Ark Royal.を参考にしてください。
まず、このMeCabで形態素解析を行うコードですが、以前、『入門ソーシャルデータ』勉強会で、Kenji Koshikawa (Kshi_Kshi)さんに頂いた、mecab_library.pyを元にしています(元のリンクが見つけられませんでした、申し訳ございません)。
mecab_library.py
# -*- coding: utf-8 -*- import MeCab mecab = MeCab.Tagger('-Ochasen') class Tokens(object): """textの形態素情報を保持""" def __init__(self, text): self.text = text #print mecab.parse(text) node = mecab.parseToNode(text) self.tokens = [] while node: self.tokens.append(Token(node.surface, *node.feature.split(','))) node = node.next class Token(object): """形態素情報""" def __init__(self, surface, *args): # Mecab Format # 表層形\t品詞,品詞細分類1,品詞細分類2,品詞細分類3,活用形,活用型,原形,読み,発音 self.surface = surface # 表層形 try: self.pos = args[0] # 品詞 self.pos_detail1 = args[1] # 品詞細分類^Z1 self.pos_detail2 = args[2] # 品詞細分類^Z2 self.pos_detail3 = args[3] # 品詞細分類^Z3 self.verb_form = args[4] # 活用形 self.verb_type = args[5] # 活用型 self.basic = args[6] # 原型 self.reading = args[7] # 読み self.pronunciation = args[8] # 発音 self.type = True # 全ての要素が格納できたとき except IndexError: self.type = False # 全ての要素が格納できなかったとき
このmecab_library.pyを用いて、tokenize(text, pos_list=["名詞","動詞"])という関数を作りました。ストップワーズは適宜編集してください。
mecab_tokenizer.py
# -*- coding: utf-8 -*- import mecab_library import pickle # tweets = pickle.load(open("cluster2_tweets.pickle","r")) def splitStr(str, num): l = [] for i in range(num): l.append(str[i::num]) l = ["".join(i) for i in zip(*l)] rem = len(str) % num # zip で捨てられた余り if rem: l.append(str[-rem:]) return l # pos: 名詞, 動詞, 形容詞, 副詞, 助詞, 接続詞, 助動詞, 連体詞, 感動詞, * def classifyPos(words, pos_list=["名詞", "動詞"]): stop_words = ["@","RT","bit","ly","goo","gl","こと","もの","好き"] texts = [] for token in words.tokens: if unicode(token.surface, 'utf-8') in stop_words: continue elif len(unicode(token.surface, 'utf-8')) == 1: continue # 1文字はスルー elif token.pos in pos_list: if token.basic == "*": texts.append(token.surface) else: texts.append(token.surface) return texts def tokenize(text, pos_list=["名詞","動詞"]): sent = text.encode('utf-8') if len(sent) > 2000000: sents = splitStr(sent, 2000000) words = mecab_library.Tokens(sents[0]) texts = classifyPos(words, pos_list) for i in range(1,len(sents)): w = mecab_library.Tokens(sents[i]) texts += classifyPos(w) print len(texts) return texts else: words = mecab_library.Tokens(sent) texts = classifyPos(words) return texts
そして、これらを元にNLTKを用いて、最瀕語と共起関係を出力する関数が以下のものです。引数には、unicode型のstrと、閾値頻度を取ります。(共起と最瀕語で閾値を変えたいときは適宜変更してください)
# -*- coding: utf-8 -*- import nltk import mecab_tokenizer # 共起と最頻語を出力する def collocations_and_freq_words(text, freq=25): tokens = mecab_tokenizer.tokenize(text) corpus = nltk.Text(tokens) print u"-----最頻語(頻度%d回以上)-----" % freq fdist1 = nltk.FreqDist(tokens) saihin1 = fdist1.keys() for voc in saihin1: if fdist1[voc] >= freq: print "%s\t%s" % (voc, fdist1[voc]) print u"" print u"-----共起関係(共起頻度%d回以上)-----" % freq bigrams = nltk.bigrams(corpus) cfd = nltk.ConditionalFreqDist(bigrams) kyouki = cfd.keys() for voc in kouki: for (key, value) in list(cfd[voc].viewitems()): if value >= freq: print "%s\t%s\t%s" % (voc, key, value)
NLTKすごい!ということで。
- 作者: Steven Bird,Ewan Klein,Edward Loper,萩原正人,中山敬広,水野貴明
- 出版社/メーカー: オライリージャパン
- 発売日: 2010/11/11
- メディア: 大型本
- 購入: 20人 クリック: 639回
- この商品を含むブログ (44件) を見る
『エンディング・ボット』
自分の書いた大量の文章をトークン化し、語彙資源化して、バイグラムの頻度分布を作成することで、自分の文章のようなランダムテキストを生成できる。
これを用いて、たとえばこれまでの自分のTwitterのポストを解析し、ランダムなトークンから始まるツイートを生成しつぶやくプログラムをcronにスケジューリングすることで、たとえ自分が死んだとしてもサーバの生きる限り自分のような文章をつぶやき続けるbotを作ることができる。
最近、『エンディング・ノート』とか流行ってるから、ソーシャルメディアのエンディング・ボットとか流行らないかな。
#!/usr/bin/env python # -*- coding: utf-8 -*- import nltk import json import sys FILENAME = sys.argv[1] def generate_model(cfdist, word, num=15): for i in range(num): print word, word = cfdist[word].max() tokens = json.load(open(FILENAME,"r")) text = nltk.Text(tokens) bigrams = nltk.bigrams(text) cfd = nltk.ConditionalFreqDist(bigrams) if __name__ = '__main__': print cfd['living'] # <FreqDist: 'creature': 7, 'thing': 4, 'substance': 2, ',': 1, '.': 1, 'soul': 1> generate_model(cfd, 'living') # living creature that he said , and the land of the land of the land
名詞評価極性辞書を利用したTwitterの感情分析(Positeve/Negative判定)
Twitter感情分析所 さんを利用しようとしたら、結構重たくて、大量の処理を実行するのは申し訳ない…。と思い、じゃあ自分でコードを書いてしまえ、と思い、調べていたところ、東山昌彦, 乾健太郎, 松本裕治, 述語の選択選好性に着目した名詞評価極性の獲得, 言語処理学会第14回年次大会論文集, pp.584-587, 2008.(日本語評価極性辞書)がありました。
日本語評価極性辞書(名詞編)ver.1.0(2008年12月版)pn.csv.m3.120408.trim.gz をダウンロード→解凍し、拡張子に.txtを設定し、適当なエディタで開きます。
Python標準モジュールのcsvで読み込ませるときに、タブ区切りが上手く読み込めなかったので、\tを,に置換して、保存します(Mac OSXの場合、\はoption+\でバックスラッシュを入力)。
また、以下のサイトを参考に、Yahoo!のアプリケーションIDを取得し、形態素解析APIを利用可能にします。
PythonからYahoo!形態素解析APIを使う - 人工知能に関する断創録 | http://d.hatena.ne.jp/aidiary/20090415/1239802199
def get_tweets_from_streaming_listener(filename):は、Streaming APIで大量のつぶやきをリアルタイムに保存する方法(Python編) | inquisitor http://blog.unfindable.net/archives/4257 を参考に、tweepyからTwitter Streaming APIを利用して収集したツイートがresult01.datに保存されている場合に使える関数です。
コンソールから実行すると、スクリーンネームを聞かれますので、入力すると、そのひとのツイートと、その評価が出力されます。(※tweepyを使ってOAuth認証が必要です。)
また、毎度のことですが、Python最大の難所、PythonのUnicodeEncodeErrorを知る - HDEラボ http://lab.hde.co.jp/2008/08/pythonunicodeencodeerror.html を参考にしました。
精度がどのくらいのものなのか、P/N以外の感情も判定したい、などと色々考えていますので、コメントなど頂けると嬉しいです。
#!/usr/bin/env python # -*- coding: utf-8 -*- import csv import json import urllib import urllib2 import tweepy from BeautifulSoup import BeautifulSoup # dev.twitter.comから取得してくる。 consumer_token = "********************************" consumer_secret = "********************************" access_token = "********************************" access_token_secret = "********************************" auth = tweepy.OAuthHandler(consumer_token, consumer_secret) auth.set_access_token(access_token, access_token_secret) oauth_api = tweepy.API(auth) # 名詞評価極性辞書を読み込む in_file = csv.reader(open('pne.txt',"rb")) pne = [] for line in in_file: try: if line[1] == 'p': score = 1.0 elif line[1] == 'e': score = 0.5 elif line[1] == 'n': score = 0.0 pne.append((line[0],score)) except: pass # トークンのリストのP/Nを判定する。 def judge_pn(tokens): score = 0 num_score = 0 for token in tokens: for _pne in pne: if token == _pne[0]: score += _pne[1] num_score += 1 if num_score != 0: pn_rate = float(score)/float(num_score) else: pn_rate = 0.5 return pn_rate # 参考:PythonからYahoo!形態素解析APIを使う - 人工知能に関する断創録 http://d.hatena.ne.jp/aidiary/20090415/1239802199 # http://developer.yahoo.co.jp/webapi/jlp/ma/v1/parse.html appid = "********************************" # 登録したアプリケーションID pageurl = "http://jlp.yahooapis.jp/MAService/V1/parse" def morph(sentence, appid=appid, results="ma", filter="9"): sentence = sentence.encode("utf-8") params = urllib.urlencode({'appid':appid, 'results':results, 'filter':filter, 'sentence':sentence}) c = urllib2.urlopen(pageurl, params) soup = BeautifulSoup(c.read()) return [str(w.surface.string) for w in soup.ma_result.word_list] # Twitter Streaming APIを使ってfilenameにツイートが保存されているものとする def get_tweets_from_streaming_listener(filename): # Streaming Listenerから読み込み lines = open(filename,"r") lines = [line for line in lines] tweets=[] for line in lines: try: tweet = json.loads(line) tweets.append(tweet) except: pass # ツイートから本文だけを取り出す texts = [tweet["text"] for tweet in tweets] return tweets # tweets = get_tweets_from_streaming_listener("result01.dat") # 個々のツイート本文をトークン化 def tokenize_list(list): sents = [] for text in texts: tokenized_text = morph(text) sents.append((text, tokenized_text)) return sents # sents = tokenize_list(texts) # 個々のツイート本文のP/Nを判定し、pn_ratesに格納 def pn_rates_and_sents(sents): pn_rates = [] pn_rates_with_sents = [] for sent in sents: pn_rate = judge_pn(sent[1]) pn_rates.append(pn_rate) pn_rates_with_sents.append((sent[0], pn_rate)) return pn_rates, pn_rates_with_sents # pn_rates, pn_rates_with_sents = pn_rate_and_sents(sents) # P/E/Nスコアを算出して出力する def print_scores(pn_rates): p, e, n = 0.0, 0.0, 0.0 p_num, e_num, n_num = 0.0, 0.0, 0.0 for pn in pn_rates: if pn > 0.5: p += pn p_num += 1 elif pn == 0.5: e += pn e_num += 1 elif pn < 0.5: n += pn n_num += 1 sum = p_num + e_num + n_num print p, e, n, p_num, e_num, n_num print p_num/sum, e_num/sum, n_num/sum if __name__ == '__main__': screen_name = raw_input("Enter Screen Name. > ") tweets = oauth_api.user_timeline(screen_name=screen_name, count=20) texts = [tweet.text for tweet in tweets] sents = tokenize_list(texts) pn_rates, pn_rates_with_sents = pn_rates_and_sents(sents) print_scores(pn_rates) for pn_rate_with_sent in pn_rates_with_sents: print "%s\t%s\n" % (pn_rate_with_sent[0], pn_rate_with_sent[1])
- 作者: Steven Bird,Ewan Klein,Edward Loper,萩原正人,中山敬広,水野貴明
- 出版社/メーカー: オライリージャパン
- 発売日: 2010/11/11
- メディア: 大型本
- 購入: 20人 クリック: 639回
- この商品を含むブログ (44件) を見る
後輩「ツイートをGoogleカレンダーに登録して、みんなの予定管理ができるようにできないかなぁ。」
寝る前にTwitter見るかなぁ、とTLを眺めてたら某後輩が「ツイートをGoogleカレンダーに登録して、みんなの予定管理ができるようにできないかなぁ。」などといったことを呟いていた。
ついこないだ初めて会ったような気がしていて、そのときはまだ1年生の終わりだか2年生の始まりだったのに、もう4年生になっていて、サークルの部室の管理とか、そういうのやってるのかな、などと、後輩の年齢や学年は本当に分からない。
後輩たちは後輩というクラスのメンバーであって、そのクラスには下位クラスは特にないのです。
といった経緯で、0.5時間弱を掛けて「なんとなく今度国立行った時に遊んでもらおー」とか考えながら、なんとなくコードを書いた。特に面白いことはしてません。
#!/usr/bin/env python # -*- coding: utf-8 -*- import tweepy import gdata.calendar.service import gdata.service import atom.service import gdata.calendar import getopt, sys, string, time, atom # Googleカレンダーにログイン calendar_service = gdata.calendar.service.CalendarService() calendar_service.email = 'あなたのGmailアドレス' calendar_service.password = 'あなたのパスワード' calendar_service.source = 'Twitter2Calendar' calendar_service.ProgrammaticLogin() # *******は、hogehoge@gmail.comの場合、hogehoge%40gmail.com(初期設定) feedURI = 'http://www.google.com/calendar/feeds/********/private/full' # dev.twitter.comからアプリケーションを登録して取得 consumer_token = "" consumer_secret = "" access_token = "" access_token_secret = "" # TwitterにOAuth認証 auth = tweepy.OAuthHandler(consumer_token, consumer_secret) auth.set_access_token(access_token, access_token_secret) oauth_api = tweepy.API(auth) # Googleカレンダーにイベントを作成する def creatEvent(title, start, end): event = gdata.calendar.CalendarEventEntry() event.title = atom.Title(text = title) event.when.append(gdata.calendar.When(start_time = start, end_time = end)) new_event = calendar_service.InsertEvent(event, feedURI) # Twitterのメンションを20件取得し、 # 「@hoge 09-18T15:00,09-18T18:00,カフェに行く」という形式のものを # パースして、Googleカレンダーにイベントを作成する。 # (*正規表現使って精度を上げたいけど、眠いからまた今度やる。) def parseTweetandCreateEvent(): mentions = oauth_api.mentions() for mention in mentions: len_screen_name = len(mention.in_reply_to_screen_name) + 2 calData = mention.text[len_screen_name:].split(",") if len(calData) == 3: try: start = u'2012-' + calData[0] + u':00.000+09:00' end = u'2012-' + calData[1] + u':00.000+09:00' title = calData[2] creatEvent(title, start, end) except: pass if __name__ == '__main__': parseTweetandCreateEvent()
※これをcronとかに設定して、自動実行させるためにはFLOWERSのカレーとハチティーが必要です。
あるツイートをRTしたひとがその次になにをつぶやいたか?
公式RTが普及してから、非公式RTでコメントする代わりに、公式RTした次のツイートでコメントするのをよく見かけるようになりました。
しかし、それがどのようなものかを発信者は知ることができません。
一回、最大101回のAPIリクエストを消費する頭の悪いコードですが、もっとスマートなやり方ないんかなぁ。
Webアプリ化したいけど、サーバ代払えなくて先日レンタルサーバが消えたばかりなので、ちょっと無理…orz
だれか、Webアプリにしてくれないかなぁ…。
#!/usr/bin/env python # -*- coding:utf-8 -*- import tweepy consumer_token = "" consumer_secret = "" access_token = "" access_token_secret = "" auth = tweepy.OAuthHandler(consumer_token, consumer_secret) auth.set_access_token(access_token, access_token_secret) oauth_api = tweepy.API(auth) def rt_users_ids(tweet_id): users_ids = [] try: retweeted_by_ids = oauth_api.retweeted_by_ids(id=tweet_id, count=100) users_ids += retweeted_by_ids except tweepy.error.TweepError: try: limit = oauth_api.rate_limit_status() print 'remaining hits is ' + str(limit['remaining_hits']) + ' of ' + str(limit['hourly_limit']) except tweepy.error.TweepError: print 'Error. Try again one more hour later.' return users_ids status_id = raw_input("ツイートのステータスIDを入力してください > ") rt_users_ids = rt_users_ids(int(status_id)) print str(len(rt_users_ids)) + u"件のRTしたユーザーのIDを取得しました。" num_get_tweet = raw_input(str(len(rt_users_ids)) + "件のうち、なん件のツイートを取得しますか? > ") for rt_user_id in rt_users_ids[:int(num_get_tweet)]: tweets = oauth_api.user_timeline(user_id=rt_user_id, count=200, include_rts=True) rts = [tweet for tweet in tweets if hasattr(tweet, 'retweeted_status')] rt_tweet_id = -1 for rt in rts: if rt.retweeted_status.id == int(status_id): rt_tweet_id = rt.id status_ids = [tweet.id for tweet in tweets] if rt_tweet_id != -1: index = status_ids.index(rt_tweet_id) - 1 while hasattr(tweets[index], "retweeted_status"): index -= 1 if index < 0: print u"%s\t該当するツイートはありません。" % tweets[0].user.screen_name else: print u"%s\t%s\n" % (tweets[index].user.screen_name, tweets[index].text) else: print u"%s\t該当するツイートはありません。" % tweets[0].user.screen_name
cites:ベイトソン『精神の生態学』、『精神と自然』
- 作者: グレゴリーベイトソン,Gregory Bateson,佐藤良明
- 出版社/メーカー: 新思索社
- 発売日: 2000/02
- メディア: 単行本
- 購入: 1人 クリック: 122回
- この商品を含むブログ (63件) を見る
「『ハート(情)には、リーゾン(理性)が感取しえない独自のリーゾン(理)がある。』フランス人、パスカルの言葉だ。」(G.ベイトソン)
「交わされるメッセージに先行して関係があるのではない。メッセージが相互に組み上がり結びあっていく、そのコンビネーション・パターンを、言語的コードによって記述したものが、たとえば『愛』であるわけである。」(G.ベイトソン)
「芸術とは、心の無意識を伝え合う術であるといえる。あるいは、そんな種類のコミュニケーションをもっと豊かに実践できるよう、心を鍛えてゆくための遊技だともいえる。」(G.ベイトソン)
「(適応のための)試行錯誤には必ず錯誤が伴う。錯誤は、生存を脅かし、精神の安定をも脅かす。そのマイナスを最小限に食い止めるには、適応が常にヒエラルキー構造を持っていることが必要になる。」(G.ベイトソン)習慣、学習は試行錯誤の回数を減らす。「前提を分析にかけない習慣」
「注目すべきことは、習慣の前提とすることが、抽象的な事柄だという点だ。…習慣でうまく処理できるのは、一般的に、あるいは反復的に、真である命題に限られる…人間関係を記述し決定する(このような)命題の数々が習慣として心の着床し、それによって…種々の症候群が生まれる」(G.ベイトソン)
外界に正対する一かたまりの主体性――《場》の変化によって変わらない安定したパターン――を《わたし》と呼ぶとすると、時の地殻の大変動のなかで、その《わたし》が希薄化し、消散しつつあるように思える。―佐藤良明『ラバーソウルの弾みかた』>>しっかしベイトソンは面白い。
ベイトソンは「ダブルバインド、1969」(イルカの実験)のなかで複数のコンテクストの衝突による主体の混乱をスキゾな苦痛に陥るものとする一方で、それを乗り越えた主体が創造性を獲得することを述べた。
[イルカショーでのオペラント条件付けの物語]「1)他の動物との重要な関係性を律する規則を誤解するような状況に追いやられた動物は、激しい苦痛感と不適応症状を呈する…2)そうした病変への落ち込みをすり抜けた、あるいはそれに耐え抜いた動物にあっては、創造性が促進される」(Gベイトソン)
「複数のコンテクストを股にかける才能によって豊かな人生を送る人たちがいる一方で、複数のコンテクストの衝突による混乱から生きる力を失ってしまう人たちがいる。その両者に共通しているのは、世界を二重に受けとるという点だ。」(G.ベイトソン)
「愛を装う母」エピソードに心痛む。ベイトソン「精神分裂病の理論化に向けて」
時があまりにツラく流れるから、同じ事実が昔と今では違う意味を持ってしまう。近くにいたいのに遠ざけたい記憶。未だに答えが出せないのはこの種の記憶による苦しみ。どうしたらいいのだろう。「トランスコンテクスチュアルシンドローム」(ベイトソン)
今日存在するものは記憶と呼ばれる、過去についてのメッセージであり、これらのメッセージはその時々で新しくフレームされ、変奏され続けていくのです。―G.Bateson「精神分裂症の集団力学」
ベイトソンは本能や本性などの概念に、『研究促進的概念』というカテゴリーを設けた。
「本論は、有機体の行動に見られる学習の現象を、論理学のフォーマットに合わせて分類しようというものである。動物のみならず機械も含めたコミュニケーションの世界に、階型理論のようなものが当てはまることを、本論は主張する」(G.Bateson[1971])
「学習」とはなんらかの変化を指し示す、ということから、「変化」をヒエラルキー構造で捉えたニュートン以来の物理学のアナロジーから切り込もうとするベイトソン
自我の強さとは自分がいま、どのコンテクストに置かれているか理解する能力だというベイトソンの定義は結構、現実をうまく捉えさせてくれる。
「科学は証明[prove]しない。探索[probe]するだけだ。」(ベイトソン)
趣味とは、生活に句読点を打つことだ
「趣味とは、生活に句読点を打つことだ」と以前読んだ(下掲書)。
句読点のまったくない文章も、句読点だらけの文章もともに読みづらい。文章にはリズムがある。句読点だけでない。一文の長さ、接続詞の有無、など。
手巻きタバコ STYLE BOOK: THE ZIG-ZAG BIBLE (別冊LEON)
- 作者: 主婦と生活社
- 出版社/メーカー: 主婦と生活社
- 発売日: 2011/04/30
- メディア: ムック
- クリック: 3回
- この商品を含むブログ (1件) を見る
カフェで珈琲を待つ間、保湿器で60~70%の湿度を保った葉を取り出し、フィルタを載せたペーパーで巻く。ペーパーの端は切手の裏側のように糊になっていて、そこを舐めて円柱状に留める。この動作を女性がすると色香があって好きだ。珈琲は中南米産の豆を中心にミディアムからシティにローストしたブレンドが好きだ。やはり一杯一杯ペーパーでハンドドリップされた珈琲が一番美味しい。いつものカフェのいつもの席でいつもの珈琲を待ちながらいつものバージニア葉を巻いた煙草を片手にバッグから本とノート、筆記具などを取り出す。熱い珈琲は味がよくわからないので少し温度が下がってから口に付ける。珈琲を味わうときは、舌の色々な部位を転がすようにして舌上の各味の感受部位とその組み合わせの刺激を楽しむ。
一口目がなにより重要だ。
その日のハンドドリップの癖、豆の状態、そして、自分の健康状態を知ることができる。これらが揃って初めて美味しいと感じる。思わず「美味しい」と声が漏れる。カウンター越しに店員さんの笑顔が返ってくる。そして、ジジのZIPPOを点火し、バージニア葉を巻いた手巻たばこに火を灯す。煙を吸い、吐き出す。続いて、深呼吸。灰皿に灰を落とす。珈琲を一口含み、飲み込む。やがて煙草の先端を灰皿の上で転がし、汚く潰れないように火を消す。そして、本を手に取る。昨日まで読んだページを開き、新しく読み始める箇所の右上に日付と場所を書き入れる。ブルーブラックのペンからオレンジの蛍光ペンに持ち替えて、本に向かう。
・・・以上が、僕が一日の勉強を始めるまでの手順だ。もはや儀式と言っていいかもしれない。この一連の儀式の中で、モードを切り替える。スイッチをオンにする。そして一日が始まる。
問題はスイッチをオフにするときだ。今日はうまくスイッチがオフにできない。だからこの文章を書いている。家に帰り、シャワーを浴び、ストレッチをして、セレッシャルのブレンド・ハーブティー「スリーピー・タイム」を淹れる。この前後で煙草を吸うときもある。一本の煙草を巻き、吸うことは、生活の句読点を打つことだからだ。
- 出版社/メーカー: 西本貿易
- メディア: 食品&飲料
- クリック: 1回
- この商品を含むブログを見る
スイッチをオフにできないとそもそも寝ることができない。オフにする儀式が必要かもしれない。そうでないと、たとえ眠れたとしても夢のなかでも現実の様々な刻限に追われてしまう。
今日は気の置けない友人たちとひたすら喋った。昔の話、中身の無い話、取り留めもない話・・・。会話自体に意味はない。これらのコミュニケーションにはスイッチをオフにするという意味以外必要とされていない。
Sennheiser カナル型ヘッドフォン CX 400-II BLACK
- 出版社/メーカー: Sennheiser
- メディア: エレクトロニクス
- 購入: 8人 クリック: 80回
- この商品を含むブログ (5件) を見る
切りとれ、あの祈る手を---〈本〉と〈革命〉をめぐる五つの夜話
- 作者: 佐々木中
- 出版社/メーカー: 河出書房新社
- 発売日: 2010/10/21
- メディア: 単行本
- 購入: 30人 クリック: 710回
- この商品を含むブログ (130件) を見る
「えたいの知れない不吉な塊が私の心を始終 圧 ( おさ ) えつけていた。 焦躁 ( しょうそう ) と言おうか、嫌悪と言おうか――酒を飲んだあとに 宿酔 ( ふつかよい ) があるように、酒を毎日飲んでいると宿酔に相当した時期がやって来る。」(梶井基次郎『檸檬』)
- 作者: 梶井基次郎
- 出版社/メーカー: 新潮社
- 発売日: 2003/10
- メディア: 文庫
- 購入: 6人 クリック: 113回
- この商品を含むブログ (176件) を見る
「R二乗値なんて信仰にすぎない!」について(F統計量のお話)
「R二乗値なんて神話・信仰の類ですよ!」と先生が仰るものだから、われわれは啓蒙されなければならない、と思い、ちょっと覚書を残しておこうと思います。
本当は、重回帰モデルの診断の話まで書きたかったのですが、それはまた後日…。
(修正済み)R二乗値だけを見て「こんな小さいR二乗値じゃ、駄目だよ」と言う人はたくさんいるらしい。
しかし、そうではない、R二乗値がいくつであれば回帰モデルは妥当か?を、F統計量から判断する、という話です。
これは、R二乗値をF統計量に変換し、それが有意か調べるという方法をとります。
使用するソフトはRです。
F統計量は定数項以外の係数が全て0という帰無仮説のもとで分子の自由度がn-1、分母の自由度がn-KのF分布に従う。
nがKに対して大きいとき、F分布の期待値はほぼ1。
今回、この重回帰モデルを例にみてみます。
修正済みR二乗値が0.335です。なんか小さい気がする…大丈夫かな…という不安がよぎります。
まだ啓蒙されてないぼくには、この値は心を不安にさせます。
サンプル数と説明変数の数(定数項含む)を指定
> n=275 > K=4
まずは、このn, KのもとでのF分布を描画する。
> x=seq(0, 10, by=0.01) > y=df(x,K-1,n-K) > plot(x,y,type="l")
次に、95%点を計算します。
> qf(0.95,K-1,n-K) [1] 2.637913
そしてそれを描画。
> abline(v=F95, col="red")
帰無仮説のもとではこの分布にF統計量が従うわけです。
ということは、この赤線の右側にF統計量があれば「やった!」となる。
それで、その「やった!」となるF統計量に対応するR二乗値はいくつか、計算します。
> F95=qf(0.95,3,271) > F95/(F95+(n-K)/(K-1)) [1] 0.02837343 >
なんとまぁ、R二乗値が0.028より大きければ回帰モデルには意味がある!ということになりました。わぁ♪
というわけでこれで、「修正済みR二乗値が0.335?そんなモデルじゃあダメだ」などとドヤ顔で言われても、
「あなたのその顔をエンライトメントしてやんよ」と切り返すことができるようになりました◎
mecab-pythonをMac OSX 10.7 Lion、Python2.7にインストールする
- 作者: Steven Bird,Ewan Klein,Edward Loper,萩原正人,中山敬広,水野貴明
- 出版社/メーカー: オライリージャパン
- 発売日: 2010/11/11
- メディア: 大型本
- 購入: 20人 クリック: 639回
- この商品を含むブログ (44件) を見る
時系列で載せます。
まず、Homebrewでmecabと辞書をインストールした(後にアンインストールした)。
mecab-python-0.991 r_onodr$ ARCHFLAGS='-arch i386 -arch x86_64' python setup.py build lipo: can't figure out the architecture type of: /var/folders/mq/pxbw7qg97994xjhnhf444dr00000gn/T//ccAJndUU.out error: command 'gcc-4.2' failed with exit status 1
エラー。なんか、gcc-4.2ってヤツが真面目に働く気がないようだ。
代わりを探す。
mecab-python-0.991 r_onodr$ which gcc /usr/bin/gcc
gccさんにがんばってもらう。
mecab-python-0.991 r_onodr$ CC=/usr/bin/gcc python setup.py build ... ld: warning: ignoring file /usr/local/Cellar/mecab/0.99/lib/libmecab.dylib, file was built for unsupported file format which is not the architecture being linked (i386)
「お!」と思ったけどまたエラー。
「i386?32bit??」って思って、色々試す(要らなかったかも…)。
mecab-python-0.991 r_onodr$ CC=/usr/bin/gcc ARCHFLAGS='-arch i386' python setup.py build mecab-python-0.991 r_onodr$ CC=/usr/bin/gcc CFLAGS='-m32' python setup.py build ... ld: warning: ignoring file /usr/local/Cellar/mecab/0.99/lib/libmecab.dylib, file was built for unsupported file format which is not the architecture being linked (i386)
結局同じエラー。
どうやら、Homebrewでインストールしたmecab本体が32bitなのが悪いっぽい。
というわけで、アンインストール。
~ r_onodr$ brew uninstall mecab ~ r_onodr$ brew uninstall mecab-ipadic
そして、mecabと辞書をダウンロードしてきて64bitでインストール!
mecab-0.993 r_onodr$ CC="gcc -m64" CXX="g++ -m64" ./configure --with-charset=utf8 mecab-0.993 r_onodr$ make mecab-0.993 r_onodr$ sudo make install mecab-ipadic-2.7.0-20070801 r_onodr$ CC="gcc -m64" CXX="g++ -m64" ./configure --with-charset=utf8 mecab-ipadic-2.7.0-20070801 r_onodr$ make mecab-ipadic-2.7.0-20070801 r_onodr$ make install mecab-python-0.991 r_onodr$ python setup.py build mecab-python-0.991 r_onodr$ python setup.py install
通った!!
テスト
~ r_onodr$ python Python 2.7.2 (v2.7.2:8527427914a2, Jun 11 2011, 15:22:34) [GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> import MeCab >>> m = MeCab.Tagger("-Ochasen") >>> str = "八頭身モナーはキモい" >>> dst = m.parse(str) >>> n = m.parseToNode(str) >>> print dst 八頭身 ハットウシン 八頭身 名詞-一般 モナー モナー モナー 名詞-一般 は ハ は 助詞-係助詞 キモ キモ キモ 名詞-固有名詞-一般 い イ い 名詞-一般 EOS >>> while n: ... print n.surface + " " + n.feature.split(",")[0] ... n = n.next ... BOS/EOS 八頭身 名詞 モナー 名詞 は 助詞 キモ 名詞 い 名詞 BOS/EOS >>>
わーい♪
【参考になったページ】
MeCab のインストール | 自宅サーバー Fedora http://honana.com/mysql/tritonn/mecab.html
OS X Lion, make/configure issue, trying to compile 64-bit libFLAC/libFLAC++ - Ars Technica OpenForum http://arstechnica.com/civis/viewtopic.php?f=20&t=1164408
Rob Hess氏によるSIFTの実装をOSX SnowLeopardにインストール. | GO HOME http://kzm42.blog24.fc2.com/blog-entry-31.html
éternuement: Snow Leopardで32bitビルドの仕方 http://eternuement.blogspot.com/2011/02/snow-leopard32bit.html
Work-around for Mac OS X python package install error ― "lipo: can’t figure out the architecture type" | post past :: james murty http://www.jamesmurty.com/2011/01/29/work-around-osx-lipo-figure-out-architecture-type/
python - Why is GCC ignoring ARCHFLAGS in Snow Leopard? - Stack Overflow http://stackoverflow.com/questions/6988528/why-is-gcc-ignoring-archflags-in-snow-leopard
入門 ソーシャルデータ ―データマイニング、分析、可視化のテクニック
- 作者: Matthew A. Russell,奥野陽(監訳),佐藤敏紀(監訳),瀬戸口光宏(監訳),原川浩一(監訳),水野貴明(監訳),長尾高弘
- 出版社/メーカー: オライリージャパン
- 発売日: 2011/11/26
- メディア: 大型本
- 購入: 18人 クリック: 779回
- この商品を含むブログ (42件) を見る