我正在尝试建立一个暹罗网络来检查两条鲸鱼(个体)之间的相似性,我的数据集中有15k张图像,有5k个类别,这就是为什么我选择暹罗并且不使用新类别重新训练模型。这是神经网络架构:
def contrastiveLoss(y_true, y_pred):
margin = 1
return K.mean(y_true * K.square(y_pred) + (1 - y_true) * K.square(K.maximum(margin - y_pred, 0)))
def weightInit(shape,dtype=None):
return rng.normal(loc = 0.0, scale = 1e-2, size = shape)
def biasInit(shape,dtype=None):
return rng.normal(loc = 0.5, scale = 1e-2, size = shape)
input_shape = (200, 200, 1)
left_input = Input(input_shape)
right_input = Input(input_shape)
model = Sequential()
model.add(Conv2D(64,(10,10),activation='relu',input_shape=input_shape,kernel_initializer=weightInit,kernel_regularizer=l2(2e-4)))
model.add(MaxPooling2D())
model.add(Conv2D(128,(7,7),activation='relu',kernel_regularizer=l2(2e-4),kernel_initializer=weightInit,bias_initializer=biasInit))
model.add(MaxPooling2D())
model.add(Conv2D(128,(4,4),activation='relu',kernel_regularizer=l2(2e-4),kernel_initializer=weightInit,bias_initializer=biasInit))
model.add(MaxPooling2D())
model.add(Conv2D(256,(4,4),activation='relu',kernel_initializer=weightInit,kernel_regularizer=l2(2e-4),bias_initializer=biasInit))
# model.add(BatchNormalization())
# model.add(Dropout(0.25))
model.add(Flatten())
# model.add(Dropout(0.5))
model.add(Dense(4096,activation="sigmoid",kernel_regularizer=l2(1e-3),kernel_initializer=weightInit,bias_initializer=biasInit))
#call the convnet Sequential model on each of the input tensors so params will be shared
encoded_l = model(left_input)
encoded_r = model(right_input)
#layer to merge two encoded inputs with the l1 distance between them
L1_layer = Lambda(lambda tensors:K.abs(tensors[0] - tensors[1]))
#call this layer on list of two input tensors.
L1_distance = L1_layer([encoded_l, encoded_r])
prediction = Dense(1,activation='sigmoid',bias_initializer=biasInit)(L1_distance)
siamese_net = Model(inputs=[left_input,right_input],outputs=prediction)
optimizer = Adam(0.001)
siamese_net.compile(loss=contrastiveLoss,optimizer='RMSprop')
我正在尝试像这样运行它:
#Training loop
evaluate_every = 10 # interval for evaluating on one-shot tasks
loss_every= 10 # interval for printing loss (iterations)
checkOverfitting = 20
batch_size = 32
epochs = 9000
N_way = 5 # how many classes for testing one-shot tasks
n_val = 250 #number of one-shot tasks to validate on
lossHistory = []
val_accHistory = []
print("training")
for i in range(1, epochs):
(inputs,targets)=dataTrainLoader.getBatch(batch_size)
(loss)=siamese_net.train_on_batch(inputs,targets)
lossHistory.append(loss)
if i % checkOverfitting == 0:
print("Comparing results with x_train and x_test to check overfitting")
val_acc_test = dataTrainLoader.test_oneshot(siamese_net,N_way,n_val,X_test,y_test,verbose=True)
val_acc_train = dataTrainLoader.test_oneshot(siamese_net,N_way,n_val,X_train,y_train,verbose=True)
print("Accuracy in train {:.2f}, accuracy in test {:.2f} ".format(val_acc_train,val_acc_test))
elif i % evaluate_every == 0:
val_acc = dataTrainLoader.test_oneshot(siamese_net,N_way,n_val,X_test,y_test,verbose=True)
val_accHistory.append(val_acc)
if i % loss_every == 0:
print("iteration {}, loss: {:.2f}, val_acc: {:.2f}".format(i,loss,val_acc))
如果需要,我可以补充缺少的功能。 DataTrainLoader是一个类,它为每个时期生成批次(成对),并创建用于测试N_way oneshot的对,并返回正确预测的百分比。
这正在减少损耗,直到某些迭代开始后的某个点如此缓慢地减小为止,例如每2个周期0.01。但是,准确度仍然保持在完整的过山车和非常糟糕的过山车上,包括测试图像和火车图像。我们可以在图形中看到: First loss, then accuracy in test
我已经添加了增强功能,并尝试了诸如更改学习率,更改体系结构,内核,将损失函数设置为binary_crossentropy,batch_size之类的尝试,尝试添加正则化,但它似乎并不过分拟合并检查了参数,通过肉眼和目标比较图像,似乎都是正确的。 我对此无能为力。图像可以用肉眼分辨,也不是不可能的任务。有什么提示,tweeks,我错过了什么错误? 预先感谢您的帮助。