keras-cn
keras-cn copied to clipboard
keras-cn文档中“面向小数据集构建图像分类模型”,‘在预训练的网络上fine-tune’部分出现错误
错误:
将vgg16最后一个卷积块前的卷积层参数冻结,原文为:
for layer in model.layers[:25]: layer.trainable = False
应该为:
for layer in model.layers[:15]: layer.trainable = False
你好,关于这部分,我一直看的很模糊,感觉作者的应用实例文档都写的很随便,又没有完整的源码参考。我觉得这里应该是25没错,可以看作者的参考图,conv block1,2,3,4都是frozen的,这刚好是25层。但是后面我还是遇到了一些问题,源码中的top_model.load_weights(top_model_weights_path),这个“ top_model_weights_path”在哪里?还有替换了vgg16后面的Flatten层,vgg16-weights的时候,会有层数不一致的问题,请问你遇到了吗?要不加个QQ,309884616,一起学习
@guohuifengby 1、我看的conv block1,2,3,4是14层。 2、top_model_weights_path是model.save_weights('bottleneck_fc_model.h5')存的h5文件。 3、可以在vgg16的基础上去掉全连接层,再加上自己的全连接层,手动载入权重。
这里不能插图吗,我导出了vgg-16的网络结构图,其实是跟代码对应的,他的意思应该是一行代码就算一层。而且你也可以导入权重的时候测试一下,如果网络不匹配的话,也会报错,报错提示说37层的vgg-16与你当前网络的layer不匹配,其实也跟文中作者的插图和训练效果一致。最后用猫狗大赛的数据集,5K猫和5K狗当训练集,1K猫和1K狗当测试集。25个epoch 跑到了95%。
model.add(ZeroPadding2D((1,1),input_shape=(3,224,224))) #block 1
model.add(Convolution2D(64, 3, 3, activation='relu'))
model.add(ZeroPadding2D((1,1)))
model.add(Convolution2D(64, 3, 3, activation='relu'))
model.add(MaxPooling2D((2,2), strides=(2,2)))
model.add(ZeroPadding2D((1,1))) #block 2
model.add(Convolution2D(128, 3, 3, activation='relu'))
model.add(ZeroPadding2D((1,1)))
model.add(Convolution2D(128, 3, 3, activation='relu'))
model.add(MaxPooling2D((2,2), strides=(2,2)))
model.add(ZeroPadding2D((1,1))) #block 3
model.add(Convolution2D(256, 3, 3, activation='relu'))
model.add(ZeroPadding2D((1,1)))
model.add(Convolution2D(256, 3, 3, activation='relu'))
model.add(ZeroPadding2D((1,1)))
model.add(Convolution2D(256, 3, 3, activation='relu'))
model.add(MaxPooling2D((2,2), strides=(2,2)))
model.add(ZeroPadding2D((1,1))) #block 4
model.add(Convolution2D(512, 3, 3, activation='relu'))
model.add(ZeroPadding2D((1,1)))
model.add(Convolution2D(512, 3, 3, activation='relu'))
model.add(ZeroPadding2D((1,1)))
model.add(Convolution2D(512, 3, 3, activation='relu'))
model.add(MaxPooling2D((2,2), strides=(2,2))) #25layer
model.add(ZeroPadding2D((1,1)))
model.add(Convolution2D(512, 3, 3, activation='relu'))
model.add(ZeroPadding2D((1,1)))
model.add(Convolution2D(512, 3, 3, activation='relu'))
model.add(ZeroPadding2D((1,1)))
model.add(Convolution2D(512, 3, 3, activation='relu'))
model.add(MaxPooling2D((2,2), strides=(2,2)))
model.add(Flatten())
model.add(Dense(4096, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(4096, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(1000, activation='softmax'))
@guohuifengby 我对网络进行冻结时,会让vgg输出其网络层数及名称,此时没有把ZeroPadding2D当做一层来显示,我用的application里面的vgg16. model = VGG16(weights='imagenet', include_top=False)
哦,我是如下加载。
model = VGG_16('vgg16_weights.h5')
此外还有个问题请不吝赐教。
例如说,我要用vgg-16来训练自己的数据集,我的数据集可能有200多分类,部分会与vgg-16有交集。比如说其中有一类是狗,没有细分,就是狗。但是vgg-16里面有细分,阿拉斯加犬,金毛犬等等,这样训练成功后,识别一只狗,识别结果是我数据集的标签狗,还是vgg-16里面标签的什么犬?关于训练自己数据集后的标签合并这一快比较困惑,求赐教。
@guohuifengby 看来你不太理解采用vgg预训练的目的哦。 我们的自己的分类标签与vgg的分类标签没有太大关系的(也就是说,我们只是用了他的权重,标签我们可以根据自己的数据自定义,比如我们也可以拿vgg来分类人的国籍,及时vgg里面没有这个类别。)所以,你分类标签是狗,就行了,不用和vgg里面一样。 我们只是用他的权值来初始化自定义模型的权值,重新送入我们的数据和标签,重新训练模型。 (当然,如果你直接用vgg的模型predict,那标签就要和vgg的一样了。)
我可以说茅塞顿开吗,非常以及相当感谢,哈哈
@guohuifengby 相互学习,共同进步。
加个微信,309884616,以后可以及时交流