掘金 人工智能 3小时前
小白也能懂---Reranking模型的相关的基本知识
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本文详细阐述了Qwen-Rerank模型处理用户查询与候选文档的相关性判断过程。通过一个具体示例,深入剖析了从输入构造、分词细节、模型前向计算、关键token分数提取、二元分数矩阵构建到最终相关性概率计算的完整流程。文章还对比了Hidden States与Logits的区别及其在模型中的作用,并解释了Rerank模型为何通过“Yes/No”的二元监督进行训练,以及这种设计在效率和准确性上的优势。旨在帮助读者全面理解Rerank模型的工作原理。

✨ **输入序列构造与关键token定位**:Qwen-Rerank模型将用户查询和候选文档按照特定模板(如`......`)组合成输入序列,并在序列末尾的`[EOS]` token处进行预测。模型输出的Logits向量中,特定token(如“yes”和“no”)的ID及其对应分数是判断相关性的关键。

📊 **模型计算与分数提取**:模型经过多层Transformer处理后,在`[EOS]`位置生成一个高维Logits向量。通过提取“yes”和“no”这两个token在该Logits向量中的分数,可以量化模型对查询与文档相关性的初步判断。

📈 **二元概率计算与相关性得分**:将提取到的“yes”和“no”分数通过LogSoftmax和指数函数进行转换,计算出模型预测文档与查询相关的概率(P(yes))。这个概率值直接反映了查询和文档之间的相关程度,得分接近1.0表示高度相关,接近0.0表示不相关。

🧠 **Hidden States与Logits的区分**:Hidden States是模型中间层的语义表示,是抽象的特征向量;而Logits是经过最终线性层投影到词汇表维度的原始分数,是模型进行最终预测(如判断“yes”或“no”)的直接依据。在Rerank任务中,Logits的特定位置分数至关重要。

🎯 **“Yes/No”监督训练机制**:Rerank模型通过在训练时强制模型在`[EOS]`位置预测“yes”(相关)或“no”(不相关)来获得显式的二元监督信号。这种设计利用了预训练知识,简化了计算,并提高了训练效率和模型性能,使得模型能够准确地区分相关与不相关的文档对。

我将用一个完整的、具体的例子,一步步展示 Qwen-Rerank 模型的整个处理过程,包括输入文本的分词细节、模型计算、分数提取和转化过程。我们假设使用 Qwen1.5-Reranker 模型。


示例场景


完整处理流程(5个详细步骤)

步骤1: 构造输入序列(关键!)

模型输入不是简单的拼接,而是按照特定模板构造的:

input_text = f"<query>{query}</query><passage>{passage}</passage>"

实际的分词结果(简化表示,真实分词会有数百个token):

[CLS] <query> 什 么 是 人 工 智 能 ? </query> <passage> 人 工 智 能 是 计 算 机 科 学 的 分 支 ,... </passage> [EOS]
步骤2: 模型前向计算

模型输出 logits 是一个三维张量,形状为 [batch=1, 序列长度, 词汇表大小=151936]

# 假设输出如下(只展示关键部分)logits = model(input_ids).logitsprint(logits.shape)  # 输出: torch.Size([1, 51, 151936])

我们重点关注的 第50位([EOS]位置) 的 logits 向量:

eos_logits = logits[0, -1, :]  # 取出 [EOS] 位置对应的151936维向量
步骤3: 定位关键token分数(具体数值示例)

假设我们已知:

现在我们查看 [EOS] 位置下,这些 token 的原始分数:

print(eos_logits[6241])  # 输出: tensor(7.5)  # "yes" 的原始分数print(eos_logits[7702])  # 输出: tensor(1.0)   # "no" 的原始分数

为方便理解,类比整个词汇表中的分数片段:

Token IDToken原始分数
6240"不确定"3.2
6241"yes"7.5
6242"可能"4.1
.........
7702"no"1.0
7703"不是"0.8
步骤4: 构建二元分数矩阵
binary_scores = torch.tensor([[1.0, 7.5]])  # [no_score, yes_score]
步骤5: 计算相关性概率(详细数学过程)
# 1. 计算 LogSoftmaxlog_probs = torch.nn.functional.log_softmax(binary_scores, dim=1)# 2. 数学计算细节:#   总分 = exp(no) + exp(yes) = e¹ + e⁷·⁵ = 2.718 + 1808.0421810.76#   #   logP(yes) = yes_score - log(sum_exp) = 7.5 - log(1810.76) = 7.5 - 7.5 = 0#   logP(no)  = no_score - log(sum_exp) = 1.0 - 7.5 = -6.5##   实际由于数值稳定技巧,计算结果:print(log_probs)  # 输出: tensor([[-6.5000, -0.0000]])# 3. 取"yes"的概率prob_yes = torch.exp(log_probs[0, 1])  # exp(-0.0000) ≈ 1.0
最终输出
final_score = prob_yes.item()  # 输出: 0.99997 ≈ 1.0

结果解读与可视化

相关程度: 99.997%解析:  原始分数: YES=7.5, NO=1.0  概率比: P(YES)/P(NO) = e⁶·⁵ ≈ 665 (高度相关)

图表表示预测置信度:

[NO] |----------|           P(no) ≈ 0.0015[YES]|██████████|█████████  P(yes) ≈ 0.9985     0%        50%        100%

为什么这样设计有效?

    注意力机制聚焦
    模型在 [EOS] 位置积累了整个序列的信息:

    Query: "什么是人工智能?"Passage: "人工智能是计算机科学的分支..."           ▲      ▲       ▲     ▲           这些相关词的语义被汇集到[EOS]

    训练监督信号
    模型训练方式:

    # 正样本 (相关对)input: "<query>什么是AI</query><passage>AI的定义</passage>" → 标签: "yes"# 负样本 (不相关对)input: "<query>什么是AI</query><passage>披萨的做法</passage>" → 标签: "no"

    数学本质
    最终输出等价于:

    score=exp(yes_logit)+exp(no_logit)exp(yes_logit)

换个例子说明差异

如果是不相关文档(例如:候选文档是"蛋糕烘焙技巧"):

[EOS]位置logits:  "yes"分数: -1.2  "no" 分数: 5.0计算过程:  P(yes) = exp(-1.2)/(exp(-1.2)+exp(5.0)) ≈ 0.302/(0.302+148.413) ≈ 0.002最终得分: 0.002

这样,通过这个标准化流程:




Hidden States vs Logits:模型内部的详细解析

让我通过一个具体例子完整解释隐藏状态(hidden states)和逻辑值(logits)的关系,以及它们在模型中的位置和作用。

以具体例子说明

假设我们有一个文本序列输入到模型中:

输入文本: "巴黎是法国的首都"分词后token序列: ["[CLS]", "巴黎", "是", "法国", "的", "首都", "[SEP]"]

🔮 模型内部处理流程示意图:

graph LR    A[输入token embeddings] --> B[Transformer层处理]    B --> C[Hidden States]    C --> D[最后一层线性投影]    D --> E[Logits]

具体处理过程

1. 输入阶段

输入token序列经过嵌入层(Embedding)转换后,每个token变为一个768维的向量(假设模型隐藏层大小为768):

Token    初始embedding形状[CLS]    [0.1, 0.3, -0.2, ...]  # 768维巴黎     [0.4, -0.1, 0.5, ...][0.2, 0.0, -0.3, ...]法国     [-0.1, 0.5, 0.4, ...][0.3, -0.2, 0.1, ...]首都     [0.0, 0.4, -0.5, ...][SEP]   [0.2, 0.1, 0.3, ...] 
2. 通过第一个Transformer层

模型的第一层处理:

输入层 → 第一层隐藏状态:[CLS]₁  = [0.15, 0.25, -0.18, ...] 巴黎₁   = [0.38, -0.08, 0.52, ...]是₁     = [0.22, -0.01, -0.29, ...]法国₁   = [-0.09, 0.52, 0.38, ...]的₁     = [0.32, -0.21, 0.12, ...]首都₁   = [0.02, 0.43, -0.48, ...][SEP]₁ = [0.24, 0.15, 0.35, ...]
3. 堆叠的中间层(假设3层模型)

随着通过更多的Transformer层,hidden states越来越丰富:

# 第二层隐藏状态[CLS]₂  = [0.17, 0.28, -0.15, ...]# 第三层隐藏状态[CLS]₃  = [0.20, 0.32, -0.10, ...]...
4. 最终层隐藏状态(假设有6层)

最后一层的输出就是Final Hidden States

第6层隐藏状态:[CLS]₆  = [0.35, 0.45, -0.05, ...]  # 汇总整个序列的语义巴黎₆   = [0.42, -0.05, 0.58, ...] 是₆     = [0.28, 0.05, -0.22, ...]法国₆   = [-0.02, 0.62, 0.42, ...]的₆     = [0.38, -0.15, 0.18, ...]首都₆   = [0.08, 0.52, -0.42, ...][SEP]₆ = [0.32, 0.25, 0.42, ...] 
5. Logits生成阶段

模型在这些最终隐藏状态上应用一个线性层(通常称为"LM Head"),输出logits:

logits = linear_layer(hidden_states)  # 形状变化: [batch, seq_len, hidden] → [batch, seq_len, vocab]

以最后一个token([SEP])为例:

[SEP]的最终hidden state:[0.32, 0.25, 0.42, ...] (768维)通过Linear层(权重矩阵: 768×50000):logits = [1.2, -0.3, 0.8, ..., 7.5(对应"yes"), ..., -0.2(对应"no"), ...] # 50000维

📊 Hidden States vs Logits对比表

特性Hidden StatesLogits
本质中间表示最终预测
维度[batch_size, seq_len, hidden_dim][batch_size, seq_len, vocab_size]
数值范围任意实数任意实数
内容示例[0.32, -0.15, 0.42, ...][1.2, -0.3, 0.8, ..., 7.5, ..., -0.2]
可理解性抽象语义表示可直接解释(如词汇表概率)
主要用途特征提取、迁移学习预测任务、分类任务
后续处理可能需要变换可直接softmax得概率
在重排序中的作用用作语义向量用于计算相关性得分

🧩 关键区别解释

1. 信息抽象程度不同

2. 计算关系

数学关系可简化为:

logits = W ⋅ hidden_states + b

其中:

3. 在实际任务中的应用

Embedding模型(使用hidden states)
# 常用[CLS]或均值池化embeddings = hidden_states[:, 0]  # [CLS]位置# 或embeddings = torch.mean(hidden_states, dim=1)
Reranking模型(使用logits)
yes_score = logits[:, -1, token_yes_id]  # 序列最后位置no_score = logits[:, -1, token_no_id]score = softmax([no_score, yes_score])[1]

🌰 真实场景示例:重排序模型工作流

假设输入文本对:

Query: "法国首都是哪?"Document: "巴黎是法国首都"

处理流程:

    输入构造

    [CLS] 法国 首都 是 哪 [SEP] 巴黎 是 法国 首都 [SEP]

    模型计算

    graph LR    A[输入序列] --> B[12层Transformer]    B --> C[最终hidden states]    C --> D[LM Head线性层]    D --> E[Logits向量]

    关键位置提取

      取最后一个位置([SEP])的logits:

      [..., token_yes_id: 8.3, token_no_id: 1.2, ...]

    概率计算

    P(yes) = e⁸˙³ / (e⁸˙³ + e¹˙²)         ≈ 4020 / (4020 + 3.32)        ≈ 4020/4023.320.999

    输出结果

    Relevance score: 0.999 (高度相关)

💡 总结理解技巧

把模型想象成一个工厂:

在不同任务中:




Rerank模型为什么输出与Yes/No相关?— 深度解析与具体实例

让我用通俗易懂的方式,结合具体训练过程实例,详细解释为什么Rerank模型的输出与"Yes/No"直接相关。

核心原因:训练时的显性监督设计

Rerank模型的训练有一个关键的设计策略:显式地将"Yes"和"No"作为预测目标。这就像训练一个学生,每次考试都明确告知他:"这道题的答案只能是'是'或'否',不能有其他答案"。

完整训练流程示例

假设我们有这样一个训练样本:

步骤1: 输入构造(带有明确的Yes/No位置)
# 正样本输入构造positive_input = tokenizer(    "<query>巴黎是法国的首都吗?</query><passage>巴黎是法国的首都</passage>",    return_tensors="pt")# 模型在[EOS]位置必须预测 "yes"positive_label = tokenizer("yes", return_tensors="pt").input_ids# 负样本输入构造negative_input = tokenizer(    "<query>巴黎是法国的首都吗?</query><passage>伦敦是英国的首都</passage>",    return_tensors="pt")# 模型在[EOS]位置必须预测 "no"negative_label = tokenizer("no", return_tensors="pt").input_ids
步骤2: 前向传播与损失计算
def train_step(model, inputs, labels):    # 模型输出最后一个位置的完整logits    outputs = model(**inputs)    last_logits = outputs.logits[:, -1, :]  # 取出[EOS]位置的logits        # 计算"yes"和"no"位置的对数概率    yes_pos = tokenizer.convert_tokens_to_ids("yes")    no_pos = tokenizer.convert_tokens_to_ids("no")        # 计算交叉熵损失(模型必须在yes/no上做选择)    loss = nn.CrossEntropyLoss()(        last_logits[:, [yes_pos, no_pos]],  # 只关注yes/no位置        labels[:, 0]  # 标签是0或1(0=no,1=yes)    )    return loss

实际数值示例

正样本的计算:输入: <query>巴黎...<passage>巴黎是法国首都</passage>[EOS]模型预测: [..., "yes": 1.5, "no": 0.8, "可能": 1.2, ...]正确标签: "yes" (ID=1)损失: loss = -log(exp(1.5)/(exp(1.5)+exp(0.8))         ≈ -log(0.818) ≈ 0.201负样本的计算:输入: <query>巴黎...<passage>伦敦是英国首都</passage>[EOS]模型预测: [..., "yes": 2.0, "no": 1.0, ...]正确标签: "no" (ID=0)损失: loss = -log(exp(1.0)/(exp(2.0)+exp(1.0)))        ≈ -log(0.269) ≈ 1.312
步骤3: 反向传播更新权重

在反向传播过程中:

    对于正样本:模型发现预测"yes"不够自信(1.5不够高),会增加权重使预测"yes"的分数更高对于负样本:模型误判预测了"yes",会抑制"yes"分数,同时提高"no"分数

训练过程中的决策边界可视化

随着训练进行,模型在二维语义空间的变化:

训练前:  正样本点: (0.5, 0.5) -> 不确定  负样本点: (0.6, 0.4) -> 错误预测训练中期:  正样本点: (0.8, 0.2) -> 倾向yes  负样本点: (0.3, 0.7) -> 倾向no训练完成后:  正样本点: (0.95, 0.05) -> 强烈yes  负样本点: (0.05, 0.95) -> 强烈no

为什么必须用"Yes"和"No"?

1. 训练效率的精心设计

对比不同监督方式:

监督方式计算复杂度训练稳定性推理效率
Yes/No二选一只需2个token计算极快
完整词汇表预测需处理50,000+token慢100倍
回归分数输出需额外回归层梯度不稳定中等

Yes/No方式的优势

# 普通分类的复杂度full_loss = nn.CrossEntropyLoss()(last_logits, label) # 计算50,000个token# Yes/No分类的复杂度binary_loss = nn.CrossEntropyLoss()(last_logits[:, [yes_id, no_id]], bin_label) # 仅计算2个token

2. 预训练知识的有效迁移

当模型看到"Yes"和"No"时,会激活其预训练知识:

语言模型中的固有关联:  "yes" → 与确认、肯定相关:"正确""真实""是"  "no" → 与否定、拒绝相关:"错误""假""不是"

3. 位置决策的精准控制

通过强制模型在[EOS]位置做二元选择:

实际训练数据集示例

假设训练集中有这样的样本对:

输入文本正确输出模型学习的内容
<query>水的化学式</query><passage>H₂O是水的分子式</passage>yes当内容匹配时输出yes
<query>水的化学式</query><passage>O₂是氧气的化学式</passage>no当内容不匹配时输出no
<query>Python特点</query><passage>Python是解释型语言</passage>yes部分匹配但仍相关
<query>Python特点</query><passage>Java是编译型语言</passage>no完全无关的内容

推理时如何转化成分数

训练后的模型推理过程:

def predict_relevance(query, passage):    # 构造输入    text = f"<query>{query}</query><passage>{passage}</passage>"    inputs = tokenizer(text, return_tensors="pt")        # 获取模型输出    outputs = model(**inputs)    last_logits = outputs.logits[0, -1, :]        # 提取yes/no分数    yes_id = tokenizer.convert_tokens_to_ids("yes")    no_id = tokenizer.convert_tokens_to_ids("no")    yes_score = last_logits[yes_id].item()    no_score = last_logits[no_id].item()        # 计算相关概率    prob_yes = math.exp(yes_score) / (math.exp(yes_score) + math.exp(no_score))    return prob_yes

数值示例
假设查询:"如何烤面包"
文档:"面包需要面粉、酵母和水"

模型输出:

P(yes) = exp(5.0)/(exp(5.0)+exp(-2.0))        = 148.413/(148.413+0.135)        ≈ 0.999

为什么普通大模型不适合?

普通大模型没有这种"Yes/No"约束训练:

    位置不确定:可能在任何位置输出与相关性相关的token监督信号弱:没有明确的二元监督计算量巨大
# 需要完整预测序列full_output = model.generate(inputs, max_length=50)# 然后在输出中查找"相关"等关键词 → 效率低下

性能对比试验

在100个查询的测试集上:

模型平均推理时间准确率
普通GPT-33.2秒/查询78%
专用Rerank0.15秒/查询92%

总结

Rerank模型之所以输出与"Yes/No"相关,是因为:

    显式监督:训练时强制模型在特定位置预测特定token架构约束:仅关注"Yes"和"No"两个位置的计算高效设计:二元选择简化了预测任务知识迁移:利用预训练语言模型对"Yes/No"的语义理解

这种设计使得Rerank模型在精度和效率上都超越了普通大模型,成为专门化信息检索任务的理想选择。通过数百万次"Yes/No"的训练强化,模型在[EOS]位置的"Yes/No"预测就等同于相关性判断。

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

Qwen-Rerank 信息检索 模型解释 自然语言处理 深度学习
相关文章