我想使用我自己的数据集对在Caffe中训练的性别检测器进行微调。这个模型是使用大约五十万张人脸图像训练的。他们对在ImageNet上预训练的VGG16进行了微调。我想使用这个模型作为我的基础模型。我从以下链接下载了gender.caffemodel文件:
我使用以下链接提供的工具将此模型转换为在Keras中使用的h5文件:
https://github.com/pierluigiferrari/caffe_weight_converter
这个工具只转换权重。我想使用Keras来训练我的模型。因此,我这样定义VGG-16架构:
tmp_model = Sequential()tmp_model.add(ZeroPadding2D((1,1),input_shape=(224, 224, 3)))tmp_model.add(Convolution2D(64, 3, 3, activation='relu'))tmp_model.add(ZeroPadding2D((1,1)))tmp_model.add(Convolution2D(64, 3, 3, activation='relu'))tmp_model.add(MaxPooling2D((2,2), strides=(2,2)))tmp_model.add(ZeroPadding2D((1,1)))tmp_model.add(Convolution2D(128, 3, 3, activation='relu'))tmp_model.add(ZeroPadding2D((1,1)))tmp_model.add(Convolution2D(128, 3, 3, activation='relu'))tmp_model.add(MaxPooling2D((2,2), strides=(2,2)))tmp_model.add(ZeroPadding2D((1,1)))tmp_model.add(Convolution2D(256, 3, 3, activation='relu'))tmp_model.add(ZeroPadding2D((1,1)))tmp_model.add(Convolution2D(256, 3, 3, activation='relu'))tmp_model.add(ZeroPadding2D((1,1)))tmp_model.add(Convolution2D(256, 3, 3, activation='relu'))tmp_model.add(MaxPooling2D((2,2), strides=(2,2)))tmp_model.add(ZeroPadding2D((1,1)))tmp_model.add(Convolution2D(512, 3, 3, activation='relu'))tmp_model.add(ZeroPadding2D((1,1)))tmp_model.add(Convolution2D(512, 3, 3, activation='relu'))tmp_model.add(ZeroPadding2D((1,1)))tmp_model.add(Convolution2D(512, 3, 3, activation='relu'))tmp_model.add(MaxPooling2D((2,2), strides=(2,2)))tmp_model.add(ZeroPadding2D((1,1)))tmp_model.add(Convolution2D(512, 3, 3, activation='relu'))tmp_model.add(ZeroPadding2D((1,1)))tmp_model.add(Convolution2D(512, 3, 3, activation='relu'))tmp_model.add(ZeroPadding2D((1,1)))tmp_model.add(Convolution2D(512, 3, 3, activation='relu'))tmp_model.add(MaxPooling2D((2,2), strides=(2,2)))tmp_model.add(Flatten())tmp_model.add(Dense(4096, activation='relu'))tmp_model.add(Dropout(0.5))tmp_model.add(Dense(4096, activation='relu'))tmp_model.add(Dropout(0.5))tmp_model.add(Dense(2, activation='softmax'))tmp_model.load_weights('/home/gender.h5')
这段代码成功加载了权重。现在我想使用这个模型的权重来微调另一个网络,用于其他分类任务,类别数量不同。由于tmp_model中的类别数量与新模型不同,我将tmp_model的权重复制到新模型的层中,除了最后一层,即softmax层。新模型的代码与tmp_model完全相同,只是最后一层不同。现在我所做的,是将tmp_model的权重逐层复制到新模型中:
for i, weights in enumerate(weights_list[0:31]): model.layers[i].set_weights(weights)
问题就出现在这里。当我运行代码时,出现了以下错误:
ValueError: You called `set_weights(weights)` on layer "zero_padding2d_14" with a weight list of length 3, but the layer was expecting 0 weights. Provided weights: [[[[ 0.27716994 0.05686508 0.0098957 ... -0.055...
正如我所说,tmp_model和model具有完全相同的架构,除了最后一层。这就是为什么我只是复制所有层的权重,除了最后一层。我做错了什么?
回答:
在我看来,weights_list只包括包含权重的层,通常它只有16层,因为VGG16有16个包含权重的层。但model.layers的范围是从0到N,这里N大于16,因为model.layers包括不包含权重的层,比如relu层、padding层和max_pooling层等等。