iMind Developers Blog

iMind開発者ブログ

PythonでJuman++を動かす

概要

形態素解析のJunam++について、インストールからPythonでの形態素解析の実行までを行う。

バージョン情報

  • jumanpp-1.0.2
  • pyknp==0.4.1

OSはUbuntu系を想定。それ以外のOSを利用している方はaptのところを適宜読み替えてください。

Juman++について

Juman++は2016年に公開された比較的新しい形態素解析ソフト。

RNNを用いたモデルを利用しており、辞書もかなり充実しているのが特徴。

JUMAN++では,RNN(recurrent neural network)に基づく言語モデルを利用しています.RNN言語モデルでは,単語の密ベクトルに基づく再帰的な文脈の意味表現を用いることにより,次に出現する意味的に妥当な単語を予測します.これと,京都大学テキストコーパス(新聞記事)および京都大学ウェブリードコーパス(ウェブテキスト)から学習した基本モデルを組み合わせることにより,文全体として意味的に妥当な単語分割を実現しました

中略

JUMAN++の文法および辞書は,JUMANの標準文法と辞書を継承しています.3万語程度の基本辞書についてさまざまな語彙情報・意味情報を人手で正確に整備し,その範囲を超えるものについてはWikipediaやウェブコーパスからの自動語彙獲得を行っています.

日本語形態素解析システムJUMAN++ version 1.0 (PDF)

辞書に関する詳細は下記サイトが詳しい。

JUMAN++の形態素解析辞書についてのメモ | 北白川日記

例えば「テザリング有料をディスっとこう」という言葉を形態素解析させると「テザリング」も「ディスる」も辞書に入っていることがわかる(共に自動獲得)。

$ echo "テザリング有料をディスっとこう" | jumanpp

テザリング テザリング テザリング 名詞 6 普通名詞 1 * 0 * 0 "自動獲得:Wikipedia Wikipedia上位語:接続/せつぞく"
有料 ゆうりょう 有料 名詞 6 普通名詞 1 * 0 * 0 "代表表記:有料/ゆうりょう カテゴリ:抽象物 ドメイン:ビジネス"
を を を 助詞 9 格助詞 1 * 0 * 0 NIL
ディスっ でぃすっ ディスる 動詞 2 * 0 子音動詞ラ行 10 タ接連用形 9 "代表表記:ディスる/でぃする 自動獲得:テキスト"
とこう とこう とく 接尾辞 14 動詞性接尾辞 7 子音動詞カ行 2 意志形 4 "代表表記:とく/とく"
EOS

辞書獲得のフローについては下記に記載されている。

『JUMAN++』の⼤規模語彙獲得へ向けた取り組み (PDF)

実際にどういった言葉が辞書に入っているかはソースコードを落としてdict-buildディレクトリで確認できる。

$ head -3 dict-build/wikipediadic/wikipedia.dic.orig 

(名詞 (普通名詞 ((読み °C)(見出し語 (°C 1.1))(意味情報 "自動獲得:Wikipedia Wikipediaリダイレクト:セルシウス度 読み不明"))))
(名詞 (普通名詞 ((読み °F)(見出し語 (°F 1.1))(意味情報 "自動獲得:Wikipedia Wikipediaリダイレクト:華氏 読み不明"))))
(名詞 (普通名詞 ((読み °R)(見出し語 (°R 1.1))(意味情報 "自動獲得:Wikipedia Wikipediaリダイレクト:レオミュール度 読み不明"))))

RNNに巨大な辞書ということから想像できる通り、実行速度はかなり遅い。いや、想像している以上に凄く遅い。

例えば青空文庫から人間失格を落としてきて解析にかけた結果を比較すると、mecabが0.054秒に対してjumanppは4分20秒と別次元の時間のかかり方をしている(実行環境: i7-8550U)。

$ time cat ningenshikkaku.txt | mecab > resulttxt
real    0m0.054s

$ time cat ningenshikkaku.txt | jumanpp > resulttxt
real    4m20.268s

他の計測している方の数字を見ても同じような結果になっているようだ。

メモ帳という名の備忘録: 形態素解析の速度比較

サーバーモードで動かした場合も4分16秒と実行時間はほぼ変わらなかった。

# ソースコードを落とすとサーバーモード用のrubyのコードがついている
$ ruby script/server.rb --cmd jumanpp
$ time cat ningenshikkaku.txt | ruby script/client.rb > result.txt
real    4m16.662s

Beam幅縮めれば多少は速くなる。(それによって精度がどう変わるかは未確認)

$ time cat ~/tmp/ningenshikkaku.txt | jumanpp -B 3 > resulttxt
real    3m24.270s

MecabもKuromojiもJanomeもこのJuman++も、利用する際の要件に応じてどれを選ぶかは考える必要がありそう。

Juman++のインストール

前置きが長くなったが本題の導入とPythonでの実行について。

インストール時は下記公式サイトからソースコードをダウンロードしてmakeする。

JUMAN++ - KUROHASHI-KAWAHARA LAB

最新版を利用したい場合はGithubからcloneする。

GitHub - ku-nlp/jumanpp: Juman++ (a Morphological Analyzer Toolkit)

インストール手順について、個人的な趣味で本手順では $HOME/local にインストールを行う。

公式サイトからtarを落としてきたらとりあえず解凍。

$ tar xvf jumanpp-*.tar.xz 

続いてconfigure。prefixに$HOME/localを指定している。

Boostをインストールせずに実行した場合。

$ cd jumanpp-*
$ ./configure --prefix=$HOME/local
checking for boostlib >= 1.57... configure: We could not detect the boost libraries (version 1.57 or higher). If you have a staged boost library (still not installed) please specify $BOOST_ROOT in your environment and do not give a PATH to --with-boost option.  If you are sure you have boost installed, then check your version number looking in <boost/version.hpp>. See http://randspringer.de/boost for more documentation.
configure: error: "Error: cannot find available Boost library."

Boost libraryがないと上記エラーになる。aptで入れてから再度configure。

$ sudo apt install libboost-all-dev
$ ./configure --prefix=$HOME/local

成功したらmakeとmake install。

$ make
$ make install

インストール完了。試しに動かしてみる。$HOME/local/binにPATHが通ってるという前提。

$ echo "動くかな" | jumanpp

動く うごく 動く 動詞 2 * 0 子音動詞カ行 2 基本形 2 "代表表記:動く/うごく 自他動詞:他:動かす/うごかす 反義:動詞:止まる/とまる"
か か か 助詞 9 接続助詞 3 * 0 * 0 NIL
な な な 助詞 9 終助詞 4 * 0 * 0 NIL
EOS

動いた。

Pythonでの実行

PyKNPをインストールする。

$ pip install pyknp
from pyknp.juman.juman import Juman
juman = Juman()
mlist = juman.analysis('動いておくれ')
[mrph.midasi for mrph in mlist.mrph_list()]
  #=> ['動いて', 'おくれ']

昔のサンプルコードを見るとJumanppというクラスを使っていることが多いが、現状では上記の記述で良いらしい。ソースにも下記のようにcommandにjumanではなくjumanppが指定されている。

class Juman(object):
    def __init__(self, command='jumanpp', ...

https://github.com/ku-nlp/pyknp/blob/master/pyknp/juman/juman.py

形態素解析結果の詳細

上記コードでは mrph.midasi で見出し語を取っているが、その他にも読みや品詞など、様々な情報が参照できる。

例として「今日は休みました」という言葉を解析した結果から取れるattributeについて、それぞれ記載していく。

mlist = juman.analysis('今日は休みました')
for mrph in mlist.mrph_list():
    print(mrph.${attribute})
attribute 意味 今日 休み ました
midasi 見出し 今日 休み
yomi 読み こんにち やすみ ました
genkei 原型 今日 休む ます
hinsi 名詞 助詞 動詞 接尾辞
hinsi_id 6 9 2 14
bunrui 品詞細分類 時相名詞 副助詞 * 動詞性接尾辞
bunrui_id 品詞細分類ID 10 2 0 7
katuyou1 活用型1 * * 子音動詞マ行 動詞性接尾辞ます型
katuyou1_id 活用型ID1 0 0 9 31
katuyou2 活用型2 * * 基本連用形 タ形
katuyou2_id 活用型ID2 0 0 8 7
imis 意味情報 代表表記:
今日/こんにち
カテゴリ:時間
NIL 代表表記:
休む/やすむ

代表表記:ます/ます
repname 代表表記 今日/こんにち 休む/やすむ ます/ます
ranks ラティスでのランク 1 1 1 1

genkei、yomi、hinsiにはお世話になることが多い。

品詞体型

品詞体型についてはソースコードの dict-build/grammar/JUMAN.grammar に載っている。まとめると下記のようになる。

品詞名 品詞細分類
特殊 句点
特殊 読点
特殊 括弧始 (, 「
特殊 括弧終 ), 」
特殊 記号 @,
特殊 空白
動詞 休む
形容詞 美しい, 尊い
判定詞 だ, である
助動詞 ず, べき
名詞 普通名詞
名詞 サ変名詞 旅行, 閲覧
名詞 固有名詞 オリンピック, 毘沙門天
名詞 地名 東京, パリ
名詞 人名 山田, 太郎
名詞 組織名 岩波, 京王
名詞 数詞 ミリ, 億
名詞 形式名詞 こと, もの
名詞 副詞的名詞 方, 程, たび, ぐらい
名詞 時相名詞 今日, 明日
指示詞 格助詞 が, を
指示詞 副助詞 そう, ああ
指示詞 接続助詞 ながら, つつ
指示詞 終助詞 な, よ, ぞ
接続詞 そして, しかし
連体詞 たった, 大きな
感動詞 へえ, うわー
接頭辞 名詞接頭辞 第, 初, 総, 新
接頭辞 動詞接頭辞 ぶっ(飛ばす), ぶん(投げる)
接頭辞 イ形容詞接頭辞 まっ(白い), 超
接頭辞 ナ形容詞接頭辞 無, 不, 非, 超
接尾辞 名詞性述語接尾辞 っぷり, 放題, 味
接尾辞 名詞性名詞接尾辞 以上, 辺り, 自体, ならでは
接尾辞 名詞性名詞助数辞 リットル, ワット, KB
接尾辞 名詞性特殊接尾辞 以内, 限り, 半, 都, 道, 府, 県
接尾辞 形容詞性述語接尾辞 たい, にくい, づらい
接尾辞 形容詞性名詞接尾辞 的だ, がちだ, 気味だ
接尾辞 動詞性接尾辞 あぐねる, ぶる, 掛ける, 得る
未定義語 その他
未定義語 カタカナ
未定義語 アルファベット hoge, fuga

optionの指定

-sを指定することでn-best解を得ることができる。

http://lotus.kuee.kyoto-u.ac.jp/nl-resource/jumanpp/jumanpp-manual-1.0.pdf

juman = Juman(option='-s 3') # 試しに3で実行
mlist = juman.analysis('今日は休みました')
for mrph in mlist.mrph_list():
    print(mrph.midasi)

実行結果

-    7   0   0   1   今日  今日/こんにち こんにち    今日  名詞  6   時相名詞    10  *   0   *   0   カテゴリ:時間|漢字|特徴量スコア:-2.51152|言語モデルスコア:-0.878094|形態素解析スコア:-3.38961|ランク:1;3
-   6   0   0   1   今日  今日/きょう    きょう   今日  名詞  6   人名  5   *   0   *   0   自動獲得:Wikipedia|Wikipedia人名|Wikipedia姓|漢字|特徴量スコア:-2.92364|言語モデルスコア:-0.878094|形態素解析スコア:-3.80174|ランク:2
-   5   0   0   1   今日  今日/きょう    きょう   今日  名詞  6   時相名詞    10  *   0   *   0   カテゴリ:時間|漢字|特徴量スコア:-2.51152|言語モデルスコア:-0.878094|形態素解析スコア:-3.38961|ランク:1;3
-   15  7;6;5   2   2   は は/は は は 助詞  9副助詞  2   *   0   *   0   特徴量スコア:0.462092|言語モデルスコア:-0.148804|形態素解析スコア:0.313288|ランク:1;2;3
-   34  15  3   4   休み  休む/やすむ    やすみ   休む  動詞  2   *   0   子音動詞マ行  9   基本連用形 8   特徴量スコア:-1.0917|言語モデルスコア:-1.12576|形態素解析スコア:-2.21746|ランク:1;2;3
-   75  34  5   7   ました   増す/ます   ました   ます  動詞  2   *   0   子音動詞サ行  5   タ形  10  反義:動詞:減らす/へらす;動詞:減る/へる|特徴量スコア:-0.280303|言語モデルスコア:-1.53912|形態素解析スコア:-1.81942|ランク:3
-   74  34  5   7   ました   ます/ます   ました   ます  接尾辞   14  動詞性接尾辞  7   動詞性接尾辞ます型 31  タ形  7特徴量スコア:0.202646|言語モデルスコア:-0.645681|形態素解析スコア:-0.443034|ランク:1;2

「今日」は「こんにち」の読みがランク1と3、「きょう」の読みがランク2。「ました」は「接尾辞」がランク1と3、「増す」がランク2に来ている。

-Bを指定することでBeam幅を指定する。デフォルトは5。

juman = Juman(option='-s 2')
mlist = juman.analysis('beam幅を指定')
[mrph.midasi for mrph in mlist.mrph_list()]

改定履歴

Author: Masato Watanabe, Date: 2019-1-12, 記事投稿