pyconjp2015 - python で作って学ぶ形態素解析

41
Python で作って学ぶ形態素解析 2015/10/11, PyConJP 2015 Tomoko Uchida

Upload: tomoko-uchida

Post on 16-Apr-2017

22.402 views

Category:

Software


4 download

TRANSCRIPT

Page 1: Pyconjp2015  - Python で作って学ぶ形態素解析

Python で作って学ぶ形態素解析2015/10/11, PyConJP 2015

Tomoko Uchida

Page 2: Pyconjp2015  - Python で作って学ぶ形態素解析

Who am I

打田智子 @moco_beta

元:Webサービス企業でPythonエンジニアをしていました

現在:検索エンジン Solr, Elasticsearch 導入支援、運用サポートをしています

(株)ロンウイット所属

普段は主にJavaときどきScala屋さん。Python のお仕事きたらいいな :-)

興味があること:情報検索と、その関連技術

自然言語処理・機械学習 脱ワナビーめざして勉強中 🐥

2

Page 3: Pyconjp2015  - Python で作って学ぶ形態素解析

目次

Janome 紹介

形態素解析?

Janome を支えるアルゴリズム

Janome の開発ふりかえり

きっかけ・実装の話・チューニング・2系/3系対応3

Page 4: Pyconjp2015  - Python で作って学ぶ形態素解析

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

Page 5: Pyconjp2015  - Python で作って学ぶ形態素解析

特徴とか辞書、言語モデルは mecab-ipadic-2.7.0-20070801 を使用

だいたいは MeCab と同じ解析結果になります。未知語処理で差異がでます

Pure Python かつ標準ライブラリのみ使用

環境問わずどこでも動く…はず

ユーザー辞書サポート (MeCab 辞書フォーマット)

単語追加が試せます 5

Page 6: Pyconjp2015  - Python で作って学ぶ形態素解析

形態素解析?

日本語の分かち書き(単語分割)?

惜しい、けどそれだけじゃない

(お約束) Wikipedia 「形態素解析」から“対象言語の文法の知識(文法のルールの集まり)や辞書(品詞等の情報付きの単語リスト)を情報源として用い、自然言語で書かれた文を形態素(Morpheme, おおまかにいえば、言語で意味を持つ最小単位)の列に分割し、それぞれの品詞を判別する作業を指す。” 6

Page 7: Pyconjp2015  - Python で作って学ぶ形態素解析

形態素??品詞??

定義は?

そういうモノがあるということでおねがいします m(__)m

気になる方は専門書へ

自然言語処理学会「言語処理学辞典」

コロナ社「自然言語処理の基礎」7

Page 8: Pyconjp2015  - Python で作って学ぶ形態素解析

Janome を支えるアルゴリズム

「すもももももももものうち」

プログラムでどうやって分割しますか?

(よく知っている方はごめんなさい…)

8

Page 9: Pyconjp2015  - Python で作って学ぶ形態素解析

すもも / も / もも / も / もも / の / うち

Janome を支えるアルゴリズム

名詞 名詞 名詞助詞 助詞 助詞 名詞必要な知識• 語彙:「すもも」「もも」という名詞、「も」「の」という助詞

• (辞書)• 日本語らしさ:名詞のあとには助詞がきやすい

• (言語モデル)

Page 10: Pyconjp2015  - Python で作って学ぶ形態素解析

Janome を支えるアルゴリズム

辞書と言語モデル

人手で整備

コーパス(学習データ)から教師あり機械学習

一般にはこのハイブリッド

なお素人には無理・・・とまではいわないけどモデルから作るのは大変

Janome は既存の辞書 mecab-ipadic を借用しています10

Page 11: Pyconjp2015  - Python で作って学ぶ形態素解析

Janome で実装したのは、いわゆる解析エンジン部分

辞書引き

解析実行:もっとも「日本語らしい」分割ポイントをさがす

Janome を支えるアルゴリズム

11

Page 12: Pyconjp2015  - Python で作って学ぶ形態素解析

辞書引き辞書は、サイズがコンパクトで高速に引けることが必要

ハッシュマップ (Python の dict) でもいいけど、

コモンプレフィックスマッチを使うと辞書引きの回数が減るので効率的

さくら 辞書さ 動詞「する」の活用形さく 動詞「さく」の基本形さく 形容詞「さくい」の活用形さくら 名詞… 他 11 単語

入力 出力

Page 13: Pyconjp2015  - Python で作って学ぶ形態素解析

辞書引き

データ構造・アルゴリズム

パトリシア木 (JUMAN)

ダブル配列 (ChaSen, MeCab)

FST (Kuromoji/Lucene版, Janome)

http://taku910.github.io/mecab/http://www.slideshare.net/lucenerevolution/automaton-invasionlucenerevolution2012 13

Page 14: Pyconjp2015  - Python で作って学ぶ形態素解析

FST ?

Finite State Transducers (決定性有限オートマトンの一種)

正確には Minimal Acyclic Subsequential Transducers

入力のプレフィックス・サフィックス両方を共有するので、トライ木と比較してコンパクト

(論文) http://citeseerx.ist.psu.edu/viewdoc/summary?

doi=10.1.1.24.369814

Page 15: Pyconjp2015  - Python で作って学ぶ形態素解析

FST

TL; DR

15

Page 16: Pyconjp2015  - Python で作って学ぶ形態素解析

図解FST

小さな辞書エントリ

{ ‘apr’: ’30’, ‘aug’: ’31’, ‘dec’: ’31’, ‘feb’: [’28’, ’29’], ‘jan,’: ’31’, ‘jul’: ’31’, ‘jun’: ’30’ }

という, 7つの 入力 => 出力 のペアからFSTを作ります

入力は形態素の文字列(表層形)、出力はマッチする形態素のIDと思ってください

16

Page 17: Pyconjp2015  - Python で作って学ぶ形態素解析

‘apr’ => 30 を投入

17

Page 18: Pyconjp2015  - Python で作って学ぶ形態素解析

‘aug’ => 31 を投入

18

Page 19: Pyconjp2015  - Python で作って学ぶ形態素解析

‘dec’ => 31 を投入

19

Page 20: Pyconjp2015  - Python で作って学ぶ形態素解析

(略)

続きはwebでhttp://mocobeta-backup.tumblr.com/post/111076688132/lucene-fst-1

20

Page 21: Pyconjp2015  - Python で作って学ぶ形態素解析

できたヽ(´ー`)ノ

21

Page 22: Pyconjp2015  - Python で作って学ぶ形態素解析

FST

余談1:Java 製検索エンジン Apache Lucene 4系で単語辞書やクエリエンジンとして採用されました

余談2:Janome は Lucene の実装を一部参考にしています

22

Page 23: Pyconjp2015  - Python で作って学ぶ形態素解析

解析

「日本語らしさ」を計算する

23

Page 24: Pyconjp2015  - Python で作って学ぶ形態素解析

解析「すもももももももものうち」(ふたたび)の区切り方はたくさんある

1.すもも / も / もも / も / もも / の / うち

2.すもも / も / もも / もも / も / の / うち

3.すもも / もも / も / もも / も / の / うち

などなど…

辞書を引きつつ、まずはすべての分割の候補を数え上げる

名詞 名詞 名詞助詞 助詞 助詞 名詞

名詞 助詞 名詞 名詞 助詞 助詞 名詞

名詞 名詞 名詞 名詞助詞 助詞 助詞

24

Page 25: Pyconjp2015  - Python で作って学ぶ形態素解析

解析

候補のなかから、一番日本語らしいパターンを選ぶ

1. すもも / も / もも / も / もも / の / うち

2. すもも / も / もも / もも / も / の / うち

「2. より1.のほうが自然」を計算で求めるには?

名詞 名詞 名詞助詞 助詞 助詞 名詞

名詞 助詞 名詞 名詞 助詞 助詞 名詞

25

Page 26: Pyconjp2015  - Python で作って学ぶ形態素解析

解析

言語モデル(隠れマルコフモデル)

「ある単語の出現しやすさ」(確率)

「前後の品詞のつながりやすさ」(確率)

確率をコスト値と読み換えれば足し算で「分割パターンの日本語らしさ」を評価できる

26

Page 27: Pyconjp2015  - Python で作って学ぶ形態素解析

解析

確率モデルにもとづき、一番「もっともらしい並び」を求める効率的なアルゴリズム

ビタビアルゴリズム (動的計画法の一種)

書籍/講義資料など解説多数

「自然言語処理の基礎」 おすすめ

Page 28: Pyconjp2015  - Python で作って学ぶ形態素解析

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スキルは初~中級くらい

Page 29: Pyconjp2015  - Python で作って学ぶ形態素解析

開発のきっかけ

Q: ところでなんで作ろうと思ったの

A: 形態素解析器の実装は自然言語処理の 101 です ^^ (by @ikawaha)

(kuromoji.js 作者)

(kagome 作者)

もしかして: 流行ってる…?(違)

Page 30: Pyconjp2015  - Python で作って学ぶ形態素解析

FST & 内包システム辞書の実装ここができれば終ったようなもの!(たぶん)

FST(オートマトン)は「辺の集まり」とみてバイト配列に落としこむ(Apache Lucene 方式)

string は encode(), decode() で bytes

にパック

int は struct.pack(), unpack() で bytes

にパック

http://mocobeta-backup.tumblr.com/post/113693778372/lucene-fst-2

janome でのエンコード例

Page 31: Pyconjp2015  - Python で作って学ぶ形態素解析

FST & 内包システム辞書の実装

mecab-ipadic の辞書エントリをFST(バイト配列)にしてバイナリデータとして保存

辞書エントリの詳細情報(品詞、活用形、読み、etc.)はFSTとは別ファイルにもつ

連接コスト(品詞の接続コスト)は二次元配列にして保存

解析器(Tokenizer)の初期化時にこれらを読み込む31

Page 32: Pyconjp2015  - Python で作って学ぶ形態素解析

辞書サイズ

初期リリース時は 20MB

0.2 系で少し小さくなって 13MB

TODO: インストールのときに、ソース埋め込みの辞書をプリコンパイルするところでメモリ3-4GB必要

とりあえずいくつか試したやり方の中で一番速かったんだ…

自分のVPS環境(2GB)で動かないのに気づいたのでなんとかします orz

32

Page 33: Pyconjp2015  - Python で作って学ぶ形態素解析

プロファイルをとって遅いところを特定して、慣れないなりに試行錯誤してみる

(遅いところ1)辞書引き(FSTの検索)が実行時間の半分を占める

キャッシュを入れたり (ここはFSTの実装がいまいちだからかな)

オブジェクト生成をやめていろいろ Tuple にしたり

(遅いところ2)連接コスト検索が実行時間の 1/4 を占める

連接コストの持ち方を、最初 dict (ハッシュテーブル) だったのを、(MeCabにならい)二次元配列に変えると高速に。データ構造とっても大事 ^^;

(遅いところ3)ラティスのノード生成が実行時間の 1/4 を占める (あとメモリも食う)

TODO

チューニング

33

Page 34: Pyconjp2015  - Python で作って学ぶ形態素解析

2系/3系対応

最初のリリース時は3系のみ

市場(?)の反応:「2系は…」 (ですよねー

(janome の場合) string, bytes の非互換だけ慎重に対応すれば、あとは簡単な置き換えで済んだ

2系対応版をとりあえず別パッケージで公開34

Page 35: Pyconjp2015  - Python で作って学ぶ形態素解析

2系/3系対応別パッケージに分かれていた2系/3系のパッケージをひとつにマージする神PRをいただき、無事統合

ありがとうございます!

Page 36: Pyconjp2015  - Python で作って学ぶ形態素解析

おわり

“これなら自分もオレオレ形態素解析器作れそう”

と思っていただけましたでしょうか(エンジン部分ならね!)

Page 37: Pyconjp2015  - Python で作って学ぶ形態素解析

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

Page 38: Pyconjp2015  - Python で作って学ぶ形態素解析

Appendix:歴史について少しだけ

(株)ジャストシステムさまからお借りしましたJastTechTalk #02 形態素解析の実装言語Talk

http://www.slideshare.net/JSUXDesign/jtt438

Page 39: Pyconjp2015  - Python で作って学ぶ形態素解析

Appendix:歴史について少しだけ

より詳しくはこちらを:

https://web.archive.org/web/20130123204941/https://www.ipa.go.jp/event/ipaforum2007/program/pdf/oss-matsumoto.pdf

39

Page 40: Pyconjp2015  - Python で作って学ぶ形態素解析

JustTechTalk !

日本語の言語処理といえば、のジャストシステム社が開催している自然言語処理や機械学習などなどの勉強会

言語処理・機械学習に興味がある方はグループに入ろう ヽ(*´∇`)ノ

DoorKeeper:https://justsystems.doorkeeper.jp

twitter:@just_techtalk 40

Page 41: Pyconjp2015  - Python で作って学ぶ形態素解析

ありがとうございました