自然言語処理ライブラリspaCyを試してみた。
お恥ずかしながら、spaCyを最近知りましたので、試してみました。 spaCyは、pythonで動かす自然言語処理ライブラリです。
目次
- spaCyとは
- 環境
- 対応言語・モデル
- モデルのインポート
- テキストのインポートとトークン化
- 品詞タグ付け
- 固有表現抽出
- tokenに対する様々なメソッド
- 「文」に分割
- Semantic Similarity(意味的類似性)
- SpaCyとNLTKの比較
spaCyとは
spaCyは、pythonで動かす自然言語処理ライブラリです。特徴は、 事前に訓練された統計モデルと単語ベクトルが付属している点です。現在33言語をサポート、8言語に対する13個の統計モデルを利用できる。TensorFlow、PyTorch、scikit-learn、Gensim、その他のPythonのAIエコシステムとシームレスに相互運用可能。現在のバージョンはv2.x。
環境
- Python3系
- モデルがライブラリとしてインストール可能。pipでインストール。
pip install -U spacy
対応言語・モデル
複数の言語に対応していますが、今回は英語を扱います。英語には、4つほど学習済みの畳み込みニューラルネットワークモデル(CNN)があるようです。
モデルのインポート
en_core_web_smモデルが推奨されているようなので、デフォルトのまま利用します。
import spacy # 英語のtokenizer、tagger、parser、NER、word vectorsをインポート nlp = spacy.load('en_core_web_sm')
テキストのインポートとトークン化
# サンプルテキストに対する固有表現とエンティティタイプの抽出 text = u'My name is Ishio from Japan. Today, talk football!!' doc = nlp(text) token = doc[3] # Ishio print([d for d in doc]) print(token)
出力結果。
[My, name, is, Ishio, from, Japan, ., Today, ,, love, football, !, !] Ishio
品詞タグ付け
text = u'My name is Ishio from Japan. Today, talk football!!' doc = nlp(text) for d in doc: print((d.text, d.pos_, d.dep_))
出力結果。固有名詞はPROPNとなっています。
('My', 'ADJ', 'poss') ('name', 'NOUN', 'nsubj') ('is', 'VERB', 'ROOT') ('Ishio', 'PROPN', 'attr') ('from', 'ADP', 'prep') ('Japan', 'PROPN', 'pobj') ('.', 'PUNCT', 'punct') ('Today', 'NOUN', 'npadvmod') (',', 'PUNCT', 'punct') ('love', 'NOUN', 'ROOT') ('football', 'NOUN', 'dobj') ('!', 'PUNCT', 'punct') ('!', 'PUNCT', 'punct')
固有表現抽出
spaCyの学習済みモデルを利用して、文章内から、固有表現を抽出します
print([(d.text, d.label_, spacy.explain(d.label_)) for d in doc.ents])
出力結果。
[('Ishio', 'ORG', 'Companies, agencies, institutions, etc.'), ('Japan', 'GPE', 'Countries, cities, states'), ('Today', 'DATE', 'Absolute or relative dates or periods')]
3つの単語が固有表現とそのエンティティタイプが抽出されました。ちなみに、spacy.explain()は、ラベルに対する説明を返してくれます。例えばORGは「Companies, agencies, institutions, etc.」という意味になります。Todayも固有名詞として認識されているが、DATEとして認識されています。IshioはPERSONとして抽出されてほしかったですが、ORG(企業、組織等)として認識されました。(My Name is…としているのに。。。)。試しに、Ishioの部分をJohnに変更してみた結果、PERSONとして認識されました。
tokenに対する様々なメソッド
様々なNLPのためのメソッドが用意されていますので、いくつか試してみます。
text = u'My name is Ishio from Japan. I was born in Saitama!!' token = doc[3] # Ishio # トークン出力。 print(token) # Ishio # 再掲:品詞 print(token.pos_) # PROPN # 再掲:より細かめの品詞 print(token.tag_) # PROPN # 言語 print(token.lang_) # en # テキストの出力。末尾に空白文字があれば一緒に出力。 print(token.text_with_ws) # 'Ishio ' # 末尾に空白文字があれば出力。 print(token.whitespace_) # エンティティのタイプ print(token.ent_type_) # 'ORG' # 小文字化 print(token.lower_) # ishio # 接頭辞(デフォルト1文字)、接尾辞(デフォルト3文字) print(token.prefix_, token.suffix_ ) #('I', 'hio') token = doc[9] # born # 見出し語(lemma) print(token.lemma_) # bear # 正規化(normalization) print(token.norm_) # born
booleanを返してくれるメソッドも多数用意されています。多用しそうなものを列挙します
メソッド | 意味 |
---|---|
is_alpha | アルファベット |
is_ascii | ASCII文字 |
is_digit | 数字列 |
is_lower | 小文字 |
is_upper | 大文字 |
is_title | 先頭大文字 |
is_punct | 記号 |
is_left_punct | 左に記号があるか。# e.g. (? |
is_right_punct | 左に記号があるか。# e.g. ]? |
is_space | 空白文字 |
is_quote | クエスチョンマーク |
is_currency | 通貨記号 |
like_url | URLっぽいtokenを判定 |
like_num | 数字っぽいtokenを判定 |
like_email | メールアドレスっぽいtokenを判定 |
is_stop | ストップリストに含まれるか判定 |
「文」に分割
センテンス(文)に分割します。
text = (u"I am in Tokyo. I was born in Saitama.") doc = nlp(text) sents = list(doc.sents) print(sents)
出力結果。
[I am in Tokyo., I was born in Saitama.]
Semantic Similarity(意味的類似性)
apples, _, oranges = nlp(u'apples and oranges') a_o_similarity = apples.similarity(oranges) o_a_similarity = oranges.similarity(apples) print(a_o_similarity, o_a_similarity)
出力結果。0-1の値を返します。
0.60679483 0.60679483
text間の類似性も計算可能です。
doc1 = nlp(u"my name is John") doc2 = nlp(u"my name is Ishio") similarity = doc1.similarity(doc2) print(similarity)
出力結果
0.9182574986865027
SpaCyとNLTKの比較
Processing pipelineの部分はまた今度勉強します。