Posted at

TermExtractで手軽にキーワード抽出 for Python

More than 1 year has passed since last update.

TermExtractはテキストデータから専門用語を取り出すためのモジュールらしいです。

専門用語(キーワード)自動抽出システム

これまではPerlのモジュールとしてしか提供されてませんでしたが、去年末にPython向けにβ版が出たようです。テキスト解析する際の未知語対策として利用できないかと思い、試しに使ってみました。


インストール

公式からzipファイルをダウンロードし、適当な場所に解凍して以下を実行するだけです。

python setup.py install

pipとかcondaからのインストールは残念ながらなさそうです。


形態素解析器の出力結果を使ったキーワード抽出

公式には、


和文の形態素解析ソフトである和布蕪の形態素解析結果を受け取り、複合語(空白区切りの単名詞)のリストか、ディクショナリ(複合語をキー、複合語の出現回数を値)を返す。


とあります。

渡す形態素解析結果というのは、以下のような形式で渡すみたいです(以下公式のサンプルテキスト)。


sample.txt

自然言語処理  名詞,一般,*,*,*,*,ダミー,ダミー,ダミー

( 記号,括弧開,*,*,*,*,(,(,(
り 助動詞,*,*,*,文語・リ,基本形,り,リ,リ
、 記号,読点,*,*,*,*,、,、,、
英 名詞,一般,*,*,*,*,ダミー,ダミー,ダミー
語 名詞,一般,*,*,*,*,ダミー,ダミー,ダミー
: 名詞,サ変接続,*,*,*,*,*
natural 名詞,一般,*,*,*,*,*
language 名詞,一般,*,*,*,*,*
processing 名詞,一般,*,*,*,*,*




Mecabでの形態素解析結果が、一行ごとに分かれている形ですね。これを以下のPythonスクリプトで読み込みます。

import termextract.mecab

import termextract.core
import collections

# ファイルを読み込む
tagged_text = open("sample.txt", "r", encoding="utf-8").read()

# 複合語を抽出し、重要度を算出
frequency = termextract.mecab.cmp_noun_dict(tagged_text)
LR = termextract.core.score_lr(frequency,
ignore_words=termextract.mecab.IGNORE_WORDS,
lr_mode=1, average_rate=1
)
term_imp = termextract.core.term_importance(frequency, LR)

# 重要度が高い順に並べ替えて出力
data_collection = collections.Counter(term_imp)
for cmp_noun, value in data_collection.most_common():
print(termextract.core.modify_agglutinative_lang(cmp_noun), value, sep="\t")

出力は以下のような感じになります。

自然言語処理  31.843366656181313

they 11.618950038622252
意味 10.392304845413264
英語 10.059467437463484
基礎技術 9.361389277282864
統計的自然言語処理 9.085602964160698
解析 8.485281374238571



結果はまずまずな感じで、それなりに複合語が抽出できてます(明らかにおかしいケースも多々ありますが・・・)。

ただ、入力がMecabの形態素解析結果というのが微妙に使いにくいですね。プレーンなテキスト、もしくは分かち書きしたテキストが渡せれば、もっと使いやすいと感じました。


和文ストップワード方式のキーワード抽出

別方式での抽出も提供されているみたいです。その一つである和文ストップワード方式の専門用語抽出は、公式で以下のように説明されています。


和文のプレインテキストを受けとり、複合語(空白区切りの単名詞)のリストか、ディクショナリ(複合語をキー、複合語の出現回数を値)を返す。複合語の切り出しは「ひらがな」「記号」による文の分割。


ひらがな・記号を区切りとしてトークナイズするってことだと思われます(すみません、ちゃんと読んでません・・・)

こちらは、プレーンなテキストを読み込ませるだけです。

import collections

import termextract.japanese_plaintext
import termextract.core

# ファイルを読み込む
text = open("sample.txt", "r", encoding="utf-8").read()

# 複合語を抽出し、重要度を算出
frequency = termextract.japanese_plaintext.cmp_noun_dict(text)
LR = termextract.core.score_lr(frequency,
ignore_words=termextract.japanese_plaintext.IGNORE_WORDS,
lr_mode=1, average_rate=1
)
term_imp = termextract.core.term_importance(frequency, LR)

# 重要度が高い順に並べ替えて出力
data_collection = collections.Counter(term_imp)
for cmp_noun, value in data_collection.most_common():
print(termextract.core.modify_agglutinative_lang(cmp_noun), value, sep="\t")

出力は以下のような感じになります。

人工知能  1226.4288753047445

人間 277.1173032591193
知能 185.75930965317852
開発 88.6373649378885
意識 60.00624902367479
人工的 57.917332434843445
可能 55.20783921098894



こちらは手軽に使えるのがいいですね。


両方式の比較

上記で、形態素解析結果方式とストップワード方式の二つを紹介しましたが、各方式での上位スコア20件を見てみます。


形態素解析方式

知能  12.649110640673518

計算知能 5.029733718731742
戦闘機 4.7381372205375865
戦闘 4.58257569495584
戦闘機操縦用 4.4406237146062955
計算機 4.426727678801286
人工知能 4.355877174692862
研究 4.0
計算 4.0
自動操縦 3.9359793425308607
学習 3.872983346207417
自動戦闘システム 3.802742902833608
人工知能技術 3.7719455481170785
論理計算 3.7224194364083982
機械学習 3.6628415014847064
記号的AI 3.6342411856642793
自動操縦可能 3.5254687665352296
論理 3.4641016151377544
機械 3.4641016151377544
機械式計算機 3.413473673690155


ストップワード方式

人工知能  1226.4288753047445

人間 277.1173032591193
知能 185.75930965317852
開発 88.6373649378885
意識 60.00624902367479
人工的 57.917332434843445
可能 55.20783921098894
研究 51.27978102078589
学習 49.31317739277511
人工知能学会 48.855373993311964
実現 48.748063633179314
理論 40.51490946041508
発表 39.39438441683934
計算知能 35.98098913381863
可能性 34.82443169313786
手法 34.6517883306879
利用 32.82677759681713
知的 31.52620185751426
動作 30.582796407248203
行動 30.582796407248203
登場 29.146786564179294

パッと見た感じだと、やはり形態素解析方式のほうが重要なキーワードをハイスコアで抽出できてそうですね。


感想

Mecab + Neologdでは検出できない未知語対応の手軽な対応手段として、検討してもいいかも?ただ、形態素解析方式の場合はモジュールとして使いにくので、薄いラッパー的なものを自分で作る必要がありそう。あと、ちゃんと検証も必要。