#この記事の目的
最近, Pythonで日本語での固有表現抽出(Named Entity Recognition; NER)を簡単に使いたいなと思っていろいろ探していたろころ, GiNZA
というものを知ったので使ってみました.
ちなみに, 固有表現抽出は自然言語処理のタスクの1つで, 以下の図のように日付や人物など, 特定の単語を検出するもののことです.
GiNZAについて
GiNZA
は自然言語処理(Natural Language Processing; NLP)を行うためのライブラリの1つで, 固有表現抽出以外にも様々なタスクをこなすことができます.
正確には, spaCy
という自然言語処理ライブラリがあるのですが, その日本語処理部分を担当しているといった感じです. そのため, spaCy
の使い方がわかる方なら早いと思います.
詳細は, 以下をご確認ください. 今回は固有表現抽出に限って紹介します.
GitHub:megagonlabs/ginza
第4回 spaCy/GiNZA を用いた自然言語処理
準備
はじめに, GiNZA
とspaCy
を準備します.
!pip install -U ginza
import spacy
from spacy import displacy
nlp = spacy.load('ja_ginza')
これで, spaCy
側でGiNZA
のモデルが読み込めたので, 処理の準備完了です.
Jupyter Notebook
を使っている場合, ここでつまづくことがあるそうなので, その際はGitHubをご参照ください.
データの用意
次に解析対象のサンプルデータを用意します.
今回は, ロンウイット社が公開しているlivedoor ニュースのデータを使います.
データは, 9つのジャンルに分かれたニュースなので, 今回はそれらから1つずつニューステキストを抽出し, 9つのニューステキストに対して, 固有表現抽出を行っていきます.
これにより, テキストのジャンルの得意・不得意などが分かるのではないかという思惑です.
ここからデータをダウンロードして解凍します.
livedoor ニュースコーパス
!wget https://www.rondhuit.com/download/ldcc-20140209.tar.gz
!tar zxvf ldcc-20140209.tar.gz
固有表現抽出
テキストファイルのパスを指定すれば, それを読み込んで解析を行うようにコードを書きました. 試しに, 独女通信の1記事を分析してみました.
#テキスト読み込み
filepath = "./text/dokujo-tsushin/dokujo-tsushin-4778030.txt"
with open(filepath) as f:
s = f.read()
#ここでいろんな処理が行われる
doc = nlp(s)
#固有表現抽出の結果の描画
displacy.render(doc, style="ent", jupyter=True)
いい感じに抽出できていますね!
ただ, 見た目の問題ですが, 色の指定がPERSONやTIMEなどにしかされておらず, 少し見づらいです. そこでオプションで色を変えてみます.
#抽出したエンティティの種類に対して色を指定する
colors = {"COUNTRY":"#00cc00", "CITY":"#00cc00", "GPE_OTHER":"#00cc00","OCCASION_OTHER":"#00cc00",
"LOCATION":"#00cc00", "LOCATION_OTHER":"#00cc00","DOMESTIC_REGION":"#00cc00","PROVINCE":"#00cc00",
"STATION":"#00cc00", "CONTINENTAL_REGION":"#00cc00","THEATER":"#00cc00",
"TIME":"#adff2f","DATE":"#adff2f","DAY_OF_WEEK":"#adff2f",
"PERIOD_YEAR":"#adff2f", "PERIOD_MONTH":"#adff2f", "PERIOD_DAY":"#adff2f",
"FLORA":"#adff99","FLORA_PART":"#adff99",
"DISH":"#ffeb99","FOOD_OTHER":"#ffeb99",
"AGE":"#3385ff","N_PERSON":"#3385ff","N_EVENT":"#3385ff","N_LOCATION_OTHER":"#3385ff","RANK":"#3385ff",
"N_PRODUCT":"#3385ff","":"#3385ff","":"#3385ff","":"#3385ff","MEASUREMENT_OTHER":"#3385ff","PERCENT":"#3385ff",
"N_ORGANIZATION":"#3385ff", "ORDINAL_NUMBER":"#3385ff", "N_FACILITY":"#3385ff","SPEED":"#3385ff",
"PHONE_NUMBER":"#3385ff",
"MONEY":"#ffff00",
"COMPANY":"#99c2ff", "SCHOOL":"#99c2ff", "INTERNATIONAL_ORGANIZATION":"#99c2ff",
"GOE_OTHER":"#99c2ff", "SHOW_ORGANIZATION":"#99c2ff","CORPORATION_OTHER":"#99c2ff",
"CLOTHING":"#ff66a3",
"PRODUCT_OTHER":"#ff66a3",
"PERSON":"#c266ff",
"POSITION_VOCATION":"#ebccff",
"MUSIC":"#ff7f50", "MOVIE":"#ff7f50", "GAME":"#ff7f50", "SPORT":"#ff7f50", "BOOK":"#ff7f50",
"BROADCAST_PROGRAM":"#ff7f50",
"ANIMAL_DISEASE":"#cd5c5c"
}
options = {"colors": colors}
displacy.render(doc, style="ent", options=options, jupyter=True)
場所系の単語は緑, 組織系の単語は青など, 適当に設定しました. 改善の余地大有りです.
今回はあくまで実験なので, これで良しとして, これを使って9つのニュース記事を固有表現抽出しました. 結果は以下の通りです.
独女通信
ITライフハック
家電チャンネル
livedoor HOMME
MOVIE ENTER
Peachy
エスマックス
Sports Watch
トピックニュース
色を設定すると, デフォルトよりは見やすくなりますね. (ちょっと目がチカチカする気もしますが...)
ニュースのジャンルによっても, エンタメ系は人物が多かったり, ガジェット系は製品や企業の名前が多かったりと一目瞭然ですね.
肝心の精度ですが, ジャンルによっては多少気になる単語もあるものの, 概ねよく抽出できていると言えるのではないでしょうか.
個人的にはITライフハックの記事で「ヤモリ」がFOODに分類されているのが気になってしまいました.
参考
GitHub:megagonlabs/ginza
オブジェクトの広場:第4回 spaCy/GiNZA を用いた自然言語処理
株式会社ロンウイット:livedoor ニュースコーパス
spaCy:Visualizing the entity recognizer
spaCy:Named Entity Recognition