将.caffemodel转换为keras h5

时间:2018-02-03 13:58:44

标签: machine-learning deep-learning keras caffe

我想使用我自己的数据集对使用caffe训练的性别检测器进行微调。通过使用大约五十万个面部图像来训练该模型。他们对在ImageNet上预训练的VGG16进行了微调。我想使用这个模型作为我的基本模型。我从这个链接下载了gender.caffemodel文件:

IMDB-Wiki

我使用了以下链接中提供的工具将此模型转换为要在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,具有完全相同的架构,除了最后一层。这就是为什么我只是复制所有层的权重,除了最后一层。我做错了什么?

1 个答案:

答案 0 :(得分:0)

在我看来,weights_list只包含包含权重的图层,通常它只有16层,因为VGG16有16层包含权重。但是model.layers的范围是0到N,这里N大于16,因为model.layers包含不包含权重的层,例如relu layer,padding_layer和max_pooling layer,等等。