以前、自然言語の評価基準「BERTScore」を使って、類似度の高い文章をスコア順に並べました。しかし、あまりにも計算が遅かったので軽量化します。
この記事について
自然言語処理をとりあえず試してみたい人がターゲットです。自然言語処理で登場する、難しい計算や図について、私はよく分かりません。
分からなくても何とか出来ることを、実感できればと思います。
事前準備
環境の用意や、参考サイトは以前の記事をご確認ください。
テストする文章も前回と同じです。
1 2 3 4 |
吾輩は猫である 未来の世界の猫である 猫型のロボットである 眼鏡をかけた黄色い服の少年 |
この4つの文章を他3つの文章と比べ、類似度のスコアを出しましょう。
前回のコードは単純な総当たりでの類似度計算で、500件くらいの文章を処理すると3日かかりました。
コードに無駄が多かったので改修します。
文章Aと文章B、文章Bと文章Aの組み合わせ計算は同じなので、再計算しないようにしています。
軽量化したPythonコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
from bert_score import score def calc_bert_score(cands, refs): Precision, Recall, F1 = score(cands, refs, lang="ja", verbose=True) # スコア Precision Recall F1 return F1.numpy().tolist() if __name__ == "__main__": with open("test.txt") as f: list = [line.strip() for line in f] F1List = list.copy() result = [] len = len(list) max = len - 1 for index, item in enumerate(list): # 総当たり用配列(全部同じ値 × 行数) cands = [] for j, item in enumerate(list): if j == max: break cands.append(list[index]) print(str(len - max) + ' / ' + str(len)) # 総当たり数(max)を1ずつ減らす max -= 1 if max == -1: break del F1List[0] F1 = calc_bert_score(cands, F1List) data = [] line = 0 for item in result: data.append([item[index][0], line]) line += 1 for item in F1: if line == index: # 同じ文章はスコア0に data.append([0, line]) line += 1 data.append([round(item, 4), line]) line += 1 result.append(data) # 最終組み合わせ data = [] for i, item in enumerate(result): data.append([item[index][0], i]) data.append([0, i + 1]) result.append(data) for i, item in enumerate(result): n = 0 print(list[i][:20]) # スコアソート item.sort(reverse=True) for score in item: print(" " + str(score[0]) + " : " + list[score[1]][:20]) n += 1 if n == 3: break |
出力結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
吾輩は猫である 0.7528 : 未来の世界の猫である 0.6964 : 猫型のロボットである 0.6372 : 眼鏡をかけた黄色い服の少年 未来の世界の猫である 0.7528 : 吾輩は猫である 0.7367 : 猫型のロボットである 0.6647 : 眼鏡をかけた黄色い服の少年 猫型のロボットである 0.7367 : 未来の世界の猫である 0.6964 : 吾輩は猫である 0.682 : 眼鏡をかけた黄色い服の少年 眼鏡をかけた黄色い服の少年 0.682 : 猫型のロボットである 0.6647 : 未来の世界の猫である 0.6372 : 吾輩は猫である |
0.7528というような数字が類似度のスコアです。
高いほど似ている文章となります。スコアとしては「吾輩は猫である」と、「未来の世界の猫である」が最も類似していることになります。
計算速度アップ
前回28.5秒だった計算が、22.8秒になりました。
4件だと微妙な速度アップですが、大量の計算だと1日差がでることもあるでしょう。