見出し画像

StanfordNLP で「私の名前は中野です」

StanfordNLP による日本語の形態素解析をちょっと試してみたので、簡単に紹介します。

StanfordNLP のサイトを見てみると、StanrordNLP とは 2018年の CoNLL という学会でスタンフォード大学のチームが発表した自然言語処理に関するソフトウェア群の総称とあります。各種モジュールは PyTorch を使って構築されており、53の言語用に学習済みのモデルが用意されているとのことです。この中に日本語も含まれていたので、試してみました。

インストールとセットアップ

インストールは通常の Python パッケージ同様、 pip のみでいけます。

pip install stanfordnlp

なお、 Python のバージョンは 3.6 以降が対象とのことで、 3.6.8 以降もしくは 3.7.2 以降がおすすめらしいです。

>>> import stanfordnlp
>>> stanfordnlp.download('ja')
Using the default treebank "ja_gsd" for language "ja".
Would you like to download the models for: ja_gsd now? (Y/n)

日本語向けツリーバンクとして ja_gsd を使うが良いかという確認を求められるので Y で。

Default download directory: /Users/setoguchi/stanfordnlp_resources
Hit enter to continue or type an alternate directory.

ダウンロード先のディレクトリを尋ねられます。デフォルトではホームディレクトリの stanfordnlp_resources となります。それで良ければリターンを、変えたければ希望するディレクトリを入力します。僕はこのままで良いのでリターン。

Downloading models for: ja_gsd
Download location: /Users/setoguchi/stanfordnlp_resources/ja_gsd_models.zip
100%|██████████████████████████████████████| 1.93G/1.93G [27:07<00:00, 1.09MB/s]
Download complete.  Models saved to: /Users/setoguchi/stanfordnlp_resources/ja_gsd_models.zip
Extracting models file for: ja_gsd
Cleaning up...Done.

ダウンロードと展開とが行われます。2GB 近くあるので、ネットワーク環境によりますがそれなりに時間がかかります。

>>> nlp = stanfordnlp.Pipeline(lang='ja')
Use device: cpu
---
Loading: tokenize
With settings: 
{'model_path': '/Users/setoguchi/stanfordnlp_resources/ja_gsd_models/ja_gsd_tokenizer.pt', 'lang': 'ja', 'shorthand': 'ja_gsd', 'mode': 'predict'}
---
Loading: pos
With settings: 
{'model_path': '/Users/setoguchi/stanfordnlp_resources/ja_gsd_models/ja_gsd_tagger.pt', 'pretrain_path': '/Users/setoguchi/stanfordnlp_resources/ja_gsd_models/ja_gsd.pretrain.pt', 'lang': 'ja', 'shorthand': 'ja_gsd', 'mode': 'predict'}
---
Loading: lemma
With settings: 
{'model_path': '/Users/setoguchi/stanfordnlp_resources/ja_gsd_models/ja_gsd_lemmatizer.pt', 'lang': 'ja', 'shorthand': 'ja_gsd', 'mode': 'predict'}
Building an attentional Seq2Seq model...
Using a Bi-LSTM encoder
Using soft attention for LSTM.
Finetune all embeddings.
[Running seq2seq lemmatizer with edit classifier]
---
Loading: depparse
With settings: 
{'model_path': '/Users/setoguchi/stanfordnlp_resources/ja_gsd_models/ja_gsd_parser.pt', 'pretrain_path': '/Users/setoguchi/stanfordnlp_resources/ja_gsd_models/ja_gsd.pretrain.pt', 'lang': 'ja', 'shorthand': 'ja_gsd', 'mode': 'predict'}
Done loading processors!

もろもろ初期化の処理が走りますが、これもわりと時間がかかります。

使ってみる

そしてついに形態素解析をします。

>>> doc = nlp('私の名前は中野です。')
>>> doc
<stanfordnlp.pipeline.doc.Document object at 0x10c2d9358>

日本語入力の Hello World と言えばやはり「私の名前は中野です」ですね。このテキストを解析してみると、Document のオブジェクトが返ってきていることがわかります。
doc 内の係り受けの関係性を見てみると...

>>> doc.sentences[0].print_dependencies()
('私', '3', 'nmod')
('の', '1', 'case')
('名前', '5', 'nsubj')
('は', '3', 'case')
('中野', '0', 'root')
('です', '5', 'cop')
('。', '5', 'punct')

こんな具合になりました。なお、係り受けにおける役割については Dependencies で確認できます。

次は2文でやってみます。

>>> doc = nlp('今日は雪が降る予報でしたが今は雨が降っています。首都高ではノーマルタイヤでの走行は控えるように案内しているそうです。')
>>> len(doc.sentences)
2

doc.sentences の len を取ることで、2文に分かれていることがわかります。次は係り受け関係ではなく、表層系・原形・品詞を見てみます。

>>> for sen in doc.sentences:
...   for w in sen.words:
...     print(w.text, w.lemma, w.upos)
... 
今日 今日 NOUN
は は ADP
雪 雪 NOUN
が が ADP
降る 降る VERB
予報 予報 NOUN
でし だ AUX
た た AUX
が が SCONJ
今 今 NOUN
は は ADP
雨 雨 NOUN
が が ADP
降っ 降る VERB
て て SCONJ
い いる AUX
ます ます AUX
。 。 PUNCT
首都 首都 NOUN
高 高 NOUN
で で ADP
は は ADP
ノーマルタイヤ ノーマルタイヤ NOUN
で で ADP
の の PART
走行 走行 NOUN
は は ADP
控える 控える VERB
ように ようだ AUX
案内 案内 VERB
し する AUX
て て SCONJ
いる いる AUX
そうです そうだ AUX
。 。 PUNCT

品詞体系については Universal POS tags にて確認できます。基本的には良さそうですが、よく見てみるといくつか気になるところがあります。

1. 「首都高」は「首都」と「高」に分かれてしまっている。
2. 「でし」の原形が「だ」となっていますが、どちらかというと「です」ではなかろうか。
3. 「ように」の部分の原形が「ようだ」となっている。

まとめ

今のところ、日本語の形態素解析においては既存の他のソフトウェアの方がうまいことできているように感じます。また、こちらは辞書の話になりそうですが、品詞の細分類・活用型・活用形などが無いようなので、品詞の持つそれらの情報を用いて内容語か否かの判断をするなどといったことには利用できないでしょう。
また、形態素解析を始めるまでの時間がかなりかかるので、バッチ的な場面で使うか、サーバーとして起動しておいて処理する感じになるのでしょうか。

ということで、現段階では日本語の形態素解析器として StanfordNLP を使うのは難しそうかなと感じましたが、今後もウォッチしていきたいと思います。

この記事が気に入ったらサポートをしてみませんか?