SimCSE-Chinese-Pytorch
SimCSE-Chinese-Pytorch copied to clipboard
loss问题
请教下,我看苏剑林的代码,loss在计算相似度前其实还有个归一化,你这里没有?是不是需要加上?应该能有一些提升的
cos_sim 那一步函数里面有做归一化 , 不用自己再做一次
cos_sim 那一步函数里面有做归一化 , 不用自己再做一次
我算了下,确实是的。不过你这个有监督loss是有问题的,可以看看这个 loss https://www.jianshu.com/p/d73e499ec859 。这个loss我跟苏剑林的git的loss比了下,结果是相同的
# 苏剑林
import numpy as np
import scipy.stats
from bert4keras.backend import keras, K, search_layer
import tensorflow as tf
def su_sup_loss(y_true, y_pred):
"""https://www.icode9.com/content-4-1357759.html"""
row = K.arange(0, K.shape(y_pred)[0], 3)
col = K.arange(K.shape(y_pred)[0])
col = K.squeeze(tf.where(K.not_equal(col % 3, 0)), axis=1)
y_true = K.arange(0, K.shape(col)[0], 2)
y_pred = K.l2_normalize(y_pred, axis=1)
similarities = K.dot(y_pred, K.transpose(y_pred)) # tf.matmul(y_pred, y_pred, adjoint_b = True)
similarities = tf.gather(similarities, row, axis=0)
similarities = tf.gather(similarities, col, axis=1)
similarities = similarities * 20
loss = K.sparse_categorical_crossentropy(y_true, similarities, from_logits=True)
# loss = K.categorical_crossentropy(y_true, similarities, from_logits=True)
return tf.reduce_mean(loss)
a = np.arange(24).reshape(6,4)*1.0
b = K.constant(a)
K.eval(su_sup_loss(1, b))
# 1.0113058
###############################
# torch版本loss
def compute_sup_loss(y_pred,lamda=0.05):
y_pred = F.normalize(y_pred, p=2, dim=1)
row = torch.arange(0,y_pred.shape[0],3,device='cpu') # [0,3]
col = torch.arange(y_pred.shape[0], device='cpu') # [0,1,2,3,4,5]
#这里[(0,1,2),(3,4,5)]代表二组样本,
#其中0,1是相似句子,0,2是不相似的句子
#其中3,4是相似句子,3,5是不相似的句子
col = torch.where(col % 3 != 0)[0]#.cuda() # [1,2,4,5]
y_true = torch.arange(0,len(col),2,device='cpu') # 生成真实的label = [0,2]
#print(y_true)
#计算各句子之间的相似度,形成下方similarities 矩阵,其中xij 表示第i句子和第j个句子的相似度
#[[ x00,x01,x02,x03,x04 ,x05 ]
# [ x10,x11,x12,x13,x14 ,x15 ]
# [ x20,x21,x22,x23,x24 ,x25 ]
# [ x30,x31,x32,x33,x34 ,x35 ]
# [ x40,x41,x42,x43,x44 ,x45 ]
# [ x50,x51,x52,x53,x54 ,x55 ]]
similarities = F.cosine_similarity(y_pred.unsqueeze(1), y_pred.unsqueeze(0), dim=2)
#这里将similarities 做切片处理,形成下方矩阵
#[[ x01,x02,x04 ,x05 ]
# [x31,x32,x34 ,x35 ]]
similarities = torch.index_select(similarities,0,row)
similarities = torch.index_select(similarities,1,col)
#print(similarities)
#论文中除以 temperature 超参
similarities = similarities / lamda
#下面这一行计算的是相似矩阵每一行和y_true = [0, 2] 的交叉熵损失
#[[ x01,x02,x04 ,x05 ] label = 0 含义:第0个句子应该和第1个句子的相似度最高, 即x01越接近1越好
# [x31,x32,x34 ,x35 ]] label = 2 含义:第3个句子应该和第4个句子的相似度最高 即x34越接近1越好
#这行代码就是simsce的核心部分,和正例句子向量相似度应该越大
#越好,和负例句子之间向量的相似度越小越好
loss = F.cross_entropy(similarities,y_true)
return torch.mean(loss)
y_pred = torch.arange(24).reshape(6,4)*1.0
sup_loss = compute_sup_loss(y_pred)
sup_loss
# tensor(1.0113)