以下搭建的VGG19模型也像上一回搭建的亚历克斯Net一样,以下搭建的VGG19模型也像上贰次搭建的亚历克斯Net一样

源码地址 https://github.com/stephen-v/tensorflow_vgg_classify

源码地址 https://github.com/stephen-v/tensorflow_vgg_classify

1. VGG介绍

1. VGG介绍

1.1. VGG模型结构

VGG互连网是哈佛大学Visual Geometry
Group团队研究开发搭建,该项目的重中之重指标是验证增加互联网深度能够在肯定程度上增强网络的精度。VGG有5种模型,A-E,个中的E模型VGG19是到位ILSVKoleosC
2015挑战赛使用的模子,并获得了ILSV兰德酷路泽C定位第一名,和分类第贰名的战表。整个经过表明,通过把互联网深度扩张到16-19层确实能够增强网络品质。VGG网络跟在此以前学习的LeNet网络和AlexNet互联网有这几个相似之处,以下搭建的VGG19模型也像上二回搭建的亚历克斯Net一样,分成了多少个大的卷积层,和三个大的全链层,分化的是,VGG的陆个卷积层层数相应扩大了;同时,为了减小网络练习参数的数额,整个卷积网络均选用3X3大小的卷积。

首先来探望原诗歌中VGG网络的5种模型结构。A-E模型均是由七个stage和1个全链层和三个softmax分类层组成,其中各样stege有2个max-pooling层和四个卷积层。每层的卷积核个数从首品级的六10个起来,种种阶段拉长一倍,直到达到5拾三个。

A:是最大旨的模型,八个卷基层,二个全连接层,一共11层。
A-LRN:忽略
B:在A的基础上,在stage1和stage2基础上独家增添了1层3X3卷积层,一共13层。
C:在B的基本功上,在stage3,stage4和stage5基础上个别大增了一层1X1的卷积层,一共16层。
D:在B的底子上,在stage3,stage4和stage5基础上独家大增了一层3X3的卷积层,一共16层。
E:在D的功底上,在stage3,stage4和stage5基础上个别大增了一层3X3的卷积层,一共19层。

模型D是正是时常说的VGG16网络,模型E则为VGG19网络。

威尼斯人娱乐 1

即便如此VGG网络使用的均是3X3的卷积filter,相当的大的压缩了参数个数,但和AlexNet相比起来,参数个数还是万分的多,以模型D为例,每一层的参数个数如下表所示,中国人民解放军总参谋部数个数为1.3亿左右,庞大的参数扩展了磨练的时日,下一章单搭建的VGG19模子仅在CPU上展开磨练,单单三个epoch就要练习8钟头以上!

威尼斯人娱乐 2

固然VGG19有那么多的参数,然而在教练进度中,小编辑发表现VGG要求很少的迭代次数就从头破灭了,那是因为:
一 、深度和小的filter尺寸起到了隐式的规则化作用
二 、一些层的pre-initialisation
如何做pre-initialisation呢?笔者先操练最浅的网络A,然后把A的前八个卷积层和末段全链层的权值当作其余互联网的初步值,未赋值的中间层通过任意初阶化进行练习。那样制止了不佳的权值开头值对于网络练习的震慑,从而加速了没有。

干什么在任何VGG网络中都用的是3X3轻重的filter呢,VGG团队提交了上面包车型客车诠释:
1、3 * 3是小小的的能够捕获上下左右和大旨概念的尺寸。

2、两个3 *
3的卷基层的少数感受野是5X5;多少个3X3的感受野是7X7,能够代表大的filter尺寸。(感受野表示互连网之中的比不上岗位的神经细胞对原图像的感受范围大小,神经元感受野的值越大表示其能接触到的固有图像范围就越大,也意味他大概带有更为全局、语义层次更高的性状;而值越小则表示其所包蕴的特征越趋向于局部和细节。)

3、多个3 *
3的卷基层比1个大尺寸filter卷基层有愈来愈多的非线性,使得判决函数越发具有判决性。

4、多个3 *
3的卷积层比2个大尺寸的filter有更少的参数,如若卷基层的输入和输出的性状图大小一样为C,那么四个3
* 3的卷积层参数个数为\(3(3^2C^2)=27C^2\);一个7 *
7的卷积层参数为\(49C^2\),整整比3 *
3的多了81%。

1.1. VGG模型结构

VGG网络是加州圣巴巴拉分校科业余大学学学Visual Geometry
Group团队研究开发搭建,该项目标最首要指标是验证扩张网络深度能够在一定水平上增强互连网的精度。VGG有5种模型,A-E,其中的E模型VGG19是到位ILSV科雷傲C
二〇一四挑衅赛使用的模子,并获取了ILSVXC60C定位第一名,和分类第贰名的成就。整个经过注解,通过把互联网深度扩充到16-19层确实能够进步网络品质。VGG网络跟在此之前学习的LeNet网络和亚历克斯Net网络有许多相似之处,以下搭建的VGG19模型也像上2回搭建的亚历克斯Net一样,分成了伍个大的卷积层,和一个大的全链层,差异的是,VGG的五个卷积层层数相应扩张了;同时,为了削减网络演习参数的数据,整个卷积网络均选用3X3分寸的卷积。

率先来看望原散文中VGG网络的5种模型结构。A-E模型均是由五个stage和二个全链层和一个softmax分类层组成,个中种种stege有一个max-pooling层和七个卷积层。每层的卷积核个数从首等级的六十三个开始,每种阶段拉长一倍,直到达到5十二个。

A:是最中央的模子,七个卷基层,1个全连接层,一共11层。
A-LRN:忽略
B:在A的根基上,在stage1和stage2基础上分别增添了1层3X3卷积层,一共13层。
C:在B的底蕴上,在stage3,stage4和stage5基础上个别大增了一层1X1的卷积层,一共16层。
D:在B的基本功上,在stage3,stage4和stage5基础上独家大增了一层3X3的卷积层,一共16层。
E:在D的功底上,在stage3,stage4和stage5基础上分别扩张了一层3X3的卷积层,一共19层。

模型D是正是隔三差五说的VGG16互联网,模型E则为VGG19互联网。

威尼斯人娱乐 3

就算如此VGG网络使用的均是3X3的卷积filter,一点都不小的缩小了参数个数,但和亚历克斯Net比较起来,参数个数还是相当的多,以模型D为例,每一层的参数个数如下表所示,中国人民解放军总参谋部数个数为1.3亿左右,庞大的参数增添了磨炼的年华,下一章单搭建的VGG19模子仅在CPU上进行演练,单单2个epoch就要训练8时辰以上!

威尼斯人娱乐 4

固然VGG19有那么多的参数,可是在教练进度中,我发现VGG要求很少的迭代次数就从头破灭了,那是因为:
① 、深度和小的filter尺寸起到了隐式的规则化成效
二 、一些层的pre-initialisation
怎么办pre-initialisation呢?作者先磨练最浅的互连网A,然后把A的前七个卷积层和尾声全链层的权值当作别的互联网的上马值,未赋值的中间层通过任意发轫化进行磨练。这样幸免了不佳的权值起始值对于网络陶冶的熏陶,从而加快了过眼烟云。

何以在全方位VGG网络中都用的是3X3尺寸的filter呢,VGG团队提交了上面包车型大巴解释:
1、3 * 3是极小的能够捕获上下左右和着力概念的尺寸。

2、两个3 *
3的卷基层的星星感受野是5X5;八个3X3的感想野是7X7,能够替代大的filter尺寸。(感受野表示网络之中的不如任务的神经细胞对原图像的感想范围大小,神经元感受野的值越大表示其能接触到的原本图像范围就越大,也意味她恐怕含有更为全局、语义层次更高的风味;而值越小则表示其所富含的表征越趋向于局部和细节。)

3、多个3 *
3的卷基层比一个大尺寸filter卷基层有愈多的非线性,使得判决函数尤其富有判决性。

4、多个3 *
3的卷积层比1个大尺寸的filter有更少的参数,假诺卷基层的输入和输出的风味图大小同等为C,那么多个3
* 3的卷积层参数个数为\(3(3^2C^2)=27C^2\);一个7 *
7的卷积层参数为\(49C^2\),整整比3 *
3的多了81%。

1.2. VGG19架构

先是来看看随想中描述的VGG19的互连网布局图,输入是一张224X224轻重的途达GB图片,在输入图片在此之前,照旧要对图片的每三个像素举行奇骏GB数据的转移和提取。然后利用3X3轻重缓急的卷积核进行卷积,小编在随想中描述了接纳3X3filter的意向:
“we use filters with a very small receptive field: 3 × 3 (which is the
smallest size to capture the notion of left/right, up/down, center).”
即上边提到的“3X3是小小的的能够捕获上下左右和核心概念的尺寸”。接着图片依次通过5个Stage和3层全连层的拍卖,一贯到softmax输出分类。卷积核深度从64一直抓牢到512,更好的领到了图片的特征向量。

威尼斯人娱乐 5

Stage1
包蕴八个卷积层,二个池化层,每一种卷积层和池化层的新闻如下:

卷积核 深度 步长
3 * 3 64 1 * 1

Stage2威尼斯人娱乐,:
包括四个卷积层,三个池化层,每个卷积层和池化层的音信如下:

卷积核 深度 步长
3 * 3 128 1 * 1

Stage3
含蓄八个卷积层,一个池化层,各样卷积层和池化层的新闻如下:

卷积核 深度 步长
3 * 3 256 1 * 1

Stage4
富含四个卷积层,八个池化层,每一种卷积层和池化层的音讯如下:

卷积核 深度 步长
3 * 3 512 1 * 1

Stage5
带有多个卷积层,几个池化层,每种卷积层和池化层的音信如下:

卷积核 深度 步长
3 * 3 512 1 * 1

池化层
方方面面网络包罗5个池化层,分别位于每3个Stage的末尾,每种池化层的尺寸均一致,如下:

池化层过滤器 步长
2 * 2 2 * 2

对此其余的隐藏层,笔者在散文中做了之类阐释:
“All hidden layers are equipped with the rectification (ReLU (Krizhevsky
et al., 2012)) non-linearity.We note that none of our networks (except
for one) contain Local Response Normalisation(LRN) normalisation
(Krizhevsky et al., 2012): as will be shown in Sect. 4, such
normalisation does not improve the performance on the ILSVRC dataset,
but leads to increased memory consumption and computation time. ”

整套网络不含有L大切诺基N,因为LPRADON会占用内部存款和储蓄器和充实计算时间。接着经过贰个全链层的拍卖,由Softmax输出一千个系列的归类结果。

1.2. VGG19架构

率先来探视故事集中讲述的VGG19的互联网布局图,输入是一张224X22伍分寸的揽胜极光GB图片,在输入图片此前,依然要对图片的每1个像素进行宝马7系GB数据的变换和提取。然后采纳3X3高低的卷积核举行卷积,作者在舆论中描述了运用3X3filter的意向:
“we use filters with a very small receptive field: 3 × 3 (which is the
smallest size to capture the notion of left/right, up/down, center).”
即上面提到的“3X3是十分小的能够捕获上下左右和基本概念的尺寸”。接着图片依次通过多少个Stage和3层全连层的处理,向来到softmax输出分类。卷积核深度从64直接加强到512,更好的领到了图片的特征向量。

威尼斯人娱乐 6

Stage1
含蓄五个卷积层,四个池化层,各样卷积层和池化层的新闻如下:

卷积核 深度 步长
3 * 3 64 1 * 1

Stage2
富含三个卷积层,3个池化层,每一个卷积层和池化层的音讯如下:

卷积核 深度 步长
3 * 3 128 1 * 1

Stage3
带有多个卷积层,三个池化层,每一个卷积层和池化层的音讯如下:

卷积核 深度 步长
3 * 3 256 1 * 1

Stage4
饱含三个卷积层,一个池化层,每一种卷积层和池化层的音信如下:

卷积核 深度 步长
3 * 3 512 1 * 1

Stage5
包涵多个卷积层,一个池化层,每一个卷积层和池化层的音讯如下:

卷积核 深度 步长
3 * 3 512 1 * 1

池化层
全方位网络包含八个池化层,分别位于每二个Stage的末尾,每一种池化层的尺寸均一致,如下:

池化层过滤器 步长
2 * 2 2 * 2

对于其他的隐藏层,小编在舆论中做了之类阐释:
“All hidden layers are equipped with the rectification (ReLU (Krizhevsky
et al., 2012)) non-linearity.We note that none of our networks (except
for one) contain Local Response Normalisation(LRN) normalisation
(Krizhevsky et al., 2012): as will be shown in Sect. 4, such
normalisation does not improve the performance on the ILSVRC dataset,
but leads to increased memory consumption and computation time. ”

整整互连网不包罗L普拉多N,因为LLX570N会占用内部存款和储蓄器和充实总计时间。接着经过三个全链层的拍卖,由Softmax输出一千个档次的归类结果。

2. 用Tensorflow搭建VGG19网络

VGG团队一度用Tensorflow搭建好了VGG16和VGG19网络,在运用他们的网络前,你供给下载已经锻练好的参数文件vgg19.npy,下载地址为:https://mega.nz/#!xZ8glS6J!MAnE91ND_WyfZ_8mvkuSa2YcA7q-1ehfSm-Q1fxOvvs
。原版的VGG16/19模子代码在 https://github.com/machrisaa/tensorflow-vgg
(该模型中涉嫌的weights文件已不可用),
我们依据该模型代码对VGG19互联网做了部分微调以适应本人的磨练须求,同时也像上一篇的亚历克斯Net一样,扩充了精调整和磨练练代码,前面会有介绍。

使用Tensorflow来搭建贰个完好无损的VGG19互连网,包蕴小编修改过的成套用了160行代码,如下附上一部分代码,该网络也是VGG团队已经磨炼好了的,你能够拿来直接实行图片识别和归类,不过只要您有其余的图样识别须求,你须要用本人的教练集来磨练1次以博得想要的结果,并储存好和谐的权重文件。

咱们在原版的根基上做了有的变动,增添了入参num_class,该参数代表分类个数,假如您有九十六个类别的图样须求操练,这些值必须设置成100,以此类推。

class Vgg19(object):
    """
    A trainable version VGG19.
    """

    def __init__(self, bgr_image, num_class, vgg19_npy_path=None, trainable=True, dropout=0.5):
        if vgg19_npy_path is not None:
            self.data_dict = np.load(vgg19_npy_path, encoding='latin1').item()
        else:
            self.data_dict = None
        self.BGR_IMAGE = bgr_image
        self.NUM_CLASS = num_class
        self.var_dict = {}
        self.trainable = trainable
        self.dropout = dropout

        self.build()

    def build(self, train_mode=None):

        self.conv1_1 = self.conv_layer(self.BGR_IMAGE, 3, 64, "conv1_1")
        self.conv1_2 = self.conv_layer(self.conv1_1, 64, 64, "conv1_2")
        self.pool1 = self.max_pool(self.conv1_2, 'pool1')

        self.conv2_1 = self.conv_layer(self.pool1, 64, 128, "conv2_1")
        self.conv2_2 = self.conv_layer(self.conv2_1, 128, 128, "conv2_2")
        self.pool2 = self.max_pool(self.conv2_2, 'pool2')

        self.conv3_1 = self.conv_layer(self.pool2, 128, 256, "conv3_1")
        self.conv3_2 = self.conv_layer(self.conv3_1, 256, 256, "conv3_2")
        self.conv3_3 = self.conv_layer(self.conv3_2, 256, 256, "conv3_3")
        self.conv3_4 = self.conv_layer(self.conv3_3, 256, 256, "conv3_4")
        self.pool3 = self.max_pool(self.conv3_4, 'pool3')

        self.conv4_1 = self.conv_layer(self.pool3, 256, 512, "conv4_1")
        self.conv4_2 = self.conv_layer(self.conv4_1, 512, 512, "conv4_2")
        self.conv4_3 = self.conv_layer(self.conv4_2, 512, 512, "conv4_3")
        self.conv4_4 = self.conv_layer(self.conv4_3, 512, 512, "conv4_4")
        self.pool4 = self.max_pool(self.conv4_4, 'pool4')

        self.conv5_1 = self.conv_layer(self.pool4, 512, 512, "conv5_1")
        self.conv5_2 = self.conv_layer(self.conv5_1, 512, 512, "conv5_2")
        self.conv5_3 = self.conv_layer(self.conv5_2, 512, 512, "conv5_3")
        self.conv5_4 = self.conv_layer(self.conv5_3, 512, 512, "conv5_4")
        self.pool5 = self.max_pool(self.conv5_4, 'pool5')

        self.fc6 = self.fc_layer(self.pool5, 25088, 4096, "fc6")
        self.relu6 = tf.nn.relu(self.fc6)
        if train_mode is not None:
            self.relu6 = tf.cond(train_mode, lambda: tf.nn.dropout(self.relu6, self.dropout), lambda: self.relu6)
        elif train_mode:
            self.relu6 = tf.nn.dropout(self.relu6, self.dropout)

        self.fc7 = self.fc_layer(self.relu6, 4096, 4096, "fc7")
        self.relu7 = tf.nn.relu(self.fc7)
        if train_mode is not None:
            self.relu7 = tf.cond(train_mode, lambda: tf.nn.dropout(self.relu7, self.dropout), lambda: self.relu7)
        elif train_mode:
            self.relu7 = tf.nn.dropout(self.relu7, self.dropout)

        self.fc8 = self.fc_layer(self.relu7, 4096, self.NUM_CLASS, "fc8")

        self.prob = tf.nn.softmax(self.fc8, name="prob")

        self.data_dict = None

动用Tenforflow来搭建网络确实代码量相比较大,网上有采纳Keras来搭建的,并且能够不用演练,直接用于图片识别,代码量少,使用简易方便,感兴趣的同学能够去
https://gist.github.com/baraldilorenzo/07d7802847aaad0a35d3#file-vgg-16_keras-py-L24
看看,由于Keras已经昭示了新本子,这一个github上的代码存在有的难点,须要做一些改动,附上本人要好修改好的代码,仅有70多行就足以开始展览利用了。在此之前看了二日Keras的官方document,在动用fit方法磨炼的时候,入参就有epoch的安装,感觉不须要用到for循环,同时,不必要自定义Optimizer和acuuracy,只需点名名字就足以了,简直方便快捷,但是对于怎么把每2个epoch获得的accuracy和loss用接近tensorboard视图的措施体现出来自作者就不太领会了,如有知道的同校,请不吝赐教。

from keras.models import Sequential
from keras.layers.core import Flatten, Dense, Dropout
from keras.layers.convolutional import Conv2D, MaxPooling2D, ZeroPadding2D


def VGG_16(weights_path=None):
    model = Sequential()
    model.add(ZeroPadding2D((1, 1), input_shape=(224, 224, 3)))
    model.add(Conv2D(64, (3, 3), activation='relu'))
    model.add(ZeroPadding2D((1, 1)))
    model.add(Conv2D(64, (3, 3), activation='relu'))
    model.add(MaxPooling2D((2, 2), strides=(2, 2)))

    model.add(ZeroPadding2D((1, 1)))
    model.add(Conv2D(128, (3, 3), activation='relu'))
    model.add(ZeroPadding2D((1, 1)))
    model.add(Conv2D(128, (3, 3), activation='relu'))
    model.add(MaxPooling2D((2, 2), strides=(2, 2)))

    model.add(ZeroPadding2D((1, 1)))
    model.add(Conv2D(256, (3, 3), activation='relu'))
    model.add(ZeroPadding2D((1, 1)))
    model.add(Conv2D(256, (3, 3), activation='relu'))
    model.add(ZeroPadding2D((1, 1)))
    model.add(Conv2D(256, (3, 3), activation='relu'))
    model.add(MaxPooling2D((2, 2), strides=(2, 2)))

    model.add(ZeroPadding2D((1, 1)))
    model.add(Conv2D(512, (3, 3), activation='relu'))
    model.add(ZeroPadding2D((1, 1)))
    model.add(Conv2D(512, (3, 3), activation='relu'))
    model.add(ZeroPadding2D((1, 1)))
    model.add(Conv2D(512, (3, 3), activation='relu'))
    model.add(MaxPooling2D((2, 2), strides=(2, 2)))

    model.add(ZeroPadding2D((1, 1)))
    model.add(Conv2D(512, (3, 3), activation='relu'))
    model.add(ZeroPadding2D((1, 1)))
    model.add(Conv2D(512, (3, 3), activation='relu'))
    model.add(ZeroPadding2D((1, 1)))
    model.add(Conv2D(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'))

    if weights_path:
        model.load_weights(weights_path)

    return model


if __name__ == "__main__":
    im = cv2.resize(cv2.imread('cat.jpg'), (224, 224)).astype(np.float32)
    im[:,:,0] -= 103.939
    im[:,:,1] -= 116.779
    im[:,:,2] -= 123.68
    im = im.transpose((2,0,1))
    im = np.expand_dims(im, axis=0)

    # Test pretrained model
    model = VGG_16('vgg16_weights.h5')
    sgd = SGD(lr=0.1, decay=1e-6, momentum=0.9, nesterov=True)
    model.compile(optimizer=sgd, loss='categorical_crossentropy')
    out = model.predict(im)
    print (np.argmax(out))

2. 用Tensorflow搭建VGG19网络

VGG共青团和少先队现已用Tensorflow搭建好了VGG16和VGG19互连网,在采取他们的网络前,你供给下载已经磨炼好的参数文件vgg19.npy,下载地址为:https://mega.nz/#!xZ8glS6J!MAnE91ND_WyfZ_8mvkuSa2YcA7q-1ehfSm-Q1fxOvvs
。原版的VGG16/19模型代码在 https://github.com/machrisaa/tensorflow-vgg
(该模型中涉及的weights文件已不可用),
我们依照该模型代码对VGG19互联网做了有个别微调以适应本身的教练须求,同时也像上一篇的亚历克斯Net一样,增添了精调整和练习练代码,前边会有介绍。

选拔Tensorflow来搭建二个完好无损的VGG19互联网,包涵笔者修改过的漫天用了160行代码,如下附上一部分代码,该互连网也是VGG团队已经磨练好了的,你能够拿来间接举办图纸识别和归类,然则只要您有其余的图形识别供给,你要求用本身的教练集来磨练1次以赢得想要的结果,并储存好本人的权重文件。

咱俩在原版的根底上做了一部分改动,扩大了入参num_class,该参数代表分类个数,若是你有九十四个体系的图形须求磨练,这些值必须设置成100,以此类推。

class Vgg19(object):
    """
    A trainable version VGG19.
    """

    def __init__(self, bgr_image, num_class, vgg19_npy_path=None, trainable=True, dropout=0.5):
        if vgg19_npy_path is not None:
            self.data_dict = np.load(vgg19_npy_path, encoding='latin1').item()
        else:
            self.data_dict = None
        self.BGR_IMAGE = bgr_image
        self.NUM_CLASS = num_class
        self.var_dict = {}
        self.trainable = trainable
        self.dropout = dropout

        self.build()

    def build(self, train_mode=None):

        self.conv1_1 = self.conv_layer(self.BGR_IMAGE, 3, 64, "conv1_1")
        self.conv1_2 = self.conv_layer(self.conv1_1, 64, 64, "conv1_2")
        self.pool1 = self.max_pool(self.conv1_2, 'pool1')

        self.conv2_1 = self.conv_layer(self.pool1, 64, 128, "conv2_1")
        self.conv2_2 = self.conv_layer(self.conv2_1, 128, 128, "conv2_2")
        self.pool2 = self.max_pool(self.conv2_2, 'pool2')

        self.conv3_1 = self.conv_layer(self.pool2, 128, 256, "conv3_1")
        self.conv3_2 = self.conv_layer(self.conv3_1, 256, 256, "conv3_2")
        self.conv3_3 = self.conv_layer(self.conv3_2, 256, 256, "conv3_3")
        self.conv3_4 = self.conv_layer(self.conv3_3, 256, 256, "conv3_4")
        self.pool3 = self.max_pool(self.conv3_4, 'pool3')

        self.conv4_1 = self.conv_layer(self.pool3, 256, 512, "conv4_1")
        self.conv4_2 = self.conv_layer(self.conv4_1, 512, 512, "conv4_2")
        self.conv4_3 = self.conv_layer(self.conv4_2, 512, 512, "conv4_3")
        self.conv4_4 = self.conv_layer(self.conv4_3, 512, 512, "conv4_4")
        self.pool4 = self.max_pool(self.conv4_4, 'pool4')

        self.conv5_1 = self.conv_layer(self.pool4, 512, 512, "conv5_1")
        self.conv5_2 = self.conv_layer(self.conv5_1, 512, 512, "conv5_2")
        self.conv5_3 = self.conv_layer(self.conv5_2, 512, 512, "conv5_3")
        self.conv5_4 = self.conv_layer(self.conv5_3, 512, 512, "conv5_4")
        self.pool5 = self.max_pool(self.conv5_4, 'pool5')

        self.fc6 = self.fc_layer(self.pool5, 25088, 4096, "fc6")
        self.relu6 = tf.nn.relu(self.fc6)
        if train_mode is not None:
            self.relu6 = tf.cond(train_mode, lambda: tf.nn.dropout(self.relu6, self.dropout), lambda: self.relu6)
        elif train_mode:
            self.relu6 = tf.nn.dropout(self.relu6, self.dropout)

        self.fc7 = self.fc_layer(self.relu6, 4096, 4096, "fc7")
        self.relu7 = tf.nn.relu(self.fc7)
        if train_mode is not None:
            self.relu7 = tf.cond(train_mode, lambda: tf.nn.dropout(self.relu7, self.dropout), lambda: self.relu7)
        elif train_mode:
            self.relu7 = tf.nn.dropout(self.relu7, self.dropout)

        self.fc8 = self.fc_layer(self.relu7, 4096, self.NUM_CLASS, "fc8")

        self.prob = tf.nn.softmax(self.fc8, name="prob")

        self.data_dict = None

行使Tenforflow来搭建网络真的代码量相比大,网上有利用Keras来搭建的,并且能够不用陶冶,直接用来图片识别,代码量少,使用简单方便,感兴趣的同班能够去
https://gist.github.com/baraldilorenzo/07d7802847aaad0a35d3#file-vgg-16_keras-py-L24
看看,由于Keras已经昭示了新本子,那些github上的代码存在有的标题,须要做一些改动,附上本身自个儿修改好的代码,仅有70多行就能够举行应用了。在此之前看了二日Keras的法定document,在行使fit方法操练的时候,入参就有epoch的设置,感觉不需求用到for循环,同时,不必要自定义Optimizer和acuuracy,只需点名名字就能够了,简直方便飞速,不过对于什么把每叁个epoch获得的accuracy和loss用接近tensorboard视图的法子体现出来自小编就不太知道了,如有知道的同学,请不吝赐教。

from keras.models import Sequential
from keras.layers.core import Flatten, Dense, Dropout
from keras.layers.convolutional import Conv2D, MaxPooling2D, ZeroPadding2D


def VGG_16(weights_path=None):
    model = Sequential()
    model.add(ZeroPadding2D((1, 1), input_shape=(224, 224, 3)))
    model.add(Conv2D(64, (3, 3), activation='relu'))
    model.add(ZeroPadding2D((1, 1)))
    model.add(Conv2D(64, (3, 3), activation='relu'))
    model.add(MaxPooling2D((2, 2), strides=(2, 2)))

    model.add(ZeroPadding2D((1, 1)))
    model.add(Conv2D(128, (3, 3), activation='relu'))
    model.add(ZeroPadding2D((1, 1)))
    model.add(Conv2D(128, (3, 3), activation='relu'))
    model.add(MaxPooling2D((2, 2), strides=(2, 2)))

    model.add(ZeroPadding2D((1, 1)))
    model.add(Conv2D(256, (3, 3), activation='relu'))
    model.add(ZeroPadding2D((1, 1)))
    model.add(Conv2D(256, (3, 3), activation='relu'))
    model.add(ZeroPadding2D((1, 1)))
    model.add(Conv2D(256, (3, 3), activation='relu'))
    model.add(MaxPooling2D((2, 2), strides=(2, 2)))

    model.add(ZeroPadding2D((1, 1)))
    model.add(Conv2D(512, (3, 3), activation='relu'))
    model.add(ZeroPadding2D((1, 1)))
    model.add(Conv2D(512, (3, 3), activation='relu'))
    model.add(ZeroPadding2D((1, 1)))
    model.add(Conv2D(512, (3, 3), activation='relu'))
    model.add(MaxPooling2D((2, 2), strides=(2, 2)))

    model.add(ZeroPadding2D((1, 1)))
    model.add(Conv2D(512, (3, 3), activation='relu'))
    model.add(ZeroPadding2D((1, 1)))
    model.add(Conv2D(512, (3, 3), activation='relu'))
    model.add(ZeroPadding2D((1, 1)))
    model.add(Conv2D(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'))

    if weights_path:
        model.load_weights(weights_path)

    return model


if __name__ == "__main__":
    im = cv2.resize(cv2.imread('cat.jpg'), (224, 224)).astype(np.float32)
    im[:,:,0] -= 103.939
    im[:,:,1] -= 116.779
    im[:,:,2] -= 123.68
    im = im.transpose((2,0,1))
    im = np.expand_dims(im, axis=0)

    # Test pretrained model
    model = VGG_16('vgg16_weights.h5')
    sgd = SGD(lr=0.1, decay=1e-6, momentum=0.9, nesterov=True)
    model.compile(optimizer=sgd, loss='categorical_crossentropy')
    out = model.predict(im)
    print (np.argmax(out))

3. 磨炼互连网

就算如此采用磨练好的网络和网络权值能够直接举办归类识别应用,不过本着学习探讨的振奋,大家供给领悟怎样磨练多少以及测试和认证互连网模型。

脚下,大家有项识别火灾的任务(该类型的数据集来自一人挪威教书,他的github地址为:https://github.com/UIA-CAIR/Fire-Detection-Image-Dataset
,他采取的是革新过的VGG16互连网),需求运用VGG19进行操练,而平时模型磨炼要求的正样本和负样本数量要对等,并且数据集越来越多越好,但在这一次磨炼中,全体图片均是我从互连网抓取而来,且磨练集中的fire的图样和non-fire图片是不对等的,分别为223张和445张(原图没有那么多,大家团结增添了有的火灾图片),测试集中的fire图片和non-fire的图样则也正是,均为50张。

对于怎么着取得batch数据,在从前的亚历克斯Net中央银行使的是数码迭代器,在本次磨炼中大家利用Tensorflow的系列来机关获取每一种batch的数目,使用队列能够把图片及相应的价签标准的取出来,同时还自行打乱顺序,分外好使用。由于接纳了tf.train.slice_input_producer成立了文件队列,因而一定要切记,在教练图片的时候需求周转tf.train.start_queue_runners(sess=sess)如此数据才会真正的填充进队列,不然程序将会挂起。
程序代码如下:

import tensorflow as tf

VGG_MEAN = tf.constant([123.68, 116.779, 103.939], dtype=tf.float32)



class ImageDataGenerator(object):
    def __init__(self, images, labels, batch_size, num_classes):
        self.filenames = images
        self.labels = labels
        self.batch_size = batch_size
        self.num_class = num_classes
        self.image_batch, self.label_batch = self.image_decode()


    def image_decode(self):
        # 建立文件队列,把图片和对应的实际标签放入队列中
        #注:在没有运行tf.train.start_queue_runners(sess=sess)之前,数据实际上是没有放入队列中的
        file_queue = tf.train.slice_input_producer([self.filenames, self.labels])

        # 把图片数据转化为三维BGR矩阵
        image_content = tf.read_file(file_queue[0])
        image_data = tf.image.decode_jpeg(image_content, channels=3)
        image = tf.image.resize_images(image_data, [224, 224])
        img_centered = tf.subtract(image, VGG_MEAN)
        img_bgr = img_centered[:, :, ::-1]

        labels = tf.one_hot(file_queue[1],self.num_class, dtype=tf.uint8)

        # 分batch从文件队列中读取数据
        image_batch, label_batch = tf.train.shuffle_batch([img_bgr, labels],
                                                          batch_size=self.batch_size,
                                                          capacity=2000,
                                                          min_after_dequeue=1000)
        return image_batch, label_batch

在精调中,代码和前边的亚历克斯Net大约,只是去掉了自定义的数目迭代器。整个VGG19网络一共操练9陆个epochs,每一个epoch有玖14个迭代,同时选择交叉熵和梯度下跌算法精调VGG19互连网的末段三个全链层fc6,fc7,fc8。衡量网络质量的精确度(Precision)、召回率(Recall)及F1值大家从没应用,简单利用了准确率这一目的。值得注意的是,在磨炼获取数据在此以前,一定要运维tf.train.start_queue_runners(sess=sess),那样才能有限支撑数据真实的填充入文件队列。通过应用Tensorflow的队列存取数据,整个精调代码比亚历克斯Net要言简意赅一些,部分代码如下:

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())

    # 运行队列
    tf.train.start_queue_runners(sess=sess)

    # 把模型图加入TensorBoard
    writer.add_graph(sess.graph)

    # 总共训练100代
    for epoch in range(num_epochs):
        print("{} Epoch number: {} start".format(datetime.now(), epoch + 1))
        # 开始训练每一代
        for step in range(num_iter):
            img_batch = sess.run(training.image_batch)
            label_batch = sess.run(training.label_batch)
            sess.run(train_op, feed_dict={x: img_batch, y: label_batch})

在测试网络品质的时候,在此以前使用的准确率(Accuracy)是不太准备的,首先看准确率计算公式(如下),这些指标有相当大的弱点,在正负样本不平衡的事态下,比如,负样本量不小,尽管超越二分之一号正楷字样本预计正确,所占的百分比也是相比较少的。所以,在总计学中时常使用精确率(Precision)、召回率(Recall)和相互的疏通平均F1值来衡量叁个网络的属性。

准确率(Accuracy)的总括公式为:
\[Accuracy=\frac{TP + TN}{TP + TN + FP
+FN}\]

其中:
True Positive(真正, TP):将正类预测为正类数.
True Negative(真负 , TN):将负类预测为负类数.
False Positive(假正, FP):将负类预测为正类数 →→ 误报 (Type I error).
False Negative(假负 , FN):将正类预测为负类数 →→ 漏报 (Type II error).

精确率(Precision)的计算公式为:
\[Precision=\frac{TP}{TP + FP}\]

召回率(Recall)的总计公式为:
\[Recall=\frac{TP}{TP + FN}\]

两者的调和平均F1:
\[F1=\frac{2TP}{2TP + FP +FN}\]

精确率(Precision)是针对预测结果而言的,它象征的是预测为正的样本中有微微是对的。有两种值,一种正是把正类预测为正类(TP),另一种正是把负类预测为正类(FP)。精确率又叫查准率。
召回率(Recall)是指向原来的样书而言,它代表的是样本中的正例有些许被猜度正确了。也有两种值,一种是把本来的正类预测成正类(TP),另一种正是把原来的正类预测为负类(FN)。召回率又称查全率。
F1为精确率和召回率的排除和消除平均,当二者值较高时,F1值也较高。

测试网络精确度代码如下:

print("{} Start testing".format(datetime.now()))

tp = tn = fn = fp = 0

    for _ in range(num_iter):
        img_batch = sess.run(testing.image_batch)
        label_batch = sess.run(testing.label_batch)
        softmax_prediction = sess.run(score, feed_dict={x: img_batch, y: label_batch})
        prediction_label = sess.run(tf.argmax(softmax_prediction, 1))
        actual_label = sess.run(tf.argmax(label_batch, 1))

        for i in range(len(prediction_label)):
            if prediction_label[i] == actual_label[i] == 1:
                tp += 1
            elif prediction_label[i] == actual_label[i] == 0:
                tn += 1
            elif prediction_label[i] == 1 and actual_label[i] == 0:
                fp += 1
            elif prediction_label[i] == 0 and actual_label[i] == 1:
                fn += 1

    precision = tp / (tp + fp)
    recall = tp / (tp + fn)
    f1 = (2 * tp) / (2 * tp + fp + fn)  # f1为精确率precision和召回率recall的调和平均
    print("{} Testing Precision = {:.4f}".format(datetime.now(), precision))
    print("{} Testing Recall = {:.4f}".format(datetime.now(), recall))
    print("{} Testing F1 = {:.4f}".format(datetime.now(), f1))

通过一天的演练和测试,网络精确度(Precision)为十分六左右,召回率(Recall)为95%,F1值为72.6%。由于图片较少,因而质量指标不是很完美,后续我们跟着改良。
上面开头验证互连网。首先在互联网上任选几张图纸,然后编写代码如下,

class_name = ['not fire', 'fire']


def test_image(path_image, num_class):
    img_string = tf.read_file(path_image)
    img_decoded = tf.image.decode_png(img_string, channels=3)
    img_resized = tf.image.resize_images(img_decoded, [224, 224])
    img_resized = tf.reshape(img_resized, shape=[1, 224, 224, 3])
    model = Vgg19(bgr_image=img_resized, num_class=num_class, vgg19_npy_path='./vgg19.npy')
    score = model.fc8
    prediction = tf.argmax(score, 1)
    saver = tf.train.Saver()
    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())
        saver.restore(sess, "./tmp/checkpoints/model_epoch50.ckpt")
        plt.imshow(img_decoded.eval())
        plt.title("Class:" + class_name[sess.run(prediction)[0]])
        plt.show()


test_image('./validate/11.jpg', 2)

对此绝大多数着实的火警图片,该互联网可能能够分辨出来,不过某些风烛残年图片可能暖色的灯光就不不难辨别。以下是一对识别图片结果:
威尼斯人娱乐 7

威尼斯人娱乐 8

威尼斯人娱乐 9

威尼斯人娱乐 10

威尼斯人娱乐 11

威尼斯人娱乐 12

威尼斯人娱乐 13

威尼斯人娱乐 14

3. 教练网络

即便使用锻练好的网络和网络权值能够平素开始展览归类识别应用,可是针对学习讨论的振奋,大家要求掌握什么样练习多少以及测试和评释互联网模型。

现阶段,大家有项识别火灾的任务(该类型的数据集来自一人挪威讲学,他的github地址为:https://github.com/UIA-CAIR/Fire-Detection-Image-Dataset
,他采纳的是革新过的VGG16网络),要求运用VGG19进展磨练,而平凡模型陶冶须求的正样本和负样本数量要对等,并且数据集越来越多越好,但在这次演练中,全部图片均是我从互连网抓取而来,且磨练集中的fire的图样和non-fire图片是不对等的,分别为223张和445张(原图没有那么多,大家温馨扩张了一部分火灾图片),测试集中的fire图片和non-fire的图样则也就是,均为50张。

对此怎么取得batch数据,在事先的亚历克斯Net中应用的是数额迭代器,在本次磨练中我们利用Tensorflow的系列来机关得到各个batch的数额,使用队列能够把图纸及相应的价签标准的取出来,同时还自行打乱顺序,分外好利用。由于接纳了tf.train.slice_input_producer创制了文本队列,因而一定要切记,在练习图片的时候须求周转tf.train.start_queue_runners(sess=sess)这么数据才会真正的填写进队列,不然程序将会挂起。
程序代码如下:

import tensorflow as tf

VGG_MEAN = tf.constant([123.68, 116.779, 103.939], dtype=tf.float32)



class ImageDataGenerator(object):
    def __init__(self, images, labels, batch_size, num_classes):
        self.filenames = images
        self.labels = labels
        self.batch_size = batch_size
        self.num_class = num_classes
        self.image_batch, self.label_batch = self.image_decode()


    def image_decode(self):
        # 建立文件队列,把图片和对应的实际标签放入队列中
        #注:在没有运行tf.train.start_queue_runners(sess=sess)之前,数据实际上是没有放入队列中的
        file_queue = tf.train.slice_input_producer([self.filenames, self.labels])

        # 把图片数据转化为三维BGR矩阵
        image_content = tf.read_file(file_queue[0])
        image_data = tf.image.decode_jpeg(image_content, channels=3)
        image = tf.image.resize_images(image_data, [224, 224])
        img_centered = tf.subtract(image, VGG_MEAN)
        img_bgr = img_centered[:, :, ::-1]

        labels = tf.one_hot(file_queue[1],self.num_class, dtype=tf.uint8)

        # 分batch从文件队列中读取数据
        image_batch, label_batch = tf.train.shuffle_batch([img_bgr, labels],
                                                          batch_size=self.batch_size,
                                                          capacity=2000,
                                                          min_after_dequeue=1000)
        return image_batch, label_batch

在精调中,代码和事先的亚历克斯Net大约,只是去掉了自定义的数码迭代器。整个VGG19互联网一共陶冶九十两个epochs,各样epoch有九1多个迭代,同时利用交叉熵和梯度降低算法精调VGG19互连网的末梢几个全链层fc6,fc7,fc8。度量互连网质量的精确度(Precision)、召回率(Recall)及F1值大家没有运用,不难利用了准确率这一指标。值得注意的是,在教练获取数据以前,一定要运营tf.train.start_queue_runners(sess=sess),那样才能保障数据真实的填充入文件队列。通过运用Tensorflow的行列存取数据,整个精调代码比亚历克斯Net要切中时弊一些,部分代码如下:

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())

    # 运行队列
    tf.train.start_queue_runners(sess=sess)

    # 把模型图加入TensorBoard
    writer.add_graph(sess.graph)

    # 总共训练100代
    for epoch in range(num_epochs):
        print("{} Epoch number: {} start".format(datetime.now(), epoch + 1))
        # 开始训练每一代
        for step in range(num_iter):
            img_batch = sess.run(training.image_batch)
            label_batch = sess.run(training.label_batch)
            sess.run(train_op, feed_dict={x: img_batch, y: label_batch})

在测试网络品质的时候,从前使用的准确率(Accuracy)是不太准备的,首先看准确率总结公式(如下),那一个指标有相当的大的弱点,在正负样本不平衡的境况下,比如,负样本量极大,固然大多数正样本测度正确,所占的比例也是比较少的。所以,在计算学中时常使用精确率(Precision)、召回率(Recall)和双面的疏通平均F1值来度量一个网络的属性。

准确率(Accuracy)的总结公式为:
\[Accuracy=\frac{TP + TN}{TP + TN + FP
+FN}\]

其中:
True Positive(真正, TP):将正类预测为正类数.
True Negative(真负 , TN):将负类预测为负类数.
False Positive(假正, FP):将负类预测为正类数 →→ 误报 (Type I error).
False Negative(假负 , FN):将正类预测为负类数 →→ 漏报 (Type II error).

精确率(Precision)的总括公式为:
\[Precision=\frac{TP}{TP + FP}\]

召回率(Recall)的总结公式为:
\[Recall=\frac{TP}{TP + FN}\]

双面包车型大巴调和平均F1:
\[F1=\frac{2TP}{2TP + FP +FN}\]

精确率(Precision)是对准预测结果而言的,它表示的是预测为正的样本中有微微是对的。有二种值,一种正是把正类预测为正类(TP),另一种正是把负类预测为正类(FP)。精确率又叫查准率。
召回率(Recall)是针对原来的样书而言,它代表的是样本中的正例有个别许被估量正确了。也有三种值,一种是把本来的正类预测成正类(TP),另一种正是把原来的正类预测为负类(FN)。召回率又称查全率。
F1为精确率和召回率的调停平均,当二者值较高时,F1值也较高。

测试网络精确度代码如下:

print("{} Start testing".format(datetime.now()))

tp = tn = fn = fp = 0

    for _ in range(num_iter):
        img_batch = sess.run(testing.image_batch)
        label_batch = sess.run(testing.label_batch)
        softmax_prediction = sess.run(score, feed_dict={x: img_batch, y: label_batch})
        prediction_label = sess.run(tf.argmax(softmax_prediction, 1))
        actual_label = sess.run(tf.argmax(label_batch, 1))

        for i in range(len(prediction_label)):
            if prediction_label[i] == actual_label[i] == 1:
                tp += 1
            elif prediction_label[i] == actual_label[i] == 0:
                tn += 1
            elif prediction_label[i] == 1 and actual_label[i] == 0:
                fp += 1
            elif prediction_label[i] == 0 and actual_label[i] == 1:
                fn += 1

    precision = tp / (tp + fp)
    recall = tp / (tp + fn)
    f1 = (2 * tp) / (2 * tp + fp + fn)  # f1为精确率precision和召回率recall的调和平均
    print("{} Testing Precision = {:.4f}".format(datetime.now(), precision))
    print("{} Testing Recall = {:.4f}".format(datetime.now(), recall))
    print("{} Testing F1 = {:.4f}".format(datetime.now(), f1))

通过一天的教练和测试,网络精确度(Precision)为60%左右,召回率(Recall)为95%,F1值为72.6%。由于图片较少,因而性能指标不是很理想,后续我们随后革新。
下边开首验证网络。首先在互连网上任选几张图片,然后编写代码如下,

class_name = ['not fire', 'fire']


def test_image(path_image, num_class):
    img_string = tf.read_file(path_image)
    img_decoded = tf.image.decode_png(img_string, channels=3)
    img_resized = tf.image.resize_images(img_decoded, [224, 224])
    img_resized = tf.reshape(img_resized, shape=[1, 224, 224, 3])
    model = Vgg19(bgr_image=img_resized, num_class=num_class, vgg19_npy_path='./vgg19.npy')
    score = model.fc8
    prediction = tf.argmax(score, 1)
    saver = tf.train.Saver()
    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())
        saver.restore(sess, "./tmp/checkpoints/model_epoch50.ckpt")
        plt.imshow(img_decoded.eval())
        plt.title("Class:" + class_name[sess.run(prediction)[0]])
        plt.show()


test_image('./validate/11.jpg', 2)

对于多数当真的火警图片,该网络也许能够辨识出来,然则有的中年老年年图片也许暖色的灯光就不便于辨认。以下是一些分辨图片结果:
威尼斯人娱乐 15

威尼斯人娱乐 16

威尼斯人娱乐 17

威尼斯人娱乐 18

威尼斯人娱乐 19

威尼斯人娱乐 20

威尼斯人娱乐 21

威尼斯人娱乐 22

参考文献

参考文献

相关文章