A级课程--- 从零开始(一)---keras实现 VGG (含完整代码)

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格式。
 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

计算机视觉-Archer

图像分割没有团队的同学可加群

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值