我正在尝试实现一个孪生网络(使用三元组损失方法)。但我无法使其进行训练。经过多次尝试后,我猜测问题可能出在生成器上(我在这里准备训练用的输入数据流),但到目前为止我还无法定位问题。求助! 🙂
这是我的模型定义(基于 ResNet50)。
model = ResNet50(weights='imagenet')model.layers.pop()for layer in model.layers: layer.trainable = Falsex = model.get_layer('flatten_1').outputmodel_out = Dense(128, activation='sigmoid', name='model_out')(x)new_model = Model(inputs=model.input, outputs=model_out)
这里我定义了要训练的模型:
anchor_in = Input(shape=(224, 224, 3))positive_in = Input(shape=(224, 224, 3))negative_in = Input(shape=(224, 224, 3))anchor_out = new_model(anchor_in)positive_out = new_model(positive_in)negative_out = new_model(negative_in)merged_vector = concatenate([anchor_out, positive_out, negative_out], axis=-1)# 定义要训练的模型siamese_model = Model(inputs=[anchor_in, positive_in, negative_in], outputs=merged_vector)siamese_model.compile(optimizer=Adam(lr=.001), loss=triplet_loss)
为了能够训练模型,我需要通过生成器提供数据,下面是我的定义方式:
(请注意,我故意在每个文件夹中只放了一张图片,只是为了开始…如果能工作,我稍后会增加每个文件夹中的图片数量。)
def generator_three_imgs(): train_path = r'C:\Users\jon\Desktop\AI_anaconda\face_recognition\dataset\train\E' generator1 = ImageDataGenerator() generator2 = ImageDataGenerator() generator3 = ImageDataGenerator() anchor_train_batches = generator1.flow_from_directory(train_path+'\Ed_A', target_size=(224, 224), batch_size=1) positive_train_batches = generator2.flow_from_directory(train_path+'\Ed_P', target_size=(224, 224), batch_size=1) negative_train_batches = generator3.flow_from_directory(train_path+'\Ed_N', target_size=(224, 224), batch_size=1) while True: anchor_imgs, anchor_labels = anchor_train_batches.next() positive_imgs, positive_labels = positive_train_batches.next() negative_imgs, negative_labels = negative_train_batches.next() concat_out = concatenate([anchor_out, positive_out, negative_out], axis=-1) yield ([anchor_imgs, positive_imgs, negative_imgs], concat_out)
最后,我尝试按以下方式训练模型:
siamese_model.fit_generator(generator_three_imgs(), steps_per_epoch=1, epochs=15, verbose=2)
但立即失败并显示以下错误消息:
Epoch 1/15Found 1 images belonging to 1 classes.Found 1 images belonging to 1 classes.Found 1 images belonging to 1 classes.---------------------------------------------------------------------------AttributeError Traceback (most recent call last)<ipython-input-23-7537b4595917> in <module>() 1 siamese_model.fit_generator(generator_three_imgs(),----> 2 steps_per_epoch=1, epochs=15, verbose=2)~\Anaconda3\envs\tensorflow\lib\site-packages\keras\legacy\interfaces.py in wrapper(*args, **kwargs) 89 warnings.warn('Update your `' + object_name + 90 '` call to the Keras 2 API: ' + signature, stacklevel=2)---> 91 return func(*args, **kwargs) 92 wrapper._original_function = func 93 return wrapper~\Anaconda3\envs\tensorflow\lib\site-packages\keras\engine\training.py in fit_generator(self, generator, steps_per_epoch, epochs, verbose, callbacks, validation_data, validation_steps, class_weight, max_queue_size, workers, use_multiprocessing, shuffle, initial_epoch) 2228 outs = self.train_on_batch(x, y, 2229 sample_weight=sample_weight,-> 2230 class_weight=class_weight) 2231 2232 if not isinstance(outs, list):~\Anaconda3\envs\tensorflow\lib\site-packages\keras\engine\training.py in train_on_batch(self, x, y, sample_weight, class_weight) 1875 x, y, 1876 sample_weight=sample_weight,-> 1877 class_weight=class_weight) 1878 if self.uses_learning_phase and not isinstance(K.learning_phase(), int): 1879 ins = x + y + sample_weights + [1.]~\Anaconda3\envs\tensorflow\lib\site-packages\keras\engine\training.py in _standardize_user_data(self, x, y, sample_weight, class_weight, check_array_lengths, batch_size) 1478 output_shapes, 1479 check_batch_axis=False,-> 1480 exception_prefix='target') 1481 sample_weights = _standardize_sample_weights(sample_weight, 1482 self._feed_output_names)~\Anaconda3\envs\tensorflow\lib\site-packages\keras\engine\training.py in _standardize_input_data(data, names, shapes, check_batch_axis, exception_prefix) 74 data = data.values if data.__class__.__name__ == 'DataFrame' else data 75 data = [data]---> 76 data = [np.expand_dims(x, 1) if x is not None and x.ndim == 1 else x for x in data] 77 78 if len(data) != len(names):~\Anaconda3\envs\tensorflow\lib\site-packages\keras\engine\training.py in <listcomp>(.0) 74 data = data.values if data.__class__.__name__ == 'DataFrame' else data 75 data = [data]---> 76 data = [np.expand_dims(x, 1) if x is not None and x.ndim == 1 else x for x in data] 77 78 if len(data) != len(names):AttributeError: 'Tensor' object has no attribute 'ndim'
有没有哪位在这方面有更多经验的朋友?
我意识到我之前粘贴的数据是错误的。但这仍然无法解决问题。Daniel Möller 在下面的建议解决了这个问题。
在上面的生成器函数内容中有一个拼写错误。修正后的版本(包括 Daniel 的建议)如下所示:
def generator_three_imgs(batch_size=1): train_path = r'C:\Users\sinthes\Desktop\AI_anaconda\face_recognition\dataset\train\E' generator1 = ImageDataGenerator() generator2 = ImageDataGenerator() generator3 = ImageDataGenerator() anchor_train_batches = generator1.flow_from_directory(train_path+'\Ed_A', target_size=(224, 224), batch_size=batch_size) positive_train_batches = generator2.flow_from_directory(train_path+'\Ed_P', target_size=(224, 224), batch_size=batch_size) negative_train_batches = generator3.flow_from_directory(train_path+'\Ed_N', target_size=(224, 224), batch_size=batch_size) while True: anchor_imgs, anchor_labels = anchor_train_batches.next() positive_imgs, positive_labels = positive_train_batches.next() negative_imgs, negative_labels = negative_train_batches.next() concat_out = np.concatenate([anchor_labels, positive_labels, negative_labels], axis=-1) yield ([anchor_imgs, positive_imgs, negative_imgs], concat_out)
回答:
是的,你的生成器在使用 Keras 的函数(用于张量)来连接 numpy 数据。
使用 numpy.concatenate([anchor_labels, positive_labels, negative_labels], axis=-1)
。