StanfordNLPをインストールして使う

最初、公式のStanford CoreNLPのPythonラッパーがリリースされた、
と思ってたら、そうではなくてPythonネイティブのライブラリだった。
（※Stanford CoreNLPのラッパーとしても使えるらしいが）

StanfordNLP
https://stanfordnlp.github.io/stanfordnlp/
https://github.com/stanfordnlp/stanfordnlp

Stanford CoreNLPより圧倒的に多い53言語のモデルが用意されている。日本語モデルあり。
（ただし、精度はよく分からない）

※【参考】StanfordNLP
https://stanfordnlp.github.io/stanfordnlp/installation_download.html

※【参考】Stanford CoreNLP
https://stanfordnlp.github.io/CoreNLP/index.html#download


## インストール
環境：Windows 10 Pro, Python 3.7.2
※StanfordNLPはPython 3.6以上が必要

Pytorchが必要なので、Pytorch、StanfordNLPの順にインストール

Pytorchのインストールは以下を参照。
https://pytorch.org/get-started/locally/

いくつかやり方が書いているが、
私はpipでCPU版Pytorchをインストールした。

```terminal
pip install https://download.pytorch.org/whl/cpu/torch-1.0.0-cp37-cp37m-win_amd64.whl
pip install torchvision
```

StanfordNLPインストール

```terminal
pip install stanfordnlp
```

## StanfordNLPを使う
### まずは英語
モデルのダウンロードに時間がかかる。

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

Default download directory: [path]
Hit enter to continue or type an alternate directory.


Downloading models for: en_ewt
Download location: [path]/en_ewt_models.zip
  3%|██▋                                                                          | 67.1M/1.96G [00:50<16:38, 1.89MB/s]
```

って、英語のモデルが1.96GBもあるのか！
ということで初回のダウンロードが終わるのをしばし待つ。

そんなこんなで待つこと30分強かかってようやくダウンロードが完了

```python
Download location: [path]/en_ewt_models.zip
100%|██████████████████████████████████████████████████████████████████████████████| 1.96G/1.96G [31:09<00:00, 850kB/s]

Download complete.  Models saved to: [path]/en_ewt_models.zip
Extracting models file for: en_ewt
'rm' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。
Cleaning up...Done.
```

最後、rmコマンド実行でエラーが発生しているようだが、そりゃまあWindowsだし。
ていうか、WSL環境じゃないんだからrm実行すんなよ。
気にせず続ける。

```python
>>> nlp = stanfordnlp.Pipeline(lang='en')
>>> doc = nlp("He ate banana with hands.")
>>> doc.sentences[0].print_tokens()
<Token index=1;words=[<Word index=1;text=He;lemma=he;upos=PRON;xpos=PRP;feats=Case=Nom|Gender=Masc|Number=Sing|Person=3|PronType=Prs;governor=2;dependency_relation=nsubj>]>
<Token index=2;words=[<Word index=2;text=ate;lemma=eat;upos=VERB;xpos=VBD;feats=Mood=Ind|Tense=Past|VerbForm=Fin;governor=0;dependency_relation=root>]>
<Token index=3;words=[<Word index=3;text=banana;lemma=banana;upos=NOUN;xpos=NN;feats=Number=Sing;governor=2;dependency_relation=obj>]>
<Token index=4;words=[<Word index=4;text=with;lemma=with;upos=ADP;xpos=IN;feats=_;governor=5;dependency_relation=case>]>
<Token index=5;words=[<Word index=5;text=hands;lemma=hand;upos=NOUN;xpos=NNS;feats=Number=Plur;governor=2;dependency_relation=obl>]>
<Token index=6;words=[<Word index=6;text=.;lemma=.;upos=PUNCT;xpos=.;feats=_;governor=2;dependency_relation=punct>]>
>>>
```

この英文は何かの本に書いてた例文みたいなやつ。
今回はとりあえず動いたのでこれで終わり。今度時間取って、これで構文解析を見てみる。

### 中国語（繁体字）

まずはモデルのダウンロード

```python
>>> import stanfordnlp
>>> stanfordnlp.download('zh')
```

モデルのファイルサイズは1GBで、英語よりサイズ小さいのは意外。
とはいえ、ダウンロードを待つこと10分程度。

台湾プロ野球ニュースの記事より
http://www.cpbl.com.tw/news/view/14888.html

```python
>>> nlp = stanfordnlp.Pipeline(lang='zh')
>>> doc = nlp('中華職棒下半季已開打一個月，由義大犀牛和統一7-ELEVEn獅分占一、二名，7月份投打MVP也由這兩隊包辦，由統一洋
投布魯斯拿下投手月MVP，打擊部分則是義大高國輝以1票之差擊敗Lamigo桃猿的「四割男」王柏融。')
>>> doc.sentences[0].print_tokens()
<Token index=1;words=[<Word index=1;text=中華;lemma=中華;upos=PROPN;xpos=NNP;feats=_;governor=2;dependency_relation=nmod>]>
<Token index=2;words=[<Word index=2;text=職棒;lemma=職棒;upos=NOUN;xpos=NN;feats=_;governor=7;dependency_relation=nsubj>]>
<Token index=3;words=[<Word index=3;text=下;lemma=下;upos=ADP;xpos=IN;feats=_;governor=2;dependency_relation=acl>]>
<Token index=4;words=[<Word index=4;text=半;lemma=半;upos=NUM;xpos=CD;feats=NumType=Card;governor=5;dependency_relation=nummod>]>
<Token index=5;words=[<Word index=5;text=季;lemma=季;upos=NOUN;xpos=NNB;feats=_;governor=7;dependency_relation=nsubj>]>
<Token index=6;words=[<Word index=6;text=已;lemma=已;upos=ADV;xpos=RB;feats=_;governor=7;dependency_relation=advmod>]>
<Token index=7;words=[<Word index=7;text=開打;lemma=開打;upos=VERB;xpos=VV;feats=_;governor=0;dependency_relation=root>]>
<Token index=8;words=[<Word index=8;text=一;lemma=一;upos=NUM;xpos=CD;feats=NumType=Card;governor=9;dependency_relation=nummod>]>
<Token index=9;words=[<Word index=9;text=個;lemma=個;upos=NOUN;xpos=NNB;feats=_;governor=10;dependency_relation=clf>]>
<Token index=10;words=[<Word index=10;text=月，;lemma=月，;upos=NOUN;xpos=NN;feats=_;governor=11;dependency_relation=nsubj>]>
<Token index=11;words=[<Word index=11;text=由;lemma=由;upos=VERB;xpos=VV;feats=_;governor=30;dependency_relation=acl>]>
<Token index=12;words=[<Word index=12;text=義大犀牛;lemma=義大犀牛;upos=NOUN;xpos=NN;feats=_;governor=28;dependency_relation=nmod>]>
<Token index=13;words=[<Word index=13;text=和;lemma=和;upos=CCONJ;xpos=CC;feats=_;governor=18;dependency_relation=cc>]>
<Token index=14;words=[<Word index=14;text=統;lemma=統;upos=PROPN;xpos=NNP;feats=_;governor=12;dependency_relation=conj>]>
<Token index=15;words=[<Word index=15;text=一;lemma=一;upos=NUM;xpos=CD;feats=NumType=Card;governor=18;dependency_relation=nummod>]>
<Token index=16;words=[<Word index=16;text=7;lemma=7;upos=NUM;xpos=CD;feats=NumType=Card;governor=18;dependency_relation=nummod>]>
<Token index=17;words=[<Word index=17;text=-;lemma=-;upos=PUNCT;xpos=HYPH;feats=_;governor=18;dependency_relation=punct>]>
<Token index=18;words=[<Word index=18;text=ELEVEn獅分占;lemma=ELEVEn獅分占;upos=X;xpos=FW;feats=_;governor=12;dependency_relation=conj>]>
<Token index=19;words=[<Word index=19;text=一;lemma=一;upos=NUM;xpos=CD;feats=NumType=Card;governor=18;dependency_relation=nummod>]>
<Token index=20;words=[<Word index=20;text=、;lemma=、;upos=PUNCT;xpos=EC;feats=_;governor=23;dependency_relation=punct>]>
<Token index=21;words=[<Word index=21;text=二;lemma=二;upos=NUM;xpos=CD;feats=NumType=Card;governor=22;dependency_relation=nummod>]>
<Token index=22;words=[<Word index=22;text=名;lemma=名;upos=NOUN;xpos=NNB;feats=_;governor=27;dependency_relation=clf>]>
<Token index=23;words=[<Word index=23;text=，;lemma=，;upos=VERB;xpos=VV;feats=_;governor=27;dependency_relation=amod>]>
<Token index=24;words=[<Word index=24;text=7;lemma=7;upos=NUM;xpos=CD;feats=NumType=Card;governor=25;dependency_relation=nummod>]>
<Token index=25;words=[<Word index=25;text=月;lemma=月;upos=NOUN;xpos=NNB;feats=_;governor=26;dependency_relation=case:suff>]>
<Token index=26;words=[<Word index=26;text=份;lemma=份;upos=PART;xpos=SFN;feats=_;governor=27;dependency_relation=nmod>]>
<Token index=27;words=[<Word index=27;text=投打;lemma=投打;upos=NOUN;xpos=NN;feats=_;governor=28;dependency_relation=appos>]>
<Token index=28;words=[<Word index=28;text=MVP;lemma=MVP;upos=X;xpos=FW;feats=_;governor=30;dependency_relation=nsubj>]>
<Token index=29;words=[<Word index=29;text=也;lemma=也;upos=ADV;xpos=RB;feats=_;governor=30;dependency_relation=mark>]>
<Token index=30;words=[<Word index=30;text=由;lemma=由;upos=VERB;xpos=VV;feats=_;governor=7;dependency_relation=ccomp>]>
<Token index=31;words=[<Word index=31;text=這;lemma=這;upos=DET;xpos=DT;feats=_;governor=33;dependency_relation=det>]>
<Token index=32;words=[<Word index=32;text=兩;lemma=兩;upos=NUM;xpos=CD;feats=NumType=Card;governor=33;dependency_relation=nummod>]>
<Token index=33;words=[<Word index=33;text=隊;lemma=隊;upos=NOUN;xpos=NN;feats=_;governor=34;dependency_relation=nsubj>]>
<Token index=34;words=[<Word index=34;text=包辦;lemma=包辦;upos=VERB;xpos=VV;feats=_;governor=30;dependency_relation=ccomp>]>
<Token index=35;words=[<Word index=35;text=，;lemma=，;upos=PART;xpos=AS;feats=Aspect=Perf;governor=34;dependency_relation=case:aspect>]>
<Token index=36;words=[<Word index=36;text=由;lemma=由;upos=VERB;xpos=VV;feats=_;governor=44;dependency_relation=acl>]>
<Token index=37;words=[<Word index=37;text=統一;lemma=統一;upos=PROPN;xpos=NNP;feats=_;governor=38;dependency_relation=case:suff>]>
<Token index=38;words=[<Word index=38;text=洋;lemma=洋;upos=PART;xpos=SFN;feats=_;governor=39;dependency_relation=appos>>
<Token index=39;words=[<Word index=39;text=投布魯斯拿;lemma=投布魯斯拿;upos=PROPN;xpos=NNP;feats=_;governor=40;dependency_relation=nsubj>]>
<Token index=40;words=[<Word index=40;text=下投;lemma=下投;upos=VERB;xpos=VV;feats=_;governor=36;dependency_relation=ccomp>]>
<Token index=41;words=[<Word index=41;text=手月;lemma=手月;upos=NOUN;xpos=NN;feats=_;governor=40;dependency_relation=obj>]>
<Token index=42;words=[<Word index=42;text=MVP;lemma=MVP;upos=X;xpos=FW;feats=_;governor=40;dependency_relation=obj>]>
<Token index=43;words=[<Word index=43;text=，;lemma=，;upos=PUNCT;xpos=,;feats=_;governor=44;dependency_relation=punct>]>
<Token index=44;words=[<Word index=44;text=打擊;lemma=打擊;upos=VERB;xpos=VV;feats=_;governor=64;dependency_relation=csubj>]>
<Token index=45;words=[<Word index=45;text=部分;lemma=部分;upos=NOUN;xpos=NN;feats=_;governor=44;dependency_relation=obj>]>
<Token index=46;words=[<Word index=46;text=則是;lemma=則是;upos=AUX;xpos=VC;feats=_;governor=64;dependency_relation=cop>]>
<Token index=47;words=[<Word index=47;text=義大高;lemma=義大高;upos=PROPN;xpos=NNP;feats=_;governor=48;dependency_relation=nmod>]>
<Token index=48;words=[<Word index=48;text=國輝;lemma=國輝;upos=PROPN;xpos=NNP;feats=_;governor=54;dependency_relation=nsubj>]>
<Token index=49;words=[<Word index=49;text=以;lemma=以;upos=ADP;xpos=IN;feats=_;governor=53;dependency_relation=case>]>
<Token index=50;words=[<Word index=50;text=1;lemma=1;upos=NUM;xpos=CD;feats=NumType=Card;governor=51;dependency_relation=nummod>]>
<Token index=51;words=[<Word index=51;text=票;lemma=票;upos=NOUN;xpos=NN;feats=_;governor=53;dependency_relation=det>]>
<Token index=52;words=[<Word index=52;text=之;lemma=之;upos=PART;xpos=DEC;feats=Case=Gen;governor=51;dependency_relation=case:dec>]>
<Token index=53;words=[<Word index=53;text=差;lemma=差;upos=NOUN;xpos=NN;feats=_;governor=54;dependency_relation=obl>]>
<Token index=54;words=[<Word index=54;text=擊敗;lemma=擊敗;upos=VERB;xpos=VV;feats=_;governor=64;dependency_relation=acl:relcl>]>
<Token index=55;words=[<Word index=55;text=Lamigo;lemma=Lamigo;upos=X;xpos=FW;feats=_;governor=56;dependency_relation=nmod>]>
<Token index=56;words=[<Word index=56;text=桃猿;lemma=桃猿;upos=NOUN;xpos=NN;feats=_;governor=61;dependency_relation=det>]>
<Token index=57;words=[<Word index=57;text=的;lemma=的;upos=PART;xpos=DEC;feats=Case=Gen;governor=56;dependency_relation=case:dec>]>
<Token index=58;words=[<Word index=58;text=「;lemma=「;upos=PUNCT;xpos=``;feats=_;governor=61;dependency_relation=punct>]>
<Token index=59;words=[<Word index=59;text=四;lemma=四;upos=NUM;xpos=CD;feats=NumType=Card;governor=60;dependency_relation=nummod>]>
<Token index=60;words=[<Word index=60;text=割;lemma=割;upos=NOUN;xpos=NN;feats=_;governor=61;dependency_relation=case:suff>]>
<Token index=61;words=[<Word index=61;text=男;lemma=男;upos=PART;xpos=SFN;feats=_;governor=54;dependency_relation=obj>]>
<Token index=62;words=[<Word index=62;text=」;lemma=」;upos=PUNCT;xpos='';feats=_;governor=61;dependency_relation=punct>]>
<Token index=63;words=[<Word index=63;text=王;lemma=王;upos=PROPN;xpos=NNP;feats=_;governor=64;dependency_relation=nmod>]>
<Token index=64;words=[<Word index=64;text=柏融;lemma=柏融;upos=PROPN;xpos=NNP;feats=_;governor=34;dependency_relation=obj>]>
<Token index=65;words=[<Word index=65;text=。;lemma=。;upos=PUNCT;xpos=.;feats=_;governor=7;dependency_relation=punct>]>
>>>
```

中国語はよくわかってないのだが、気になるのは2点。

- 独特な固有名詞が変に分割されている
    - ”統一7-ELEVEn獅”は、これ1語で固有名詞（前処理で別単語に置換するのがいいかなあ・・）
- 登場人物が3名いるが、正しく固有名詞（PROPN）にタグ付けされたのは王柏融 1名だけ
    - 布魯斯：”投布魯斯拿”で1つの固有名詞になっている
        - 洋投布魯斯拿下投手月MVP → ”洋投 布魯斯 拿下 投手 月MVP”って分割して欲しい
    - 高國輝：”義大高”と”國輝”の2つに分割されてる
        - 義大高國輝 → "義大 高國輝"って分割して欲しい

### 韓国語

まずはモデルのダウンロード。

```python
>>> import stanfordnlp
>>> stanfordnlp.download('ko')
```

ファイルサイズは932MB。

文章は韓国プロ野球（KBO）のニュースより
https://www.koreabaseball.com/News/Preview/View.aspx?bdSe=39227

```python
>>> doc = nlp('KBO 최고포수 양의지가 가세한 NC가 희망에 부풀어 있다.')
>>> doc.sentences[0].print_tokens()
<Token index=1;words=[<Word index=1;text=KBO;lemma=KBO;upos=X;xpos=f;feats=_;governor=2;dependency_relation=compound>]>
<Token index=2;words=[<Word index=2;text=최고포수;lemma=최고+포수;upos=NOUN;xpos=ncn+ncn;feats=_;governor=3;dependency_relation=compound>]>
<Token index=3;words=[<Word index=3;text=양의지가;lemma=양의지+가;upos=NOUN;xpos=ncn+jcs;feats=_;governor=4;dependency_relation=nsubj>]>
<Token index=4;words=[<Word index=4;text=가세한;lemma=가세+하+ㄴ;upos=VERB;xpos=ncpa+xsv+etm;feats=_;governor=5;dependency_relation=acl>]>
<Token index=5;words=[<Word index=5;text=NC가;lemma=NC+가;upos=NOUN;xpos=f+jcs;feats=_;governor=7;dependency_relation=nsubj>]>
<Token index=6;words=[<Word index=6;text=희망에;lemma=희망+에;upos=ADV;xpos=ncpa+jca;feats=_;governor=7;dependency_relation=obl>]>
<Token index=7;words=[<Word index=7;text=부풀어;lemma=부풀+어;upos=VERB;xpos=pvg+ef;feats=_;governor=0;dependency_relation=root>]>
<Token index=8;words=[<Word index=8;text=있다.;lemma=있+다수;upos=PUNCT;xpos=sf;feats=_;governor=7;dependency_relation=p
unct>]>
```

品詞付けはあってそうだが、人名などの固有名詞かどうかの情報も付加して欲しいなあと。
（”양의지”は、ヤン・ウイジ ていう人名）

ちなみに同じ文章をmecab-koで形態素解析してみると、、

```sh
KBO	SL,*,*,*,*,*,*,*
최고	NNG,*,F,최고,*,*,*,*
포수	NNG,*,F,포수,*,*,*,*
양의지	NNP,인명,F,양의지,*,*,*,*,양의지,1788,3549,4104,NNP,인명,F,양의지,*,*,*,*
가	JKS,*,F,가,*,*,*,*
가세	NNG,*,F,가세,*,*,*,*
한	XSA+ETM,*,T,한,Inflect,XSA,ETM,하/XSA/*+ᆫ/ETM/*
NC	SL,*,*,*,*,*,*,*
가	JKS,*,F,가,*,*,*,*
희망	NNG,정적사태,T,희망,*,*,*,*
에	JKB,*,F,에,*,*,*,*
부풀	VV,*,T,부풀,*,*,*,*
어	EC,*,F,어,*,*,*,*
있	VX,*,T,있,*,*,*,*
다	EF,*,F,다,*,*,*,*
.	SF,*,*,*,*,*,*,*,.,1794,3560,3518,SF,*,*,*,*,*,*,*
EOS
```

となり、양의지 は固有名詞（NNP）、人名（인명） の情報が付加されている。

## 使ってみた感想

- 1つのパッケージ（StanfordNLP）で、複数の言語を解析できるのは便利
- なんとなく、JavaのStanford CoreNLPより扱いやすい気がする
- 今後、精度がよくなることに期待（特に中国語）　
- GCPのf1.microやAWSのt2.microで動かしてみたい（メモリが足りるかなあ）
- モデルをロードした状態、CGIサーバとして起動したいなあ（Pythonに詳しくないのでやり方あるんかどうか）