CV视觉论文VGG学习笔记

《Very Deep Convolutional Networks For Large-scale image Recongniton》

基于卷积神经网络的图像分类(经典网络)

作者: Karen Simonyan&Andrew Zisserman

单位:牛津大学(visual Geometry Group)

发表会议及时间:arXiv 2015

论文导读

论文研究背景,成果

自从2012年ALexnet将深度学习的方法应用到imageNet的图像分类比赛中并取得了state of the art的惊人结果后,大家都竞相效仿并在此基础上做了大量的尝试和改经,改经的方向主要有:

1.小卷积核

在第一个卷积层使用更小的卷积核和卷积stride(Zeiler & Fergus, 2013; Sermanet al.,2014):

使用更小的卷积核可以提取到更细节的特征。

2.多尺度

训练和测试使用整张图的不同尺度(Sermanet at ., 2014;Howard 2014)

这样可以增加模型的泛化能力。

vgg作者不仅将上面两种方法应用到自己的网络设计和训练测试阶段,同时还考虑了网络深度对结果的影响。实验证明网络深度对提高网络精度很重要。

VGG成果

在2014年在ILSVRC比赛上获得了分类项目的第二名(第一名是GoogLeNet),和定位项目的第一名。同时模型对其他数据集有很好的泛化能力。

VGG由于其结构简单,提取特征能力强,所以应用场景广泛

例如:

快速风格迁移算法中使用了VGG的某一卷积层来提取特征,还原出对应这种特征的原始图像

作为目标检测的backbone使用VGG某个卷积层提取特征,使用特征进行后续的物体坐标回归以及分类。

gan网络的损失部分使用VGG 提取特征,通过提取到的特征,计算图片的感知损失,感知损失可以使图像重构更精细。

第一张图片展示了VGG网络提取特征进行目标检测,第二张图是VGG神经网络提取特征做感知损失,第三张图是风格迁移的示意图,将右上角图的风格变成了梵高画的风格。

论文研究方法

作者一共设置了6组对比实验,包括A,A-LRN,B,C,D,E六种不同的网络结构A网络包含11×8个卷积层和三个fc层A-LRN网络在A网络的基础上加入了LRN层,B网络在A网络的基础上加上了两个3*3的卷积层,C网络又在B网络的基础上加入了三个 1×1的卷积层,D网络又将C网络中1×1的卷积层变成了3*3的卷积层,E网络又在D网络的基础上加入了三个3×3的卷积层总的来说就是这六个网络他们的网络结构越来越深。

 单尺度测试结果对比

结论:

第一点:LRN对网络性能的提升没有帮助

第二点:对同一个网络结构多尺度训练可以提高网络精度。

第三点:E模型(VGG19)效果最好,一定程度加深网络可以提高网络精度。

从表中可以看出作者进行了12组实验前三个实验的结果前三个实验作者先以固定尺度256的图像训练A,A-LRN,B三个网络然后他的测试数据也用固定的尺度也为256可以看到测试结果中A A-LRN网络与A网络相比top one与top five并没有什么变化所以我们可以得到一个结论那就是LRN层对提高网络性能没有什么帮助所以作者在后续B C D E四个网络中并没有使用LRN层。

再看一下B网络与A网络的对比可以看到B网络比A网络的top-one error下降了0.9,top-five error 下降了0.5这组对比实验可以得到结论就是对于同一个网络结构多尺度训练可以提高网络精度。C网络的三个对比实验第一个实验train image给固定大小为256,测试图片的尺度也为256在这个实验条件下与B对比可以看到他的top one error 下降了0.6top-fiveerror下降了0.5这组对比实验有进一步的说明网络深度的重要性,C的第二组实验依旧使用固定尺度的图像来进行训练和测试但是本次实验的尺度变为了384,对比C的第一组实验和第二组实验可以发现它的精度并没有什么提高。说明单独扩大数据尺度对网络提高没有效果。 第三组使用了多次度的图像来训练网络然后使用了固定尺度的图像来测试网络尺度的变化区间为256到512,具体操作就是让一张图像最小边的尺寸在256到512之间变化然后随机从图中截取224个图像块也就是说网络输入的图像一直都是224×224。

只不过是让原图像的尺寸发生了变化,实验结果可以看到使用多尺度的训练方法可以使网络的精度进一步提高,在D网络中的第一个实验图像尺度为256与C网络第一组的情况下的实验做对比可以看到top one error降低了1.1 top fiveerror降低了0.6,1×1的卷积换为3*3的卷积核是有效的D的第三组实验依旧验证了多尺度训练的有效性,最后看E的三组实验,依旧是用了两个固定的尺度还有一个变化尺度的时间来做对比,这种实验也证明了多尺度训练的重要性,E的第三组实验是效果最好的。

多尺度的测试结果

注意到D和E的多尺度训练多尺度测试的结果是相同的,之前E网络使用单尺度的结果是什么?可以看到top one error为25.5 top-five error为8:0而使用多尺度测试则变为了24.8和7.5。

精准率均有提升,通过table 4与table 3的对比可以得到两个结论:第一个结论:对比单尺度预测多尺度综合预测能够提升预测的精度也就再次证明了尺度抖动的作用。在这里看到D和E的精度是一样的但是的深度小于一的深度也就是说地网络的模型比网络的小但是他的网络性能也很好所以可以得出第二个结论:VGG为最好的模型。但在实际工作中VGG16和VGG19使用频率都很高D和E模型都需要掌握

多尺度测试结果对比

这一组对比实验对D和E两个网络做对比。

D的三组对比实验,第一个实验使用dense的方法进行测试,第二个实验使用multi-crop的方式来进行网络的测试,第三个就是使用multi-crop&dense两种方式来估测网络的性能可以看到联合两种测试方式结果会更好一些,E网络的三个对比实验也表明了这一点所以我们可以得到一个结论:

dense evluation &multi-crop两种测试方式联合使用效果最好。

模型融合结果对比

可以看到D和E两个模型融合,使用multi-crop&dense联合使用, 

得到的结果是最好的也就是说融合模型D和E之后模型错误率显著下降。top-one error为23.7,top-five error为6.8。

与其他网络结果对比

 table7 是VGG参加ILSVRC与其他人做的对比,可以看到最好的是GoogleNet,是7个网络融合的结果,VGG作为第二名它的精度也是高于其他网络所以VGG的表现也是相当优秀。

论文结论

1.在一定范围内通过增加深度能有效提升网络性能

2.最佳模型VGG 16从头到尾只有3*3的卷积和2×2的池化简洁优美

3.多个小卷积核比单个卷积核和性能好(与Alexnet对比就可知);

4.Alexnet曾经用到的LRN层并没有带来性能的提升,因此在与其他组网络中均没有再出现LRN层

5.尺度抖动(scale jittering)(多尺度训练,多尺度测试)有利于网络性能的提升

感受野

感受也的定义是卷积神经网络每一层输出的特征图上的像素点再输入图片上映射的区域大小。

再通俗的讲就是特征图上的一个点跟原图上有关系多点的区域

感受野概念为什么重要?

感受野被称为是CNN中最重要的概念之一目标检测流行的算法比如SSD,FASTER RCNN等中的prior box和anchor box的设计都是以感受也为依据做的设计。

输入原始图像为7*7

conv1: 3*3 strides=1,valid

feature:(7-3+1)/1=5    经过第一层卷积后,featuremap的大小为5*5

conv2: 3*3  strides=1,valid

feature:(5-3+1)/1=3

原始输入感受野:1

conv1层感受野:3

conv2层感受野:5

思考:

如果conv1:5*5,strides=1,vaild感受野是多少?

感受野为5,因为conv1的一个点是由原始图像的5*5个点组成的的。

结论:一个5*5卷积核感受野大小与两个3*3卷积核的感受野等效。

以此类推三个3*3的卷积核感受野与1个7*7卷积核的感受野等效。

感受野计算公式:

r_{n}=r_{n-1}+(k_{n}-1)\prod_{i=1}^{n-1}s_{i} 其中r_{n-1}上一层感受野的大小 k_{n}本层卷积核尺寸s_{n}卷积步幅大小

eg:

conv1: 3*3 strides=1 valid

conv2: 3*3 strides=1 valid

conv3: 3*3 strides=2 valid

conv4: 3*3 strides=1 valid

maxp: 2*2 strides=2

(计算感受野时,maxp看作conv:2*2,strides=2)

原图感受野:1

conv1:1+(3-1)=3

conv2:3+(3-1)*1=5

conv3:5+(3-1)*1*1=7

conv4:7+(3-1)*1*1*2=11

conv4:11+(2-1)*1*1*2*1=13

注意:这里只是理论感受野,实际上起作用的感受野是小于理论感受野的。 

作业:

思考vgg与alexnet的区别

求Alexnet的理论感受野

论文详解

1.上节回顾

1.1.论文研究背景及成果

从多个方面对laexnet进行改进:小卷积,多尺度。

作者将网络的深度考虑进去。

1.2.论文研究方法

设计了6个不同的网络结构

深度依次增加

进行多尺度训练和测试

1.3.论文结论

增加网络深度可以提高准确度

多个小卷积核比多个大卷积核性能好

LRN层并没有带来性能的提升

vgg16 best model

1.4.感受野

感受野概念

感受野计算公式

2.论文整体框架

1 Abstract

摘要

本文研究了在大规模图片识别中,卷积神经网络的深度对准确率(accuracy)的影响。我们的主要贡献是通过非常小的3×3卷积核的神经网络架构全面评估了增加深度对网络的影响。结果表明16到19层的网络可以使现有设置的网络性能得到显著提高。这项发现是我们在2014年的你们这net比赛中提交提交方案的基础我们的团队分别在定位和分类中获得了第一和第二的成绩我们还证明了此模型可以泛化到其他数据机上并达到当前最佳水平我们已经公布了两个性能最佳的卷积神经网络模型以便深度视觉在计算机视觉中的进一步研究。

网络深度 小卷积核 16-19层 Vgg16 vgg19

2 Introduction

论文研究背景

3 Convet configuration

training

        网络超参数

        训练数据处理

testing

fc变成conv

details

实验环境

训练时长

4 Classification Experiments

与其他的工作做了对比

5 Conclusions

增加网络深度可以提高网络的分类精准度

3.网络结构与权重参数计算

conv1: conv1_1,conv1_2

5个卷积块,小卷积核堆积

通道的数量依次增加一倍(64-128-256)

卷积块结束后进行maxpooling

三个全连接层 

思考?

Q1: 为什么使用3*3的卷积核?

深度更深并增加了非线性

3个3×3的卷积核感受野与一个7×7卷积核的感受野等效。但是三个3×3卷积核加入了激活函数。与仅使用一个7×7卷积核相比深度更深且增加了非线性。

参数量减少

假设输入数据通道大小为C三个C通道的3×3卷积核参数量为

3*(C*3*3*C)=27 C*C

一个C通道的7×7减结合的参数量为

C*7*7*C=49C*C

Q2:1*1卷积核的作用?

一种为决策增加非线性因素的方式

调整网络维度扩维或者缩小维度

eg: mobilenet使用1*1卷积核来扩维

resent使用1*1卷积核来减少维度。

4.网络超参数及训练数据处理

Let S be the smallest side of an isotropically-rescaled training image

各向同性的缩放训练图像的最小边

以S=256为例

1.将图片进行等比变换,最小长度为256

2.对等比变换后的图像随机截取224*224的图像块

3.对裁剪的图像块进行随机水平翻转与RGB颜色翻转

增加数据量,提高网络的泛化能力,防止过拟合。 

数据处理代码

import numpy as np
from PIL import image
S=256  #图像最小边长度
crop_size=224
image_path='./image.jpeg'
or_image=image.open(image_path)#加载图像
image_w,image_h=or_image.size#获取原始图片宽度
scale=S/(min(image_w,image_h))#0.4 将图片的最小边缩小为224
new_w=np.int(image_w*scale)#计算等比缩放后图像的长宽
new_h=np.int(image_h*scale)
print(new_w,new_high)#256 341
resize_image=or_image.resize((new_w,new_h),image.BICUBIC)#用线性差值方式缩放
max_offset_width=np.random.randint(low=0,high=new_w-crop_size+1,dtype='int32')
max_offset_height=np.random.randint(low=0,high=new_h-crop_size+1,dtype='int32')
crop_image=resize_image.crop((max_offset_width,max_offset_height,max_offset_width+crop_size,
max_offset_height+crop_size)) #截图
print(crop_image.size)#(224,224)
transpose_image=crop_image.transpose(image.FLIP_LEEF_RIGHT)
#水平翻转
r,g,b=transpose_image.split()#分离图像三个通道
pic=image.merge('RGB',(g,r,b)) #交换g,r通道

超参数设置

批量大小:batchsize=256

权重衰减:weight decay=5*10-4

学习率:learning rate=0.01  衰减因子为0.1

动量:momentum=0.9(优化方式为带动量的SGD)

迭代步数 :370K

轮数:epoches=75

卷积核初始化方式:均值为0方差为1的高斯分布

(深层网络使用浅层网络权重初始化)

偏置初始化方式:初始化为0

全连接层初始化方式:高斯分布(std=0.005),bias常数初始化(0.1)

5.网络特点

1.小卷积核

VGG使用多个小卷积核(3*3)的卷积层代替大的卷积核,一方面可以减少参数,另一方面相当于进行了更多的非线性映射,以增加网络的拟合/表达能力。

2.小池化核

相比于AlexNet的3*3的池化核,VGG全部采用2*2的池化核。

3.层数更深

VGG常用结构为16层,19层(仅计算conv,fc层),Alexnet有八层(5个conv,3个fc)

4.全连接转卷积

网络测试阶段将训练阶段的三个全链接替换为三个卷积,测试重用训练时的参数,使得测试得到得全卷积网络因为没有全连接的限制,用此可以接受任意宽或者高为输入。

借鉴论文:integrated Recognition Localization and detection using Convolutional Networks

卷积层替换全连接层

全链接层的计算公式为fc=w^{T}x+b

假设输入到全连接层特征大小为7*7*5

输出特征大小为1000*1

首先将输入特征变为一个列向量

7*7*5---->(245,1)

则x大小为(245,1)

然后全链接层的权重相乘,偏置相加

w的大小为(245,1000)

b的大小为(1000*1)

假如测试时输入到全链接层的特征的大小为14*14*5,我们需要输出的特征大小依旧1000*1

x变为(980,1)

而此时的w的大小为(245,1000)

就会出现尺寸不匹配问题

如果使用卷积层,使用1000个7*7*5的卷积代替fc层卷积参数量为7*7*5*1000=245*1000与fc层参数量相同,所以可以将fc层学习到的参数赋给卷积层

假设输入特征为7*7*5,令stirds=1,最后输出尺度为[1,1,1,1000]可以降维为[1,1000]

如果输入的特征为14*14*5,最后得到特征为[1,2,2,1000]即为一个scroemap,我们对他求平均得到[1,1000]向量。

作业内容

1.使用tensorboard可视化Vgg 16 网络结构

2.计算VGG 16理论感受野

3.使用张亮形式如何对训练数据进行处理。

上节回顾

01 论文整体框架

论文整体包括Abstract,Intoduction,Convnet configuration, Classification Framework,classiciction Experiments Conclusion

02 网络结构及部分参数计算

VGG 16网络结构:5个卷积块,3个全连接层,VGG16每层权重占用内存两个思考问题:使用3*3小卷积核的好处 1*1卷积核什么作用

03网络超参数及训练数据处理

网络超参数的设置,学习率,batchsize等

训练数据产生方式:各向同性缩放,随机裁剪等

测试方式:multi-crop dense evaluation

04网络的特征

使用了小卷积核,小池化核,深度更深,卷积层替换全连接层

微调知识(迁移学习)

微调概念(CNN)

简单描述:使用预训练的神经网络模型,来训练我们自己的数据集合。即使用训练好的权重来初始化我们的网络,并不是随机初始化。在实践中,我们通常不会完全从头开始随机初始化训练DCNN,这是因为有能满足深度网络需求的足够大小的数据集相当的少见。作为代替,常见的是在一个大数据集上预训练一个DCNN,然后使用这一训练的DCNN的权重作为初始设置或作为相关任务的固定的特征提取器。

什么情况下使用?

自己设计的网络不好,精度太低

数据集合相似但是数据量小

自己的计算资源不够

为什么微调会有效?

神经网络浅层学习的通用特征即基础特征,比如边缘,轮廓颜色等特征。深层是针对特定数据的抽象的特征,对于人脸来说可能就是某个人的脸。全链接层就是对特征进行组合并评分分类。

我们可以利用网络前几层学习到的通用特征,仅让网络学习数据的抽象特征,节省资源和时间。

不同场景

微调(Fine-Tuning):迁移学习策略取决于多种因素,但是最重要的两个是数据集的大小以及数据集与原数据集的相似度。以下是4个主要场景:

新数据集量小,内容上相似:这种情况下,通常情况我们只需要训练最后的输出层,即最后一层,因为可能分类的数量不同,最后一层需要做修改(平时最常见)

新数据集量大,内容上相似:这是最理想的情况,我们可以微调整个网络,因为数据量足够大不用担心出现过拟合。

新数据集量小,内容不相同:由于数据较小,且相似度低,这种情况使用微调效果不是很好,我们可以尝试冻结前面大部分卷积层,重新训练网络的高层卷积层及全链接层。

新数据集量大,内容不相同:由于数据集很大,且相似度很低,最好不要使用预训练的模型,从头开始训练整个网络。

数据增强代码

功能:
    计算将图片最小边缩放为目标尺寸时图像的宽高为多少即返回目标宽高
_R_MEAN=123.68
_G_MEAN=116.78
_B_MEAN=103.94
_RESIZE_SIDE_MIN=256
_RESIZE_SIDE_MAX=512
crop_height=224
crop_width=224

def_smallest_size_at_least(height,width,smallest_side):
"""
    函数实现 将图片最小边缩放为small_side时,宽度和高度分别变为多少
    param height 原始图像高度
    param width 原始图像宽度
    param smallest side:
    return:缩放后图像的高度和宽度
"""
smallest_side=tf.convert_to_tensor(smallest_side,dtype=tf.int32)
height=tf.to_float(height)
width=tf.cond(tf.greater(height,width),lambda:smallest_side/width,
                                            lambda:smallest_side/height)
new_height=tf.cast(tf.rint(height*scale).tf.int32)
new_width=tf.cast(tf.rint(width*scale),tf.int32)
return new_height,new_width
#图片的缩放
def_aspect_preserving_resize(image,smallest_side):
"""
    函数实现将图片等比缩放,最小边长为smallest_side
    param image:3维张量
    param smallest_side: 等比缩放后最小边长
    return:等比变化的张量
"""
    smallest_side=tf.convert_to_tensor(smallest_side,dtype=tf.int32)
    shape=tf.shape(image)
    height=shape[0]
    width=shape[1]
    new_height,new_width=smallest_size_at_least(height,width,smallest_side)
    image=tf.image.convert_image_dtype(image,dtype=tf.float32)
    resized_image=tf.image.resize_images(image,[new_height,new_widt],
    method=tf.image.ResizeMethod.BICUBIC)
    return resized_image

对图片进行随机裁剪

随机裁剪224*224的图像块

def random_crop(image,crop_height,crop_width):
    original_shape=tf.shape(img_data_jpg)
    #判断original_shape的维度是否为3,如果是则不会报错
    rank_assertion=tf.Assert(tf.equal(t.rank(img_data_jpg),3),
    ['Rank of image must be equal to 3'])
    #cropped_shape=[224,224,3]
    with tf.control_dependencies([rank_assertion]):
        cropped_shape=tf.stack([crop_height,crop_width,original_shape[2]])
        #判断原图像块的大小,若原图像块尺寸那么抛出异常
    size_assertion=tf.Assert(tf.lgical_and(
                                  
                           tf.greater_equal(original_shape[0],crop_height),
                           tf.greater_equal(original_shape[1],crop_width)),
                           ['crop size greater than the image size'])
    #确定最大裁剪范围
    max_offset_height=tf.reshape(original_shape[0]-crop_height+1,[])
    max_offset_width=tf.reshape(original_shape[1]-crop_width+1,[])
#生成随机裁剪的起始点
offset_hight=tf.random_uniform([],maxval=max_offset_hight,dtype=tf.int32)
offset_width=tf.random_uniform([],maxval=max_offset_width,dtype=tf.int32)
#裁剪的偏移量
offset=tf.cast(tf.stack([offset_height,offset_width,0]),tf.int32)
#对图像进行裁剪
with tf,control_dependencies([size_assertion]):
image=tf.slice(img_data_jpg,offsets,cropped_shape)
return tf,reshape(image,cropped_shape)
#图像缩放最小尺寸为256,最大尺寸为512
resize_side_min=_RESIZE_SIDE_MIN
resize_side_max=_RESIZE_SIDE_MAX
#读出的未解码的图片
image_raw_data_jpg=tf.gfile.GFile('./timg1.jpeg','rb').read()
#图像解码
img_data_jpg=tf.image.decode_jpeg(imge_raw_data_jpg)
#随机产生最小边尺寸
resize_side=tf.random_uniform([],minval=resize_side_min,maxval=resize_side_max+1,dtype=tf.int32)
#对图片进行等比缩放
resize_img=_aspect_preserving_resize(img_data_jpg,resize_side)
#对缩放后的图片进行随机裁剪
crop_img=random_crop(resize_img,crop_height,crop_width)
#左右翻转
image_data=tf.image.random_flip_left_right(crop_img)
#调整图像亮度
image_data=tf.image.random_brightness(image_data,0.5)

重点代码讲解

所需环境

python 3

Tensorflow=1.9

数据集合简介

flowers数据集合

2987张花朵图

加载权重

vgg16.npy二进制权重

功能:使用VGG16 进行微调

代码结构:

train_Vgg.py 主程序,包含了整个工程的完整流程

load_data.py数据产生程序,包含了数据的读取与去均值过程

VGG16.py定义了网络结构,损失函数,准确率计算等

test_vgg16.py测试模型效果

test_images文件夹 包含若干张测试图片(来源于网络下载)

定义VGG16类权重文件位置是否可训练

class VGG16:
"""
一个可训练的VGG16
"""
def_init_(self,vgg16_npy_path=None,trainable=True):定义构造网络函数
    if vgg16_npy_path is not None:
      
   self.data_dict=np.load(vgg16_npy_path,allow_pickle=True,ecoding='latin1').item()
    del self.data_dict['fc8' ]
    del self.data_dict['fc7' ]
    del self.data_dict['fc6' ]
    print("===load weithts succesfully===")
   else:
        self.data_dict=None
self.var_dict={}
self.trainable+trainable

AlexNet网络定义

5个卷积块

3个全连接

def build(self,x,num_classes,dropout):
#第一个卷积块
    self.conv1_1=self.conv_layer(x,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.conv3_2,'pool3')
#第三个卷积块
    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.pool3=self.max_pool(self.conv3_3,'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.pool4=self.max_pool(self.conv4_3,'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.pool5=self.max_pool(self.conv5_3,'pool5')
#全连接层
    self.fc6=self.fc_layer(self.pool5,25088,4096,'fc6')
    self.relu6=tf.nn.relu(self.fc6)
    self.felu6=tf.nn.dropout(self.relu6,dropout)
    self.fc7=self.fc_layer(self.relu6,4096,4096,'fc7')
    self.relu7=tf.nn.relu(self.fc7)
    self.felu7=tf.nn.dropout(self.relu7,dropout)
    self.fc8=self.fc_layer(self.relu7,4096,num_classes,'fc8')

数据的加载

对数据与label进行操作函数

def_parse_function_train(self,filename,label):
"""input parser for samples of the training set."""
# convert label number into one-hot-encoding
    one_hot=tf.one_hot(label,self.num_classes)
# load and preprocess the image
    img_string=tf.read_fie(filename)
    img_decoded=tf.image.decode_jpeg(img_string,channels=3)
    image_data=tf.image.resize_images(img_decoded,[224,224])
    """
    数据增强
    #左右翻转
    image_data=tf.image.random_filp_left_right(img_resized)
    #调整图像的亮度
    image_data=tf.image.random_brightness(image_data,0.5)
    """
    #减去均值
    image_data=self._mean_image_subtraction(image_data)
    return image_data,one_hot

主程序

train_vgg.py

超参数设置 分割数据 

import tensorflow as tf
import os
from VGG16 import VGG16
from datetime import datetime
from tensorflow.data import lterator
import numpy as np
import matplotlib.pyplot as plt
#超参数设置
learning_rate=0.01
decay_rate=0.1
batch_size=32
num_epochs=100
rate=0.5
filewriter_path="./tesorboard"
checkpoint_path="./checkpoints"
vgg16_npy_path="./vgg 16.npy"
#训练图像的路径
data_dir='./flower_photos'
num_classes=5
#将数据分为训练集合和测试集合,给不同的花卉品种分配标签
training_filenames,validation_filenames,class_numes_to_ids=split_datas(data_dir)
#获取数据和相应的标签列表
train_data,train_label=get_datas_and_labels('train',training_filenames,clas_names_to_ids)
val_data,val_label=get_datas_and_labels('validation',validation_filenames,clas_names_to_ids)

加载数据

定义占位符

#加载batch_size数据 设备为cpu:0
with tf.device('/cpu:0'):
    train=Load_data(train_data,train_label,batch_size=batch_size,
                    num_classes=num_classes,mode='training',shuffle=True,
buffer_size=100)
    val=Load_data(val_data,val_label,batch_size=batch_size,
                    num_classes=num_classes,mode='validation',shuffle=False,
buffer_size=100)
    #创建迭代器
            iterator=iterator.from_structure(train.data.output_types,train.data.output_shapes)
next_batch=iterator.get_next()
    #分别给训练数据和验证数据初始化迭代器
training_init_op=iterator.make_initializer(train.data)
validation_init_op=iterator.make_initializer(val.data)
#定义占位符
x=tf.placeholder(tf.float32,[batch_size,224,224,3])
y=tf.placeholder(tf.float32,[batch_size,num_classes])
fc_rate=tf.placeholder(tf.float32)

主程序

main_vgg.py

加载网络

将特征图写入

tensorboard

#载入网络
vgg16=VGG16(vgg16_npy_path,False)
vgg16.build(x,num_classes,rate)
#将特征图写入tensorboard
with tf.variable_scope('feature_map'):
    conv1_1_feature=vgg16.conv1_1
    split_mumber=conv1_1feature.get_shape().as_list()[-1]
    conv1_1=tf.split(conv1_1_feature,num_or_size_splits=split_mumber,axis=3)
    #将第一个特征map写入到tensorboard
    tf.summary.image('conv1',conv1_1[0],max_outputs=4)
y_predict=vgg16.fc8
#计算损失
vgg16.loss(y_predict,y)
#调用优化器最小化损失
vgg16.training(learning_rate,decay_rate)
#验证网络的准确度
vgg16.evaluation(y_predict,y)
[batchsize,224,224,64]---->[batchsize,224,224,1]---->[4,224,224,1]

loss震荡严重,但是网络的确在学习,因为准确率在上升。

 

loss震荡严重,但是准确率在上升

 

第一层主要记录了边缘信息,后面的背景变弱,每个batch——size是随机取的

讨论与总结

什么情况适合微调-------数据量小,且内容相似

什么情况不适合微调----数据量小,且内容不相似

微调的优点是什么-------节省时间和资源

总结

上节回顾

VGG16网络结构

参数计算

网络特点

迁移学习的概念

四种情况

数据增强

如何使用tensorflow对数据进行数据增强

重点代码

讲解了工程中的重点的部分代码,数据处理函数及部分主程序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值