さて、前回までは環境設定とツールの説明まででした。今回からは少しづつ各ツールを使った分析を行っていきます。
お題目の自然言語処理ですが、例えば、「本発明はエネルギーを消費することなく自律走行が可能な移動体に関わる。」というようなテキストを分析する場合に、自然言語処理はこれをこのまま処理するのではありません。ざっくりいうと、元のテキストからひらがなを抜いて切り分けたようなキーワードの集まり、(「本発明」、「エネルギー」、「消費」、「自律走行」、「可能」、「移動体」・・・)のような形式に変換する必要があります。自然言語処理では、このような変換処理の後で、これらのキーワードが幾つあるか(頻度)、どのような並びで出現しているか(位置関係)等に基づいて分析を行っていきます。
前述の切り分け処理を形態素解析等と呼びます。前回までの環境設定で導入したMeCabもその一つですが、他にもJanomeやJuman等があります。
まずは、MeCabを使った形態素解析について、Jupyter Notebook上での処理の具体例を説明していきます。
Jupyter NoteBookを起動して、新規でPython3のNoteBookを作成したら、Mecabが使えるようにMecabのTaggerを呼び出します。
from MeCab import Tagger
分析対象となるテキストとして上述した例のテキストを設定します。
target_text = u"本発明はエネルギーを消費することなく自律走行が可能な移動体に関わる。"
MecabのTaggerオブジェクトをmとして生成し、mに上記のテキスト例の形態素分析を行わせた上で結果を出力させます。
m = Tagger()
print(m.parse(target_text))
基本的なJupyter NoteBook上での形態素分析について説明しました。
次は実践編として、特許公報の発明の詳細な説明全体を取り込んで、Mecabで形態素解析を行った上で、形態素解析で切り分けたキーワードの頻度を分析する手法について説明していきます。特許公報のデータは、本日時点でJ-PlatPatの分類検索でIoT系の特許分類ZITでヒットする特許公報の内で最初の案件、特開2017-139005「肌状態測定分析情報管理システムおよび肌状態測定分析情報管理方法」の発明の詳細な説明全体をコピーして、メモ帳にテキストを張り付けて、文字コードをUTF-8にして(ここ大事)、ファイル名samplepatent.txtとして保存しました。
Jupyter NoteBookを起動して、新規でPython3のNoteBookを作成したら、初期設定として、Mecabとキーワードカウント用にCounterを呼び出すとともに、分析元の特許公報データのテキスト名をfname、形態素解析を行った後のテキストデータの保管先のファイル名をfname_parsedに設定します。
import MeCab
from collections import Counter
fname = 'samplepatent.txt'
fname_parsed = 'samplepatent.txt.mecab'
with open(fname) as data_file, open(fname_parsed, mode='w') as out_file:
mecab = MeCab.Tagger()
out_file.write(mecab.parse(data_file.read()))
出来上がる形態素分析済みのファイルの中身は次のようになります。
【 記号,括弧開,*,*,*,*,【,【,【
発明 名詞,サ変接続,*,*,*,*,発明,ハツメイ,ハツメイ
の 助詞,連体化,*,*,*,*,の,ノ,ノ
詳細 名詞,形容動詞語幹,*,*,*,*,詳細,ショウサイ,ショーサイ
な 助動詞,*,*,*,特殊・ダ,体言接続,だ,ナ,ナ
説明 名詞,サ変接続,*,*,*,*,説明,セツメイ,セツメイ
】 記号,括弧閉,*,*,*,*,】,】,】 ….
形態素解析後のファイルを呼び出して、上から順に処理してmorphemesに辞書のリストとして保存していきます。分析結果の分かりやすさのために名詞の形態素のみをリストに追加するようにしています。
with open(fname_parsed) as file_parsed:
morphemes = []
for line in file_parsed:
# 表層形はtab区切り、それ以外は','区切りでバラす
cols = line.split('\t')
if(len(cols) < 2):
continue
res_cols = cols[1].split(',')
# 辞書作成、リストに追加(名詞のみ)
if res_cols[0] == '名詞':
morpheme = {
'surface': cols[0],
'base': res_cols[6],
'pos': res_cols[0],
'pos1': res_cols[1]
}
morphemes.append(morpheme)
{‘base’: ‘発明’, ‘pos’: ‘名詞’, ‘pos1’: ‘サ変接続’, ‘surface’: ‘発明’},
{‘base’: ‘発明’, ‘pos’: ‘名詞’, ‘pos1’: ‘サ変接続’, ‘surface’: ‘発明’},
{‘base’: ‘詳細’, ‘pos’: ‘名詞’, ‘pos1’: ‘形容動詞語幹’, ‘surface’: ‘詳細’},
{‘base’: ‘詳細’, ‘pos’: ‘名詞’, ‘pos1’: ‘形容動詞語幹’, ‘surface’: ‘詳細’},
{‘base’: ‘説明’, ‘pos’: ‘名詞’, ‘pos1’: ‘サ変接続’, ‘surface’: ‘説明’},
{‘base’: ‘説明’, ‘pos’: ‘名詞’, ‘pos1’: ‘サ変接続’, ‘surface’: ‘説明’},
{‘base’: ‘説明’, ‘pos’: ‘名詞’, ‘pos1’: ‘サ変接続’, ‘surface’: ‘説明’}, ….]
word_counter = Counter()
for morpheme in morphemes:
word_counter.update([morpheme['surface']])
for word, cnt in word_counter.most_common():
print (word, cnt)