В настоящее время я работаю над простой проблемой классификации, используя средство извлечения признаков и классификатор. Для экстрактора функций я использую предварительно обученную модель ResNet50, найденную в tf.keras.application в TF 1.15.2 . Я провожу двухэтапное обучение, на котором я обучаю экстрактор признаков на первом этапе (здесь нет проблем) и обучаю классификатор на втором этапе, где я замораживаю обученный экстрактор признаков (проблемы здесь). Я использую размер пакета 128 и скорость обучения 0,3 для обучения классификатора. У меня возникли проблемы с производительностью фактического набора для проверки, поэтому я проверяю производительность обучающего набора, чтобы лучше понять, в чем проблема с моим кодом.
Вот мой код для загрузки набора данных
def make_generator(images, labels):
def _generator():
for image, label in zip(images, labels):
yield image, np.array(label)
return _generator
def create_dataset(dataset_dict, shuffle=False):
images = []
labels = []
buffer_size = 0
for k,v in dataset_dict.items():
images += v
labels += [k for _ in v]
buffer_size += len(v)
dataset = tf.data.Dataset.from_generator(make_generator(images, labels),
(tf.float32, tf.uint8), output_shapes=(tf.TensorShape([HEIGHT,WIDTH,DEPTH]), tf.TensorShape([])))
if shuffle:
dataset = dataset.shuffle(buffer_size, reshuffle_each_iteration=True)
dataset = dataset.batch(batch_size, drop_remainder=True) \
.prefetch(10)
return dataset
где dataset_dict - это словарь, содержащий {label: <preprocessed images from class>}
train_dataset = create_dataset(base_train_dict, shuffle=True)
Создать модель
def get_feature_extractor(pretrained=True):
if pretrained:
weights = 'imagenet'
feat_extractor = tf.keras.applications.ResNet50(
input_shape=(HEIGHT, WIDTH, DEPTH),
include_top=False,
layers=tf.keras.layers,
pooling='avg',
weights=weights)
for layer in feat_extractor.layers[:25]:
layer.trainable = False
return feat_extractor
model_input = tf.keras.Input(shape=(HEIGHT, WIDTH, DEPTH), name='input')
feat_extractor = get_feature_extractor()
.
.
.
# feat_extractor is trained in first stage
output = feat_extractor(model.inputs)
output = Dense(num_classes, 'softmax')(output)
model = tf.keras.Model(model.inputs, output)
# freeze layers before classification layer
for layer in model.layers[:-1]:
layer.trainable = False
Определить метрики
loss = 'sparse_categorical_crossentropy'
if optimizer == 'SGD':
opt = SGD(lr=learning_rate, momentum=momentum, clipnorm=5)
else:
opt = Adam(lr=learning_rate, decay=weight_decay, clipnorm=5)
def sparse_top_3_categorical_accuracy(y_true, y_pred):
return sparse_top_k_categorical_accuracy(y_true, y_pred, k=3)
metrics = ['sparse_categorical_accuracy', sparse_top_3_categorical_accuracy]
model.compile(loss=loss, optimizer=opt, metrics=metrics)
def scheduler(epoch, restart=50):
if epoch % restart == 0:
return learning_rate
else:
return learning_rate * (0.999 ** (epoch % restart))
monitor = 'val_sparse_categorical_accuracy'
callbacks = []
callbacks.append(
ModelCheckpoint('output/local_base_class.h5', monitor=monitor,
save_best_only=True,
mode='max'))
# callbacks.append(CustomTensorBoardCallback(log_dir=tensorboard_dir))
# callbacks.append(ReduceLROnPlateau(monitor='sparse_categorical_accuracy', patience=8, verbose=1))
callbacks.append(TerminateOnNaN())
callbacks.append(CSVLogger(f'classifier_base_{datetime.now()}.log'))
callbacks.append(LearningRateScheduler(scheduler))
epochs = 10
logging.info("Starting classifier training")
history = model.fit(train_dataset,
epochs=epochs,
validation_data=train_dataset,
callbacks=callbacks,
verbose=2)
Я столкнулся со специфической проблемой получения совершенно разных результатов для моего вызова model.fit()
, и я подозреваю, что это связано с уровнем BatchNormalization Layer, найденным в ResNet50.
Epoch 10/10
82/82 - 22s - loss: 5.5539 - sparse_categorical_accuracy: 0.5319 - sparse_top_3_categorical_accuracy: 0.6624 - val_loss: 74.7229 - val_sparse_categorical_accuracy: 0.0033 - val_sparse_top_3_categorical_accuracy: 0.0109
Затем я сделал оценку
model.evaluate(train_dataset)
82/82 [==============================] - 10s 125ms/step - loss: 74.7229 - sparse_categorical_accuracy: 0.0033 - sparse_top_3_categorical_accuracy: 0.0109
Итак, я попытался исправить, выполнив
from tensorflow.keras import backend as K
from tensorflow.keras.models import load_model
dependencies = {
'sparse_top_3_categorical_accuracy': sparse_top_3_categorical_accuracy
}
K.clear_session()
K.set_learning_phase(1)
model = load_model('tmp.h5', custom_objects=dependencies)
Но я получил тот же результат
model.evaluate(train_dataset)
82/82 [==============================] - 11s 135ms/step - loss: 74.7229 - sparse_categorical_accuracy: 0.0033 - sparse_top_3_categorical_accuracy: 0.0109
Как исправить эту проблему, чтобы получить почти такой же уровень производительности для model.fit()
для того же набора данных или такую же производительность для model.evaluate
?