卷积神经网络(2)----Vgg16
一、VGG net介绍 点击此处返回总目录 二、常用的函数 三、VGG16网络结构 四、VGG16代码
一、VGG 介绍 今天分享一下,如何复现已有网络,实现特定应用。我们以VGG net为例,讲解图片识别的源代码。 这套代码可以对输入的图片进行识别,比如把左边的图片输入网络,VGG net会输出斑马。 VGG net介绍:
二、常用的函数 在讲解代码前,先和大家分享几个函数的用法。 复现神经网络时,需要用tf.placeholder()给输入占位。卷积计算要求输入的图片按照4个维度喂入网络,第0个维度表示一次喂入几张图,第1、2、3维度是对输入图片的描述,由于已有网络对输入的要求是224*244的分辨率,是红绿蓝3通道信息。所以这里写[1,224,224,3]。 在后面的代码中会用feed_dict{x:}把输入图片x按照[1,224,224,3]的维度整理后,喂入求分类评估值的节点。
np.load()和np.save()是将数组以二进制格式读出或写入磁盘,默认保存的扩展名为.npy。 .item()表示遍历其内的每一个。 如果把他们连起来用,可以把事先保存在vgg16.npy中的数组和对应的名字,以键值对的形式赋给data_dict。data_dict是字典类型。这样就可以读出提前训练好的神经网络参数了。
数据的维度,可以方便我们了解存在npy文件中的各层参数的数据结构。可以使用tf.shape()获得张量、列表、数组的维度。
tf.nn.bias_add()可以把偏置项bias加到乘加和上。 tf.reshape(tensor,[n行, m列])可以把张量变成需要的维度。n为-1,表示根据其他维度自动调整。 np.argsort(列表)可以把列表从小到大排序。注意返回的是列表索引值。 os.getcwd()可以返回当前的工作目录。 os.path.join(, , ...)可以把后面的路径文件拼接。比如,这句话实现了把当前路径和"vgg16.npy"拼接为一个路径。这样就可以通过vgg16_path所引到vgg16.npy文件。
tf.split()是切分数据用的。可以把输入切成指定大小或份数,在哪个维度切。比如,value是个5行30列的张量。tf.split(value,[4,5,11],1)可以把value在第1个维度,分为4,15,11三份。切分后分别是5行4列、5行15列和5行11列。 也可以指定切成几份。比如tf.split(value,num_or_size_splits=3,axis=1)表示把value在第一个维度切成3份,平均切。每一份是5行10列。 tf.concat()可以实现粘贴。把张量t1和t2,按照第0个维度粘,是上面的结果。按照第1个维度粘是下面的结果。
在这里和大家分享一下,通用的学习方法,在以后的学习中,会有大量的源代码阅读,不可能每个函数都记得用法,这个时候需要查找相关的参考资料,对于TensorFlow,推荐大家使用Google官方文档查询网网页:https://tensorflow.google.cn。
有时候,我们需要把运行的结果可视化。 用fig = plt.figure("图名字")实例化图对象。 img = io.imread()可以把图片读入到img. 用fig.add_subplot()给出这幅图片包含几行几列个子图,当前是第几个子图。 用bar()函数可以画柱状图。分别给出柱子的个数,柱子所表示的数值大小,柱子的名字,柱子的宽度,柱子的颜色。 用set_ylabel()给出y轴的名字。以字符串的形式给出。如果是中文,有时候需要在前面加个"u"。 用set_title()给子图加名字。 用text()添加文字,需要给出文字的x、y坐标,文字的内容,横向、纵向位置,字号大小。
以上这些描述完成后,用imshow()把子图画出来。
三、VGG16 网络结构 我们使用的是论文中编号为D的网络结构。
四、VGG代码 我们这一讲的代码一共有5个文件。 app.py //应用程序,实现图片识别功能。 vgg16.py //读取了模型参数,并搭建模型。 utils.py //是一些辅助函数。包括读取一张输入图片,计算百分比形式的概率。 Nclasses.py //是一个标签字典。通过神经网络识别出来的是一个编号,这个编号就是Nclasses.py中的字典labels的键,可以根据键找 到对应的值。
vgg16.npy //是个500M+的文件。包含了神经网络的所有参数。代码中我们会用类初始化函数 __init__()读入vgg16.npy里面保存的模型参数,参数以字典形式存入data_dict,我们可以用for循环打印data_dict中的键。 data_dict中的每个键对应卷积或全连接对应的参数: 比如,conv1_1 对应了第一个conv3-64,包含了64个3*3*3的卷积核参数和64个偏置。 conv1_2对应下一个conv3-64,包含了64个3*3*3的卷积核参数和64个偏置。 conv2_1对应第一个conv3-128,包含了128个3*3*3的卷积核参数和128个偏置。 conv2_2对应下一个conv3-128,包含了128个3*3*3的卷积核参数和128个偏置。 ...... fc6对应FC-4096,包含第一层全连接参数w和偏置b ... fc8对应FC-1000,包含了4096*1000个参数w和1000个偏置b 评估输出的是千分类评估值,前分类评估值经过softmax函数便满足了概率分布。
下面开始看详细的代码: 代码app.py可以读入一张待识别图片,输出可视化的识别结果。load_image读取图片。为了输出图片识别结果,要复现前向传播过程,sess.run()执行softmax函数会得到预测的1000个分类各自出现的概率,保存到probability[[]]中,probability[0][i]可以遍历每一个概率值,probability列表的索引值对应着Nclasses.py中标签的键。可以通过键找到分类名称。 top5[]提取了probability列表中5个最高概率的索引值,这个索引值就是Nclasses.py中标签的键。
vgg16.py包括两部分内容,__init__()加载参数到data_dict,forward()函数构建了前向传播网络,包括卷积计算、最大池化计算和全连接计算。在卷积计算中,包括读取卷积核参数的函数,读取偏置项参数的函数。在全连接计算中,包括了读取全连接线上的参数w和偏置项b的函数。
//
|