次のページを参考にしました。
Pythonで「Bag Of Words」を使い文章の類似度を調べる【自然言語処理】
ライブラリーのインストール
pip install janome
janome_check.py
#! /usr/bin/python
#
# janome_check.py
# Nov/27/2021
# ------------------------------------------------------------------
from janome.tokenizer import Tokenizer
import numpy as np
import sys
# ------------------------------------------------------------------
def gen_toks_list(sentence_list):
"""
文章のリストをJanomeのトークン列のリストに変換する
"""
t = Tokenizer()
return [list(t.tokenize(s)) for s in sentence_list]
# ------------------------------------------------------------------
def gen_word_to_index(toks_list):
"""
トークンの表層形から添え字を得られるようにマップを作成する
"""
word_to_index = {}
for toks in toks_list:
for tok in toks:
# もしトークンがマップに含まれていなければインデックスを追加する
if tok.surface not in word_to_index.keys():
new_index = len(word_to_index) # 新しいインデックスを作成
word_to_index[tok.surface] = new_index # マーク
return word_to_index
# ------------------------------------------------------------------
def gen_corpus(toks_list, word_to_index):
"""
行列の作成
"""
# len(toks_list) x len(word_to_index) の成分0の行列を作成
corpus = np.zeros((len(toks_list), len(word_to_index)))
# 行列を処理する
for i, toks in enumerate(toks_list):
# 行を処理する
for tok in toks:
# 行の持っているトークンの列に対してマーキング
corpus[i, word_to_index[tok.surface]] += 1
return corpus
# ------------------------------------------------------------------
def gen_bag_of_words(toks_list):
"""
Bag of Wordsを使って行列を作成
"""
word_to_index = gen_word_to_index(toks_list)
corpus = gen_corpus(toks_list, word_to_index)
return corpus
# ------------------------------------------------------------------
def cos_sim(x, y):
"""
類似度の計算
cos類似度という方法を用いる
"""
return np.dot(x, y) / (np.sqrt(np.sum(x ** 2)) * np.sqrt(np.sum(y ** 2)))
# ------------------------------------------------------------------
def show_per(corpus):
for it, vv in enumerate(['B', 'C', 'D', 'E']):
it += 1
per = cos_sim(corpus[0], corpus[it])
print(f'A vs {vv}: {per:.2}')
# ------------------------------------------------------------------
def proc01(sentence_list):
# トークン列のリストの作成
toks_list = gen_toks_list(sentence_list)
# Bag of Wordsの作成
corpus = gen_bag_of_words(toks_list)
# 結果を出力
show_per(corpus)
# ------------------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")
sentence_list = [
'昔ある所に、王様がいました。', # 文章A
'ある所に、かわいい女の子がいました。', # 文章B
'一人の王様がいました。', # 文章C
'昔ある所に、貧しい女がいました。', # 文章D
'昔、王様がある所にいました。', # 文章E
]
proc01(sentence_list)
sys.stderr.write("*** 終了 ***\n")
# ------------------------------------------------------------------
実行結果
$ ./janome_check.py
*** 開始 ***
A vs B: 0.82
A vs C: 0.6
A vs D: 0.87
A vs E: 1.0
*** 終了 ***