yoriyukiの日記 このページをアンテナに追加 RSSフィード

2010-10-24

[][]Google 日本語入力 TechTalk 2010 ノート Google 日本語入力 TechTalk 2010 ノートを含むブックマーク

ノートをそのまま公開する。具合が悪い場合はご連絡下さい。

始め

会場ついた。プロジェクタTweetが表示されている(Tweet Search Stream)。

しかし説明用の漫画を作るとかお金あるなあ。

「IME開発をしようとする気持ちを新たにしてくださると嬉しい。」

ライトニングトークテーマは入力

入力じゃなくて人力だった?!でもOK

お知らせ

諸注意

写真撮影禁止

Google 日本語入力 イベント」と検索すれば出る

ソースコード:mozcで検索

Google C++ style guide ← よめ:例外処理禁止とか。Boostに対する扱いとか。

プレゼン資料は公開禁止。ノートはOK

Google DocumentのGoogle Presentationを使う。便利だよ!

Google 日本語入力ができるまで

小松さん

Google 日本語入力

Webから自動的に辞書作成

サジェスト機能

マルチプラットフォーム

開発経緯

工藤さんと小松さんの20%プロジェクトから

工藤

Mecab, AjaxIME <- Web 2.0時代, Zinnia

小松

PRIME

Tomoe

2005年ごろから

20%ルール由来

App Engine, GMail, Transit, QR code API, 弁当注文システム, 今日の受付システム

やりたいことをやったほうがいい

何故Google がIME

「もしかして」の大部分が既存のIMEの誤変換

どろん除

インしてみる

スーパーロボット大戦

いい入力はいい検索の第一歩

だって作りたいし

Mozc team

Anthy、WinAnthy、Skkime、AjaxIME、PRIME、SCIM-skkの開発者が参加。

プロジェクト立ち上げ

最初の半年はディスカッションのみ

週数回集まって議論

デザインを決める

ある時コードが一つもないことに気づく

週一回週的にコーディングする時間を設ける

デモ

libanrhy.so クローン

プロジェクトに昇格←ずっと20%ルールでやっていたわけではない。今は本業としている人もたくさん居る。

リリースまでの道のり I

社内でドッグフード←自分のものは自分で食べる

既存のIMEとの互換性

既存IMEからの移行コストを最小限に

既存のIMEのメジャーな機能を踏襲

キーバインドも既存のIMEを踏襲

サジェスト+豊富な語彙で勝負

リリースまでの道のりII

長い長いラストワンマイル

テスト!テスト!テスト!

テストコードが本コードの2,3倍

必要最小限の機能にとどめて安定性を向上。

リリース

リリースプロセス

ドッグフード

毎日のビルドを使ってみる(社内)

continuous build、

ユニットテストストレステスト

開発版(数週間で更新)

アップデートテストなど最低限のテストのみ

クラッシュレポートを活用

利用統計情報←文字自体は送っていない。安心して!

ベータ

数か月で更新

オープンソース

googol機能←?

IMEの機能を網羅

マルチプラットフォーム

研究にも活用してください。

質問

テスト不十分で出てない機能は→答えられない。

テストが十分であるかどうかの判断は? - Crash Report, Bug Tracking

UIのテスト手法 - いいやり方がない。レイヤーを切り分けてできるだけユニットテストに落とし込む。手で動かしてみるのもやっている。バグラッシュ(?)ドッグフード

かかった人月 言えません。2人でやってるわけでも、20%でやってるわけでもない。

ユニットテストビルドを自動化。ビルド時にユニットテスト エラー→最後に変更した人とレヴューした人にメール

Google日本語入力/Mozcno設計概要

工藤さん

空気のようなIME

マルチプラットフォーム

スピード

セキュリティ

安定性

既存のやり方はうまくいかない

IMEの複雑

複雑怪奇…書ききれない

従来のやり方

DLLとして実装、辞書は共有リソース

安定性が良くない。IMEがクラッシュすると全体がクラッシュする

アプリケーションはよくクラッシュする→辞書が壊れる。

セキュリティ

IMEはセキュリティーの高いコンテキストで実行されることがある

機能の分離

IMM DLLをできるだけ小さく

処理ごとに別のプロセスに分業

ありがちな機能分離

Canna,Wnn

多くの処理をクライアントで行う

ローマ字かな変換とか

クライアントクラッシュリスクはそれほど低減しない

仮名漢字変換エンジンとキーイベントハンドラではキーイベントハンドラの方がサイズが大きい!

Stateless化

クライアントはステートレス

Google 日本語入力の機能分離

IM DLL キーイベントプロキシ

描画

候補ウィンドウはGUIレンダラとして別プロセル

安定性の工夫

データファイルは.exeに埋め込み

言語モデルは全部バイナリ

辞書が壊れない

ファイルIOのエラーが起きない

古い辞書後方互換性を気にしなくていい

#良さそう

リブート不要の自動アップデート

古典的なIME:

動作中のDLLをアップデート出来ないので、再起動を要求される

新旧のDLLが共有データを共有するのはまずい。

Google IME:

変換エンジンをkillして再起動するだけ。DLLはミニマル

仮名漢字変換アルゴリズム

n文節最長一致法:

使っているのは?

コスト最小法:

Google IMEは最小コスト法。

最小コスト

Viterbi

コスト推定法

P(x) = C p(y) * p(x|y)

p(y) : 言語モデル, 品詞ベースクラス言語モデル

Web上の単語頻度から推定

p(x|y) : 読みモデル 漢字yをどう読むか

言語モデルができるまで

Mecab形態素解析言語モデル

ウェブINDEX->単漢字辞書Googleサジェスト

読みの推定

既存の辞書ipadicからEMアルゴリズムを使って単漢字辞書を作る

当て字に弱い

読み間違い

辞書の圧縮

Mozcの辞書はIPADicのスーパーセット

100万単語

LOUDS 9.5M


Key value store -> だめ

Common Prefix Search

Predictive Search:あるPrefixをもつ文字列

データ構造はLOUD:メモリ効率がよい。おそいけど。

副作用の低減

語彙が多いと精度が下がる

一般的な表現が特殊な表現に上書きされる

評価

機械的な評価

評価の難しさ

当たり前のことを間違えることの方がNG

平均的、機械的な制度はあまり当てにならない。

<- Bleu(spell ?) test, exact test (花岡さんによる)

自動回帰テスト

絶対に変換できないといけないとまずい例をたくさん作る

失敗すると出荷できない。

日本語入力の開発は総合格闘技
質疑

プロセス間通信

Linux - Unix domain socket

Windows - Named Pipe

Mac - Mach IPC

socketを使っていない理由はセキュリティー。

相手先が認証できる。PID, username.

ストレステスト:ランダム

レンダラ:クラッシュしたら?←レンダラーはステートレスなので再起動すればOK. Linuxでは公開されていないのでIBUSでやっているのでクラッシュするかも。

品詞体系 IPADIC

プレイバック機能。変換エンジンを殺し続けても大丈夫。4秒ごとにkillしてもユーザーは気づかない。

基本語彙:IPADICは人手で修正する。ランキングはいじっていない。

コードリーディング

ビルドシステム

Jun Mukaiさん

GYPを使う(Chromeのために開発された)

why GYP:

もともとSConsを使っていた。

なぜ移行したか

SCONS:

Pythonで書かれたビルドシステム

Python普通に書けるので何でもできる

凝ったことをやろうとすると大変なことになる

プラットフォームサポートが弱い

アプリケーションや.imeファイル(?)を作るのが厄介

GYP:

シンプルビルド構文

凝ったことはできない

GYP自体はビルドしない。いろんなビルドファイルを生成する。

プラットフォームサポートが厚い

ただのPythonのDict。条件分岐が文字列キモイ

dependencies

include .gypi

action

コマンド実行ができるので、Pythonスクリプトを実行できる。

Mozcの辞書生成はC++

build_mozc.pyがgypを呼ぶ。←面倒な部分をやる

フェーズビルド:

2フェーズ

build_tools:辞書生成ツールなど

build: 本体

build_mozc.py --onepassで一度にビルドできる。

Client

小松さん

クライアントローマ字変換しない

プロセス間通信

Protocol Bufferでシリアライズしたデータのやり取り

code.google.com/p/protobuf

データ構造をバイト列にシリアライズ

シリアライズ可能なデータ構造

C++、JavaPythonに。

後方互換性、フィールドを増やすのは簡単。

Mozcのプロトコル:

セッションの作成:各入力ボックスごとに

セッションidをUniqueに割り当てる

mozc.el: Emacs

mozc_emacs_helper.cc

Converter Layer

工藤さん

Segments Class:

文節列を表現

Segments = Segment[]

Segment = Candidate[] + meta information

Candidate: Key(yomi), Value(kaki)

ConverterInterface:

ImmutableComverter

ひらがな→漢字変換

いつも同じ結果、ステートレス

Imuutable Converter

virtual bool Convert(Segments *segments) const

segmentsを呼び出し側がセットするときに制約を与える。

Rewriter

後処理

Perdictor

予測変換

rewrite:

segmentsを適宜書き換える

#うーん、あまり感心しない設計だなあ。

品詞テーブル:

data/dictionary/id.def

番号は頻繁に更新

dictionary*.txt

よみ 左品詞ID 右品詞ID 生起コスト

同じ単語でも2つの品詞を持つことがある!←複合語

data/connection.txt

コスト= -500* log(p)

システム辞書に単語を追加したい→お勧めしない

適当な量のテキストを集める

既存単語の頻度と追加したい単語の頻度比を求める

  同じ品詞になるように

頻度比のlogを取ってたす

文節区切りルール:

助詞から名詞は文節境界

data/rules/segmenter.def

データジェネレーション:

id.def segmenter.def -> if-then rule (isBoundaryInternal)

compress! bit-array ← 2,3行で書ける長さに!

Rewriter

Converterの中に

RewriterInterface:

Rewrite <- 重要

Finish 学習

Sync たまに呼ばれる

Clear 使うことはない。入力履歴をクリアする

!すべての変換で呼ばれる!

スペースが押されないとrewriterは呼ばれません

サジェスト時にはrewriterは使われません。

トリガリングルールシンプルにしないと遅くなります。

御籤:

http://code.google.com/p/mozc/source/browse/trunk/src/rewriter/fortune_rewriter.cc

数値変換:

number_rewrite.cc

数値の変換は結構複雑

四万十川 -> 4010川?

Converterは変換の途中で数値をアラビア数字に変換している

変換ルールは手で書いてある。謎めいている。

Googol 10^100->Googol

顔文字:

単純

data/emoticon/emoticon.tsv

電卓:

必ず=で終わるときだけ

lemon parserを使ってパースと演算

候補を一番上に出す

Storage

花岡さん

辞書:

LookupPredictive

LookupPrefix

LookupExact 不使用

LookupReverse 不使用

dictionary/dictionary.cc

user_dictionary:

protocol_bufferのファイル

<user profile dir>/user_dictionary.db

system_dictionary:

binaryに埋め込まれる

data/dictionary*.txt

各種データストレージ:

existence filter:

bool Exists(uint64 hash)

変換とサジェストで結果を変えるときに使う

Bloomフィルタ

LRU storage:

Insert

lookup

FAQ

バグ、問題を見つけました:Issue Trackerへ

修正パッチを送りたい:とても時間がかかる。自然言語での報告、変更方法の方が助かります。改善したいです。

辞書、単語を追加したい:BSDライセンス/パブリックドメインで公開してください。例:沖縄辞書

〇〇で動きますか:C++/STL/POSIXなら。little endianマシンだけ

Mozcを改造したい:Rewriterがおすすめです

深く開発に参加したい:Googleは通年採用しております

質疑応答

顔文字辞書:人手で

文字コード:UTF-8、困ったこと。コンパイラーのデフォルトコードがShiftJISだったりする。ヴィとか全角チルド

速度の測定:converterはクエリにどのくらい時間がかかったかを返すので、それを使う。

機能の取捨選択:重要度、容易さ、開発者思い入れ

公開されているテスト:ユニットテストストレステストがMozcに入っている。

開発プラットフォーム:開発環境:クライアント側:その環境。それ以外:好きなOS。ビルドエラーは自動ビルドで検出。

LT - 入力全般

自分の発表で忙しくてあまりノートは取れませんでした。でもSTAKKで打ち間違いに対応しているというのは面白かった。あとでコードを確認したい。

ローマ字変換テーブル

入力

出力 → 確定した文字

次の入力 → 確定前の以前の出力

懇親会

知り合いでは稲葉さん、奥野さん、田畑さん、花岡さん、向井さんと会った。向井さんとはネットでは10年くらいの知り合いなのにリアルでは初めて会った。ネット世代の恐怖。

OCamlで釣れた人一名。

Trieなら簡単にあいまい検索できるはず:要検討

Google社内での言語事情とか。

Camomile 1.0へのロードマップOCamlメインにマージするにはどうすればいいか。

Rubyの多言語化は迷走している。松本さんの趣味?どうせUnicodeに全部なるんだから無駄な抵抗はやめればいいのに。Cruby以外はUnicodeになるんじゃないか。JRubyの方が普及しているかもしれない。せっかくVMにしたのに、Railsがevalしまくりなので速くならない。悲しい。

Google IMEベンチマーク方法。Bleu(spell?)テストとexactテスト、regresssionテストベンチマークと体感が食い違う -- 当たり前のことを間違えることの方が、めったに無いものをきちんと変換するより大事。変換結果は言語モデルベースになったコーパスの質にもよる。

Appleソフトウェアキーボードはいろいろつくりこんである。前の入力で次の入力の認識範囲を変更するとか。そのために上位層との切り分けができていなくてAPIが公開できないのかもしれない。

「方が」がGoogle IME 安定版で変換できない件。まとめて変換したほうが効率が良い。

Google Japanエンジニアの割合。移転前で半分くらい。

Google IMEは社内で重視されている。本業でやっている。(今は20%ruleじゃない)。

開発効率を上げる方法:アジャイルとかTDD。

奥野さんのPythonでの実装では、Viterbiで使うポインターの代わりに、配列のインデックスを使っている。

#あまり感心しないなあ。

感想、真字へのプランなど

いろいろとモチベーションをもらった。

Mozcの辞書は使えそう。フォーマットもIPADICよりも分かりやすい。

英文の認識

とりあえずの目標としてみる。

未知語生成の部分に組み込めないか?

文字bigramで生成する未知語のコストを計算する。Mozcの辞書トレーニング

すればよい?

かな<->ローマ字が一対一でないことが問題かも。

jmukjmuk 2010/10/25 02:49 一点、こまかい訂正ですが、「ヴ」はひらがなの「う」に濁点を念頭において話していたと思います。この文字はUnicodeにはあるのですが(U+3094)、JISには(確か)ありません。IMEに閉じていれば問題ないですが、IMEを使っているアプリケーションがUnicodeをちゃんとサポートしているとは限らないので、安易に「う」に濁点を使うと問題が発生することがある、という話なのです。

zakizaki 2010/10/25 08:05 googol機能は 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 が googol に変換されるというイースターエッグですね

yoriyukiyoriyuki 2010/10/25 19:56 「う」に濁点はUnicodeでひとつの文字として書けるんですね。いろいろそういう文字はありそうですね。

yoriyukiyoriyuki 2010/10/25 19:58 はい、Googgol機能はあとで説明がありました。ノート取るまでもないかなと思ったんで書いてないんですけど。