#python #tensorflow #keras #deep-learning
#python #тензорный поток #keras #глубокое обучение
Вопрос:
Мы пытаемся добавить пользовательский слой внутри предварительно обученной модели imagenet. Для последовательной или непоследовательной модели мы можем легко это сделать. Но вот некоторые требования.
Прежде всего, мы не хотим раскрывать всю модель imagenet и иметь дело с желаемым внутренним слоем. Допустим DenseNet
, нам нужны следующие слои, а затем получить их форму вывода для соединения с некоторыми пользовательскими слоями.
vision_model = tf.keras.applications.DenseNet121(
input_shape=(224,224,3),
include_top = False,
weights='imagenet')
for i, layer in enumerate(vision_model.layers):
if layer.name in ['conv3_block12_concat', 'conv4_block24_concat']:
print(i,'t',layer.trainable,'t :',layer.name)
if layer.name == 'conv3_block12_concat':
print(layer.get_output_shape_at(0)[1:]) # (28, 28, 512)
if layer.name == 'conv4_block24_concat':
print(layer.get_output_shape_at(0)[1:]) # (14, 14, 1024)
Все требование можно продемонстрировать следующим образом
Зеленый индикатор — это, по сути, переходный слой плотной сети.
На приведенной выше диаграмме модель с плотной сетью имеет (скажем так), 5 blocks
и среди них мы хотим выбрать block 3
block 4
и добавить несколько пользовательских слоев, а затем объединить их, чтобы получить конечный результат.
Кроме того, блоки DenseNet
(от 1 до 5 блоков) должны быть максимально раскрыты с их предварительно обученными весами imagenet. Нам нравится иметь возможность замораживать и размораживать предварительно обученные слои, когда они нам нужны.
Как мы можем эффективно достичь этого с tf.keras
помощью ? или, если вы считаете, что есть какой-то лучший подход к тому же, пожалуйста, предложите.
Допустим, пользовательский блок выглядит примерно так
class MLPBlock(tf.keras.layers.Layer):
def __init__(self, kernel_num=32, kernel_size=(3,3), strides=(1,1), padding='same'):
super(ConvModule, self).__init__()
# conv layer
self.conv = tf.keras.layers.Conv2D(kernel_num,
kernel_size=kernel_size,
strides=strides, padding=padding)
# batch norm layer
self.bn = tf.keras.layers.BatchNormalization()
def call(self, input_tensor, training=False):
x = self.conv(input_tensor)
x = self.bn(x, training=training)
return tf.nn.relu(x)
Мотивация
Я пытаюсь реализовать эту бумажную работу, где они сделали что-то вроде этого. Изначально документ можно было получить бесплатно, но теперь это не так. Но ниже приведена основная блок-схема их подхода.
Ответ №1:
У меня нет доступа к бумаге, поэтому я просто создаю пример, подобный тому, который вы рисуете:
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers, models
class ConvBlock(layers.Layer):
def __init__(self, kernel_num=32, kernel_size=(3,3), strides=(1,1), padding='same'):
super(ConvBlock, self).__init__()
# conv layer
self.conv = layers.Conv2D(kernel_num,
kernel_size=kernel_size,
strides=strides, padding=padding)
# batch norm layer
self.bn = layers.BatchNormalization()
def call(self, input_tensor, training=False):
x = self.conv(input_tensor)
x = self.bn(x, training=training)
return tf.nn.relu(x)
vision_model = keras.applications.DenseNet121(
input_shape=(224,224,3),
include_top = False,
weights='imagenet')
# Control freeze and unfreeze over blocks
def set_freeze(block, unfreeze):
for layer in block:
layer.trainable = unfreeze
block_1 = vision_model.layers[:7]
block_2 = vision_model.layers[7:53]
block_3 = vision_model.layers[53:141]
block_4 = vision_model.layers[141:313]
block_5 = vision_model.layers[313:]
set_freeze(block_1, unfreeze=False)
set_freeze(block_2, unfreeze=False)
for i, layer in enumerate(vision_model.layers):
print(i,'t',layer.trainable,'t :',layer.name)
layer_names = ['conv3_block12_concat', 'conv4_block24_concat', 'conv5_block16_concat']
vision_model_outputs = [vision_model.get_layer(name).output for name in layer_names]
custom_0 = ConvBlock()(vision_model_outputs[0])
custom_1 = ConvBlock()(layers.UpSampling2D(2)(vision_model_outputs[1]))
cat_layer = layers.concatenate([custom_0, custom_1])
last_conv_num = 2
custom_2 = layers.UpSampling2D(4)(vision_model_outputs[2])
outputs = layers.concatenate([ConvBlock()(cat_layer) for i in range(last_conv_num)] [custom_2])
model = models.Model(vision_model.input, outputs)
keras.utils.plot_model(model, "./Model_structure.png", show_shapes=True)
Запустите код, и вы увидите block1
, что и block2
заморожены,
Поскольку график полной модели длинный, я просто публикую несколько его фрагментов:
Комментарии:
1. Больше, чем я ожидал. Спасибо. 🙂
2. Рад помочь 🙂