无法将ResNet50预训练模型从Tensorflow 1.15加载到Tensorflow 2.4



我有一个经过微调的ResNet50模型,如下所示

def get_model_RES(img_width, img_height, img_channels, num_classes, name_weight = None):
from keras.applications.resnet50 import ResNet50
base_model = ResNet50(include_top=False, weights='imagenet', input_tensor=None,
input_shape=(img_width, img_height, img_channels), pooling='avg',
classes=num_classes)
x = base_model.output
x = Dense(256)(x)
x = BatchNormalization()(x)
x = Activation('relu')(x)
x = Dense(num_classes, activation='softmax')(x)
model = Model(inputs=base_model.input, outputs=x)
if name_weight != None:
model.load_weights(name_weight)
print('load Resnet done!')
return model

我使用Tensorflow/Keras 1.15训练了这个模型,并且在训练后我已经保存了模型权重。今天,我将Tensorflow和Keras升级到2.4。然而,当我使用这个精确微调的ResNet50模型加载权重时,我会收到一个ValueError

File "D:lst_model.py", line 41, in get_model_RES
model.load_weights(name_weight)
File "C:UsersICDSP-TRONGAnaconda3envstf_gpu_v2libsite-packagestensorflowpythonkerasenginetraining.py", line 2234, in load_weights
hdf5_format.load_weights_from_hdf5_group(f, self.layers)
File "C:UsersICDSP-TRONGAnaconda3envstf_gpu_v2libsite-packagestensorflowpythonkerassavinghdf5_format.py", line 710, in load_weights_from_hdf5_group
K.batch_set_value(weight_value_tuples)
File "C:UsersICDSP-TRONGAnaconda3envstf_gpu_v2libsite-packagestensorflowpythonutildispatch.py", line 201, in wrapper
return target(*args, **kwargs)
File "C:UsersICDSP-TRONGAnaconda3envstf_gpu_v2libsite-packagestensorflowpythonkerasbackend.py", line 3706, in batch_set_value
x.assign(np.asarray(value, dtype=dtype(x)))
File "C:UsersICDSP-TRONGAnaconda3envstf_gpu_v2libsite-packagestensorflowpythonopsresource_variable_ops.py", line 891, in assign
(tensor_name, self._shape, value_tensor.shape))
ValueError: Cannot assign to variable conv3_block1_0_conv/kernel:0 due to variable shape (1, 1, 256, 512) and value shape (512, 128, 1, 1) are incompatible

我猜Tensorflow/Keras在2.4版本中更改了ResNet 50架构。那么,我如何在版本1中重用预先训练的模型权重呢?非常感谢。

我发现的一个可能的解决方案是重用Keras团队在Github上编写的resnet50.py文件https://github.com/keras-team/keras-applications/blob/master/keras_applications/resnet50.py在更改了几行代码后,我有了

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import os
import warnings
import keras
WEIGHTS_PATH = ('https://github.com/fchollet/deep-learning-models/'
'releases/download/v0.2/'
'resnet50_weights_tf_dim_ordering_tf_kernels.h5')
WEIGHTS_PATH_NO_TOP = ('https://github.com/fchollet/deep-learning-models/'
'releases/download/v0.2/'
'resnet50_weights_tf_dim_ordering_tf_kernels_notop.h5')
backend = None
layers = None
models = None
keras_utils = None

def identity_block(input_tensor, kernel_size, filters, stage, block):
filters1, filters2, filters3 = filters
bn_axis = 3
conv_name_base = 'res' + str(stage) + block + '_branch'
bn_name_base = 'bn' + str(stage) + block + '_branch'
x = keras.layers.Conv2D(filters1, (1, 1),
kernel_initializer='he_normal',
name=conv_name_base + '2a')(input_tensor)
x = keras.layers.BatchNormalization(axis=bn_axis, name=bn_name_base + '2a')(x)
x = keras.layers.Activation('relu')(x)
x = keras.layers.Conv2D(filters2, kernel_size,
padding='same',
kernel_initializer='he_normal',
name=conv_name_base + '2b')(x)
x = keras.layers.BatchNormalization(axis=bn_axis, name=bn_name_base + '2b')(x)
x = keras.layers.Activation('relu')(x)
x = keras.layers.Conv2D(filters3, (1, 1),
kernel_initializer='he_normal',
name=conv_name_base + '2c')(x)
x = keras.layers.BatchNormalization(axis=bn_axis, name=bn_name_base + '2c')(x)
x = keras.layers.add([x, input_tensor])
x = keras.layers.Activation('relu')(x)
return x

def conv_block(input_tensor, kernel_size, filters, stage, block, strides=(2, 2)):
filters1, filters2, filters3 = filters
bn_axis = 3
conv_name_base = 'res' + str(stage) + block + '_branch'
bn_name_base = 'bn' + str(stage) + block + '_branch'
x = keras.layers.Conv2D(filters1, (1, 1), strides=strides,
kernel_initializer='he_normal',
name=conv_name_base + '2a')(input_tensor)
x = keras.layers.BatchNormalization(axis=bn_axis, name=bn_name_base + '2a')(x)
x = keras.layers.Activation('relu')(x)
x = keras.layers.Conv2D(filters2, kernel_size, padding='same',
kernel_initializer='he_normal',
name=conv_name_base + '2b')(x)
x = keras.layers.BatchNormalization(axis=bn_axis, name=bn_name_base + '2b')(x)
x = keras.layers.Activation('relu')(x)
x = keras.layers.Conv2D(filters3, (1, 1),
kernel_initializer='he_normal',
name=conv_name_base + '2c')(x)
x = keras.layers.BatchNormalization(axis=bn_axis, name=bn_name_base + '2c')(x)
shortcut = keras.layers.Conv2D(filters3, (1, 1), strides=strides,
kernel_initializer='he_normal',
name=conv_name_base + '1')(input_tensor)
shortcut = keras.layers.BatchNormalization(
axis=bn_axis, name=bn_name_base + '1')(shortcut)
x = keras.layers.add([x, shortcut])
x = keras.layers.Activation('relu')(x)
return x

def ResNet50(include_top=True, weights='imagenet', input_tensor=None, input_shape=None, pooling=None, classes=1000):
if not (weights in {'imagenet', None} or os.path.exists(weights)):
raise ValueError('The `weights` argument should be either '
'`None` (random initialization), `imagenet` '
'(pre-training on ImageNet), '
'or the path to the weights file to be loaded.')
if weights == 'imagenet' and include_top and classes != 1000:
raise ValueError('If using `weights` as `"imagenet"` with `include_top`'
' as true, `classes` should be 1000')
if input_tensor is None:
img_input = keras.layers.Input(shape=input_shape)
else:
if not backend.is_keras_tensor(input_tensor):
img_input = keras.layers.Input(tensor=input_tensor, shape=input_shape)
else:
img_input = input_tensor
bn_axis = 3

x = keras.layers.ZeroPadding2D(padding=(3, 3), name='conv1_pad')(img_input)
x = keras.layers.Conv2D(64, (7, 7),
strides=(2, 2),
padding='valid',
kernel_initializer='he_normal',
name='conv1')(x)
x = keras.layers.BatchNormalization(axis=bn_axis, name='bn_conv1')(x)
x = keras.layers.Activation('relu')(x)
x = keras.layers.ZeroPadding2D(padding=(1, 1), name='pool1_pad')(x)
x = keras.layers.MaxPooling2D((3, 3), strides=(2, 2))(x)
x = conv_block(x, 3, [64, 64, 256], stage=2, block='a', strides=(1, 1))
x = identity_block(x, 3, [64, 64, 256], stage=2, block='b')
x = identity_block(x, 3, [64, 64, 256], stage=2, block='c')
x = conv_block(x, 3, [128, 128, 512], stage=3, block='a')
x = identity_block(x, 3, [128, 128, 512], stage=3, block='b')
x = identity_block(x, 3, [128, 128, 512], stage=3, block='c')
x = identity_block(x, 3, [128, 128, 512], stage=3, block='d')
x = conv_block(x, 3, [256, 256, 1024], stage=4, block='a')
x = identity_block(x, 3, [256, 256, 1024], stage=4, block='b')
x = identity_block(x, 3, [256, 256, 1024], stage=4, block='c')
x = identity_block(x, 3, [256, 256, 1024], stage=4, block='d')
x = identity_block(x, 3, [256, 256, 1024], stage=4, block='e')
x = identity_block(x, 3, [256, 256, 1024], stage=4, block='f')
x = conv_block(x, 3, [512, 512, 2048], stage=5, block='a')
x = identity_block(x, 3, [512, 512, 2048], stage=5, block='b')
x = identity_block(x, 3, [512, 512, 2048], stage=5, block='c')
if include_top:
x = keras.layers.GlobalAveragePooling2D(name='avg_pool')(x)
x = keras.layers.Dense(classes, activation='softmax', name='fc1000')(x)
else:
if pooling == 'avg':
x = keras.layers.GlobalAveragePooling2D()(x)
elif pooling == 'max':
x = keras.layers.GlobalMaxPooling2D()(x)
else:
warnings.warn('The output shape of `ResNet50(include_top=False)` '
'has been changed since Keras 2.2.0.')
inputs = img_input
# Create model.
model = keras.models.Model(inputs, x, name='resnet50')
return model

那么我就可以成功地加载我的预训练模型。

最新更新