4 TensorFlow1.x的反向传播推导与实现
第四讲 神经网络实现过程(步骤1~3是训练过程 步骤4是使用过程)
1、准备数据集,提取特征,作为输入喂给神经网络(neural network,NN) 2、搭建NN结构,从输入到输出(先搭建计算图,再用会话执行) (NN前向传播算法–>计算输出)
3、大量特征数据喂给NN,迭代优化NN参数 (NN反向传播算法–>优化NN参数) 反向传播训练方法:以减小loss值为优化目标,分别有3种不同的方法可以使用——梯度下降、momentum优化器、adam优化器等 4、使用训练好的模型预测和分类
前向传播:搭建神经网络模型,让神经网络NN实现推理过程
计算节点模板 #变量初始化,计算图节点运算都有要用会话(with结构)实现
with tf.Session() as sess:
# sess.run()
#变量初始化:在sess.run函数中用tf.global_variables_initializer()
init__op=tf.global_variables()
sess.run(init__op)
#计算图节点运算:在sess.run函数中写入待运算的节点
sess.run(y)
————————————————
版权声明:本文为CSDN博主「Enigmalgia」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_39104294/article/details/85091093
#用tf.plaeholder 占位,在sess.run函数中用feed_dict喂数据
# 如果一次喂一组数据shape的第一维位置写1,第二维位置看有几个输入特征;
# 如果一次想喂多组数据,shape的第一维位置可以写None表示先空着,第二维位置写有几个输入特征。
# 喂一组数据:
x=tf.placeholder(tf.float32,shape=(1,2)) #这里定义了x是一行两列的矩阵
sess.run(y,feed_dict={x:[[0.5,0.6]]})
# 喂多组数据:
x=tf.placeholder(tf.float32,shape=(None,2))
sess.run(y,feed_dict={x:[[0.1,0.2],[0.2,0.3],[0.3,0.4],[0.4,0.5]]}) #feed_dict={} 用字典把特征喂入
———————————————— 版权声明:本文为CSDN博主「Enigmalgia」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/weixin_39104294/article/details/85091093
tf.placeholder 实现输入定义 喂入多组数据给神经网络,注意tf.placeholder()函数中的参数的赋值变化
#!/user/bin/env python3
# -*- coding: utf-8 -*-
# 两层简单神经网络(全连接)
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
import tensorflow as tf
# 定义输入和参数
# 用placeholder定义输入(sess.run喂多组数据)
x = tf.placeholder(tf.float32, shape=(None, 2))
# shape的第一个参数是None表示不知道,这样在with结构中可以一次喂入多组输入;
# shape的第二个参数为2,因为我们已经知道了x的输入是体积和重量这两个特征
w1 = tf.Variable(tf.random_normal([2, 3], stddev=1, seed=1))
w2 = tf.Variable(tf.random_normal([3, 1], stddev=1, seed=1))
# 定义前向传播过程
a = tf.matmul(x, w1)
y = tf.matmul(a, w2)
# 到此为止 神经网络创建完成
# 调用会话计算结果
with tf.Session() as sess:
init_op = tf.global_variables_initializer()
sess.run(init_op)
print("result:")
print(sess.run(y, feed_dict={x: [[0.7,0.5],[0.2,0.3],[0.3,0.4],[0.4,0.5]]}))
print("w1:")
print(sess.run(w1))
print("w2:")
print(sess.run(w2))
'''
result:
[[ 3.0904665 ]
[ 1.2236414 ]
[ 1.72707319]
[ 2.23050475]]
w1:
[[-0.81131822 1.48459876 0.06532937]
[-2.4427042 0.0992484 0.59122431]]
w2:
[[-0.81131822]
[ 1.48459876]
[ 0.06532937]]
'''
p16代码实现
#coding:utf-8 #0导入模块,生成模拟数据集。 #tensorflow学习笔记(北京大学) tf3_6.py 完全解析神经网络搭建学习 #QQ群:476842922(欢迎加群讨论学习
start = (i*BATCH_SIZE) % 32 #i8%32 计算取数据集的下标 32个为一组 end = start + BATCH_SIZE #i8%32+8 计算取标签的下标
import tensorflow as tf
# 导入python的科学计算模块 numpy
import numpy as np
# 定义一次喂入神经网络的数据量 数据不宜过大
BATCH_SIZE = 8
SEED = 23455
rdm = np.random.RandomState(SEED)
X = rdm.rand(32,2) #32组表示两个参数的输入数据集
Y_ = [[int(x0 + x1 < 1)] for (x0, x1) in X] #x0 + x1 < 1时Y=1
print("X:\n",X)
print("Y_:\n",Y_)
x = tf.placeholder(tf.float32, shape=(None, 2))#用placeholder实现输入定义,none表示输入x的数组数有多个,2表示体积和重量两个特征
y_= tf.placeholder(tf.float32, shape=(None, 1))#用placeholder实现占位。1表示输出的特征只有一个特征,就是标签的可能性,只有合格或不合格
w1= tf.Variable(tf.random_normal([2, 3], stddev=1, seed=1))#正态分布随机数。2个输入,对应3个神经元
w2= tf.Variable(tf.random_normal([3, 1], stddev=1, seed=1))#正态分布随机数。3个神经元,对应1个输出
a = tf.matmul(x, w1)#点积
y = tf.matmul(a, w2)#点积
#2定义损失函数及反向传播方法。
loss_mse = tf.reduce_mean(tf.square(y-y_)) # y_是预测值
train_step = tf.train.GradientDescentOptimizer(0.001).minimize(loss_mse)#梯度下降法优化用于减少loss,0.001是学习率,可以选择不同优化器
#train_step = tf.train.MomentumOptimizer(0.001,0.9).minimize(loss_mse)不同的优化器
#train_step = tf.train.AdamOptimizer(0.001).minimize(loss_mse)不同的优化器
#3生成会话,训练STEPS轮
with tf.Session() as sess:
init_op = tf.global_variables_initializer()#初始化
sess.run(init_op)
# 输出目前(未经训练)的参数取值。
print("w1:\n", sess.run(w1))
print("w2:\n", sess.run(w2))
print("\n")
# 训练模型。
STEPS = 3000 #训练次数
for i in range(STEPS):#3000轮
start = (i*BATCH_SIZE) % 32 #i*8%32 计算取数据集的下标 0*8%32=0 ..8%32=8,40%32=8
end = start + BATCH_SIZE #i*8%32+8 计算取标签的下标
sess.run(train_step, feed_dict={x: X[start:end], y_: Y_[start:end]}) #喂入神经网络, sess.run执行神经网络
if i % 500 == 0: %500轮打印loss值
total_loss = sess.run(loss_mse, feed_dict={x: X, y_: Y_})
print("After %d training step(s), loss_mse on all data is %g" % (i, total_loss))
# 输出训练后的参数取值。
print("\n")
print("w1:\n", sess.run(w1))
print("w2:\n", sess.run(w2))
#,只搭建承载计算过程的
#计算图,并没有运算,如果我们想得到运算结果就要用到“会话 Session()”了。
#√会话(Session): 执行计算图中的节点运算
print("w1:\n", w1)
print("w2:\n", w2)
"""
X:
[[ 0.83494319 0.11482951]
[ 0.66899751 0.46594987]
[ 0.60181666 0.58838408]
[ 0.31836656 0.20502072]
[ 0.87043944 0.02679395]
[ 0.41539811 0.43938369]
[ 0.68635684 0.24833404]
[ 0.97315228 0.68541849]
[ 0.03081617 0.89479913]
[ 0.24665715 0.28584862]
[ 0.31375667 0.47718349]
[ 0.56689254 0.77079148]
[ 0.7321604 0.35828963]
[ 0.15724842 0.94294584]
[ 0.34933722 0.84634483]
[ 0.50304053 0.81299619]
[ 0.23869886 0.9895604 ]
[ 0.4636501 0.32531094]
[ 0.36510487 0.97365522]
[ 0.73350238 0.83833013]
[ 0.61810158 0.12580353]
[ 0.59274817 0.18779828]
[ 0.87150299 0.34679501]
[ 0.25883219 0.50002932]
[ 0.75690948 0.83429824]
[ 0.29316649 0.05646578]
[ 0.10409134 0.88235166]
[ 0.06727785 0.57784761]
[ 0.38492705 0.48384792]
[ 0.69234428 0.19687348]
[ 0.42783492 0.73416985]
[ 0.09696069 0.04883936]]
Y_:
[[1], [0], [0], [1], [1], [1], [1], [0], [1], [1], [1], [0], [0], [0], [0], [0], [0], [1], [0], [0], [1], [1], [0], [1], [0], [1], [1], [1], [1], [1], [0], [1]]
w1:
[[-0.81131822 1.48459876 0.06532937]
[-2.4427042 0.0992484 0.59122431]]
w2:
[[-0.81131822]
[ 1.48459876]
[ 0.06532937]]
After 0 training step(s), loss_mse on all data is 5.13118
After 500 training step(s), loss_mse on all data is 0.429111
After 1000 training step(s), loss_mse on all data is 0.409789
After 1500 training step(s), loss_mse on all data is 0.399923
After 2000 training step(s), loss_mse on all data is 0.394146
After 2500 training step(s), loss_mse on all data is 0.390597
w1:
[[-0.70006633 0.9136318 0.08953571]
[-2.3402493 -0.14641267 0.58823055]]
w2:
[[-0.06024267]
[ 0.91956186]
[-0.0682071 ]]
"""
更改batchsize,训练次数,优化器观察loss值
模板
1、前向传播:定义输入、参数以及输出
x=定义输入Input 对应的组数和每组特征数 y_=定义标签Lable 对应的组数和标签特征数,预测值
w1=定义输入层到第一层的权重参数 行号要于输入的每组特征数一致 w2=定义第一层到输出层的权重参数 列号要于输出的标签特征数一致
a=第一层得到的结果 传递给下一层 y=输出层得到的结果 ————————————————
原文链接:https://blog.csdn.net/weixin_39104294/article/details/85091093
2、定义损失函数及反向传播方法。
loss_mse = tf.reduce_mean(tf.square(y - y_))
#三种损失函数 这里用的是 梯度下降
train_step = tf.train.GradientDescentOptimizer(0.001).minimize(loss_mse)
#train_step = tf.train.MomentumOptimizer(0.001,0.9).minimize(loss_mse)
#train_step = tf.train.AdamOptimizer(0.001).minimize(loss_mse)
3、迭代循环:生成会话,迭代训练STEPS轮
with tf.session() as sess Init_op=tf. global_variables_initializer() sess_run(init_op) STEPS=3000 for i in range(STEPS): start= end= sess.run(train_step, feed_dict:) ————————————————
5 TensorFlow1.x的损失函数和交叉熵举例讲解及实现 神经元模型: f(ΣXW+b)加入了 激活函数(activation function)和偏置项(bias) 计算神经网络层数:不计算输入层
-
层数 = 隐藏层的个数+1个输出层 -
总参数 = 总 W + 总 b
2层NN 参数=(34+4)+(42+2)=26;输入层个数*第一次隐藏层个数=第一层w个数;第一层偏置数=第一次隐藏层个数
常用的激活函数
? relu? sigmoid? tanh
损失函数(loss):
用来表示预测值(y|)与已知答案(y_|)的差距。在训练神经网络时我们的目标是让损失函数(loss)的值最小。通过不断改变神经网络中所有参数,使损失函数(loss)不断减小,从而训练出更高准确率的神经网络模型。
常用的损失函数有均方误差(mse Mean Squaread Error)、自定义 和 交叉熵(CE Cross Entropy)等 ———————————————— 举例:opt4_1.py 预测酸奶日销量 y来拟定每日的酸奶产量,影响日销量的两个因素分别是x1和 x2。
应提前采集的数据有:一段时间内,每日的 x1 因素、x2因素和真实销量 y_。采集的数据应当尽量多。在本例中用销量预测产量,最优的产量应该等于销量。由于目前没有数据集,所以拟造了一套数据集。利用 Tensorflow 中函数随机生成 x1、 x2,制造标准答案y_= x1 + x2,为了更真实,求和后还加了正负 0.05 的随机噪声。 我们把这套自制的数据集喂入神经网络,构建一个一层的神经网络,拟合预测酸奶日销量的函数。 ———————————————— SEED=234555 #生成数据集 rdm = np.random.RandomState(SEED) X = rdm.rand(32,2) Y_ = [[x1+x2+(rdm.rand()/10.0-0.05)] for (x1, x2) in X] # rdm.rand()是(0,1)随机数,得到正负 0.05 的随机噪声
交叉熵
表示两个概率分布之间的距离。交叉熵越大,两个概率分布距离越远,两 个概率分布越相异;交叉熵越小,两个概率分布距离越近,两个概率分布越相似。 交叉熵计算公式:𝐇(𝐲_ , 𝐲) = ?∑𝐲_ ? 𝒍𝒐𝒈 𝒚 (y为预测)用 Tensorflow 函数表示为
方式一:ce= -tf.reduce_mean(y_* tf.log(tf.clip_by_value(y, 1e-12, 1.0))) #1e-12, 1.0使概率在0,1之间
例如: 两个神经网络模型解决二分类问题中,已知标准答案为 y_ = (1, 0),(表示第一种情况概率为1,第二种情况为0).第一个神经网络模型预测结果为 y1=(0.6, 0.4),第二个神经网络模型预测结果为 y2=(0.8, 0.2),判断哪个神经网络模型预测的结果更接近标准答案。 根据交叉熵的计算公式得: H1((1,0),(0.6,0.4)) = -(1log0.6 + 0log0.4) ≈ -(-0.222 + 0) = 0.222 H2((1,0),(0.8,0.2)) = -(1log0.8 + 0log0.2) ≈ -(-0.097 + 0) = 0.097 由于 0.222>0.097,所以预测结果 y2 与标准答案 y_更接近,y2 预测更准确。
方式二: ce = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y, labels=tf.argmax(y_, 1)) cem = tf.reduce_mean(ce) #让模型的输出经过 softmax 函数,以获得输出分类的概率分布,再与标准答案对比,求出交叉熵,得到损失函数
softmax 函数
将 n 分类的 n 个输出(y1,y2…yn)变为满足以下概率分布要求的函数。 ?𝐱 𝐏(𝐗 = 𝐱) ∈ [𝟎, 𝟏] 且∑𝑷𝒙 (𝑿 = 𝒙) = 𝟏,即使输出为概率值
学习率
表示每次参数更新的幅度 【北京大学】6 TensorFlow1.x的学习率、滑动平均和正则化实例及实现 参数和学习率自定义初始值
设置学习率
学习率过大,会导致待优化的参数在最小值附近波动,不收敛;学习率过小,会导致待优化的参数收敛缓慢。 指数衰减学习率:动态调整学习率
反向传播训练方法:以减小loss值为优化目标,分别有3种不同的方法可以使用——梯度下降、momentum优化器、adam优化器等 在TensorFlow中代码表示分别如下: train_step=tf.train.GradientDescentOptimizer(learning_rate).minimize(loss) train_step=tf.train.MomentumOptimizer(learning_rate, momentum).minimize(loss) train_step=tf.train.AdamOptimizer(learning_rate).minimize(loss)
#定义指数下降学习率 #其中,LEARNING_RATE_BASE 为学习率初始值,LEARNING_RATE_DECAY 为学习率衰减率,global_step 记 录了当前训练轮数,为不可训练型参数。学习率 learning_rate 更新频率为输入数据集总样本数除以每次喂入样本数。若 staircase 设置为 True 时,表示 global_step/learning rate step 取整数,学习率阶梯型衰减;若 staircase 设置为 false 时,学习率会是一条平滑下降的曲线。 learning_rate = tf.train.exponential_decay(LEARNING_RATE_BASE, global_step, LEARNING_RATE_STEP, LEARNING_RATE_DECAY, staircase=True)
#定义反向传播方法 使用minimize()操作,该操作不仅可以优化更新训练的模型参数,也可以为全局步骤(global_step)计数 train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss, global_step=global_step)
什么是超参数?
超参数的定义:在机器学习的上下文中,超参数是在开始学习过程之前设置值的参数,而不是通过训练得到的参数数据。通常情况下,需要对超参数进行优化,给学习机选择一组最优超参数,以提高学习的性能和效果。
理解:超参数也是一个参数,是一个未知变量,但是它不同于在训练过程中的参数,它是可以对训练得到的参数有影响的参数,需要训练者人工输入,并作出调整,以便优化训练模型的效果。
超参数:
- 定义关于模型的更高层次的概念,如复杂性或学习能力。
- 不能直接从标准模型培训过程中的数据中学习,需要预先定义。
- 可以通过设置不同的值,训练不同的模型和选择更好的测试值来决定
超参数的一些示例:
- 聚类中类的个数
- 话题模型中话题的数量
- 模型的学习率
- 深层神经网络隐藏层数
滑动平均率:代码opt4_6
#tf.assign(A, new_number): 这个函数的功能主要是把A的值变为new_number sess.run(tf.assign(w1, 1)) 从运行结果可知,最初参数 w1 和滑动平均值都是 0;参数 w1 设定为 1 后,滑动平均值变为 0.9;当迭代轮数更新为 100 轮时,参数 w1 更新为 10 后,滑动平均值变为 1.644。随后每执行一次,参数w1 的滑动平均值都向参数 w1 靠近。可见,滑动平均追随参数的变化而变化。滑动平均越接近w1越好
正则化
√正则化计算方法: ① L1 正则化: 𝒍𝒐𝒔𝒔𝑳𝟏 = ∑𝒊|𝒘𝒊| 用 Tesnsorflow 函数表示:loss(w) = tf.contrib.layers.l1_regularizer(REGULARIZER)(w) REGULARIZER是超参数,正则化权重,可设置为0.01 ② L2 正则化: 𝒍𝒐𝒔𝒔𝑳𝟐 = ∑𝒊|𝒘𝒊|𝟐 用 Tesnsorflow 函数表示:loss(w) = tf.contrib.layers.l2_regularizer(REGULARIZER)(w) √用 Tesnsorflow
代码:函数实现正则化:
tf.add_to_collection('losses', tf.contrib.layers.l2_regularizer(regularizer)(w)
loss = cem + tf.add_n(tf.get_collection('losses')
)
matplotlib 模块:Python 中的可视化工具模块,实现函数可视化 终端安装指令:sudo pip install matplotlib pycharm内 :pip install matplotlib -i https://pypi.tuna.tsinghua.edu.cn/simple
import matplotlib.pyplot as plt
plt.scatter (x 坐标, y 坐标, c=”颜色”) plt.show() #形成网格坐标点 xx, yy = np.mgrid[起:止:步长,起:止:步长] #降低维度,说直白点就是把数据拉直 #x,y坐标进行拉直配对 grid = np.c_[xx.rave(),yy.ravel()]# np.c_表示组成矩阵,xx.rave(),yy.ravel()表示拉直,一行n列 #把手机的网格坐标点,进行训练 probs = sess.run(y,feed_dict={x:grid}) probs = probs.reshape(xx.shape) #给点上色 plt.contour(x轴坐标值,y轴坐标值,该点的高度,levels =[等高线的高度]) plt.show()
opt4_7.py 解析
#遍历Y中的每个元素,1赋值’red’其余赋值’blue’,这样可视化显示时人可以直观区分 ##预测值 y 接近 1 则为红色点概率越大,接近 0 则为蓝色点概率越大。 Y_c = [[‘red’ if y else ‘blue’] for y in Y_]
#对数据集X和标签Y进行shape整理,第一个元素为-1表示,随第二个参数计算得到,第二个元素表示多少列,把X整理为n行2列,把Y整理为n行1列 X = np.vstack(X).reshape(-1,2)#n行两列,-1表示n行 Y_ = np.vstack(Y_).reshape(-1,1)
#用plt.scatter画出数据集X各行中第0列元素和第1列元素的点即各行的(x0,x1),用各行Y_c对应的值表示颜色(c是color的缩写)
plt.scatter(X[:,0], X[:,1], c=np.squeeze(Y_c))
plt.show()
#定义神经网络的输入、参数和输出,定义前向传播过程
def get_weight(shape, regularizer):
w = tf.Variable(tf.random_normal(shape), dtype=tf.float32)
#L2 正则化
tf.add_to_collection('losses', tf.contrib.layers.l2_regularizer(regularizer)(w))
return w
def get_bias(shape):
b = tf.Variable(tf.constant(0.01, shape=shape))
return b
x = tf.placeholder(tf.float32, shape=(None, 2))
y_ = tf.placeholder(tf.float32, shape=(None, 1))
w1 = get_weight([2,11], 0.01)
b1 = get_bias([11])#11列
y1 = tf.nn.relu(tf.matmul(x, w1)+b1) #神经元模型 ,tf.nn.relu线性激活函数
w2 = get_weight([11,1], 0.01)
b2 = get_bias([1])
y = tf.matmul(y1, w2)+b2 #输出层不过激活
#定义损失函数
# 一般的损失函数
loss_mse = tf.reduce_mean(tf.square(y-y_))
# 正则化的损失函数
# tf.add_to_collection('losses', tf.contrib.layers.l2_regularizer(regularizer)(w))
loss_total = loss_mse + tf.add_n(tf.get_collection('losses'))
#将xx , yy拉直,并合并成一个2列的矩阵,得到一个网格坐标点的集合 grid = np.c_[xx.ravel(), yy.ravel()] #收集规定区域内所有的网格坐标点 #将网格坐标点喂入神经网络 ,probs为输出 probs = sess.run(y, feed_dict={x:grid}) #probs的shape调整成xx的样子 probs = probs.reshape(xx.shape) #给probs等于0.5的上色,把红色的点和蓝色的点分开,输出的预测值 y 为 0.5 是红蓝点概率分界线 plt.contour(xx, yy, probs, levels=[.5]) plt.show(
第五讲 MNIST数据集输出手写数字识别准确率
模型选择和调参需要验证集
实现“Mnist 数据集手写数字识别”的常用函数:
tf.argmax(y_, 1) 取出每行最大值 tf.Graph( ).as_default( )函数 表示将当前图设置成为默认图,并返回一个上下文管理器。该函数一般与 with 关键字搭配使用,应用于将已经定义好的神经网络在计算图中复现。 例如: with tf.Graph().as_default() as g,表示将在 Graph()内定义的节点加入到 计算图 g 中。
字符串.split( )函数 表示按照指定“拆分符”对字符串拆分,返回拆分列表。 例如: ‘./model/mnist_model-1001’.split(’/’)[-1].split(’-’)[-1] 在该例子中,共进行两次拆分。第一个拆分符为‘/’,返回拆分列表,并提取 列表中索引为-1 的元素即倒数第一个元素;第二个拆分符为‘-’,返回拆分列 表,并提取列表中索引为-1 的元素即倒数第一个元素,故函数返回值为 1001。
tf.reduce_mean()函数求平均值 得到神经网络模型在本组数据上的准确率 tf.equal(,)函数 判断维度是否相等
代码结构
1)forward.py# 定义前向传播过程 2)backward.py
√正则化、指数衰减学习率、滑动平均方法的设置
①正则化项 regularization 当在前向传播过程中即 forward.py 文件中,设置正则化参数 regularization 为 1 时,则表明在反向传播过程中优化模型参数时,需要在损失函数中加入正则化项。结构如下: 首先,需要在前向传播过程即 forward.py 文件中加入 #如果使用正则化,将其加入w的loss中 if regularizer != None: tf.add_to_collection(‘losses’, tf.contrib.layers.l2_regularizer(regularizer)(w)) 其次,需要在反向传播过程即 backword.py 文件中加入
#让模型的输出经过 softmax 函数,以获得输出分类的概率分布,再与标准答案对比,求出交叉熵,得到损失函数
ce = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y, labels=tf.argmax(y_, 1)) #输出概率分布
cem = tf.reduce_mean(ce) #求平均
loss = cem + tf.add_n(tf.get_collection('losses'))
其中,tf.nn.sparse_softmax_cross_entropy_with_logits()表示 softmax()函数与交叉熵一起使用。
②指数衰减学习率 在训练模型时,使用指数衰减学习率可以使模型在训练的前期快速收敛接近较优 解,又可以保证模型在训练后期不会有太大波动。 运用指数衰减学习率,需要在反向传播过程即 backword.py 文件中加入:
learning_rate = tf.train.exponential_decay( LEARNING_RATE_BASE,
global_step, LEARNING_RATE_STEP, LEARNING_RATE_DECAY, staircase=True)
③滑动平均 在模型训练时引入滑动平均可以使模型在测试数据上表现的更加健壮。 需要在反向传播过程即 backword.py 文件中加入:
ema = tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY, global_step)
ema_op = ema.apply(tf.trainable_variables())
with tf.control_dependencies([train_step, ema_op]):
train_op = tf.no_op(name='train')
完整代码 fc1
实现手写体 mnist 数据集的识别任务,共分为三个模块文件,分别是描述网络结 构的前向传播过程文件(mnist_forward.py)、描述网络参数优化方法的反向传 播 过 程 文 件 ( mnist_backward.py )、 验 证 模 型 准 确 率 的 测 试 过 程 文 件 (mnist_test.py)。
(1)mnist_forward.py
1前向传播过程 import tensorflow as tf #网络输入节点为784个(代表每张输入28*28图片的像素个数) INPUT_NODE = 784 #输出节点为10个(表示输出为数字0-9的十分类) OUTPUT_NODE = 10 #隐藏层节点500个 LAYER1_NODE = 500 def get_weight(shape, regularizer): # 参数满足截断正态分布,并使用正则化, w = tf.Variable(tf.truncated_normal(shape, stddev=0.1)) # w = tf.Variable(tf.random_normal(shape,stddev=0.1)) # 将每个参数的正则化损失加到总损失中 if regularizer != None: tf.add_to_collection(‘losses’, tf.contrib.layers.l2_regularizer(regularizer)(w)) return w def get_bias(shape): # 初始化的一维数组,初始化值为全 0 b = tf.Variable(tf.zeros(shape)) return b def forward(x, regularizer): # 由输入层到隐藏层的参数w1形状为[784,500] w1 = get_weight([INPUT_NODE, LAYER1_NODE], regularizer) # 由输入层到隐藏的偏置b1形状为长度500的一维数组, b1 = get_bias([LAYER1_NODE]) # 前向传播结构第一层为输入 x与参数 w1矩阵相乘加上偏置 b1 ,再经过relu函数 ,得到隐藏层输出 y1。 y1 = tf.nn.relu(tf.matmul(x, w1) + b1) # 由隐藏层到输出层的参数w2形状为[500,10] w2 = get_weight([LAYER1_NODE, OUTPUT_NODE], regularizer) # 由隐藏层到输出的偏置b2形状为长度10的一维数组 b2 = get_bias([OUTPUT_NODE]) # 前向传播结构第二层为隐藏输出 y1与参 数 w2 矩阵相乘加上偏置 矩阵相乘加上偏置 b2,得到输出 y。 # 由于输出 y要经过softmax函数,使其符合概率分布,故输出y不经过 relu函数 y = tf.matmul(y1, w2) + b2 return y
(2)mnist_backward.py
#2反向传播过程
#引入tensorflow、input_data、前向传播mnist_forward和os模块
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
==import mnist_forward==
import os
#每轮喂入神经网络的图片数
BATCH_SIZE = 200
#初始学习率
LEARNING_RATE_BASE = 0.1
#学习率衰减率
LEARNING_RATE_DECAY = 0.99
#正则化系数
REGULARIZER = 0.0001
#训练轮数
STEPS = 50000
#滑动平均衰减率
MOVING_AVERAGE_DECAY = 0.99
#模型保存路径
MODEL_SAVE_PATH="./model/"
#模型保存名称
MODEL_NAME="mnist_model"
>
>def backward(mnist):
>
>> #用placeholder给训练数据x和标签y_占位
x = tf.placeholder(tf.float32, [None, mnist_forward.INPUT_NODE])
y_ = tf.placeholder(tf.float32, [None, mnist_forward.OUTPUT_NODE])
#调用mnist_forward文件中的前向传播过程forword()函数,并设置正则化,计算训练数据集上的预测结果y
y = mnist_forward.forward(x, REGULARIZER)
#当前计算轮数计数器赋值,设定为不可训练类型
global_step = tf.Variable(0, trainable=False)
#调用包含所有参数正则化损失的损失函数loss
ce = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y, labels=tf.argmax(y_, 1))
cem = tf.reduce_mean(ce)
loss = cem + tf.add_n(tf.get_collection('losses'))
#设定指数衰减学习率learning_rate
learning_rate = tf.train.exponential_decay(
LEARNING_RATE_BASE,
global_step,
mnist.train.num_examples / BATCH_SIZE,
LEARNING_RATE_DECAY,
staircase=True)
#使用梯度衰减算法对模型优化,降低损失函数
#train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss, global_step=global_step)
train_step = tf.train.MomentumOptimizer(learning_rate,0.9).minimize(loss, global_step=global_step)
#train_step = tf.train.AdamOptimizer(learning_rate).minimize(loss, global_step=global_step)
#定义参数的滑动平均
ema = tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY, global_step)
ema_op = ema.apply(tf.trainable_variables())
#实例化可还原滑动平均的saver
#在模型训练时引入滑动平均可以使模型在测试数据上表现的更加健壮
with tf.control_dependencies([train_step,ema_op]):
train_op = tf.no_op(name='train')
saver = tf.train.Saver()
with tf.Session() as sess:
#所有参数初始化
init_op = tf.global_variables_initializer()
sess.run(init_op)
#每次喂入batch_size组(即200组)训练数据和对应标签,循环迭代steps轮
for i in range(STEPS):
xs, ys = mnist.train.next_batch(BATCH_SIZE)
_, loss_value, step = sess.run([train_op, loss, global_step], feed_dict={x: xs, y_: ys})
if i % 1000 == 0:
print("After %d training step(s), loss on training batch is %g." % (step, loss_value))
#将当前会话加载到指定路径
saver.save(sess, os.path.join(MODEL_SAVE_PATH, MODEL_NAME), global_step=global_step)
def main():
#读入mnist
mnist = input_data.read_data_sets("./data/", one_hot=True)
#反向传播
backward(mnist)
if __name__ == '__main__':
main()
(3)mnist_test.py
import time
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
import mnist_forward
import mnist_backward
TEST_INTERVAL_SECS = 5
def test(mnist):
with tf.Graph().as_default() as g:
x = tf.placeholder(tf.float32, [None, mnist_forward.INPUT_NODE])
y_ = tf.placeholder(tf.float32, [None, mnist_forward.OUTPUT_NODE])
y = mnist_forward.forward(x, None)
ema = tf.train.ExponentialMovingAverage(mnist_backward.MOVING_AVERAGE_DECAY)
ema_restore = ema.variables_to_restore()
saver = tf.train.Saver(ema_restore)
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
while True:
with tf.Session() as sess:
ckpt = tf.train.get_checkpoint_state(mnist_backward.MODEL_SAVE_PATH)
if ckpt and ckpt.model_checkpoint_path:
saver.restore(sess, ckpt.model_checkpoint_path)
global_step = ckpt.model_checkpoint_path.split('/')[-1].split('-')[-1]
accuracy_score = sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels})
print("After %s training step(s), test accuracy = %g" % (global_step, accuracy_score))
else:
print('No checkpoint file found')
return
time.sleep(TEST_INTERVAL_SECS)
def main():
mnist = input_data.read_data_sets("./data/", one_hot=True)
test(mnist)
if __name__ == '__main__':
main()
断点续训 表示如果程序中断,下次训练从中断的位置继续训练模型,而不是从头开始训练 ckpt = tf.train.get_checkpoint_state(mnist_backward.MODEL_SAVE_PATH) # 若模型存在,则加载出模型到当前对话,在测试数据集上进行准确率验证,并打印出当前轮数下的准确率 if ckpt and ckpt.model_checkpoint_path: saver.restore(sess, ckpt.model_checkpoint_path)
———————————————— fc2代码加入 with tf.Session() as sess: init_op = tf.global_variables_initializer() sess.run(init_op) #实现断点续训、能接着之前的数据训练 ckpt = tf.train.get_checkpoint_state(MODEL_SAVE_PATH) if ckpt and ckpt.model_checkpoint_path: saver.restore(sess, ckpt.model_checkpoint_path)
for i in range(STEPS):
xs, ys = mnist.train.next_batch(BATCH_SIZE)
_, loss_value, step = sess.run([train_op, loss, global_step], feed_dict={x: xs, y_: ys})
if i % 1000 == 0:
print("After %d training step(s), loss on training batch is %g." % (step, loss_value))
saver.save(sess, os.path.join(MODEL_SAVE_PATH, MODEL_NAME), global_step=global_step)
|