【Datawhale AI夏令营第四期】 浪潮源大模型应用开发方向笔记 Task05 源大模型微调实战代码精读 RAG测试 AI简历助手代码优化 网课剩余部分
教程基础背景知识:
微调能解决的问题正好是我需要的——模型在某个特定方面上能力不够。我感觉这种情况适用于让模型去完成特定小众的任务,比如原神数值分析,原神剧情梳理啥的,不属于普罗大众知识库的专精小微领域?我感觉也能用在我们草台班子的人话八股文助手里面,不过我暂时还没有具体的应用方案。
关于Lora的部分,之前AIGC方向的教案和笔记有详细介绍。我印象里是把新得到的矩阵理解为两个矩阵的乘积(比如100x100理解为一个100xk的矩阵再乘一个kx100的矩阵),然后根据需要调节k的大小来控制参数的复杂度。
模型加载与数据处理:
这个JSON是一条条包含提示词和答案的数据:
找一条数据出来看:
这个数据处理函数特别长:
# 定义数据处理函数 接收一个样本(example)作为输入,并对其进行预处理
def process_func(example):
MAX_LENGTH = 384 # Llama分词器会将一个中文字切分为多个token,因此需要放开一些最大长度,保证数据的完整性
instruction = tokenizer(f"{
example['input']}<sep>") #instruction: 使用 tokenizer 对输入文本进行分词。这里使用了 <sep> 作为分隔符
response = tokenizer(f"{
example['output']}<eod>") #response: 使用 tokenizer 对输出文本进行分词。这里使用了 <eod> 作为结束标记
input_ids = instruction["input_ids"] + response["input_ids"] #input_ids: 将 instruction 和 response 的 input_ids 合并在一起
attention_mask = [1] * len(input_ids)
labels = [-100] * len(instruction["input_ids"]) + response["input_ids"] # instruction 不计算loss labels: 构造标签序列,其中 instruction 部分的标签设置为 -100,这在训练过程中会被忽略,不会计算损失
if len(input_ids) > MAX_LENGTH: # 做一个截断 如果合并后的 input_ids 长度超过了 MAX_LENGTH,则对 input_ids、attention_mask 和 labels 进行截断
input_ids = input_ids[:MAX_LENGTH]
attention_mask = attention_mask[:MAX_LENGTH]
labels = labels[:MAX_LENGTH]
return {
#返回一个字典,包含 input_ids、attention_mask 和 labels
"input_ids": input_ids,
"attention_mask": attention_mask,
"labels": labels
}
说真的,恕我才疏学浅,真没看明白????
感觉他这个数据处理过程占了代码的大头。我后面自己跟着代码敲了一遍,又向Kimi请教,还是没完全理解究竟这复杂的处理过程具体每一步有什么意义……
但是大概功能就一句话,翻译。把人话翻译成模型能懂的。
# 处理数据集 使用了之前定义的 process_func 函数来处理数据集 ds,并对处理后的数据集进行了列的移除。下面是这段代码的详细解释:
tokenized_id = ds.map(process_func, remove_columns=ds.column_names) #通过 remove_columns 参数移除了原始数据集中的所有列。这意味着处理后的数据集将只包含由 process_func 函数返回的新列
tokenized_id #通过 map 方法将 process_func 函数应用于数据集中的每一个样本
Lora部分:
然后就是这种形式的Lora代码,最近AIGC和大模型应用方向都在提:
高深的玩法我没见识过,但就我这几次学习遇到Lora相关代码的经验来看,感觉Lora这个概念被包装得看着很高大上,往简单了想,本质上就是要么换数据集调教模型,要么就是改这个config配置里面的这几个超参数。
问了一下Kimi,跟我预计的差不多,粗略地可以这么理解。
我感觉人工智能很多东西其实本质用起来并不难,特别是一般人的应用场景(算法巨佬卷王不在讨论范围),可能就是换换数据集改参数的事,但是非要拿英文包装个很高大上的概念,吓得人望而却步。
既然这些Lora相关的都是超参数,我又想起我之前学过还写了笔记的一样东西——自动调参神器Optuna。
https://blog.csdn.net/bailichen800/article/details/140362947
传送门
那么Lora能不能也用Optuna来帮忙寻找最合适的超参数呢?
问了Kimi——可以的!!!!!!
我们让Kimi写一段示例代码,发现用起来并不复杂,也就是按套路引入库+调函数+改参数的事。
import optuna
from peft import LoraConfig, TaskType, get_peft_model
from transformers import AutoModelForCausalLM, AutoTokenizer
from datasets import load_dataset
# 假设我们有一个加载数据集的函数
def load_data():
# 这里加载你的数据集
dataset = load_dataset("your_dataset_script")
tokenizer = AutoTokenizer.from_pretrained("model_name")
return dataset, tokenizer
# 定义目标函数,Optuna将调用此函数来评估超参数
def objective(trial):
# 加载数据集和tokenizer
dataset, tokenizer = load_data()
# 定义超参数搜索空间
r = trial.suggest_int('r', 4, 64) # LoRA的秩
lora_alpha = trial.suggest_int('lora_alpha', 8, 128) # LoRA的缩放因子
# 创建LoRA配置
lora_config =