使用指令微调对大模型进行微调。主运行代码是从chinese-LLaMA-Alpaca里面拷贝过来,进行了一些修改:
- 修改了使用lora保存模型的方式,原始方法不能保存完整的模型参数。同时,只保存一份lora参数。
- 修改支持的模型为chatglm-6b。
注意:目前还存在问题。
- RuntimeError: element 0 of tensors does not require grad and does not have a grad_fn
后面查阅相关资料,在modeliing_chatglm.py里面加上了loss.requires_grad_(True)
后可成功运行。为了
排除是不支持chatglm,将模型换成chinese-LLaMA-Alpaca里面同样的模型还是有这个问题。不管怎么说修改之
后还是可以运行成功的。
-
虽然整个流程没有问题,但是模型似乎不能够有效的进行训练。损失一直在4点几左右,尝试了不同的学习率以及训练更长的时间还是有同样的问题。
-
该项目主要是:
- sentencepiece_chinese_bpe:怎么让英文大语言模型支持中文?(一)构建中文tokenization
- chinese_llm_pretrained:怎么让英文大语言模型支持中文?(二)继续预训练
的第三部分,对预训练模型进行指令微调。主要是讲解整个流程,详细介绍可查看知乎:https://zhuanlan.zhihu.com/p/640086409,如果想实际使用的话可以参考发布的其它的项目:[taishan1994 (西西嘛呦) (github.com)](https://github.com/taishan1994)。
mpi4py
transformers==4.28.1
peft==0.3.0
icetk
deepspeed==0.9.2
accelerate
cpm_kernels
sentencepiece==0.1.99
peft=0.3.0
torch=2.0.0
datasets
包版本使用最新的应该也可以。
-
1、下载好chatglm-6b模型到model_hub/chatglm-6b下
-
2、准备好数据,如data/msra/train.txt里面数据的格式,一行为一条样本,样本类似:
{"instruct": "你现在是一个实体识别模型,你需要提取文本里面的人名、地名、机构名,如果存在结果,返回'实体_实体类型',不同实体间用\n分隔。如果没有结果,回答'没有'。", "query": "文本:一位郑州学人说,越秀学术讲座对郑州学界而言堪称功德之举。", "answer": "郑州_地名\n越秀_机构名"}
-
3、准备好数据之后就可以使用指令进行训练了:
torchrun --nnodes 1 --nproc_per_node 1 run_clm_sft_with_peft.py \ --deepspeed ds_zero2_no_offoad.json \ --model_name_or_path model_hub/chatglm-6b \ --tokenizer_name_or_path model_hub/chatglm-6b \ --dataset_dir data/msra/ \ --per_device_train_batch_size 8 \ --per_device_eval_batch_size 8 \ --do_train \ --seed $RANDOM \ --fp16 \ --num_train_epochs 3 \ --learning_rate 3e-5 \ --warmup_ratio 0.01 \ --weight_decay 0 \ --logging_strategy steps \ --logging_steps 10 \ --save_strategy steps \ --save_total_limit 3 \ --save_steps 200 \ --gradient_accumulation_steps 1 \ --preprocessing_num_workers 8 \ --max_seq_length 256 \ --output_dir output_dir \ --overwrite_output_dir \ --ddp_timeout 30000 \ --logging_first_step True \ --lora_rank 8 \ --lora_alpha 32 \ --trainable query_key_value \ --lora_dropout 0.05 \ --torch_dtype float16 \ --gradient_checkpointing \ --ddp_find_unused_parameters False
-
4、训练完成后可以使用test_sft_model.py进行预测:
import os import torch from transformers import AutoTokenizer, AutoModel from peft import PeftModel tokenizer = AutoTokenizer.from_pretrained("model_hub/chatglm-6b", trust_remote_code=True) model = AutoModel.from_pretrained("model_hub/chatglm-6b", trust_remote_code=True).half() model_vocab_size = model.get_output_embeddings().weight.size(0) model.resize_token_embeddings(len(tokenizer)) model = PeftModel.from_pretrained(model, os.path.join("output_dir", "adapter_model")) model.cuda() model.eval() response, history = model.chat(tokenizer, "你好", history=[]) print(response) response, history = model.chat(tokenizer, "晚上睡不着应该怎么办", history=[]) print(response) response, history = model.chat(tokenizer, "你现在是一个实体识别模型,你需要提取文本里面的人名、地名、机构名,如果存在结果,返回'实体_实体类型',不同实体间用\n分隔。如果没有结果,回答'没有'。文本:我们是受到郑振铎先生、阿英先生著作的启示,从个人条件出发,瞄准现代出版史研究的空白,重点集藏解放区、国民党毁禁出版物。", history=[]) print(response)
-
5、其它一些,比如lora的可训练的层怎么定义,可以使用fin_lora_names.py进行查看。可以使用test_datset.py测试数据。使用test_toenizer.py测试分词器。使用test_model.py测试原始模型。