繁体   English   中英

暹罗网络的 Keras 模型不学习并始终预测相同的输出

[英]Keras Model for Siamese Network not Learning and always predicting the same ouput

我正在尝试使用 Keras 训练 Siamese 神经网络,目的是确定 2 张图像是否属于同一类。 我的数据被打乱,并且正例和负例的数量相等。 我的模型没有学习任何东西,它总是预测相同的输出。 我每次都得到相同的损失、验证准确性和验证损失。

训练输出

def convert(row):
    return imread(row)

def contrastive_loss(y_true, y_pred):
    margin = 1
    square_pred = K.square(y_pred)
    margin_square = K.square(K.maximum(margin - y_pred, 0))
    return K.mean(y_true * square_pred + (1 - y_true) * margin_square)

def SiameseNetwork(input_shape):
    top_input = Input(input_shape)

    bottom_input = Input(input_shape)

    # Network
    model = Sequential()
    model.add(Conv2D(96,(7,7),activation='relu',input_shape=input_shape))
    model.add(MaxPooling2D())
    model.add(Conv2D(256,(5,5),activation='relu',input_shape=input_shape))
    model.add(MaxPooling2D())
    model.add(Conv2D(256,(5,5),activation='relu',input_shape=input_shape))
    model.add(MaxPooling2D())
    model.add(Flatten())
    model.add(Dense(4096,activation='relu'))
    model.add(Dropout(0.5))
    model.add(Dense(1024,activation='relu'))
    model.add(Dropout(0.5))
    model.add(Dense(512,activation='relu'))
    model.add(Dropout(0.5))

    encoded_top = model(top_input)
    encoded_bottom = model(bottom_input)

    L1_layer = Lambda(lambda tensors:K.abs(tensors[0] - tensors[1]))    
    L1_distance = L1_layer([encoded_top, encoded_bottom])

    prediction = Dense(1,activation='sigmoid')(L1_distance)
    siamesenet = Model(inputs=[top_input,bottom_input],outputs=prediction)
    return siamesenet

data = pd.read_csv('shuffleddata.csv')
print('Converting X1....')

X1 = [convert(x) for x in data['X1']]

print('Converting X2....')

X2 = [convert(x) for x in data['X2']]

print('Converting Y.....')
Y = [0 if data['Y'][i] == 'Negative' else 1 for i in range(len(data['Y']))]

input_shape = (53,121,3,)
model = SiameseNetwork(input_shape)
model.compile(loss=contrastive_loss,optimizer='sgd',metrics=['accuracy'])
print(model.summary())
model.fit(X1,Y,batch_size=32,epochs=20,shuffle=True,validation_split = 0.2)
model.save('Siamese.h5')

为了社区的利益,在本部分提及此问题的解决方案(即使它出现在评论部分)。

由于模型与其他标准数据集配合良好,解决方案是使用更多数据 模型没有在学习,因为它用于训练的数据较少。

如评论和 Tensorflow Support 的回答中所述,该模型可以很好地处理更多数据。 稍微调整模型也有效。 将第 2 和第 3 卷积层中的滤波器数量从 256 更改为 64 会大量减少可训练参数的数量,因此模型开始学习。

我想在这里提几件可能对其他人有用的事情:

1) 数据分层/随机抽样

当您使用validation_split Keras 使用最后 x% 的数据作为验证数据。 这意味着如果数据是按类别排序的,例如因为“成对”或“三胞胎”是按顺序生成的,则验证数据将仅来自包含在最后 x% 数据中的类别(或类别)。 在这种情况下,验证集将没有用。 因此,必须对输入数据进行混洗以确保验证集包含来自每个类的随机样本。

validation_split的文档说:

介于 0 和 1 之间的浮点数。要用作验证数据的训练数据的一部分。 该模型将把这部分训练数据分开,不会对其进行训练,并将在每个时期结束时评估损失和此数据的任何模型指标。 验证数据是从提供的 x 和 y 数据中的最后一个样本中选择的,然后再混洗

2)优化器的选择

model.compile()选择optimizer='sgd'可能不是最好的方法,因为sgd可能会卡在局部最小值等中。 Adam请参阅文档)似乎是一个不错的选择,因为它...

[...] 结合了 [...] AdaGrad 处理稀疏梯度的优势,以及 RMSProp 处理非平稳目标的能力。

根据Kingma 和 Ba (2014 年,第 10 页)。

from keras.optimizers import Adam
...
model.compile(loss=contrastive_loss, optimizer=keras.optimizers.Adam(lr=0.0001))

3)提前停止/学习率

在训练期间使用提前停止调整学习率也可能对获得良好的结果非常有用。 所以模型可以训练直到不再成功(在这种情况下自动停止)。

from keras.callbacks import EarlyStopping
from keras.callbacks import ReduceLROnPlateau
...
early_stopping = EarlyStopping(monitor='val_loss', patience=50, mode='auto', restore_best_weights=True)
reduce_on_plateau = ReduceLROnPlateau(monitor="val_loss", factor=0.8, patience=15, cooldown=5, verbose=0)
...
hist = model.fit([img_1, img_2], y, 
            validation_split=.2, 
            batch_size=128, 
            verbose=1, 
            epochs=9999,
            callbacks=[early_stopping])

4)内核初始化

内核初始化(带有小 SD)也可能有帮助。

# Layer 1
    seq.add(Conv2D(8, (5,5), input_shape=input_shape, 
        kernel_initializer=keras.initializers.TruncatedNormal(mean=0.0, stddev=0.01, seed=None), 
        data_format="channels_first"))
    seq.add(Activation('relu'))
    seq.add(MaxPooling2D(pool_size=(2, 2))) 
    seq.add(Dropout(0.1))

5) 过拟合

我注意到,与其使用 dropout 来对抗过拟合,不如添加一些噪声会很有帮助。 在这种情况下,只需在网络顶部添加一些GaussianNoise

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM