SimCSE-Chinese-Pytorch icon indicating copy to clipboard operation
SimCSE-Chinese-Pytorch copied to clipboard

loss问题

Open shexuan opened this issue 8 months ago • 2 comments

请教下,我看苏剑林的代码,loss在计算相似度前其实还有个归一化,你这里没有?是不是需要加上?应该能有一些提升的

shexuan avatar Oct 16 '23 12:10 shexuan

cos_sim 那一步函数里面有做归一化 , 不用自己再做一次

vdogmcgee avatar Oct 16 '23 12:10 vdogmcgee

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)

shexuan avatar Oct 17 '23 07:10 shexuan