加载含自定义AddedTokens的微调Llama模型尺寸不匹配问题求助
解决Llama-2微调后embed_tokens/lm_head权重尺寸不匹配的加载问题
核心原因
你微调时给分词器新增了3个自定义token,导致词汇表大小从32000变为32003,对应的embed_tokens和lm_head权重维度也同步扩容。但直接用AutoModelForCausalLM.from_pretrained加载时,默认会先加载原Llama-2基础模型(词汇表大小32000),再合并LoRA权重,这就触发了维度不匹配。而ignore_mismatched_sizes=True在此场景无效,因为它仅处理部分层参数数量差异,无法解决整个词汇表维度的变化问题。
正确加载步骤
1. 先加载自定义分词器
必须先加载微调时使用的、已添加新token的分词器,确保模型加载时获取正确的词汇表大小:
from transformers import AutoTokenizer tokenizer = AutoTokenizer.from_pretrained("你的本地微调模型路径") # 确认词汇表大小为32003 print(tokenizer.vocab_size)
2. 加载模型时指定词汇表大小并正确合并LoRA权重
方法一:使用peft库加载(推荐)
由于是LoRA微调,peft库可自动处理词汇表尺寸匹配:
from transformers import AutoModelForCausalLM from peft import PeftModel, PeftConfig # 加载LoRA配置 peft_config = PeftConfig.from_pretrained("你的本地微调模型路径") # 加载基础模型时,用分词器的词汇表大小覆盖默认值 base_model = AutoModelForCausalLM.from_pretrained( peft_config.base_model_name_or_path, vocab_size=tokenizer.vocab_size, device_map="auto" ) # 合并LoRA权重到基础模型 model = PeftModel.from_pretrained(base_model, "你的本地微调模型路径") model = model.merge_and_unload() # 验证尺寸匹配 print(model.get_input_embeddings().weight.shape) # 应为[32003, 4096] print(model.get_output_embeddings().weight.shape) # 应为[32003, 4096]
方法二:手动调整模型尺寸后加载权重
若不使用peft库,可手动扩容基础模型的embed_tokens和lm_head,再加载微调权重:
from transformers import AutoModelForCausalLM # 加载基础模型 base_model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-2-7b-chat-hf") # 扩容输入embedding层 old_embeddings = base_model.get_input_embeddings().weight new_embeddings = base_model._get_resized_embeddings(old_embeddings, tokenizer.vocab_size) base_model.set_input_embeddings(new_embeddings) # 扩容输出lm_head层 old_lm_head = base_model.get_output_embeddings().weight new_lm_head = base_model._get_resized_lm_head(old_lm_head, tokenizer.vocab_size) base_model.set_output_embeddings(new_lm_head) # 加载微调后的权重,此时尺寸已匹配 model = AutoModelForCausalLM.from_pretrained( "你的本地微调模型路径", state_dict=base_model.state_dict(), device_map="auto" )
3. 验证加载结果
加载完成后,可通过简单生成测试确认模型正常处理自定义token:
inputs = tokenizer("<|move|>测试内容<|endmove|><|end|>", return_tensors="pt").to("cuda") outputs = model.generate(**inputs, max_new_tokens=50) print(tokenizer.decode(outputs[0], skip_special_tokens=False))
关键注意点
- 必须保证分词器与模型的词汇表大小完全一致,这是解决此类问题的核心。
- LoRA微调场景优先用
peft库加载,它会自动处理权重匹配细节,避免手动调整的繁琐。 ignore_mismatched_sizes=True不适合词汇表整体扩容的场景,它无法自动扩容embedding层,只会跳过不匹配权重,导致模型缺失新token的embedding参数。
内容的提问来源于stack exchange,提问作者Stefano Mezza
相关产品推荐
相关产品推荐

