【深度学习】深层神经网络

深度学习:一类通过多层非线性变换对高复杂性数据建模算法的集合

深层神经网络是实现“多层非线性变换”最常用的一种方法

深度学习 ≈ 深层神经网络

深度学习的重要特征:多层、非线性

 

线性模型局限性:

一个线性模型中通过输入的函数得到输出的函数被称为一个线性变换。

线性模型的最大特点是任意线性模型的组合依然还是线性模型。

线性模型只能解决线性可分的问题,很多问题是无法线性分割的

 

激活函数去线性化:

将每一个神经元的输出通过一个非线性函数,那么整个神经网络模型不再是线性。

这个非线性函数 = 激活函数

激活函数图像都不是一条直线,所以通过非线性函数,则整个神经网络模型不再是线性。

TensorFlow提供7种非线性函数

       nn.relu、sigmoid、tanh、是比较常用的。

TensorFlow也支持自定义激活函数

 

通过多层网络解决异或运算(多层变换):

感知机无法模拟异或运算的功能。

异或运算:如果两个输入的符号相同时,则输出为0,异号则输出1。

感知机模型过程:先将输入进行加权和再通过激活函数得到输出。

深层神经网络实际上有组合特征提取功能,对于图片、语音识别有很大帮助。

 

损失函数的定义:

神经网络模型的效果以及优化的目标是通过损失函数来定义。

 

经典损失函数:

监督学习的两大种类:分类问题、回归问题

分类问题:希望解决将不同的样本分到事先定义好的类别中。

回归问题:希望解决对具体数值的预测。

 

分类问题常用的损失函数

交叉熵:信息论概念,估算平均编码的长度,刻画两个概率分布之间的距离。

Softmax回归可以作为学习算法来优化分类结果。

 

回归问题常用的损失函数

均方误差:

tf.reduce_mean(tf.square(y - _y))

y为神经网络输出答案,_y为标准答案

 

自定义损失函数

自定义损失函数使得神经网络优化结果更加接近实际问题的需求。

tf.where() 比较两个张量中的每一个元素的大小,返回比较结果

tf.selecct() 根据第一个参数T/F选择第二个参数中的值还是第三个参数中的值

案例:

importtensorflow as tf
from numpy.random import RandomState

batch_size = 8

# input two node
x = tf.placeholder(tf.float32,shape=(None,2),name='x-input')

# regression onlyone output node
y_ = tf.placeholder(tf.float32,shape=(None,1),name='y-input')

# definition onemonolayer neural network forward propagation
w1 = tf.Variable(tf.random_normal([2,1],stddev=1,seed=1))
y = tf.matmul(x,w1)

# cost
loss_less = 10
loss_more = 1

loss = tf.reduce_mean(tf.where(tf.greater(y,y_),
                               (y - y_) * loss_more,
                               (y_ - y) * loss_less))

train_step = tf.train.AdadeltaOptimizer(0.001).minimize(loss)

# Generate asimulation data set
rdm = RandomState(1)

dateset_size = 128
X =rdm.rand(dateset_size,2)

Y = [[x1 + x2 + rdm.rand()/10.0-0.05] for (x1,x2) in X]

# drill
with tf.Session() as sess:
    init_op = tf.global_variables_initializer()
    sess.run(init_op)
    STEPS = 5000
    for i in range(STEPS):
        start = (i * batch_size) % dateset_size
        end = min(start+batch_size,dateset_size)
        sess.run(train_step,feed_dict={x:X[start:end],y_:Y[start:end]})
        print(sess.run(w1))


 

神经网络优化算法:

通过反向传播算法和梯度下降算法调整神经网络中的参数取值

梯度下降算法主要优化单个参数的取值,而反向传播算法是给出一个高效的方式在所有参数上使用梯度下降算法,使其神经网络模型在训练集上的损失函数最小化。

反向传播算法是训练神经网络模型的核心算法,根据定义好的损失函数优化神经网络参数的取值,使其神经网络模型在训练集上的损失函数达到最小值。

神经网络模型中的参数优化过程决定了模型的质量,使用神经网络最重要的一步。

 

没有一个通用的方法可以对任意损失函数直接求解最佳的参数取值。

梯度下降算法是最常用的神经网络优化方法

参数梯度通过求偏单的方式计算,有了梯度还需要定义学习率。

学习率定义每次参数移动的幅度

 

神经网络的优化过程可以分为两个阶段

1、       通过前向传播算法计算得到预测值,将预测值与真实值对比得到差距

2、       通过反向传播算法计算损失函数对每一个参数的梯度,根据梯度和学习率使用梯度下降算法更新每一个参数。

 

梯度下降算法并不能保证被优化的函数达到全局最优解,可以达到局部最优解。

训练神经网络时,参数的初始值会很大程度影响最后的结果,只有当损失函数为凸函数时,梯度下降算法才能保证达到全局最优解。

 

梯度下降算法的另外一个问题就是计算时间长,可以使用梯度下降算法族中的随机梯度下降算法,这个算法并不是优化全部训练数据上的损失函数,而是在每轮迭代中,随机优化某一条训练数据上的损失函数。但是更新速度加快某一条数据上的损失函数最小并不代表全部数据上的损失函数最小,有可能无法等到局部最优解。

 

两个算法的折中:

每次训练一小部分训练数据的损失函数,这部分数据为一个batch,通过矩阵运算,每次在一个batch上的优化神经网络的参数并不会比单个数据慢太多,每次使用一个batch可以大大减小收敛所需要的迭代次数,同时使收敛到的结果更加接近梯度下降的效果。

案例:

batch_size = n
# 每次取一小部分数据为当前的训练数据
x = tf.placeholder(tf.float32,shape=(batch_size,2),name='x-input')
y_ = tf.placeholder(tf.float32,shape=(batch_size,1),name='y-input')
for i in range(STEPS):
# 准备batch_size个训练数据
    start = (i * batch_size) % dateset_size
    end = min(start+batch_size,dateset_size)
    sess.run(train_step,feed_dict={x:X[start:end],y_:Y[start:end]})
    print(sess.run(w1))


 

神经网络进一步的优化:

 

学习率:

设置学习率控制参数更新速度学习率决定了参数每次更新的幅度

更新幅度过大会导致参数在最优解两侧徘徊

指数衰减法:TensorFlow提供了一种更加灵活的学习率设置方法

tf.tanin.exponential_decay():实现了指数衰减学习率,可以使用较大的学习率加速得到一个较优解。可以设置参数staircase选择不同的衰减方式,阶梯和连续状的衰减曲线。

 

过拟合:

避免过拟合问题,最常使用正则化

正则化思想是在损失函数中加入刻画模型复杂程度的指标。

常用的刻画模型复杂程度的函数有两种:L1、L2


总体思想都是希望通过限制权重的大小,使得模型不能任意拟合训练数据中的随机噪音。

 

L1和L2的区别:

       L1正则化会让参数变得稀疏;计算公式不可导;损失函数更加复杂;

       L2不会变稀疏;公式可导;可使损失函数的优化更简洁

可同时使用L1和L2.

 

L2的使用案例:

w = tf.Variable(tf.random_normal([2,1]), stddev=1,seed=1)

y = tf.matmul(x,w)

loss=tf.reduce_mean(tf.square(_y - y))+tf.contrib.layers.l2_regularizer(lambda)(w)

lambda为正则化权重,w为需要计算正则化损失的参数

 

同时使用两种正则化案例:

w=tf.constant([[1.0,-2.0],[-3.0,4.0]])

with tf.Session() as sess:

  print sess.run(tf.contrib.layers.l1_regularizer(.5)(w))

       printsess.run(tf.contrib.layers.l2_regularizer(.5)(w))

 

一个5层神经网络带L2正则化的损失函数的计算方法(程序的正则化部分):

# 定义训练的目标函数loss,训练次数及训练模型

train_op = tf.train.AdamOptimizer(0.001).minimize(loss)

TRAINING_STEPS =40000

 

with tf.Session() as sess:

   tf.global_variables_initializer().run()

   for i inrange(TRAINING_STEPS):

       sess.run(train_op, feed_dict={x: data, y_: label})

       if i %2000==0:

            print("After %d steps, loss: %f"% (i, sess.run(loss,feed_dict={x: data, y_: label})))

 

   # 画出训练后的分割曲线      

   xx, yy = np.mgrid[-1:1:.01, 0:2:.01]

   grid = np.c_[xx.ravel(), yy.ravel()]

   probs = sess.run(y, feed_dict={x:grid})

   probs = probs.reshape(xx.shape)

 

plt.scatter(data[:,0], data[:,1], c=label,

           cmap="RdBu", vmin=-.2, vmax=1.2, edgecolor="white")

plt.contour(xx, yy,probs, levels=[.5], cmap="Greys", vmin=0, vmax=.1)

plt.show()


全部代码:

https://github.com/935048000/tensorflow-tutorial/blob/master/Deep_Learning_with_TensorFlow/1.0.0/Chapter04/3.%20%E6%AD%A3%E5%88%99%E5%8C%96.ipynb

 

滑动平均模型:

滑动平均模型:可使模型在测试数据上更加健壮的方法

一定程度提高最终模型在测试数据上的表现

 

实现滑动平均模型:tf.ExponentialMovingAverage()需要提高一个衰减率

衰减率控制模型的更新速度

ExponentialMovingAverage对每个变量会维护一个影子变量,这个影子变量的初始值就是相应变量的初始值,每次运行变量更新时,影子变量的值会更新为:

影子变量 = 衰减率 * 影子变量+ (1 – 衰减率)*待更新变量

衰减率决定模型的更新速度,decay越大,模型越趋于稳定。一般设置为趋于1的数,如0.999或0.9999

 

使用滑动平均模型和指数衰减的学习率在一定程度是限制神经网络中的参数更新速度

 

ExponentialMovingAverage还可以设置动态设置衰减率的参数num_updates

案例:

#coding=utf-8
import tensorflow as tf

# 定义变量及滑动平均类
v1 = tf.Variable(0, dtype=tf.float32)
# 迭代轮数
step = tf.Variable(0, trainable=False)
# 平滑平均类
ema = tf.train.ExponentialMovingAverage(0.99, step)
# 更新变量
maintain_averages_op= ema.apply([v1])

# 查看不同迭代中变量取值的变化。
with tf.Session () as sess:
    # 初始化
    init_op = tf.global_variables_initializer ()
    sess.run (init_op)
    print()
    sess.run ([v1, ema.average (v1)])

    # 更新变量v1的取值
    sess.run (tf.assign (v1, 5))
    sess.run (maintain_averages_op)
    print()
    sess.run ([v1, ema.average (v1)])

    # 更新step和v1的取值
    sess.run (tf.assign (step, 10000))
    sess.run (tf.assign (v1, 10))
    sess.run (maintain_averages_op)
    print()
    sess.run ([v1, ema.average (v1)])

    # 更新一次v1的滑动平均值
    sess.run (maintain_averages_op)
    print()
    sess.run ([v1, ema.average (v1)])

 


 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值