Hatena::ブログ(Diary)

アスペ日記

2011-07-30

雑感3

この数日間は、イベント等があって趣味のプログラミングはしていない。


前々回前回ネガティブな日記を書いた。考えを論文にして、アルゴリズムに関するものであっても実験で性能を出して国際学会で採択されるなどしないと、アルゴリズムの内容も読んでもらえないということにちょっと不満があったから。


普通に考えると、しょうがないといえばしょうがない。人間はこんなに多いのに、誰かが「いいアイディア思いついたよ」と言っても、そんなのいちいち読んでいられない。こういう状況では、性能の出る応用に結び付いたアイディアだけをみんなが読むというのが効率的なんだろう。今のシステムよりいいものも特に考えつかない。


それにしても、学術界の業績駆動システムには疑問を感じないでもない。学術界の中ではそれで回っていくのかもしれないが、在野の者がちょっといいアイディアを思いついたと思っても、学術界の外では「業績」というのはそんなに価値のあるものではないので、英語で論文を書くほどのモチベーションにつながらないんじゃないだろうか。


元々、学術界というのはそういうものは誤差として無視するようになっているんだろうな。良質なアイディア発生装置があって、それによってアイディア選別装置がフル稼働しているなら、低質なアイディア発生装置からの入力を受け付けないほうが理にかなっている。


まあ、それはそれとして。


N-gram かな漢字変換については、今後ゆっくり解説を書いていこう。共通接頭辞検索とかのあたりは日本語自然言語処理に共通のところだし。N-gram デコードの部分は、今回きちんとソースを整理してみたらほとんど自明動的計画法だったので、自分の知らないうちに他の人が論文の中でついでに実装していたりするかもしれないが、それでも一応書いてみる。

そもそも、N-gram デコードは自分が修士の時にやりかけていた「品詞・形態素混合 N-gram」の中で使ったアルゴリズムのシンプル版。誰か他の人が、同じように何かのついでに軽く実装していても不思議ではない。


可変次数 CRF のほうはそんなにシンプルではない。N-gram デコードに比べると何十倍もの時間をかけて考えに考え抜いて、定式化なんて自分には無理だと思ったけど、他人にもわかってもらえないと意味がないので必死に定式化して、実用的な実装なんてとてもできそうになかったけど、岡崎さんのCRFSuiteのおかげで何とか実装もできて、修士論文という形にもできた。それは修士論文・NLP2011 という流れがあったからこそできたことで、これを国際学会に出すようなエネルギーは、少なくとも今はない。


なんでそのモチベーションが出ないかというと、何よりもまず、「自分で確信が持てない」から。もちろん、自分なりの自信があるんだけど、誰かに、それを理解した上でいいとかダメとか言ってほしい。


でも、自分の論文が正しいか正しくないかは置いておいて、複雑すぎてとても手軽に読めるようなものではない。というか、ぼく自身も先行研究であるConditional Random Fields with High-Order Features for Sequence Labelingを読めていない(まったく…)。


こっちのほうは、手が空いた時にゆっくり修士論文を英訳してそれをアップロードして、誰かが読んでくれるのを期待しようかな。

2011-07-27

雑感2

今日も引き続き、ソウルジェムの穢れをまき散らすような日記を書いてみる。


なぜ論文を書きたくないか。

それは、「そりゃこれは書かないとだめだよね」と納得できる以上のことを書かないといけないからだ。


まず、先行研究。

修士のころ、論文を書いていて「先行研究の数が少ない」とよく言われた。

はぁぁ?

先行研究が、「少ない」、って?

お前は何を(ry


自分としては、その研究に関連する論文は精一杯列挙したつもり。

もちろん、それで網羅できているとは限らないので、研究内容を誰かが見て「この内容ならこの論文に言及していないのはおかしい」と言ってくれたら、それはすごくありがたい。

でも、先行研究が「少ない」ってねぇ。

量って売るの? 先行研究って。


だいたい、一つの研究に多くの先行研究があって、それらの中身を書かないといけないとしたら、その時点で何かおかしいんじゃないの。「親クラス」にあたるような先行研究についてはそれなりに書かないといけないと思うけど、そういうのが多くあるというのはおかしい。多重継承禁止、とまでは行かなくても、せいぜい 2個ぐらいじゃないのか。また、手法として利用しているというものに関しては、その論文で中身まで書く必要はないんじゃないか。何のために参考文献があるのか。


また、自分がやっていた・やっているのは一貫して「アルゴリズム=計算方法」(可変次数 CRF/N-gram の)なのだが、それについて、応用上の性能(タグ付け精度なりとか)が求められるというのも違和感がある。


例えば、かけ算の筆算を例にとる(わかりやすさのためのたとえであって、自分のしていることの有用性を主張するものではない)。かけ算の筆算を発明した人がいたとして、その人が示すべきなのは、その方法によってそれまでのやり方よりも計算が速くできるということまでなんじゃないか、ということ。アルゴリズムの研究に応用上の性能を求めるというのは、かけ算の筆算を発明した人に「筆算を使うとかけ算が速くなるのはわかったけど、それがどう役に立つか教えてよ」というようなものじゃないの。本人からしたら、「えっ、かけ算使わないの? 速くできたらうれしくないの?」ってところだろう。


昨日も書いた通り、自分では自分のしていることにずっと自信を持っている。可変長 CRF を学会に発表するまでは、「今事故に遭ったらどうしよう」という気持ちがずっとあったぐらいだ。今死んだら、研究内容が失われてしまうんじゃないかと思って。どれだけ小さいものであっても、それが新しい/役に立つことなら、それが失われるのは惜しい。


今ではその心配はしていない。国内とはいっても、第一線の人たちが参加するところで発表して、さらにソフトウェアを作って GitHub で公開して、それ用のサイトを作って、 そのリンクも論文に書いた。これで何かが失われるとしても、それは自分の責任ではないと思えるところまでは頑張ったと思う。

2011-07-26

雑感

N-gram かな漢字変換アップデート

内部の Unicode 化、未知の文字への対応。

これまでは未知の文字があると結果を返さなかったので、特に漢字かな変換では致命的だったが、今回の変更で大丈夫になったかもしれない。

まだ漢字かなでは試してないけど。


昨日、Twitter@zzzelch 先生に、学生と協力してWTIM 2011 に出してみないかというお誘いをいただいた。

期限は今日の 19:59 なので、現実的には無理だったけど、それでもそう言っていただけたのはうれしい。


こういうことは重なるものなのか、今日は会社で Variable Order Linear-Chain CRFs(可変長 CRF、修論で研究して NLP2011 でも発表した)について聞いてくれる人がいた。

誰も興味ないかと思っていたので、意外な喜び。


その時、「国際学会には出さないんですか」と言われた。

うーん。

どうなんだろう。


可変長 CRF にせよ、可変長 N-gram デコードにせよ、主観的には自分のやっていることに自信はある。

もし実際はたいしたことなかったとなったら恥をかくが、そのリスクを冒して言うと、何か新しい、役に立つことをしたつもり。

だって、高次の CRF や N-gram を、指数的に遅くならないように DP でできたらうれしいじゃん。


そう思ってはいるのだが、不安な面もある。

もしも自分のしていることが、自分が思っているぐらい役に立つことなら、どうして誰もそう言わないんだろう?

もし 2年前の自分が、高次の CRF や N-gram の DP による解き方があると聞いていたら、それだけで興奮したと思うし、それができたらうれしいと思ったからそれなりに頑張ったのだ。


しかし、実際には反応はほとんどない。

となると、役に立つことをしたと思っている自分が間違っているか、得るべき評価を得ていないかのどちらかだ。

みんな知っているように、「得るべき評価を得ていない」なんていう考えはたいてい危ない。

「いつも誰かに見張られている」とかいうのと同じぐらい危険信号だ。

だから、まあ自分のほうが間違っているんだろうということにはしているが、ちょっともやもやしている。


それなら、それをすっきりさせるためにもちゃんと研究にして発表すればいいじゃん!と言われそうだし、そういう考えもないでもない。


だが、もし自分のしていることが役に立つことだとしたら、「人の役に立つために、好きでもないこと(論文を書いたり)をする」ということに対して、心のどこかで納得ができない。


自分がしたいことをする傍ら、それを他の人にも使えるように、使いやすいようにすることを心がけるといったレベルの利他性なら自分も持っている。

でも、それ以上となるとちょっと。

英語で論文を書くなんて、ちょっとやそっとの面倒ではない。

利他性が十分じゃないのだろうか?

経験上、他の人類もそこまで利他的ではないと思うんだけど。

もちろん、世の中には素晴らしい人格を備えた人もいることは知っているし、自分もそうなれたらいいと思ってはいるが、現時点で自分はそうではないし、それをごまかしてもろくなことにはならない。


どうするのがいいんだろうなぁ。

まあ、自分のやっていることが正しい方向性のことならきっと他の人がそのうち同じことをするだろうし、もしそうじゃなかったら元々必要なかったってことだし、どちらにしても特に何もしなくても大丈夫だろう。


しかし、「もやもやする」という感覚は残るので、「面白い」とか「つまらない」とか思った人は教えてください。

どちらなのかわからないという状態が一番もやもやするので。

2011-07-23

N-gram かな漢字変換(3)

リポジトリを更新した。

N-gram ID から スコアを取得するのに cdb を使っていたのをメモリマップトファイルに変えた。

さらにスコアは 1バイトで持つようにした。

400MB ぐらいだったサイズが 20MB ぐらいになって、速度もだいぶ向上した。

合計すると、辞書のサイズは 60MB ぐらい。

まだそれなりに大きい。

4-gram のかな漢字変換用辞書をあらかじめリポジトリに入れておくようにした。

marisa-trie モジュールさえ入れてあれば、

./converter_sample.py --dicname-prefix=dics/bccwj4_rev_dic --order=4 --interactive

ですぐにかな漢字変換が実行できる。

だいぶ手軽になったはず。

作成済み辞書を置くのに問題はないかな?

まずかったら削除します。

ついでに、Google日本語入力APIでAjax IME を参考に、さくらVPS に工藤さん作成の Ajax IME を利用した変換テキストボックスを置いてみた。

http://vocrf.net/test/ime.html

候補が選択できないのであまり実用的ではないけど。

2011-07-19

N-gram かな漢字変換:続き

昨日(記事を)書いた N-gram かな漢字(&漢字かな)変換について。

プログラムを書いたのはこの一週間ぐらい。

先週は仕事が終わってからマクドナルドで書いて、連休中は家でも書いていた。

N-gram の N は、最初は 3 で十分かと思って、それで試した。

"Trigram に勝つのは難しい" (by Manning 先生 - id:nokuno さんのツイートより)という言葉もあるので。

モデルを作って辞書を構築、変換を動かしてみた。

> ほんをかいたい
本を書いたい

なんだか残念な変換結果が。

どうしてこうなった

原因は、元コーパスの区切りの細かさ。

「書いた」というのは、"書/か い/い た/た" というように分割されている。

このコーパスを元にして作った trigram によって "ほんをかいたい" を変換する時、次のようなことが起こる。

まず、"本/ほん を/を 書/か" の trigram によって、高い点数を持ったノードができる。

その後も、"を/を 書/か い/い"、"書/か い/い た/た" でも高い点数を取り続ける。

ここまではいいのだが、次の "い/い た/た い/い" のところですでに "書/か" が忘れ去られてしまっているため、ここでも高い点を取ってしまい、結果として "本を書いたい" というものになってしまう。

そこで、単純に N を増やして 4-gram にしてみた。

> ほんをかいたい
本を買いたい

今回はいい感じになった。

4-gram では、"書/か い/い た/た い/い" よりも "買/か い/い た/た い/い" のほうがはるかに良いスコアを得るため(前者の -2.580363 に対し、後者は -0.05844066)。

この 4-gram モデルを辞書にした結果は、marisa-trie のファイルが 3つ合わせて 約40MB ほど、cdb のファイルが約450MB ほど。

この cdb は marisa-trie に格納した n-gram とそのスコア・バックオフスコアを結びつけているだけなので、単純なバイナリファイルにしたほうが効率的になりそうだ。

さて、この 4-gram かな漢字変換、けっこう賢く見える変換をしてくれる。

> いぬをかいたい
犬を飼いたい
> ほんをかいたい
本を買いたい
> まぐろをかいたい
マグロを解体

共起の処理を特にしているわけではないけど、4-gram によって自然にできている。

間に副詞が入るなどしたらもちろんうまくいかなくなるのだが、単純に 4-gram によってデコードしただけということを考えるとけっこううまくいっているんじゃないだろうか。

2011-07-18

N-gram 漢字-かな変換

@gologo13さんの言語モデル配布ページのデータを利用して簡単な漢字->かな/かな->漢字変換ができないかなーと思って作ってみた。

言語モデルの作成には SRILMを使用。

配布中のデータを SRILM で扱うには多少加工しないといけないので、その変換スクリプトも作った。

GitHub リポジトリhttps://github.com/hiroshi-manabe/ngram-converter

[追記]最新のバージョンでは、4-gram のかな漢字変換用辞書をあらかじめリポジトリに入れてある。

marisa-trie モジュールさえ入れてあれば、

./converter_sample.py --dicname-prefix=dics/bccwj4_rev_dic --order=4 --interactive

ですぐにかな漢字変換が実行できる。

まず、@gologo13さんの言語モデル配布ページ からkkc-BCCWJ.tarダウンロード解凍

1-gram.fwk, 2-gram.fwk, ... 7-gram.fwk というファイルができるはず。

(注意: 4-gram 以上の場合、コーパスの問題によりエラーが生じるので、後述の対策をしてください)(2011/08/12 現在、元コーパスの問題は解消されています)

その後、process_files.py で SRILM 向けの形式に変換。

./process_files.py -n 4 -o bccwj4_rev.ngram -r -e euc-jp

のようにする。

-n の数字や -o のファイル名は適当に。

-r は、元ファイルの "漢字/かんじ" といったものを "かんじ/漢字" のように変換する。

これをつけるとかな漢字変換用のデータになり、つけないと漢字かな変換のものになる。

-e は元ファイルのエンコーディング。現時点では EUC-JP で配布されているので、上のように指定すればいい。

将来変わったら適宜変えてください。

かなり時間がかかるけど、これで bccwj4_rev.ngram のようなファイルがそのうちできるはず。

その後、SRILM の ngram-count を実行。

オプションは次のような感じで。

ngram-count -order 4 -interpolate -kndiscount -read bccwj4_rev.ngram -lm bccwj4_rev.lm -write-vocab bccwj4_rev.vocab

これで、bccwj4_rev.lm, bccwj4_rev.vocab といったファイルができる。

次に、build_dics.py を実行(marisa-trie モジュールが必要)。

./build_dics.py --dicname-prefix=bccwj4_rev_dic --vocab=bccwj4_rev.vocab --lm=bccwj4_rev.lm

初回にこれを実行すると、bccwj4_rev.vocab と bccwj4_rev.lm を読み込んで、bccwj4_rev_dic.lookup, bccwj4_rev_dic.pair, bccwj4_rev_dic.ngram という 3つの marisa-trie ファイルと bccwj4_rev_dic.scores という 1つの バイナリファイルを生成する。

生成した辞書を使って変換を試すのは、converter_sample.py で。

./converter_sample.py --dicname-prefix=bccwj4_rev_dic --order=4 --interactive

プロンプトが表示され、入力待ち状態になる。

> きょうはいいてんきですね。
今日はいい天気ですね。

のようになれば成功。

--interactive を入れないと標準入力から読んで、変換結果を標準出力に出す(はず)。

以下は、現バージョンでは解消されている。

4-gram 以上の場合の注意というのは、元ファイルの 4-gram.fwk に次のような行があることによるもの。

9693774:      1 環境/かんきょう 変化/へんか の/ BT
10332411:      1 戦略/せんりゃく 環境/かんきょう 変化/へんか の/

「の」に対するかなが割り当てられておらず、空文字が「の」に対応することになりエラーが起こる。

"の/の" に修正するなり、この行を削除するなり、SRILM 実行後の vocab ファイルから "/の" (逆になっている)を削除するなりして対応してください。

2011-07-12

.gdbinit を公開してみる

タイトルのまま。

自分はずっと Windows で開発してきたので、C++Visual Studio(VS) でやっていた。

VS のいいところは、デバッグ機能。

条件付きブレークポイントやメモリ変更時のブレークといったことをしても爆速で動いてくれてきちんと止まってくれる。

この良さは使ったことがある人ならわかるはず。

修士の時に開発した Variable-Order Linear-Chain CRFs も、VS なしには開発は無理だったはず。

さて、今の会社に入ってからは開発は Linux 一色のため、しょうがなく Emacs+gdb に移行した。

VS に比べると、まさに石器時代といった趣き。

まあ、郷に入れば郷に従えということで。

それで、少しでも快適に使えるようにキーバインドをいじってみた。

以下がその結果の .gdbinit.

define a
  up
end

define m
  down
end

define o
  bt $arg0
end

define rs
  kill
  run
end

define st
  b _start
  run
end

define go
  tbreak $arg0
  c
end

define v
  display $arg0
end

define w
  info breakpoints
end

define id
  info display
end

define dd
  delete display $arg0
end

define eb
  enable breakpoint $arg0
end

define db
  disable breakpoint $arg0
end

define y
  fin
end

define z
  fin
  s
end

一番気に入ってるのは z。

C++デバッガを使っていると、コンストラクタとかオペレーター(vector の [] とか)に入ってしまって鬱陶しい思いをすることがよくある。そういう時、z キーひとつでリターン→ステップ実行できるので、目的の関数に入るまで繰り返せばいい。

st は、プログラムを実行しないとブレークポイントが設置できない時のため。

rs は、ワンキーでリスタートするため。

go は、「指定行まで実行」。

また、a/m でスタックフレームを移動できる。これは当然 1キーでできないといけない。

ノートに使用済みコマンドを書き出して割り当てキーを考えた。

もっといい割り当てがあったら教えて下さい。