介绍

以ChatGLM-6B ptuning提供的微调代码来进行测试,整体代码在此

训练和推理

训练就直接使用官方代码啦,推理也是滴,整体流程跑通都很顺畅,整体是采用quantization_bit=4,所以单卡(5~6G显存)就能跑的起来。

记录几个有意思的点。

1. p-tuning

这个是众多Parameter Efficient fine-tune实现方式之一,其发展历程简单理解有两个阶段,一是人工构造template,二是机器自己学习一个template。

比如一开始做分类,例如“这个沙发怎么样”,那就在这句话前面(当然也可以放到后面)加上一个template,比如情感分析,这个沙发怎么样你觉得这句话是正向还是负向:这个沙发怎么样,那训练时只对这个template进行微调,因为微调seq_len很少,所以速度杠杠滴。不过另外还有一个比较重要的点,贴和预训练模型任务。比如bert采用了mask方式来做预训练,但是你这里明明后面接个二分类,咋说也说不通啊,那为了贴和预训练任务,构造也可以这样:情感分析,这个沙发怎么样<mask>,那由bert来预测<mask>位置的值,比如“好”或者“坏”,或者设置一堆和“好”或者“坏”同义的词(amaze、bad)。但是这个呢,又不能解决通用,比如NER任务,“张三和李四谁更漂亮?”,那总不能先知道几个<mask>吧,以及bert的<mask>是字粒度的。

emmmm,扯远了,总结来说第一个阶段的peft可理解为人工构造一个template,但是呢,它是显性的,谁知道哪个template会更好。所以咱也不猜了,让模型自己去学去吧。

所以这里引入了第二个阶段:模型自己来学习合适的template。

p-tuning v2采用引入一个pre_seq_len,也就是PrefixEncoder,比如2, 8, 16(只要不超长都可以),那只对这一部分进行微调,bert本身不参与微调哦,从而达成了不自己抓脑袋想一个有效的template,从而也完成了一个通用的目的。

关于p-tuning v2实现,可以参考这里

2. 速度

这个真是牙痒痒,明明已经使用p-tuning了,明明也量化到4bit了,明明还使用了GPU,还这么慢,不得提前吐槽一下。。。

关于速度慢,一个点是更长的上下文计算attention不可能不慢,新的技术flash-attention(torch2已经原生支持了哦,现在很多大模型都在torch2上跑了哦)更为有效解决这个问题,不过这个不是在算法本身做了优化,所以跳过。

建议使用v2或v3, 如果非用这个,建议推理时采用stream_chat,或是采用Lora微调。

3. 效果

比如采用下面脚本看微调后的效果,会遇到几个比较值得注意的点。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
from transformers import set_seed, AutoConfig, AutoModel, AutoTokenizer
import torch
import os
import time

set_seed(42)

model_name_or_path = 'chatglm-6b'
ptuning_checkpoint = 'ptuning/output/adgen-chatglm-6b-pt-128-0.02/checkpoint-3000'

config = AutoConfig.from_pretrained(model_name_or_path, trust_remote_code=True)
config.pre_seq_len = 128
config.prefix_projection = False


tokenizer = AutoTokenizer.from_pretrained(model_name_or_path, trust_remote_code=True)


model = AutoModel.from_pretrained(model_name_or_path, config=config, trust_remote_code=True)

prefix_state_dict = torch.load(os.path.join(ptuning_checkpoint, "pytorch_model.bin"), map_location='cpu')
new_prefix_state_dict = {}
for k, v in prefix_state_dict.items():
if k.startswith("transformer.prefix_encoder."):
new_prefix_state_dict[k[len("transformer.prefix_encoder."):]] = v
model.transformer.prefix_encoder.load_state_dict(new_prefix_state_dict)
model = model.quantize(4)

model.to("cuda:0")
model = model.half()
model.transformer.prefix_encoder.float()
model.eval()
start_time = time.time()
for i in range(30):
response, history = model.chat(tokenizer, "你好", history=[])
print(response)
response, history = model.chat(tokenizer, "晚上睡不着应该怎么办", history=history)
print(response)

# CUDA_VISIBLE_DEVICES=0 python run_finetuned_demo.py

response, history = model.chat(tokenizer, "请根据以下标签为商品编写一段广告\n类型#裤*版型#显瘦*颜色#黑色*风格#简约*裤长#九分裤", history=[])
print(response)

print(time.time() - start_time)


1. 出现<UNK>和重复

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
一件<UNK>,<UNK>,<UNK>,<UNK>,<UNK>,<UNK>,<UNK>,<UNK>,<UNK>,<UNK>,<UNK>,<UNK>,<UNK>,<UNK>,<UNK>,
BRAND这款<UNK>的裤子,在设计上很注重细节,衣袖和裤腿处都是<UNK>的<UNK>,<UNK>和<UNK>,<UNK>和<UNK>,<UNK>和<UNK>,<UNK>和<UNK>,
简约修身的版型设计,上身十分显瘦,而且穿着十分有型。黑色款式设计,简约大气,时尚百搭,适合各种场合穿着。九分裤的长度设计,露出脚踝,视觉上显瘦。
设计师对细节的把控是很高的,这样可以让整体看上去更加有设计感。而设计师在设计的同时对颜色的选择也是特别用心的,这样可以让整体看上去更加有格调,并且可以更好的展现出一种高端大气的格调。
睡眠是身体和心灵都需要得到放松的,而晚上睡不着,可以做一些舒缓身心的活动,比如<UNK>,释放身心压力,缓解身心疲劳。而晚上睡不着,还可以去<UNK>,<UNK>音乐,让身心都得到放松。此外,可以做一些轻松的瑜伽,
简约的黑色,上身更显帅气与利落,时尚修身的剪裁,穿着舒适,尽显女性魅力。九分的长度,轻松露出纤细的脚踝,更显腿长,拉长身材比例。
采用优质的面料,使宝贝穿着舒适,保持柔软亲肤。搭配精致小立领,凸显宝贝脸型,彰显气质。搭配精致的包边工艺,使宝贝穿着舒适,方便宝贝穿脱。
选用优质的面料,柔软亲肤,穿着舒适,穿着方便。精致小立领设计,凸显宝贝脸型,凸显宝贝气质。精致的包边工艺,方便穿脱。搭配精致的小立领,彰显宝贝气质。穿着舒适,柔软亲肤,穿着方便,穿着舒适。
经典简约的黑色调,搭配九分裤的设计,不仅显瘦还修饰腿部曲线,上身更显腿长。修身的版型设计,展现女性优美的腿部曲线,尽显优雅气质。
小宝贝在婴儿时期就接受了优质的营养,所以宝宝的身体健康状况良好。宝宝从婴儿时期就接受了优质的营养,因此宝宝身体健康状况良好,没有<UNK>。宝宝在婴儿时期就接受了优质的营养,所以宝宝身体健康。
小宝贝从婴儿时期就接受了优质的营养,身体健康状况良好,没有<UNK>。小宝贝从婴儿时期就接受了优质的营养,身体健康状况良好,没有<UNK>。小宝贝从婴儿时期就接受了优质的营养,身体健康状况良好,没有<UNK>。小宝贝从婴儿
黑色修身的九分裤,能更好的修饰腿型,让双腿显得更加修长,凸显女性的高挑。简约的修身版型,穿起来更显笔直修长。九分裤的长度,可以更好的修饰腿型,让双腿显得更加修长,显瘦效果也更好。
非常可爱的小萌宝,可爱又甜美,非常符合儿童的审美。可爱的小萌宝,大大的眼睛,大大的眼睛,大大的眼睛,很迷人。小萌宝,小萌宝,非常可爱,非常可爱。
儿童睡觉不踏实,晚上睡不着,是困扰许多家长的问题。在儿童睡眠中,儿童喜欢甜甜地睡觉,而且儿童喜欢甜美可爱的形象。儿童喜欢甜美可爱的形象,喜欢可爱可爱的儿童,喜欢甜美可爱的儿童。儿童喜欢甜美可爱的儿童,喜欢甜美可爱的儿童。甜美可爱的
这条黑色的修身九分裤,简约时尚,轻松穿出帅气的感觉,上身之后非常显瘦。而且裤脚采用了松紧的设计,穿起来更加舒适。九分的长度,轻松露出纤细的脚踝,显得双腿修长又笔直。
一件<UNK>的衬衫是很多人衣橱里必不可少的单品,穿着舒适,上身效果出色。而这款衬衫的面料采用的是<UNK>面料,柔软舒适,穿着不紧绷。
衬衫作为女性衣橱里的必备单品,穿起来舒适又百搭,让你轻松穿出女神范。而这款衬衫选用的是柔软舒适的面料,穿着舒适又透气。而且面料表面带有<UNK>的纹理,看起来质感丰富。穿着舒适不紧绷,上身效果出色。而且衬衫的衣领
一款简约而不简单的休闲裤,黑色的色调,经典百搭,彰显时尚气质。修身的版型,展现窈窕身材,搭配九分裤长,彰显干练气质。
采用<UNK>面料,<UNK>工艺,面料轻盈舒适,不易变形。<UNK>面料,<UNK>面料,<UNK>面料,<UNK>面料,<UNK>面料,<UNK>面料,<UNK>面料,<UNK>面料,<UNK>
轻薄的面料,轻盈舒适,不会引起的任何不适。面料柔软舒适,不易变形,穿着舒适,不易褶皱。采用<UNK>工艺,不易变形,不会引起的任何不适。面料轻盈舒适,不易变形,不会引起的任何不适。<UNK>面料,<UNK>面料,
黑色百搭又显瘦,在裤子的设计上,设计师采用简约大方的九分裤型,上身显瘦又显腿长。腰部采用了松紧的设计,不勒腰,穿脱方便。
来自<UNK>的这款儿童儿童<UNK>儿童儿童<UNK>儿童儿童<UNK>儿童儿童<UNK>儿童儿童<UNK>儿童儿童<UNK>儿童儿童儿童<UNK>儿童儿童<UNK>儿童儿童<UNK>儿童儿童儿童<UNK>儿童儿童<
儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童儿童

按理说这6B大模型不应该啊!!按理说即使不做超参调整或者说generate时做重复惩罚,也应该效果好是不是~~~

2. 灾难性遗忘

首先这是一个现象,其issue里也讨论了蛮多关于这个话题。有人说p-tuning不就干这个的嘛,你推理时都加了p-tuning这部分参数,那肯定的啊。还有人说Lora虽然也有这个现象,但是比p-tuning要好的多。反正婆说婆有理。

官方给的improve,比如在官方示例前面添加描述性文本”请根据以下标签为商品编写一段广告\n“,最终训练数据类似下面这样:

1
请根据以下标签为商品编写一段广告\n类型#裤*版型#显瘦*颜色#黑色*风格#简约*裤长#九分裤

但是我训练完还是会这样。

也有人说把学习率调的更低一些,还有说官方给了10几w的训练样本,只用1~2k试试。

这个本身还是有方法可以解决的,比如base大模型不动,可以在上面添加很多的prefx_encoder嘛~~~

总结

多来点A100~