pyconjp2015 - python で作って学ぶ形態素解析
TRANSCRIPT
Python で作って学ぶ形態素解析2015/10/11, PyConJP 2015
Tomoko Uchida
Who am I
打田智子 @moco_beta
元:Webサービス企業でPythonエンジニアをしていました
現在:検索エンジン Solr, Elasticsearch 導入支援、運用サポートをしています
(株)ロンウイット所属
普段は主にJavaときどきScala屋さん。Python のお仕事きたらいいな :-)
興味があること:情報検索と、その関連技術
自然言語処理・機械学習 脱ワナビーめざして勉強中 🐥
2
目次
Janome 紹介
形態素解析?
Janome を支えるアルゴリズム
Janome の開発ふりかえり
きっかけ・実装の話・チューニング・2系/3系対応3
Janome とはhttp://mocobeta.github.io/janome/
“janome (蛇の目) は, Pure Python で書かれた, 辞書内包の形態素解析器です.”
(venv) $ pip install janome(venv) $ python>>> from janome.tokenizer import Tokenizer>>> t = Tokenizer()>>> for token in t.tokenize("すもももももももものうち"):
… print(token)…すもも 名詞,一般,*,*,*,*,すもも,スモモ,スモモも 助詞,係助詞,*,*,*,*,も,モ,モもも 名詞,一般,*,*,*,*,もも,モモ,モモも 助詞,係助詞,*,*,*,*,も,モ,モもも 名詞,一般,*,*,*,*,もも,モモ,モモの 助詞,連体化,*,*,*,*,の,ノ,ノうち 名詞,非自立,副詞可能,*,*,*,うち,ウチ,ウチ 4
特徴とか辞書、言語モデルは mecab-ipadic-2.7.0-20070801 を使用
だいたいは MeCab と同じ解析結果になります。未知語処理で差異がでます
Pure Python かつ標準ライブラリのみ使用
環境問わずどこでも動く…はず
ユーザー辞書サポート (MeCab 辞書フォーマット)
単語追加が試せます 5
形態素解析?
日本語の分かち書き(単語分割)?
惜しい、けどそれだけじゃない
(お約束) Wikipedia 「形態素解析」から“対象言語の文法の知識(文法のルールの集まり)や辞書(品詞等の情報付きの単語リスト)を情報源として用い、自然言語で書かれた文を形態素(Morpheme, おおまかにいえば、言語で意味を持つ最小単位)の列に分割し、それぞれの品詞を判別する作業を指す。” 6
形態素??品詞??
定義は?
そういうモノがあるということでおねがいします m(__)m
気になる方は専門書へ
自然言語処理学会「言語処理学辞典」
コロナ社「自然言語処理の基礎」7
Janome を支えるアルゴリズム
「すもももももももものうち」
プログラムでどうやって分割しますか?
(よく知っている方はごめんなさい…)
8
すもも / も / もも / も / もも / の / うち
Janome を支えるアルゴリズム
名詞 名詞 名詞助詞 助詞 助詞 名詞必要な知識• 語彙:「すもも」「もも」という名詞、「も」「の」という助詞
• (辞書)• 日本語らしさ:名詞のあとには助詞がきやすい
• (言語モデル)
Janome を支えるアルゴリズム
辞書と言語モデル
人手で整備
コーパス(学習データ)から教師あり機械学習
一般にはこのハイブリッド
なお素人には無理・・・とまではいわないけどモデルから作るのは大変
Janome は既存の辞書 mecab-ipadic を借用しています10
Janome で実装したのは、いわゆる解析エンジン部分
辞書引き
解析実行:もっとも「日本語らしい」分割ポイントをさがす
Janome を支えるアルゴリズム
11
辞書引き辞書は、サイズがコンパクトで高速に引けることが必要
ハッシュマップ (Python の dict) でもいいけど、
コモンプレフィックスマッチを使うと辞書引きの回数が減るので効率的
さくら 辞書さ 動詞「する」の活用形さく 動詞「さく」の基本形さく 形容詞「さくい」の活用形さくら 名詞… 他 11 単語
入力 出力
辞書引き
データ構造・アルゴリズム
パトリシア木 (JUMAN)
ダブル配列 (ChaSen, MeCab)
FST (Kuromoji/Lucene版, Janome)
http://taku910.github.io/mecab/http://www.slideshare.net/lucenerevolution/automaton-invasionlucenerevolution2012 13
FST ?
Finite State Transducers (決定性有限オートマトンの一種)
正確には Minimal Acyclic Subsequential Transducers
入力のプレフィックス・サフィックス両方を共有するので、トライ木と比較してコンパクト
(論文) http://citeseerx.ist.psu.edu/viewdoc/summary?
doi=10.1.1.24.369814
FST
TL; DR
15
図解FST
小さな辞書エントリ
{ ‘apr’: ’30’, ‘aug’: ’31’, ‘dec’: ’31’, ‘feb’: [’28’, ’29’], ‘jan,’: ’31’, ‘jul’: ’31’, ‘jun’: ’30’ }
という, 7つの 入力 => 出力 のペアからFSTを作ります
入力は形態素の文字列(表層形)、出力はマッチする形態素のIDと思ってください
16
‘apr’ => 30 を投入
17
‘aug’ => 31 を投入
18
‘dec’ => 31 を投入
19
(略)
続きはwebでhttp://mocobeta-backup.tumblr.com/post/111076688132/lucene-fst-1
20
できたヽ(´ー`)ノ
21
FST
余談1:Java 製検索エンジン Apache Lucene 4系で単語辞書やクエリエンジンとして採用されました
余談2:Janome は Lucene の実装を一部参考にしています
22
解析
「日本語らしさ」を計算する
23
解析「すもももももももものうち」(ふたたび)の区切り方はたくさんある
1.すもも / も / もも / も / もも / の / うち
2.すもも / も / もも / もも / も / の / うち
3.すもも / もも / も / もも / も / の / うち
などなど…
辞書を引きつつ、まずはすべての分割の候補を数え上げる
名詞 名詞 名詞助詞 助詞 助詞 名詞
名詞 助詞 名詞 名詞 助詞 助詞 名詞
名詞 名詞 名詞 名詞助詞 助詞 助詞
24
解析
候補のなかから、一番日本語らしいパターンを選ぶ
1. すもも / も / もも / も / もも / の / うち
2. すもも / も / もも / もも / も / の / うち
「2. より1.のほうが自然」を計算で求めるには?
名詞 名詞 名詞助詞 助詞 助詞 名詞
名詞 助詞 名詞 名詞 助詞 助詞 名詞
25
解析
言語モデル(隠れマルコフモデル)
「ある単語の出現しやすさ」(確率)
「前後の品詞のつながりやすさ」(確率)
確率をコスト値と読み換えれば足し算で「分割パターンの日本語らしさ」を評価できる
26
解析
確率モデルにもとづき、一番「もっともらしい並び」を求める効率的なアルゴリズム
ビタビアルゴリズム (動的計画法の一種)
書籍/講義資料など解説多数
「自然言語処理の基礎」 おすすめ
Janome 開発ふりかえりたまに、どのくらいの期間で開発したのか聞いてくださる方がいるので、Github リポジトリ (https://github.com/mocobeta/janome) のコミット履歴を追ってみた
2015/1/20 頃: 準備 (FSTの論文, Luceneのソース読み始めた)
2015/2/14 頃: FSTのベースを作り始める
2015/3/14 頃: システム辞書 (mecab-ipadic) を作り始める
2015/4/1 頃: ラティスを作り始める
2015/4/7: ユーザー辞書がつく
2015/4/8: PyPI に登録、公開
開発工数こんな感じFSTの理解と実装に2ヶ月mecab-ipadic の内包辞書化に0.5ヶ月ビタビの実装に数日リリース作業に1日
pythonスキルは初~中級くらい
開発のきっかけ
Q: ところでなんで作ろうと思ったの
A: 形態素解析器の実装は自然言語処理の 101 です ^^ (by @ikawaha)
(kuromoji.js 作者)
(kagome 作者)
もしかして: 流行ってる…?(違)
FST & 内包システム辞書の実装ここができれば終ったようなもの!(たぶん)
FST(オートマトン)は「辺の集まり」とみてバイト配列に落としこむ(Apache Lucene 方式)
string は encode(), decode() で bytes
にパック
int は struct.pack(), unpack() で bytes
にパック
http://mocobeta-backup.tumblr.com/post/113693778372/lucene-fst-2
janome でのエンコード例
FST & 内包システム辞書の実装
mecab-ipadic の辞書エントリをFST(バイト配列)にしてバイナリデータとして保存
辞書エントリの詳細情報(品詞、活用形、読み、etc.)はFSTとは別ファイルにもつ
連接コスト(品詞の接続コスト)は二次元配列にして保存
解析器(Tokenizer)の初期化時にこれらを読み込む31
辞書サイズ
初期リリース時は 20MB
0.2 系で少し小さくなって 13MB
TODO: インストールのときに、ソース埋め込みの辞書をプリコンパイルするところでメモリ3-4GB必要
とりあえずいくつか試したやり方の中で一番速かったんだ…
自分のVPS環境(2GB)で動かないのに気づいたのでなんとかします orz
32
プロファイルをとって遅いところを特定して、慣れないなりに試行錯誤してみる
(遅いところ1)辞書引き(FSTの検索)が実行時間の半分を占める
キャッシュを入れたり (ここはFSTの実装がいまいちだからかな)
オブジェクト生成をやめていろいろ Tuple にしたり
(遅いところ2)連接コスト検索が実行時間の 1/4 を占める
連接コストの持ち方を、最初 dict (ハッシュテーブル) だったのを、(MeCabにならい)二次元配列に変えると高速に。データ構造とっても大事 ^^;
(遅いところ3)ラティスのノード生成が実行時間の 1/4 を占める (あとメモリも食う)
TODO
チューニング
33
2系/3系対応
最初のリリース時は3系のみ
市場(?)の反応:「2系は…」 (ですよねー
(janome の場合) string, bytes の非互換だけ慎重に対応すれば、あとは簡単な置き換えで済んだ
2系対応版をとりあえず別パッケージで公開34
2系/3系対応別パッケージに分かれていた2系/3系のパッケージをひとつにマージする神PRをいただき、無事統合
ありがとうございます!
おわり
“これなら自分もオレオレ形態素解析器作れそう”
と思っていただけましたでしょうか(エンジン部分ならね!)
MeCab (C++) のクローン、またはMeCab辞書(モデル)を借用している形態素解析器あれこれ
Igo (Java), igo-python (Python), igo-ruby (Ruby), igo-javascript (JavaScript)
Kuromoji (Java), kuromoji.js (JavaScript)
kagome (Go), janome (Python)
他...
Appendix:歴史について少しだけ
37
Appendix:歴史について少しだけ
(株)ジャストシステムさまからお借りしましたJastTechTalk #02 形態素解析の実装言語Talk
http://www.slideshare.net/JSUXDesign/jtt438
Appendix:歴史について少しだけ
より詳しくはこちらを:
https://web.archive.org/web/20130123204941/https://www.ipa.go.jp/event/ipaforum2007/program/pdf/oss-matsumoto.pdf
39
JustTechTalk !
日本語の言語処理といえば、のジャストシステム社が開催している自然言語処理や機械学習などなどの勉強会
言語処理・機械学習に興味がある方はグループに入ろう ヽ(*´∇`)ノ
DoorKeeper:https://justsystems.doorkeeper.jp
twitter:@just_techtalk 40
ありがとうございました