CoreNLPの方は中身を改変しながら使っているのだけれど、
色々できるようになっているらしいのでやってみました。
環境
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/
の中段ぐらいに書いてありますが、私の環境の場合、
pip install torch torchvision
で良いようです。続いてstanfordnlpを入れます。
pip install stanfordnlp
mac限定 lzmaが入っていない場合
pyenvで環境構築している場合
brew install xz
pyenv install 3.7.2
でなんとかなります。(関連プログラムが入っていないことが原因です。入っていなくてもpythonをinstallできてしまうのが問題の根本な気もします。)
使ってみる
英語(公式ページ)
公式ページのように
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)とか聞いてくるので、適切に答えてください。
結果は以下のようになっているはずです。
('Barack', '4', 'nsubj:pass')
('Obama', '1', 'flat')
('was', '4', 'aux:pass')
('born', '0', 'root')
('in', '6', 'case')
('Hawaii', '4', 'obl')
('.', '4', 'punct')
一応、 dependencies
プロパティでもう少し詳しい情報が見えます。
doc.sentences[0].dependencies
結果
[(<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>)]
日本語
日本語もできるらしいのでやってみました。
まずはモデルのダウンロード
stanfordnlp.download('ja')
やっぱりja
じゃなくてja_gsd
だよと言ってきます。
このモデルもサイズが大きくて、zipで1.93GB、展開後2.66GBあります。
次は、piplineの設定
nlp_ja = stanfordnlp.Pipeline(lang='ja')
やってみる
doc_ja = nlp_ja('庭には二羽ニワトリがいる。')
doc_ja.sentences[0].print_dependencies()
結果
('庭', '7', 'iobj')
('に', '1', 'case')
('は', '1', 'case')
('二羽', '7', 'advmod')
('ニワトリ', '7', 'nsubj')
('が', '5', 'case')
('いる', '0', 'root')
('。', '7', 'punct')
doc_ja.sentences[0].dependencies
結果2
[(<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つぐらいやってみる。(夏目漱石『こころ』より 青空文庫)
text = '私が先生と知り合いになったのは鎌倉である。その時私はまだ若々しい書生であった。'
doc_ja = nlp_ja(text)
doc_ja.sentences[0].print_dependencies()
doc_ja.sentences[0].dependencies
結果1
('私', '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
[(<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++はどうなったんだろう?
- 参考にもあげた記事の方が書いているようにserverを立てようかなと思う。全部合わせて docker imageにしてしまうつもり。
参考
https://qiita.com/gayou/items/ddfd4f3ac6092faf180e
https://stanfordnlp.github.io/stanfordnlp/