新手初识Tensorflow

前些日子偶然接触到Tensorflow,作为一名新手,本人根据Tensorflow中文社区中的文档进行了基础部分的学习,并对学习过程以及学习过程中的问题一并进行了记录。

根据本机代码结果整理出这篇文档,希望对大家有所帮助。如果本文任何地方的表述或某些个人理解有所不妥,欢迎各位大神批评指正。

注:若本机代码实验运行结果与官方文档不符,本文中的结果记录为本机运行结果。

另注:本文有点小长且有些枯燥……

本文参考:Tensorflow中文社区

 

【零】Tensorflow介绍:

TensorFlow是一个非常强大的,用来做大规模数值计算的库,其所擅长的任务之一就是实现以及训练深度神经网络。

采用数据流图(data flow graphs),用于数值计算;
节点(nodes)表示数学操作,被称为op(operation);
线(edges)表示在节点间相互联系的n维数据数组——张量(tensor);
一个op获得0个或多个tensor执行计算,产生0个或多个tensor。

Tensorflow使用图(graph)表示计算任务;
在会话(session)的上下文(context)中执行图,调用Session.run()方法执行操作(Session对象使用之后需要关闭以释放资源,个人理解类似C语言中的malloc或C++中的new);
使用张量(tensor)表示数据,一个tensor包含一个静态类型rank和一个shape;
通过变量(variable)维护图执行过程中的状态信息;
使用feed、fetch为任意操作赋值或获取数据。

图必须在会话里被启动,会话将op分发到GPU或CPU一类的设备上,同时提供执行op的方法,这些方法执行后,将产生的tensor返回。

Tensorflow程序通常被组织成一个构建阶段和一个执行阶段:
【构建阶段】op的执行步骤被描述成一个图(创建一个图表示和训练神经网络)
【执行阶段】使用会话执行图中的op(反复执行图中的训练op)

【一】会话(session)关闭的两种方式:
import tensorflow as tf
m1 = tf.constant([[3.,3.]])
m2 = tf.constant([[3.],[2.]])
p = tf.matmul(m1,m2)

1.显式调用close方法:
  sess = tf.Session()
  result = sess.run(p)
  print result
  sess.close()
2.利用with代码块执行图后自动关闭:
  with tf.Session() as sess:
    result = sess.run(p)
    print result

实验.
若:
m1 = tf.constant([[3.,3.]])
m2 = tf.constant([[3.],[2.]])
result = sess.run(p)
#则输出结果为:[[ 15.]]
result = sess.run([p])
#则输出结果为:[array([[ 15.]], dtype=float32)]

若:
m1 = tf.constant([[3,3]])
m2 = tf.constant([[3],[2]])
result = sess.run(p)
#则输出结果为:[[15]]
result = sess.run([p])
#则输出结果为:[array([[15]], dtype=int32)]

总结.
矩阵中元素后加小数点则张量类型为float32,不加小数点则张量类型为int32(类似C语言或python中的类型定义方式)。

【二】Session与InteractiveSession:
Tensorflow依赖于一个高效C++后端进行计算,利用session与后端进行连接。一般来讲,使用Tensorflow程序的流程是先创建图,再在session中启动。
Python交互环境中,可以使用InteractiveSession类代替Session类,利用它可以更加灵活地构建代码。
利用Tensor.eval()、Operation.run()方法代替Session.run()方法,避免使用变量持有会话(提高灵活性)。
InteractiveSession可以在运行图的时候插入由某些op构成的计算图(适合交互式环境),可以先构建session再定义操作;
Session要在启动Session前构建整个图,需要在构建会话前定义好全部操作。
eg:
import tensorflow as tf
sess = tf.InteractiveSession()

x = tf.Variable([1.0, 2.0])
a = tf.constant([3.0, 3.0])

x.initializer.run()    #使用初始化器initializer的run()方法对x进行初始化(详见第四部分)

sub = tf.sub(x, a)
print sub.eval()

【三】张量的阶、形状和数据类型
1.阶:张量维数的数量描述
eg:
t = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]为二阶
零阶张量:纯量(s = 4)
一阶张量:向量(v = [1,2,3])
二阶张量:矩阵(m = [[1, 2, 3], [4, 5, 6], [7, 8, 9]])    #可用语句t[i,j]访问
三阶张量:立体数据(t = [[[2], [4], [6]], [[8], [10], [12]], [[14], [16], [18]]])    #可用语句t[i,j,k]访问

2.形状:描述张量维度的三种记号:阶、形状、维度
阶   形状                         维数     
0     [ ]                             0-D     
1     [D0]                         1-D     
2     [D0, D1]                   2-D     
3     [D0, D1, D2]            3-D     
n     [D0, D1, ... Dn-1]     n-D     

3.数据类型:tensors的数据类型属性
数据类型               Python 类型            描述
DT_FLOAT              tf.float32               32 位浮点数.
DT_DOUBLE          tf.float64               64 位浮点数.
DT_INT64               tf.int64                   64 位有符号整型.
DT_INT32               tf.int32                   32 位有符号整型.
DT_INT16               tf.int16                   16 位有符号整型.
DT_INT8                 tf.int8                      8 位有符号整型.
DT_UINT8              tf.uint8                   8 位无符号整型.
DT_STRING            tf.string                  可变长度的字节数组.每一个张量元素都是一个字节数组.
DT_BOOL               tf.bool                    布尔型.
DT_COMPLEX64    tf.complex64        由两个32位浮点数组成的复数:实数和虚数.
DT_QINT32            tf.qint32                 用于量化Ops的32位有符号整型.
DT_QINT8              tf.qint8                    用于量化Ops的8位有符号整型.
DT_QUINT8           tf.quint8                 用于量化Ops的8位无符号整型.

【四】变量
通常会将一个统计模型中的参数表示为一组变量,变量必须进行初始化之后才有具体值。
例如, 将一个神经网络的权重作为某个变量存储在一个tensor中.在训练过程中, 通过重复运行训练图, 更新这个tensor。
eg:
state = tf.Variable(0, name = "counter")

one = tf.constant(1)
new_value = tf.add(state, one)
update = tf.assign(state, new_value)    #assign()将new_value赋值给state

init_op = tf.initialize_all_variables()    #启动图后, 变量必须先经过op初始化, 增加一个初始化op到图中

with tf.Session() as sess:
  sess.run(init_op)    #运行 'init' op
  print sess.run(state)
  for _ in range(3):
    sess.run(update)
    print sess.run(state)

输出:
0
1
2
3
 

Q.

该程序中,init_op=tf.initialize_all_variables() + sess.run(init_op)是否可以利用state.initialize.run()代替?

A.

可以,但要注意state.initialize.run()要在sess定义之后运行(本例中with语句后)。
否则会提示会话未创建信息:
ValueError: Cannot execute operation using `run()`: No default session is registered. Use `with sess.as_default():` or pass an explicit session to `run(session=sess)`
且对所有变量均需要进行初始化操作。

 

Q.

是否可以不对变量进行初始化操作?

A.

不可以。

以本例为例,不进行初始化操作将会进行如下报错:
tensorflow.python.framework.errors_impl.FailedPreconditionError: Attempting to use uninitialized value counter
     [[Node: _retval_counter_0_0 = _Retval[T=DT_INT32, index=0, _device = "/job:localhost/replica:0/task:0/device:CPU:0"](counter)]]

 

Q.

state = tf.Variable(0, name = "counter")一句中name = "counter"的作用是什么?

A.

用name关键字定义的节点和张量名称,是模型本身的一部分,会和模型一起存储到checkpoint或SavedModel里面去(训练的结果),可以被其他语言所调用(C++,Java等)。


【五】fetch机制
为取回操作的输出内容,在使用Session对象的run()调用执行图时,可以传入tensor,让这些tensor取回结果(可以取回多个tensor)。
eg:
input1 = tf.constant(3.0)
input2 = tf.constant(2.0)
input3 = tf.constant(5.0)
intermed = tf.add(input2, input3)
mul = tf.mul(input1, intermed)

with tf.Session() as sess:
  result = sess.run([mul, intermed])
  print result

输出:
[21.0, 7.0](本机输出与Tensorflow中文社区官方文档中的输出不同)

实验.
而若代码改为:
intermed = tf.add([input2], [input3])
mul = tf.multiply([input1], [intermed])
则输出结果为:

 

[array([[ 21.]], dtype=float32), array([ 7.], dtype=float32)]

总结.
Session.run()方法参数为矩阵(维度为2)时,将返回各元素数据类型等信息。
(注:注意区分张量维度)

【六】feed机制
TensorFlow提供了feed机制,该机制可以临时替代图中的任意操作中的tensor,可以对图中任何操作提交补丁,直接插入一个tensor。
feed使用一个tensor值临时替换一个操作的输出结果:提供feed数据作为run()调用的参数。
feed只在调用它的方法内有效,方法结束,feed 就会消失。
最常见的用例是将某些特殊的操作指定为"feed"操作,标记的方法是使用tf.placeholder()为这些操作创建占位符。
eg:
input1 = tf.placeholder(tf.float32)
input2 = tf.placeholder(tf.float32)
output = tf.multiply(input1, input2)

with tf.Session() as sess:
  print sess.run([output], feed_dict = {input1:[7.], input2:[2.]})

输出:
[array([ 14.], dtype=float32)]

与第五部分相同:
若赋值字典改为feed_dict = {input1:7., input2:2.}
输出为:[14.0]

(注:Tensorflow中文社区官方文档中的一些API诸如tf.mul(),tf.sub()已经弃用,需要改为tf.multiply()或tf.subtract())

【七】模型建立
1.建立抽象模型(很重要)

 

 

利用所建立的模型进行训练。

2.定义损失函数和训练方法
定义损失函数值为loss;
训练方法一般为梯度下降法:optimizer = tf.train.GradientDescentOptimizer(rateOfStudy);

 

 

参数rateOfStudy为学习速率,一般无定值,根据经验进行确定,且很多算法(SSD、YOLO等)在训练过程中可以多该参数进行改动。

3.确定训练目标
训练目标一般为将损失函数降到最低(loss减小):train = optimizer.minimize(cross_entropy)。

【八】MNIST数据集
60000行的训练数据集 + 10000行的测试数据集
MINST数据单元由两部分组成:手写数字图片(mnist.train.image)、对应标签(mnist.train.labels)

图片:每张图片由28*28(784)个像素点构成,故mnist.train.image是一个形状为[60000,784]的张量,60000用作图片索引,784用所像素点索引。该张量(矩阵)中的每个元素表示某图片中某像素点的强度值p,0<p<1。

标签:介于0-9的数字,用来描述图片中的数字。利用 "one-hot vectors" 表示标签数据,一个one-hot向量只有一位数字为1,其余维度数字均为0,故数字n表示为在第n维数字为1的10维向量(例如,标签0被表示为([1,0,0,0,0,0,0,0,0,0,0]))。
即,mnist.train.labels是一个[60000, 10]的数字矩阵。

【九】Softmax回归
MNIST中每张图片均表示一个数字,希望得到某图片代表每个数字的概率。
即,模型推测一张包含9的图片代表数字9的概率是80%,而判断其为8的概率为5%,它代表其它数字的概率可能更小。

 

 

softmax模型可以用于给不同的对象分配概率。

softmax回归分为两步:
1.
对图片像素值进行加权求和,为得到一张图片属于某数字类的证据(evidence):

 

 

如果该像素有很强的证据说明该图片不属于此类,则相应权值为负;若该像素拥有有利的证据支持该图片属于此类,则权值为正。

2.
由于输入往往带入某些无关的干扰量,故加入额外偏置量(bias)。

对于给定的输入图片x,它代表的数字为i的证据可以表示为:
evidence(i) = ∑W(i,j) * x(j) + b(i)
其中,W表示权重,b(i)表示数字i类的偏置量,j表示给定图片x的像素索引用于像素求和.利用softmax函数将证据转化为概率y:
y = softmax(evidence)
更进一步,我们可以将上式写为:
y = softmax(W*x+b)

其中,softmax可以看作一个激励函数或链接函数,将定义的线性函数的输出转换为10个数字类的概率分布(我们想要的格式)。
因此,给定一张图片,它对于每个数字的吻合度可以被softmax函数转换为一个概率值,该函数可定义为:
softmax(x) = normalize(exp(x))
将输入当成幂指数求值,再正则化结果值.幂运算表示更大的证据对应更大的假设模型里面的乘数权重,更少的证据意味着在假设模型中拥有更小的乘数系数.假设模型中不允许权值W<=0,softmax将权重值正则化,使它们总和为1,以此构造有效的概率分布。

【十】实现回归模型
Tensorflow先用图描述一系列可交互的计算操作,然后全部一起在python之外运行。

用x表示所有输入的MNIST图像像素的二维数组,输入的图像个数在定义图时无法确定,希望在运行计算时进行输入,而每一张图展平成784维的向量。
用二位浮点数张量x表示这些图,将x设置为一个占位符placeholder(因为图像个数无法确定,所以创建占位符先进行“占位”)。
x = tf.placeholder("float", [None, 784])
其中,None表示此张量的第一个维度可以为任何长度(任意图像个数)。

W、b为模型参数,可以在训练过程中被修改,设置为变量Variable。
W = tf.Variable(tf.zeros([784,10]))
b = tf.Variable(tf.zeros([10]))
由于W、b是需要学习的值,所以他们的初值可以随意设置(训练过程中更改)。
注:
W的维度是[784,10],因为要用784维的图片向量乘以它得到一个10维的证据值向量,每一位对应不同数字类;
b的形状是[10],可以直接把它加到输出上面。

定义模型:
y = tf.nn.softmax(tf.matmul(x,W) + b)

【十一】训练模型
定义指标表示模型的好坏,该指标被成为成本(cost)或损失(loss),然后最小化该loss(或cost)。
一种较为常见的成本函数是交叉熵(cross-entropy),定义如下:
Hy'(y)=-∑y(i)' * log(y(i))
其中,y是预测的概率分布,y'是实际分布(输入的one-hot vector)。

为了计算交叉熵,添加一个新的占位符输入正确值:
y_ = tf.placeholder("float", [None,10])
计算交叉熵:
cross_entropy = -tf.reduce_sum(y_*tf.log(y))

Tensorflow有一张描述上述各计算单元的图,它自动确定变量如何影响最小化的成本值(使用反向传播算法),然后Tensorflow会利用选择的优化算法不断修改变量,降低loss(cost)。

梯度下降算法:
train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)
梯度下降算法是一个简单的学习过程,Tensorflow将每个变量一点点向成本不断降低的方向移动:
上面一行中的梯度下降算法以0.01的学习速率最小化交叉熵。

在运行计算之前,需要添加一个操作初始化变量:
init = tf.initialize_all_variables()
在Session中启动模型并初始化变量:
sess = tf.Session()
sess.run(init)
然后开始训练模型(本例中模型循环训练1000次):
for i in range(1000):
  batch_xs, batch_ys = mnist.train.next_batch(100)    #随机抓取100个批处理数据点
  sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})    #利用抓取的数据点替换之前的占位符运行train_step

【十二】评估模型
1.找出预测正确的标签.
tf.argmax函数:可以给出某tensor对象在某一维上的数据最大值所在的索引值。
标签向量由0,1组成,最大值即为1,索引位置即为类别标签。
tf.argmax(y,1)返回的是模型对于任一输入y预测到的标签值,tf.argmax(y_,1)代表正确的标签,可以用tf.equal检测预测是否正确。

correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))
该行代码会给出一组布尔值,可以将其转换为浮点数然后取平均值以确定正确预测项的比例。

accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
[True, False, True, True] 会变成 [1,0,1,1] ,取平均值后得到 0.75。

最后,计算所学习到的模型在测试数据集上的正确率.
print sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels})

【十三】计算图
为了在Python中进行高效数值计算,通常利用numpy一类的库将耗时操作在python外部进行计算(通过其他语言更为高效的代码来实现,各种各样丰富的库也是python最牛的地方之一)。
Python代码的目的是用来构建这个可以在外部运行的计算图,安排计算图的哪一部分应该被运行。

【十四】构建Softmax回归模型
(建立一个拥有一个线性层的softmax回归模型)
通过为输入图像和目标输出类别创建节点,开始构建计算图:
x = tf.placeholder("float", shape=[None, 784])
y_ = tf.placeholder("float", shape=[None, 10])
x,y_可以在Tensorflow运行某一计算时根据该占位符输入具体的值。
x:二维浮点数张量,shape为[None,784],784为一张展平的MNIST图片维度,None作为第一个维度值,指代batch大小(x数量不定).
y_:二维浮点数张量,每一行为一个10维的one-hot向量,代表某一MNIST图片类别。
(注:placeholder占位符的shape参数可选,但有了shape,Tensorflow可以自动捕捉因数据维度不一致导致的错误)

W = tf.Variable(tf.zeros([784,10]))
b = tf.Variable(tf.zeros([10]))
变量可以在计算过程中使用,甚至进行修改。
在机器学习的过程中,模型参数(模型需要每轮改变学习得到的参数值,有些参数值即为模型训练过后得到的结果)一般用变量Variable来表示。

sess.run(tf.initialize_all_variables())
变量需要通过session初始化后才可以使用,可一次性为所有变量完成此操作。

y = tf.nn.softmax(tf.matmul(x,W) + b)
cross_entropy = -tf.reduce_sum(y_*tf.log(y))
注意,tf.reduce_sum把minibatch里的每张图片的交叉熵值都加起来了,我们计算的交叉熵是指整个minibatch的。

train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)
用来向计算图中添加新操作,包括计算梯度,计算每个参数的步长变化,并计算新的参数值。
返回的train_step操作对象,在运行时会使用梯度下降来更新参数,因此,整个模型的训练可以通过反复地运行train_step来完成。

for i in range(1000):
  batch = mnist.train.next_batch(50)
  train_step.run(feed_dict={x: batch[0], y_: batch[1]})
每一步迭代加载50个训练样本,然后执行一次train_step,通过feed_dict将x和y_张量占位符用训练数据替代。
(注:在计算图中可以用feed_dict来替代任何张量,并不仅限于替换占位符)

correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
print accuracy.eval(feed_dict={x: mnist.test.images, y_: mnist.test.labels})

【十五】创建多层卷积网络
1.权重初始化
为创建该模型,需要创建大量权重和偏置项,该模型中的权重在初始化时应该加入少量的噪声打破对称性以及避免0梯度。
由于使用的是ReLU神经元,因此较好的做法是用一个较小的正数初始化偏置项,以避免神经元节点输出恒为0的问题(dead neurons)。
为了不反复进行初始化操作,定义两个函数用于初始化:
def weight_variable(shape):
  initial = tf.truncated_normal(shape, stddev=0.1)
  return tf.Variable(initial)

def bias_variable(shape):
  initial = tf.constant(0.1, shape=shape)
  return tf.Variable(initial)

函数分析.
tf.truncated_normal(shape, mean, stddev):
shape表示张量维度,mean为均值,stddev为标准差。

 

 

该函数产生正态分布,均值和标准差由使用者自行设定,如果产生正态分布的值与均值差值大于两倍的标准差,则重新生成。

 

 

函数分析.
tf.constant(value, shape):
创建一个常量tensor,按照给出value来赋值,可以用shape来指定其形状,value可以是一个数,也可以是一个list:
如果是一个数,那么这个常量中所有值的按该数来赋值;

如果是list,那么len(value)一定要小于等于shape展开后的长度。赋值时,先将value中的值逐个存入,不够的部分全部存入value的最后一个值。

 

2.卷积、池化

 

对卷积和池化不了解的朋友们可以参看本人另外一篇博客:

机器学习中的一些基本概念(未完待续)

Tensorflow在卷积、池化上有很强的灵活性(包括怎样处理边界,步长应该设多大),在该实例中,一直使用vanilla版本。
卷积使用1步长(stride size)、0边距(padding size)的模板,保证输入输出是同一个大小。
池化用简单传统的2*2大小的模板作max pooling,为了代码更简洁,该部分被抽象成一个函数:
def conv2d(x, W):
  return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')

def max_pool_2x2(x):
  return tf.nn.max_pool(x, ksize=[1, 2, 2, 1],
                        strides=[1, 2, 2, 1], padding='SAME')

函数分析.
tf.nn.conv2d(input, filter, strides, padding, use_cudnn_on_gpu=None, name=None):
除去name参数用以指定该操作的name,与该方法有关的参数一共有5个:
【input】
指需要做卷积的输入图像,要求是一个tensor,具有[batch,in_height,in_weight,in_channels]这样的shape,表示[训练时一个batch的图片数量,图片高度,图片宽度,图片通道数],这是一个四维的tensor,要求类型为float32或float64。

【filter】
相当于CNN中的卷积核,要求是一个tensor,具有[filter_height,filter_width,in_channels,out_channels]这样的shape,表示[卷积核的高度,卷积核的宽度,图像通道数,卷积核个数],要求类型与参数input相同,其中,第三维in_channels就是参数input的第四维。

【strides】
卷积在图像每一维的步长,一个一维向量,长度为4。

【padding】
string类型的量,只能是“SAME”、“VALID”其中之一,决定了不同的卷积方式。

【use_cudnn_on_gpu】
bool类型,是否使用cudnn加速,默认为true。

结果返回一个tensor,该输出即为我们常说的feature map。
 

Q.

图像如何转化成tensor中的数字?(像素点中存储的是什么?)

A.

像素点中存储的即为数字。
(例如,GBR方式存储0-255的数字)


函数分析2.
tf.nn.max_pool(value, ks计组据说是计算机专业最难的课程ize, strides, padding, name=None):
参数有4个,与卷积类似:
【value】
需要池化的输入,一般来讲,池化层接在卷积层后面,所以输入通常是feature map,依然是[batch,height,weight,channels]这样的shape。

【ksize】
池化窗口大小,取一个四维向量,一般是[1,height,width,1],因为不想在batch和channels上做池化,所以这两个维度设为1。

【strides】
和卷积类似,窗口在每个维度上滑动的步长,一般也是[1,stride,stride,1]。

【padding】
和卷积类似,可以取“VALID”或“SAME”。

结果返回一个tensor,类型不变,shape依然是[batch,height,weight,channels]这种形式。

 

3.第一层卷积

第一层:由一个卷积接一个max pooling完成。
卷积在每个5*5的patch中算出32个特征,卷积的权重张量形状是[5,5,1,32],前两个维度是patch的大小,接着是输入的通道数,最后是输出的通道数,对每个输出通道都有一个对应的偏移量。
W_conv1 = weight_variable([5, 5, 1, 32])
b_conv1 = bias_variable([32])

为了用这一层,我们把x变成一个4d向量,其第2、第3维对应图片的宽、高,最后一维代表图片的颜色通道数。
(因为是灰度图所以这里的通道数为1,如果是rgb彩色图,则为3)。
x_image = tf.reshape(x, [-1,28,28,1])

我们把x_image和权值向量进行卷积,加上偏置项,然后应用ReLU激活函数,最后进行max pooling。
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
h_pool1 = max_pool_2x2(h_conv1)

4.第二层卷积
为了构建一个更深的网络,我们会把几个类似的层堆叠起来。
第二层中,每个5x5的patch会得到64个特征。
W_conv2 = weight_variable([5, 5, 32, 64])
b_conv2 = bias_variable([64])

h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
h_pool2 = max_pool_2x2(h_conv2)

5.密集连接层
现在,图片尺寸减小到7x7,我们加入一个有1024个神经元的全连接层,用于处理整个图片。
我们把池化层输出的张量reshape成一些向量,乘上权重矩阵,加上偏置,然后对其使用ReLU。
W_fc1 = weight_variable([7 * 7 * 64, 1024])
b_fc1 = bias_variable([1024])

h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64])
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)
 

6.Dropout

对dropout不了解的朋友们可以参看本人另外一篇博客:

机器学习中的一些基本概念(未完待续)

为了减少过拟合,在输出层之前加入dropout。
用一个placeholder代表一个神经元的输出在dropout中保持不变的概率,这样可以在训练过程中启用dropout而在测试过程中关闭它.Tensorflow的tf.nn.dropout操作除了可以屏蔽神经元的输出外,还会自动处理神经元输出值的scale,所以用dropout时可以不用考虑scale。
keep_prob = tf.placeholder("float")
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)

7.输出层
最后,添加一个softmax层,就像之前的单层softmax regression一样。
W_fc2 = weight_variable([1024, 10])
b_fc2 = bias_variable([10])

y_conv=tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)

8.训练和评估模型
为了进行训练和评估,我们使用与之前简单的单层SoftMax神经网络模型几乎相同的一套代码。
只是我们会用更加复杂的ADAM优化器来做梯度最速下降,在feed_dict中加入额外的参数keep_prob来控制dropout比例.
每100次迭代输出一次日志。
cross_entropy = -tf.reduce_sum(y_*tf.log(y_conv))
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
correct_prediction = tf.equal(tf.argmax(y_conv,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
sess.run(tf.initialize_all_variables())
for i in range(20000):
  batch = mnist.train.next_batch(50)
  if i%100 == 0:
    train_accuracy = accuracy.eval(feed_dict={
        x:batch[0], y_: batch[1], keep_prob: 1.0})
    print "step %d, training accuracy %g"%(i, train_accuracy)
  train_step.run(feed_dict={x: batch[0], y_: batch[1], keep_prob: 0.5})

print "test accuracy %g"%accuracy.eval(feed_dict={

    x: mnist.test.images, y_: mnist.test.labels, keep_prob: 1.0})

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值