https://www.bilibili.com/video/av41228356
分类任务
1 网络结构分析
输入:(224x224x3)
->两个(卷积层+relu) (224x224x64)
->一个最大池化, 两个卷积+relu (112x112x128)
->一个最大池化,三个卷积+relu (56x56x256)
->一个最大池化,三个卷积+relu (28x28x512)
->一个最大池化,三个卷积+relu (14x14x512)
->一个最大池化(7x7x512)
->三个全连接层+relu:前两个是(1x1x4096)维向量,最后一个是输出(1x1x1000)1000个类别
->softmax
一共16层(排除5个maxpoling和一个softmax)
很多conv都是重复的,所以写一个函数来调用
二 代码实现
# -*- coding=utf-8 -*-
# Author: zjc
# Creation Date:19-7-7
from keras.models import Sequential
from keras.layers.core import Flatten, Dropout, Dense
from keras.convolutional import Convolution2D, Maxpooling2D
import cv2
import numpy as np
class vgg(object):
def __init__(self, model_weights):
self.model = model_weights
self.model = Sequential()
self.mean = [103, 93, 116, 79, 123.68] # 这是所有图片的均值,后面对每个输入图片减去均值
# ???不应该是 [103.93, 116.79, 123.68]
def load_img(self, imgurl): # 定义一个加载图像的方法
self.img = cv2.imread(imgurl)
im = cv2.resize(self.img, (224, 224)).astype(np.float32) # 调整大小:传入网络的输入图像需要是224,224,3的
im[:, :, 0] -= self.mean[0] # 每个通道减去对应的均值
im[:, :, 1] -= self.mean[1]
im[:, :, 2] -= self.mean[2]
im = np.expand_dims(im, axis=0) # 添加一个维度, 输入网络的图像应该是4维的[batch, width, height, channels]
return im
def model_add(self, filter=None, isConv=False, isMax=False, input_shape=None):
# 因为有很多重复的卷积,为了不去做重复的工作,设置一个函数用来调用
# filter卷积核的个数, isConv是否是卷积, isMax是否是池化层, input_shape输入形状
if isConv:
if input_shape:
# vgg里面kernel_size都是3x3, 步长都是1x1
self.model.add(Convolution2D(filters=filter, strides=(1, 1), kernel_size=(3, 3),
input_shape=input_shape, activation='relu', padding='same'))
else:
# 在keras里面如果不加下面这种没有input_shape的情况,会报错
self.model.add(Convolution2D(filter=filter, strides=(1, 1), kernel_size=(3, 3),
activation='relu', padding='same'))
if isMax:
# 池化层
self.model.add(Maxpooling2D(pool_size=(2, 2), strides=(2, 2)))
def nn(self):
# 开始搭建神经网络
self.model_add(filter=64, isConv=True,
input_shape=(224, 224, 3)) # 第一层conv:224x224x3--->224x224x64
self.model_add(64, isConv=True) # 第二层conv:224x224x64--->224x224x64
# pooling:224x224x64--->112x112x128
self.model_add(isMax=True)
self.model_add(128, isConv=True) # 第三层conv:112x112x128--->112x112x128
self.model_add(128, isConv=True) # 第四层conv:112x112x128--->112x112x128
# pooling:56x56x256--->56x56x256
self.model_add(isMax=True)
self.model_add(256, isConv=True) # 第五层conv:56x56x256--->56x56x256
self.model_add(256, isConv=True) # 第六层conv:56x56x256--->56x56x256
self.model_add(256, isConv=True) # 第七层conv:56x56x256--->56x56x256
# pooling:56x56x256--->28x28x512
self.model_add(isMax=True)
self.model_add(512, isConv=True) # 第八层conv:28x28x512--->28x28x512
self.model_add(512, isConv=True) # 第九层conv:28x28x512--->28x28x512
self.model_add(512, isConv=True) # 第十层conv:28x28x512--->28x28x512
# pooling:28x28x512--->14x14x512
self.model_add(isMax=True)
self.model_add(512, isConv=True) # 第十一层conv:14x14x512--->14x14x512
self.model_add(512, isConv=True) # 第十二层conv:14x14x512--->14x14x512
self.model_add(512, isConv=True) # 第十三层conv:14x14x512--->14x14x512
# pooling:14x14x512--->7x7x512
self.model_add(isMax=True)
self.model_add(Flatten()) # 特征打平
self.model_add(Dense(4096, activation='relu')) # 全连接层, relu
self.model_add(Dropout(.5)) # 防止过拟合
self.model_add(Dense(4096, activation='relu')) # 全连接层, relu
self.model_add(Dropout(.5)) # 防止过拟合
self.model_add(Dense(1000, activation='softmax')) # 全连接层, softmax激活
self.model.load_weight('model/vgg/vgg16_weights_tf_dim_ordering_tf_kernels.h5') # 加载权重
def pred(self): # 预测
self.nn() # 这里没有添加optimizal优化器,如果是训练需要添加
cls = open('model/vgg/classes.txt') # 把所有类别读出来
lines = cls.readlines() # 逐行读取
cls.close()
img = self.load_img(imgurl) # 读取图片,对图片处理:减去均值
pre = np.argmax(self.model.predict(img)) # 预测图片的1000个类别各自的可能性,然后选取最大值,作为预测结果
self.show_img(lines[pre]) # ???
def show_img(self, test):
cv2.putText(self.img, test, (50, 50), cv2.FONT_HERSHEY_SIMPLEX, .5, (0, 0, 255), 1)
# 文字 内容 位置 字体 字体宽度, 颜色:红色
cv2.imshow('img', self.img)
cv2.waitKey(0)
cv2.destroyAllWindows()
if __name__ == '__main__':
net = vgg(model_weights='vgg16_weights_tf_dim_ordering_tf_kernels.h5')
net.pred('time.jpg')
三 keras模型格式介绍
tensorflow中的模型常常是protobuf格式,这种格式既可以是二进制也可以是文本。
keras模型保存和加载与tensorflow不同,keras中的模型保存和加载往往是保存成hdf5格式。