spaCyで英語の文をトークナイズする方法を丁寧に
はじめに
本記事では,spaCy
を用いて英文をトークナイズする方法を紹介します.
トークナイズに関する情報を比較的詳しく解説するとともに,公式ドキュメントやソースコードへの導線を張ることを目的にしています.
本記事に書いてあることは,公式ドキュメントの以下のページに書いてあることとほとんど変わりません.公式ドキュメントほど信頼性が高いものはありませんので,先にこちらを読まれるのをお勧めします.
Linguistic Features · spaCy Usage Documentation
目次
モジュールのインポート
インポートは一行です.
import spacy
モデルの作成
まずは,トークナイズを行うモデルを読み込みます.これはspacy.load(モデル名)
で書けます.今回は英文を対象とするので,英語のモデルとして一般的に使われているen_core_web_sm
を読み込んでいます.
import spacy nlp = spacy.load('en_core_web_sm')
もしエラーが出る場合は,en_core_web_sm
のモデルがインストールされていないので,
python -m spacy download en_core_web_sm
でインストールしてください.
モデルは英語以外にも用意されています.各言語に対応するモデルは以下の公式ドキュメントを参考にしてください.
Models · spaCy Models Documentation
英文のトークナイズとDocオブジェクト
読み込んだモデルは関数のように扱うことができます.入力は文字列で,出力はspaCy独自のDocオブジェクトになります.
Docオブジェクトの詳細: Doc · spaCy API Documentation
import spacy nlp = spacy.load('en_core_web_sm') sent = "I don't like apple." doc = nlp(sent) print(type(doc)) ''' 出力: <class 'spacy.tokens.doc.Doc'> '''
Docオブジェクトは,トークナイズ後の単語列に関する情報が含まれていて,リストのような振る舞いをします.例えば,0
番目を参照すると,先頭単語に関する情報が得られます.よって,一般的なリストのように,indexによる参照と,for文による先頭単語からの参照が可能です.
import spacy nlp = spacy.load('en_core_web_sm') sent = "I don't like apple." doc = nlp(sent) # for文で参照 for token in doc: print(type(token), token) # indexで参照 print(doc[0]) ''' 出力: <class 'spacy.tokens.token.Token'> I <class 'spacy.tokens.token.Token'> do <class 'spacy.tokens.token.Token'> n't <class 'spacy.tokens.token.Token'> like <class 'spacy.tokens.token.Token'> apple <class 'spacy.tokens.token.Token'> . I '''
このように参照したオブジェクトは,print()
するとトークナイズ後の単語がそのまま出力されます.上の例では,don't → do n't
やapple. → apple .
のようにトークナイズされていることが分かります.ただし,型は文字列ではなく,spaCy独自のTokenオブジェクトになります.
よって,単にトークナイズ後の表層系だけ欲しい場合は
import spacy def tokenizer(nlp, sent): doc = nlp(sent) return ' '.join([tok.text for tok in doc]) nlp = spacy.load('en_core_web_sm') sent = "I don't like apple." print(tokenizer(nlp, sent)) ''' 出力: I do n't like apple . '''
のように多少自作しなければなりません..text
については次の節で説明します.
Tokenオブジェクトの機能
spaCy独自のTokenオブジェクトは,様々な情報を持っています.単語を表す文字列の情報はもちろん,その単語の品詞や係り受けなどの情報を持ちます.
以下では公式ドキュメントが紹介している代表的な属性を紹介します.
import spacy nlp = spacy.load('en_core_web_sm') sent = "I don't like apple." doc = nlp(sent) # 3番目のトークン token = doc[2] print('.text: ', token.text, type(token.text), sep='\t') print('.lemma_: ', token.lemma_, type(token.lemma_), sep='\t') print('.pos_: ', token.pos_, type(token.pos_), sep='\t') print('.tag_: ', token.tag_, type(token.tag_), sep='\t') print('.dep_: ', token.dep_, type(token.dep_), sep='\t') print('.shape: ', token.shape_, type(token.shape_), sep='\t') print('.is_alpha:', token.is_alpha, type(token.is_alpha), sep='\t') print('.is_stop: ', token.is_stop, type(token.is_stop), sep='\t') ''' 出力: .text: n't <class 'str'> .lemma_: not <class 'str'> .pos_: ADV <class 'str'> .tag_: RB <class 'str'> .dep_: neg <class 'str'> .shape: x'x <class 'str'> .is_alpha: False <class 'bool'> .is_stop: False <class 'bool'> '''
.text
は,単語そのものです..lemma_
は,単語の原形です.例えば,go
,went
,going
のlemmaは全てgo
です..pos_
は,品詞です.詳しくは.pos_の品詞タグ早見表
の節で説明しますが,17種類あります..tag_
は,より詳細な品詞です.例えば,.pos_
では単にNOUN
(名詞)と表されるものが,.tag_
ではNNS
(複数形の名詞)のように表されるようなことです.タグの一覧は以下を参照してください.spaCy/tag_map.py at 3ddb799f27578d3eed39ded12fc812609106b26c · explosion/spaCy · GitHub
.dep_
は,構文の依存関係を表します.詳しくは構文依存関係について
の節を参照してください..shape_
は,単語の形を表します.具体的には,各文字について,大文字はX
,小文字はx
,数字はd
に変換して表示します.記号はそのままです.例えば,aA2'!$#&%
はxXd'!$#&%
となります..is_alpha
は,単語がアルファベットだけで構成されているかを判定します.数字や記号が一つでも混じっているとFalse
になります..is_stop
は,ストップワードかどうか判定します.英語におけるストップワードの単語集合は,以下を参照してください.(他の言語についても,同じようにソースを見に行けば単語集合を得られます.)spaCy/stop_words.py at 3ddb799f27578d3eed39ded12fc812609106b26c · explosion/spaCy · GitHub
これ以外にもたくさんの属性が用意されています.詳しくは以下を参照してください.
Token · spaCy API Documentation
.pos_の品詞タグ早見表
品詞タグは17種類あります.Universal POS tagsを利用しています.
縦長になるので横に並列して書くことにします.
品詞タグ | 意味 | 品詞タグ | 意味 |
---|---|---|---|
ADJ | 形容詞 | PART | 助詞 |
ADP | 設置詞 | PRON | 代名詞 |
ADV | 副詞 | PROPN | 固有名詞 |
AUX | 助動詞 | PUNCT | 句読点 |
CONJ | 接続詞 | SCONJ | 連結詞 |
DET | 限定詞 | SYM | シンボル |
INTJ | 間投詞 | VERB | 動詞 |
NOUN | 名詞 | X | その他(主に未知語) |
NUM | 数詞 |
.dep_: 構文依存関係について
構文依存関係は.dep_
で参照できる情報で,係り受けを表すものです.例えば,動詞の目的語を特定できます.
公式ドキュメントでは明確に言及にしている記述が見つけられませんでしたが,おそらくUniversal Dependenciesを用いていると思います.これについては,数が非常に多いため,一つ一つ解説することは避けます.参考1(英語,公式),参考2(日本語,ブログ記事)を参照してください.
参考2: 自然言語処理におけるPOSタグと係り受けタグ一覧 - Qiita
係り受け解析の可視化
係り受け解析の結果は,spaCyのモジュールdisplacy
を使うことで可視化できます.このモジュールは,spaCy2.0以降に実装されています.具体的には,displacy.serve()
関数を使います.入力として<class 'spacy.tokens.doc.Doc'>
型のトークナイズした直後のオブジェクトを与えると,ローカルサーバの上で図が閲覧できます.
import spacy from spacy import displacy nlp = spacy.load('en_core_web_sm') sent = "I don't like apple." doc = nlp(sent) displacy.serve(doc, style="dep") ''' 出力: Using the 'dep' visualizer Serving on http://0.0.0.0:5000 ... '''
これを実行するとServing on http://0.0.0.0:5000 ...
と表示されるので,ブラウザでlocalhost:5000
にアクセスすると,係り受けの可視化図が閲覧できます.この図には,各単語の係り受け.dep_
の情報と,その品詞.pos_
の情報が含まれています.
おわりに
今回はspaCyによる英文トークナイズについて紹介しました.思ったよりざっくりとした記事になった気もしますが,参考になれば幸いです.他に面白そうな機能を見つけたら随時更新するかもしれません.
間違いなどあればご指摘お願いいたします.