【问题标题】:How to modify Keras Siamese Network example?如何修改 Keras Siamese Network 示例?
【发布时间】:2017-08-25 09:35:34
【问题描述】:

我试图从Keras example about siamese network 更改代码。但奇怪的是,无论损失减少多少,准确率始终为 0.5000。我现在的假设是我错误地修改了 create_pair 函数,我想尝试将类数更改为 4:

原文:

def create_pairs(x, digit_indices):
'''Positive and negative pair creation.
Alternates between positive and negative pairs.
'''
pairs = []
labels = []
n = min([len(digit_indices[d]) for d in range(10)]) - 1
for d in range(10):
    for i in range(n):
        z1, z2 = digit_indices[d][i], digit_indices[d][i + 1]
        pairs += [[x[z1], x[z2]]]
        inc = random.randrange(1, 10)
        dn = (d + inc) % 10
        z1, z2 = digit_indices[d][i], digit_indices[dn][i]
        pairs += [[x[z1], x[z2]]]
        labels += [1, 0]
return np.array(pairs), np.array(labels)

并且,在第 93-97 行:

digit_indices = [np.where(y_train == i)[0] for i in range(10)]
tr_pairs, tr_y = create_pairs(x_train, digit_indices)

digit_indices = [np.where(y_test == i)[0] for i in range(10)]
te_pairs, te_y = create_pairs(x_test, digit_indices)

这是我的代码:

def create_pairs(x, digit_indices):
'''Positive and negative pair creation.
Alternates between positive and negative pairs.
'''
pairs = []
labels = []
n = min([len(digit_indices[d]) for d in range(4)]) - 1
for d in range(4):
    for i in range(n):
        z1, z2 = digit_indices[d][i], digit_indices[d][i + 1]
        pairs += [[x[z1], x[z2]]]
        inc = random.randrange(1, 4)
        dn = (d + inc) % 4
        z1, z2 = digit_indices[d][i], digit_indices[dn][i]
        pairs += [[x[z1], x[z2]]]
        labels += [1, 0]
return np.array(pairs), np.array(labels)

并且,在第 93-97 行:

digit_indices = [np.where(y_train == i)[0] for i in range(4)]
tr_pairs, tr_y = create_pairs(x_train, digit_indices)

digit_indices = [np.where(y_test == i)[0] for i in range(4)]
te_pairs, te_y = create_pairs(x_test, digit_indices)

这是我的base_network(使用RNN的那个,不是我在评论回复中谈到的conv net,都给出了相同的结果,50%的准确率):

def create_base_network(embedding_layer):
    seq = Sequential()
    seq.add(embedding_layer)
    seq.add(GRU(512, use_bias=True, dropout=0.5, recurrent_dropout=0.5, return_sequences=True))
    seq.add(GRU(512, use_bias=True, dropout=0.5, recurrent_dropout=0.5))
    seq.add(Dense(512, activation='relu'))
    seq.add(Dropout(0.1))
    seq.add(Dense(512, activation='relu'))
    return seq

嵌入层只是一个简单的手套矩阵。我还在合并后使用 sigmoid 激活函数添加了另一个密集层。

有什么遗漏吗?或者这不是我应该如何改变它?提前致谢

【问题讨论】:

  • 我收到了 0 到 3 位数字的 * Accuracy on training set: 99.97%`` * Accuracy on test set: 99.69%...你还改变了什么?
  • 你可以在这里查看我对你要求的限制的更改gist.github.com/oak-tree/49fcbee1d2ecfb11c78b1b64bafc9a76
  • 我也更改了 base_network,我尝试复制 this paper。因此,我使用 conv net(s) 更改了基础网络,并在 lambda 层之后添加了一个密集层 + 我将欧几里德距离更改为 L1 距离。所以我想可能我只需要增加 epoch 以便 conv 层可以了解更多(?)。你怎么看?
  • 如果您发布您的来源 更容易提供帮助。请注意您添加的论文,您还需要添加 sigmoid 激活
  • 是的,我在 Lambda 层之后添加了 sigmoid 层,并且我更新了问题以向您展示我的 base_network,对该代码有什么建议吗? @橡树

标签: keras


【解决方案1】:

连体代码错误,尚未修复。问题是损失函数在切换 0 和 1 时不对称,但 keras 代码假设它是对称的。 改变这一行

return K.mean(y_true * K.square(y_pred) + (1 - y_true) * K.square(K.maximum(margin - y_pred, 0)))

进入

return K.mean((1 - y_true) * K.square(y_pred) + y_true * K.square(K.maximum(margin - y_pred, 0)))

labels += [1, 0]

进入

labels += [0, 1]

【讨论】:

  • 但是,我已经尝试了原始代码,它显示了一个很好的结果,然后我尝试更改数据,仍然给出(某种)一个很好的结果。但是当我将 base_network 更改为一层卷积时,准确率将停留在 50%
  • 我试着像你说的那样改变损失函数和标签。但它给出了更糟糕的结果。但是当我使用 keras 给出的代码时。它显示了一个很好的结果。有没有可能是误报实验?
  • 可能你的keras版本比较新,原代码的bug已经修复。但在任何情况下,您的代码都不能低于 50%,因为这是纯粹机会的基线。这意味着在您的代码中某处存在错误。
  • 所以你认为我应该只使用 mnist_siamese_graph.py 中的 keras 给出的代码,尽管它没有使用与原始论文中相同的对比损失方程吗?因为我很乐意这样做,因为它给了我一个非常好的结果@emanuele
  • 不,我只是告诉你代码中的某个地方存在错误。
猜你喜欢
  • 2021-04-08
  • 2019-07-05
  • 1970-01-01
  • 2019-10-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-06
  • 2020-10-16
相关资源
最近更新 更多