介绍
这篇文章的思路来源自paddleNLP–>语义检索–>recall–>paddleNLP In-batch negative,它提供了一种非常有特点的数据增强,帮助提升模型训练效果。
任务介绍
它是一个语义检索召回阶段任务,输入两个句子s1和s2,判断这两个句子的相似度。
做法
0. 数据格式
1 | 我手机丢了,我想换个手机 我想买个新手机,求推荐 |
注意,每一行的两句话都是相似的。
1. 模型结构
1 | class SemanticIndex(nn.Module): |
2. loss
假设query_cls_embedding和title_cls_embedding的维度为(32,256)和(32,256),经过forward.cosine_sim后,维度变成了(32,32),这里作者有用到缩放等方式来加快模型收敛。
核心来了,label是什么呢?
label就是torch.arange(0, 32)!!
为什么呢,只有对角线上面的俩句子才是相似的,其余都不是相似的!
这个就叫做什么是in batch negative(在一个batch内构造负样本)
3. 推理
3.1 建立知识库索引
比如有一个语料库corpus.txt,这个文件为一整个知识库,决定搜索的范围。
对corpus.txt建立语义索引,通过self.get_pooled_embedding
方法跑出index,然后保存到类似faiss,milvus,hnswlib类ann库中。
build_index完后,剩下就是检索了。
3.2 召回
这里以hnswlib库进行说明,在支持的计算相似度算法上,选择ip.
Distance | parameter | Equation |
---|---|---|
Squared L2 | ‘l2’ | d = sum((Ai-Bi)^2) |
Inner product | ‘ip’ | d = 1.0 - sum(Ai*Bi) |
Cosine similarity | ‘cosine’ | d = 1.0 - sum(Ai*Bi) / sqrt(sum(Ai*Ai) * sum(Bi*Bi)) |
拿到query embed后,调用hnswlib的knn_query
函数进行计算,最终d = 1 - cosine_sim
。
3.3 评估指标
比如dev.txt如下面这个样子:
第一列为query,第二列为doc
1 | 我喜欢张三 我李四喜欢张三 |
输入query,经过knn_query调整topK大小,比如10,代表选取10个相关集。
如果doc在这10个相关集中,那么recall@10就为1
那同理,如果topK为1,并且doc在这1个结果内,那么recall@1就为1
总结
平时在构造负样本的时候,一般是在生成train和dev数据集的时候,而本文提出了in-batch negative,非常不同的实现角度。
不过这个方法也有局限性,不同的任务,可能未必能使用这种方法来构造负样本,因为一个batch内,sample和sample之间会是相互独立的,没有关系的。
不过本篇文章同时也讲明白了召回的实现思路,给大家进阶之路参考。