【TensorFlow-windows】(七) CNN之VGG-net的测试
主要内容:
1.CNN之VGG-net的测试
2.该实现中的函数总结
平台:
1.windows 10 64位
2.Anaconda3-4.2.0-Windows-x86_64.exe (当时TF还不支持python3.6,又懒得在高版本的anaconda下配置多个Python环境,于是装了一个3-4.2.0(默认装python3.5),建议装anaconda3的最新版本,TF1.2.0版本已经支持python3.6!)
3.TensorFlow1.1.0
牛津大学计算机视觉组(Visual Geometry Group)出产的VGGnet是 ILSVRC 2014年 分类第二名,定位项目第一名,其VGG-16\VGG-19广泛应用于图像领域!
论文《very deep convolutional networks for large-scale image recognition》
特点就是多个小卷积核(3*3)的堆叠来替代大卷积核(5*5,7*7),减少参数的同时增加了特征提取的能力。
来看看论文中给了5个模型的基本情况:
今天就用TF写一个VGG-16 ,上图红框中的那个,由于硬件问题,这里和Alex-net一样,只是做了一个前向和反向的耗时计算。(PS: GTX960m的 GPU(2G显存),没办法实现 batch_size为32,全连接层1为4096,全连接层2为4096个神经元的VGG网络,因此我修改了网络大小, batch_size为16, 全连接层1和2 都改为2048个神经元)
# -*- coding: utf-8 -*-
"""
Created on Mon Jun 12 16:36:43 2017
@author: ASUS
"""
from datetime import datetime
import math
import time
import tensorflow as tf
# 定义函数对卷积层进行初始化
# input_op : 输入数据
# name : 该卷积层的名字,用tf.name_scope()来命名
# kh,kw : 分别是卷积核的高和宽
# n_out : 输出通道数
# dh,dw : 步长的高和宽
# p : 是参数列表,存储VGG所用到的参数
# 采用xavier方法对卷积核权值进行初始化
def conv_op(input_op, name, kh, kw, n_out, dh, dw, p):
n_in = input_op.get_shape()[-1].value # 获得输入图像的通道数
with tf.name_scope(name) as scope:
kernel = tf.get_variable(scope+'w',
shape = [kh, kw, n_in, n_out], dtype = tf.float32,
initializer = tf.contrib.layers.xavier_initializer_conv2d())
# 卷积层计算
conv = tf.nn.conv2d(input_op, kernel, (1, dh, dw, 1), padding = 'SAME')
bias_init_val = tf.constant(0.0, shape = [n_out], dtype = tf.float32)
biases = tf.Variable(bias_init_val, trainable = True, name = 'b')
z = tf.nn.bias_add(conv, biases)
activation = tf.nn.relu(z, name = scope)
p += [kernel, biases]
return activation
# 定义函数对全连接层进行初始化
# input_op : 输入数据
# name : 该全连接层的名字
# n_out : 输出的通道数
# p : 参数列表
# 初始化方法用 xavier方法
def fc_op(input_op, name, n_out, p):
n_in = input_op.get_shape()[-1].value
with tf.name_scope(name) as scope:
kernel = tf.get_variable(scope+'w',
shape = [n_in, n_out], dtype = tf.float32,
initializer = tf.contrib.layers.xavier_initializer())
biases = tf.Variable(tf.constant(0.1, shape = [n_out],
dtype = tf.float32), name = 'b')
activation = tf.nn.relu_layer(input_op, kernel, # ???????????????
biases, name = scope)
p += [kernel, biases]
return activation
# 定义函数 创建 maxpool层
# input_op : 输入数据
# name : 该卷积层的名字,用tf.name_scope()来命名
# kh,kw : 分别是卷积核的高和宽
# dh,dw : 步长的高和宽
def mpool_op(input_op, name, kh, kw, dh, dw):
return tf.nn.max_pool(input_op, ksize = [1,kh,kw,1],
strides = [1, dh, dw, 1], padding = 'SAME', name = name)
#---------------创建 VGG-16------------------
def inference_op(input_op, keep_prob):
p = []
# 第一块 conv1_1-conv1_2-pool1
conv1_1 = conv_op(input_op, name='conv1_1', kh=3, kw=3,
n_out = 64, dh = 1, dw = 1, p = p)
conv1_2 = conv_op(conv1_1, name='conv1_2', kh=3, kw=3,
n_out = 64, dh = 1, dw = 1, p = p)
pool1 = mpool_op(conv1_2, name = 'pool1', kh = 2, kw = 2,
dw = 2, dh = 2)
# 第二块 conv2_1-conv2_2-pool2
conv2_1 = conv_op(pool1, name='conv2_1', kh=3, kw=3,
n_out = 128, dh = 1, dw = 1, p = p)
conv2_2 = conv_op(conv2_1, name='conv2_2', kh=3, kw=3,
n_out = 128, dh = 1, dw = 1, p = p)
pool2 = mpool_op(conv2_2, name = 'pool2', kh = 2, kw = 2,
dw = 2, dh = 2)
# 第三块 conv3_1-conv3_2-conv3_3-pool3
conv3_1 = conv_op(pool2, name='conv3_1', kh=3, kw=3,
n_out = 256, dh = 1, dw = 1, p = p)
conv3_2 = conv_op(conv3_1, name='conv3_2', kh=3, kw=3,
n_out = 256, dh = 1, dw = 1, p = p)
conv3_3 = conv_op(conv3_2, name='conv3_3', kh=3, kw=3,
n_out = 256, dh = 1, dw = 1, p = p)
pool3 = mpool_op(conv3_3, name = 'pool3', kh = 2, kw = 2,
dw = 2, dh = 2)
# 第四块 conv4_1-conv4_2-conv4_3-pool4
conv4_1 = conv_op(pool3, name='conv4_1', kh=3, kw=3,
n_out = 512, dh = 1, dw = 1, p = p)
conv4_2 = conv_op(conv4_1, name='conv4_2', kh=3, kw=3,
n_out = 512, dh = 1, dw = 1, p = p)
conv4_3 = conv_op(conv4_2, name='conv4_3', kh=3, kw=3,
n_out = 512, dh = 1, dw = 1, p = p)
pool4 = mpool_op(conv4_3, name = 'pool4', kh = 2, kw = 2,
dw = 2, dh = 2)
# 第五块 conv5_1-conv5_2-conv5_3-pool5
conv5_1 = conv_op(pool4, name='conv5_1', kh=3, kw=3,
n_out = 512, dh = 1, dw = 1, p = p)
conv5_2 = conv_op(conv5_1, name='conv5_2', kh=3, kw=3,
n_out = 512, dh = 1, dw = 1, p = p)
conv5_3 = conv_op(conv5_2, name='conv5_3', kh=3, kw=3,
n_out = 512, dh = 1, dw = 1, p = p)
pool5 = mpool_op(conv5_3, name = 'pool5', kh = 2, kw = 2,
dw = 2, dh = 2)
# 把pool5 ( [7, 7, 512] ) 拉成向量
shp = pool5.get_shape()
flattened_shape = shp[1].value * shp[2].value * shp[3].value
resh1 = tf.reshape(pool5, [-1, flattened_shape], name = 'resh1')
# 全连接层1 添加了 Droput来防止过拟合
fc1 = fc_op(resh1, name = 'fc1', n_out = 2048, p = p)
fc1_drop = tf.nn.dropout(fc1, keep_prob, name = 'fc1_drop')
# 全连接层2 添加了 Droput来防止过拟合
fc2 = fc_op(fc1_drop, name = 'fc2', n_out = 2048, p = p)
fc2_drop = tf.nn.dropout(fc2, keep_prob, name = 'fc2_drop')
# 全连接层3 加一个softmax求给类别的概率
fc3 = fc_op(fc2_drop, name = 'fc3', n_out = 1000, p = p)
softmax = tf.nn.softmax(fc3)
predictions = tf.argmax(softmax, 1)
return predictions, softmax, fc3, p
# 定义评测函数
def time_tensorflow_run(session, target, feed, info_string):
num_steps_burn_in = 10
total_duration = 0.0
total_duration_squared = 0.0
for i in range(num_batches + num_steps_burn_in):
start_time = time.time()
_ = session.run(target, feed_dict = feed)
duration = time.time() - start_time
if i >= num_steps_burn_in:
if not i % 10:
print('%s: step %d, duration = %.3f' %
(datetime.now(), i-num_steps_burn_in, duration))
total_duration += duration
total_duration_squared += duration * duration
mean_dur = total_duration / num_batches
var_dur = total_duration_squared / num_batches - mean_dur * mean_dur
std_dur = math.sqrt(var_dur)
print('%s: %s across %d steps, %.3f +/- %.3f sec / batch' %(datetime.now(), info_string, num_batches, mean_dur, std_dur))
# 定义函数 运行网络
def run_benchmark():
with tf.Graph().as_default():
image_size = 224
images = tf.Variable(tf.random_normal(
[batch_size, image_size, image_size, 3],
dtype = tf.float32, stddev = 1e-1))
keep_prob = tf.placeholder(tf.float32)
predictions, softmax, fc3, p = inference_op(images, keep_prob)
# 创建session ,初始化参数
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init)
# 评测 forward的耗时
time_tensorflow_run(sess, predictions, {keep_prob: 1.0}, 'Forward')
# 评测 forward 和 backward
objective = tf.nn.l2_loss(fc3)
gard = tf.gradients(objective, p)
time_tensorflow_run(sess,gard,predictions, {keep_prob: 0.5}, 'Forward-backward')
batch_size = 16
num_batches = 100
run_benchmark()
函数总结(续上篇)
sess = tf.InteractiveSession() 将sess注册为默认的session
tf.placeholder() , Placeholder是输入数据的地方,也称为占位符,通俗的理解就是给输入数据(此例中的图片x)和真实标签(y_)提供一个入口,或者是存放地。(个人理解,可能不太正确,后期对TF有深入认识的话再回来改~~)
tf.Variable() Variable是用来存储模型参数,与存储数据的tensor不同,tensor一旦使用掉就消失
tf.matmul() 矩阵相乘函数
tf.reduce_mean 和tf.reduce_sum 是缩减维度的计算均值,以及缩减维度的求和
tf.argmax() 是寻找tensor中值最大的元素的序号 ,此例中用来判断类别
tf.cast() 用于数据类型转换
————————————–我是分割线(一)———————————–
tf.random_uniform 生成均匀分布的随机数
tf.train.AdamOptimizer() 创建优化器,优化方法为Adam(adaptive moment estimation,Adam优化方法根据损失函数对每个参数的梯度的一阶矩估计和二阶矩估计动态调整针对于每个参数的学习速率)
tf.placeholder “占位符”,只要是对网络的输入,都需要用这个函数这个进行“初始化”
tf.random_normal 生成正态分布
tf.add 和 tf.matmul 数据的相加 、相乘
tf.reduce_sum 缩减维度的求和
tf.pow 求幂函数
tf.subtract 数据的相减
tf.global_variables_initializer 定义全局参数初始化
tf.Session 创建会话.
tf.Variable 创建变量,是用来存储模型参数的变量。是有别于模型的输入数据的
tf.train.AdamOptimizer (learning_rate = 0.001) 采用Adam进行优化,学习率为 0.001
————————————–我是分割线(二)———————————–
1. hidden1_drop = tf.nn.dropout(hidden1, keep_prob) 给 hindden1层增加Droput,返回新的层hidden1_drop,keep_prob是 Droput的比例
2. mnist.train.next_batch() 来详细讲讲 这个函数。一句话概括就是,打乱样本顺序,然后按顺序读取batch_size 个样本 进行返回。
具体看代码及其注释,首先要找到函数定义,在tensorflow\contrib\learn\python\learn\datasets 下的mnist.py
————————————–我是分割线(三)———————————–
1. tf.nn.conv2d(x, W, strides = [1, 1, 1, 1], padding =’SAME’)对于这个函数主要理解 strides和padding,首先明确,x是输入,W是卷积核,并且它们的维数都是4(发现strides里有4个元素没,没错!就是一一对应的)
先说一下卷积核W也是一个四维张量,各维度表示的信息是:[filter_height, filter_width, in_channels, out_channels]
输入x,x是一个四维张量 ,各维度表示的信息是:[batch, in_height, in_width, in_channels]
strides里的每个元素就是对应输入x的四个维度的步长,因为第2,3维是图像的长和宽,所以平时用的strides就在这里设置,而第1,4维一般不用到,所以是1
padding只有两种取值方式,一个是 padding=[‘VALID’] 一个是padding=[‘SAME’]
valid:采用丢弃的方式,只要移动一步时,最右边有超出,则这一步不移动,并且剩余的进行丢弃。如下图,图片长13,卷积核长6,步长是5,当移动一步之后,已经卷积核6-11,再移动一步,已经没有足够的像素点了,所以就不能移动,因此 12,13被丢弃。
same:顾名思义,就是保持输入的大小不变,方法是在图像边缘处填充全0的像素
————————————–我是分割线(四)———————————–
1.tf.nn.l2_loss()是对一个Tensor对象求L2 norm,这里用来求权值的L2范数
2.tf.add_to_collection(‘losses’, weight_loss), 把weight_loss 加到名为losses的loss中去
3.tf.nn.lrn,做局部相应归一化,来看看函数的定义
lrn(input, depth_radius=None, bias=None, alpha=None, beta=None,name=None)
函数有6个输入,第一个自然是输入啦,2-5是LRN用到的参数,第一个是depth半径,bias alpha beta是相应的参数,来看看伪代码就清楚了
sqr_sum[a, b, c, d] = sum(input[a, b, c, d - depth_radius : d + depth_radius + 1] ** 2)
output = input / (bias + alpha * sqr_sum) ** beta
2-5的参数是有默认值的,分别是5,1,1,0.5
3.tf.nn.sparse_softmax_cross_entropy_with_logits()就是计算交叉熵的,但是如果是一个batch的,得出的是一个向量,还需要配合tf.reduce_mean()才能计算得出最终的loss(标量)
4.tf.get_collection(‘losses’), 从一个集合中取出全部变量,返回的是一个列表,这里是把losses的都取出来,在上面把 weight_loss和输出层的loss都加到losses中了,这个函数就是把losses中的loss取出来
5.tf.add_n:把一个列表的东西都依次加起来 (Adds all input tensors element-wise.) 输入是一个list (inputs: A list of Tensor objects, each with same shape and type.)
————————————–我是分割线(五)———————————–
1.t.get_shape().as_list() ,t是一个tensor,函数以list的形式返回 tensor的shape
2.tf.name_scope(‘conv1’) as scope ,tf.name_scope是用来命名Variable的,print(parameters)可以看到命名
3. tf.Graph().as_default()能够在这个上下文里面覆盖默认的图,测试了一下 不用这个也可以,但是用上好点,可能是避免冲突吧~
————————————–我是分割线(六)———————————–
1. tensor.get_shape()[-1].value 获得 倒数第一个维度上的维数
2. tf.get_variable(scope+’w’,
shape = [kh, kw, n_in, n_out], dtype = tf.float32,
initializer = tf.contrib.layers.xavier_initializer_conv2d())
来看看函数定义:
def get_variable(name,
shape=None,
dtype=None,
initializer=None,
regularizer=None,
trainable=True,
collections=None,
caching_device=None,
partitioner=None,
validate_shape=True,
use_resource=None,
custom_getter=None):
这下就清楚多了,除了第一个形参,其余都是带默认值的关键字参数,这样不根据参形参的顺序对参数赋值啦
3.tf.nn.relu_layer(input_op, kernel, biases, name = scope)
这个函数把 卷积操作,加偏置操作,relu操作 集成在一块儿了,不过这个仅限于全连接层这种一维的层,因为输入必须是2D的,具体如下:
def relu_layer(x, weights, biases, name=None):
Args:
x: a 2D tensor. Dimensions typically: batch, in_units
weights: a 2D tensor. Dimensions typically: in_units, out_units
biases: a 1D tensor. Dimensions: out_units
name: A name for the operation (optional). If not specified
“nn_relu_layer” is used.
Returns:
A 2-D Tensor computing relu(matmul(x, weights) + biases).
Dimensions typically: batch, out_units.
【TensorFlow-windows】(七) CNN之VGG-net的测试的更多相关文章
- 【深度学习系列】用PaddlePaddle和Tensorflow实现经典CNN网络Vgg
上周我们讲了经典CNN网络AlexNet对图像分类的效果,2014年,在AlexNet出来的两年后,牛津大学提出了Vgg网络,并在ILSVRC 2014中的classification项目的比赛中取得 ...
- tensorflow windows
conda create -n py35 python=3.5 activate py35 pip install --ignore-installed --upgrade https://stora ...
- CNN tensorflow text classification CNN文本分类的例子
from:http://deeplearning.lipingyang.org/tensorflow-examples-text/ TensorFlow examples (text-based) T ...
- 基于Tensorflow + Opencv 实现CNN自定义图像分类
摘要:本篇文章主要通过Tensorflow+Opencv实现CNN自定义图像分类案例,它能解决我们现实论文或实践中的图像分类问题,并与机器学习的图像分类算法进行对比实验. 本文分享自华为云社区< ...
- Tensorflow object detection API(1)---环境搭建与测试
参考: https://blog.csdn.net/dy_guox/article/details/79081499 https://blog.csdn.net/u010103202/article/ ...
- Alink漫谈(七) : 如何划分训练数据集和测试数据集
Alink漫谈(七) : 如何划分训练数据集和测试数据集 目录 Alink漫谈(七) : 如何划分训练数据集和测试数据集 0x00 摘要 0x01 训练数据集和测试数据集 0x02 Alink示例代码 ...
- 【深度学习系列】用PaddlePaddle和Tensorflow实现经典CNN网络AlexNet
上周我们用PaddlePaddle和Tensorflow实现了图像分类,分别用自己手写的一个简单的CNN网络simple_cnn和LeNet-5的CNN网络识别cifar-10数据集.在上周的实验表现 ...
- TensorFlow Windows 安装
欢迎大家关注我们的网站和系列教程:http://www.tensorflownews.com/,学习更多的机器学习.深度学习的知识! 本系列教程将手把手带您从零开始学习Tensorflow,并最终通过 ...
- 猫狗识别-CNN与VGG实现
本次项目首先使用CNN卷积神经网络模型进行训练,最终训练效果不太理想,出现了过拟合的情况.准确率达到0.72,loss达到0.54.使用预训练的VGG模型后,在测试集上准确率达到0.91,取得了不错的 ...
随机推荐
- [论文]Coordination of Cluster Ensembles via Exact Methods
作者:Ioannis T. Christou, Member, IEEE IEEE TRANSACTIONS ON PATTERN ANALYSIS AND MACHINE INTELLIGENCE, ...
- Java EE学习记录(一)
话说大家都在说java EE,但是java EE的分层结构如下: 1.数据持久层:主要由一些负责操作POJO(Plain Old Java Object)的类构成,主要负责将数据保存进入数据库; 2. ...
- FTP上传文件服务器python实现
总结 使用Python的socket和socketserver模块实现ftp文件服务器.不是很难,但在粘包的问题上纠缠了不少时间.解决办法是发送文件信息之后等待一段时间. #!/usr/bin/pyt ...
- 转:C#制作ORM映射学习笔记一 自定义Attribute类
之前在做unity项目时发现只能用odbc连接数据库,感觉非常的麻烦,因为之前做web开发的时候用惯了ORM映射,所以我想在unity中也用一下ORM(虽然我知道出于性能的考虑这样做事不好的,不过自己 ...
- hdu 5056(尺取法思路题)
Boring count Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Tota ...
- Smpt命令顺序不正确。 服务器响应为: Error: need EHLO and AUTH first !
刚发现以前做的QQ邮箱发送邮件不能用了,查找了下原因:未加( EnableSsl SSL加密连接 )导致的,顿时觉得很坑,以前QQ邮箱也没有这个限制啊,可能是最近加的. 好吧不多说直接从头走起,照顾 ...
- Graphs (Cakewalk) 1 B - medium
Discription Bear Limak examines a social network. Its main functionality is that two members can bec ...
- 【报错】项目启动,仅仅报错 One or more listeners failed to start. Full details will be found in the appropriate container log file
今天spring4.3.13 项目,整合ActiveMQ的时候,项目启动在自动部署到tomcat下的时候,不能正常的部署,仅仅报错如下: Connected to server [-- ::,] Ar ...
- Git历险记(四)——索引与提交的幕后故事
我想如果看过<Git历险记>的前面三篇文章的朋友可能已经知道怎么用git add,git commit这两个命令了:知道它们一个是把文件暂存到索引中为下一次提交做准备,一个创建新的提交(c ...
- CSS实现鼠标放图片上显示白色边框+文字描写叙述
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...