如何确定卷积神经网络中三元组损失的准确性

How to determine accuracy with triplet loss in a convolutional neural network

一个三重网络(受"Siamese network"启发)由同一个前馈网络(具有共享参数)的3个实例组成。当输入 3 个样本时,网络输出 2 个中间值——其两个输入的嵌入表示之间的 L2(欧几里得)距离 第三个代表

我正在使用成对的三张图像来为网络提供数据(x = 锚图像,标准图像,x+ = 正图像, 包含与 x 相同对象的图像 - 实际上,x+ 与 class 与 x 相同,而 x- = 负像 , 图像 class 不同于 x.

我正在使用 here.

中描述的三元组损失成本函数

如何确定网络的准确性?

我假设您从事的是图像检索或类似任务。

你应该首先随机生成一些三元组,或者使用一些困难(半困难)的负面挖掘方法。然后你将你的三元组分成训练集和验证集。

如果您这样做,那么您可以将验证准确度定义为三元组数量的比例,其中锚点和正例之间的特征距离小于验证三元组中锚点和负例之间的特征距离。可以看到an example here是用PyTorch写的

作为另一种方式,您可以直接根据最终测试指标进行衡量。例如,对于图像检索,通常我们使用 mean average precision 来衡量模型在测试集上的性能。如果你使用这个指标,你应该首先在你的验证集上定义一些查询和它们对应的地面实况图像。

以上两个指标都可以。选择您认为适合您的情况。

所以我正在执行一个类似的任务,即使用 Triplet loss 进行分类。以下是我如何将新颖的损失方法与分类器一起使用。 首先,使用 N 个时期的标准三元组损失函数训练您的模型。一旦确定模型(我们将其称为嵌入生成器)已经过训练,请保存权重,因为我们将在前面使用这些权重。 假设您的嵌入生成器定义为:

class EmbeddingNetwork(nn.Module):
def __init__(self):
    super(EmbeddingNetwork, self).__init__()
    self.conv1 = nn.Sequential(
        nn.Conv2d(1, 64, (7,7), stride=(2,2), padding=(3,3)),
        nn.BatchNorm2d(64),
        nn.LeakyReLU(0.001),
        nn.MaxPool2d((3, 3), 2, padding=(1,1))
    )
    self.conv2 = nn.Sequential(
        nn.Conv2d(64,64,(1,1), stride=(1,1)),
        nn.BatchNorm2d(64),
        nn.LeakyReLU(0.001),
        nn.Conv2d(64,192, (3,3), stride=(1,1), padding=(1,1)),
        nn.BatchNorm2d(192),
        nn.LeakyReLU(0.001),
        nn.MaxPool2d((3,3),2, padding=(1,1))
    )
    self.fullyConnected = nn.Sequential(
        nn.Linear(7*7*256,32*128),
        nn.BatchNorm1d(32*128),
        nn.LeakyReLU(0.001),
        nn.Linear(32*128,128)
    )
def forward(self,x):
  x = self.conv1(x)
  x = self.conv2(x)
  x = self.fullyConnected(x)
  return torch.nn.functional.normalize(x, p=2, dim=-1)

现在我们将使用这个嵌入生成器创建另一个分类器,将我们之前保存的权重拟合到这部分网络,然后冻结这部分,这样我们的分类器训练器就不会干扰三元组模型。可以这样做:

class classifierNet(nn.Module):
def __init__(self, EmbeddingNet):
    super(classifierNet, self).__init__()
    self.embeddingLayer = EmbeddingNet
    self.classifierLayer = nn.Linear(128,62)
    self.dropout = nn.Dropout(0.5)

def forward(self, x):
    x = self.dropout(self.embeddingLayer(x))
    x = self.classifierLayer(x)
    return F.log_softmax(x, dim=1)

现在我们将加载之前保存的权重并使用以下方法冻结它们:

embeddingNetwork = EmbeddingNetwork().to(device)
embeddingNetwork.load_state_dict(torch.load('embeddingNetwork.pt'))
classifierNetwork = classifierNet(embeddingNetwork)

现在使用 BinaryCrossEntropy 或 CrossEntropy 等标准分类损失训练此分类器网络。