投稿日
大規模企業名辞書「JCLdic」で企業名を認識する
もくじ
はじめに
こんにちは。戦略技術センターの梁です。TIS入社3年目です。現在、自然言語処理の研究をやっています。
2020年3月末までの研究活動として、企業名のカバレージと表記ゆれを考慮した大規模企業名辞書「JCLdic」を作り上げました。
今回は「JCLdic」を作った経緯と辞書の使い方を紹介します。
背景
金融テキストを解析する際、辞書を用いて企業名を認識するアプローチはよく使われます。しかし、このアプローチは「辞書のカバレージが低い」と「表記揺れの対応が弱い」という欠点がありました。これらを解決するため、我々は大規模企業名辞書「JCLdic」を作りました。
「JCLdic」には、800万以上の企業名があり、ロングテールの企業名も含まれています。我々は、別名生成の手法を提案し、表記の揺れを考慮できるようにしました。関連のソースコードと論文は、以下で公開しています。
研究の経緯
カバレージ問題
日本で登録されている法人数は約500万です(表1) 。法人の種類を株式会社、有限会社、合同会社(営利企業)に絞っても、400万以上の企業があります。 表2は、テキストを解析する際によく使われている辞書のリストとその中に含まれる会社数です。これらの辞書は、企業名に特化した辞書ではありません。そのため、テキストに頻出する企業名は認識できますが、ロングテールの企業名を認識には課題がありました。
(表1):2019年12月31日まで。
(表2):2019年12月31日まで。
カバレージを上げるため、我々はウェブから企業名を収集するのではなく、国税庁に登録されているすべての法人を辞書に入れました。最終的に生成された辞書は、800万以上の企業名が含まれているため(表3)、ロングテールの企業名があってもカバーできます。
(表3)
表記揺れ問題
企業名は様々な表記で出現します(表4)。そのため、1つの名前を登録するだけでは、認識できない企業名が頻出します。
(表4)
表記の揺れを解決するため、我々は別名生成の手法を提案し、表記の揺れを考慮できるようにしました(表5)。
(表5)
実験で検証
実験では、JCLdicで企業名を認識し、CRFモデルの特徴にしてモデルの予測精度を上げました。MainichiとBCCWJはデータセットです。
Single Lexicon | Mainichi F1 (CRF) | BCCWJ F1 (CRF) |
---|---|---|
Gold | 0.7826 | 0.5537 |
JCL-slim | 0.7969 | 0.5892 |
JCL-meidum | 0.7927 | 0.5813 |
JCL-full | 0.8039 | 0.6205 |
Juman | 0.7923 | 0.5661 |
IPAdic | 0.7924 | 0.5961 |
NEologd | 0.7897 | 0.5718 |
Multiple Lexicon | ||
IPAdic-NEologd | 0.7986 | 0.6187 |
IPAdic-NEologd-JCL(medium) | 0.8009 | 0.6132 |
詳しい実験の内容は論文とHomepageに確認ください。
JCLdicの使い方
辞書の取得
- JCLdic Download Page JCL_slimを例にして、MeCab Dicをダウンロードします。
環境の準備
前提条件として、MeCabとmecab-python3はインストール済みとします。ダウンロードしたjcl_slim_mecab.dic
を指定のフォルダに移動します。
$ mkdir /usr/local/lib/mecab/dic/user_dict
$ mv jcl_slim_mecab.dic /usr/local/lib/mecab/dic/user_dict
MeCabの設定ファイルmecabrc
を更新して、辞書のパスを書きます。
$ vim /usr/local/etc/mecabrc
mecabrc
の中で、dicdir
システムの辞書パス、userdic
はユーザー辞書のパスです。JCLdicのパスをuserdic
に書きます。
dicdir = /usr/local/lib/mecab/dic/ipadic
;dicdir = /usr/local/lib/mecab/dic/mecab-ipadic-neologd
;dicdir = /usr/local/lib/mecab/dic/jumandic
;dicdir = /usr/local/lib/mecab/dic/unidic
userdic = /usr/local/lib/mecab/dic/user_dict/jcl_slim_mecab.dic
; output-format-type = wakati
; input-buffer-size = 8192
; node-format = %mn
; bos-format = %Sn
; eos-format = EOSn
複数のユーザー辞書のパスも指定できます。
userdic = /usr/local/lib/mecab/dic/user_dict/jcl_full_mecab_1.dic,/usr/local/lib/mecab/dic/user_dict/jcl_full_mecab_2.dic
これで準備が整いました。
コマンドラインでJCLdicを使う
jcl_slim_mecab.dic
を使わなかった結果:
▶ echo "TIS株式会社は自然言語処理で企業名認識を行うための辞書JCLdic(日本会社名辞書)を無償公開。" | mecab
TIS 名詞,固有名詞,組織,*,*,*,*
株式会社 名詞,一般,*,*,*,*,株式会社,カブシキガイシャ,カブシキガイシャ
は 助詞,係助詞,*,*,*,*,は,ハ,ワ
自然 名詞,形容動詞語幹,*,*,*,*,自然,シゼン,シゼン
言語 名詞,一般,*,*,*,*,言語,ゲンゴ,ゲンゴ
処理 名詞,サ変接続,*,*,*,*,処理,ショリ,ショリ
で 助詞,格助詞,一般,*,*,*,で,デ,デ
......
EOS
jcl_slim_mecab.dic
を使った結果:
▶ echo "TIS株式会社は自然言語処理で企業名認識を行うための辞書JCLdic(日本会社名辞書)を無償公開。" | mecab
TIS株式会社 名詞,固有名詞,組織,*,*,*,TIS株式会社,*,*
は 助詞,係助詞,*,*,*,*,は,ハ,ワ
自然 名詞,形容動詞語幹,*,*,*,*,自然,シゼン,シゼン
言語 名詞,一般,*,*,*,*,言語,ゲンゴ,ゲンゴ
処理 名詞,サ変接続,*,*,*,*,処理,ショリ,ショリ
で 助詞,格助詞,一般,*,*,*,で,デ,デ
......
EOS
ユーザー辞書もコマンドラインから直接指定できます。
▶ echo "TIS株式会社は自然言語処理で企業名認識を行うための辞書JCLdic(日本会社名辞書)を無償公開。" | mecab -u /usr/local/lib/mecab/dic/user_dict/jcl_slim_mecab.dic
PythonでJCLdicを使う
正規化
辞書のサイズを抑えることで、検索効率が上がります。そのため、JCLdicに収録された企業名はすべて半角にしています。テキストを解析する前に、正規化することをおすすめします。
import unicodedata
text = 'TIS株式会社'
text = unicodedata.normalize('NFKC', text) # convert zenkaku to hankaku
print(text)
出力:
TIS株式会社
辞書の指定方法
方法1:辞書のパスで指定 システム辞書は-d
、ユーザー辞書は-u
で指定します。
tagger = MeCab.Tagger('-d /usr/local/lib/mecab/dic/mecab-ipadic-neologd -u /usr/local/lib/mecab/dic/user_dict/jcl_slim_mecab.dic')
方法2:設定ファイルで指定 複数の辞書を導入したい場合、設定ファイルmecabrc
に追加すればいいです。
tagger = MeCab.Tagger('-r /usr/local/etc/mecabrc')
parse
メソッドで解析
import unicodedata
import MeCab
# import multiple dictionaries by mecabrc
tagger = MeCab.Tagger('-r /usr/local/etc/mecabrc')
text = 'TIS株式会社は自然言語処理で企業名認識を行うための辞書JCLdic(日本会社名辞書)を無償公開。'
# convert zenkaku to hankaku
text = unicodedata.normalize('NFKC', text)
# parse
print(tagger.parse(text))
出力:
TIS株式会社 名詞,固有名詞,組織,*,*,*,TIS株式会社,*,*
は 助詞,係助詞,*,*,*,*,は,ハ,ワ
自然 名詞,形容動詞語幹,*,*,*,*,自然,シゼン,シゼン
言語 名詞,一般,*,*,*,*,言語,ゲンゴ,ゲンゴ
処理 名詞,サ変接続,*,*,*,*,処理,ショリ,ショリ
で 助詞,格助詞,一般,*,*,*,で,デ,デ
...
EOS
parseToNode
メソッドで解析
組織
キーワードで企業名エンティティを認識します。
import unicodedata
import MeCab
tagger = MeCab.Tagger('-r /usr/local/etc/mecabrc')
text = 'TIS株式会社と株式会社インテックはグループの中核企業である。'
# convert zenkaku to hankaku
text = unicodedata.normalize('NFKC', text)
# parse
node = tagger.parseToNode(text)
result = []
while node:
# node feature map: 品詞,品詞細分類1,品詞細分類2,品詞細分類3,活用形,活用型,原形,読み,発音
# example: TIS: ['名詞', '固有名詞', '組織', '*', '*', '*', '有限会社TIS', '*', '*']
features = node.feature.split(",")
pos2 = features[2]
if pos2 == '組織':
result.append(node.surface)
node = node.next
print(result)
出力:
['TIS株式会社', '株式会社インテック']
非法人名の対応
JCLdicが収録された企業名は国税庁に登録されていた法人名です。しかし、ニュースでグループ名のような非法人名もあります。JCLdicはグループ名を収録していないため、グループ名のような非法人名の抽出はできません。 ただし、多くのグループ名はその主要企業の名称を含むため、結果的に関連している企業の抽出をできるケースが多いです。 例えば「TISインテックグループ」というグループ名があります。 このグループ名から関連している「TIS」と「インテック」2つの企業名が抽出されます。
import unicodedata
import MeCab
tagger = MeCab.Tagger('-r /usr/local/etc/mecabrc')
text = 'TISインテックグループのTIS株式会社は、自然言語処理で企業名認識を行うための辞書JCLdic(日本会社名辞書)を無償公開。'
# convert zenkaku to hankaku
text = unicodedata.normalize('NFKC', text)
# parse
node = tagger.parseToNode(text)
result = []
while node:
features = node.feature.split(",")
pos2 = features[2] if pos2 =='組織':
result.append(node.surface)
node = node.next
print(result)
出力:
['TIS', 'インテック', 'TIS株式会社']
おわりに
今回は「JCLdic」を作った経緯と使い方を紹介しました。
日本語の企業名は漢字、ひらがな、カタカナ、アルファベットなどの表記があるため、表記揺れを解決する難しさを改めて感じました。 今回出会った問題を次からの研究に活かすため、更に調査をおこない、より良い解決策を見つけようと考えています。
辞書の詳しい作り方を知りたい方は、論文を参考にしてみてください。ソースコードと辞書は、全部GitHubで公開しています。お気軽に試してください。
本コンテンツはクリエイティブコモンズ(Creative Commons) 4.0 の「表示—継承」に準拠しています。