Window微调QLORA
1. QLORA 的原理与应用
LoRA是引入低秩矩阵来对模型进行微调。
量化 (Quantization):是将高精度的浮点数(如FP32或FP16)转换为较低精度的整数(如int8或int4)表示,以减少模型的存储空间和加速推理。

1. 基本参数假设
1B 参数数量:(10亿个参数)
参数精度:
FP32:4字节/参数
FP16:2字节/参数
INT4(量化):0.5字节/参数
优化器状态: 通常需要存储 2-3 倍的模型参数(比如动量、梯度累积等)。
LoRA 插入参数比例: 假设适配器权重占模型总参数的 0.1%。
QLoRA 分页机制: 假设所有基础模型参数都存储在 CPU,而显存仅存储 LoRA 模块和部分中间梯度。
(1) Full Finetuning(全量微调)
模型参数(FP16):
1B×2bytes=2GB
优化器状态(FP16 动量+梯度等,假设 3 倍参数量):
2GB×3=6GB
总内存需求:
2GB+6GB=8GB
(2) LoRA 微调模型参数(FP16,冻结,不更新):
1B×2 bytes=2 GB
LoRA 适配器参数(假设 0.1% 参数量,FP16):
1B×0.001×2 bytes=0.002 GB (即 2MB)
优化器状态(仅适配器,假设 3 倍):
0.002GB×3=0.006GB(即 6MB)
总内存需求:
2GB+0.002GB+0.006GB=2.008GB
(3)QLoRA 微调
模型参数(INT4,存储在 CPU):
1B ×0.5bytes=0.5GB
LoRA 适配器参数(0.1%,FP16):
1B×0.001×2bytes=0.002GB
优化器状态(仅适配器,假设 3 倍):
0.006GB
中间缓存(用于分页,假设 GPU 仅加载一部分参数):
0.5GB×10%=0.05GB
总显存需求(GPU 部分):
0.002GB+0.006GB+0.05GB=0.058GB
总 CPU 存储需求:
0.5+0.058=0.558GB
微调方式 | 显存需求(GPU) | 适用场景 |
---|---|---|
Full Finetuning | 8 GB | 高性能环境,需全量更新参数。 |
LoRA | 2.008 GB | 中小型硬件环境,专注领域适配。 |
QLoRA | 0.558 GB | 极限内存优化场景(低显存机器,如 8GB 显存)。 |
在普通的训练中,模型参数以FP32(32位浮点数) 或FP16(16位浮点数) 表示,这样可以保持计算的高精度。
QLoRA 使用了更低的精度,比如INT4(4位整数),以更少的位数存储参数,同时通过一个量化比例(scaling factor)保证精度的还原。
核心原理:
将参数范围压缩到一个有限范围,比如 -127 到 127(INT8 Qlora 8)或 -7 到 7(INT4 Qlora4)。
存储参数的量化值,同时存储一个全局或局部的缩放因子,用于反量化时恢复精度。
例如 FP16 vs INT4
假设我们有一个简单的权重数组,初始存储为 FP16,每个数值占用 2 字节(16 位):
FP16 权重数组
权重值:
权重=[0.3456,−0.8750,1.2345,−0.4567]
每个值以 16 位浮点数存储,内存需求:
4(值个数)×2(字节数)=8字节
INT4 量化的处理
(1) 确定最大绝对值和量化比例(scaling factor)
假设权重最大值为 absmax=1.2345,INT4 的值范围是 [−7,7],量化比例为
scaling factor =
(2) 量化:将权重值缩放到 [-7, 7],然后取整
对权重值进行缩放和取整:
量化权重 = round
计算结果:
量化权重=round([0.3456,−0.8750,1.2345,−0.4567]/0.1764)=[2,−5,7,−3]
(3) 存储量化权重和缩放因子
量化后的权重值是整数,每个值占 4 位(INT4)。
缩放因子存储为一个浮点数(FP16 或 FP32,通常为 FP16)。
内存需求:
权重值存储:
4(值个数)×0.5(字节数,INT4)=2字节
缩放因子存储:
2字节(FP16)
总内存需求:
2(量化权重)+2(缩放因子)=4字节
存储方式 | 权重存储大小 | 缩放因子存储大小 | 总存储大小 |
---|---|---|---|
FP16 | 8 字节 | 0 字节 | 8 字节 |
INT4 | 2 字节 | 2 字节 | 4 字节 |
为什么 INT4 在量化中常用 [-7, 7] 而不是 [-8, 7]?
4 位二进制可以表示 16个值,正数方向二进制0111 表示为7 范围是0-7
负数是10000到1111 表示 -8- -1 那么范围应该是[-8,7]
但是为了对称化向量,所以变成[-7,7],并且防止边界化溢出,减少数值溢出风险,所以int8 对应的就是[-127,127]
量化公式
$$
\mathbf{X}^{\text{Int8}} = \text{round} \left( \frac{127}{\text{absmax}(\mathbf{X}^{\text{FP32}})} \cdot \mathbf{X}^{\text{FP32}} \right)
= \text{round} \left( c^{\text{FP32}} \cdot \mathbf{X}^{\text{FP32}} \right),
$$
[2,−5,7,−3]*0.1764=[0.3528,−8882,1.2348,−0.5292]
量化前
[0.3456,−0.8750,1.2345,−0.4567]
反量化后
[0.3528,−0.8882,1.2348,−0.5292]
反量化公式
$$
\text{dequant}(c^{\text{FP32}}, \mathbf{X}^{\text{Int8}}) = \frac{\mathbf{X}^{\text{Int8}}}{c^{\text{FP32}}} = \mathbf{X}^{\text{FP32}}.
$$
- 4-Normal Distribution
[0.0002,−0.001,1.2345,−0.0003]
round([0.0002,−0.001,1.2345,−0.0003]/0.1764)=[1,−1,7,−1]
反量化后
[0.1764,−0.1764,1.2348,−0.1764]
数据相差太大,所以只能分桶计算

本质上4-Normal Distribution 是一种权重分布建模方式,模型权重并非是严格正态分布,通常都是非对称,或者重尾性(偏向一侧的中间或者尾部) 。为了让这一部分数据也能发挥更好的价值。
一组数值为 [0.1, -0.2, 1.5, -1.2, 0.7, -0.5, 2.3, -2.1, 0.0] 大部分数值都在[-1,1] 为了权重相等也就是面积相等。
使用正态分布的分位点(Quantiles)来划分量化区间。例如:
分位点的含义:
正态分布的分位点是每个值在分布中的相对位置。例如:
中位数 (50% 分位点):权重的中心值(0)。
四分位数 (25%, 75%):分布中 25% 和 75% 权重的位置。
极值分位点 (1%, 99%):接近尾部的权重。
根据这些分位点,我们可以划分区间:
区间 1:权重非常接近中心([-0.5, 0.5])
区间 2:权重稍远([-1.5, -0.5] 和 [0.5, 1.5])
区间 3:极端权重([-3, -1.5] 和 [1.5, 3])
每个值映射到小的范围区间内,后做向量化与反向量化,转成整数。每个区间会对应自己的scaling
- Double Quantization
原始:[0.3456,−0.8750,1.2345,−0.4567]
缩放因子:0.1764
整数化的值:[2,−5,7,−3]
现在这里面最大的就是缩放因子,几十上百亿数据必然每组数据都有自己缩放因子,存储占比也比较大进行二次缩放。
- 分页机制:
假设你正在使用一个神经网络模型进行训练,而该模型非常大,无法将所有的参数一次性加载到GPU显存中。模型的大小超出了GPU显存的容量,导致显存不足以容纳整个模型。通过使用分页机制,模型的参数会被分成几个小块,而不是一次性加载整个模型,这样可以有效利用有限的显存。
假设:
模型和内存:
假设我们有一个模型,包含 1 亿个参数。
这些参数是 16 位浮点数(FP16),每个参数占 2 字节。
如果整个模型一次性加载到显存中,它的内存占用将是:
1亿个参数×2字节=200MB
假设你的 GPU 显存只有 8GB (8000MB),这就足够加载整个模型。
然而,随着更大的模型(比如 100 亿参数或更多),内存的需求将大大增加,甚至16GB或32GB的显存都不足以容纳这些模型。
步骤 1:分页
假设这个 1 亿参数的模型被分页为 5 个小块,每个小块包含 2000 万个参数(相当于每块占用 40MB)。分页后,模型的每一块将动态地加载到显存中,而不是将整个模型一次性加载。
步骤 2:训练过程中的参数加载
在训练过程中,不是所有的参数都在同一时刻被计算。例如,当模型在训练时,可能只需要更新模型的一部分(例如某个层的权重)。通过分页机制,只有当前需要用到的部分(比如当前层或某些模块的参数)会被加载到显存中,其他不需要的部分则会被卸载。
假设你在训练第一个 epoch 时,当前只需要使用模型的前 3 个分页块:
第 1 步: 第一个分页块(40MB)加载到显存中,模型开始训练。
第 2 步: 第二个分页块(40MB)加载到显存中,模型继续训练。
第 3 步: 第三个分页块(40MB)加载到显存中。
在这个阶段,显存中会存储 3 个分页块的数据,总内存占用为 120MB,远小于 200MB 的完整模型占用。
步骤 3:卸载与重新加载
当训练到了需要用到第 4 或第 5 个分页块的阶段时,前面的分页块会被卸载出显存。显存会根据需要进行动态更新:
第 4 步: 第四个分页块(40MB)加载到显存中,显存中的第一个分页块被卸载。
第 5 步: 第五个分页块(40MB)加载到显存中,第二个分页块被卸载。
这种方式确保了显存的动态利用,显存的占用始终保持在需要的范围内,而不会导致显存溢出。
主要是节省内存,能够提高训练效率,适用于资源受限的环境。
分页并不是越多越好,每次切换分页都会引起额外的I/O操作影响微调效率。
2. 如何在window上配置微调环境
Window 租赁地址:https://www.compshare.cn/












初始化完成后才会显示磁盘空间大小

- 链接方式一


- 链接方式二





关闭界面即可正常使用

以上方式可以连接,但是使用过程延迟较高,且窗口不友好,建议使用本地连接。
- 链接方式二:window 用户如何本地连接
win+R 然后输入 mstsc


输入租用服务器的外部IP BGP ,每次删除资源后的服务器ip是不一样的,所以有变化是正常,只要就住选择外部IP即可


注意使用电脑默认账户是无法登录的

默认用户名为:Administartor 密码是上边租赁服务器中的



- 链接方式三: mac 用户如何本地连接
windows app 软件下载地址:https://go.microsoft.com/fwlink/?linkid=868963
下载完成后

按步骤安装






找到服务器外部IP地址

打开windows 后填入IP地址


点击链接弹出窗口



- 创建conda环境
安装anaconda 软件,建议官网下载最新版本或者适合版本,不要下载过老版本,很大概率会安装出错。(之前教程有进行安装说明,本次不在赘述,有需要要安装步骤的找小可爱要安装文档即可)
conda create -n llama_factory python=3.11
注意 llama_factory是推荐环境方便区分,大家可以自行定义,只要安装上基础包和python=3.11即可
因老师实验过程中走了太多弯路,后续命名为 ll5 (表示至少部署了6次) 但是环境相同 命令为 conda create -n ll5 python=3.11

使用指定环境 conda activate 环境名称
如上边环境为llama_factory 则是 conda activate llama_factory
如上边环境为ll5 则是 conda activate ll5

- 下载LLama_factory 地址为:https://github.com/hiyouga/LLaMA-Factory/ 详细步骤请见微调系列 《Ch 2. LLama_Factory+LORA大模型微调》
下载到指定目录

解压文件

当前使用conda prommpt窗口开始命令

启动后到目标conda环境 llama_factory 或者 ll5 执行安装配置,建议大部分安装官网推荐配置
conda install pytorch==2.4.0 torchvision==0.19.0 torchaudio==2.4.0 pytorch-cuda=12.1 -c pytorch -c nvidia
待安装完成后,如果想要检查是否成功安装了GPU版本的PyTorch,可以通过几个简单的步骤在Python环境中进行验证:
python -c "import torch; print(torch.cuda.is_available())"
表示成功:

- 如果出现异常 1
ImportError: /root/.cache/torch_extensions/py311_cu121/cpu_adam/cpu_adam.so: cannot open shared object file: No such file or directory
Exception ignored in: <function DeepSpeedCPUAdam.__del__ at 0x7fe3b03987c0>
Traceback (most recent call last):
File "/root/anaconda3/envs/llama_factory/lib/python3.11/site-packages/deepspeed/ops/adam/cpu_adam.py", line 102, in __del__
self.ds_opt_adam.destroy_adam(self.opt_id)
^^^^^^^^^^^^^^^^
AttributeError: 'DeepSpeedCPUAdam' object has no attribute 'ds_opt_adam'
Exception ignored in: <function DeepSpeedCPUAdam.__del__ at 0x7fe6333807c0>
Traceback (most recent call last):
- 如果出现异常 2
python -c "import torch; print(torch.cuda.is_available())"
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "C:\ProgramData\anaconda3\envs\ll2\Lib\site-packages\torch\__init__.py", line 148, in <module>
raise err
OSError: [WinError 126] 找不到指定的模块。 Error loading "C:\ProgramData\anaconda3\envs\ll2\Lib\site-packages\torch\lib\fbgemm.dll" or one of its dependencies.
(ll2) C:\Users\Administrator>
(ll2) C:\Users\Administrator>python -c "import torch; print(torch.cuda.is_available())"
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "C:\ProgramData\anaconda3\envs\ll2\Lib\site-packages\torch\__init__.py", line 148, in <module>
raise err
OSError: [WinError 126] 找不到指定的模块。 Error loading "C:\ProgramData\anaconda3\envs\ll2\Lib\site-packages\torch\lib\fbgemm.dll" or one of its dependencies.
需要查看CUDA版本 注意当前是 CUDA Toolkit 版本命令 nvcc --version , CUDA Toolkit版本要>=上边安装CUDA 12.1 不然就会报错
nvcc --version
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2023 NVIDIA Corporation
Built on Tue_Aug_15_22:09:35_Pacific_Daylight_Time_2023
Cuda compilation tools, release 12.2, V10.1.140
Build cuda_12.2.r12.2/compiler.33191640_0
但如果驱动过低 也就是 nvidia-smi 版本过低 也会异常就需要去下载对应显卡需要的驱动版本:https://www.nvidia.com/en-us/drivers/results/(%E5%BD%93%E5%89%8D%E9%93%BE%E6%8E%A5%E4%B8%BARTX40 常说的4090 对应的驱动版本型号为555.99)


因原有CUDA Toolkit 版本太低 也要下载 CUDA Toolkit
先查看系统环境 方式一: 打开 控制面板(可以在开始菜单中搜索)。选择 系统和安全,然后点击 系统。
方式二:按下 Win + R 键打开运行对话框。输入 msinfo32,然后按 Enter。


下载完成后

注意:安装之前要卸载历史驱动
"新手请谨慎操作"
"新手请谨慎操作"
"新手请谨慎操作"
"新手请谨慎操作"
"新手请谨慎操作"
"新手请谨慎操作"
"新手请谨慎操作"
"新手请谨慎操作"


先安装驱动:555.99对应内容
再安装CUDA Tooklist 12.2
配置环境变量


执行nvcc --version

再次执行:
python -c "import torch; print(torch.cuda.is_available())"
表示成功(以上执行都要在统一的conda环境中ll5 或者是 llama_factory):

如果不成功则在此执行pytorch安装 https://pytorch.org/get-started/previous-versions/
conda install pytorch==2.4.0 torchvision==0.19.0 torchaudio==2.4.0 pytorch-cuda=12.1 -c pytorch -c nvidia
GPU显示版本号是最高支持12.2 可以向下兼容的。


问题处理完后:进入 LLAma_Factory 路径下
注意当前路径在llama_factory 文件夹下 执行命令下载安装包 pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple/

注意当前路径在llama_factory 文件夹下 执行命令下载安装包 pip install -e ".[torch,metrics]"

遇到包冲突时,可使用 pip install --no-deps -e . 解决
以可编辑模式安装,可以在安装后继续修改源代码。
并且跳过安装包的依赖项。
如果要在 Windows 平台上开启量化 LoRA(QLoRA),需要安装预编译的 bitsandbytes 库, 支持 CUDA 11.1 到 12.2
pip install https://github.com/jllllll/bitsandbytes-windows-webui/releases/download/wheels/bitsandbytes-0.41.2.post2-py3-none-win_amd64.whl

启动llama_factory
llamafactory-cli webui

打开界面:localhost:7860

- 下载模型

任意环境安装即可 pip install modelscope

同一环境下到指定路径后,下载模型C:\Users\Administrator\Downloads\muyan\qwen> modelscope download --model Qwen/Qwen2.5-3B-Instruct --local_dir ./Qwen2.5-3B-Instruct (建议创建好Qwen2.5-3B-Instruct文件夹)

检查下载模型文件内容

3. 数据集清洗注册
- 3.1 数据下载




python convert_sharegpt.py industry_instruction_semantic_cluster_dedup_旅游_地理_valid_train.jsonl sharegpt_valid_train.jsonl
python convert_sharegpt.py industry_instruction_semantic_cluster_dedup_旅游_地理_valid_val.jsonl sharegpt_valid_val.jsonl
新建路径download_data

import json
# 查看数据并且将数据转换为 sharegpt格式
def convert_to_sharegpt_format(data):
# 初始化一个空列表来存储转换后的对话
sharegpt_format = []
# 遍历每个条目(在这个例子中可能有多个条目)
for entry in data:
# 初始化一个空列表来存储当前条目的对话
conversation = []
# 获取对话部分
conversations = entry.get("conversations", [])
# 遍历每个交互
for interaction in conversations:
# 将用户的指令添加到对话中
conversation.append({
"from": interaction["from"],
"value": interaction["value"]
})
# 将当前对话添加到最终的格式中
sharegpt_format.append({
"conversations": conversation
})
return sharegpt_format
# 示例输入数据
data = [
{
"deita_score": 11.4492515798,
"rw_score": 16.75,
"id": "generate_from_topic_and_persona",
"instruction": "",
"lang": "zh",
"length": 44,
"conversations": [
{
"from": "human",
"value": "在我野外考察和实地调查的过程中,我发现地理大数据在旅游业中起到了重要的作用。您能给我一些例子来说明它的具体应用吗?"
},
{
"from": "gpt",
"value": "当然可以!地理大数据在旅游业中有许多具体的应用。以下是一些例子:\n\n1. 目的地选择和规划:地理大数据可以提供关于各个目的地的详细信息,包括景点、交通、住宿、餐饮等。旅游者可以通过分析地理大数据来选择适合自己的目的地,并规划行程。\n\n2. 旅游路线优化:地理大数据可以帮助旅游者优化旅游路线,以节省时间和成本。通过分析交通流量、道路状况和景点的分布,可以找到最佳的路线,避免拥堵和浪费。\n\n3. 旅游体验个性化:地理大数据可以根据旅游者的个人偏好和需求,提供个性化的旅游体验。通过分析旅游者的历史数据和行为模式,可以推荐适合他们的景点、活动和美食。\n\n4. 游客行为分析:地理大数据可以帮助旅游业者了解游客的行为和偏好,以优化服务和推广策略。通过分析游客的位置数据、社交媒体活动和消费记录,可以更好地了解他们的需求,并提供更好的服务。\n\n5. 旅游资源管理:地理大数据可以帮助旅游业者更好地管理和保护旅游资源。通过分析资源利用情况、环境状况和游客分布,可以制定合理的资源管理策略,保持资源的可持续利用。\n\n希望以上例子可以帮助您了解地理大数据在旅游业中的具体应用!如果您还有其他问题,请随时提问。"
}
]
},
{
"deita_score": 9.9156255109,
"rw_score": 11.125,
"id": "generate_from_given_text",
"instruction": "",
"lang": "en",
"length": 23,
"conversations": [
{
"from": "human",
"value": "Write a brief paragraph describing the Liangzhu ancient city site and its importance to Chinese history and culture."
},
{
"from": "gpt",
"value": "Liangzhu ancient city site is a monumental discovery in Chinese prehistory, showcasing an early regional state dating back to the Neolithic period. Spanning approximately 8 square kilometers, it features a complex of high-level burials, sacrificial altars, and a massive water conservation system. This site not only reveals a sophisticated urban civilization but also highlights the importance of rice agriculture and unified spiritual beliefs in the formation of early Chinese culture. Its historical significance is underscored by its inclusion on the \"World Heritage List,\" marking it as a pivotal piece of evidence for the 5,000-year history of Chinese civilization."
}
]
}
]
# 转换数据
sharegpt_output = convert_to_sharegpt_format(data)
# 打印转换后的数据
print(json.dumps(sharegpt_output, indent=4, ensure_ascii=False))
[
{
"conversations": [
{
"from": "human",
"value": "在我野外考察和实地调查的过程中,我发现地理大数据在旅游业中起到了重要的作用。您能给我一些例子来说明它的具体应用吗?"
},
{
"from": "gpt",
"value": "当然可以!地理大数据在旅游业中有许多具体的应用。以下是一些例子:\n\n1. 目的地选择和规划:地理大数据可以提供关于各个目的地的详细信息,包括景点、交通、住宿、餐饮等。旅游者可以通过分析地理大数据来选择适合自己的目的地,并规划行程。\n\n2. 旅游路线优化:地理大数据可以帮助旅游者优化旅游路线,以节省时间和成本。通过分析交通流量、道路状况和景点的分布,可以找到最佳的路线,避免拥堵和浪费。\n\n3. 旅游体验个性化:地理大数据可以根据旅游者的个人偏好和需求,提供个性化的旅游体验。通过分析旅游者的历史数据和行为模式,可以推荐适合他们的景点、活动和美食。\n\n4. 游客行为分析:地理大数据可以帮助旅游业者了解游客的行为和偏好,以优化服务和推广策略。通过分析游客的位置数据、社交媒体活动和消费记录,可以更好地了解他们的需求,并提供更好的服务。\n\n5. 旅游资源管理:地理大数据可以帮助旅游业者更好地管理和保护旅游资源。通过分析资源利用情况、环境状况和游客分布,可以制定合理的资源管理策略,保持资源的可持续利用。\n\n希望以上例子可以帮助您了解地理大数据在旅游业中的具体应用!如果您还有其他问题,请随时提问。"
}
]
},
{
"conversations": [
{
"from": "human",
"value": "Write a brief paragraph describing the Liangzhu ancient city site and its importance to Chinese history and culture."
},
{
"from": "gpt",
"value": "Liangzhu ancient city site is a monumental discovery in Chinese prehistory, showcasing an early regional state dating back to the Neolithic period. Spanning approximately 8 square kilometers, it features a complex of high-level burials, sacrificial altars, and a massive water conservation system. This site not only reveals a sophisticated urban civilization but also highlights the importance of rice agriculture and unified spiritual beliefs in the formation of early Chinese culture. Its historical significance is underscored by its inclusion on the \"World Heritage List,\" marking it as a pivotal piece of evidence for the 5,000-year history of Chinese civilization."
}
]
}
]
默认限制前10000条数据用于训练 将代码存储文件:convert_sharegpt_munber.py
import json
import argparse
def convert_to_sharegpt_format(input_file, output_file, limit):
# 初始化一个空列表来存储转换后的对话
sharegpt_format = []
# 打开输入文件并逐行读取
with open(input_file, 'r', encoding='utf-8') as file:
for i, line in enumerate(file):
if i >= limit:
break
try:
# 解析每一行作为一个 JSON 对象
entry = json.loads(line.strip())
# 初始化一个空列表来存储当前条目的对话
conversation = []
# 获取对话部分
conversations = entry.get("conversations", [])
# 遍历每个交互
for interaction in conversations:
# 将用户的指令添加到对话中
conversation.append({
"from": interaction["from"],
"value": interaction["value"]
})
# 将当前对话添加到最终的格式中
sharegpt_format.append({
"conversations": conversation
})
except json.JSONDecodeError as e:
print(f"Failed to decode JSON on line {i + 1}: {line}")
print(e)
# 将转换后的数据写入输出 JSON 文件
with open(output_file, 'w', encoding='utf-8') as output_file_handle:
json.dump(sharegpt_format, output_file_handle, ensure_ascii=False, indent=4)
if __name__ == "__main__":
# 创建 ArgumentParser 对象
parser = argparse.ArgumentParser(description="Convert given .jsonl data to ShareGPT format and specify the number of entries to process.")
# 添加输入文件路径参数
parser.add_argument("input_file", type=str, help="Path to the input .jsonl file")
# 添加输出文件路径参数
parser.add_argument("output_file", type=str, help="Path to the output JSON file")
# 添加限制条数参数,默认值为 10000
parser.add_argument("--limit", type=int, default=10000, help="Number of entries to process (default: 10000)")
# 解析命令行参数
args = parser.parse_args()
# 调用转换函数
convert_to_sharegpt_format(args.input_file, args.output_file, args.limit)
执行命令为:python convert_sharegpt_munber.py industry_instruction_semantic_cluster_dedup_旅游_地理_valid_train.jsonl sharegpt_valid_train_1w.json --limit 10000
当前数据越位13.7W 大家按照需求自行判定需要多少数据,本次分别注册了 全量、1W、4k 三分数据。以及全量的测试数据500条。

将数据移动到llama_factory/data路径下

打开dataset_info.json文件并开始注册数据
"sharegpt_valid_val": {
"file_name": "sharegpt_valid_val.json",
"formatting": "sharegpt",
"columns": {
"messages": "conversations"
}
},
"sharegpt_valid_train": {
"file_name": "sharegpt_valid_train.json",
"formatting": "sharegpt",
"columns": {
"messages": "conversations"
}
},
"sharegpt_valid_train_1w": {
"file_name": "sharegpt_valid_train_1w.json",
"formatting": "sharegpt",
"columns": {
"messages": "conversations"
}
},

去界面查看数据:

4 模型微调及验证
4.1 使用lora微调
因本次启动命令是在 llama_factory路径下启动,对应相对路径为llama_factory下。
全量13.7W数据命令
llamafactory-cli train `
--stage sft `
--do_train True `
--model_name_or_path C:\Users\Administrator\Downloads\muyan\qwen\Qwen2.5-3B-Instruct `
--preprocessing_num_workers 16 `
--finetuning_type lora `
--template qwen `
--flash_attn auto `
--dataset_dir data `
--dataset sharegpt_valid_train `
--cutoff_len 2048 `
--learning_rate 5e-05 `
--num_train_epochs 3.0 `
--max_samples 100000 `
--per_device_train_batch_size 2 `
--gradient_accumulation_steps 8 `
--lr_scheduler_type cosine `
--max_grad_norm 1.0 `
--logging_steps 5 `
--save_steps 100 `
--warmup_steps 0 `
--packing False `
--report_to none `
--output_dir saves\Qwen2.5-3B-Instruct\lora\train_2024-11-25-15-16-28 `
--fp16 True `
--plot_loss True `
--ddp_timeout 180000000 `
--optim adamw_torch `
--lora_rank 8 `
--lora_alpha 16 `
--lora_dropout 0 `
--lora_target all

4K数据微调


4.2 QLora int8 微调
llamafactory-cli train `
--stage sft `
--do_train True `
--model_name_or_path C:\Users\Administrator\Downloads\muyan\qwen\Qwen2.5-3B-Instruct `
--preprocessing_num_workers 16 `
--finetuning_type lora `
--template qwen `
--flash_attn auto `
--dataset_dir data `
--dataset sharegpt_valid_train_4k `
--cutoff_len 2048 `
--learning_rate 5e-05 `
--num_train_epochs 3.0 `
--max_samples 100000 `
--per_device_train_batch_size 2 `
--gradient_accumulation_steps 8 `
--lr_scheduler_type cosine `
--max_grad_norm 1.0 `
--logging_steps 5 `
--save_steps 100 `
--warmup_steps 0 `
--packing False `
--report_to none `
--output_dir saves\Qwen2.5-3B-Instruct\lora\train_2024-11-25-18-10-17 `
--fp16 True `
# 主要作用于模型的前向传播和后向传播的计算过程 主要用于加速训练
--plot_loss True `
--ddp_timeout 180000000 `
--optim adamw_torch `
--quantization_bit 8 `
# 指定量化位数为 8 位
# 作用于模型的权重和激活值的存储和计算。
# 将模型的权重从浮点数(通常是 FP32)量化为 8 位整数(INT8)
--quantization_method bitsandbytes `
# 指定量化方法为 bitsandbytes
--lora_rank 8 `
--lora_alpha 16 `
--lora_dropout 0 `
--lora_target all
如果对参数设置不确定,可以考虑到llama_factory路径下examples/train_qlora找样例文件查看对比使用。



4.3 QLora int4 微调


epoch = 3.0:表示整个训练数据集已经被模型完整地遍历了3次。
total_flos = 39351596GF:FLOPS是每秒浮点运算次数的缩写,而这里的“FLO”指的是浮点运算。GF代表十亿次(Giga)。因此,39351596GF表示在整个微调过程中,模型进行了大约393.5亿次浮点运算。这个数字反映了训练过程中的计算量。
train_loss = 1.452:这是训练过程中的损失值,通常是一个衡量模型预测与实际标签之间差异的数值。较低的损失值意味着模型的预测更加准确。不同的任务和模型可能有不同的损失函数,所以具体的数值需要结合实际情况来看待。
train_runtime = 1:03:03.19:表示整个训练过程花费的时间,是1小时3分钟3.19秒。
train_samples_per_second = 3.172:表示训练过程中每秒钟处理的样本数量。这是一个衡量训练速度的指标,反映了系统的吞吐量。
train_steps_per_second = 0.198:表示训练过程中每秒钟完成的训练步骤数量。一个步骤通常指模型权重的一次更新。


合并导出模型文件,注意选择向量化等级,检查点路径。

4.4 横向对比
为什么使用 INT8 进行 QLoRA 微调所需时间通常比 INT4 更长?
1. 数据类型的复杂性:INT8 能表示的数值范围更广,因此在计算时需要更多的内存带宽和计算资源来处理这些数据。
2. 计算效率:INT4 的数据量更小,内存带宽的使用效率更高,计算速度也更快。
3. 内存带宽和存储需求
QLoRA 进行 INT8 微调所需时间比 INT4 更长的原因主要包括数据类型的复杂性、计算效率的差异、内存带宽的使用以及量化后的模型性能。
- 模型加载对比

一定要先选择量化等级然后再加载模型,导出时也是!
基座模型 | LORA | QLORA int 8 | QLORA int 4 | QLORA int 4(30epoch) | |
---|---|---|---|---|---|
加载内存 | 7070M | 7019M | 4169M | 2990M | 3026M |
基座模型

Lora 微调

QLora int4 30 epoch 微调

中横公路东端入口处的东西横贯公路牌楼上“东西横贯公路”六个字的书写者是台湾当代重要书家之一的王壮为先生,当年他时任陈诚副总统的机要秘书及代笔工作。
基座模型验证 :"predict_bleu-4": 23.456885
lora : "predict_bleu-4": 55.473792
Qlora int8 : "predict_bleu-4": 50.672361
Qlora int4 : "predict_bleu-4": 46.697114
Qlora int4_30 : "predict_bleu-4": 53.362194
5. 总结
