spaCyの固有表現抽出の使い方

spacy-ner-ja code

こんにちは、ヤギユキです。

渋谷のIT企業でエンジニアやっています。

本日は、spaCyというライブラリで文章から固有表現を抽出する方法を記事にしました。

spaCyは自然言語処理の多くのタスクを統合したライブラリです。

例えば、こんなことができます。

  • 固有表現抽出
  • 係り受け解析
  • 形態素解析

また、CNNで学習したモデルも組み込まれているので、学習データを用意する必要もありません。

手軽にディープラーニングで自然言語処理をやってみたい方にはとても便利です!

このspaCyですが、v2.2系までは、日本語の学習済みモデルがありませんでした。

よって、日本語の解析をするには、学習データを用意する必要がありました。(もしくは、GiNZAというspaCyの派生ライブラリを使う必要があった)

しかし、v2.3系から日本語の学習済みモデルが組み込まれたので、spaCy単体で日本語のデータ分析ができるようになりました!

 

環境構築

検証環境は、Colaboratoryを使います。
Colaboratoryは、googleが提供する無償のpython実行環境です。
jupyterインタフェースで操作ができて、今回のように、機械学習ライブラリの検証やデータ分析には、とても便利です。

この環境に検証に必要なライブラリをインストールします。
今回は、spaCyと学習済みモデルをインストールします。

spacyのインストール

Colaboratoryには、デフォルトでspacyが入っていますがバージョンが2.2系(2020/08月時点)です。 日本語の学習済みモデルを使う場合は、2.3系が必要なので、下記のように再インストールしましょう。

%%bash
pip install spacy==2.3.2

学習済みモデルのインストール

学習済みモデルには、大中小の3種類あります。

https://spacy.io/models/ja

今回は固有表現抽出を試しに使ってみることが目的であるので、一番小さいサイズをひとまずいれてみます。

%%bash
python -m spacy download ja_core_news_sm

固有表現の抽出

では、本題の固有表現抽出をやっています。
始める前に、以下でパッケージをリロードしておいてください。

import pkg_resources, imp
imp.reload(pkg_resources)

Colaboratoryの場合、上の処理をしておかないとインストールしたモデルが読み込めないので、やっておく必要があります。

では、試しに適当な文章から固有表現を抽出してみましょう。

import spacy

# モデルのロード
nlp = spacy.load("ja_core_news_sm")
# 解析対象のテキスト
input_text = "2018年の8月に旅行にフランスへ旅行に行った。ルーヴル美術館でモナリザの絵を見た。" 
# モデルに解析対象のテキストを渡す
doc = nlp(input_text)
# 固有表現を抽出
for ent in doc.ents: 
    print(ent.text, ent.label_, ent.start_char, ent.end_char)

# 2018年 DATE 0 5
# 8月 DATE 6 8
# フランス GPE 12 16
# ルーヴル美術館 ORG 24 31
# モナリザ PERSON 32 36

これだけです。非常に少ないコードで結果を出すことができます。

また、解析結果を可視化することもできます。

from spacy import displacy
displacy.render(doc, style="ent", jupyter=True)

ブログやプレゼンなどの説明に便利そうですね。

文脈と抽出結果

抽出結果は文脈にも多少依存があるようです。

例えば、以下の文章から固有表現を抽出すると、期待どおり「新宿」、「渋谷」、「銀座」が固有表現として抽出できます。

import spacy 
nlp = spacy.load("ja_core_news_sm") 
input_text = "渋谷、新宿、銀座へ遊びに行きました。" 

doc = nlp(input_text)
print(doc.ents)
# (渋谷, 新宿, 銀座)

ところが以下の文章では、固有表現は空で返却されます。

import spacy 
nlp = spacy.load("ja_core_news_sm") 
input_text = "銀座でランチをご一緒しましょう。"

doc = nlp(input_text)
print(doc.ents)

# ()

本来であれば、「銀座」が抽出できてほしいところですが、できていないですね。

冒頭で説明した通り、spaCyの学習済みモデルは、CNNベースのモデルです。
CNNベースのモデルは、連続性を考慮した学習に適していないので、文脈と抽出結果は依存しにくいと思ったのですが、多少は依存があるようですね。

ちなみに、連続した情報の解釈に有効な手段としては、RNNが有名です。
CNNとRNNの違いは、こちらが参考になるので興味がある方は見てください。

https://lionbridge.ai/ja/articles/neural-network-cnn-rnn/

ちなみに、2番目の例から「銀座」が抽出できない問題は、ja_core_news_mdかja_core_news_smのモデルを使うことで解消できました。

import spacy 
nlp = spacy.load("ja_core_news_md") 
input_text = "銀座でランチをご一緒しましょう。"

doc = nlp(input_text)
print(doc.ents)

# (銀座,)

以上です。

固有表現抽出以外でも、spaCyを使えば、いろんな自然言語処理タスクを手軽に試すことができます。
興味のある方はぜひ参考にしてください!

コメント

タイトルとURLをコピーしました