Tensorflow笔记_神经网络优化
# 神经元模型:神经元模型用公式表示为::𝐟(∑𝒊𝒙𝒊𝒘𝒊 + 𝐛), 其中 f 表示为激活函数,神经网络是以神经元为基本单位构成
# 激活函数:引入非线性激活因素,提高模型的表达能力
常用的激活函数有
# 激活函数relu tf.nn.relu() # 激活函数sigmold tf.nn.sigmold() # 激活函数tanh tf.nn.tanh()# 神经网络的复杂度:
1:可用神经网络的层数和神经网络中待优化的参数个数表示
2:计算神经网络层数一般不计算输入层
3:神经网络的层数 = 隐藏层数 + 1个输出层
4:神经网络待优化参数 = 神经网络中所有参数w的个数 + 所有参数b的个数
例如:
# 神经网络的层数 = 1个隐藏层 + 一个输出层,所以该神经网络的层数为2层
# 神经网络的待优化参数:第一层参数用三行四列的二阶张量表示(具有12个线上权重w)再加上4个偏置b,第二层参数是四行两列的二阶张量(具有8个线上权重w),再加上2个偏置b,该神经网络总参数 = 3*4+4 + 4*2+2 = 26
1:损失函数 loss
2:学习率 learing_rate
3:滑动平均 ema
4:正则化 regularization
## 神经网络优化-损失函数
用预测值 y 与已知答案 y_ 的差距,再训练神经网络的过程中,通过不断的改变神经网络中所有参数,使损失函数不断减小,训练出更高准确率的神经网络模型
神经网络优化目标:找到某条参数,使得y和y_无限接近,也就是它们的差距loss最小
常用的损失函数:
1:均方误差
2:自定义
3:交叉熵
# 均方误差mse:n个样本的预测值y与已知答案y_之差的平方和,再求平均值,公式表示为如下
均方误差再Tensorflow中的表示
loss_mse = tf.reduce_mean(tf.square(y_ - y))
# 用下面的例子来理解损失函数
预测酸奶日销量 y,x1 和 x2 是影响日销量的两个因素。
建模前应提前采集的数据有:一段时间内,每日的 x1 因素、x2 因素和销量 y_。采集的数据量越大越好。
在本例中用销量预测产量,最优的产量应该等于销量。由于目前没有数据集,所以拟造了一套数 据集。利用 Tensorflow 中函数随机生成 x1、 x2,制造标准答案 y_ = x1 + x2,为了更真实,求和后还加了正负 0.05 的随机噪声
# 损失函数使用均方误差的方法
#coding:utf-8 # 导入模块 生成数据集 import tensorflow as tf import numpy as np BATCH_SIZE = 8 SEED = 23455 # 保证生成的随机数一样 rdm = np.random.RandomState(SEED) X = rdm.rand(32,2) Y_ = [[x1 + x2 + (rdm.rand()/10.0-0.05)] for (x1,x2) in X] #1 定义神经网络参数和输入,输出,定义向前传播的过程 x = tf.placeholder(tf.float32, shape=(None,2)) y_ = tf.placeholder(tf.float32, shape=(None,1)) w1 = tf.Variable(tf.random_normal([2,1], stddev=1, seed=1)) y = tf.matmul(x, w1) # 定义一输出结果y #2 定义损失函数反向传播的方法 # 定义损失函数为均方误差,反向传播的方法为梯度下降 loss_men = tf.reduce_mean(tf.square(y_-y)) train_step = tf.train.GradientDescentOptimizer(0.001).minimize(loss_men) #3 生成会话 训练STEPS轮 with tf.Session() as sess: init_op = tf.global_variables_initializer() sess.run(init_op) STEPS = 20000 for i in range(STEPS): start = (i*BATCH_SIZE) % 32 end = start + BATCH_SIZE sess.run(train_step,feed_dict={x: X[start:end],y_ : Y_[start:end]}) if i % 500 == 0: print "After %d training steps,w1 is " %(i) print sess.run(w1),"\n" print "Final w1 is :\n",sess.run(w1)
# 输出结果
Final w1 is:
[[0.98019385]
[1.01598072]]
通过使损失函数不断的降低,神经网络模型最终得到的参数 w1 = 0.98;w2 = 1.02,所以销量的预测结果为y = 0.98*x1 + 1.02*x2,
在生成数据集时,我们设置的标准答案为 y = x1+x2,所以神经网络预测的结果和标准答案非常的接近,说明预测正确# 自定义损失函数:根据问题的实际情况,定制合理的损失函数
对于预测酸奶日销量问题,如果预测销量大于实际销量则会损失成本;如果预测销量小于实际销量则 会损失利润。在实际生活中,往往制造一盒酸奶的成本和销售一盒酸奶的利润是不等价的。因此,需 要使用符合该问题的自定义损失函数。
自定义损失函数为::loss = ∑𝑛𝑓(y_, y)
将损失定义成分段函数:
上方损失函数表示:若预测的结果y小于标准答案 y_,损失函数为利润乘以预测结果y和标准答案y_之差;如果预测的结果y大于标准答案y_,损失函数为成本乘以预测结果y与标准答案之差
利用Tensorflow表示为:
loss = tf.reduce_sum(tf.where(tf.greater(y,y_),COST(y-y_),PROFIT(y_-y)))# 将酸奶的成本定为1元,利润定为9元,则制造成本小于酸奶的利润,所以希望预测的记过y多一些,代码代码如下
#coding:utf-8 # 导入模块 生成数据集 import tensorflow as tf import numpy as np BATCH_SIZE = 8 SEED = 23455 COST = 1 # 成本 PROFIT = 9 # 利润 rdm = np.random.RandomState(SEED) X = rdm.rand(32,2) Y_ = [[x1 + x2 + (rdm.rand()/10.0-0.05)] for (x1,x2) in X] #1 定义神经网络参数和输入,输出,定义向前传播的过程 x = tf.placeholder(tf.float32, shape=(None,2)) y_ = tf.placeholder(tf.float32, shape=(None,1)) w1 = tf.Variable(tf.random_normal([2,1], stddev=1, seed=1)) y = tf.matmul(x, w1) # 定义一输出结果y# 定义损失函数反向传播方法 # 定义损失函数,使得预测少了损失大,于是模型因该偏向多的方向预测 loss = tf.reduce_sum(tf.where(tf.greater(y, y_),(y - y_)*COST,(y_ - y)*PROFIT)) train_step = tf.train.GradientDescentOptimizer(0.001).minimize(loss_men) #3 生成会话 训练STEPS轮 with tf.Session() as sess: init_op = tf.global_variables_initializer() sess.run(init_op) STEPS = 20000 for i in range(STEPS): start = (i*BATCH_SIZE) % 32 end = start + BATCH_SIZE sess.run(train_step,feed_dict={x: X[start:end],y_ : Y_[start:end]}) if i % 500 == 0: print "After %d training steps,w1 is " %(i) print sess.run(w1),"\n" print "Final w1 is :\n",sess.run(w1)
# 输出结果
Final w1 is:
[[1.02965927]
[1.0484432]]
神经网络最终的参数为w1 = 1.03;w2 = 1.05,销量的预测结果为 y = 1.03*x1 + 1.05*x2,可以看出使用自定义损失函数预测的结果
大于采用均方误差预测的结果,自定义更符合实际需求
# 将酸奶的成本定为9元,利润定为1元,则制造的成本大于利润,所以希望y小一些。代码如下
# 导入模块 生成数据集 import tensorflow as tf import numpy as np BATCH_SIZE = 8 SEED = 23455 COST = 9 # 成本 PROFIT = 1 # 利润 rdm = np.random.RandomState(SEED) X = rdm.rand(32,2) Y_ = [[x1 + x2 + (rdm.rand()/10.0-0.05)] for (x1,x2) in X] #1 定义神经网络参数和输入,输出,定义向前传播的过程 x = tf.placeholder(tf.float32, shape=(None,2)) y_ = tf.placeholder(tf.float32, shape=(None,1)) w1 = tf.Variable(tf.random_normal([2,1], stddev=1, seed=1)) y = tf.matmul(x, w1) # 定义一输出结果y # 定义损失函数反向传播方法 # 定义损失函数,使得预测少了损失大,于是模型因该偏向多的方向预测 loss = tf.reduce_sum(tf.where(tf.greater(y, y_),(y - y_)*COST,(y_ - y)*PROFIT)) train_step = tf.train.GradientDescentOptimizer(0.001).minimize(loss_men) #3 生成会话 训练STEPS轮 with tf.Session() as sess: init_op = tf.global_variables_initializer() sess.run(init_op) STEPS = 20000 for i in range(STEPS): start = (i*BATCH_SIZE) % 32 end = start + BATCH_SIZE sess.run(train_step,feed_dict={x: X[start:end],y_ : Y_[start:end]}) if i % 500 == 0: print "After %d training steps,w1 is " %(i) print sess.run(w1),"\n" print "Final w1 is :\n",sess.run(w1) # 输出结果 Final w1 is: [[0.96004069] [0.97334176]] 神经网络最终的参数为w1 = 0.96;w2 = 0.97,销量的预测结果为 y = 0.96*x1 + 0.97*x2,可以看出使用自定义损失函数预测的结果 小于采用均方误差预测的结果,自定义更符合实际需求
# 交叉熵
表示两个概率分布之间的距离,交叉熵越大,两个概率分布的距离就越远,两个概率分布越相异;交叉熵越小,两个概率分布距离越相近,两个概率分布越相似
交叉熵计算公式:𝐇(𝐲_ , 𝐲) = −∑𝐲_ ∗ 𝒍𝒐𝒈 𝒚
在Tensorflow中表示为:
ce= -tf.reduce_mean(y_* tf.log(tf.clip_by_value(y, 1e-12, 1.0)))
例如:两个神经网络模型解决二分类问题中,已知标准答案为 y_ = (1, 0),第一个神经网络模型预测结果为 7 y1=(0.6, 0.4),第二个神经网络模型预测结果为 y2=(0.8, 0.2),判断哪个神经网络模型预测的结果更接近标准答案。
根据交叉熵的计算公式得:
H1((1,0),(0.6,0.4)) = -(1*log0.6 + 0*log0.4) ≈ -(-0.222 + 0) = 0.222
H2((1,0),(0.8,0.2)) = -(1*log0.8 + 0*log0.2) ≈ -(-0.097 + 0) = 0.097
由于 0.222>0.097,所以预测结果 y2 与标准答案 y_更接近,y2 预测更准确。
# softmax函数:
将n分类的n个输出(y1,y2,y3....yn)变为满足以下概率分布要求的函数
∀𝐱 𝐏(𝐗 = 𝐱) ∈ [𝟎, 𝟏] 且∑𝑷 𝒙 (𝑿 = 𝒙) = 1
softmax函数表示为:
softmax函数的作用:在n分类中,模型会有n个输出,即y1,y2,y3...,yn,其中yi表示第i中情况出现的可能性大小,将n个输出经过sofmax函数,可得到符合概率分布的分类结果
在Tensorflow中,一般先让模型的输出经过softmax函数,得到输出分类的概率分布,再与标准答案进行对比,求出交叉熵,得到损失函数,用Tensorflow实现如下
ce = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y, labels=tf.argmax(y_, 1)) cem = tf.reduce_mean(ce)
## 神经网络优化--学习率
学习率:表示每次更新的幅度大小,学习率过大,会导致优化参数在最小值附近波动,不收敛;学习率过小,会导致待优化的参数收敛缓慢
在训练过程中,参数的更新向着损失函数梯度下降的方向
参数更新的公式为 𝒘𝒏+𝟏 = 𝒘𝒏 − 𝒍𝒆𝒂𝒓𝒏𝒊𝒏𝒈_𝒓𝒂𝒕𝒆▽
wn+1:更新后的参数
wn:当前参数
learning_rate:学习率
▽:损失函数的梯度(导数)
例如:损失函数为loss = (w+1)2 ,梯度时损失函数的导数为▽ = 2w+2,如果参数的初值为5,学习率为0.2,则参数和损失函数的更新如下
1次 参数w:5 5 - 0.2 * (2 * 5 + 2) = 2.6 2次 参数w:2.6 2.6 - 0.2 * (2 * 2.6 + 2) = 1.16 3次 参数w:1.16 1.16 – 0.2 * (2 * 1.16 + 2) = 0.296 4次 参数w:0.296
损失函数loss = (w + 1)2 的图像为:
从上图可以看出,损失函数loss的最小值在(-1,0)处,这时损失函数的导数为0,得到最终参数w=-1,代码如下
#coding:utf-8 #设置损失函数 loss=(w+1)^2 令w的初始值为5 反向传播就是求最优w 即求最小的loss 对应的w import tensorflow as tf # 定义待优化的参数W的初始值为5 W = tf.Variable(tf.constant(5, dtype=tf.float32)) # 定义损失函数 loss = tf.square(W+1) #定义反向传播的方法(0.2为学习率) train_step = tf.train.GradientDescentOptimizer(0.2).minimize(loss) # 生成会话, 训练40轮 with tf.Session() as sess: init_op = tf.global_variables_initializer() sess.run(init_op) for i in range(40): sess.run(train_step) w_val = sess.run(W) loss_val = sess.run(loss) print "After %s steps: W is %f, loss is %f " % (i,w_val,loss_val)
# 最终结果:随着损失函数的值减小,w无限趋近于-1,模型计算推测出最优参数w = -1
# 学习率的设置
学习率过大:参数震荡不收敛;学习率小了:收敛速度慢
指数衰减学习率:学习率随着训练轮数的变化而动态更新
学习率的计算公式
在Tensorflow中表示为:
global_step = tf.Variable(0, trainable=False) learning_rate = tf.train.exponential_decay(LEARNING_RATE_BASE,global_step,
LEARNING_RATE_STEP, LEARNING_RATE_DECAY, staircase=True/False)LEARNING_RATE_BASE:学习率的初始值
global_step:标记当前训练的轮数,为不可训练参数
LEARNING_RATE_DECAY:学习率的衰减率
若 staircase 设置为 True 时,表示 global_step/learning rate step 取整数,学习 率阶梯型衰减;
若 staircase 设置为 false 时,学习率会是一条平滑下降的曲线。例子:将学习率的初值设置为0.1,将学习率衰减率设置为0.99,BATCH_SIZE设置为1(表示喂入一轮更新一次学习率)
#coding:utf-8 #设置损失函数 loss=(w+1)^2 令w的初始值为5 反向传播就是求最优w 即求最小的loss 对应的w import tensorflow as tf LEARNING_RATE_BASE = 0.1 # 最初的学习率 LEARNING_RATE_DECAY = 0.99 # 学习率衰减率 LEARNING_RATE_BASE = 1 # 喂入多少轮BATCH_SIZE后,更新一次学习率,一般设置为:总样本数/BATCH_SIZE # 运行了几轮BATCH_SIZE的计数器,初值为0,设为不被训练 global_step = tf.Variable(0, trainable=False) # 定义指数下降学习率 learning_rate = tf.train.exponential_decay(LEARNING_RATE_BASE,global_step, LEARNING_RATE_STEP, LEARNING_RATE_DECAY, staircase=True) # 定义待优化的参数W的初始值为10 W = tf.Variable(tf.constant(10, dtype=tf.float32)) # 定义损失函数 loss = tf.square(W+1) #定义反向传播的方法(0.2为学习率) train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss,global_step=global_step) # 生成会话, 训练40轮 tf.Session() as sess: init_op = tf.global_variables_initializer() sess.run(init_op) for i in range(40): ess.run(train_step) w_val = sess.run(W) loss_val = sess.run(loss) print "After %s stps: W is %f, loss is %f " % (i,w_val,loss_val)## 神经网络优化--滑动平均
1:滑动平均:记录一段时间内模型中所有参数w和b各自的平均值。利用滑动平均可以增强模型的泛化能力
2:针对所有的参数进行优化:w和b
3:像是给参数加了影子,参数变化,影子缓慢追随
4:滑动平均(影子)的计算公式:
影子 = 衰减率 * 影子 + ( 1 - 衰减率 ) * 参数
影子初值 = 参数初值
衰减率 = min { MOVING_AVERAGE_DECAY,(1 + 轮数) / (10 + 轮数) }
在Tensorflow中函数表示为:
ema = tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY,global_step)
# 其中 MOVING_AVERAGE_DECAY表示滑动平均的衰减率,是个超参数,一般附一个较大的值(接近1的值)
# global_step:当前训练了多少轮ema_op = ema.apply(tf.trainable_variables()) # 其中,ema.apply()函数实现对括号内参数求滑动平均,tf.trainable_variables()函数实现把所有待训练参数汇总为列表。with tf.control_dependencies([train_step, ema_op]): train_op = tf.no_op(name='train') # 该函数实现将滑动平均和训练过程同步运行计算滑动平均例子:
在神经网络模型中,将 MOVING_AVERAGE_DECAY 设置为 0.99,参数 w1 设置为 0,w1 的滑动平均值设置为 0
1:开始时,轮数 global_step 设置为 0,参数 w1 更新为 1,则 w1 的滑动平均值为: w1 滑动平均值=min(0.99,1/10)*0+(1– min(0.99,1/10)*1 = 0.9 2:当轮数 global_step 设置为 100 时,参数 w1 更新为 10,以下代码 global_step 保持为 100,每 次执行滑动平均操作影子值更新,则滑动平均值变为: w1 滑动平均值=min(0.99,101/110)*0.9+(1– min(0.99,101/110)*10 = 0.826+0.818=1.644 3:再次运行,参数 w1 更新为 1.644,则滑动平均值变为: w1 滑动平均值=min(0.99,101/110)*1.644+(1– min(0.99,101/110)*10 = 2.328 4:再次运行,参数 w1 更新为 2.328,则滑动平均值: w1 滑动平均值=2.95计算滑动平均代码如下:
#coding:utf-8 import tensorflow as tf # 定义变量及滑动平均类 # 定义一个32为的浮点变量,初始值为0.0 这个代码不断的变更w1参数,优化w1的参数,滑动平均做了个w1的影子 w1 = tf.Variable(0,dtype=tf.float32) #定义num_updates(NN的迭代轮数)初始的值为0不可被优化(不可被训练),这个参数不参与训练 gloable_step = tf.Variable(0,trainable=False) #实例滑动平均类,给删减率为0.99,当前轮数为 gloable_step MOVING_AVERAGE_DECAY = 0.99 ema = tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY,gloable_step) # ema.apply后的括号中是更新列表 每次运行rsess,run(ema_op) 时 对更新列表中的元素求滑动平均值 # 在实际的应用中 会使用tf.trainable_variables() 自动将所有待训练的参数汇总为列表 ema_op = ema.apply(tf.trainable_variables()) with tf.Session() as sess: # 初始化 init_op = tf.global_variables_initializer() sess.run(init_op) # 用ema.average(w1获取w1的滑动平均值 (要运行多个节点 作为列表中的元素列出,写在sess.run中) #打印出当前参数w1 和w1的滑动平均值 print sess.run([w1,ema.average(w1)]) #参数w1的值赋为1 sess.run(tf.assign(w1,1)) sess.run(ema_op) print sess.run([w1,ema.average(w1)]) # 更新step 和w1的值 模拟出100轮迭代后 w1的值变为10 sess.run(tf.assign(gloable_step, 100)) sess.run(tf.assign(w1,10)) sess.run(ema_op) print sess.run([w1,ema.average(w1)]) # 每次执行sess.run会更新一次w1的滑动平均值 sess.run(ema_op) print sess.run([w1,ema.average(w1)]) sess.run(ema_op) print sess.run([w1,ema.average(w1)]) sess.run(ema_op) print sess.run([w1,ema.average(w1)]) sess.run(ema_op) print sess.run([w1,ema.average(w1)])
sess.run(ema_op) print sess.run([w1,ema.average(w1)]) sess.run(ema_op) print sess.run([w1,ema.average(w1)])## 神经网络优化--正则化
过拟合:神经网络模型在训练数据集上准确率较高,在新的数据进行预测或分类时准确率较低,说明模型的泛型差
利用正则化来缓解过拟合:正则化在损失函数中引入模型复杂度指标,利用给W加权值,弱化了训练数据的噪声(一般不对b进行正则化)
使用正则化后,损失函数 loss 变为亮相之和:
loss = loss(y 与 y_) + REGULARIZER*loss(w)
loss(y 与 y_) :模型中所有参数的损失函数,如交叉熵,均方误差
REGULARIZER:用超参数 REGULARIZER 给出参数w在总loss中的比例,即正则化的权重
loss(w):其中 w 表示需要正则化的参数
正则化的计算方法
1:L1 正则化: 𝒍𝒐𝒔𝒔𝑳𝟏 = ∑𝒊 | 𝒘𝒊 |
在Tensorflow中表示为“
loss(w) = tf.contrib.layers.l1_regularizer(REGULARIZER)(w)2:L2 正则化: 𝒍𝒐𝒔𝒔𝑳𝟐 = ∑𝒊 | 𝒘𝒊 | 2
在Tensorflow中表示为
loss(w) = tf.contrib.layers.l2_regularizer(REGULARIZER)(w)用Tensorflow实现正则化:
ce = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y, labels=tf.argmax(y_, 1)) cem = tf.reduce_mean(ce) tf.add_to_collection('losses', tf.contrib.layers.l2_regularizer(regularizer)(w)) loss = cem + tf.add_n(tf.get_collection('losses'))例子:
用 300 个符合正态分布的点 X[x0, x1]作为数据集,根据点 X[x0, x1]计算生成标注 Y_,将数据集 标注为红色点和蓝色点。
标注规则为:当 x0 2 + x1 2 < 2 时,y_=1,标注为红色;当 x0 2 + x1 2 ≥2 时,y_=0,标注为蓝色。
我们分别用无正则化和有正则化两种方法,拟合曲线,把红色点和蓝色点分开。在实际分类时, 如果前向传播输出的预测值 y 接近 1 则为红色点概率越大,接近 0 则为蓝色点概率越大,输出的预 测值 y 为 0.5 是红蓝点概率分界线。
代码如下:
#coding:utf-8 import tensorflow as tf import numpy as np import matplotlib.pyplot as plt BATCH_SIZE = 30 seed = 2 # 基于seed产生随机数 rdm = np.random.RandomState(seed) # 随机数返回300行2列的急诊,表示300组坐标(x0,x1)作为输入数据集 X = rdm.randn(300,2) # 从X这个300行2列的矩阵中取出一行,判断如果两个坐标的平方和小于2,给Y赋值1,其余赋值为0 Y_ = [int(x0 * x0 + x1*x1 < 2) for (x0,x1) in X] # 遍历y中的每个元素,1赋值为red,其余赋值为blue 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) Y_ = np.vstack(Y_).reshape(-1,1) print (X) print (Y_) print (Y_c) # 用plt.scatter画出数据集X隔行中的第0列元素和第1列元素的点即隔行的(x0x1),用Y_c对应的值表示颜色 plt.scatter(X[:,0],X[:,1],c=np.squeeze(Y_c)) plt.show() # 定义神经网络的输入输出参数,定义向前传播的过程 def get_weight(shqpe,regularizer): W = tf.Variable(tf.random_normal(shqpe),dtype=tf.float32) 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]) y1 = tf.nn.relu(tf.matmul(x,w1)+b1) 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_)) loss_total = loss_mse + tf.add_n(tf.get_collection('losses')) # 定义反向传播方法:不含正则化 train_step = tf.train.AdamOptimizer(0.0001).minimize(loss_mse) with tf.Session() as sess: init_op = tf.global_variables_initializer() sess.run(init_op) STEPS = 40000 for i in range(STEPS): start = (i*BATCH_SIZE) % 300 end = start + BATCH_SIZE sess.run(train_step,feed_dict={x:X[start:end],y_:Y_[start:end]}) if i % 2000 == 0: loss_mse_v = sess.run(loss_mse,feed_dict={x:X,y_:Y_}) print ("After %d steps,loss is :%f" %(i,loss_v)) # xx在-3到3之间以步长为0.01,yy在-3到3之间以步长为0.01,生成二维网络坐标点 xx,yy = np.mgrid[-3:3:.01,-3:3:.01] # 将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) print ("w1:\n",sess.run(w1)) print ("b1:\n",sess.run(b1)) print ("w2:\n",sess.run(w2)) plt.scatter(X[:,0],X[:,1],c=np.squeeze(Y_c)) plt.contour(xx,yy,probs,lecels=[.5]) plt.show() # 定义反向传播的方法:包含正则化 train_step = tf.train.AdamOptimizer(0.0001).minimize(loss_total) with tf.Session() as sess: init_op = tf.global_variables_initializer() sess.run(init_op) STEPS = 40000 for i in range(STEPS): start = (i*BATCH_SIZE) % 300 end = start + BATCH_SIZE sess.run(train_step,feed_dict={x:X[start:end],y_:Y_[start:end]}) if i % 2000 == 0: loss_v = sess.run(loss_total,feed_dict={x:X,y_:Y_}) print ("After %d steps,loss is :%f" %(i,loss_v)) xx,yy = np.mgrid[-3:3:.01,-3:3:.01] grid = np.c_[xx.ravel(),yy.ravel()] probs = sess.run(y,feed_dict={x:grid}) probs = probs.reshape(xx.shape) print ("w1:\n",sess.run(w1)) print ("b1:\n",sess.run(b1)) print ("w2:\n",sess.run(w2)) print ("b2:\n",sess.run(b2)) plt.scatter(X[:,0],X[:,1],c=np.squeeze(Y_c)) plt.contour(xx,yy,probs,lecels=[.5]) plt.show()执行代码,效果如下图所示
然后执行无正则化的训练过程,将途中红色点和蓝色点分开,如下图所示
最后执行有正则化的训练过程,将红色点和蓝色点分开,生成的曲线如下图所示
对比无正则化与有正则化的训练结果,可以看出有正则化模型的拟合曲线平滑,模型具有更好的泛化能力
## 搭建模块化神经网络八股
# 前向传播的目的:搭建网络,设计网络结构,由输入到输出,搭建完整的网络结构
描述前向创博的过程需要定义三个函数:
定义第一个函数:forward(),该函数完成网络结构的设计,从输入到输出搭建完整的网络结构,实现前向传播的过程。其中参数x为输入,regularzer为正则化的权重,返回值为预测分类或则是结果y
def forward(x,regularizer): w = b = y = return y第二个函数 :get_weight()对参数 w 设定。该函数中,参数 shape 表示参数 w 的形状,regularizer 表示正则化权重,返回值为参数 w。其中,tf.variable()给 w 赋初值,tf.add_to_collection()表 示将参数 w 正则化损失加到总损失 losses 中,返回w
def get_weight(shape, regularizer): w = tf.Variable() tf.add_to_collection('losses', tf.contrib.layers.l2_regularizer(regularizer)(w)) return w第三个函数: get_bias()对参数 b 进行设定,其实就是某层中b的个数。该函数中,参数 shape 表示参数 b 的形状,返回值为参数 b。其中,tf.variable()表示给 b 赋初值,返回b
def get_bias(shape): b = tf.Variable() return b# 反向传播:训练网络,优化网络参数
函数 backward()中,placeholder()实现对数据集 x 和标准答案 y_占位,forward.forward()实现前向 传播的网络结构,参数 global_step 表示训练轮数,设置为不可训练型参数。 20 在训练网络模型时,常将正则化、指数衰减学习率和滑动平均这三个方法作为模型优化方法。
def backward( ): x = tf.placeholder( ) y_ = tf.placeholder( ) y = forward.forward(x, REGULARIZER) global_step = tf.Variable(0, trainable=False) loss =
以上的内容在之前都有体现,这里不再指出...
本笔记整理自:慕课Tensorflow笔记