netease-youdao / BCEmbedding

Netease Youdao's open-source embedding and reranker models for RAG products.
Apache License 2.0
1.35k stars 90 forks source link

Rerank阈值设置咨询 #15

Open Sunnylee0101 opened 7 months ago

Sunnylee0101 commented 7 months ago

感谢贵团队的工作!

想请教一下,检索完成以后采用排序模型进行Rerank,这个Rerank的值设置为多大比较合适?0.5吗,低于0.5就是不相关,高于0.5就是相关?

shenlei1020 commented 7 months ago

不能这么设置: 1、建议根据你的场景测试数据来定阈值,跑一遍,就能看出来不相关和相关的阈值分界线;

Sunnylee0101 commented 7 months ago

谢谢回复! 因为在检索的过程中,如果我的query和passage是一样的话,余弦相似度的值是1,而在使用排序模型进行Rerank时,Query和Passage一样的时候,这个得到的score的分数每次不一样,也不是1,所有很好奇这是不是用的sigmod损失训练的,如果是sigmoid损失的话,低于0.5就可以认为它是负相关,高于0.5则是正相关了

shenlei1020 commented 7 months ago

是这样的,RerankerModel对query和passage相同的情况,只会得分比较高,但不会是1,这是算法底层原理决定的。 关于阈值,我建议按照自己的场景来定,我们自己用的话,取的阈值是0.35或0.4,仅供参考。

Sunnylee0101 commented 7 months ago

好的 非常感谢!!!很有用的建议!

longshuicui commented 7 months ago

感觉rerank的分数区分度很小 下面这个例子,bge-rerank-base 和 bce-rerank-base-v1的得分,

pairs = [['what is panda?', 'hi'], ['what is panda?', 'The giant panda (Ailuropoda melanoleuca), sometimes called a panda bear or simply panda, is a bear species endemic to China.']] with torch.no_grad(): inputs = bge_tokenizer(pairs, padding=True, truncation=True, return_tensors='pt', max_length=512) for key in inputs: inputs[key]=inputs[key].to("cuda:0") bge_scores = bge_model(**inputs, return_dict=True).logits.view(-1, ).float() print(bge_scores)

inputs = bce_tokenizer(pairs, padding=True, truncation=True, return_tensors='pt', max_length=512)
for key in inputs:
    inputs[key]=inputs[key].to("cuda:0")
bce_scores = bce_model(**inputs, return_dict=True).logits.view(-1, ).float()
print(bce_scores)

未sigmoid结果: tensor([-8.1544, 6.1821], device='cuda:0') tensor([-0.6458, 0.3187], device='cuda:0')

sigmoid结果: tensor([2.8739e-04, 9.9794e-01], device='cuda:0') tensor([0.3439, 0.5790], device='cuda:0')

shenlei1020 commented 6 months ago

感觉rerank的分数区分度很小 下面这个例子,bge-rerank-base 和 bce-rerank-base-v1的得分,

pairs = [['what is panda?', 'hi'], ['what is panda?', 'The giant panda (Ailuropoda melanoleuca), sometimes called a panda bear or simply panda, is a bear species endemic to China.']] with torch.no_grad(): inputs = bge_tokenizer(pairs, padding=True, truncation=True, return_tensors='pt', max_length=512) for key in inputs: inputs[key]=inputs[key].to("cuda:0") bge_scores = bge_model(**inputs, return_dict=True).logits.view(-1, ).float() print(bge_scores)

inputs = bce_tokenizer(pairs, padding=True, truncation=True, return_tensors='pt', max_length=512)
for key in inputs:
    inputs[key]=inputs[key].to("cuda:0")
bce_scores = bce_model(**inputs, return_dict=True).logits.view(-1, ).float()
print(bce_scores)

未sigmoid结果: tensor([-8.1544, 6.1821], device='cuda:0') tensor([-0.6458, 0.3187], device='cuda:0')

sigmoid结果: tensor([2.8739e-04, 9.9794e-01], device='cuda:0') tensor([0.3439, 0.5790], device='cuda:0')

感谢您对bce的关注,是这样的:

1、rerank判断query和passage的语义相关性分数,bce是0~1的,这个例子中0.34和0.58是很合理的。因为一般bce的rerank分数用来过滤低质量的passage,推荐的rerank分数阈值是0.35或0.4,所以这个0.35或0.4是一个门槛,0.58是一个相对比较正的正例对了。

2、bge一般不用sigmoid来获取分数,因为bge模型训练过程中语义相关分数是用softmax得出来的,但是softmax得到的分数是相对分数(相对分数只能用来排序,但用来表征query和passage到底有多么语义相关就不可靠了(具体可以看一下softmax公式);绝对分数用处就比较大了,既可以用来排序,也可以表征query和passage到底有多么相关,可以用来过滤低质量passage)。

3、你举的例子bge rerank+sigmoid分数看着更符合的你预期只是巧合,多试几个例子你就会发现问题(问题根源是bge rerank不应该用sigmoid)。而且你细想,你举的例子,其实bce rerank分数更加科学,因为例子中的正例bge rerank能达到0.998,这个分数高的出奇,你细想就会发现问题(这个分数太硬了,更正的正例分数应该预期是多少呢?bge rerank分数太硬的原因是错用了sigmoid输出分数,应该用softmax)。

相对来说bce rerank负例0.34,正例0.58是更科学的,正负例的rerank分数更加smooth(其实这个smooth就是我们bce rerank精排能力强的一个原因:https://github.com/netease-youdao/BCEmbedding?tab=readme-ov-file#1-multiple-domains-scenarios)。 更多解释,详见bce技术报告:https://zhuanlan.zhihu.com/p/681370855

4、总结一下:bce rerank可以输出绝对的语义相关分数,而且rerank 分数是smooth的,以0.35或0.4为界,可用于过滤低质量passage。

tianBosh commented 5 months ago

感觉 bce reranker 训练阶段先 pointwise 得到绝对语义分,再 listwise 转相对排序分,实现兼顾的思想。但从技术报告来看,似乎更加复杂,如提到的 “其分数的绝对值可表征真实的语义相关程度”。能再详细的解释一下吗 @shenlei1020

tianBosh commented 5 months ago

感觉 bce reranker 训练阶段先 pointwise 得到绝对语义分,再 listwise 转相对排序分,实现兼顾的思想。但从技术报告来看,似乎更加复杂,如提到的 “其分数的绝对值可表征真实的语义相关程度”。能再详细的解释一下吗

感觉rerank的分数区分度很小 下面这个例子,bge-rerank-base 和 bce-rerank-base-v1的得分, pairs = [['what is panda?', 'hi'], ['what is panda?', 'The giant panda (Ailuropoda melanoleuca), sometimes called a panda bear or simply panda, is a bear species endemic to China.']] with torch.no_grad(): inputs = bge_tokenizer(pairs, padding=True, truncation=True, return_tensors='pt', max_length=512) for key in inputs: inputs[key]=inputs[key].to("cuda:0") bge_scores = bge_model(**inputs, return_dict=True).logits.view(-1, ).float() print(bge_scores)

inputs = bce_tokenizer(pairs, padding=True, truncation=True, return_tensors='pt', max_length=512)
for key in inputs:
    inputs[key]=inputs[key].to("cuda:0")
bce_scores = bce_model(**inputs, return_dict=True).logits.view(-1, ).float()
print(bce_scores)

未sigmoid结果: tensor([-8.1544, 6.1821], device='cuda:0') tensor([-0.6458, 0.3187], device='cuda:0') sigmoid结果: tensor([2.8739e-04, 9.9794e-01], device='cuda:0') tensor([0.3439, 0.5790], device='cuda:0')

感谢您对bce的关注,是这样的:

1、rerank判断query和passage的语义相关性分数,bce是0~1的,这个例子中0.34和0.58是很合理的。因为一般bce的rerank分数用来过滤低质量的passage,推荐的rerank分数阈值是0.35或0.4,所以这个0.35或0.4是一个门槛,0.58是一个相对比较正的正例对了。

2、bge一般不用sigmoid来获取分数,因为bge模型训练过程中语义相关分数是用softmax得出来的,但是softmax得到的分数是相对分数(相对分数只能用来排序,但用来表征query和passage到底有多么语义相关就不可靠了(具体可以看一下softmax公式);绝对分数用处就比较大了,既可以用来排序,也可以表征query和passage到底有多么相关,可以用来过滤低质量passage)。

3、你举的例子bge rerank+sigmoid分数看着更符合的你预期只是巧合,多试几个例子你就会发现问题(问题根源是bge rerank不应该用sigmoid)。而且你细想,你举的例子,其实bce rerank分数更加科学,因为例子中的正例bge rerank能达到0.998,这个分数高的出奇,你细想就会发现问题(这个分数太硬了,更正的正例分数应该预期是多少呢?bge rerank分数太硬的原因是错用了sigmoid输出分数,应该用softmax)。

相对来说bce rerank负例0.34,正例0.58是更科学的,正负例的rerank分数更加smooth(其实这个smooth就是我们bce rerank精排能力强的一个原因:https://github.com/netease-youdao/BCEmbedding?tab=readme-ov-file#1-multiple-domains-scenarios)。 更多解释,详见bce技术报告:https://zhuanlan.zhihu.com/p/681370855

4、总结一下:bce rerank可以输出绝对的语义相关分数,而且rerank 分数是smooth的,以0.35或0.4为界,可用于过滤低质量passage。

可能有 《Joint Optimization of Ranking and Calibration with Contextualized Hybrid Model》 这篇论文的思想在里面,能大概捋一下吗

sevenandseven commented 3 months ago

感觉rerank的分数区分度很小 下面这个例子,bge-rerank-base 和 bce-rerank-base-v1的得分, pairs = [['what is panda?', 'hi'], ['what is panda?', 'The giant panda (Ailuropoda melanoleuca), sometimes called a panda bear or simply panda, is a bear species endemic to China.']] with torch.no_grad(): inputs = bge_tokenizer(pairs, padding=True, truncation=True, return_tensors='pt', max_length=512) for key in inputs: inputs[key]=inputs[key].to("cuda:0") bge_scores = bge_model(**inputs, return_dict=True).logits.view(-1, ).float() print(bge_scores)

inputs = bce_tokenizer(pairs, padding=True, truncation=True, return_tensors='pt', max_length=512)
for key in inputs:
    inputs[key]=inputs[key].to("cuda:0")
bce_scores = bce_model(**inputs, return_dict=True).logits.view(-1, ).float()
print(bce_scores)

未sigmoid结果: tensor([-8.1544, 6.1821], device='cuda:0') tensor([-0.6458, 0.3187], device='cuda:0') sigmoid结果: tensor([2.8739e-04, 9.9794e-01], device='cuda:0') tensor([0.3439, 0.5790], device='cuda:0')

感谢您对bce的关注,是这样的:

1、rerank判断query和passage的语义相关性分数,bce是0~1的,这个例子中0.34和0.58是很合理的。因为一般bce的rerank分数用来过滤低质量的passage,推荐的rerank分数阈值是0.35或0.4,所以这个0.35或0.4是一个门槛,0.58是一个相对比较正的正例对了。

2、bge一般不用sigmoid来获取分数,因为bge模型训练过程中语义相关分数是用softmax得出来的,但是softmax得到的分数是相对分数(相对分数只能用来排序,但用来表征query和passage到底有多么语义相关就不可靠了(具体可以看一下softmax公式);绝对分数用处就比较大了,既可以用来排序,也可以表征query和passage到底有多么相关,可以用来过滤低质量passage)。

3、你举的例子bge rerank+sigmoid分数看着更符合的你预期只是巧合,多试几个例子你就会发现问题(问题根源是bge rerank不应该用sigmoid)。而且你细想,你举的例子,其实bce rerank分数更加科学,因为例子中的正例bge rerank能达到0.998,这个分数高的出奇,你细想就会发现问题(这个分数太硬了,更正的正例分数应该预期是多少呢?bge rerank分数太硬的原因是错用了sigmoid输出分数,应该用softmax)。

相对来说bce rerank负例0.34,正例0.58是更科学的,正负例的rerank分数更加smooth(其实这个smooth就是我们bce rerank精排能力强的一个原因:https://github.com/netease-youdao/BCEmbedding?tab=readme-ov-file#1-multiple-domains-scenarios)。 更多解释,详见bce技术报告:https://zhuanlan.zhihu.com/p/681370855

4、总结一下:bce rerank可以输出绝对的语义相关分数,而且rerank 分数是smooth的,以0.35或0.4为界,可用于过滤低质量passage。

你好,我通过以下方式计算出来的分数是: for key in inputs: inputs[key]=inputs[key] scores = model(**inputs, return_dict=True).logits.view(-1, ).float() tensor([ 2.9957, -10.7941, -10.8128, -10.8182, -10.8041, -10.4744, -10.8346, -10.7246, -10.6901, -10.8047, -10.8207, -10.8142, -10.8110, -10.7981, -10.8313, -10.4111, -10.8006, -9.8900, -10.8348, -8.9105, -10.8347, -10.7687, -10.8125, -10.6540, -10.8346, -10.2274, -10.7834, -10.4933, -10.8300, -10.8356, -10.8261], grad_fn=)

请问是需要对他进行softmax处理吗?应该怎么处理?

yushengliao commented 2 months ago

虽然bce评分标准可能更科学。 但是他与bge的区别太大。 不利于迁移和模型切换。

从bge或者其他模型切换到bce需要重新设置阈值。而且某些应用允许用户自定义设置rerank阈值

另外,bge的文档里提到重要的是分数的相对顺序,而不是绝对值。

goldeneave commented 1 month ago

感觉rerank的分数区分度很小 下面这个例子,bge-rerank-base 和 bce-rerank-base-v1的得分,

pairs = [['what is panda?', 'hi'], ['what is panda?', 'The giant panda (Ailuropoda melanoleuca), sometimes called a panda bear or simply panda, is a bear species endemic to China.']] with torch.no_grad(): inputs = bge_tokenizer(pairs, padding=True, truncation=True, return_tensors='pt', max_length=512) for key in inputs: inputs[key]=inputs[key].to("cuda:0") bge_scores = bge_model(**inputs, return_dict=True).logits.view(-1, ).float() print(bge_scores)

inputs = bce_tokenizer(pairs, padding=True, truncation=True, return_tensors='pt', max_length=512)
for key in inputs:
    inputs[key]=inputs[key].to("cuda:0")
bce_scores = bce_model(**inputs, return_dict=True).logits.view(-1, ).float()
print(bce_scores)

未sigmoid结果: tensor([-8.1544, 6.1821], device='cuda:0') tensor([-0.6458, 0.3187], device='cuda:0')

sigmoid结果: tensor([2.8739e-04, 9.9794e-01], device='cuda:0') tensor([0.3439, 0.5790], device='cuda:0')

不好意思,想请教一下,我最近也在用reranker模型做文本重排,原来使用的是xinference下的bge-reranker,得到的分数都是处于0 1之间,但因为计算效率不高,现在改从huggingface下载模型来做重排,但这样得到的分数就出现了负数,想请教一下您的sigmoid步骤在哪里加入的,是在向量计算过程中的吗,希望您能解答

longshuicui commented 1 month ago

感觉rerank的分数区分度很小 下面这个例子,bge-rerank-base 和 bce-rerank-base-v1的得分, pairs = [['what is panda?', 'hi'], ['what is panda?', 'The giant panda (Ailuropoda melanoleuca), sometimes called a panda bear or simply panda, is a bear species endemic to China.']] with torch.no_grad(): inputs = bge_tokenizer(pairs, padding=True, truncation=True, return_tensors='pt', max_length=512) for key in inputs: inputs[key]=inputs[key].to("cuda:0") bge_scores = bge_model(**inputs, return_dict=True).logits.view(-1, ).float() print(bge_scores)

inputs = bce_tokenizer(pairs, padding=True, truncation=True, return_tensors='pt', max_length=512)
for key in inputs:
    inputs[key]=inputs[key].to("cuda:0")
bce_scores = bce_model(**inputs, return_dict=True).logits.view(-1, ).float()
print(bce_scores)

未sigmoid结果: tensor([-8.1544, 6.1821], device='cuda:0') tensor([-0.6458, 0.3187], device='cuda:0') sigmoid结果: tensor([2.8739e-04, 9.9794e-01], device='cuda:0') tensor([0.3439, 0.5790], device='cuda:0')

不好意思,想请教一下,我最近也在用reranker模型做文本重排,原来使用的是xinference下的bge-reranker,得到的分数都是处于0 1之间,但因为计算效率不高,现在改从huggingface下载模型来做重排,但这样得到的分数就出现了负数,想请教一下您的sigmoid步骤在哪里加入的,是在向量计算过程中的吗,希望您能解答

对结果直接sigmoid,比如hf模型结果为 output = tensor([-8.1544, 6.1821], device='cuda:0'),sigmoid(output) = tensor([2.8739e-04, 9.9794e-01], device='cuda:0')

goldeneave commented 1 month ago

感觉rerank的分数区分度很小 下面这个例子,bge-rerank-base 和 bce-rerank-base-v1的得分, pairs = [['what is panda?', 'hi'], ['what is panda?', 'The giant panda (Ailuropoda melanoleuca), sometimes called a panda bear or simply panda, is a bear species endemic to China.']] with torch.no_grad(): inputs = bge_tokenizer(pairs, padding=True, truncation=True, return_tensors='pt', max_length=512) for key in inputs: inputs[key]=inputs[key].to("cuda:0") bge_scores = bge_model(**inputs, return_dict=True).logits.view(-1, ).float() print(bge_scores)

inputs = bce_tokenizer(pairs, padding=True, truncation=True, return_tensors='pt', max_length=512)
for key in inputs:
    inputs[key]=inputs[key].to("cuda:0")
bce_scores = bce_model(**inputs, return_dict=True).logits.view(-1, ).float()
print(bce_scores)

未sigmoid结果: tensor([-8.1544, 6.1821], device='cuda:0') tensor([-0.6458, 0.3187], device='cuda:0') sigmoid结果: tensor([2.8739e-04, 9.9794e-01], device='cuda:0') tensor([0.3439, 0.5790], device='cuda:0')

不好意思,想请教一下,我最近也在用reranker模型做文本重排,原来使用的是xinference下的bge-reranker,得到的分数都是处于0 1之间,但因为计算效率不高,现在改从huggingface下载模型来做重排,但这样得到的分数就出现了负数,想请教一下您的sigmoid步骤在哪里加入的,是在向量计算过程中的吗,希望您能解答

对结果直接sigmoid,比如hf模型结果为 output = tensor([-8.1544, 6.1821], device='cuda:0'),sigmoid(output) = tensor([2.8739e-04, 9.9794e-01], device='cuda:0')

了解了 十分感谢!