termextractを使って記事で使われている専門用語の自動抽出を試してみよう

2022-10-14

イントロダクション

このブログの更新をポチポチ進めています。 Wordpressから移植してきた記事にタグ設定が一切されていないことに気が付きました。 気が付きましたというかずっと放置してたのが正しいですね。

見返してみると大小あれど、200記事近く書いてきたので手作業でタグ付けする必要があるのですが、正直やりたくないです。

termxtractという専門用語抽出用のライブラリがあるようですのでそれを動かしてみようかしらというのが今日の趣旨です。

terxtract

”専門用語(キーワード)自動抽出システム”のページへようこそ

公式からの説明文をまるごと引用します。

当サイトでは、専門用語(キーワード)自動抽出システムの基本システムおよび応用システムを提供しています。
  専門用語(キーワード)自動抽出システムとは、単なる文章の単語分割ではありません。一般に文章中では複数の単語の組み合わせで複雑な概念を表す場合が多く、文章の内容が専門的な事項に特化すればその傾向はさらに顕著なものとなるでしょう。したがって文章中からキーワードを抽出する場合、単語分割機能だけでは意味を成しません。そこで、このシステムでは、(1)形態素解析プログラムによる単語分割、(2)複合語の作成、(3)文章中における重要度の計算、という3つのステップを踏むことで、複合語により複雑な概念を表すことが多い専門用語をキーワードとして文章中から抽出することに成功しました。
・自作の文章からキーワードを抽出したい!
・メタデータ作成のためにウェッブサイトからキーワードを抽出したい!
・言語学的な研究に利用したい!
など様々な利用方法が考えられると思いますので、ご自由にお使いだください。

形態素解析だけでは意味の類推できない単語を、繋げていい感じに計算するとまずは理解しました。 結構今回の用途にぴったりじゃないかと思います。

install

Pythonで試していきましょう。 専門用語(キーワード)自動抽出Pythonモジュールtermextract

本体のDLです。とりあえず直リンを叩いてDLしてきました。 Windowsで実行しています。

curl http://gensen.dl.itc.u-tokyo.ac.jp/soft/pytermextract-0_02.zip -o pytermxtract.zip
curl http://gensen.dl.itc.u-tokyo.ac.jp/soft/pytermextract-0_02.zip -o pytermxtract.zip
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  693k  100  693k    0     0   552k      0  0:00:01  0:00:01 --:--:--  552k

DLしてきたzipファイルを解凍します。

Expand-Archive .\pytermxtract.zip
cd .\pytermxtract\

本体をインストールします。

pip install .             

無事に実行できるとこんな感じです。

Processing d:\src\python\termextract\pytermxtract
  Preparing metadata (setup.py) ... done
Using legacy 'setup.py install' for termextract, since package 'wheel' is not installed.
Installing collected packages: termextract
  Running setup.py install for termextract ... done
Successfully installed termextract-0.12b0

実行に必要となる形態素解析ライブラリなどを追加していきます。 英語と日本語でとりあえずいいですかね。

pip install janome nltk

無事に実行できるとこんな感じです。

Requirement already satisfied: janome in c:\users\kenpo\appdata\local\programs\python\python310\lib\site-packages (0.4.2)
(中略)
Requirement already satisfied: regex>=2021.8.3 in c:\users\kenpo\appdata\local\programs\python\python310\lib\site-packages (from nltk) (2022.8.17)
Requirement already satisfied: tqdm in c:\users\kenpo\appdata\local\programs\python\python310\lib\site-packages (from nltk) (4.64.0)
Requirement already satisfied: colorama in c:\users\kenpo\appdata\local\programs\python\python310\lib\site-packages (from click->nltk) (0.4.5)
Installing collected packages: joblib, click, nltk
Successfully installed click-8.1.3 joblib-1.2.0 nltk-3.7

sampleに入っていたコードを実行してみる。 読み込ませるテキストファイルは過去記事のMarkdownファイルを使うことにする。

python termex_jpn_plain.py kigi.md

実行結果貼り付ける。

```	399.73478958141993
###	79.99999999999999
"bitflyer"	58.944503978246175
```	39.79949748426479
記載	37.2092957441843
}	33.297799220076186
##	32.0
{	31.30169160146575
"config	30.178402312390453
go	27.603919605494468
Config	26.944387170614956
"2021	25.298221281347036
iniファイル	25.238858928247925
"api_key"	24.85786004763087
"api_secret"	24.85786004763087
APIキー	19.79898987322333
ini"	19.1012077113392
ini	16.1120976856959
####	16.0
config	16.0
bitflyer	15.0
23"	14.226235280311382
"	14.226235280311382
"Failed	13.239003678587492
中身	12.24744871391589
config	11.313708498984761
ini	10.816653826391967
"golang"	10.582454175217517
%v"	10.169211627335248
"log"	10.059467437463484
"os"	10.059467437463484
"fmt"	10.059467437463484
config"	9.319944406005703
ConfigList{	8.559305551469302
記事	8.031068545740872
go	7.937253933193772
"golang	7.871958685061721
string	7.4448388728167965
golang	7.348469228349534
ファイル	7.211102550927978
:=	7.200411487357017
file:	7.200411487357017
ApiKey:	7.200411487357017
ApiSecret:	7.200411487357017
利用	7.135242690016327
err	7.0
webp"	6.590195889768262
v1"	6.590195889768262
作成	6.260338320293149
本記事	6.068002663979602
部分	6.0
cfg	6.0
"コンピュータ	5.981395124884882
"program_1614450578	5.981395124884882
"アプリ	5.981395124884882
"gopkg	5.981395124884882
定義	5.180040128222703
Section	5.0
Key	5.0
別ファイル	4.997998798878767
操作	4.898979485566356
設定値	4.529868801645403
Config	4.426727678801286
tags:	4.391029277219845
作成	4.279652775734651
構造体	4.160167646103808
ConfigList	4.0
log	4.0
os	4.0
String	4.0
fmt	4.0
mod	3.7224194364083982
sum	3.7224194364083982
今回	3.4641016151377544
紹介	3.4641016151377544
準備	3.4641016151377544
執筆	3.4641016151377544
mod	3.4641016151377544
ApiKey	3.4641016151377544
ApiSecret	3.4641016151377544
Go	3.363585661014858
│	3.363585661014858
XXXXXX	3.363585661014858
XXXXXXXXXXXXXXXXX	3.363585661014858
main	3.363585661014858
title:	3.2531531233955713
date:	3.2531531233955713
categories:	3.2531531233955713
coverImage:	3.2531531233955713
description:	3.2531531233955713
E:	3.2531531233955713
下記	3.19343686757474
Trade	3.0
touch	3.0
api_key	3.0
api_secret	3.0
└─Config	2.728523203642732
modファイル	2.4989993994393833
sumファイル	2.4989993994393833
初期ファイル	2.4341306737344115
用テンプレートプロジェクト	2.0
プログラム	2.0
ニーズ	2.0
テンプレート	2.0
init	2.0
package	2.0
import	2.0
ConfigList	2.0
func	2.0
Load	2.0
if	2.0
nil	2.0
Printf	2.0
to	2.0
read	2.0
Exit	2.0
セクション	2.0
Println	2.0
自動取引ツール	1.8131474454755332
最初	1.681792830507429
失敗時	1.5874010519681994
自前	1.5650845800732873
アプリ	1.4142135623730951
実際	1.4142135623730951
終了	1.4142135623730951
箇所	1.4142135623730951
要素	1.4142135623730951
名称	1.4142135623730951
表示	1.4142135623730951
main	1.4142135623730951
当面	1.4142135623730951
過程	1.4142135623730951
小出	1.4142135623730951
02	1.0
サンプル	1.0
mkdir	1.0
XXXX	1.0
サービス	1.0
シークレットキー	1.0
コード	1.0
in	1.0
type	1.0
struct	1.0
var	1.0
ロード	1.0
ソフト	1.0
パッケージ	1.0
println	1.0

これによると、15~19以上の単語を選べば結構いい結果がでそうですね。 例外設定を行って実行すればこのブログの記事系統も取り出して遊べたり等もできそうですね。

微修正を加えてみる

99.9%ぐらいはサンプルそのままです。 例外の文字列を指定してみるとこんな感じかしら。

import sys
import collections

import termextract.core
import termextract.japanese_plaintext

def output(data):
    """
    処理結果を"jpn_plain_extracted.txt"に出力
    """
    outfile = open("jpn_plain_extracted.txt", "w", encoding="utf-8")
    data_collection = collections.Counter(data)
    for cmp_noun, value in data_collection.most_common():
        outfile.write(termextract.core.modify_agglutinative_lang(cmp_noun))
        outfile.write("\t")
        outfile.write(str(value))
        outfile.write("\n")
    outfile.close()

if __name__ == "__main__":
    ARGVS = sys.argv
    infile = open(ARGVS[1], "r", encoding="utf-8")
    text = infile.read()
    infile.close()

    ignore_words = ["###","```","##","#","####","#####","|","```","\"","{","}","%v",'```']
    frequency = termextract.japanese_plaintext.cmp_noun_dict(text)
    # term_list = termextract.japanese_plaintext.cmp_noun_list(text)
    lr = termextract.core.score_lr(frequency, lr_mode=1,ignore_words=ignore_words, average_rate=1)
    term_imp = termextract.core.term_importance(frequency, lr)
    output(term_imp)

まとめ

遊んでみましたがどうでしょうかね。 かなり手軽に試せるのがいいですね。ただ実行結果はかなり調整しないと自動タグ付けの目的を果たすのは難しそうな印象を受けました。 残念です。