Lora微调Deepseek-llm-7B-chat
一、单机多卡训练
- 方法一:把AutoModelForCausalLM.from_pretrained的参数device_map改为"auto",可自动把模型和数据分配到多个GPU上
- 方法二:也可以使用 Accelerate,其是一个分布式训练工具包,提供底层的分布式训练基础。它更倾向于与##手动训练##循环配合使用,而不是与高级抽象如 Trainer 配合使用。
二、把数据转换为模型可以处理的格式
-
基础知识
输入模型的数据需要进行处理,一般模型都会有聊天模版,可以用apply_chat_template函数直接处理或者手动处理。处理后的输出包括:
- input_ids:是输入序列token的id列表,用于模型输入
-attention_mask: 用于指示模型在处理输入序列时应关注哪些标记。
-labels(训练时候需要): 是目标序列的标记 ID 列表。不需要计算损失的标签需要被设置为 -100。注意:由于我们模型的目的是预测下一个token,因此某一位值labels的实际值是该位置的下一位input_id。但是由于某些datacollator例如DataCollatorForLanguageModeling会自动让labels向右位移一位,所以不需要手动位移。
-
tokenizer.apply_chat_template函数
用于将对话格式的聊天数据转换为模型可以处理的输入格式,对于不同的模型,输出格式会有所不同。-
参数说明:
messages: 对话列表,每个元素是一个字典,包含 role (system/user/assistant) 和 content (文本内容)
tokenize: 是否直接进行tokenize (默认True,返回token IDs;False则返回格式化后的字符串)
add_generation_prompt: 是否添加提示词表示需要模型生成回复 (默认False),推理时候要设置为True
return_tensors: 返回的张量格式 (“pt” for PyTorch, “tf” for TensorFlow)
truncation=True:当输入文本长度超过 max_length 时,自动截断超出的部分
max_length:设置文本最大长度
padding:设置padding方式,可选 max_length,False,longest -
注意:
1.该函数输出的attention_mask填充部分为0,其余部分为1。
2.这个函数并不输出labels,训练时候若需要,要手动设置 -
不同模型示例 :
deepseek-ai/deepseek-llm-67b-chat:<|begin▁of▁sentence|>你是一个乐于助人的助手。 User: 你好,你叫什么名字? Assistant: 我是DeepSeek助手,很高兴为您服务!<|end▁of▁sentence|
Qwen/Qwen1.5-7B-Chat:
<|im_start|>system 你是一个乐于助人的助手。<|im_end|> <|im_start|>user 你好,你叫什么名字?<|im_end|> <|im_start|>assistant 我是DeepSeek助手,很高兴为您服务!<|im_end|>
-
-
处理指令对话数据
-
单轮对话数据
- 直接用apply_chat_template函数,然后创建一个labels,因为我们不需要学习assistant回答之外的内容,因此可以创建一个与input_id一样的数组,然后把system和user内容的labels设为-100,其余值不变,最后输出三者。
- 手动设置。
按照模型的对话模板手动设置三者,此时要在对话末尾注意添加eos_token。EOS的label要设置为-100,mask为1(因为我们需要关注EOS的生成,否则无法学习到何时生成EOS),EOS的input_id为tokenizer.eos_token_id,很多模型的EOS和PAD的id一样。
例如:input_ids, attention_mask, labels = [], [], [] instruction = tokenizer(f"User: {example['instruction']+example['input']}\n\n", add_special_tokens=False) # add_special_tokens 不在开头加 special_tokens response = tokenizer(f"Assistant: {example['output']}", add_special_tokens=False) input_ids = instruction["input_ids"] + response["input_ids"] + [tokenizer.pad_token_id] attention_mask = instruction["attention_mask"] + response["attention_mask"] + [1] labels = [-100] * len(instruction["input_ids"]) + response["input_ids"] + [tokenizer.pad_token_id]
-
多轮对话数据
- 与单轮对话类似
- 与单轮对话不同的是,我们不止要在对话末尾添加EOS,而是要在每次助手回复的内容后加上EOS,否则模型不会学习停止回答。
-
-
DataCollator
DataCollator 的主要作用是在训练前对一批(batch)样本进行处理,确保它们具有相同的格式和长度,以便能够组成一个有效的张量(tensor)输入模型。一般在在训练时被调用。
在这里介绍几个常见的DataCollator-
DataCollatorForLanguageModeling
- 作用:专门用于语言建模任务,包括:
- 因果语言建模:预测下一个token(如GPT系列)
- 掩码语言建模:预测被掩盖的token(如BERT系列)
- 关键参数:
tokenizer: 必需的分词器实例
mlm:是否使用掩码语言建模,False 表示使用因果语言建模。
当 mlm=False(因果LM)时:label会和input_ids一样,即使你自己设置了labels也会覆盖。自动将labels向左移动一位,并对最后一个token进行掩码;
当 mlm=True(掩码LM)时:会随机选择15%的token进行掩盖(80%用[MASK],10%用随机token,10%保持不变)
mlm_probability:当 mlm=True 时,token被掩盖的概率(默认0.15)
pad_to_multiple_of:将序列长度填充到该值的倍数(有助于某些硬件加速)
return_tensors:返回的张量类型,通常是 "pt"(PyTorch)
padding:padding的方式,新版取消了,默认padding到序列最长。如需要设置padding方式,需要配合DataCollatorWithPadding
注意:如果数据有column,记得remove_columns=['xxxx'],否则会报错
-
DataCollatorForSeq2Seq
- 作用:专门用于序列到序列的任务,如翻译、摘要、对话生成,微调就用这个。作用是让每一个batch内的input_ids和labels都长度对齐
- 关键参数:
tokenizer: 必需的分词器实例
model:可选的模型实例(用于自动获取decoder_start_token_id等)
padding:是否进行填充(默认为True)
max_length:最大序列长度
pad_to_multiple_of:填充到的倍数
label_pad_token_id:用于填充labels的token ID(默认为-100)
return_tensors:返回的张量类型
-
还有DataCollatorForTokenClassification、DataCollatorForWholeWordMask、DataCollatorForSeq2Seq、DataCollatorWithPadding等
-