QEUR23_LMABYS9: (準備運動)GPT4Allの回答の品質評価
~ 準備運動しましょ ~
QEU:FOUNDER : “さて、本格的にLLM(大規模言語)モデルの評価を行う前に、GPT4Allでの事例研究(ケーススタディ)をやりましょう。”
D先生 : “全然ダメダメGPTでの事例ですね。”
QEU:FOUNDER : “じゃあ、回答の評価プログラムに行きましょう。”
# -----
# 回答品質を評価する
# インポート
import pandas as pd
import numpy as np
import nltk
nltk.download('punkt')
from nltk.tokenize import sent_tokenize
from transformers import AutoTokenizer, AutoModel
import torch
import torch.nn.functional as F
############
# BLEUに代る回答品質の評価指標を作りたい
# 2つの文の類似度を比較するためのプログラム
# Mean Pooling - Take attention mask into account for correct averaging
def mean_pooling(model_output, attention_mask):
token_embeddings = model_output[0] #First element of model_output contains all token embed-dings
input_mask_expanded = attention_mask.unsqueeze(-1).expand(token_embeddings.size()).float()
return torch.sum(token_embeddings * input_mask_expanded, 1) / torch.clamp(input_mask_expanded.sum(1), min=1e-9)
# Load model from HuggingFace Hub
tokenizer = AutoTokenizer.from_pretrained('sentence-transformers/all-MiniLM-L6-v2')
model = AutoModel.from_pretrained('sentence-transformers/all-MiniLM-L6-v2')
# -----
# 文全体をベクトル化する
def create_embedding(sentences):
# Tokenize sentences
encoded_input = tokenizer(sentences, padding=True, truncation=True, return_tensors='pt')
# Compute token embeddings
with torch.no_grad():
model_output = model(**encoded_input)
# Perform pooling
sentence_embeddings = mean_pooling(model_output, encoded_input['attention_mask'])
# Normalize embeddings
sentence_embeddings = F.normalize(sentence_embeddings, p=2, dim=1)
return sentence_embeddings
# -----
# コサイン類似度計算
def cons_similarity(sentences):
# -----
# ベクトル化
sentence_embeddings = create_embedding(sentences)
#print("Sentence embeddings:")
#print(sentence_embeddings)
# -----
# NUMPY変換、配列の大きさを確認する
mx_embedding = np.array(sentence_embeddings)
#print(mx_embedding.shape)
a = mx_embedding[0]
b = mx_embedding[1]
cos = np.dot(a, b)/(np.sqrt(np.dot(a, a))*np.sqrt(np.dot(b, b)))
return cos
# -----
# 文章と文に分割する
def split_sentences(text: str) -> list:
texts = sent_tokenize(text)
return texts
# -----
# 文章のコサイン比較を実行する
def compare_cos(num_sentence, mx_sentences):
arr_cos = []
arr_text = []
for k in range(num_sentence):
sentences = mx_sentences[k].tolist()
#print(sentences[0])
#print(sentences[1])
# -----
# 個別類似度の測定
cos = cons_similarity(sentences)
arr_cos.append(cos)
arr_text.append(sentences[1])
#print("--- 中間計算 ---")
#print(f"ベース文: {sentences[0]}, 比較文: {sentences[1]}")
#print(f"コサイン類似度: {cos}")
# -----
# 最大類似度の計算と注目テキスト
max_cos = np.max(arr_cos)
fctext = arr_text[np.argmax(arr_cos)]
return max_cos, fctext
##################################
##################################
# 質問と回答のデータベースをロードする
df = pd.read_excel('USverify100_gpt(Raw).xlsx')
print(len(df))
# -----
df_cut = df.loc[:,["NO","Question","Reference","Type","Answer"]]
answer_list = df["Answer"].values
#print(answer_list[0:20])
# -----
reference_list = df["Reference"].values
#print(reference_list[0:20])
# -----
type_list = df["Type"].values
print(type_list[0:20])
##################################
##################################
# リストを指定する
arr_sentence = []
arr_cos = []
arr_fctext = []
# 質問番号を指定する
for j_Question in range(100):
# -----
# 回答文章を文に分割する
text = answer_list[j_Question]
#print(text)
texts = split_sentences(text)
num_sentence = len(texts)
#print(texts)
# -----
str_reference = str(reference_list[j_Question]).replace("\n", "")
mx_sentences = []
for i in range(num_sentence):
str_texts = str(texts[i]).replace("\n", "")
mx_sentences.append([str_reference, str_texts])
mx_sentences = np.array(mx_sentences)
#print(mx_sentences)
# -----
# データベース上の文章を連続して比較をする
max_cos, fctext = compare_cos(num_sentence, mx_sentences)
# -----
# リストを指定する
arr_sentence.append(num_sentence)
arr_cos.append(max_cos)
arr_fctext.append(fctext)
# 結果の表示
print(f"---- NO:{j_Question}, TYPE:{type_list[j_Question]}")
print(f"文の数: {num_sentence}")
print(f"注目文: {fctext}")
print(f"最大コサイン類似度: {max_cos}")
# 結果リストの表示
print("---------")
print(arr_sentence)
print("---------")
print(arr_cos)
print("---------")
print(arr_fctext)
# -----
# データフレームを生成する
df_out = df_cut.copy()
df_out["num_sen"] = arr_sentence
df_out["fctext"] = arr_fctext
df_out["cos"] = arr_cos
print(df_out)
# -----
# 出力のファイル名を UScos100_gpt(Raw)_no2.xlsx, シート名を Sheet_name_1 として保存する。
df_out.to_excel("UScos100_gpt(Raw)_no2.xlsx",sheet_name="Sheet_name_1")
QEU:FOUNDER : “もうさんざん解説をしたので、解析結果だけを話します。質問の型式である「open_qa」と「classification」で層別して、COS類似度の平均値を比較しました。”
(Langchainなし) / (LangChainあり)
Open_qa : 0.632 / 0.596
Classification : 0.194 / 0.256
D先生 : “どう評価したらいいものやら・・・。”
QEU:FOUNDER : “この(sentence-transformer)コサイン類似度って、どれほど精密な尺度じゃないです。値が0.5位でも合格の回答もたくさんありますから・・・。だから、数値が高い(0.5以上)の件数を調べたほうがいいです。”
(Langchainなし) / (LangChainあり)
Open_qa : 32 / 36
Classification : 4 / 9
D先生 : “明らかに良化しましたね。”
~ まとめ ~
QEU:FOUNDER : “天気も熱いので、「ゆるい」話題を・・・。”
C部長 : “ワロタ・・・。”
QEU:FOUNDER : “笑いごとじゃないんですがね・・・。”
コメント
コメントを投稿