【问题标题】:How to determine accuracy with triplet loss in a convolutional neural network如何确定卷积神经网络中三元组损失的准确性
【发布时间】:2017-12-28 12:44:21
【问题描述】:

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

我使用成对的三张图像来馈送网络(x = 锚图像,标准图像,x+ = 正图像,包含相同对象的图像as x - 实际上,x+ 与 x 是同一类,而 x- = 负像与 x 具有不同类的图像。。 p>

我正在使用 here 描述的三元组损失成本函数。

如何确定网络的准确性?

【问题讨论】:

    标签: neural-network conv-neural-network triplet


    【解决方案1】:

    我假设您正在从事图像检索或类似任务的工作。

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

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

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

    以上两个指标中的任何一个都可以。选择您认为适合您的情况的任何内容。

    【讨论】:

    • 发生了一件非常奇怪的事情:准确率上升到 99%(如您的答案中所定义),但是当我使用模型生成的嵌入对人进行分类时,只有 20% 的分类是正确的(网络将图像转换为 124 个浮点数)。你能帮帮我吗?
    • 特征嵌入是为检索或聚类任务量身定制的。我不确定特征对分类任务的有效性。另外,99% 的准确率在验证集上?
    • 是的,我在验证集上得到了这个意想不到的好结果。我实际上正在关注这篇文章arxiv.org/pdf/1503.03832.pdf,他们使用triplet loss 进行面部验证。
    • 我使用 CASIA 作为训练集(我正在生成违反损失的三元组)和来自 LFW 的 6400 张随机照片作为验证集。我确信这两个数据集不会重叠(因此没有过度拟合)。
    • 影响因素太多了。您的功能 L2 是否标准化?你如何为你的验证集生成三元组。您是否使用任何正则化(权重衰减、辍学等)。你的测试集是什么?同样,为什么要使用为检索任务训练的特征来执行分类任务。
    【解决方案2】:

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

    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 等标准分类损失来训练这个分类器网络。

    【讨论】:

      猜你喜欢
      • 2017-11-17
      • 2016-08-02
      • 1970-01-01
      • 2018-07-25
      • 2016-12-15
      • 2017-08-31
      • 2016-12-08
      • 1970-01-01
      • 2021-04-18
      相关资源
      最近更新 更多