QEUR23_LMABYS11: Llama2の精度評価(英語方面)
~ 注:今回の精度評価法はQEUオリジナルです(多分) ~
D先生 : “LLM(大規模言語モデル)を使う環境が揃ったので、これからモデルの精度を評価するんですよね?”
QEU:FOUNDER : “今回も、US永住権認証試験(改)のデータを使います。もちろん、英語の部分を使います。”
D先生 : “ちなみに、前回やってみたGPT4Allを使ったときの正解率は、以下のような感じでした。普通のPCのcpuでも動くモデルの「出来栄え」はこの程度なのは、しようがないかと・・・。”
----- | Langchainなし | LangChainあり |
---|---|---|
Open_qa : | 32/61 | 36/61 |
Classification : | 4/39 | 9/39 |
QEU:FOUNDER : “今回使用したLLMで回答するためのプログラムは、次回の「日本語編」で晒します。ロジックの基本は前回のプログラムと同じですからね。ちなみに、その結果として、このような(↓)感じに100件の回答結果が出力されます。”
QEU:FOUNDER : “そして、その結果を読み込んで精度評価を行います。・・・では、プログラムをドン!!”
D先生 : “ちょっと待った。どんな精度評価を行ったんですか?そのメトリックスの由来を説明してください。”
QEU:FOUNDER : “この精度評価法は我々のオリジナルになると思います。「sentence-transformer」を使います。これは、文を特徴ベクトルに変換するものであり、この技術はLangChainにも使われています。このベクトルを基準となる回答例を変換したベクトルと比較するために、「COS類似度」を使います。ちなみに、あのLangChainでも言語データを切り刻んだ「Chunk」という言語単位をCOS類似度で比較して、もっとも類似度が高いChunkを採用するんです。”
D先生 : “要するに、我々の評価法はLangChainのVector Store技術の応用にすぎないと・・・。”
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("/content/drive/MyDrive/LCdocs/QEU-verify100-en(Raw).xlsx")
#print(df)
#len(df)
df = pd.read_excel("QEU-verify100-en(Raw).xlsx")
#print(df)
len(df)
#####
# 統計(前半)
print("--- 合計(サイズ) ---")
grouped = df.groupby("Type")
df_count = grouped.sum().loc[:,"COUNT"]
print(df_count)
#####
# 分析用のデータを抽出する
# -----
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 = []
arr_correct = []
# 質問番号を指定する
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 = reference_list[j_Question].replace("\n", "")
str_reference = str_reference.replace("'", "")
mx_sentences = []
for i in range(num_sentence):
str_texts = texts[i].replace("\n", "")
str_texts = str_texts.replace("'", "")
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)
val_correct = 0
if max_cos > 0.5:
val_correct = 1
# -----
# リストを指定する
arr_sentence.append(num_sentence)
arr_cos.append(max_cos)
arr_fctext.append(fctext)
arr_correct.append(val_correct)
# 結果の表示
print(f"---- NO:{j_Question}, TYPE:{type_list[j_Question]}")
print(f"文の数: {num_sentence}")
print(f"注目文: {fctext}")
print(f"最大コサイン類似度: {max_cos}")
print(f"正解ポイント: {val_correct}")
# 結果リストの表示
print("---------")
print(arr_sentence)
print("---------")
print(arr_cos)
print("---------")
print(arr_fctext)
# -----
# データフレームを生成する
df_out = df_cut.copy()
#df_out = df_out[0:5]
#print(df_out)
# -----
df_out["num_sen"] = arr_sentence
df_out["cos"] = arr_cos
df_out["correct"] = arr_correct
df_out["fctext"] = arr_fctext
print(df_out)
#####
# 統計(後半)
# -----
# 平均
print("--- 平均 ---")
grouped = df_out.groupby("Type")
df_mean = grouped.mean().loc[:,["cos","correct"]]
print(df_mean)
# -----
# 結合
df_stat = pd.merge(df_count, df_mean, on='Type')
print("--- 合計(サイズ) ---")
print(df_stat)
# -----
# CSV ファイル (UScos100_llama(Raw).xlsx) として出力
df_out.to_excel("UScos100_llama(Raw).xlsx")
D先生 : “いきなり結果からいえば、以下の表がLlama-v2-13b(GPTQ)のパフォーマンスになるわけですね。やはりGPT4Allとは比較にならないほどレベルが高いです。”
QEU:FOUNDER : “それでも、かなり不正解があるんですよね。ちなみに、不正解というのはCOS類似度が0.5以下として定義しています。”
D先生 : “あの・・・、具体的にどんな不正解があるんですか?”
D先生 : “えっ!?「不正解リスト」の中にも、正解があるじゃないですか・・・。”
QEU:FOUNDER : “まずはNO7の例を見てみましょう。27件というのは正解なのですが、「matter」なのか「amendment」なのかで差異が生じました。当たり前ながら、数字の類似度はあまり評価されないんですよ。NO8の場合は、もう、どうしようもないです。言い回しが違うだけで、内容は完全に正解なんですよ・・・。”
D先生 : “NO8の回答は、Llama2の答えの方がいいと思いますがね。”
~ まとめ ~
・・・ 前回のつづきです ・・・
QEU:FOUNDER : “ネトウヨってYouTubeの「申し子」だと思っているんです。つまり、歴史のような複雑なモノを取り扱うには、現状のメディアは不完全です。個人の好奇心が必要になるのは大前提にはなります。しかし、今の技術をうまく使えば「ネトウヨの量産」は回避できるんですよ。”
C部長 : “そういえば、FOUNDERは、いまでもMMT(現代貨幣理論)を信じているんですか?”
QEU:FOUNDER : “さあね・・・(笑)。あれって、「J国スゴイ」がベースとなっている理論でしょ?”
C部長 : “えっ!?(〇国スゴイと)関係あるの?しかし、愛国のFOUNDERも変わったものだ。”
QEU:FOUNDER : “昔よく見た「愛国番組」でよく言っていました。A国とC国はもうやっている。K国はできないが、J国はできるんだって・・・。じゃあ、今の状況を精査して、K国ができなくってJ国ならできるという理由はなんなん?”
C部長 : “理論破綻しますね。いやいや、ここは一転して、「K国も成長した、いまならK国もできる」って言うんじゃないんですか?”
QEU:FOUNDER : “こんなこと(↑)言っていた人が?”
C部長 : “(爆笑)”
QEU:FOUNDER : “本件は、もっとマジメに説明しようとすればできるのだが、この説明がもっともわかりやすいでしょ?”
- おっさん(@QCサークル講話);「従業員の皆さんにはテレビを見てください。皆が同じように考えてください。」
- オッサン(@車中、N社検査不正について): 「“検査不正”っていうのはなァ、(組織外に不正を)漏らしたヤツが悪いんだよ・・・」
- オッサン(海外工場のあいさつにて):「私の使命はこの会社で終身雇用制を実現することにある・・・。」
QEU:FOUNDER : “ただし、小生は本件は楽観的なんです。J国には「優秀なシニア層」という超分厚い人材層があって、彼らは昔、自分は偉いんだっていつも言ってました。小生も心から尊敬しています。ここは、彼らががんばって窮状を救ってくれると確信しています。”
コメント
コメントを投稿