Я подгоняю сиамскую CNN со следующей структурой:
def get_siamese_model(input_shape):
"""
Model architecture
"""
# Define the tensors for the three input images
A_input = Input(input_shape)
B_input = Input(input_shape)
C_input = Input(input_shape)
# Convolutional Neural Network
#Initialzers
initializer = 'random_uniform'
initializer0 = 'zeros'
model = Sequential()
model.add(Conv2D(64, (10,10), activation='relu', input_shape=input_shape,
kernel_initializer=initializer , kernel_regularizer=l2(2e-4)))
model.add(MaxPooling2D())
model.add(Conv2D(128, (7,7), activation='relu', kernel_initializer=initializer ,
bias_initializer=initializer0, kernel_regularizer=l2(2e-4)))
model.add(MaxPooling2D())
model.add(Conv2D(128, (4,4), activation='relu', kernel_initializer=initializer ,
bias_initializer=initializer0, kernel_regularizer=l2(2e-4)))
print("C3 shape: ", model.output_shape)
model.add(MaxPooling2D())
print("P3 shape: ", model.output_shape)
model.add(Conv2D(256, (4,4), activation='relu', kernel_initializer=initializer ,
bias_initializer=initializer0, kernel_regularizer=l2(2e-4)))
model.add(Flatten())
model.add(Dense(4096, activation='sigmoid',
kernel_regularizer=l2(1e-3),
kernel_initializer=initializer,
bias_initializer=initializer0))
# Generate the encodings (feature vectors) for the three images
encoded_A = model(A_input)
encoded_B = model(B_input)
encoded_C = model(C_input)
#Custom Layer for L1-norm
L1_layer = Lambda(lambda tensors: K.sum(K.abs(tensors[0] - tensors[1]), axis=1,keepdims=True))
L_layerAB = L1_layer([encoded_A, encoded_B])
L2_layer = Lambda(lambda tensors: K.sum(K.abs(tensors[0] - tensors[1]), axis=1,keepdims=True))
L_layerAC = L2_layer([encoded_A, encoded_C])
merge6 = concatenate([L_layerAB, L_layerAC], axis = 0)
prediction = Dense(1,activation='sigmoid')(merge6)
siamese_net = Model(inputs=[A_input,B_input, C_input],outputs= prediction)
# return the model
return siamese_net
Обучающие данные - это триплеты изображений в виде массива со следующими размерами: (128,128,3). И целевые данные - это метка (0,1).
Затем мы подбираем модель:
model = siam.get_siamese_model((128,128,3))
model.fit([tripletA,tripletB, tripletC], targets , epochs=2, verbose=1,
batch_size = 1)
Это работает для batch_size = 1, но все, что превышает размер партии> 1, приводит к следующей ошибке:
Epoch 1/5
Traceback (most recent call last):
File "<ipython-input-147-8959bad9406a>", line 2, in <module>
batch_size = 2)
File "C:\Users\valan\Anaconda3\lib\site-packages\keras\engine\training.py", line 1239, in fit
validation_freq=validation_freq)
File "C:\Users\valan\Anaconda3\lib\site-packages\keras\engine\training_arrays.py", line 196, in fit_loop
outs = fit_function(ins_batch)
File "C:\Users\valan\Anaconda3\lib\site-packages\tensorflow_core\python\keras\backend.py", line 3727, in _call_
outputs = self._graph_fn(*converted_inputs)
File "C:\Users\valan\Anaconda3\lib\site-packages\tensorflow_core\python\eager\function.py", line 1551, in _call_
return self._call_impl(args, kwargs)
File "C:\Users\valan\Anaconda3\lib\site-packages\tensorflow_core\python\eager\function.py", line 1591, in _call_impl
return self._call_flat(args, self.captured_inputs, cancellation_manager)
File "C:\Users\valan\Anaconda3\lib\site-packages\tensorflow_core\python\eager\function.py", line 1692, in _call_flat
ctx, args, cancellation_manager=cancellation_manager))
File "C:\Users\valan\Anaconda3\lib\site-packages\tensorflow_core\python\eager\function.py", line 545, in call
ctx=ctx)
File "C:\Users\valan\Anaconda3\lib\site-packages\tensorflow_core\python\eager\execute.py", line 67, in quick_execute
six.raise_from(core._status_to_exception(e.code, message), None)
File "<string>", line 3, in raise_from
InvalidArgumentError: Incompatible shapes: [4,1] vs. [2,1]
[[node loss_16/dense_47_loss/binary_crossentropy/logistic_loss/mul (defined at C:\Users\valan\Anaconda3\lib\site-packages\keras\backend\tensorflow_backend.py:3009) ]] [Op:__inference_keras_scratch_graph_33258]
Кто-нибудь знает, где проблема с batch_size> 1?
EDIT1:
Мы обнаружили, что следующее строки вызвали ошибку :
L1_layer = Lambda(lambda tensors: K.sum(K.abs(tensors[0] - tensors[1]), axis=1,keepdims=True))
L_layerAB = L1_layer([encoded_A, encoded_B])
L2_layer = Lambda(lambda tensors: K.sum(K.abs(tensors[0] - tensors[1]), axis=1,keepdims=True))
L_layerAC = L2_layer([encoded_A, encoded_C])
Удаление этих строк и использование сигмоида в кодированном A и, таким образом, упрощение модели позволяет ей работать для пакетов размером> 1.
Но кто-нибудь знает, как правильно повторно добавить эти настроенные слои?