Facico / Chinese-Vicuna

Chinese-Vicuna: A Chinese Instruction-following LLaMA-based Model —— 一个中文低资源的llama+lora方案,结构参考alpaca
https://github.com/Facico/Chinese-Vicuna
Apache License 2.0
4.14k stars 421 forks source link

关于LLAMA词表的疑问 #12

Open uloveqian2021 opened 1 year ago

uloveqian2021 commented 1 year ago

您好!感谢开源这么棒的项目,我有些疑问,很多人说LLAMA词表中只有几百个中文字,显然是不全的,这方面大佬是怎么考虑的?

Facico commented 1 year ago

@uloveqian2021 感谢对我们项目的关注。 关于llama词表的问题,其实也是很多模型的问题。

下面是一个简单的测试代码。

from transformers import LlamaTokenizer, LlamaForCausalLM

tokenizer = LlamaTokenizer.from_pretrained("decapoda-research/llama-7b-hf")

inputs = "你好一丁丂七丄丅丆万丈三上下丌不与丏丐丑丒专且丕世丗丘丙业丛东丝丞丟丠両丢丣两严並丧丨丩"
input_ids = tokenizer(inputs, return_tensors="pt")['input_ids']
print(input_ids)
print(tokenizer.decode(input_ids[0]))

正常输出为:

tensor([[    1, 29871, 30919, 31076, 30287, 31968,   231,   187,   133, 31425,
           231,   187,   135,   231,   187,   136,   231,   187,   137, 31535,
           231,   187,   139, 30457, 30429, 30557,   231,   187,   143, 30413,
         31267,   231,   187,   146,   231,   187,   147,   231,   187,   148,
           231,   187,   149, 31756,   231,   187,   151,   231,   187,   152,
         30793,   231,   187,   154,   231,   187,   155,   231,   187,   156,
         31729,   231,   187,   158, 30979,   231,   187,   160,   231,   187,
           161,   231,   187,   162,   231,   187,   163,   231,   187,   164,
           231,   187,   165,   231,   187,   166, 31977,   231,   187,   168,
           231,   187,   169,   231,   187,   170,   231,   187,   171,   231,
           187,   172]])
 你好一丁丂七丄丅丆万丈三上下丌不与丏丐丑丒专且丕世丗丘丙业丛东丝丞丟丠両丢丣两严並丧丨丩

所说的llama中只有几百个中文字,是指的像“你好”这样的,可以有一个token_id和一个字一一对应的情况。

而其他的字则可能是一3对一的形式出现,我们都知道embedding是有类似的叠加性的(比如最经典的“king-man+woman=queen”),当然llama里不是简单的相加,具体细节可以参考llama的paper。

这种方式相比起一一对应的方式,好处是能更方便地处理各种符号,所以llama的词表也比较小。但对于中文来说,他还是有很强的编码能力的,唯一的缺点在于llama所使用的中文预训练数据集不够大,会缺失很多中文特有的常识。

我们对目前这个架构有以下考虑

希望的回答对你有所帮助。

sgsdxzy commented 1 year ago

@uloveqian2021 感谢对我们项目的关注。 关于llama词表的问题,其实也是很多模型的问题。

下面是一个简单的测试代码。

from transformers import LlamaTokenizer, LlamaForCausalLM

tokenizer = LlamaTokenizer.from_pretrained("decapoda-research/llama-7b-hf")

inputs = "你好一丁丂七丄丅丆万丈三上下丌不与丏丐丑丒专且丕世丗丘丙业丛东丝丞丟丠両丢丣两严並丧丨丩"
input_ids = tokenizer(inputs, return_tensors="pt")['input_ids']
print(input_ids)
print(tokenizer.decode(input_ids[0]))

正常输出为:

tensor([[    1, 29871, 30919, 31076, 30287, 31968,   231,   187,   133, 31425,
           231,   187,   135,   231,   187,   136,   231,   187,   137, 31535,
           231,   187,   139, 30457, 30429, 30557,   231,   187,   143, 30413,
         31267,   231,   187,   146,   231,   187,   147,   231,   187,   148,
           231,   187,   149, 31756,   231,   187,   151,   231,   187,   152,
         30793,   231,   187,   154,   231,   187,   155,   231,   187,   156,
         31729,   231,   187,   158, 30979,   231,   187,   160,   231,   187,
           161,   231,   187,   162,   231,   187,   163,   231,   187,   164,
           231,   187,   165,   231,   187,   166, 31977,   231,   187,   168,
           231,   187,   169,   231,   187,   170,   231,   187,   171,   231,
           187,   172]])
 你好一丁丂七丄丅丆万丈三上下丌不与丏丐丑丒专且丕世丗丘丙业丛东丝丞丟丠両丢丣两严並丧丨丩

所说的llama中只有几百个中文字,是指的像“你好”这样的,可以有一个token_id和一个字一一对应的情况。

而其他的字则可能是一3对一的形式出现,我们都知道embedding是有类似的叠加性的(比如最经典的“king-man+woman=queen”),当然llama里不是简单的相加,具体细节可以参考llama的paper。

这种方式相比起一一对应的方式,好处是能更方便地处理各种符号,所以llama的词表也比较小。但对于中文来说,他还是有很强的编码能力的,唯一的缺点在于llama所使用的中文预训练数据集不够大,会缺失很多中文特有的常识。

我们对目前这个架构有以下考虑

* 1、比起目前市面上效果还可以的GLM:GLM的方法不是传统的MLM,在很多适配上不太容易。同时他们相对较小的模型只有10B,chatGLM是6B的(已经经过各种微调的)。llama现在的生态比较好。

* 2、我们目前做的还是instruction tuning和lora的工作。我们都知道instruction tuning是可能损害模型的能力的,他的优点在于更加听话,更加服从指令,便于挖掘模型的能力。同时lora可能也不具备学习新知识的能力。所以我们目前的框架在于如果更好的挖掘llama的能力(llama已经喂过非常多的数据了)。

希望的回答对你有所帮助。

其实那个大的GLM-130B效果也不是很好,即使是做文本生成也不够coherent,主观感受上不如llama+中文finetune。

sgsdxzy commented 1 year ago

@Facico 大佬觉得,用不用lora对于提高模型的中文能力有多少区别。我现在大概有88G显存(2080Ti 22G x 4)+128G内存,我算了一下不用lora的话用deepspeed或colossalai offload勉强能训练13B的模型,而用lora的话可以训练30B或65B的模型,您感觉哪一种方案会更好。 是不是补充全新中文知识需要非lora的训练,但是目前数据量足不足以支持这样的训练?

Evilran commented 1 year ago

@Facico 大佬您好,非常棒的开源项目,我有一个疑问。昨天看到另外一个项目,请问用这种方式对 LLaMA 进行中文词表扩充,重构合并 LoRA,然后再通过本项目进行训练,是否会对模型的中文表现有比较大的提升呢?

https://github.com/ymcui/Chinese-LLaMA-Alpaca

Facico commented 1 year ago

@sgsdxzy lora并不具备学习新知识的能力(或说非常弱),同时它对模型做的破坏也比较小,相当于一种定向挖掘。

补充全新的中文知识肯定不适合用lora。我觉得经济一点考虑可以在llama的数据上做三段式训练架构:pretrain + pre-finetune + finetune,这样pretrain的时候就用llama的模型(不需要自己去预训练),finetune的时候用lora来定向增强,pre-finetune的时候使用你自己需要扩充的数据集。这种范式在不少paper中也有。

然后offload非常慢,如果训练进度你可以接受的话也可以考虑。我们后续可能会考虑加上模型并行的部分来跑更大的模型。不过模型越大,训练速度越慢,建议看看进程,在合理的范围内就行。13B的llama纸面数据要比7B的好很多,你也可以考虑,更大模型考虑训练行程我觉得得上A100了。

Facico commented 1 year ago

@Evilran 我也关注了这个项目。由于他们这个项目是只训练embedding的部分,我觉得只要对扩充的词表训练得足够充分,在一定程度是可以提升的,这可能是一个渐进的过程,如果直接一下就扩充非常多的词很有可能会降低模型能力。

sgsdxzy commented 1 year ago

@sgsdxzy lora并不具备学习新知识的能力(或说非常弱),同时它对模型做的破坏也比较小,相当于一种定向挖掘。

补充全新的中文知识肯定不适合用lora。我觉得经济一点考虑可以在llama的数据上做三段式训练架构:pretrain + pre-finetune + finetune,这样pretrain的时候就用llama的模型(不需要自己去预训练),finetune的时候用lora来定向增强,pre-finetune的时候使用你自己需要扩充的数据集。这种范式在不少paper中也有。

然后offload非常慢,如果训练进度你可以接受的话也可以考虑。我们后续可能会考虑加上模型并行的部分来跑更大的模型。不过模型越大,训练速度越慢,建议看看进程,在合理的范围内就行。13B的llama纸面数据要比7B的好很多,你也可以考虑,更大模型考虑训练行程我觉得得上A100了。

好的,本地毕竟只是测试一下可行性,发现路能走通的话用云服务商的机器训练就好了,目前数据也不多,训练的epoch也少,也用不了多少钱。

llama这种级别的模型基本都需要offload吧,每个参数至少需要一个fp16存自己+fp32的梯度,即使用8bit adam也还需要2个字节的优化器状态,也就是1个参数需要8个字节的显存,A100 80G也就勉强能做7B的ddp,别的模型无论如何得shard

Facico commented 1 year ago

@sgsdxzy 我们这个项目初衷就是用低配置(我们使用的是11G的2080Ti)的方案。并没有使用offload,lora+fp16+8bit+256 token的训练,是可以在11G以内训练llama7B的,而且也有不错的效果。

当然如果你要全量参数微调是肯定需要offload的(在不考虑模型并行、张量并行的情况下),我们自己在11G 2080Ti上做过测试,128内存的情况下,offload极限是塞过3.5B左右的模型(offload有个estimate_zero3_model_states_mem_needs_all_live函数可以粗略的计算消耗),估计在3090Ti(24G)上可以用offload塞下llama7B

RobotSe7en commented 1 year ago

感谢作者的工作。但是我有个疑问,llama我也训练过很多次了,没有扩充词表,我也是使用的lora+8bit+1024token,数据集用的是Alpaca_50k和Belle抽取的50k合并之后的,但是训练出来的中文能力都特别差。比如“介绍一下中国的首都”,回答的不太好,有时还会一直重复。请问你的也会出现这种问题吗?还是有其它一些技巧来处理?

RobotSe7en commented 1 year ago

感谢作者的工作。但是我有个疑问,llama我也训练过很多次了,没有扩充词表,我也是使用的lora+8bit+1024token,数据集用的是Alpaca_50k和Belle抽取的50k合并之后的,但是训练出来的中文能力都特别差。比如“介绍一下中国的首都”,回答的不太好,有时还会一直重复。请问你的也会出现这种问题吗?还是有其它一些技巧来处理?

同时,我发现伯克利的vicuna的中文能力还不错,他们好像也只使用了少量中文数据集,没有刻意加入中文。唯一的区别是他们没用lora,我在想会不会lora就存在这种缺陷

Facico commented 1 year ago

@RobotSe7en 首先,效果不好,可能有以下问题:

  1. 生成的时候没有使用beam search,Repetition Penalty等参数
  2. 数据量的问题,50k+50k的中文对于一个主要是英文的模型可能还差了一点。像alpaca 50k英文那个语料,可能得训10个epoch才充分一点。

全量微调比lora的好处目前应该只在一些垂直语料的训练上。不过在挖掘llama的中文能力上使用全量微调肯定会比lora有好处,我们后续会尝试将lora的low rank开大一点,同时使lora能训练的参数加多一点。

RobotSe7en commented 1 year ago

推理代码我是这样写的:

model.eval()
with torch.no_grad():
    preds = model.generate(
        input_ids=input_ids,
        max_new_tokens=256,
        do_sample=True,
        temperature=0.7,
        top_p=0.95,
        top_k=40
    )

应该是用了beam_search吧

Facico commented 1 year ago

你可以参考我们generate里面设置试试

RobotSe7en commented 1 year ago

你可以参考我们generate里面设置试试

好的,我试试

vpegasus commented 1 year ago

@sgsdxzy lora并不具备学习新知识的能力(或说非常弱),同时它对模型做的破坏也比较小,相当于一种定向挖掘。

补充全新的中文知识肯定不适合用lora。我觉得经济一点考虑可以在llama的数据上做三段式训练架构:pretrain + pre-finetune + finetune,这样pretrain的时候就用llama的模型(不需要自己去预训练),finetune的时候用lora来定向增强,pre-finetune的时候使用你自己需要扩充的数据集。这种范式在不少paper中也有。

然后offload非常慢,如果训练进度你可以接受的话也可以考虑。我们后续可能会考虑加上模型并行的部分来跑更大的模型。不过模型越大,训练速度越慢,建议看看进程,在合理的范围内就行。13B的llama纸面数据要比7B的好很多,你也可以考虑,更大模型考虑训练行程我觉得得上A100了。

@Facico 你好,请问lora并不具备学习新知识的能力(或说非常弱) 这个结论有没有相关参考资料呀, 想深入了解下, 比如论文,全方位的对比实验,或者理论推导也可,谢谢。 因为我们现在gpu资源有限,而且还想着让模型学习特定知识。 如果上述结论有理论支持的话,我们可能要调整我们的策略。

guker commented 1 year ago

@Facico 大佬觉得,用不用lora对于提高模型的中文能力有多少区别。我现在大概有88G显存(2080Ti 22G x 4)+128G内存,我算了一下不用lora的话用deepspeed或colossalai offload勉强能训练13B的模型,而用lora的话可以训练30B或65B的模型,您感觉哪一种方案会更好。 是不是补充全新中文知识需要非lora的训练,但是目前数据量足不足以支持这样的训练?

使用88G显存训练13B,你的batchsize是多少?

machengyan commented 1 year ago

@Facico 很奇怪,我用DDP方式两块3090训练13B vicunna, 一个月之前是可以的, 但是现在一样的环境就不行了, 说是cuda显存不够. 我看了以下,模型加载进去占用了14G, 还剩10G的空闲显存. 开始训练后,一下就溢出了. 因为一个月前我训练的时候,没问题,所以没有看具体的占用情况. 我把batch ,microbatch都调到了最小,也不行.

gloryfromca commented 2 months ago

lora并不具备学习新知识的能力(或说非常弱),同时它对模型做的破坏也比较小,相当于一种定向挖掘。

补充全新的中文知识肯定不适合用lora。我觉得经济一点考虑可以在llama的数据上做三段式训练架构:pretrain + pre-finetune + finetune,这样pretrain的时候就用llama的模型(不需要自己去预训练),finetune的时候用lora来定向增强,pre-finetune的时候使用你自己需要扩充的数据集。这种范式在不少paper中也有。

然后offload非常慢,如果训练进度你可以接受的话也可以考虑。我们后续可能会考虑加上模型并行的部分来跑更大的模型。不过模型越大,训练速度越慢,建议看看进程,在合理的范围内就行。13B的llama纸面数据要比7B的好很多,你也可以考虑,更大模型考虑训练行程我觉得得上A100了。

@Facico 这个范式叫什么?有没有经典的paper展示全流程?我现在希望用0.5B模型学习垂直领域的特定知识然后再对任务进行微调,我也是这个思路,但目前不确定要怎么做。比如训练的领域数据集大小、构造和如何训练。

Facico commented 2 months ago

@gloryfromca 你可以看看post pretrain/continue pretrain相关的东西