”MeCab以外からneologd辞書を使えるようにする”のが今回のテーマ.
とはいえ,mecab辞書と形式が違うために,除外しなければならないワードもあり,neologd辞書をそのまま使えるように
したわけではありません.その点を注意していただきたいと思います.
また,”ユーザ名”やパスは各々の環境に合わせて適宜変更してください.
あと,コードブロックが見づらいかもしれません...よい書き方知っている方がいれば教えてください!
事前にやっておくべきこと
mecab辞書の形式
ipadic-neologd辞書は
表層形,左文脈ID,右文脈ID,コスト,品詞,品詞細分類1,品詞細分類2,品詞細分類3,活用型,活用形,原形,読み,発音
といった形式で,これを考慮して,各形態素解析器の辞書の形式に変換する必要があります.
やっていなっかたら,やっておくべき注意点
juman++には推奨ライブラリがあり,これらをインストールした後にインストールしたjuman++でないと,辞書のインストール自体は成功しても,jumanpp
コマンドが使えず,juman++での形態素解析ができなくなります.
なので,ユーザ辞書の追加には,推奨ライブラリは事前に入れておくべき必須ツールです.少なくとも,私の環境かでは,インストールし直したことで,改善できました.
ちなみに,推奨ライブラリは以下の3つです.いずれも最新版のインストールでよいかと思います.
- libunwind
- gperftools
- Boost
以上のライブラリの導入は以下の過去記事に書きましたので,参照してください. 推奨ライブラリを入れずにjuman++をインストールした場合,推奨ライブラリをインストールしてから再度同じステップでjuman++をインストールしましょう.
この工程をやらないと,辞書登録後のjumanpp
コマンドで
terminate called after throwing an instance of 'std::out_of_range' what(): _Map_base::at
もしくはSegmantation Fault
と表示されて,解析できないので気を付けましょう.
新たにインストールするモジュール
$ pip install mojimoji $ pip install jaconv $ sudo apt-get install zsh
というように,必要なモジュールは用意・アップデートしておきましょう.
”jaconv”は正規化処理などに使うモジュールで,日本語処理において必須と言えそうなツールのようなので,この際に入れておいた方がよいかもしれませんね.
また,/dict-build/userdic
内にあるdummy.dic
は削除しておきましょう.0バイトのファイルなんで,特に置いておく必要はないと思います.
neologd2jumanを使う場合の注意
本記事のように自分でスクリプトとフォルダを作るのではなく,すでに公開されているモジュール”neologd2juman”を使う場合に関して, まず,インストールして,モジュールを使う方法は
$ git clone https://github.com/fumankaitori/neologd2juman.git $ cd neologd2juman $ sudo make
です.注意点として,デフォルトのPythonの環境が3.7以降の場合はneologd2juman.pyでエラーが出ると思いますので,
def my_csv_reader(csv_reader): """ NULL回避のためのcsvジェネレータ :return: """ while True: try: yield next(csv_reader) except csv.Error: pass except StopIteration: return
というように'StopIteration'を追加したほうがよいです.
スクリプト
以下のスクリプトをまとめた”neologd2jumanpp_and_kytea”フォルダ(フォルダ名は各々好きなものにしてかまいません)を端末から開きsudo make
を実行すれば,Neologd辞書のダウウンロードから,mecabへのインストール,kyteaの辞書作り+辞書学習,juman++用の辞書作成と
ファルダへの移動まで一括して行います.この後に,juman++への辞書登録をやりましょう.
Makefile
install: wget --no-check-certificate https://github.com/neologd/mecab-ipadic-neologd/tarball/master -O mecab-ipadic-neologd.tar tar -xvf mecab-ipadic-neologd.tar rm -rf /home/ユーザ名/neologd-mecab-ipadic-neologd-* mv neologd-mecab-ipadic-neologd-* /home/hiro/ wget --no-check-certificate https://github.com/neologd/mecab-unidic-neologd/tarball/master -O mecab-unidic-neologd.tar tar -xvf mecab-unidic-neologd.tar rm -rf /home/ユーザ名/neologd-mecab-unidic-neologd-* mv neologd-mecab-unidic-neologd-* /home/ユーザ名/ # mecabにneologd辞書をインストール sudo /home/ユーザ名/neologd-mecab-ipadic-neologd-*/bin/install-mecab-ipadic-neologd -n -a -y sudo /home/ユーザ名/neologd-mecab-unidic-neologd-*/bin/install-mecab-unidic-neologd -n -y # csvファイルに変換 sudo xz -dc /home/ユーザ名/neologd-mecab-ipadic-neologd-*/seed/mecab-user-dict-seed.*.csv.xz > mecab-ipadic-user-dict-seed.csv sudo xz -dc /home/ユーザ名/neologd-mecab-unidic-neologd-*/seed/mecab-unidic-user-dict-seed.*.csv.xz > mecab-unidic-user-dict-seed.csv # kytea用に辞書作成し、学習させる /home/ユーザ名/anaconda3/bin/python kytea_make_unidic_dict.py mecab-unidic-user-dict-seed.csv kytea-unidic-user-dict.txt train-kytea -full train.txt -dict kytea-unidic-user-dict.txt -model train.model # jumanpp用に辞書作成し、辞書をインストール /home/ユーザ名/anaconda3/bin/python ipadic_neologd2juman.py mecab-ipadic-user-dict-seed.csv jumanpp-ipadic-neologd-dict rm -rf /home/ユーザ名/jumanpp-1.02/dict-build/userdic/jumanpp-ipadic-neologd-dict-*.dic sudo chmod a=rwx jumanpp-ipadic-neologd-dict-*.dic mv jumanpp-ipadic-neologd-dict-*.dic /home/ユーザ名/jumanpp-1.02/dict-build/userdic/
/home/ユーザ名/anaconda3/bin/python
という風にしないと,Ubuntuに元々入っているPythonでスクリプトを実行しようとしてエラーになります.pip
で入れたモジュールがAnaconda内にあるため,モジュール使用できずに起こるエラーだと思われます.
なので,インストールしたAnacondaの中のPythonを指定し,それでスクリプトを実行してもらうように,以上のような/home/ユーザ名/anaconda3/bin/python
とします.標準ライブラリだけでできてるスクリプトならこのような変更はいらないんですけど,pip
やconda
でインストールしたモジュールを使うスクリプトをMakeファイルとかで呼び出して使う場合はこのような変更が必要です.
他にいい方法があったら教えてください~
ipadic_neologd2juman.py:ipadic-neologd辞書のcsvファイルをjuman形式にした辞書の作成するスクリプト
#-*- coding:utf-8 -*- import sys import jaconv def System_Message(i): if i != 0 and i % 100000 == 0: sys.stderr.write("{}M lines done\n".format(i / 1000000)) elif i != 0 and i % 10000 == 0: sys.stderr.write(".") sys.stderr.flush() dic = sys.argv[1] file_name = sys.argv[2] with open(dic,mode='r',encoding='utf-8') as d: for i,line in enumerate(d): if 'カッコカッコ' in line: continue if 'カオモジ' in line: kaomoji = True else: kaomoji = False line = line.split(',') if line[4] == '記号': if kaomoji: with open(file_name+'-kaomoji.dic',mode='a',encoding="utf-8") as f: f.write('(特殊 (記号 ((読み {0})(見出し語 {1})(意味情報 "顔文字"))))\n'.format(line[0],line[-3])) else: with open(file_name+'-emoji.dic',mode='a',encoding="utf-8") as f: f.write('(特殊 (記号 ((読み {0})(見出し語 {1})(意味情報 "代表表記:{2}/* 絵文字"))))\n'.format(jaconv.kata2hira(jaconv.h2z(line[-2])),line[0],line[-3])) System_Message(i) continue # 排除対象 if ' ' in line[0]: continue if '(' in line[0]: continue if ')' in line[0]: continue if line[4] == "名詞": if line[5] == "固有名詞": if line[6] == "人名": with open(file_name+'-noun.dic',mode='a',encoding="utf-8") as f: f.write('(名詞 (人名 ((読み {0})(見出し語 {1})(意味情報 "人名"))))\n'.format(jaconv.kata2hira(jaconv.h2z(line[-2])),line[0])) if line[6] == "地域": with open(file_name+'-noun.dic',mode='a',encoding="utf-8") as f: f.write('(名詞 (地名 ((読み {0})(見出し語 {1})(意味情報 "代表表記:{2}/{3} 地名"))))\n'.format(jaconv.kata2hira(jaconv.h2z(line[-2])),line[0],line[-3],jaconv.kata2hira(jaconv.h2z(line[-2])))) if line[6] == "組織": with open(file_name+'-noun.dic',mode='a',encoding="utf-8") as f: f.write('(名詞 (組織名 ((読み {0})(見出し語 {1})(意味情報 "代表表記:{2}/{3}"))))\n'.format(jaconv.kata2hira(jaconv.h2z(line[-2])),line[0],line[-3],jaconv.kata2hira(jaconv.h2z(line[-2])))) else: with open(file_name+'-noun.dic',mode='a',encoding="utf-8") as f: f.write('(名詞 (固有名詞 ((見出し語 {0}) (読み {1}) (意味情報 "代表表記:{2}/{3}"))))\n'.format(line[0],jaconv.kata2hira(jaconv.h2z(line[-2])),line[-3],jaconv.kata2hira(jaconv.h2z(line[-2])))) System_Message(i) continue else: # 一般名詞 if line[5] == "一般": with open(file_name+'-noun.dic',mode='a',encoding="utf-8") as f: f.write('(名詞 (普通名詞 ((読み {0})(見出し語 {1})(意味情報 "代表表記:{2}/{3}"))))\n'.format(jaconv.kata2hira(jaconv.h2z(line[-2])),line[0],line[-3],jaconv.kata2hira(jaconv.h2z(line[-2])))) elif line[5] == "サ変接続": with open(file_name+'-noun.dic',mode='a',encoding="utf-8") as f: f.write('(名詞 (サ変名詞 ((読み {0})(見出し語 {1})(意味情報 "代表表記:{2}/{3}"))))\n'.format(jaconv.kata2hira(jaconv.h2z(line[-2])),line[0],line[-3],jaconv.kata2hira(jaconv.h2z(line[-2])))) if line[4] == "副詞": with open(file_name+'-fukushi.dic',mode='a',encoding="utf-8") as f: f.write('(副詞 ((読み {0})(見出し語 {1})(意味情報 "代表表記:{2}/{3} 副詞識別")))\n'.format(jaconv.kata2hira(jaconv.h2z(line[-2])),line[0],line[-3],jaconv.kata2hira(jaconv.h2z(line[-2])))) if line[4] == "形容詞": with open(file_name+'-keiyoshi.dic',mode='a',encoding="utf-8") as f: f.write('(形容詞 ((読み {0})(見出し語 {1})(意味情報 "代表表記:{2}/{3}")))\n'.format(jaconv.kata2hira(jaconv.h2z(line[-2])),line[0],line[-3],jaconv.kata2hira(jaconv.h2z(line[-2])))) sys.stderr.write("{} lines done\n".format(i))
ファイル名は”ipadic_neologd2juman.py”としておくか,違うファイル名にする場合はMakefile内の該当箇所を変更しておいてください.
kytea_make_unidic_dict.py:ipadic-neologd辞書のcsvファイルをjuman形式にした辞書の作成するスクリプト
kytea_make_unidic_dict.pyは,コマンドライン引数を使ったPythonスクリプトになります.コマンドライン引数について,以下を参考にしました.何故”ipadic”辞書はkytea用に作らないかと申しますと,作ってtrain-kytea
をやったのですが,エラーがどうしても出ちゃうんですよ.なのでipadic辞書の方はkyteaに学習させません.おそらく,kyteaはipadic形式が使えないのかもしれません.
#-*- coding:utf-8 -*- import sys dic = sys.argv[1] file_name = sys.argv[2] with open(file_name,mode='w',encoding="utf-8") as f: with open(dic,mode='r',encoding='utf-8') as d: for i,line in enumerate(d): line = line.split(',') if line[4] == '記号': continue elif line[5] == '固有名詞': pos = line[5] else: pos = line[4] f.write(line[0] + '/' + pos + '/' + line[10]) # System Message if i != 0 and i % 100000 == 0: sys.stderr.write("{}M lines done\n".format(i / 1000000)) elif i != 0 and i % 10000 == 0: sys.stderr.write(".") sys.stderr.flush() sys.stderr.write("{} lines done\n".format(i))
ファイル名は”kytea_make_unidic_dict.py”としておくか,違うファイル名にする場合はMakefile内の該当箇所を変更しておいてください.
train.txt:kytea用のコーパスデータ
コーパス/名詞/こーぱす の/助詞/の 文/名詞/ぶん で/助動詞/で す/語尾/す 。/補助記号/。 もう/副詞/もう ひと/名詞/ひと つ/接尾辞/つ の/助詞/の 文/名詞/ぶん で/補助記号/で す/語尾/す 。/補助記号/。
のようなテキストデータを作ります. ファイル名は”train.txt”としておくか,違うファイル名にする場合はMakefile内の該当箇所を変更しておいてください.
juman++への辞書登録
以上のスクリプトをまとめたフォルダ内でsudo make
実行後,”/home/ユーザ名/jumanpp-1.02/dict-build”へ移動して,そこで
sudo make sudo ./install.sh
というコマンドを実行します.sudo make
で軽く一時間かかるかと思います.以上でそのまんまではないですが,neologd辞書を
mecab以外から使えるようになりました.
試用
juman++
野獣先輩が走る。 野獣先輩 やじゅうせんぱい 野獣先輩 名詞 6 固有名詞 3 * 0 * 0 "代表表記:野獣先輩/やじゅうせんぱい" が が が 助詞 9 格助詞 1 * 0 * 0 NIL 走る はしる 走る 動詞 2 * 0 子音動詞ラ行 10 基本形 2 "代表表記:走る/はしる" 。 。 。 特殊 1 句点 1 * 0 * 0 NIL EOS !!( ; ロ)゚ ゚ !! !! !! 未定義語 15 その他 1 * 0 * 0 "品詞推定:名詞" ( ( ( 未定義語 15 その他 1 * 0 * 0 "品詞推定:名詞" \ \ \ 特殊 1 空白 6 * 0 * 0 "代表表記: / " ;\ ;\ ;\ 未定義語 15 その他 1 * 0 * 0 "品詞推定:名詞" ロ ロ ロ 未定義語 15 その他 1 * 0 * 0 "品詞推定:名詞" ) ) ) 未定義語 15 その他 1 * 0 * 0 "品詞推定:名詞" ゚ ; ゚ 特殊 1 記号 5 * 0 * 0 "顔文字" @ ゚ ゚ ゚ 特殊 1 記号 5 * 0 * 0 "顔文字" @ ゚ Д ゚ 特殊 1 記号 5 * 0 * 0 "顔文字" @ ゚ !! ゚ 特殊 1 記号 5 * 0 * 0 "顔文字" \ \ \ 特殊 1 空白 6 * 0 * 0 "代表表記: / " ゚ ; ゚ 特殊 1 記号 5 * 0 * 0 "顔文字" @ ゚ ゚ ゚ 特殊 1 記号 5 * 0 * 0 "顔文字" @ ゚ Д ゚ 特殊 1 記号 5 * 0 * 0 "顔文字" @ ゚ !! ゚ 特殊 1 記号 5 * 0 * 0 "顔文字"
固有名詞である”野獣先輩”がjuman++で認識されて処理されていることが分かります.しかし,顔文字の認識がうまくいってないです.辞書へはneologd辞書のまんまの半角で登録したのがダメだったのかな...
kytea
train-kytea
で次のように表示されます.
Scanning dictionaries and corpora for vocabulary Reading corpus from train.txt done (14 lines) Reading dictionary from kytea-unidic-user-dict.txt WARNING - empty training data specified. Building dictionary index done! Creating word segmentation features done! Building classifier done! Creating tagging features (tag 1) done! Training local tag classifiers done! Creating tagging features (tag 2) done! Training local tag classifiers done! Printing model to train.model done!
この後,この結果で形態素解析したい場合はkytea -nows
とコマンド入力してください.kytea
だとモデル学習してない通常のkytea状態での形態素解析になります.
また,WARNING - empty training data specified
とあるように,用意したコーパスが不十分なようで,滅茶苦茶な形態素解析になります.例えば,
$ kytea 野獣先輩と海 野獣/名詞/やじゅう 先輩/名詞/せんぱい と/助詞/と 海/名詞/うみ $ kytea -nows 野獣先輩と海 野獣先輩と海/URL/のけものさきはいとうみ
という感じ.コーパスも合うものを用意または自作するしかないようですね...いい塩梅の学習用コーパスがあれば頂きたいですね~
参考
- Juman++(1.02)でユーザー辞書を登録(Mac => Vagrant => Ubuntu16.04) - Qiita
- juman++ 1.02内のりどみと辞書ファイル
- neologd辞書をjuman/juman++で使えるようにするスクリプト作った - Qiita
- 自然言語処理をテストする環境を整えるまでの手順① - Qiita
- GitHub - fumankaitori/neologd2juman: Support tool to convert neologd-ipadic into Juman-dic
- mecab-ipadic-neologd/README.ja.md at master · neologd/mecab-ipadic-neologd · GitHub
- 形態素解析ツールの品詞体系
- MeCab: 単語の追加方法
- Releases · ku-nlp/jumanpp · GitHub
- configure, make, make install とは何か - Qiita
- makeでコンパイルしよう - 愚鈍人
- Python: コマンドライン引数とは?(超基礎) - Qiita
- Python 3.7 ではGeneretor で StopIteration を使うと RuntimeError になる - Qiita
- 「sudo: pip: コマンドが見つかりません」というエラー - ストックドッグ
- pip installしたはずなのにImport errorと言われた場合 - Qiita
- sudoコマンドでaliasを使えるようにする - Qiita
- Juman++(1.02)でユーザー辞書を登録(Mac => Vagrant => Ubuntu16.04) - Qiita