3.2 TensorFlow
3.2 tensorflow
tensorflow是被工业界和学术界使用最广泛的深度学习框架之一。我们以解决经典的手写数字识别的问题为例,介绍tensorflow的基本使用方法,代码路径为:
https://github.com/duoergun0729/adversarial_examples/blob/master/code/2-tensorflow.ipynb
1. 加载相关库
加载处理经典的手写数字识别的问题相关的python库。
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
from tensorflow.python.framework import graph_util
import os
2. 加载数据集
mnist是一个入门级的计算机视觉数据集,它包含各种手写数字图片如图3-3所示。
它也包含每一张图片对应的标签,告诉我们这个是数字几。比如这四张图片的标签分别是5、0、4、1。数据集包括60000个的训练数据集和10000个的测试数据集,见表3-1。每一个mnist数据单元由两部分组成,即一张包含手写数字的图片和一个对应的标签。
图3-3 mnist图片示例
表3-1 mnist数据集详解
mnist的网址为:http://yann.lecun.com/exdb/mnist/。mnist官网如图3-4所示。
图3-4 mnist官网
mnist默认图像的形状为[28,28,1],为了便于处理,需要改变其形状为一维向量784。另外特征数据需要归一化为0到1,这可以通过除以255来完成。默认的标签的数据类型为整数,取值范围为0到9,为了便于深度学习网络训练,通常会把标签数据转换为独热编码(one hot)。所谓独热编码,又称一位有效编码,其方法是使用n位状态寄存器来对n个状态进行编码,每个状态都有它独立的寄存器位,并且在任意时候,其中只有一位有效。比如标签0到5就可以分别编码为:
000001,000010,000100,001000,010000,100000
3. 定义网络结构
本例中输入层大小为784,隐藏层节点数为300,激活函数为relu,中间为了避免过拟合,使用dropout层,输出层大小为10,激活函数为softmax。为了导出导入pb文件时方便,将输入命名为input,将输出命名为output。网络结构使用工具tensorboard查看,如图3-5所示。
in_units = 784 #输入节点数
h1_units = 300 #隐藏层节点数
#初始化隐藏层权重w1,服从默认均值为0,标准差为0.1的截断正态分布
w1 = tf.variable(tf.truncated_normal([in_units, h1_units], stddev=0.1))
b1 = tf.variable(tf.zeros([h1_units])) #隐藏层偏置b1全部初始化为0
w2 = tf.variable(tf.zeros([h1_units, 10]))
b2 = tf.variable(tf.zeros([10]))
x = tf.placeholder(tf.float32, [none, in_units],name="input")
keep_prob = tf.placeholder(tf.float32,name="keep_prob")
#定义模型结构
hidden1 = tf.nn.relu(tf.matmul(x, w1) + b1)
hidden1_drop = tf.nn.dropout(hidden1, keep_prob)
y = tf.nn.softmax(tf.matmul(hidden1_drop, w2) + b2,name="output")
图3-5 tensorflow处理mnist的网络结构图
4. 定义损失函数和优化器
完成了前向传播的定义,就需要定义损失函数和优化器,便于训练阶段进行反向传递。本例为多分类问题,故使用交叉熵定义损失函数,使用adagrad优化器。
y_ = tf.placeholder(tf.float32, [none, 10])
cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y),
reduction_indices=[1]))
train_step = tf.train.adagradoptimizer(0.3).minimize(cross_entropy)
5. 训练与验证
初始化参数,迭代训练5000轮,每轮训练的批处理大小为100,为了抵御过拟合,每次训练时仅通过75%的数据。每训练200批次,打印中间结果。
sess.run(tf.global_variables_initializer())
correct_prediction = tf.equal(tf.arg_max(y, 1), tf.arg_max(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
for i in range(5000):
batch_xs, batch_ys = mnist.train.next_batch(100)
_,loss=sess.run([train_step,cross_entropy],{x: batch_xs, y_: batch_ys, keep_prob: 0.75})
if i % 200 == 0:
acc=accuracy.eval(feed_dict={x:mnist.test.images,
y_:mnist.test.labels,keep_prob:1})
print("loss={},acc={}".format(loss,acc))
经过5000轮训练,准确度达到98%。
loss=0.021222606301307678,acc=0.9814000129699707
loss=0.04722728207707405,acc=0.9786999821662903
loss=0.024759886786341667,acc=0.9797000288963318
loss=0.009720790199935436,acc=0.9803000092506409
tensorflow是被工业界和学术界使用最广泛的深度学习框架之一。我们以解决经典的手写数字识别的问题为例,介绍tensorflow的基本使用方法,代码路径为:
https://github.com/duoergun0729/adversarial_examples/blob/master/code/2-tensorflow.ipynb
1. 加载相关库
加载处理经典的手写数字识别的问题相关的python库。
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
from tensorflow.python.framework import graph_util
import os
2. 加载数据集
mnist是一个入门级的计算机视觉数据集,它包含各种手写数字图片如图3-3所示。
它也包含每一张图片对应的标签,告诉我们这个是数字几。比如这四张图片的标签分别是5、0、4、1。数据集包括60000个的训练数据集和10000个的测试数据集,见表3-1。每一个mnist数据单元由两部分组成,即一张包含手写数字的图片和一个对应的标签。
图3-3 mnist图片示例
表3-1 mnist数据集详解
mnist的网址为:http://yann.lecun.com/exdb/mnist/。mnist官网如图3-4所示。
图3-4 mnist官网
mnist默认图像的形状为[28,28,1],为了便于处理,需要改变其形状为一维向量784。另外特征数据需要归一化为0到1,这可以通过除以255来完成。默认的标签的数据类型为整数,取值范围为0到9,为了便于深度学习网络训练,通常会把标签数据转换为独热编码(one hot)。所谓独热编码,又称一位有效编码,其方法是使用n位状态寄存器来对n个状态进行编码,每个状态都有它独立的寄存器位,并且在任意时候,其中只有一位有效。比如标签0到5就可以分别编码为:
000001,000010,000100,001000,010000,100000
3. 定义网络结构
本例中输入层大小为784,隐藏层节点数为300,激活函数为relu,中间为了避免过拟合,使用dropout层,输出层大小为10,激活函数为softmax。为了导出导入pb文件时方便,将输入命名为input,将输出命名为output。网络结构使用工具tensorboard查看,如图3-5所示。
in_units = 784 #输入节点数
h1_units = 300 #隐藏层节点数
#初始化隐藏层权重w1,服从默认均值为0,标准差为0.1的截断正态分布
w1 = tf.variable(tf.truncated_normal([in_units, h1_units], stddev=0.1))
b1 = tf.variable(tf.zeros([h1_units])) #隐藏层偏置b1全部初始化为0
w2 = tf.variable(tf.zeros([h1_units, 10]))
b2 = tf.variable(tf.zeros([10]))
x = tf.placeholder(tf.float32, [none, in_units],name="input")
keep_prob = tf.placeholder(tf.float32,name="keep_prob")
#定义模型结构
hidden1 = tf.nn.relu(tf.matmul(x, w1) + b1)
hidden1_drop = tf.nn.dropout(hidden1, keep_prob)
y = tf.nn.softmax(tf.matmul(hidden1_drop, w2) + b2,name="output")
图3-5 tensorflow处理mnist的网络结构图
4. 定义损失函数和优化器
完成了前向传播的定义,就需要定义损失函数和优化器,便于训练阶段进行反向传递。本例为多分类问题,故使用交叉熵定义损失函数,使用adagrad优化器。
y_ = tf.placeholder(tf.float32, [none, 10])
cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y),
reduction_indices=[1]))
train_step = tf.train.adagradoptimizer(0.3).minimize(cross_entropy)
5. 训练与验证
初始化参数,迭代训练5000轮,每轮训练的批处理大小为100,为了抵御过拟合,每次训练时仅通过75%的数据。每训练200批次,打印中间结果。
sess.run(tf.global_variables_initializer())
correct_prediction = tf.equal(tf.arg_max(y, 1), tf.arg_max(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
for i in range(5000):
batch_xs, batch_ys = mnist.train.next_batch(100)
_,loss=sess.run([train_step,cross_entropy],{x: batch_xs, y_: batch_ys, keep_prob: 0.75})
if i % 200 == 0:
acc=accuracy.eval(feed_dict={x:mnist.test.images,
y_:mnist.test.labels,keep_prob:1})
print("loss={},acc={}".format(loss,acc))
经过5000轮训练,准确度达到98%。
loss=0.021222606301307678,acc=0.9814000129699707
loss=0.04722728207707405,acc=0.9786999821662903
loss=0.024759886786341667,acc=0.9797000288963318
loss=0.009720790199935436,acc=0.9803000092506409