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),梯度时损失函数的导数为▽ = 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笔记

posted @ 2019-04-22 22:02  一头牛这么多人放  阅读(549)  评论(0编辑  收藏  举报