TL;DR
- Pythonで形態素解析をしたい
-
mecab-python3も良いが、MeCabを入れたりするのは避けたい
- 要は、
pip
で完結させたい
- 要は、
- Janomeを使うのがいいのではないだろうか
Janome
Pythonで実装された、形態素解析器だそうです。
作者様は、Apache Luceneのコミッターをされていらっしゃいますね。
APIリファレンスは、こちら。
以下の特徴を持つようです。
- Python 2.7または3.3以上で動作
-
Tokenizer
を使った、形態素解析ライブラリ -
janome
スクリプトを使用したコマンドラインでの実行が可能 - デフォルトの辞書は
mecab-ipadic-2.7.0-20070801
- ユーザー定義辞書の利用
-
mmap
のサポート - Graphvizファイルの作成
-
Analyzer
フレームワーク(experimental)
などなど。
Q&Aにもありますが、速度自体はMeCabには敵わないようなので、用途に合わないようであればMeCabを使用する方がよいでしょう。
環境
今回の環境は、こちらです。
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 18.04.3 LTS
Release: 18.04
Codename: bionic
$ python3 -V
Python 3.6.8
この環境に、Janomeをインストールして簡単に形態素解析して遊んでみます。
Janomeのインストール
pip
でインストールすれば完了です。
$ pip3 install janome
今回のJanomeのバージョンは、こちら。
$ pip3 freeze
Janome==0.3.9
Tokenizer
を使う
では、ドキュメントを見ながら、まずはTokenizer
を使ってみましょう。
サンプルコード。
hello_tokenizer.py
from janome.tokenizer import Tokenizer
tokenizer = Tokenizer()
sentenses = [
"ギョエェェエーと叫ぶだけの人生だった。",
"最終兵器は懐にしまいます。",
"お前は助からない。",
"ログを読め。",
"さあご一緒に!「TRUE 1 が TRUE! TRUE 0 が FALSE!」"
]
for sentence in sentenses:
print("=============================================")
print(sentence)
for token in tokenizer.tokenize(sentence):
print(" " + str(token))
Tokenizer
のインスタンスを作成して
tokenizer = Tokenizer()
形態素解析したい文字列をtokenize
メソッドに渡せばOKです。
for token in tokenizer.tokenize(sentence):
実行結果。
$ python3 hello_tokenizer.py
=============================================
ギョエェェエーと叫ぶだけの人生だった。
ギョエェェエー 名詞,一般,*,*,*,*,ギョエェェエー,*,*
と 助詞,格助詞,一般,*,*,*,と,ト,ト
叫ぶ 動詞,自立,*,*,五段・バ行,基本形,叫ぶ,サケブ,サケブ
だけ 助詞,副助詞,*,*,*,*,だけ,ダケ,ダケ
の 助詞,連体化,*,*,*,*,の,ノ,ノ
人生 名詞,一般,*,*,*,*,人生,ジンセイ,ジンセイ
だっ 助動詞,*,*,*,特殊・ダ,連用タ接続,だ,ダッ,ダッ
た 助動詞,*,*,*,特殊・タ,基本形,た,タ,タ
。 記号,句点,*,*,*,*,。,。,。
=============================================
最終兵器は懐にしまいます。
最終 名詞,一般,*,*,*,*,最終,サイシュウ,サイシュー
兵器 名詞,一般,*,*,*,*,兵器,ヘイキ,ヘイキ
は 助詞,係助詞,*,*,*,*,は,ハ,ワ
懐 名詞,一般,*,*,*,*,懐,フトコロ,フトコロ
に 助詞,格助詞,一般,*,*,*,に,ニ,ニ
しまい 動詞,自立,*,*,五段・ワ行促音便,連用形,しまう,シマイ,シマイ
ます 助動詞,*,*,*,特殊・マス,基本形,ます,マス,マス
。 記号,句点,*,*,*,*,。,。,。
=============================================
お前は助からない。
お前 名詞,代名詞,一般,*,*,*,お前,オマエ,オマエ
は 助詞,係助詞,*,*,*,*,は,ハ,ワ
助から 動詞,自立,*,*,五段・ラ行,未然形,助かる,タスカラ,タスカラ
ない 助動詞,*,*,*,特殊・ナイ,基本形,ない,ナイ,ナイ
。 記号,句点,*,*,*,*,。,。,。
=============================================
ログを読め。
ログ 名詞,サ変接続,*,*,*,*,ログ,ログ,ログ
を 助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
読め 動詞,自立,*,*,五段・マ行,命令e,読む,ヨメ,ヨメ
。 記号,句点,*,*,*,*,。,。,。
=============================================
さあご一緒に!「TRUE 1 が TRUE! TRUE 0 が FALSE!」
さあ 感動詞,*,*,*,*,*,さあ,サア,サー
ご 接頭詞,名詞接続,*,*,*,*,ご,ゴ,ゴ
一緒 名詞,サ変接続,*,*,*,*,一緒,イッショ,イッショ
に 助詞,格助詞,一般,*,*,*,に,ニ,ニ
! 記号,一般,*,*,*,*,!,!,!
「 記号,括弧開,*,*,*,*,「,「,「
TRUE 名詞,固有名詞,組織,*,*,*,TRUE,*,*
記号,空白,*,*,*,*, ,*,*
1 名詞,数,*,*,*,*,1,*,*
記号,空白,*,*,*,*, ,*,*
が 接続詞,*,*,*,*,*,が,ガ,ガ
記号,空白,*,*,*,*, ,*,*
TRUE 名詞,固有名詞,組織,*,*,*,TRUE,*,*
! 記号,一般,*,*,*,*,!,!,!
記号,空白,*,*,*,*, ,*,*
TRUE 名詞,固有名詞,組織,*,*,*,TRUE,*,*
記号,空白,*,*,*,*, ,*,*
0 名詞,数,*,*,*,*,0,*,*
記号,空白,*,*,*,*, ,*,*
が 接続詞,*,*,*,*,*,が,ガ,ガ
記号,空白,*,*,*,*, ,*,*
FALSE 名詞,固有名詞,組織,*,*,*,FALSE,*,*
! 記号,一般,*,*,*,*,!,!,!
」 記号,括弧閉,*,*,*,*,」,」,」
形態素解析の結果は、Token
として取得できます。
Token
自体を文字列として出力した時になにが出ているかは、こちらを参照するとよいでしょう。
例えば、表層形(surface)と基本形(base_form)を出力してみます。
for sentence in sentenses:
print("=============================================")
print(sentence)
for token in tokenizer.tokenize(sentence):
print(" " + token.surface + " | " + token.base_form)
こんな感じの結果に。
=============================================
ギョエェェエーと叫ぶだけの人生だった。
ギョエェェエー | ギョエェェエー
と | と
叫ぶ | 叫ぶ
だけ | だけ
の | の
人生 | 人生
だっ | だ
た | た
。 | 。
=============================================
最終兵器は懐にしまいます。
最終 | 最終
兵器 | 兵器
は | は
懐 | 懐
に | に
しまい | しまう
ます | ます
。 | 。
=============================================
お前は助からない。
お前 | お前
は | は
助から | 助かる
ない | ない
。 | 。
=============================================
ログを読め。
ログ | ログ
を | を
読め | 読む
。 | 。
=============================================
さあご一緒に!「TRUE 1 が TRUE! TRUE 0 が FALSE!」
さあ | さあ
ご | ご
一緒 | 一緒
に | に
! | !
「 | 「
TRUE | TRUE
|
1 | 1
|
が | が
|
TRUE | TRUE
! | !
|
TRUE | TRUE
|
0 | 0
|
が | が
|
FALSE | FALSE
! | !
」 | 」
活用形で書かれていた場合に、基本形が確認できたりします。
=============================================
ログを読め。
ログ | ログ
を | を
読め | 読む
。 | 。
表層形のみがあればよい場合は、分かち書きモードを使用するとよいみたいですよ。
janome
スクリプトを使う
コマンドラインからJanomeを使う場合は、janome
スクリプトを使用します。
mecab
コマンドのように使えます。
echo
などからパイプで渡してもいいですし
$ echo 'ログを読め。' | janome
ログ 名詞,サ変接続,*,*,*,*,ログ,ログ,ログ
を 助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
読め 動詞,自立,*,*,五段・マ行,命令e,読む,ヨメ,ヨメ
。 記号,句点,*,*,*,*,。,。,。
1度コマンドを起動して
$ janome
対話的に入力してもOKです。
私は、東京都に行く。
私 名詞,代名詞,一般,*,*,*,私,ワタシ,ワタシ
は 助詞,係助詞,*,*,*,*,は,ハ,ワ
、 記号,読点,*,*,*,*,、,、,、
東京 名詞,固有名詞,地域,一般,*,*,東京,トウキョウ,トーキョー
都 名詞,接尾,地域,*,*,*,都,ト,ト
に 助詞,格助詞,一般,*,*,*,に,ニ,ニ
行く 動詞,自立,*,*,五段・カ行促音便,基本形,行く,イク,イク
。 記号,句点,*,*,*,*,。,。,。
ヘルプ。
$ janome -h
usage: janome [-h] [-e ENC] [--udic UDIC] [--udic-enc UDIC_ENC]
[--udic-type UDIC_TYPE] [-m [MMAP]] [-g [GRAPHVIZ]]
[--gv-out GV_OUT] [--gv-format GV_FORMAT] [--version]
optional arguments:
-h, --help show this help message and exit
-e ENC, --enc ENC Input encoding. Default is 'utf8'
--udic UDIC Path to user dictionary file
--udic-enc UDIC_ENC User dictionary encoding. Default is 'utf8'
--udic-type UDIC_TYPE
User dictionary type, 'ipadic' or 'simpledic.' Default
is 'ipadic'
-m [MMAP], --mmap [MMAP]
Use mmap mode
-g [GRAPHVIZ], --graphviz [GRAPHVIZ]
Output visualized lattice graph by Graphviz
--gv-out GV_OUT Graphviz output file path. This option is used with -g
or --graphviz
--gv-format GV_FORMAT
Graphviz output format. default is 'png'. This option
is used with -g or --graphviz. See
https://graphviz.gitlab.io/_pages/doc/info/output.html
for the supported formats.
--version show program's version number and exit
Analyzer
フレームワーク
Janomeには、Ananlyzer
フレームワークというものがあり、文字の正規化などの前処理を行うCharFilter
、形態素解析後の後処理を行うTokenFilter
、CharFilter
、Tokenizer
、TokenFilter
を組み合わせて構成するAnalyzer
から成っています。
(experimental) Analyzer フレームワーク
今回は、先ほどのサンプルで扱った文をちょっと修正して、遊んでみます。
CharFilter
としてUnicodeNormalizeCharFilter
を選んで全角英数字を正規化し(デフォルトでNFKC)、TokenFilter
としてPOSStopFilter
を使って特定の品詞を除去、LowerCaseFilter
で小文字化を行います。
hello_analyzer.py
from janome.tokenizer import Tokenizer
from janome.analyzer import Analyzer
from janome.charfilter import *
from janome.tokenfilter import *
text = "さあご一緒に! TRUE 1 が TRUE TRUE 0 が FALSE!"
char_filters = [ UnicodeNormalizeCharFilter() ]
tokenizer = Tokenizer()
token_filters = [ POSStopFilter(["記号", "助詞", "接続詞"]), LowerCaseFilter() ]
analyzer = Analyzer(char_filters, tokenizer, token_filters)
for token in analyzer.analyze(text):
print(token)
結果は、こちら。
$ python3 hello_analyzer.py
さあ 感動詞,*,*,*,*,*,さあ,サア,サー
ご 接頭詞,名詞接続,*,*,*,*,ご,ゴ,ゴ
一緒 名詞,サ変接続,*,*,*,*,一緒,イッショ,イッショ
! 名詞,サ変接続,*,*,*,*,!,*,*
true 名詞,固有名詞,組織,*,*,*,true,*,*
1 名詞,数,*,*,*,*,1,*,*
true 名詞,固有名詞,組織,*,*,*,true,*,*
true 名詞,固有名詞,組織,*,*,*,true,*,*
0 名詞,数,*,*,*,*,0,*,*
false 名詞,固有名詞,組織,*,*,*,false,*,*
! 名詞,サ変接続,*,*,*,*,!,*,*
簡単に使えて、良さそうですね。