keras 在对提取的影像网模型进行微调时如何应用正则化

rxztt3cl  于 2022-11-13  发布在  其他
关注(0)|答案(3)|浏览(177)

微调的一种方法是提取一个模型(如在Imagenet上训练的VGG16),添加一个层,然后训练模型。
除了使用Tensorflow.Keras添加的层之外,是否可以对模型层应用正则化?我认为仅对一个层添加正则化不会对结果产生太大影响。
我知道我们可以对添加的层应用正则化:

x = Dense(classes, kernel_regularizer=l2(reg), name="labels")(x)

但是在Keras中是否也可以对其他层应用正则化?在mxnet中可以很容易地完成。
会感激任何帮助。

svgewumm

svgewumm1#

这个解决方案应该可以工作。通过迭代模型层,我们可以只添加一个正则化器。然后你可以添加你的密集层。

model = tf.keras.applications.VGG16(include_top=False, weights=None)
regularizer = tf.keras.regularizers.l2(0.001)

for i in range(len(model.layers)):
    if isinstance(model.layers[i], tf.keras.layers.Conv2D):
        print('Adding regularizer to layer {}'.format(model.layers[i].name))
        model.layers[i].kernel_regularizer = regularizer

# Add Dense layer
classes = 10
x = model.output
x = Dense(classes, kernel_regularizer=regularizer, name="labels")(x)

model = tf.keras.Model(model.input, x)
vc6uscn9

vc6uscn92#

不幸的是,@DMolony的答案不会更新图形,这意味着您的模型将不会对更改的图层应用正则化。
您可以检查model.losses来检查是否正确更新了loss。运行@DMolony的代码片段:

import tensorflow as tf

model = tf.keras.applications.VGG16(include_top=False, weights=None)
regularizer = tf.keras.regularizers.l2(0.001)
print(f'model.losses (original): {model.losses}')

for i in range(len(model.layers)):
  if isinstance(model.layers[i], tf.keras.layers.Conv2D):
    print('Adding regularizer to layer {}'.format(model.layers[i].name))
    model.layers[i].kernel_regularizer = regularizer
print(f'model.losses (after setting reg): {model.losses}')

# Add Dense layer
classes = 10
x = model.output
x = tf.keras.layers.Dense(
    classes, kernel_regularizer=regularizer, name='labels')(
        x)

model = tf.keras.Model(model.input, x)
print(f'model.losses (after adding dense): {model.losses}')

我们看到,新的正则化损失没有添加到模型中:

model.losses (original): []
Adding regularizer to layer block1_conv1
Adding regularizer to layer block1_conv2
...
Adding regularizer to layer block5_conv3
model.losses (after setting reg): []
model.losses (after adding dense): [<tf.Tensor: shape=(), dtype=float32, numpy=0.019377343>]

如果要更新图形,需要1)保存更新后的模型配置,2)保存当前权重,3)在添加正则化器后重新加载配置和权重:

import os
import tempfile
import tensorflow as tf

model = tf.keras.applications.VGG16(include_top=False, weights=None)
regularizer = tf.keras.regularizers.l2(0.001)
print(f'model.losses (original): {model.losses}')

for layer in model.layers:
  if isinstance(layer, tf.keras.layers.Conv2D) and hasattr(layer, 'kernel_regularizer'):
    print('\tAdding regularizer to layer {}'.format(layer.name))
    setattr(layer, 'kernel_regularizer', regularizer)
print(f'model.losses (after setting reg): {model.losses}')

# Add Dense layer
classes = 10
x = model.output
x = tf.keras.layers.Dense(
    classes, kernel_regularizer=regularizer, name='labels')(
        x)

model = tf.keras.Model(model.input, x)
print(f'model.losses (after adding dense): {model.losses}')

tmp_weights_dir = tempfile.gettempdir()
tmp_weights_path = os.path.join(tmp_weights_dir, 'tmp_weights.h5')

# Save model config and weights and reload the model from these values.
model_json = model.to_json()
model.save_weights(tmp_weights_path)
model = tf.keras.models.model_from_json(model_json)
model.load_weights(tmp_weights_path, by_name=True)
print(f'model.losses (after reloading):')
loss_str = '\n'.join(['\t' + str(loss) for loss in model.losses])
print(loss_str)

现在,模型中的损耗可用:

odel.losses (original): []
    Adding regularizer to layer block1_conv1
    Adding regularizer to layer block1_conv2
    Adding regularizer to layer block2_conv1
    Adding regularizer to layer block2_conv2
    Adding regularizer to layer block3_conv1
    Adding regularizer to layer block3_conv2
    Adding regularizer to layer block3_conv3
    Adding regularizer to layer block4_conv1
    Adding regularizer to layer block4_conv2
    Adding regularizer to layer block4_conv3
    Adding regularizer to layer block5_conv1
    Adding regularizer to layer block5_conv2
    Adding regularizer to layer block5_conv3
model.losses (after setting reg): []
model.losses (after adding dense): [<tf.Tensor: shape=(), dtype=float32, numpy=0.019144716>]
model.losses (after reloading):
    tf.Tensor(0.0058215745, shape=(), dtype=float32)
    tf.Tensor(0.06401116, shape=(), dtype=float32)
    tf.Tensor(0.08538648, shape=(), dtype=float32)
    tf.Tensor(0.12775433, shape=(), dtype=float32)
    tf.Tensor(0.17033958, shape=(), dtype=float32)
    tf.Tensor(0.2565217, shape=(), dtype=float32)
    tf.Tensor(0.25641307, shape=(), dtype=float32)
    tf.Tensor(0.34119228, shape=(), dtype=float32)
    tf.Tensor(0.5120113, shape=(), dtype=float32)
    tf.Tensor(0.51162773, shape=(), dtype=float32)
    tf.Tensor(0.5116309, shape=(), dtype=float32)
    tf.Tensor(0.5124292, shape=(), dtype=float32)
    tf.Tensor(0.5116511, shape=(), dtype=float32)
    tf.Tensor(0.019144716, shape=(), dtype=float32)
rekjcdws

rekjcdws3#

实际上有一个解决方案,而不需要重新加载模型图及其权重!
您可以利用带有Layer.add_loss示例方法的公共kerasapi,它将自动为您跟踪依赖关系。
我用这个API更新了这个例子:

import tensorflow as tf

model = tf.keras.applications.VGG16(include_top=False, weights=None)
regularizer = tf.keras.regularizers.l2(1e-3)
print('\nmodel.losses (original): \n', model.losses)

for lyr in model.layers:
  if isinstance(lyr, tf.keras.layers.Conv2D):
    print(f'Adding regularizer to layer {lyr.name}')
    lyr.add_loss(lambda x=lyr.kernel: regularizer(x))
print('\nmodel.losses (after setting reg): \n', model.losses)

# Add Dense layer
classes = 10
x = model.output
x = tf.keras.layers.Dense(
    classes, kernel_regularizer=regularizer, name='labels')(x)

model = tf.keras.Model(model.input, x)
print('\nmodel.losses (after adding dense): \n', model.losses)

相关问题