首先还是和 SimCSE 一样,一个 case 两次 dropout,然后最小化自身两次 dropout 的距离,并推远与其它样本的距离;即,SimCSE 原 loss 全部保留。 剩下就是怎么找出来困难样本。 1. 假设 batch 为 32,我们需要找出第一句话的困难样本,因为是无监督模型,除了第一句话自身,其余所有 case 都是负样本,那么模型输出特征向量和第一句话越相似的,其就越可能是第一句话的困难样本是吧?我们首先定义一个 k,在每个 batch 中找到每句话输出特征向量最近的 k 句话,后文称为这句话的 k 领域,后面就用这 k 句话创建第一句话的虚拟困难样本。 2. 假设第一句话经过模型输出的特征向量是 e,随便搞一个高斯白噪声 α,加上去,得到一个新的特征向量 e+α,理论上来说,这个新的特征向量和第一句话的意思应该还是相近的,因为是高斯白噪声,其不会对原始向量数据分布产生太大影响,这个过程大概可以模拟成这样:
e = e + np.random.standard_normal(y.shape) * 0.01 如果是给一张图片加上高斯白噪声,基本是看不出什么变化的。仔细看一下这个高斯白噪声的代码,好好想想,理论上按照这个公式,高斯白噪声一定不应该对原句的语义产生太大影响。 当然,实际上我们不是随便乱加一个高斯白噪声,我们期待我们有很多的高斯白噪声,然后再其中选取一个最优的高斯白噪声,可以使得第一句话加上这个噪声以后,即 e+α 和原来的特征向量 e,最远,但是第一句话 k 领域内的所有负样本加上这个噪声 α 后都和原句 e 更靠近了,这样的一个高斯白噪声可谓是坏事干尽了,迷惑性贼大! 所以当原句 e 加上这个最优的噪声 α,就得到了一个很强的困难样本!