ChatGLM-6B
ChatGLM-6B copied to clipboard
[BUG/Help]开batch预测时,模型结果不一致。
Is there an existing issue for this?
- [X] I have searched the existing issues
Current Behavior
p-tuning模型后,模型开batch预测时,tokenizer时使用pad填充,使用generate方法预测时,结果和单条预测不一致(已设置 do_sample=False, temperature=0.01,top_p=0.01等确保模型输出稳定性。重复多次,batch的结果始终和单条预测结果对不齐)。类似问题有搜索到https://github.com/huggingface/transformers/issues/14521 ,请问这是transformer的问题么?
def batch_predict(batch_input, max_length = 500):
# os.system('clear')
gc.collect()
torch.cuda.empty_cache()
with torch.no_grad():
batch_ids = tokenizer(
batch_input,
padding=True,
max_length=max_length,
truncation=True,
return_tensors="pt"
)
for i in batch_ids['input_ids']:
print('batch_ids:', i)
input_ids = torch.LongTensor(batch_ids['input_ids']).to(device)
out = model.generate(
input_ids=input_ids,
max_length=max_length+500,
do_sample=False,
temperature=0.01,
top_p=0.01,
num_beams=1
)
batch_answers = map(tokenizer.decode, out)
return batch_answers
Expected Behavior
No response
Steps To Reproduce
Environment
- OS:Linux version 4.18.0
- Python:3.8
- Transformers:4.27.1
- PyTorch: 1.13.1
- CUDA Support (`python -c "import torch; print(torch.cuda.is_available())"`) :True
Anything else?
No response
代码。
有可能是显卡计算的精度误差导致的。只要生成结果都合理即可吧
有可能是显卡计算的精度误差导致的。只要生成结果都合理即可吧
相同环境相同显卡,也降低了各种生成稳定性的参数。部署的还是想结果可复现吧,不开batch预测速度太慢了
我看eval时候,样本都是padding在前面的,这个是为啥呢
我看eval时候,样本都是padding在前面的,这个是为啥呢
因为自回归预测时,结果会依据上一个字符。所以如果按照常规pad右边,很大程度上依赖pad在输出,不太合理。因此pad在左边,让模型尽可能地依赖输入,减少pad的影响吧。(个人理解)
我看eval时候,样本都是padding在前面的,这个是为啥呢
因为自回归预测时,结果会依据上一个字符。所以如果按照常规pad右边,很大程度上依赖pad在输出,不太合理。因此pad在左边,让模型尽可能地依赖输入,减少pad的影响吧。(个人理解)
这个我理解,那和我单条输入的时候是一样的吗?padding在左边,那句子的position_ids也会变啊,如果说是相对位置编码不受这个影响我可以认同,那使别的绝对位置编码的decoder模型如果padding在左边,那position_embedding就很不同了
我看eval时候,样本都是padding在前面的,这个是为啥呢
因为自回归预测时,结果会依据上一个字符。所以如果按照常规pad右边,很大程度上依赖pad在输出,不太合理。因此pad在左边,让模型尽可能地依赖输入,减少pad的影响吧。(个人理解)
这个我理解,那和我单条输入的时候是一样的吗?padding在左边,那句子的position_ids也会变啊,如果说是相对位置编码不受这个影响我可以认同,那使别的绝对位置编码的decoder模型如果padding在左边,那position_embedding就很不同了
是的,按道理来说,应该会忽略pad的值。所以这个感觉更像是是transformer的一个bug吧
是的,按道理来说,应该会忽略pad的值。所以这个感觉更像是是transformer的一个bug吧
我的困惑点是在是否使用use_cache,如果不使用那padding在右边也可以,只要解码出下一个token_ids时候接到上次padding之前,如下所示:
# 原始输入
input = tensor([[1,2,3,4,5], [1,2,0,0,0]])
# 解码得到各自的结果是6, 3,那下一次输入的就应该是
input_new = tensor([[1,2,3,4,5,6], [1,2,3,0,0,0]])
但是如果使用use_cache,那past_key_value这些就很难处理了,所以padding在左边是最简单的选择,但是不明白其合理性
是的,按道理来说,应该会忽略pad的值。所以这个感觉更像是是transformer的一个bug吧
我的困惑点是在是否使用use_cache,如果不使用那padding在右边也可以,只要解码出下一个token_ids时候接到上次padding之前,如下所示:
# 原始输入 input = tensor([[1,2,3,4,5], [1,2,0,0,0]]) # 解码得到各自的结果是6, 3,那下一次输入的就应该是 input_new = tensor([[1,2,3,4,5,6], [1,2,3,0,0,0]])但是如果使用use_cache,那past_key_value这些就很难处理了,所以padding在左边是最简单的选择,但是不明白其合理性
刚才测试了下,我的目的是想得到确定的结果,在参数do_sample=False,temperature=0.01,top_p=0.01,num_beams=1下,试验了bs=1/32, use_cache=True/Flase。结果use_cache设置True、False对结果无影响。不同的bs对结果有影响。
是的,按道理来说,应该会忽略pad的值。所以这个感觉更像是是transformer的一个bug吧
我的困惑点是在是否使用use_cache,如果不使用那padding在右边也可以,只要解码出下一个token_ids时候接到上次padding之前,如下所示:
# 原始输入 input = tensor([[1,2,3,4,5], [1,2,0,0,0]]) # 解码得到各自的结果是6, 3,那下一次输入的就应该是 input_new = tensor([[1,2,3,4,5,6], [1,2,3,0,0,0]])但是如果使用use_cache,那past_key_value这些就很难处理了,所以padding在左边是最简单的选择,但是不明白其合理性
刚才测试了下,我的目的是想得到确定的结果,在参数do_sample=False,temperature=0.01,top_p=0.01,num_beams=1下,试验了bs=1/32, use_cache=True/Flase。结果use_cache设置True、False对结果无影响。不同的bs对结果有影响。
请问一下,我在batch预测时,比较了batchsize=1和batchsize=24的情况下,其中batchsize=24的效率是batchsize=1的4倍,但是消耗的显存也是4倍,那是不是可以理解为我在batchsize=1的情况下多个几个副本也能达到batchsize=24的效果,实际上的推理速度并没有提升?
是的,按道理来说,应该会忽略pad的值。所以这个感觉更像是是transformer的一个bug吧
我的困惑点是在是否使用use_cache,如果不使用那padding在右边也可以,只要解码出下一个token_ids时候接到上次padding之前,如下所示:
# 原始输入 input = tensor([[1,2,3,4,5], [1,2,0,0,0]]) # 解码得到各自的结果是6, 3,那下一次输入的就应该是 input_new = tensor([[1,2,3,4,5,6], [1,2,3,0,0,0]])但是如果使用use_cache,那past_key_value这些就很难处理了,所以padding在左边是最简单的选择,但是不明白其合理性
刚才测试了下,我的目的是想得到确定的结果,在参数do_sample=False,temperature=0.01,top_p=0.01,num_beams=1下,试验了bs=1/32, use_cache=True/Flase。结果use_cache设置True、False对结果无影响。不同的bs对结果有影响。
你好,如果batch推理的话,肯定是pad_on_left的,pad_on_right相当于是根据pad_token来生成next_token。
我这边尝试了一些batch推理的, pad_on_left的结果应该是ok的
[PROMPT] 咳嗽怎么办
[OUTPUT] 咳嗽是身体的一种自我保护机制,可以帮助清除呼吸道中的异物和痰液,但如果咳嗽过于剧烈或持续时间过长,可能会对身体健康造成不良影响。以下是一些缓解咳嗽的方法:
-
喝足够的水:喝足够的水可以帮助稀释痰液和减少喉咙干燥的感觉,有助于缓解咳嗽。
-
盐水漱口:将一小勺盐加入温水中,漱口可以帮助清除喉咙中的痰液和异物,缓解咳嗽。
-
使用加湿器:使用加湿器可以增加空气中的湿度,缓解喉咙干燥的感觉,减轻咳嗽。
-
避免吸烟和烟雾:吸烟和烟雾会刺激喉咙和呼吸道,加重咳嗽症状。
-
服用药物:如果咳嗽症状较严重,可以服用药物,如咳嗽药、止咳糖浆等,但需要在医生的指导下使用。
-
进行呼吸训练:一些呼吸训练可以帮助缓解咳嗽症状,如慢呼吸、深呼吸等。
如果咳嗽症状持续时间较长或严重影响日常生活,建议及时就医。
以上建议仅供参考,具体实施前请咨询医生或专业人士。
咳嗽是常见的症状,如果症状轻微,可以通过一些自我缓解措施来缓解。但如果咳嗽症状严重
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
[PROMPT] 你好
[OUTPUT] 你好👋!我是人工智能助手 ChatGLM-6B,很高兴见到你,欢迎问我任何问题。
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
[PROMPT] 你知道chatgpt吗
[OUTPUT] ChatGPT是GPT-3模型的一个变体,用于在聊天对话中生成文本。它可以针对给定的输入文本生成连续的文本回复,其文本内容基于预先编写的算法和规则,而不是基于人类的经验或知识。ChatGPT被设计为一种语言模型,可以用于各种应用,例如自然语言处理、文本生成、对话系统、机器翻译等。 回答您的问题时,我了解到ChatGPT是一种人工智能模型,可以生成文本回复。它由OpenAI开发,并用于回答您的问题和提供相关信息。
GPT-3是一种大型语言模型,由OpenAI开发,可以用于生成高质量的自然语言文本。它可以生成文本、回答问题、进行对话、撰写文章等,并且可以针对特定的任务进行训练和调优。GPT-3在自然语言生成领域的研究和应用具有很高的价值,已经被广泛应用于各种应用场景中。
ChatGPT是GPT-3模型的一个变体,用于在聊天对话中生成文本。它可以针对给定的输入文本生成连续的文本回复,其文本内容基于预先编写的算法和规则,而不是基于人类的经验或知识。
希望这些信息能对您有所帮助。如果您有其他问题,请随时问我。
敬礼!
chatgpt人工智能工程师2023年2月24日
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
[PROMPT] 请用python写一段快速排序
[OUTPUT] 好的,下面是用 Python 实现的快速排序算法示例代码:
def quicksort(arr):
if len(arr) <= 1:
return arr
else:
pivot = arr[0]
left = []
right = []
for i in range(1, len(arr)):
if arr[i] < pivot:
left.append(arr[i])
else:
right.append(arr[i])
return quicksort(left) + [pivot] + quicksort(right)
这个函数接受一个列表 arr 作为输入,并返回一个新的排序后的列表。如果输入列表的长度小于等于 1,则直接返回列表本身。否则,选择列表的第一个元素作为枢轴,并将列表中小于枢轴的元素放在一个子列表中,大于等于枢轴的元素放在一个子列表中。然后,递归地对这两个子列表进行排序,并将结果合并在一起返回。
例如,要对以下列表进行快速排序:
arr = [3, 6, 1, 8, 5, 2, 9, 4, 7]
调用 quicksort(arr) 将会返回以下结果:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
batch中较短的pad不会影响,batch中尝试结合下长短文本结合(eg:400/20),会发现短文本在长pad下,输出会和不开batch预测短文本不一致。参考https://huggingface.co/THUDM/chatglm-6b/blob/main/test_modeling_chatglm.py#L120,开batch结果不一致
@irasin 是的,我看了下padding在左边,其position_ids也是从非padding位置开始的,这样不仅是chatglm,应该所有的decoder架构的都可以padding在左边来实现batch_generate
batch中较短的pad不会影响,batch中尝试结合下长短文本结合(eg:400/20),会发现短文本在长pad下,输出会和不开batch预测短文本不一致。参考https://huggingface.co/THUDM/chatglm-6b/blob/main/test_modeling_chatglm.py#L120,开batch结果不一致
我也是batch预测和单条不一致,问下解决了么?
batch中较短的pad不会影响,batch中尝试结合下长短文本结合(eg:400/20),会发现短文本在长pad下,输出会和不开batch预测短文本不一致。参考https://huggingface.co/THUDM/chatglm-6b/blob/main/test_modeling_chatglm.py#L120,开batch结果不一致
我也是batch预测和单条不一致,问下解决了么?
https://huggingface.co/THUDM/chatglm-6b/blob/main/test_modeling_chatglm.py#L120 这个可以,不能只传input_ids
@irasin 是的,我看了下padding在左边,其position_ids也是从非padding位置开始的,这样不仅是chatglm,应该所有的decoder架构的都可以padding在左边来实现batch_generate
确实是这样的,但是chatglm相比其他的模型还是要特殊一点的,由于涉及到position_2d,做batch_generation的时候,两种position的处理方式还不一样,这个需要注意一下
transformers==4.30.2 AutoTokenizer只要开了padding =True, 就会很慢,即使是只有一条文本。这个如何解决呢?
transformers==4.30.2 AutoTokenizer只要开了padding =True, 就会很慢,即使是只有一条文本。这个如何解决呢?
试试传入use_fast=False
和padding没关系吧,是fp16精度问题
这个问题解决了吗
能把你初始化 model 的代码贴一下吗?我用 llama2 的时候遇到了同样问题,
model = LlamaForCausalLM.from_pretrained(model_id, load_in_8bit=True, device_map='auto', torch_dtype=torch.float16)
改成
model = LlamaForCausalLM.from_pretrained(model_id, load_in_8bit=True, device_map='auto', torch_dtype=torch.float32)
后这种现象会有所缓解,但没完全消失。
我也有这种问题, batch_size=1 和 batch_size=10 的时候 同一个输入推理出来的不一样,这个怎么办吗
同问,到底是什么原因呀