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

[BUG/Help]开batch预测时,模型结果不一致。 #841

Open
1 task done
lidejian opened this issue Apr 27, 2023 · 23 comments
Open
1 task done

[BUG/Help]开batch预测时,模型结果不一致。 #841

lidejian opened this issue Apr 27, 2023 · 23 comments

Comments

@lidejian
Copy link

lidejian commented Apr 27, 2023

Is there an existing issue for this?

  • 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的结果始终和单条预测结果对不齐)。类似问题有搜索到huggingface/transformers#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

@lidejian
Copy link
Author

image代码。

@duzx16
Copy link
Member

duzx16 commented Apr 27, 2023

有可能是显卡计算的精度误差导致的。只要生成结果都合理即可吧

@lidejian
Copy link
Author

有可能是显卡计算的精度误差导致的。只要生成结果都合理即可吧

相同环境相同显卡,也降低了各种生成稳定性的参数。部署的还是想结果可复现吧,不开batch预测速度太慢了

@Tongjilibo
Copy link

我看eval时候,样本都是padding在前面的,这个是为啥呢

@lidejian
Copy link
Author

我看eval时候,样本都是padding在前面的,这个是为啥呢

因为自回归预测时,结果会依据上一个字符。所以如果按照常规pad右边,很大程度上依赖pad在输出,不太合理。因此pad在左边,让模型尽可能地依赖输入,减少pad的影响吧。(个人理解)

@Tongjilibo
Copy link

我看eval时候,样本都是padding在前面的,这个是为啥呢

因为自回归预测时,结果会依据上一个字符。所以如果按照常规pad右边,很大程度上依赖pad在输出,不太合理。因此pad在左边,让模型尽可能地依赖输入,减少pad的影响吧。(个人理解)

这个我理解,那和我单条输入的时候是一样的吗?padding在左边,那句子的position_ids也会变啊,如果说是相对位置编码不受这个影响我可以认同,那使别的绝对位置编码的decoder模型如果padding在左边,那position_embedding就很不同了

@lidejian
Copy link
Author

我看eval时候,样本都是padding在前面的,这个是为啥呢

因为自回归预测时,结果会依据上一个字符。所以如果按照常规pad右边,很大程度上依赖pad在输出,不太合理。因此pad在左边,让模型尽可能地依赖输入,减少pad的影响吧。(个人理解)

这个我理解,那和我单条输入的时候是一样的吗?padding在左边,那句子的position_ids也会变啊,如果说是相对位置编码不受这个影响我可以认同,那使别的绝对位置编码的decoder模型如果padding在左边,那position_embedding就很不同了

是的,按道理来说,应该会忽略pad的值。所以这个感觉更像是是transformer的一个bug吧

@Tongjilibo
Copy link

Tongjilibo commented Apr 28, 2023

是的,按道理来说,应该会忽略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在左边是最简单的选择,但是不明白其合理性

@lidejian
Copy link
Author

是的,按道理来说,应该会忽略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对结果有影响。

@HL0718
Copy link

HL0718 commented May 10, 2023

是的,按道理来说,应该会忽略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的效果,实际上的推理速度并没有提升?

@irasin
Copy link

irasin commented May 11, 2023

是的,按道理来说,应该会忽略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]
咳嗽是身体的一种自我保护机制,可以帮助清除呼吸道中的异物和痰液,但如果咳嗽过于剧烈或持续时间过长,可能会对身体健康造成不良影响。以下是一些缓解咳嗽的方法:

  1. 喝足够的水:喝足够的水可以帮助稀释痰液和减少喉咙干燥的感觉,有助于缓解咳嗽。

  2. 盐水漱口:将一小勺盐加入温水中,漱口可以帮助清除喉咙中的痰液和异物,缓解咳嗽。

  3. 使用加湿器:使用加湿器可以增加空气中的湿度,缓解喉咙干燥的感觉,减轻咳嗽。

  4. 避免吸烟和烟雾:吸烟和烟雾会刺激喉咙和呼吸道,加重咳嗽症状。

  5. 服用药物:如果咳嗽症状较严重,可以服用药物,如咳嗽药、止咳糖浆等,但需要在医生的指导下使用。

  6. 进行呼吸训练:一些呼吸训练可以帮助缓解咳嗽症状,如慢呼吸、深呼吸等。

如果咳嗽症状持续时间较长或严重影响日常生活,建议及时就医。

以上建议仅供参考,具体实施前请咨询医生或专业人士。

咳嗽是常见的症状,如果症状轻微,可以通过一些自我缓解措施来缓解。但如果咳嗽症状严重

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

[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]

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

@lidejian
Copy link
Author

lidejian commented May 11, 2023

batch中较短的pad不会影响,batch中尝试结合下长短文本结合(eg:400/20),会发现短文本在长pad下,输出会和不开batch预测短文本不一致。参考https://huggingface.co/THUDM/chatglm-6b/blob/main/test_modeling_chatglm.py#L120,开batch结果不一致

@Tongjilibo
Copy link

@irasin 是的,我看了下padding在左边,其position_ids也是从非padding位置开始的,这样不仅是chatglm,应该所有的decoder架构的都可以padding在左边来实现batch_generate

@hrdxwandg
Copy link

batch中较短的pad不会影响,batch中尝试结合下长短文本结合(eg:400/20),会发现短文本在长pad下,输出会和不开batch预测短文本不一致。参考https://huggingface.co/THUDM/chatglm-6b/blob/main/test_modeling_chatglm.py#L120,开batch结果不一致

我也是batch预测和单条不一致,问下解决了么?

@hrdxwandg
Copy link

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
Copy link

irasin commented Jun 16, 2023

@irasin 是的,我看了下padding在左边,其position_ids也是从非padding位置开始的,这样不仅是chatglm,应该所有的decoder架构的都可以padding在左边来实现batch_generate

确实是这样的,但是chatglm相比其他的模型还是要特殊一点的,由于涉及到position_2d,做batch_generation的时候,两种position的处理方式还不一样,这个需要注意一下

@sc-lj
Copy link

sc-lj commented Aug 2, 2023

transformers==4.30.2
AutoTokenizer只要开了padding =True, 就会很慢,即使是只有一条文本。这个如何解决呢?

@Tongjilibo
Copy link

transformers==4.30.2
AutoTokenizer只要开了padding =True, 就会很慢,即使是只有一条文本。这个如何解决呢?

试试传入use_fast=False

@jameswu2014
Copy link

和padding没关系吧,是fp16精度问题

@kylinat2688
Copy link

这个问题解决了吗

@minixalpha
Copy link

minixalpha commented Oct 23, 2023

能把你初始化 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)

后这种现象会有所缓解,但没完全消失。

@xiaoduozhou
Copy link

我也有这种问题, batch_size=1 和 batch_size=10 的时候 同一个输入推理出来的不一样,这个怎么办吗

@Mucalinda2436
Copy link

同问,到底是什么原因呀

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