Моя проблема:
Я пытаюсь обучить модель сегментации semanti c в tf.keras, на самом деле она работает очень хорошо, когда я использую режим channels_last (WH C) (он достигает 96% + значение a cc). Я хотел обучить его в режиме channels_first (CHW) , чтобы веса были совместимы с TensorRT. Когда я это делаю, точность обучения ~ 80% в первые несколько эпох опускается примерно до 0,020% и остается там постоянно.
Полезно знать, что основа моей модели представляет собой модель tf.keras.applications.MobileNet()
с предварительно обученными весами 'imag enet'. (Архитектура модели внизу.)
Процесс преобразования:
Я использовал предоставленные рекомендации и изменил здесь только несколько вещей:
- Установите
tf.keras.backend.set_image_data_format()
на 'channels_first'. - Я изменяю порядок каналов во входном тензоре с:
input_tensor=Input(shape=(376, 672, 3))
на: input_tensor=Input(shape=(3, 376, 672))
- В моей предварительной обработке изображения (используя
tf.data.Dataset
), я использую tf.transpose(img, perm=[2, 0, 1])
как на моем входном изображении, так и на маске с горячим кодированием, чтобы изменить порядок каналов. Я проверил это с помощью утверждения равенства, чтобы убедиться, что оно правильное, и вроде бы все в порядке.
Когда я меняю их, обучение начинается нормально, но, как я уже сказал, точность обучения снижается почти до нуля. Когда я возвращаюсь обратно, все снова в порядке.
Возможные зацепки:
Что я делаю не так или в чем может быть проблема? Мои подозрения связаны с этими вопросами:
- Изменились ли веса предварительно обученного изображения eNet на порядок «channels_first» также, когда я устанавливаю бэкэнд? Должен ли я вообще об этом подумать?
- Может быть, функция
tf.transpose()
испортила горячую кодировку маски? (У меня есть 3 класса, представленные 3 цветами: полоса, противоположная полоса, фон)
Возможно, я не вижу чего-то очевидного. При необходимости я могу предоставить дополнительный код и ответы.
РЕДАКТИРОВАТЬ:
08/17: Это все еще актуальная проблема, я пробовал несколько вещей:
- Я проверил правильность изображения и маски после транспонирования с утверждением numpy, кажется правильным.
- Я подозревал, что функция потерь вычисляется не на той оси, поэтому я настроил функцию потерь для первой оси (где каналы). Вот он:
def ReverseAxisLoss(y_true, y_pred):
return K.categorical_crossentropy(y_true, y_pred, from_logits=True, axis=1)
- Мое главное подозрение в том, что бэкэнд-настройка «сначала каналы» ничего не делает для транспонирования предварительно обученных весов «imag enet» для mobil enet часть. Есть ли обновленный способ для TF2.x / Keras транспонировать предварительно обученные веса в формат CHW?
Вот архитектура , которую я использую (skipNet()
это головная сеть и мобил enet это база, и она подключена в функции create_model()
)
def skipNet(encoder_output, feed1, feed2, classes):
# random initializer and regularizer
stddev = 0.01
init = RandomNormal(stddev=stddev)
weight_decay = 1e-3
reg = l2(weight_decay)
score_feed2 = Conv2D(kernel_size=(1, 1), filters=classes, padding="SAME",
kernel_initializer=init, kernel_regularizer=reg)(feed2)
score_feed2_bn = BatchNormalization()(score_feed2)
score_feed1 = Conv2D(kernel_size=(1, 1), filters=classes, padding="SAME",
kernel_initializer=init, kernel_regularizer=reg)(feed1)
score_feed1_bn = BatchNormalization()(score_feed1)
upscore2 = Conv2DTranspose(kernel_size=(4, 4), filters=classes, strides=(2, 2),
padding="SAME", kernel_initializer=init,
kernel_regularizer=reg)(encoder_output)
height_pad1 = ZeroPadding2D(padding=((1,0),(0,0)))(upscore2)
upscore2_bn = BatchNormalization()(height_pad1)
fuse_feed1 = add([score_feed1_bn, upscore2_bn])
upscore4 = Conv2DTranspose(kernel_size=(4, 4), filters=classes, strides=(2, 2),
padding="SAME", kernel_initializer=init,
kernel_regularizer=reg)(fuse_feed1)
height_pad2 = ZeroPadding2D(padding=((0,1),(0,0)))(upscore4)
upscore4_bn = BatchNormalization()(height_pad2)
fuse_feed2 = add([score_feed2_bn, upscore4_bn])
upscore8 = Conv2DTranspose(kernel_size=(16, 16), filters=classes, strides=(8, 8),
padding="SAME", kernel_initializer=init,
kernel_regularizer=reg, activation="softmax")(fuse_feed2)
return upscore8
def create_model(classes):
base_model = tf.keras.applications.MobileNet(input_tensor=Input(shape=IMG_SHAPE),
include_top=False,
weights='imagenet')
conv4_2_output = base_model.get_layer(index=43).output
conv3_2_output = base_model.get_layer(index=30).output
conv_score_output = base_model.output
head_model = skipNet(conv_score_output, conv4_2_output, conv3_2_output, classes)
for layer in base_model.layers:
layer.trainable = False
model = Model(inputs=base_model.input, outputs=head_model)
return model