#python #tensorflow #machine-learning #keras #computer-vision
Вопрос:
В настоящее время я пытаюсь создать модель классификации изображений с несколькими метками с использованием Keras. Модель имеет 8 классов с небольшим дисбалансом в наборе данных (у некоторых 300~, в то время как у некоторых других 600~).
После нескольких недель игры с ним я заметил, что любое предсказание, которое я получаю, совершенно случайно, что привело меня к выводу, что, возможно, я совершаю какую — то глупую ошибку, не замечая этого (я предполагаю, что это как-то связано с анализом записей TF, но я не уверен).
Я пробовал несколько вещей: использование разных размеров изображений, изменение размера пакета, добавление/удаление выпадающих слоев, увеличение/уменьшение скорости обучения, добавление/удаление увеличения — даже позволяя модели в разной степени перестраиваться. Однако ничто из этого не имело никакого значения, и модель по-прежнему делает случайные предсказания. Возможно, самое тревожное, что заставило меня поверить, что я, возможно, совершаю ошибку с загрузкой меток, — это то, что результаты одного и того же, идентичного запуска несколько раз сильно отличаются.
Вот что я пытался сделать, чтобы загрузить файлы:
def load_dataset(files, img_w):
def parse_tfrecord(data):
features = {
'image_raw': tf.io.FixedLenFeature([], tf.string),
'label' : tf.io.FixedLenFeature([8], tf.int64),
}
tf_record = tf.io.parse_single_example(data, features)
image = tf.io.decode_jpeg(tf_record['image_raw'], channels=3)
image = tf.image.resize(image, [img_w, img_w])
image = tf.cast(image, tf.float32) / 255
label = tf_record['label']
return image, label
records = tf.data.TFRecordDataset(files, num_parallel_reads=AUTOTUNE)
return records.map(parse_tfrecord, num_parallel_calls=AUTOTUNE)
def augment(image, label):
image = tf.image.random_flip_left_right(image)
image = tf.image.random_hue(image, 0.1)
image = tf.image.random_flip_up_down(image)
return image, label
def get_train_dataset(files, img_w, batch_size, n_train):
train_dataset = load_dataset(files, img_w)
train_dataset = train_dataset.cache()
train_dataset = train_dataset.shuffle(buffer_size=n_train)
train_dataset = train_dataset.batch(batch_size)
train_dataset = train_dataset.prefetch(AUTOTUNE)
train_dataset = train_dataset.map(augment)
return train_dataset
def get_val_dataset(files, img_w, batch_size, n_val):
val_dataset = load_dataset(files, img_w)
val_dataset = val_dataset.cache()
val_dataset = val_dataset.shuffle(buffer_size=n_val)
val_dataset = val_dataset.batch(batch_size)
val_dataset = val_dataset.prefetch(AUTOTUNE)
val_dataset = val_dataset.map(augment)
return val_dataset
def get_datasets(batch_size, img_w):
train_ds_path = "/content/dataset/tfrecords/train.tfrecords"
val_ds_path = "/content/dataset/tfrecords/validation.tfrecords"
n_train, n_val = get_n_samples()
train_dataset = get_train_dataset(train_ds_path, img_w, batch_size, n_train)
val_dataset = get_val_dataset(val_ds_path, img_w, batch_size, n_train)
return train_dataset, val_dataset
Вот как я создал модель:
def get_model():
tf.keras.backend.clear_session()
model = Sequential()
model.add(Conv2D(32, (3, 3), padding='same', input_shape=(IMG_W, IMG_W, 3)))
model.add(Activation('relu'))
model.add(Conv2D(32, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Conv2D(64, (3, 3), padding='same'))
model.add(Activation('relu'))
model.add(Conv2D(64, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(512))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(8, activation='sigmoid'))
model.compile(Adam(learning_rate=L_RATE),
loss=BinaryCrossentropy(from_logits=False),
metrics=[AUC(), Precision(), Recall(), Accuracy()])
return model
И вот как я тренировался:
def train():
early_stopping_cb = EarlyStopping(monitor='val_loss', patience=PATIENCE)
model.fit(train_ds,
verbose=0,
validation_data=val_ds,
epochs=EPOCHS,
callbacks=[early_stopping_cb])
Однако, когда я тестирую, я получаю прогнозы, которые не имеют никакого смысла; нет «предпочтительного» класса, который предсказывается большую часть времени, или даже аналогичного шаблона, который можно идентифицировать во время выполнения — они полностью случайны.
На всякий случай, если это должно помочь, вот что я пытался сделать для тестирования:
def test():
for img_path in glob.glob("/content/dataset/test/*"):
img = preprocessing.image.load_img(img_path, target_size=(IMG_W, IMG_W, 3))
img = preprocessing.image.img_to_array(img)
img = img/255
proba = model.predict(img.reshape(1, IMG_W, IMG_W, 3))
top_3 = np.argsort(proba[0])[:-4:-1]
predictions = []
for i in range(3):
predictions.append((CLASS_NAMES[top_3[i]], round(proba[0][top_3[i]], 2)))
test_output.append((img, predictions))
Также — это пример показателей из нескольких запусков, где потери, похоже, сразу же увеличиваются:
https://i.stack.imgur.com/DQ40a.png
В чем причина таких случайных предсказаний?
Редактировать:
Я добавил большое количество или выборку, чтобы сделать набор данных менее несбалансированным, но это не решило проблему. В настоящее время каждый класс имеет примерно 650 представлений в наборе данных, но прогнозы по — прежнему полностью случайны.
Комментарии:
1. Не могли бы вы предоставить подмножество ваших данных для тестирования вашего кода?