python - 关于余弦相似度,损失函数和网络如何选择(我有两个方案)
问题描述
对不起,我不知道,我不知道在哪里可以找到解决方案。我正在使用两个网络来构建两个嵌入,我有二进制目标来指示 embeddingA 和 embeddingB 是否“匹配”(1 或 -1)。数据集是这样的:
embA0 embB0 1.0
embA1 embB1 -1.0
embA2 embB2 1.0
...
我希望使用余弦相似度来得到分类结果。但是我在选择损失函数的时候感到困惑,两个生成embeddings的网络是分开训练的,现在我可以想到两个选项如下:
计划一:
构建第3个网络,使用embeddingA和embeddingB作为nn.cosinesimilarity()的输入计算最终结果(应该是[-1,1]中的概率),然后选择二分类损失函数。
(对不起,我不知道该选择哪个损失函数。)
class cos_Similarity(nn.Module):
def __init__(self):
super(cos_Similarity,self).__init__()
cos=nn.CosineSimilarity(dim=2)
embA=generator_A()
embB=generator_B()
def forward(self,a,b):
output_a=embA(a)
output_b=embB(b)
return cos(output_a,output_b)
loss_func=nn.CrossEntropyLoss()
y=cos_Similarity(a,b)
loss=loss_func(y,target)
acc=np.int64(y>0)
方案2: 将两个Embeddings作为输出,然后使用nn.CosineEmbeddingLoss()作为损失函数,当我计算准确率时,我使用nn.Cosinesimilarity()输出结果(概率在[-1,1])。
output_a=embA(a)
output_b=embB(b)
cos=nn.CosineSimilarity(dim=2)
loss_function = torch.nn.CosineEmbeddingLoss()
loss=loss_function(output_a,output_b,target)
acc=cos(output_a,output_b)
我真的需要帮助。我该如何选择?为什么?或者我只能通过实验结果为我做出选择。非常感谢!
###############################添加
def train_func(train_loss_list):
train_data=load_data('train')
trainloader = DataLoader(train_data, batch_size=BATCH_SIZE)
cos_smi=nn.CosineSimilarity(dim=2)
train_loss = 0
for step,(a,b,target) in enumerate(trainloader):
try:
optimizer.zero_grad()
output_a = model_A(a) #generate embA
output_b = model_B(b) #generate embB
acc=cos_smi(output_a,output_b)
loss = loss_fn(output_a,output_b, target.unsqueeze(dim=1))
train_loss += loss.item()
loss.backward()
optimizer.step()
train_loss_list.append(loss)
if step%10==0:
print('train:',step,'step','loss:',loss,'acc',acc)
except Exception as e:
print('train:',step,'step')
print(repr(e))
return train_loss_list,train_loss/len(trainloader)
解决方案
回应评论线程。
目标或管道似乎是:
- 接收两个嵌入向量(例如,A 和 B)。
- 检查这两个向量是否“相似”(使用余弦相似度)。
- 如果它们相似,则标签为 1,否则为 -1(我建议将其更改为 0 或 1 而不是 -1 和 1)。
我能想到的有以下几点。如果我误解了什么,请纠正我。免责声明是,我几乎是在不知道任何细节的情况下根据自己的直觉编写代码,因此如果您尝试运行,它可能会充满错误。让我们仍然尝试获得高层次的理解。
模型
import torch
import torch.nn as nn
class Model(nn.Module):
def __init__(self, num_emb, emb_dim): # I'm assuming the embedding matrices are same sizes.
self.embedding1 = nn.Embedding(num_embeddings=num_emb, embedding_dim=emb_dim)
self.embedding2 = nn.Embedding(num_embeddings=num_emb, embedding_dim=emb_dim)
self.cosine = nn.CosineSimilarity()
self.sigmoid = nn.Sigmoid()
def forward(self, a, b):
output1 = self.embedding1(a)
output2 = self.embedding2(b)
similarity = self.cosine(output1, output2)
output = self.sigmoid(similarity)
return output
培训/评估
model = Model(num_emb, emb_dim)
if torch.cuda.is_available():
model = model.to('cuda')
model.train()
criterion = loss_function()
optimizer = some_optimizer()
for epoch in range(num_epochs):
epoch_loss = 0
for batch in train_loader:
optimizer.zero_grad()
a, b, label = batch
if torch.cuda.is_available():
a = a.to('cuda')
b = b.to('cuda')
label = label.to('cuda')
output = model(a, b)
loss = criterion(output, label)
loss.backward()
optimizer.step()
epoch_loss += loss.cpu().item()
print("Epoch %d \t Loss %.6f" % epoch, epoch_loss)
我省略了一些细节(例如,超参数值、损失函数和优化器等)。这个整体过程是否类似于您正在寻找的 OP?
推荐阅读
- javascript - 脚本问题:表单提交但不重定向
- google-cloud-platform - Gcloud 无法通过 cli 分离磁盘 - 区域错误中不存在磁盘
- python - 训练自定义 SpaCy NER 模型会产生训练错误
- tooltip - Altair:使用 x 轴值作为工具提示标题
- javascript - 这被认为是一种稳定的排序方法吗?
- c++ - 进程以退出代码 -1073741819 (0xC0000005) C++ clion 完成
- xamarin.forms - 避免在 Xamarin iOS 中更改图标的通知对话框
- javascript - 如何在 Shopify 结帐页面中显示特定网关
- entity-framework - EF Core 复合类到同一张表中
- react-native - 如何从 React Native 中的功能组件正确调用函数?