Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Help] 如果最终准备量化部署,是应该从int4的模型开始训练吗? #141

Open
1 task done
bash99 opened this issue Jun 30, 2023 · 17 comments
Open
1 task done

Comments

@bash99
Copy link

bash99 commented Jun 30, 2023

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

我用peft的lora在 chatglm2 训练了一个Lora(参考了 @shibing624 https://github.com/shibing624/MedicalGPT 里面的方法),只训练了一个epoch。

训练后测试效果,发现如果缺省模式(fp16)输出,效果很稳定。
如果加载lora后,量化到8bit或者4bit运行,则结果非常不稳定,有时达到了部分训练后的效果,有时候和完全没训练的原始模型输出一样。

Expected Behavior

4bit量化效果的质量损失有这么大吗?而且8bit似乎也没什么优势?

我本来以为只会有一点点差异的。

还是我的训练方法错误,应该从4bit直接训练?
或者我应该多训练几个epoch?

Steps To Reproduce

https://huggingface.co/datasets/shibing624/CSC 的语料库,如下代码生成 alpaca 格式的训练数据

import json
import random
import sys

f = open('train.json',)
data = json.load(f)

for line in data:
    input_text = line['original_text']
    wrong_ids = line['wrong_ids']
    target_text = line['correct_text'] + '\n错误字:' + ','.join([input_text[i] for i in wrong_ids])
    output_item = {
        "instruction": "对下面中文拼写纠错:",
        "input": input_text,
        "output": target_text,
    }
    print(json.dumps(output_item, ensure_ascii=False))

# Closing file
f.close()

Environment

- OS: Ubuntu 20.04
- Python: 3.10
- Transformers: 4.30.2
- PyTorch: 2.0.0
- CUDA Support (`python -c "import torch; print(torch.cuda.is_available())"`) : True

Anything else?

另外未来有没有可能实现类似ggml q5_1或者 gptq那样的高质量或者高速量化方法?

@valkryhx
Copy link

valkryhx commented Jul 1, 2023

请问您是使用了整个252K 的数据集进行LORA 微调吗? LR是脚本中默认值吗?我这边只有4K微调语料,LORA微调训练了10个epoch 感觉基本没学到东西。

@bash99
Copy link
Author

bash99 commented Jul 3, 2023

请问您是使用了整个252K 的数据集进行LORA 微调吗? LR是脚本中默认值吗?我这边只有4K微调语料,LORA微调训练了10个epoch 感觉基本没学到东西。

嗯,我把训练限制从1000放到310000,eval限制从100放到500(如果换成1000会爆V100的32G显存),batchsize只能调整到2

@valkryhx
Copy link

valkryhx commented Jul 3, 2023

请问您是使用了整个252K 的数据集进行LORA 微调吗? LR是脚本中默认值吗?我这边只有4K微调语料,LORA微调训练了10个epoch 感觉基本没学到东西。

嗯,我把训练限制从1000放到310000,eval限制从100放到500(如果换成1000会爆V100的32G显存),batchsize只能调整到2

好的 感谢您的指导

@shuxueslpi
Copy link

我在训练时用qlora把base model固定在4bit,然后训练lora model,lora model训练好是fp的,训练完再把lora model和base model进行合并,最后再量化合并后的模型,好像没有出现很大的损失
https://github.com/shuxueslpi/chatGLM-6B-QLoRA

@shuxueslpi
Copy link

不过,目前官方的量化方法,显存占用会减少,但推理速度是有所下降的,属于用空间换时间的方法,可以看我链接里的测试结果

@bash99
Copy link
Author

bash99 commented Jul 4, 2023

我在训练时用qlora把base model固定在4bit,然后训练lora model,lora model训练好是fp的,训练完再把lora model和base model进行合并,最后再量化合并后的模型,好像没有出现很大的损失 https://github.com/shuxueslpi/chatGLM-6B-QLoRA

CSC中文纠错数据集我这边比较明显,就是那个测试例子:”少先队员因该为老人让坐“,里面有两个错别字,不量化基本上100%识别出来,量化后50%机率”坐“没识别(改成座)。

我什么时候试试你的先量化后训练模式,跑一个epoch看看。

另外求救你推理代码里面:

q_config = BitsAndBytesConfig(load_in_4bit=True,
                              bnb_4bit_quant_type='nf4',
                              bnb_4bit_use_double_quant=True,
                              bnb_4bit_compute_dtype=torch.float32)

这个我原来理解BitSandBytes就是Transformer底层用的,官网量化到4的代码也就是
Model.quantize(4) 和你这个有什么区别吗? 缺省的bnb_4bit_quant_type应该也是nf4吧?

@shuxueslpi
Copy link

@bash99 我看了官方的model.quantize(4)的方法,好像和bitsandbytes的还有点不一样,官方的是直接量化的,bitsandbytes这种参考:https://huggingface.co/blog/zh/hf-bitsandbytes-integration

@shuxueslpi
Copy link

@bash99 期待你测试的结果

@bash99
Copy link
Author

bash99 commented Jul 6, 2023

期待你测试的结果
@shuxueslpi

我测试下来效果确实好很多,几乎和不量化差不多了。不过因为我中间也调整了训练的prompt,暂时还没有和参照https://github.com/shibing624/MedicalGPT 方法直接PEFT训练做对比。

另外我用PEFT直接训练后,似乎没法用同样的nf4去量化再加载lora进行推理,报"RuntimeError: mat1 and mat2 must have the same dtype" 这类错误。

@shuxueslpi
Copy link

@bash99 你是怎么合并lora的?我那里面有个合并lora model和base model的脚本

@bash99
Copy link
Author

bash99 commented Jul 7, 2023

@bash99 你是怎么合并lora的?我那里面有个合并lora model和base model的脚本

哦,我没做合并,直接用你推理代码的例子,先加载base_model (nf4量化),再model = PeftModel.from_pretrained(base_model, peft_model_path) 去加载lora然后推理了

你是说提前合并可能可以避免 "mat1 and mat2 must have the same dtype" 错误?

@shuxueslpi
Copy link

@bash99 先加载base_model (nf4量化),再model = PeftModel.from_pretrained(base_model, peft_model_path) 去加载lora然后推理了,这样不会报错的吧?
然后你是这样加载后想直接量化?这样加载后,base model一侧是4bit的,另一侧lora层都是fp的,就会这样报错吧。
你试试用我那个合并的脚本,直接合并一个模型,再量化看看效果。

@shuxueslpi
Copy link

@bash99 我觉得现在有几种模式,可能要测一下:
1、base model + lora model,不合并的模式,也就是你试验过的
2、base model 和 lora model做merge,但不量化(我那个脚本支持这种)
3、base model和 lora model做merge,用官方的量化方法到4bit(我那个脚本就是这样的量化)
4、base model和lora model做merge,不量化,加载的时候用BitsAndBytesConfig,即nf4的方式加载

@bash99
Copy link
Author

bash99 commented Jul 12, 2023

@bash99 我觉得现在有几种模式,可能要测一下: 1、base model + lora model,不合并的模式,也就是你试验过的 2、base model 和 lora model做merge,但不量化(我那个脚本支持这种) 3、base model和 lora model做merge,用官方的量化方法到4bit(我那个脚本就是这样的量化) 4、base model和lora model做merge,不量化,加载的时候用BitsAndBytesConfig,即nf4的方式加载

3和1就是我之前对比的,推理质量(可靠性)大幅度下降的问题。1和2对比推理时无区别。
4我刚刚测了,对比1 推理质量下降很轻微(或者不可见)。

对比了两种训练方式(lora和qlora),两种量化加载方式,用的CSC数据集,测试用例暂时比较有限。
lora比qlora,劣势:训练内存占用高、速度似乎稍慢、后期加载时必须合并;优势:可并行GPU加速;loss下降更快,3个epoch后的最低loss也更好;推理结果更好

量化加载方式,nf4推理质量优势明显,但是不够灵活,对于lora训练(而非qlora量化训练)的adapter_model.bin,必须先合并再加载。

@shuxueslpi
Copy link

shuxueslpi commented Jul 12, 2023 via email

@valkryhx
Copy link

@bash99 我觉得现在有几种模式,可能要测一下: 1、base model + lora model,不合并的模式,也就是你试验过的 2、base model 和 lora model做merge,但不量化(我那个脚本支持这种) 3、base model和 lora model做merge,用官方的量化方法到4bit(我那个脚本就是这样的量化) 4、base model和lora model做merge,不量化,加载的时候用BitsAndBytesConfig,即nf4的方式加载

3和1就是我之前对比的,推理质量(可靠性)大幅度下降的问题。1和2对比推理时无区别。 4我刚刚测了,对比1 推理质量下降很轻微(或者不可见)。

对比了两种训练方式(lora和qlora),两种量化加载方式,用的CSC数据集,测试用例暂时比较有限。 lora比qlora,劣势:训练内存占用高、速度似乎稍慢、后期加载时必须合并;优势:可并行GPU加速;loss下降更快,3个epoch后的最低loss也更好;推理结果更好

量化加载方式,nf4推理质量优势明显,但是不够灵活,对于lora训练(而非qlora量化训练)的adapter_model.bin,必须先合并再加载。

我想请问下方案4 是不是加载merge后的模型时需要向from pretrain函数传入包含nf4在内的qconfig来实现

@bash99
Copy link
Author

bash99 commented Jul 13, 2023

我想请问下方案4 是不是加载merge后的模型时需要向from pretrain函数传入包含nf4在内的qconfig来实现
对,就是下面这样
base_model = AutoModel.from_pretrained(config.base_model_name_or_path,
quantization_config=q_config
我始终找不到 加载完 lora 后再用nf4这样的模式量化的方法,就成了我说的必须先合并再nf4量化了。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants