不可視点

search guy at cookpad.com

MeCabの辞書にはてなキーワードを追加しよう

MeCab形態素解析のためのソフトウェアです。日本語を分かち書きするために使われるものとしては最も人気の高いものだと思われますが、チャットや掲示板に書き込まれるような崩した日本語や、正しく書かれた日本語でも新語を期待した通りに分かち書きしてくれないことがあります。これはMeCabの内部で使われている辞書が一般的な言葉を情報源としているわけではないことに関係があります。MeCabというか、より一般的な話ですが以下のような認識が一般的かと思われます。

というのも、一番広く使われているであろう自然言語処理技術は形態素解析(単語分かち書き、と言ったほうがいいのかもしれない)であろうが、これは現在99%くらいの精度になっていて、すでに人間がやるより遙かに高精度で行えるのだが、これだけ高い精度が出せるのは新聞記事を相手にしたときだけであって、それは新聞記事をコーパスとして用いる機械学習により形態素解析器を作っているので仕方ない面はあるが、医療分野や特許分野のように専門分野になったりウェブ文書を相手にしたりすると、一気に精度が落ち込むのは広く知られた事実である。大規模なコーパスがある状況で、実際に適用したい分野がそのコーパスと違う状況でも精度を落とさず解析できるようにしましょう、というのは自然言語処理の言葉では分野適応というのだが、これもここ数年研究が始まったばかりで、機械翻訳の現状を見ると「こうすれば万事解決」というようなものではない。(もっとも、ある分野を解析したいとして、数千語辞書を作れば精度95%くらいには上がるそうなので、現実的には地道に辞書を作ればいい、という話でもある)

Wolfram|alpha や Bing のすごくないがゆえにすごいところ - 生駒日記

じゃあ辞書ってどこにあんの

現在MeCabではnaist-jdicという辞書が推奨されています。5月の下旬に最新版が更新されています。

しかし、前述の通りこれだけでは最新の単語に対応することは出来ません。そこで辞書として新語やネット上で一般的な言葉でMeCabに入っていないような語はどこにあるんだと考えたところ、エリートスパム集団はてなのはてなキーワードwikipediaの項目名が浮かびました。Googleで単語検索したとき誰もが目にする情報源ですから関心を持って項目を更新している方が多いと思われ、今後もしばらく有用であると考えられます。
両方とも公式に最新のダンプが公開されています。入手方法は以下を参照してください。

単語数:24万(2009年5月)

page_namespace=0の項目数:85万(2008年12月)
かなり性質の違うものなので項目数以上のことは特に調べていません。注意点としては両方とも日付など単語として不適な項目が含まれていることです。目的に応じて中身をチェックしておくことが必要です。
今回ははてなキーワードを追加してみます。

MeCabのインストール

以下はCentOS5,MacOSXで使うためのメモです。*1(19:58追記)
依存ライブラリ等が入っていない場合は下記のコマンドの前に公式のインストールガイドを参照してインストールしてください。

MeCab

wget http://nchc.dl.sourceforge.net/sourceforge/mecab/mecab-0.98pre3.tar.gz
tar xzvf mecab-0.98pre3.tar.gz
cd mecab-0.98pre3
./configure && make
sudo make install

naist-jdic

MeCabだけではまだ利用できません。MeCabが利用する辞書をインストールしましょう。naist-jdicを使います。

wget http://iij.dl.sourceforge.jp/naist-jdic/40117/mecab-naist-jdic-0.6.0-20090616pre3.tar.gz
tar xzvf mecab-naist-jdic-0.6.0-20090616pre3.tar.gz
cd mecab-naist-jdic-0.6.0-20090616pre3
./configure --with-charset=utf8
make
sudo make install

デフォルトだと辞書が/usr/local/lib_mecab/dic/naist-jdicに作成されます。

sudo vi /usr/local/etc/mecabrc

にて利用する辞書を選択できるので作成したnaist-jdicを利用するように変更します。

dicdir = /usr/local/lib/mecab/dic/ipadic
を以下のように変更
dicdir = /usr/local/lib/mecab/dic/naist-jdic

テスト

これでMeCabが使えるようになりました。プロンプトで以下のようにして動作を確認してください。

echo ずっと日曜日ならいいのに | mecab
ずっと日曜日ならいいのに
ずっと 副詞,一般,*,*,*,*,ずっと,ズット,ズット
日曜日 名詞,副詞可能,*,*,*,*,日曜日,ニチヨウビ,ニチヨービ
なら 助動詞,*,*,*,特殊・ダ,仮定形,だ,ナラ,ナラ
いい 形容詞,自立,*,*,形容詞・イイ,基本形,いい,イイ,イイ
のに 助詞,接続助詞,*,*,*,*,のに,ノニ,ノニ
EOS

辞書の更新

MeCabはユーザーが辞書を更新することが出来ます。MeCab: 単語の追加方法を参考にはてなキーワードを追加します。
mecab-naist-jdic-0.6.0-20090616pre3/で作業します。はてなキーワードをダウンロードして辞書に追加します。

wget http://d.hatena.ne.jp/images/keyword/keywordlist_furigana.csv -O hatena.txt
nkf -Ew hatena.txt | python createDict.py | nkf -e > hatenakeyword.csv

辞書の構築では辞書候補として.csvが自動選択されるため、はてなキーワードはhatena.txtにリネームして保存していることに注意してください。
createDict.pyってなんだよ。って話なんですが、はてなキーワードcsvMeCabの辞書csvのフォーマットが異なるため、整形するためのフィルタです。
僕は文字コードが非常に苦手ですのでファイル整形にPythonを使いましたがPythonの中はUTF8でやりたかったのでまぬけなnkfが付いてます。
vi createDict.pyなどして以下のようなスクリプトを配置した上で、上記のコマンドを実行してください。

# -*- encoding: utf-8 -*-
import sys
import re

#数字四桁が入ったキーワードは役に立ちませんので検出して飛ばします。
year = re.compile("[0-9]{4}")

#驚くべきことにはてなキーワードには%00というキーワードがありますが、
#これがcsvとして提供されているダンプではヌル文字になっているのでシステム制御文字を非許可にします。
ng = [chr(i) for i in range(0,32)] 

def main():        
        for x in sys.stdin:
                if re.search(year,x):
                        continue #日付スキップ
                k = x.split("\t")[1].strip()
                if len(k) < 2:
                        continue #一文字スキップ
                for word in ng:
                        if word in k:
                                continue #システム制御文字スキップ
                k = k.lower() #MeCabはケースセンシティブなので小文字に統一して辞書作成
                cost = int(max(-36000, -400 * len(k)**1.5)) #コストについては後述
                print "%s,0,0,%s,名詞,一般,*,*,*,*,%s,*,*,はてなキーワード," % (k,cost,k) #0については後述
if __name__ == '__main__':
  main()

若干複雑になってきましたが、以下のような物が作成されていればokです。

grep "google wave" hatenakeyword.csv | nkf -Ew
google wave,0,0,-14593,名詞,一般,*,*,*,*,google wave,*,*,はてなキーワード,

ここまで確認できたら辞書を再構築してインストールし直しましょう。

make clean && make
sudo make install

辞書が再構築され、はてなキーワードMeCabでも切り出せるようになったことを確認してください。

echo ニコニコ動画車載動画は楽しいですが東のエデンの方が面白い。 | mecab
ニコニコ動画 名詞,一般,*,*,*,*,ニコニコ動画,*,*,はてなキーワード,
の 助詞,連体化,*,*,*,*,の,ノ,ノ,,
車載動画 名詞,一般,*,*,*,*,車載動画,*,*,はてなキーワード,
は 助詞,係助詞,*,*,*,*,は,ハ,ワ,,
楽しい 名詞,一般,*,*,*,*,楽しい,*,*,はてなキーワード,
です 助動詞,*,*,*,特殊・デス,基本形,です,デス,デス,,
が 助詞,接続助詞,*,*,*,*,が,ガ,ガ,,
東のエデン 名詞,一般,*,*,*,*,東のエデン,*,*,はてなキーワード,
の 助詞,連体化,*,*,*,*,の,ノ,ノ,,
方 名詞,非自立,一般,*,*,*,方,ホウ,ホー,,
が 助詞,格助詞,一般,*,*,*,が,ガ,ガ,,
面白い 形容詞,自立,*,*,形容詞・アウオ段,基本形,面白い,オモシロイ,オモシロイ,おもしろい/面白い,
。 記号,句点,*,*,*,*,。,。,。,,
EOS

単語に設定するコストと文脈IDをどう決めるか

話が前後して申し訳ないのですが、前述のcreateDict.pyの中で

                cost = int(max(-36000, -400 * len(k)**1.5)) #コストについては後述
                print "%s,0,0,%s,名詞,一般,*,*,*,*,%s,*,*,はてなキーワード," % (k,cost,k) #0については後述

としていた箇所について説明します。MeCab: 単語の追加方法によれば、

コストは,その単語がどれだけ出現しやすいかを示しています. 小さいほど, 出現しやすいという意味になります. 似たような単語と 同じスコアを割り振り, その単位で切り出せない場合は, 徐々に小さくしていけばいいと思います.

とのことなので文字列の長さに応じてコストを設定しています。gooとgoogleが同じコストで登録されるとgoogleと書いてもgooで切り出されたります。それは期待した動作ではないのでMeCab の辞書構造と汎用テキスト変換ツールとしての利用のケーススタディを参考にコストを設定しています。
これらの数値の設定によって挙動は変わるので、期待した動作にならない場合は調節してみましょう。その際にはmecabの-Nオプションを使ってどのような候補のなかで結果が選ばれたのか参照しながら進めると若干楽かもしれません。以下は上記のコスト関数で実行した例です。すべてのキーワードのコストを同じにしてはいけないことがなんとなく分かります。

#gooとgoogleについて
echo google | mecab -N2
google 名詞,一般,*,*,*,*,google,*,*,はてなキーワード,
EOS
goo 名詞,一般,*,*,*,*,goo,*,*,はてなキーワード,
gl 名詞,一般,*,*,*,*,gl,*,*,はてなキーワード,
e 記号,アルファベット,*,*,*,*,e,イー,イー,,
EOS

#もう一例
echo ニコニコ動 | mecab -N2
ニコニコ 名詞,一般,*,*,*,*,ニコニコ,*,*,はてなキーワード,
動 名詞,一般,*,*,*,*,動,ドウ,ドー,,
EOS
ニコ 名詞,一般,*,*,*,*,*
ニコ動 名詞,一般,*,*,*,*,ニコ動,*,*,はてなキーワード,
EOS

文脈ID
                print "%s,0,0,%s,名詞,一般,*,*,*,*,%s,*,*,はてなキーワード," % (k,cost,k) #0については後述

次に文脈ID(0,0,とか指定されていた部分)ですが、これは正直に言うとどのような数値を設定するのが妥当なのかわかりません。ただし、-1によって自動判定してくれる機能がバグっていて利用できないので1345とか0とか名詞,一般の他の単語にどのような数値が設定されているかを参考に設定するのがよいかもしれません。何かご存知の方は教えてくださると助かります。

*1:Xcodeを入れたMacOSX 10.5.7でも手順通りに進むことを確認しましたがnkfがデフォルトでは入っていないのでsudo port install nkfしてください。 [http://blog.livedoor.jp/dankogai/archives/51218958.html:title=404 Blog Not Found:tips - Mac OS X - には iconv も piconv も入っている]といった指摘を頂きました。加えて、wgetはデフォルトでは無かったのでcurlを利用するとよいでしょう。

twitter検索のクロール方法について

twitter検索はpublic_timelineをスクレイピングする方法でポストを収集していました。
これはうまくいっていたのですが3月のはじめにAPIによるアクセスに続いて通常ページもキャッシュされるようになり、ポストの取得がとびとびになってしまいました。影響はかなり出てしまい、回収率は1/10程度に落ち込んでしまいました。

代替策

TwitterはData mining feedという600ほどのポストを一度でもらえるAPIを提供していてポストを多く集めたい人はそれを使うようにというアナウンスをしています。しかしこれもキャッシュが効いているようですからそれほど改善しないのではないかと思い試していません。
また、既に事実上日本語のみを検索対象にするサービスになっているので日本語ユーザーのポストだけもらえればいいかと思い、日本語ユーザー(7万人前後)をRSSで取得する方法を考えましたが、APIホワイトリストに入ることが必須となります。申請は認められたのですがなぜかAPI呼び出し回数の上限が更新されず、問い合わせても返答がありませんでした。そこでsearch.twitter.comを代用して実験してみました。回収率はおおむね良好でしたがsearch.twitter.comは数値は明記されていませんが一定時間に何度もアクセスするとデータを取得させてもらえなくなります。
Twitter向けの検索サービスはリアルタイム性が高いことが一つの特徴ですから、なるべく速く日本語ユーザー全員を巡回することを目指したいので、この方法でsearch.twitter.comに合わせてのんびりデータを取得するのは無理があるかなと思い本番投入はしていません。
巡回先の数を7万人と書きましたが、直近では、public_timelineを用いる方法がうまくいっていた2月中を含む、2009の2月〜3月中旬における日本語ユニークユーザー数は5.3万人だったのでもう少し少なくはなりそうです。search.twitter.comの上限は1IPあたり、1秒に一回だと少し多すぎるようでした。

Gnip

そこで違う方法をさがしていました。今はGnipというサービスを使う方法が有望であると考えています。

TwitterTwitter searchはGnipにpublisherとして参加しています。そこでGnipから提供されるポストの一覧とスクレイピングでほぼリアルタイムに近い水準でもれなく回収できることが期待できます。
実際に試してみたのですがあまり芳しくない状況です。

Gnipにおいてtwitterの情報が1時間程度遅れてくる問題は知られています。ところがよく見てみると遅れてくるだけではなく、遅延がある上限を超えると1時間分のデータを飛ばして再開しているように見えます。この現象は定期的に起こります。
私はGnipの1分前のデータを1分おきに取得しています。

(認証が必要)https://api-v21.gnip.com/gnip/publishers/twitter/notification/200903291058.xml

SELECT id as twitter_status_id,time as tweet_time, gnip as gnip_time, (gnip-time) as gap_in_sec 
FROM test_2009b 
ORDER BY test_2009b.time desc, gnip desc
LIMIT 30;

スクリーンショット(GMT+9:00):

このため、twitter検索でこの方法を使う場合、現状では最低でも20分程度経過しないとポストが検索可能になりません。(最大で70分程度)
さらに1時間分きっちり抜ける瞬間が一日に何度もあります。また、10分程度にわたってポストが追加されないこともあります。

このような問題を考慮しても24時間で28日(土)20時〜29日(日)20時までの14.3万の書き込みを拾えますので現状より断然網羅率が高まります。

その他の方法と組み合わせることで回収率をあげることは可能ですが、いきなり古いポストが結果に現れたりといった現象が想定されます。短い時間の間に同じクエリに対して違う結果を返すことになってしまうでしょう。
多くの利用方法においてこれは大きな問題とはならないと考えますが、定期的に機械的にアクセスするAPIでの利用では問題となる場合もありえると思いますので当面はGnipのみを利用する方法で様子をみてみようと考えています。

APIを利用されている方はどのような解決方法が望ましいかアイデアがありましたらお知らせください。
またはTwitterからデータを引っ張る方法についてご存知の方はお聞かせください。

PFI手法による刑務所が運営開始

PFI手法による官民共同の新たな刑務所の整備についてのメモ:

PFI手法:Private Finance Initiative

公共施設の建設、維持管理、運営等を民間の資金、経営能力及び技術的能力を活用して行う手法。

事業主体は民間でもその執行にかかる最終責任はあくまで行政。事業自体を民間に売却して行政から切り離す「民営化」や行政と民間の共同出資により運営される第3セクターとは性格が異なる。

他国のPFI刑務所について

英米系の諸国:全ての業務を民間が執行できる。民営刑務所
大陸系の諸国:保安業務、サービス業務による混合運営施設(日本はこちら

日本初のPFI手法による刑務所

山口県 美祢社会復帰促進センター社会復帰サポート美祢)ネーミングも受け入れ地域との親和性を高める。
土地は国が買い上げ運営会社に無償提供し、約517億円によって18年間運用したのち、国に無償返却される。
セコムや清水建設などが中心となる社会復帰サポート美祢株式会社は、美祢社会復帰促進センター整備・運営事業を落札した「美祢セコムグループ」が設立した特定目的会社

最初に収監されるのは"特A級"とよばれる犯罪傾向の進んでいない初犯の囚人を全国6万人より男女500人ずつ選抜。
運営の継続性や安定性を確保するため例えば逃走事故などがあると最大となる毎年度の事業費の3%のペナルティが課される。
平成14年名古屋刑務所事件→行刑の現場の透明性の確保も期待される。

受け入れ地域

刑事施設内の診療設備を地元に解放する。施設の来訪者とは別の入り口から利用できる。

設備

動線をなるべく短く。パノプティコンのような監視部は1〜3階を貫く独自の階段を持つ。
ICタグを携帯させ静脈による生態認証によって施設を管理しなるべく行動を制限しない。鉄格子の代わりに強化ガラス。赤外線センサー、振動センサー、カメラによる監視。
ICタグにより2秒ごとに屋内外を問わず1〜3mの誤差で囚人の位置を捕捉する。
http://www.chugoku-np.co.jp/News/Tn20070403005901.jpg
http://www.chugoku-np.co.jp/News/Tn200704030059.html

刑務作業

  • ソフトウェアプログラミング
  • 地図情報入力
  • ブルーベリーの温室栽培
  • 古着のリメイク
  • パソコン技能、就労に必要な基礎知識を必須とする。

介護技能、フラワーアレンジメントなどもある。
図書の点訳や読み上げよう音声コード入力など社会貢献として意義のある内容の作業。点字成果物は地元に提供される。

今後

この後1年半で島根あさひ社会復帰促進センターを2号とし日本全体の8%にあたる6000人をPFI手法の刑務所が引き受ける。
先進国に並ぶ水準。美祢社会復帰促進センターは19年度より29億円が国から支出される。
人材の育成が非常に大変だと思う。セコムはこの事業を社会的責任(CSR)の一環とコメントしている。
一般的な警備のノウハウだけでは足りないだろうし、パイロット事業なのでこの4月から運営されるこの刑務所に注目が集まる。はず。

参考

http://b.hatena.ne.jp/code46/pfi/

via ジュリストNo.1333 2007.4.15
ジュリストにはより詳しい内容と有効な批判や分析、証言が掲載されています。

Amazon NOIR

Amazonになか見!検索という機能がある。対象書籍の全文検索が可能で、うまく使えば非常に便利な機能。しかし、この検索にクエリーを出し、そこから得られた結果ピースをクエリーに反映させることで全文を取得し、検索結果を統合すると書籍が再構築できてしまう。

まず、これを思いつくのがえらいというかいいところなんだけど、実際にやってはいけないのではないか。3000冊の再構築に成功したとしており、

ダヴィンチ・コードとか911の報告書など。比較的問題になりにくそうな7つのPDF。 AMAZON NOIRは実際にプレスリリースを発し、3000冊のダウンロードをアナウンスし、数ヵ月後、司法とアマゾンに屈し敗北宣言を出したそうだ。 壮大な釣り。

参考:
http://b.hatena.ne.jp/code46/amazonnoir/
via http://architectradure.blogspot.com/2007/04/more-bad-guys.html

ICCはAMAZON NOIRやhttp://gwei.org/などのプロジェクトを遅かれ早かれきちんと拾って紹介してくれる。