#python #tensorflow #keras
#python #тензорный поток #keras
Вопрос:
# We have 2 inputs, 1 for each picture
left_input = Input(img_size)
right_input = Input(img_size)
# We will use 2 instances of 1 network for this task
convnet = MobileNetV2(weights='imagenet', include_top=False, input_shape=img_size,input_tensor=None)
convnet.trainable=True
x=convnet.output
x=tf.keras.layers.GlobalAveragePooling2D()(x)
x=Dense(320,activation='relu')(x)
x=Dropout(0.2)(x)
preds = Dense(101, activation='sigmoid')(x) # Apply sigmoid
convnet = Model(inputs=convnet.input, outputs=preds)
# Connect each 'leg' of the network to each input
# Remember, they have the same weights
encoded_l = convnet(left_input)
encoded_r = convnet(right_input)
# Getting the L1 Distance between the 2 encodings
L1_layer = Lambda(lambda tensor:K.abs(tensor[0] - tensor[1]))
# Add the distance function to the network
L1_distance = L1_layer([encoded_l, encoded_r])
prediction = Dense(1,activation='sigmoid')(L1_distance)
siamese_net = Model(inputs=[left_input,right_input],outputs=prediction)
optimizer = Adam(lr, decay=2.5e-4)
#//TODO: get layerwise learning rates and momentum annealing scheme described in paperworking
siamese_net.compile(loss=keras.losses.binary_crossentropy,optimizer=optimizer,metrics=['accuracy'])
siamese_net.summary()
и результат обучения выглядит следующим образом
Epoch 1/10
126/126 [==============================] - 169s 1s/step - loss: 0.5683 - accuracy: 0.6840 - val_loss: 0.4644 - val_accuracy: 0.8044
Epoch 2/10
126/126 [==============================] - 163s 1s/step - loss: 0.2032 - accuracy: 0.9795 - val_loss: 0.2117 - val_accuracy: 0.9681
Epoch 3/10
126/126 [==============================] - 163s 1s/step - loss: 0.1110 - accuracy: 0.9925 - val_loss: 0.1448 - val_accuracy: 0.9840
Epoch 4/10
126/126 [==============================] - 164s 1s/step - loss: 0.0844 - accuracy: 0.9950 - val_loss: 0.1384 - val_accuracy: 0.9820
Epoch 5/10
126/126 [==============================] - 163s 1s/step - loss: 0.0634 - accuracy: 0.9990 - val_loss: 0.0829 - val_accuracy: 1.0000
Epoch 6/10
126/126 [==============================] - 165s 1s/step - loss: 0.0526 - accuracy: 0.9995 - val_loss: 0.0729 - val_accuracy: 1.0000
Epoch 7/10
126/126 [==============================] - 164s 1s/step - loss: 0.0465 - accuracy: 0.9995 - val_loss: 0.0641 - val_accuracy: 1.0000
Epoch 8/10
126/126 [==============================] - 163s 1s/step - loss: 0.0463 - accuracy: 0.9985 - val_loss: 0.0595 - val_accuracy: 1.0000
Модель предсказывает с хорошей точностью, когда я сравниваю два разных изображения. Кроме того, он действительно хорошо прогнозирует с тем же классом изображений.
Но когда я сравниваю Image1 с самим image1, он предсказывает, что они похожи только с вероятностью 0,5.
в другом случае, если я сравниваю image1 с image2, то он правильно предсказывает с вероятностью 0,8. (здесь image1 и image2 принадлежат к одному классу)
когда я сравниваю отдельные изображения, он правильно предсказывает, я пробовал разные альтернативы, но не тренировался. Могу ли я узнать, в чем может быть ошибка?
Ответ №1:
Расстояние L1 между двумя равными векторами всегда равно нулю.
Когда вы передаете одно и то же изображение, сгенерированные кодировки равны ( encoded_l
равно encoded_r
). Следовательно, входные данные для вашего конечного сигмовидного слоя представляют собой нулевой вектор.
И, sigmoid(0) = 0.5
.
Это причина, по которой идентичные входные данные для вашей модели выдаются 0.5
в качестве выходных данных.
Комментарии:
1. Что я должен изменить в коде? Потому что это также влияло на точность моего тестирования. Когда я попытался протестировать модель с помощью набора тестов, она дает 50% точности теста. Но когда я проверяю каждое отдельное изображение, оно работает действительно хорошо. За исключением описанной выше проблемы. Могу ли я узнать, как мне преодолеть это?
2. Замените функцию L1 чем-нибудь другим. Например, используйте
Add()
илиConcatenate()
и переобучите модель.3. Спасибо за ваш ответ на мой вопрос. Не могли бы вы, пожалуйста, подробно описать Add() или Concatenate() ?
4. И мои вопросы: я думаю, что это общий способ определения функции L1_distance для сиамского CNN?
5. L1 или любые четко определенные функции расстояния не являются хорошим выбором для сиамских сетей. Всегда лучше позволить модели изучить функцию сравнения. Лучше всего, если вы используете
Concatenate()([encoded_l, encoded_r])