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:ceval, cmmlu和mmlu中选项ABCD的概率计算错误 #57

Open
naturesphere opened this issue Nov 26, 2023 · 3 comments
Open

BUG:ceval, cmmlu和mmlu中选项ABCD的概率计算错误 #57

naturesphere opened this issue Nov 26, 2023 · 3 comments

Comments

@naturesphere
Copy link

Skywork/eval/文件夹下的evaluate_ceval.py, evaluate_cmmlu.py和evaluate_mmlu.py文件中,获取选项ABCD的概率的关键代码如下:

    softval = torch.nn.functional.softmax(
        torch.tensor(
            [
                logits[tokenizer("A")["input_ids"][-1]],
                logits[tokenizer("B")["input_ids"][-1]],
                logits[tokenizer("C")["input_ids"][-1]],
                logits[tokenizer("D")["input_ids"][-1]],
            ]
        ),
        dim=0,
    )

以选项A为例:
tokenizer("A")会把“A“认为是一个句子,在”A“前面拼接句子开始标志”_“。因此tokenizer实际上转化的字符为“<s> _A”,得到input_ids=[1, 319]。代码中tokenizer("A")["input_ids"][-1]取得的id是319,对应的字符为“_A”,而真正“A”字符对应的id是:

tokenizer.convert_tokens_to_ids('A')=29909.

BCD选项也存在同样的问题。

评估时的一个full_prompt的例子格式如下:

以下是关于农学的单项选择题,请直接给出正确答案的选项。

题目:肉牛屠宰后,胴体的哪个部位肉质较好
A. 胸
B. 腹
C. 大腿
D. 小腿
答案:C

……

题目:羊胴体中,肉质较好的部位是
A. 胸下肉
B. 肩胛肉
C. 后腿肉
D. 小腿肉
答案:C

以下是关于农学的单项选择题,请直接给出正确答案的选项。

题目:在农业生产中被当作极其重要的劳动对象发挥作用,最主要的不可替代的基本生产资料是
A. 农业生产工具
B. 土地
C. 劳动力
D. 资金
答案:

根据full_prompt例子的格式,选项应该填在“答案:”后面,不应该另起一行。
因此选择ABCD选项的id时,应该取“A”“B”“C”"D"字符的概率,而不是“_A”,"_B","_C","_D"字符的概率。

@TianwenWei
Copy link
Contributor

我们的实现是正确的。孤立的“A”在BPE中指的是非词首的“A”,例如"helloA"里面的A。词首"A",即"_A"才是选项对应。

@naturesphere
Copy link
Author

我们的实现是正确的。孤立的“A”在BPE中指的是非词首的“A”,例如"helloA"里面的A。词首"A",即"_A"才是选项对应。

prompt给的例子里,例如“答案:C”里,冒号和C之间没有空格,是直接连着的。从构造prompt的代码中能看到:

def format_example(line, subject, include_answer=True):
    example = f"以下是中国关于{task2desc[subject]}考试的单项选择题,请选出其中的正确答案。\n\n"
    example = example + line["question"]
    for choice in choices:
        example += f'\n{choice}. {line[f"{choice}"]}'

    if include_answer:
        example += "\n答案:" + line["answer"] + "\n\n"
    else:
        example += "\n答案:"
    return example

example += "\n答案:" + line["answer"] + "\n\n" 这里,“答案:”后面直接接选项。
以“答案:A”为例:

tokenizer("答案:A")['input_ids'] = [1, 29871, 40738, 30383, 29909]

A对应的编码是29909。如果在冒号和A之间加入空格:

tokenizer("答案: A")['input_ids']=[1, 29871, 40738, 30383, 319]

此时,A对应的编码是319,即字符'▁A'对应的编码。

@liuyijiang1994
Copy link

我们的实现是正确的。孤立的“A”在BPE中指的是非词首的“A”,例如"helloA"里面的A。词首"A",即"_A"才是选项对应。

prompt给的例子里,例如“答案:C”里,冒号和C之间没有空格,是直接连着的。从构造prompt的代码中能看到:

def format_example(line, subject, include_answer=True):
    example = f"以下是中国关于{task2desc[subject]}考试的单项选择题,请选出其中的正确答案。\n\n"
    example = example + line["question"]
    for choice in choices:
        example += f'\n{choice}. {line[f"{choice}"]}'

    if include_answer:
        example += "\n答案:" + line["answer"] + "\n\n"
    else:
        example += "\n答案:"
    return example

example += "\n答案:" + line["answer"] + "\n\n" 这里,“答案:”后面直接接选项。 以“答案:A”为例:

tokenizer("答案:A")['input_ids'] = [1, 29871, 40738, 30383, 29909]

A对应的编码是29909。如果在冒号和A之间加入空格:

tokenizer("答案: A")['input_ids']=[1, 29871, 40738, 30383, 319]

此时,A对应的编码是319,即字符'▁A'对应的编码。

他们也许是想直接输出句首A作为答案,而不是答案字符串中的A.

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