Julia で形態素解析 [awabi]
エゴサしていたら Julia 言語研究会 https://julialang.jp/ というサイトで、
Awabi.jl https://nakagami.blog.ss-blog.jp/2021-12-03 を使ってみた手順を書いていてくれていることを発見した。
Linux/macOS/Windows で Awabi.jl を使って形態素解析する手順
https://julialang.jp/2022/05/20/julia-morpher/
SageMaker Studio Lab で使う手順
https://julialang.jp/2022/05/22/julia-morpher2/
SageMaker Studio Lab でワードクラウド
https://julialang.jp/2022/05/28/wordcloud/
ありがたい。
(ありがたいがこのサイト5月後半に形態素解析に関する記事を立て続けに書いていて、頑張りすぎて続かなくなるんじゃないかと、ちょっと心配)
自分以外に果たして何人の人が動かしてみているだろう?というようなマイナーなライブラリの場合、手順通りにやって動作することを報告してくれるだけでも非常にありがたい。
世の中の人は、こんなしっかりした記事でなくても、やってみた系の記事をどんどん書いてくれるといいなって思ってる。
しかも、今回は Windows や SageMaker Studio Lab で動かすというバリエーションもあり。
(Windows では mecabrc の読み込みがちゃんとできてないんだな、とは思うが使えないことないみたいだから、とりあえずこのままでいっか)
Awabi.jl https://nakagami.blog.ss-blog.jp/2021-12-03 を使ってみた手順を書いていてくれていることを発見した。
Linux/macOS/Windows で Awabi.jl を使って形態素解析する手順
https://julialang.jp/2022/05/20/julia-morpher/
SageMaker Studio Lab で使う手順
https://julialang.jp/2022/05/22/julia-morpher2/
SageMaker Studio Lab でワードクラウド
https://julialang.jp/2022/05/28/wordcloud/
ありがたい。
(ありがたいがこのサイト5月後半に形態素解析に関する記事を立て続けに書いていて、頑張りすぎて続かなくなるんじゃないかと、ちょっと心配)
自分以外に果たして何人の人が動かしてみているだろう?というようなマイナーなライブラリの場合、手順通りにやって動作することを報告してくれるだけでも非常にありがたい。
世の中の人は、こんなしっかりした記事でなくても、やってみた系の記事をどんどん書いてくれるといいなって思ってる。
しかも、今回は Windows や SageMaker Studio Lab で動かすというバリエーションもあり。
(Windows では mecabrc の読み込みがちゃんとできてないんだな、とは思うが使えないことないみたいだから、とりあえずこのままでいっか)
形態素解析器awabi [awabi]
これは「自然言語処理 (NLP: Natural Language Processing) 2020 アドベントカレンダー」2日目の記事です
https://qiita.com/advent-calendar/2020/nlp
今年は、 awabi という MeCab 辞書を使って形態素解析を行う形態素解析器を書きました。
(MeCab や janome のように辞書を引いて形態素解析する形態素解析器は、辞書を構築する機能も持っていますが、辞書を構築する機能を MeCab に頼っているので、「形態素解析器を書きました」と断言するのは恥ずかしいのですが形態素解析はしているので・・・)
ことの始まりは、昨年、janome で MeCab の辞書を使うパッケージを書いたことです。
https://nakagami.blog.ss-blog.jp/2019-10-20
この時、
「ん?Common Prefix Search の部分は、MeCabの辞書を検索する処理を書けそうだし、あとは Lattice構造を作って最短経路を求めればいいのか。 形態素解析器がかけそうだぞ」
と感じました。
Rust を勉強し始めて、何か習作となるネタはないかなぁと考えた時に、形態素解析器のことを思い出して書いたのが Rust 版の(オリジナルの)awabi です。
https://nakagami.blog.ss-blog.jp/2020-03-15
その後、awabi を Python や、Elixir から使うラッパーを書いたり、Go や Python で再実装したりしました。
この日記の awabi カテゴリを見ると、https://nakagami.blog.ss-blog.jp/archive/c2306218653-1 断片的なメモがあります。
また Gist に、インストール方法、簡単なベンチマークなどを整理した文書を置きましたので、興味あったら、こちらを読んでください。
https://gist.github.com/nakagami/f718e4a5b08cc39d9902ed129fa69bc6
色々書いてみてよくわかったのは、「MeCab 速い」ということと、「辞書とロジックを分離した MeCab に先見の明あり」ということでした。
https://qiita.com/advent-calendar/2020/nlp
今年は、 awabi という MeCab 辞書を使って形態素解析を行う形態素解析器を書きました。
(MeCab や janome のように辞書を引いて形態素解析する形態素解析器は、辞書を構築する機能も持っていますが、辞書を構築する機能を MeCab に頼っているので、「形態素解析器を書きました」と断言するのは恥ずかしいのですが形態素解析はしているので・・・)
ことの始まりは、昨年、janome で MeCab の辞書を使うパッケージを書いたことです。
https://nakagami.blog.ss-blog.jp/2019-10-20
この時、
「ん?Common Prefix Search の部分は、MeCabの辞書を検索する処理を書けそうだし、あとは Lattice構造を作って最短経路を求めればいいのか。 形態素解析器がかけそうだぞ」
と感じました。
Rust を勉強し始めて、何か習作となるネタはないかなぁと考えた時に、形態素解析器のことを思い出して書いたのが Rust 版の(オリジナルの)awabi です。
https://nakagami.blog.ss-blog.jp/2020-03-15
その後、awabi を Python や、Elixir から使うラッパーを書いたり、Go や Python で再実装したりしました。
この日記の awabi カテゴリを見ると、https://nakagami.blog.ss-blog.jp/archive/c2306218653-1 断片的なメモがあります。
また Gist に、インストール方法、簡単なベンチマークなどを整理した文書を置きましたので、興味あったら、こちらを読んでください。
https://gist.github.com/nakagami/f718e4a5b08cc39d9902ed129fa69bc6
色々書いてみてよくわかったのは、「MeCab 速い」ということと、「辞書とロジックを分離した MeCab に先見の明あり」ということでした。
AWS 上で Open Data として公開された UniDic を使う [awabi]
https://aws.amazon.com/jp/blogs/news/published-unidic-mecab-on-aws-open-data/
これを使って、MeCab と awabi で形態素解析してみる。
ダウンロードするのに aws コマンド(awc_cli)が必要で、色々インストールの方法はあるけど、
例えば、Ubuntu2004 だったら apt で入れられる
/etc/mecabrc の dicdir の行を以下のように修正(上で展開したdirectory を指定)
表示形式が違うのは、 mecab は dicrc の node-format-unidic22 の値を見てフォーマットしているのに対して、(こういう時 MeCab って色々機能あるなぁ、と気づかされる) awabi は、辞書の feature にあるものをそのまま出しているからと思われる。
この、表示形式の違いは、今のままでいいかなと思っている。
これを使って、MeCab と awabi で形態素解析してみる。
ダウンロードするのに aws コマンド(awc_cli)が必要で、色々インストールの方法はあるけど、
例えば、Ubuntu2004 だったら apt で入れられる
$ sudo apt install awscli $ aws --version aws-cli/1.18.69 Python/3.8.5 Linux/5.4.0-48-generic botocore/1.16.19 $ aws s3 --no-sign-request cp s3://cotonoha-dic/unidic.zip ./ $ unzip unidic.zip
/etc/mecabrc の dicdir の行を以下のように修正(上で展開したdirectory を指定)
dicdir = /home/nakagami/unidic
$ echo 'すもももももももものうち' |mecab すもも 名詞,普通名詞,一般,,,,スモモ,李,すもも,スモモ,すもも,スモモ,和,,,,,,,体,スモモ,スモモ,スモモ,スモモ,0,C2,,15660352771596800,56972 も 助詞,係助詞,,,,,モ,も,も,モ,も,モ,和,,,,,,,係助,モ,モ,モ,モ,,動詞%F2@-1,形容詞%F4@-2,名詞%F1,,10324972564259328,37562 もも 名詞,普通名詞,一般,,,,モモ,桃,もも,モモ,もも,モモ,和,,,,,,,体,モモ,モモ,モモ,モモ,0,C3,,10425303000293888,37927 も 助詞,係助詞,,,,,モ,も,も,モ,も,モ,和,,,,,,,係助,モ,モ,モ,モ,,動詞%F2@-1,形容詞%F4@-2,名詞%F1,,10324972564259328,37562 もも 名詞,普通名詞,一般,,,,モモ,桃,もも,モモ,もも,モモ,和,,,,,,,体,モモ,モモ,モモ,モモ,0,C3,,10425303000293888,37927 の 助詞,格助詞,,,,,ノ,の,の,ノ,の,ノ,和,,,,,,,格助,ノ,ノ,ノ,ノ,,名詞%F1,,7968444268028416,28989 うち 名詞,普通名詞,副詞可能,,,,ウチ,内,うち,ウチ,うち,ウチ,和,,,,,,,体,ウチ,ウチ,ウチ,ウチ,0,C3,,881267193291264,3206 EOS
$ echo 'すもももももももものうち' |awabi すもも 名詞,普通名詞,一般,*,*,*,スモモ,李,すもも,スモモ,すもも,スモモ,和,*,*,*,*,*,*,体,スモモ,スモモ,スモモ,スモモ,0,C2,*,15660352771596800,56972 も 助詞,係助詞,*,*,*,*,モ,も,も,モ,も,モ,和,*,*,*,*,*,*,係助,モ,モ,モ,モ,*,"動詞%F2@-1,形容詞%F4@-2,名詞%F1",*,10324972564259328,37562 もも 名詞,普通名詞,一般,*,*,*,モモ,桃,もも,モモ,もも,モモ,和,*,*,*,*,*,*,体,モモ,モモ,モモ,モモ,0,C3,*,10425303000293888,37927 も 助詞,係助詞,*,*,*,*,モ,も,も,モ,も,モ,和,*,*,*,*,*,*,係助,モ,モ,モ,モ,*,"動詞%F2@-1,形容詞%F4@-2,名詞%F1",*,10324972564259328,37562 もも 名詞,普通名詞,一般,*,*,*,モモ,桃,もも,モモ,もも,モモ,和,*,*,*,*,*,*,体,モモ,モモ,モモ,モモ,0,C3,*,10425303000293888,37927 の 助詞,格助詞,*,*,*,*,ノ,の,の,ノ,の,ノ,和,*,*,*,*,*,*,格助,ノ,ノ,ノ,ノ,*,名詞%F1,*,7968444268028416,28989 うち 名詞,普通名詞,副詞可能,*,*,*,ウチ,内,うち,ウチ,うち,ウチ,和,*,*,*,*,*,*,体,ウチ,ウチ,ウチ,ウチ,0,C3,*,881267193291264,3206 EOS
表示形式が違うのは、 mecab は dicrc の node-format-unidic22 の値を見てフォーマットしているのに対して、(こういう時 MeCab って色々機能あるなぁ、と気づかされる) awabi は、辞書の feature にあるものをそのまま出しているからと思われる。
この、表示形式の違いは、今のままでいいかなと思っている。
Elixir から、形態素解析器 awabi を呼ぶ [awabi]
PyO3 で Rust のコードを Python から簡単に呼び出せたけど
https://nakagami.blog.ss-blog.jp/2020-03-21
https://nakagami.blog.ss-blog.jp/2020-07-08-1
https://nakagami.blog.ss-blog.jp/2020-07-11
・・・そう言えば、同じように Rust のコードを簡単に Elixir の NIF にして
呼べるようなのがあったんじゃなかったっけ?と思って、探した.
Rustler っていうのがそれらしい
https://github.com/rusterlium/rustler
これを参考にして・・・
Writing Rust NIFs for Elixir With Rustler
https://simplabs.com/blog/2020/06/25/writing-rust-nifs-for-elixir-with-rustler/
- mix new exawabi
- {:rustler, "~> 0.22-rc"} を mix.exs の deps に加える
- mix deps.get
- mix rustler.new
・・・を実行して, mix rustler.new の中で聞かれる問いに
Module name に「ExAwabi」
Library name に「awabi_nif」
を指定して、できたファイルに、色々修正してできたのがこれ
- https://github.com/nakagami/exawabi
- https://hex.pm/packages/exawabi
・・・と、簡単には書いているが、途中、色々試行錯誤してしまった。
上の記事では、 mix.exs の修正についての説明がないが、 Rustler 向けの記述をいくつか追加した。
https://github.com/nakagami/exawabi/blob/master/mix.exs
の compilers とか、 rustler_crates のあたり。
Elixir の該当コードを見ると https://github.com/nakagami/exawabi/blob/master/lib/exawabi.ex
エラー関数を呼んでいるよには見えるけど、 Rust の関数を呼んでいるように見えなくて、
なんか、よくわかんないけど、マクロすごい・・・と思っているところ。
Elixir だと、関数として実装しないといけないので(クラスとかメソッドの形で Elixir にExportできないので)制限はあるけど、簡単に NIF が作れるというのは本当だなと思った。
C で NIF 作る気はしないけど、Rust でならできそう。
・・・で、できたもの
https://hexdocs.pm/exawabi/ExAwabi.html
https://github.com/nakagami/exawabi
https://nakagami.blog.ss-blog.jp/2020-03-21
https://nakagami.blog.ss-blog.jp/2020-07-08-1
https://nakagami.blog.ss-blog.jp/2020-07-11
・・・そう言えば、同じように Rust のコードを簡単に Elixir の NIF にして
呼べるようなのがあったんじゃなかったっけ?と思って、探した.
Rustler っていうのがそれらしい
https://github.com/rusterlium/rustler
これを参考にして・・・
Writing Rust NIFs for Elixir With Rustler
https://simplabs.com/blog/2020/06/25/writing-rust-nifs-for-elixir-with-rustler/
- mix new exawabi
- {:rustler, "~> 0.22-rc"} を mix.exs の deps に加える
- mix deps.get
- mix rustler.new
・・・を実行して, mix rustler.new の中で聞かれる問いに
Module name に「ExAwabi」
Library name に「awabi_nif」
を指定して、できたファイルに、色々修正してできたのがこれ
- https://github.com/nakagami/exawabi
- https://hex.pm/packages/exawabi
・・・と、簡単には書いているが、途中、色々試行錯誤してしまった。
上の記事では、 mix.exs の修正についての説明がないが、 Rustler 向けの記述をいくつか追加した。
https://github.com/nakagami/exawabi/blob/master/mix.exs
の compilers とか、 rustler_crates のあたり。
Elixir の該当コードを見ると https://github.com/nakagami/exawabi/blob/master/lib/exawabi.ex
エラー関数を呼んでいるよには見えるけど、 Rust の関数を呼んでいるように見えなくて、
なんか、よくわかんないけど、マクロすごい・・・と思っているところ。
Elixir だと、関数として実装しないといけないので(クラスとかメソッドの形で Elixir にExportできないので)制限はあるけど、簡単に NIF が作れるというのは本当だなと思った。
C で NIF 作る気はしないけど、Rust でならできそう。
・・・で、できたもの
https://hexdocs.pm/exawabi/ExAwabi.html
https://github.com/nakagami/exawabi
pure python の形態素解析器 pure-pyawabi [awabi]
この時 https://nakagami.blog.ss-blog.jp/2020-07-11 にも書いたが、 pip install で awabi が python から使えるようになったものの、Rust とか、 python3-dev とかインストールしないといけなくて、簡単に使うにしては、ちょっとハードル高いなぁ、と思っていた。
先日、ふと
「(もう一回実装するのは面倒だけど)awabi を python に移植(=書き直し)すればいいんじゃない?」
ということに気づいた。処理は遅いだろうけど。
ということで、とりあえず動くところまでできた。
- https://github.com/nakagami/pure-pyawabi/
- https://pypi.org/project/pure-pyawabi/
pyawabi と pure-pyawabi に(共通の)最低限の API しかないが、もうちょい使いやすい API を用意したいと思っている。
先日、ふと
「(もう一回実装するのは面倒だけど)awabi を python に移植(=書き直し)すればいいんじゃない?」
ということに気づいた。処理は遅いだろうけど。
ということで、とりあえず動くところまでできた。
- https://github.com/nakagami/pure-pyawabi/
- https://pypi.org/project/pure-pyawabi/
pyawabi と pure-pyawabi に(共通の)最低限の API しかないが、もうちょい使いやすい API を用意したいと思っている。
awabi が、MeCab と同じ結果を返すようになった [awabi]
Rust 製の形態素解析器 awabi
https://nakagami.blog.ss-blog.jp/2020-03-15
と、Go製の goawabi
https://nakagami.blog.ss-blog.jp/2020-04-11
スペースが含まれる文章で、 MeCab と違う結果を返していて、できれば、 MeCab と同じ結果を返したいなぁと思っていたが、昨日、無事修正できて、とりあえず自分の認識している範囲ではMeCab と同じ結果を返すようになった。
pyawabi https://nakagami.blog.ss-blog.jp/2020-07-11 は、更新された awabi を使うので、同じく、MeCab と同じ結果を返すはず。
違う結果を返す文字列があったら教えて欲しいと思っている。
https://nakagami.blog.ss-blog.jp/2020-03-15
と、Go製の goawabi
https://nakagami.blog.ss-blog.jp/2020-04-11
スペースが含まれる文章で、 MeCab と違う結果を返していて、できれば、 MeCab と同じ結果を返したいなぁと思っていたが、昨日、無事修正できて、とりあえず自分の認識している範囲ではMeCab と同じ結果を返すようになった。
pyawabi https://nakagami.blog.ss-blog.jp/2020-07-11 は、更新された awabi を使うので、同じく、MeCab と同じ結果を返すはず。
違う結果を返す文字列があったら教えて欲しいと思っている。
setuptools-rust で pyawabi のパッケージを作る [awabi]
stable な Rust で、Rust のソースから Python のモジュールをコンパイルできるようになったが https://nakagami.blog.ss-blog.jp/2020-07-08-1
考えてみると、 Rust でコンパイルした .so を名前を変えて PYTHONPATH にコピーするの面倒だな。
そもそも、それだと pip でインストールできなくて、 Python のエコシステムに乗れない。
なんかあるんだろうなぁ、と思って探したら PyO3 のOrganization にあった
https://github.com/PyO3/setuptools-rust
色々試行錯誤して、モジュール名も調整して pypi にアップロードできた
https://pypi.org/project/pyawabi/
wheel binary を用意してあげるといいんだろうけど、バイナリは Python のバージョンごとにビルドしないといけないし、少なくとも Linux と Windows のバイナリは用意しないといけないだろうし、 Python のバージョンが毎年上がるのにバイナリ作るの大変そうなので、ソースだけ置いておくことにする。
考えてみると、 Rust でコンパイルした .so を名前を変えて PYTHONPATH にコピーするの面倒だな。
そもそも、それだと pip でインストールできなくて、 Python のエコシステムに乗れない。
なんかあるんだろうなぁ、と思って探したら PyO3 のOrganization にあった
https://github.com/PyO3/setuptools-rust
色々試行錯誤して、モジュール名も調整して pypi にアップロードできた
https://pypi.org/project/pyawabi/
wheel binary を用意してあげるといいんだろうけど、バイナリは Python のバージョンごとにビルドしないといけないし、少なくとも Linux と Windows のバイナリは用意しないといけないだろうし、 Python のバージョンが毎年上がるのにバイナリ作るの大変そうなので、ソースだけ置いておくことにする。
Go製の形態素解析器 goawabi [awabi]
Go言語は、辞書を内包した形態素解析器 kagome というのが使われていて、これから形態素解析器書いても、出る幕ないだろうなぁと思っていた。
先月、Rust 製の形態素解析器 awabi を書いた。
https://nakagami.blog.ss-blog.jp/2020-03-15
・・・ん?これは、もしかして golang に移植できるんじゃない?
と思って、Go言語の復習をかねて試みてみることにした。
Mmap で MeCab の辞書を読めそうだぞということになって、
あとは、割と Rust の実装を一対一に移植していったらできた。
https://github.com/nakagami/goawabi
先月、Rust 製の形態素解析器 awabi を書いた。
https://nakagami.blog.ss-blog.jp/2020-03-15
・・・ん?これは、もしかして golang に移植できるんじゃない?
と思って、Go言語の復習をかねて試みてみることにした。
Mmap で MeCab の辞書を読めそうだぞということになって、
あとは、割と Rust の実装を一対一に移植していったらできた。
https://github.com/nakagami/goawabi
Rust 製の形態素解析器 awabi の python ラッパー pyawabi [awabi]
Rust製の形態素解析器awabi https://nakagami.blog.ss-blog.jp/2020-03-15 は、
形態素解析している部分はライブラリークレートになっているので、ほかから使うことができる。
Rust でPython のモジュールが書ける PyO3 というのがあるので、 Python モジュールにして Python から形態素解析できることを目指してみた。
できたのがこれ↓
https://github.com/nakagami/pyawabi
モジュールの中に(クラスのインスタンスなど複雑な形式じゃなくて)プリミティブな型の組み合わせの結果を返すだけの関数を実装するだけであれば、比較的簡単にできた。
今回の例では、「文字列と文字列のタプルのリストのリスト」は、Rust の関数の結果値を返すだけでうまく動いた。
難点を上げるとすると、PyO3 がいまだに Rust のnightly ビルドじゃないと動かないこと https://github.com/PyO3/pyo3/issues/5 と
できあがった.so ファイルを(ファイル名をちょっと変えて)python のパスが通るところにコピーしないといけないのが、ちょっと面倒ということかな。
Python の C拡張は、リファレンスカウントの扱いとか、文字列のマーシャリングとか、僕には難しくて、これなら python から使えて速度が必要な処理はRust で書けばいいんじゃないか?と思う今日この頃
形態素解析している部分はライブラリークレートになっているので、ほかから使うことができる。
Rust でPython のモジュールが書ける PyO3 というのがあるので、 Python モジュールにして Python から形態素解析できることを目指してみた。
できたのがこれ↓
https://github.com/nakagami/pyawabi
モジュールの中に(クラスのインスタンスなど複雑な形式じゃなくて)プリミティブな型の組み合わせの結果を返すだけの関数を実装するだけであれば、比較的簡単にできた。
今回の例では、「文字列と文字列のタプルのリストのリスト」は、Rust の関数の結果値を返すだけでうまく動いた。
難点を上げるとすると、PyO3 がいまだに Rust のnightly ビルドじゃないと動かないこと https://github.com/PyO3/pyo3/issues/5 と
できあがった.so ファイルを(ファイル名をちょっと変えて)python のパスが通るところにコピーしないといけないのが、ちょっと面倒ということかな。
Python の C拡張は、リファレンスカウントの扱いとか、文字列のマーシャリングとか、僕には難しくて、これなら python から使えて速度が必要な処理はRust で書けばいいんじゃないか?と思う今日この頃
Rust 製の形態素解析器 awabi [awabi]
Rust の習作として Rust 製の形態素解析器 awabi を書きました。
https://github.com/nakagami/awabi
MeCab の辞書を使って形態素解析をするので、MeCab 辞書のインストールが必要です。
使用に際しては、辞書の登録のために、MeCab も必要だと思います。
ちょっとうごかしてみた感じでは、動いてそうです。
不具合あったら教えて欲しいです。
不具合を修正する Pull Request くれたら、もっとうれしいです。
- ビルドすると、 warning がいっぱい出るけど、これ、どうやって直すの?
- コメントとかドキュメントとか、整備したい
- 機能を追加したい
とか、いろいろ課題あるんですが、 crates.io に登録して、ソースを公開しておきます。
https://github.com/nakagami/awabi
MeCab の辞書を使って形態素解析をするので、MeCab 辞書のインストールが必要です。
使用に際しては、辞書の登録のために、MeCab も必要だと思います。
ちょっとうごかしてみた感じでは、動いてそうです。
不具合あったら教えて欲しいです。
不具合を修正する Pull Request くれたら、もっとうれしいです。
- ビルドすると、 warning がいっぱい出るけど、これ、どうやって直すの?
- コメントとかドキュメントとか、整備したい
- 機能を追加したい
とか、いろいろ課題あるんですが、 crates.io に登録して、ソースを公開しておきます。