【问题标题】:Siamese model not learning anything, always encodes the image into a vector of zeros连体模型不学习任何东西,总是将图像编码成一个零向量
【发布时间】:2019-10-22 00:35:44
【问题描述】:

我正在尝试训练一个连体模型来预测写在两个图像中的单词是否相同。除了这个模型之外,还应该能够区分两个人的写作。问题类似于签名验证问题。

我的基础网络如下所示:

def create_base_network_signet(input_shape):
    '''Base Siamese Network'''

    seq = Sequential()
    seq.add(Conv2D(96, kernel_size=(7,7), strides=2, input_shape= input_shape, activation='relu'))
    seq.add(BatchNormalization())
    seq.add(ZeroPadding2D(padding=(2, 2)))

    seq.add(Conv2D(96, kernel_size=(7,7), strides=1, activation='relu'))
    seq.add(BatchNormalization())
    seq.add(MaxPooling2D(pool_size=(3, 3), strides=2))
    seq.add(ZeroPadding2D(padding=(1, 1)))

    seq.add(Conv2D(128, kernel_size=(5,5), strides=1, activation='relu'))
    seq.add(Conv2D(128, kernel_size=(5,5), strides=1, activation='relu'))
    seq.add(MaxPooling2D(pool_size=(3, 3), strides=2))
    seq.add(Dropout(0.3))
    seq.add(ZeroPadding2D(padding=(1, 1)))

    seq.add(Conv2D(384, kernel_size=(3,3), strides=1, activation='relu'))
    seq.add(Conv2D(256, kernel_size=(3,3), strides=1, activation='relu'))
    seq.add(BatchNormalization())
    seq.add(MaxPooling2D(pool_size=(3,3), strides=2))
    seq.add(Dropout(0.3))
    seq.add(ZeroPadding2D(padding=(1,1)))

    seq.add(Conv2D(128, kernel_size=(2,2), strides=1, activation='relu'))
    seq.add(Dropout(0.3))

    seq.add(Flatten(name='flatten'))
    seq.add(Dense(1024, W_regularizer=l2(0.0005), activation='relu', init='glorot_uniform'))
    seq.add(Dropout(0.4))

    seq.add(Dense(128, W_regularizer=l2(0.0005), activation='relu', init='glorot_uniform')) # softmax changed to relu

    return seq

最终模型(对比损失):

base_network = create_base_network_signet(input_shape)
input_a = Input(shape=(input_shape), name="first")
input_b = Input(shape=(input_shape), name="second")

processed_a = base_network(input_a)
processed_b = base_network(input_b)

distance = Lambda(euclidean_distance, output_shape=eucl_dist_output_shape)([processed_a, processed_b])

model = Model(input=[input_a, input_b], output=distance)

除了这个模型,我还尝试了其他更简单的模型作为基础模型。我还尝试将 VGG16 和 Inception 等模型作为基础模型进行训练。在训练所有这些模型时,我遇到了同样的问题。模型最终学习将输入图像编码为一个零向量。

我尝试过三元组损失和对比损失来训练模型。两者最终都有预测零的相同问题。对比损失函数取自 keras 教程。而triplet loss定义为:

def triplet_loss(y_true, y_pred, alpha = 0.5):
    anchor, positive, negative = y_pred[0], y_pred[1], y_pred[2]
    pos_dist = tf.reduce_sum(tf.square(tf.subtract(anchor, positive)), axis=-1)
    neg_dist = tf.reduce_sum(tf.square(tf.subtract(anchor, negative)), axis=-1)
    basic_loss = tf.add(tf.subtract(pos_dist, neg_dist), alpha)
    loss = tf.reduce_sum(tf.maximum(basic_loss, 0.0))

    return loss

我还想提一下,当我使用binary_crossentropy 损失函数训练我的模型时。模型开始学习编码。但是,在准确率达到 82% 左右之后,准确率就停止了提高,而损失却在不断下降。

这是在三元组损失和对比损失的情况下输出编码的样子:

我的训练数据如下所示:

【问题讨论】:

    标签: python machine-learning keras deep-learning similarity


    【解决方案1】:

    在我的一个使用三元组损失训练的连体网络中,我遇到了同样的问题。对我来说,诀窍是从loss = tf.reduce_sum(tf.maximum(basic_loss, 0.0)) 行中删除tf.reduce_sum() 部分。我的三元组损失代码的相关sn-p如下。

    # distance between the anchor and the positive
    pos_dist = K.sum(K.square(anchor-positive),axis=1)
    
    # distance between the anchor and the negative
    neg_dist = K.sum(K.square(anchor-negative),axis=1)
    
    # compute loss
    basic_loss = pos_dist-neg_dist+alpha
    loss = K.maximum(basic_loss,0.0)
    

    最后,当你编译模型时,如下所示。

    model.compile(optimizer=Adam(), loss=triplet_loss)

    我相信 reduce_sum() 部分是由 keras 在训练中处理的,当 triplet_loss 被指定为 loss 时。

    试试这个,看看是否有帮助。

    【讨论】:

    • 所以,昨天我修改了我的基础模型的架构并添加了更多的卷积层。现在,具有triplet loss 的模型没有给出零作为编码。它还开始学习保持anchor和positive之间的距离较小,而保持anchor和negative之间的距离相对较高。但是,结果仍然不好,因为输出的范围是可变的。
    • 例如,这就是现在的结果。- Triplet 1--> distance(a, n) = 0.34774 and distance(a, p) = 0.028473。 三元组 2--> 距离(a, n) = 0.044774 和距离(a, p) = 0.018473。 三元组 3--> 距离(a, n) = 0.46774 和距离(a, p) = 0.18473。我应该训练模型更多的时期吗?此外,当我对新模型进行对比损失训练时,它仍然给出 0 作为输出编码。我也会尝试你的建议。
    • 兄弟,你说的我都试过了。但它仍然无法正常工作。我仍然遇到零编码的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-16
    • 1970-01-01
    • 2021-03-28
    • 2020-07-12
    • 1970-01-01
    • 2019-11-28
    • 2018-11-04
    相关资源
    最近更新 更多