Я пытаюсь обучить сиамскую модель прогнозированию совпадения слов, написанных на двух изображениях.Помимо этой модели также следует уметь различать написание двух людей.Эта проблема аналогична проблеме проверки подписи.
Моя базовая сеть выглядит следующим образом:
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
учебников.И триплетная потеря определяется как:
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% точность перестает улучшаться, а потери продолжают уменьшаться.
Вот как выглядит выходное кодирование в случае триплетной потери и контрастной потери:
Мои тренировочные данные выглядят так: