StanfordNLP 使ってみる。

CoreNLPの方は中身を改変しながら使っているのだけれど、
色々できるようになっているらしいのでやってみました。

https://stanfordnlp.github.io/stanfordnlp/

## 環境
macOS Sierra 10.12.6
Python 3.7.2

注意!Python 3.6 or later 必須、 Python 3.6.8 or later and Python 3.7.2 or later を推奨されています！ 公式ドキュメントに書いてありますが、importすら動かないので注意です。

## 準備
pytorchを入れて、その後stanfordnlpを入れます。　pytorchの入れ方は、公式ページ
https://pytorch.org/
の中段ぐらいに書いてありますが、私の環境の場合、

```bash
pip install torch torchvision
```

で良いようです。続いてstanfordnlpを入れます。

```bash
pip install stanfordnlp
```

#### mac限定 lzmaが入っていない場合
pyenvで環境構築している場合

```bash
brew install xz
pyenv install 3.7.2
```

でなんとかなります。（関連プログラムが入っていないことが原因です。入っていなくてもpythonをinstallできてしまうのが問題の根本な気もします。)

## 使ってみる
### 英語（公式ページ）
公式ページのように

```python
import stanfordnlp
stanfordnlp.download('en')
nlp = stanfordnlp.Pipeline() 
doc = nlp("Barack Obama was born in Hawaii.  He was elected president in 2008.")
doc.sentences[0].print_dependencies()
```

とやると、一応できます。

`en`をダウンロードしようとすると、 `en_ewt`でいいか？とかどこにこのモデル置く？（download sizeで1.96GB(zip)/展開後2.67GB)とか聞いてくるので、適切に答えてください。 

結果は以下のようになっているはずです。

```text
('Barack', '4', 'nsubj:pass')
('Obama', '1', 'flat')
('was', '4', 'aux:pass')
('born', '0', 'root')
('in', '6', 'case')
('Hawaii', '4', 'obl')
('.', '4', 'punct')
```

一応、 `dependencies` プロパティでもう少し詳しい情報が見えます。

```python
doc.sentences[0].dependencies
```

結果

```text
[(<Word index=4;text=born;lemma=bear;upos=VERB;xpos=VBN;feats=Tense=Past|VerbForm=Part|Voice=Pass;governor=0;dependency_relation=root>,
  'nsubj:pass',
  <Word index=1;text=Barack;lemma=Barack;upos=PROPN;xpos=NNP;feats=Number=Sing;governor=4;dependency_relation=nsubj:pass>),
 (<Word index=1;text=Barack;lemma=Barack;upos=PROPN;xpos=NNP;feats=Number=Sing;governor=4;dependency_relation=nsubj:pass>,
  'flat',
  <Word index=2;text=Obama;lemma=Obama;upos=PROPN;xpos=NNP;feats=Number=Sing;governor=1;dependency_relation=flat>),
 (<Word index=4;text=born;lemma=bear;upos=VERB;xpos=VBN;feats=Tense=Past|VerbForm=Part|Voice=Pass;governor=0;dependency_relation=root>,
  'aux:pass',
  <Word index=3;text=was;lemma=be;upos=AUX;xpos=VBD;feats=Mood=Ind|Number=Sing|Person=3|Tense=Past|VerbForm=Fin;governor=4;dependency_relation=aux:pass>),
 (<Word index=0;text=ROOT>,
  'root',
  <Word index=4;text=born;lemma=bear;upos=VERB;xpos=VBN;feats=Tense=Past|VerbForm=Part|Voice=Pass;governor=0;dependency_relation=root>),
 (<Word index=6;text=Hawaii;lemma=Hawaii;upos=PROPN;xpos=NNP;feats=Number=Sing;governor=4;dependency_relation=obl>,
  'case',
  <Word index=5;text=in;lemma=in;upos=ADP;xpos=IN;feats=_;governor=6;dependency_relation=case>),
 (<Word index=4;text=born;lemma=bear;upos=VERB;xpos=VBN;feats=Tense=Past|VerbForm=Part|Voice=Pass;governor=0;dependency_relation=root>,
  'obl',
  <Word index=6;text=Hawaii;lemma=Hawaii;upos=PROPN;xpos=NNP;feats=Number=Sing;governor=4;dependency_relation=obl>),
 (<Word index=4;text=born;lemma=bear;upos=VERB;xpos=VBN;feats=Tense=Past|VerbForm=Part|Voice=Pass;governor=0;dependency_relation=root>,
  'punct',
  <Word index=7;text=.;lemma=.;upos=PUNCT;xpos=.;feats=_;governor=4;dependency_relation=punct>)]
```

### 日本語
日本語もできるらしいのでやってみました。
まずはモデルのダウンロード

```python
stanfordnlp.download('ja')
```

やっぱり`ja`じゃなくて`ja_gsd`だよと言ってきます。
このモデルもサイズが大きくて、zipで1.93GB、展開後2.66GBあります。
次は、piplineの設定

```python
nlp_ja = stanfordnlp.Pipeline(lang='ja') 
```

やってみる

```python
doc_ja = nlp_ja('庭には二羽ニワトリがいる。')
doc_ja.sentences[0].print_dependencies()
```
結果

```text
('庭', '7', 'iobj')
('に', '1', 'case')
('は', '1', 'case')
('二羽', '7', 'advmod')
('ニワトリ', '7', 'nsubj')
('が', '5', 'case')
('いる', '0', 'root')
('。', '7', 'punct')
```

```python
doc_ja.sentences[0].dependencies
```
結果２

```text
[(<Word index=7;text=いる;lemma=いる;upos=VERB;xpos=_;feats=_;governor=0;dependency_relation=root>,
  'iobj',
  <Word index=1;text=庭;lemma=庭;upos=NOUN;xpos=_;feats=_;governor=7;dependency_relation=iobj>),
 (<Word index=1;text=庭;lemma=庭;upos=NOUN;xpos=_;feats=_;governor=7;dependency_relation=iobj>,
  'case',
  <Word index=2;text=に;lemma=に;upos=ADP;xpos=_;feats=_;governor=1;dependency_relation=case>),
 (<Word index=1;text=庭;lemma=庭;upos=NOUN;xpos=_;feats=_;governor=7;dependency_relation=iobj>,
  'case',
  <Word index=3;text=は;lemma=は;upos=ADP;xpos=_;feats=_;governor=1;dependency_relation=case>),
 (<Word index=7;text=いる;lemma=いる;upos=VERB;xpos=_;feats=_;governor=0;dependency_relation=root>,
  'advmod',
  <Word index=4;text=二羽;lemma=二羽;upos=ADV;xpos=_;feats=_;governor=7;dependency_relation=advmod>),
 (<Word index=7;text=いる;lemma=いる;upos=VERB;xpos=_;feats=_;governor=0;dependency_relation=root>,
  'nsubj',
  <Word index=5;text=ニワトリ;lemma=ニワトリ;upos=NOUN;xpos=_;feats=_;governor=7;dependency_relation=nsubj>),
 (<Word index=5;text=ニワトリ;lemma=ニワトリ;upos=NOUN;xpos=_;feats=_;governor=7;dependency_relation=nsubj>,
  'case',
  <Word index=6;text=が;lemma=が;upos=ADP;xpos=_;feats=_;governor=5;dependency_relation=case>),
 (<Word index=0;text=ROOT>,
  'root',
  <Word index=7;text=いる;lemma=いる;upos=VERB;xpos=_;feats=_;governor=0;dependency_relation=root>),
 (<Word index=7;text=いる;lemma=いる;upos=VERB;xpos=_;feats=_;governor=0;dependency_relation=root>,
  'punct',
  <Word index=8;text=。;lemma=。;upos=PUNCT;xpos=_;feats=_;governor=7;dependency_relation=punct>)]
```

さすがにつまらないので、もう1つぐらいやってみる。(夏目漱石『こころ』より [青空文庫](https://www.aozora.gr.jp/cards/000148/card773.html))

```python
text = '私が先生と知り合いになったのは鎌倉である。その時私はまだ若々しい書生であった。'
doc_ja = nlp_ja(text)
doc_ja.sentences[0].print_dependencies()
doc_ja.sentences[0].dependencies
```

結果1

```text
('私', '7', 'nsubj')
('が', '1', 'case')
('先生', '5', 'nmod')
('と', '3', 'case')
('知り合い', '7', 'iobj')
('に', '5', 'case')
('なっ', '11', 'csubj')
('た', '7', 'aux')
('の', '7', 'mark')
('は', '7', 'case')
('鎌倉', '0', 'root')
('である', '11', 'cop')
('。', '11', 'punct')
```

結果2

```text
[(<Word index=7;text=なっ;lemma=なる;upos=VERB;xpos=_;feats=_;governor=11;dependency_relation=csubj>,
  'nsubj',
  <Word index=1;text=私;lemma=私;upos=PRON;xpos=_;feats=_;governor=7;dependency_relation=nsubj>),
 (<Word index=1;text=私;lemma=私;upos=PRON;xpos=_;feats=_;governor=7;dependency_relation=nsubj>,
  'case',
  <Word index=2;text=が;lemma=が;upos=ADP;xpos=_;feats=_;governor=1;dependency_relation=case>),
 (<Word index=5;text=知り合い;lemma=知り合い;upos=NOUN;xpos=_;feats=_;governor=7;dependency_relation=iobj>,
  'nmod',
  <Word index=3;text=先生;lemma=先生;upos=NOUN;xpos=_;feats=_;governor=5;dependency_relation=nmod>),
 (<Word index=3;text=先生;lemma=先生;upos=NOUN;xpos=_;feats=_;governor=5;dependency_relation=nmod>,
  'case',
  <Word index=4;text=と;lemma=と;upos=ADP;xpos=_;feats=_;governor=3;dependency_relation=case>),
 (<Word index=7;text=なっ;lemma=なる;upos=VERB;xpos=_;feats=_;governor=11;dependency_relation=csubj>,
  'iobj',
  <Word index=5;text=知り合い;lemma=知り合い;upos=NOUN;xpos=_;feats=_;governor=7;dependency_relation=iobj>),
 (<Word index=5;text=知り合い;lemma=知り合い;upos=NOUN;xpos=_;feats=_;governor=7;dependency_relation=iobj>,
  'case',
  <Word index=6;text=に;lemma=に;upos=ADP;xpos=_;feats=_;governor=5;dependency_relation=case>),
 (<Word index=11;text=鎌倉;lemma=鎌倉;upos=PROPN;xpos=_;feats=_;governor=0;dependency_relation=root>,
  'csubj',
  <Word index=7;text=なっ;lemma=なる;upos=VERB;xpos=_;feats=_;governor=11;dependency_relation=csubj>),
 (<Word index=7;text=なっ;lemma=なる;upos=VERB;xpos=_;feats=_;governor=11;dependency_relation=csubj>,
  'aux',
  <Word index=8;text=た;lemma=た;upos=AUX;xpos=_;feats=_;governor=7;dependency_relation=aux>),
 (<Word index=7;text=なっ;lemma=なる;upos=VERB;xpos=_;feats=_;governor=11;dependency_relation=csubj>,
  'mark',
  <Word index=9;text=の;lemma=の;upos=PART;xpos=_;feats=_;governor=7;dependency_relation=mark>),
 (<Word index=7;text=なっ;lemma=なる;upos=VERB;xpos=_;feats=_;governor=11;dependency_relation=csubj>,
  'case',
  <Word index=10;text=は;lemma=は;upos=ADP;xpos=_;feats=_;governor=7;dependency_relation=case>),
 (<Word index=0;text=ROOT>,
  'root',
  <Word index=11;text=鎌倉;lemma=鎌倉;upos=PROPN;xpos=_;feats=_;governor=0;dependency_relation=root>),
 (<Word index=11;text=鎌倉;lemma=鎌倉;upos=PROPN;xpos=_;feats=_;governor=0;dependency_relation=root>,
  'cop',
  <Word index=12;text=である;lemma=だ;upos=AUX;xpos=_;feats=_;governor=11;dependency_relation=cop>),
 (<Word index=11;text=鎌倉;lemma=鎌倉;upos=PROPN;xpos=_;feats=_;governor=0;dependency_relation=root>,
  'punct',
  <Word index=13;text=。;lemma=。;upos=PUNCT;xpos=_;feats=_;governor=11;dependency_relation=punct>)]
```

## 感想

* CoreNLPはJavaだったので、そちらよりはpiplineの扱いがしやすそう。
* CoreNLPのdependency++はどうなったんだろう？
* 参考にもあげた[記事](https://qiita.com/gayou/items/ddfd4f3ac6092faf180e)の方が書いているようにserverを立てようかなと思う。全部合わせて　docker imageにしてしまうつもり。


## 参考
https://qiita.com/gayou/items/ddfd4f3ac6092faf180e
https://stanfordnlp.github.io/stanfordnlp/