前言
LLaMA-factory是一个非常有用的开源框架。关于利用llama-factory实现大模型的微调,研究了有一个多月了,终于相对成功的微调了一个QWen的大模型。其中的曲折愿和大家分享!
一、源码的下载
在github上的网址:
GitHub - hiyouga/LLaMA-Factory: Unified Efficient Fine-Tuning of 100+ LLMs & VLMs (ACL 2024)
不采用git,直接download,如图:
下载完毕后,解压后的效果如下:
二、在AnaConda配置完成安装
启动AnaConda的命令行:
查看现有的虚拟环境,如下图:
(可见我当前的系统安装了多个Python版本的环境,这个可以参考我的另外一篇博客:
https://quickrubber.blog.csdn.net/article/details/140995598)
激活Python311
进入LLaMa-Factory的下载目录,如下图:
安装依赖:
下载得速度还是比较快的,然后如下:
三、启动LLaMa-factory
自动打开了浏览器(这个启动过程大约需要十多秒),如下图:
尝试直接挂接Ollama的本地大模型,发现无法成功,具体可以参看我的另一篇博客:
llama-Factory不宜直接挂接Ollama的大模型-CSDN博客
所以,考虑直接采用魔搭社区下载的大模型。
四、访问本地的千问(QWen)大模型对比微调结果
4.1、从魔搭社区下载大模型文件
采用的还是比较轻量级的QWen2.5:0.5B。
链接:魔搭社区
直接逐个下载即可(当然也可用命令行下载,在此不赘述)
下载完毕后,文件夹中的文件如下:
4.2、PyCharm工程访问大模型文件实现测试1
代码如下:
from transformers import AutoModelForCausalLM, AutoTokenizer
#模型文件采用在线的方式进行
#model_name = "Qwen/Qwen2.5-0.5B-Instruct"
model_name=r"E:\models_\Qwen2.5_0.5_before_fine_tuning"
model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype="auto",
device_map="auto"
)
tokenizer = AutoTokenizer.from_pretrained(model_name)
instruction = "Produce a list of the top 5 NHL players in 2021."
input_text = ""
messages = [
{"role": "system", "content": "You are Qwen, created by Alibaba Cloud. You are a helpful assistant."},
{"role": "user", "content": f"Instruction: {instruction}\nInput: {input_text}"}
]
text = tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True
)
model_inputs = tokenizer([text], return_tensors="pt").to(model.device)
generated_ids = model.generate(
**model_inputs,
max_new_tokens=512
)
generated_ids = [
output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)
]
response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
print("Model output:", response)
运行结果如下:
(结果图1)
4.3、采用LLaMa-factory实现模型的微调
选定模型位置:
选择一个llama-factory自带的一个数据集:
开始训练:
控制台的训练显示1:
查看资源管理器,发现GPU已100%被占用:
训练完毕(2080显卡用时1小时):
完毕后可以得到一个训练记录:
点开文件夹:
4.4、采用llama-factory将微调后的模型导出
导出完毕:
得到的模型文件夹内容:
4.5、将用于微调的数据集中数据测试微调后的模型
代码:
from transformers import AutoModelForCausalLM, AutoTokenizer
#模型文件采用在线的方式进行
#model_name = "Qwen/Qwen2.5-0.5B-Instruct"
model_name=r"E:\models_\Qwen2.5_0.5_after_fine_tuning"
model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype="auto",
device_map="auto"
)
tokenizer = AutoTokenizer.from_pretrained(model_name)
instruction = "Produce a list of the top 5 NHL players in 2021."
input_text = ""
messages = [
{"role": "system", "content": "You are Qwen, created by Alibaba Cloud. You are a helpful assistant."},
{"role": "user", "content": f"Instruction: {instruction}\nInput: {input_text}"}
]
text = tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True
)
model_inputs = tokenizer([text], return_tensors="pt").to(model.device)
generated_ids = model.generate(
**model_inputs,
max_new_tokens=512
)
generated_ids = [
output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)
]
response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
print("Model output:", response)
运行效果:
(结果图2)
显然“结果图2”比“结果图1”(4.2)更加接近微调数据集的答案。
微调数据集中对应的内容:
换行打印的内容如下:
可见,可能人名未必对的上,但是意思比微调前接近了。
人名对不上的缘故是,微调才运行了3个epoch,持续微调,降低误差后。可能更准确。
五、自定义数据集进行微调
5.1、5条数据的数据集
alpaca_en_demo.json有1000条数据集,所以微调起来慢。
我选取了其中5条,构成了新的alpaca_en_demo_mychange.json
关于alpaca_en_demo_mychange.json的内容:
在dataset_info.json中添加数据信息
为了方便微调数据集的加载,必须修改dataset_info.json,添加自定义数据集的信息:
5.2、按照4.3方式微调
重启llama-factory:
然后,开始重新训练:
训练完毕(2080显卡用时2分钟):
得到新的训练结果:
5.3、导出新的大模型文件
具体方法参照4.4
5.4、最新大模型文件测试
代码:
from transformers import AutoModelForCausalLM, AutoTokenizer
#model_name = "Qwen/Qwen2.5-0.5B-Instruct"
model_name=r"E:\models_\Qwen2.5_0.5_after_fine_tuning_5"
model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype="auto",
device_map="auto"
)
tokenizer = AutoTokenizer.from_pretrained(model_name)
instruction = "Produce a list of the top 5 NHL players in 2021."
input_text = ""
messages = [
{"role": "system", "content": "You are Qwen, created by Alibaba Cloud. You are a helpful assistant."},
{"role": "user", "content": f"Instruction: {instruction}\nInput: {input_text}"}
]
text = tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True
)
model_inputs = tokenizer([text], return_tensors="pt").to(model.device)
generated_ids = model.generate(
**model_inputs,
max_new_tokens=512
)
generated_ids = [
output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)
]
response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
print("Model output:", response)
运行结果:
原微调数据集:
对比微调数据集,第二个名字(Conner McDavid)完全能对上。所以微调还是有了改进。
但是结果还是不满意。
5.5、加大epoch数量(500)进行微调
训练完毕(大约用了半小时):
再同样进行模型文件合并导出,重新用Python程序进行测试,发现仍然还是只有一个球员名字对上,效果还是不满意。(尽管loss误差已经是零了)
5.6、重磅级别的改进
在Python问答环节中增加了一个sample=False的设置:
运行效果如下:
对比微调用的数据集中的内容:
Good!终于完全对上了!微调成功!
测试程序的对应源码,可以从此处下载:
https://download.csdn.net/download/quickrubber/90778391