从代码中学习:评估模型的性能
在这篇博客中,我们将逐步解析一段Python代码,并解释每一行的作用。这段代码主要用于加载数据集、加载预训练模型、进行推理并评估模型的性能。我们将以简单易懂的方式解释每一部分,确保即使是小学生也能理解。
1. 导入必要的库
首先,我们需要导入一些Python库,这些库将帮助我们完成后续的任务。
import datasets
import tempfile
import logging
import random
import config
import os
import yaml
import logging
import difflib
import pandas as pdimport transformers
import datasets
import torchfrom tqdm import tqdm
from utilities import *
from transformers import AutoTokenizer, AutoModelForCausalLMlogger = logging.getLogger(__name__)
global_config = None
解释:
datasets
:用于加载和处理数据集的库。tempfile
:用于创建临时文件和目录。logging
:用于记录日志信息。random
:用于生成随机数。config
:用于管理配置文件的库。os
:用于与操作系统交互,如文件路径操作。yaml
:用于解析YAML格式的配置文件。difflib
:用于比较文本的差异。pandas as pd
:用于数据处理和分析。transformers
:用于加载和使用预训练的自然语言处理模型。torch
:PyTorch库,用于深度学习。tqdm
:用于显示进度条。AutoTokenizer
和AutoModelForCausalLM
:用于自动加载预训练的分词器和语言模型。
2. 加载数据集
接下来,我们加载一个名为lamini/lamini_docs
的数据集,并从中提取测试集。
dataset = datasets.load_dataset("lamini/lamini_docs")
test_dataset = dataset["test"]
解释:
datasets.load_dataset("lamini/lamini_docs")
:加载名为lamini/lamini_docs
的数据集。dataset["test"]
:从数据集中提取测试集。
3. 打印测试集中的第一个问题及答案
我们可以打印出测试集中的第一个问题和对应的答案,以便查看数据的内容。
print(test_dataset[0]["question"])
print(test_dataset[0]["answer"])
解释:
test_dataset[0]["question"]
:获取测试集中第一个问题的文本。test_dataset[0]["answer"]
:获取测试集中第一个问题的答案。
4. 加载预训练模型和分词器
我们加载一个名为lamini/lamini_docs_finetuned
的预训练模型及其对应的分词器。
model_name = "lamini/lamini_docs_finetuned"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(model_name)
解释:
model_name = "lamini/lamini_docs_finetuned"
:指定预训练模型的名称。AutoTokenizer.from_pretrained(model_name)
:加载与模型对应的分词器。AutoModelForCausalLM.from_pretrained(model_name)
:加载预训练的语言模型。
5. 定义一个简单的评估函数
我们定义一个函数is_exact_match
,用于判断两个字符串是否完全匹配。
def is_exact_match(a, b):return a.strip() == b.strip()
解释:
a.strip() == b.strip()
:去除字符串a
和b
两端的空白字符后,判断它们是否相等。
6. 设置模型为评估模式
在进行推理之前,我们需要将模型设置为评估模式。
model.eval()
解释:
model.eval()
:将模型设置为评估模式,这会关闭一些在训练时使用的功能,如Dropout。
7. 定义推理函数
我们定义一个函数inference
,用于生成模型的预测结果。
def inference(text, model, tokenizer, max_input_tokens=1000, max_output_tokens=100):# Tokenizetokenizer.pad_token = tokenizer.eos_tokeninput_ids = tokenizer.encode(text,return_tensors="pt",truncation=True,max_length=max_input_tokens)# Generatedevice = model.devicegenerated_tokens_with_prompt = model.generate(input_ids=input_ids.to(device),max_length=max_output_tokens)# Decodegenerated_text_with_prompt = tokenizer.batch_decode(generated_tokens_with_prompt, skip_special_tokens=True)# Strip the promptgenerated_text_answer = generated_text_with_prompt[0][len(text):]return generated_text_answer
解释:
tokenizer.encode(text, return_tensors="pt", truncation=True, max_length=max_input_tokens)
:将输入文本编码为模型可以理解的输入ID。model.generate(input_ids=input_ids.to(device), max_length=max_output_tokens)
:使用模型生成文本。tokenizer.batch_decode(generated_tokens_with_prompt, skip_special_tokens=True)
:将生成的token解码为文本。generated_text_with_prompt[0][len(text):]
:去除提示文本,只保留生成的答案。
8. 运行模型并比较预测结果与预期答案
我们使用模型生成答案,并将其与预期答案进行比较。
test_question = test_dataset[0]["question"]
generated_answer = inference(test_question, model, tokenizer)
print(test_question)
print(generated_answer)answer = test_dataset[0]["answer"]
print(answer)exact_match = is_exact_match(generated_answer, answer)
print(exact_match)
解释:
test_question = test_dataset[0]["question"]
:获取测试集中的第一个问题。generated_answer = inference(test_question, model, tokenizer)
:使用模型生成答案。answer = test_dataset[0]["answer"]
:获取测试集中的第一个问题的答案。exact_match = is_exact_match(generated_answer, answer)
:判断生成的答案与预期答案是否完全匹配。
9. 在整个数据集上运行模型并评估
我们可以在整个测试集上运行模型,并计算准确率。
n = 10
metrics = {'exact_matches': []}
predictions = []
for i, item in tqdm(enumerate(test_dataset)):print("i Evaluating: " + str(item))question = item['question']answer = item['answer']try:predicted_answer = inference(question, model, tokenizer)except:continuepredictions.append([predicted_answer, answer])exact_match = is_exact_match(predicted_answer, answer)metrics['exact_matches'].append(exact_match)if i > n and n != -1:break
print('Number of exact matches: ', sum(metrics['exact_matches']))
解释:
n = 10
:设置最大评估样本数为10。metrics = {'exact_matches': []}
:用于存储每个样本的匹配结果。predictions = []
:用于存储预测结果和真实答案。for i, item in tqdm(enumerate(test_dataset))
:遍历测试集中的每个样本。predicted_answer = inference(question, model, tokenizer)
:使用模型生成答案。exact_match = is_exact_match(predicted_answer, answer)
:判断生成的答案与预期答案是否完全匹配。if i > n and n != -1: break
:如果评估的样本数超过n
,则停止评估。
10. 将预测结果保存为DataFrame
我们可以将预测结果保存为Pandas DataFrame,以便进一步分析。
df = pd.DataFrame(predictions, columns=["predicted_answer", "target_answer"])
print(df)
解释:
pd.DataFrame(predictions, columns=["predicted_answer", "target_answer"])
:将预测结果和真实答案保存为DataFrame。
11. 加载评估数据集
我们还可以加载另一个评估数据集,以便进行更全面的评估。
evaluation_dataset_path = "lamini/lamini_docs_evaluation"
evaluation_dataset = datasets.load_dataset(evaluation_dataset_path)
解释:
datasets.load_dataset(evaluation_dataset_path)
:加载评估数据集。
12. 尝试ARC基准测试
最后,我们可以尝试使用ARC基准测试来评估模型的性能。
!python lm-evaluation-harness/main.py --model hf-causal --model_args pretrained=lamini/lamini_docs_finetuned --tasks arc_easy --device cpu
解释:
!python lm-evaluation-harness/main.py
:运行ARC基准测试脚本。--model hf-causal
:指定模型类型为因果语言模型。--model_args pretrained=lamini/lamini_docs_finetuned
:指定预训练模型。--tasks arc_easy
:指定任务为ARC Easy。--device cpu
:指定在CPU上运行。
总结
通过这篇博客,我们逐步解析了一段用于加载数据集、加载预训练模型、进行推理并评估模型性能的Python代码。希望这些解释能帮助你更好地理解每一行代码的作用,并激发你对Python编程的兴趣!