深度神经网络学习笔记

第一节

这篇文章是深度神经网络的学习笔记,首先抛出下面一个问题。

人工智能、机器学习和深度学习之间的关系?

8291d93c1ebeddb46abce1e79c665131.png

从图中可以看出人工智能概念的范围更广,机器学习是其中的一个子集,而深度学习又是机器学习中的一个子集。

深度学习的应用领域在计算机视觉、语音识别、自然语言处理和人机博弈方面比基于数理统计的机器学习会有更高的准确度。这里主要是做深度学习方面的学习笔记。

深度学习的发展历程

以下部分图片摘自《TensorFlow 实战Google深度学习框架》

深度发学习是深度神经网络的代名词,其起源于上世纪,只是在这几年开始火起来。

早期的神经网络模型类似于放生机器学习,由人类大脑的神经元演化出的神经元模型,见下图:

d3e5abadd5c9bb7cefb77b4e66e7baf2.png

后面出现了感知机模型、分布式知识表达和神经网络反向传播算法,再到后来的卷积神经网络、循环神经网络和 LSTM 模型。

在神经网络发展的同时,传统机器学习算法的研究也在不断发展,上世纪 90 年代末逐步超越了神经网络,在当时相比之下传统机器学习算法有更好的识别准确率,而神经网络由于数据量和计算能力的限制发展比较困难。到了最近几年,由于云计算、GPU、大数据等的出现,为神经网络的发展做好了铺垫,AI 开始了一个新的时代。

下面一张图表是对比主流深度学习开源工具

324db33925f7105c2b11bc0b0f392f11.png

目前我听说的比较多的两个开源工具是 Caffe 和 TensorFlow,然后去看了下 Github 关注量,前者 20.1k 后者 69.3k,TensorFlow 应该是目前最火的一个深度学习框架了吧。这篇文章包括后面的文章都会去记录 TensorFlow 的学习过程,下面的内容是介绍 TensorFlow 的基础概念,介绍中我尽量避免加入代码,因为目前 TensorFlow 更新比较快,发现好多写法在新的版本中不再被支持。

TensorFlow 学起来

TensorFlow 有两个重要概念 Tensor (张量)和 Flow(流),Tensor 表名的是数据结构,Flow 提现的是计算模型。

PS:以下将 TensorFlow 简称为 tf

tf 计算模型 — 计算图

tf 通过计算图来表述计算的编程系统,其中的每个节点表示一个计算,不同点之间的连接表达依赖关系。下面几行代码表达一下:

import tensorflow as tf
a = tf.constant([1.0, 2.0], name='a')
b = tf.constant([2.0, 3.0], name='b')
result = a + b

上面的代码在计算图中会有 a、b、a + b三个节点。tf 默认会有一个全局的计算图,也可以生成新的计算图,不同计算图之间不会共享张量和运算

计算图中可以通过集合的方式管理不同的资源,这些资源可以是张量、变量或者队列资源等。

tf 数据模型 — 张量

张量是 tf 管理和表示数据的形式,可以简单理解为多维数组。零阶张量表示标量,就是一个数;一阶张量是一个一维数组;n 阶张量是一个 n 维数组。 tf.add(a, b, name='add') 这行代码在运行时并不会得到结果,而是一个结果的引用,是一个张量的结构,包含三个属性 name、shape、dtype,name 仅仅是一个节点的名称;shape 是张量的维度,这个是一维的,长度为 2,这个属性比较重要;dtype 是数据类型,每个张量有唯一的数据类型,不同张量之间的计算需要保证类型统一。

上面的例子就是对两个常量做加法,然后生成计算结果的引用。

tf 运行模型 — 会话

tf 的会话用来执行定义好的运算,会话用来管理运行过程中的所有资源,计算完成后会帮助回收资源,通过 with tf.Session() as sess: 这种方式会在 with 结束时自动关闭回收资源。

通过 tf.ConfigProto 可以配置类似并行线程数、GPU分配策略、运算超时时间等参数,将配置添加到 tf.Session 中创建会话。

向前传播算法

通过全连接网络结构介绍,一个神经元有多个输入和一个输出,输出是不同输入的加权和,不同的输入权重就是神经网络的参数,神经网络的优化就是优化参数取值的过程。全连接网络结构是指相邻两层之间任意两个节点之间都有连接。

向前传播算法需要的三部分信息:

  • 第一部分从实体中取出特征向量作为输入。
  • 第二部分是神经网络的连接结构,不同神经元之间的输入输出的连接关系。
  • 第三部分是每个神经元中的参数。

在 tf 中通过变量(tf.Variable)来保存和更新神经网络中的参数。

278c2e5ff2b727a4e8a1b931d5398bda.png
import tensorflow as tf
# w1 是第一层,通过随机数生成一个 (2,3) 的矩阵
w1 = tf.Variable(tf.random_normal([2, 3], stddev=1, seed=1))
# w2 是第二层,通过随机石生成一个 (3,1) 的矩阵
w2 = tf.Variable(tf.random_normal([3, 1], stddev=1, seed=1))
# x 是输入层,为一个 (1,2) 的矩阵
x = tf.placeholder(tf.float32, shape=(1, 2), name='input')
# 通过 tensorflow 提供的矩阵相乘算法计算
a = tf.matmul(x, w1)
y = tf.matmul(a, w2)
with tf.Session() as sess:
    # 这里初始化所有变量
    sess.run(tf.global_variables_initializer())
    # 通过 输入值 x 与 第一层的参数进行矩阵相乘,再与 第二层的参数进行矩阵相乘,实现神经网络的向前传播算法。
    print sess.run(y, feed_dict={x: [[0.7, 0.9]]})

输出:

[[ 3.95757794]]

第二节

向前传播算法是一种线性模型,全连接神经网络和单层神经网络模型都只能处理线性问题,这具有相当大的局限性。而深度学习要强调的是非线性。

激活函数去线性化

如下图,如果我们将每一个神经元的输出通过一个非线性函数,那么这个神经网络模型就不再是线性的了,而这个非线性函数就是激活函数,也实现了我们对神经元的去线性化。

bc0950257d859989a6f2d494bd3fcdf0.png

下面列举了三个常用激活函数

  • ReLU 函数
  • sigmoid 函数
  • tanh 函数

c1aad44039fbedf014d109a727220dea.png

tf 中也提供了这几种不同的非线性激活函数。

tf.nn.relu(tf.matmul(x, w1) + biases1)

通过对 x 的加权增加偏置项,再在外层加上激活函数,实现神经元的非线性化。

损失函数

损失函数用来衡量预测值与真实值之间的不一致程度,是一个非负实值函数,损失函数越小,证明模型预测的越准确。

交叉熵可以用来衡量两个概率分布之间的距离,是分类问题中使用比较光的一种损失函数。对于两个概率分布 p 和 q,表示交叉熵如下:

H(p,q)=-\sum_{x}p(x)log q(x)

将神经网络向前传播得到的结果变成概率分布使用 Softmax 回归,它可以作为一个算法来优化分类结果。假设神经网络的输出值为 y1,y2,...yn,那么 Softmax 回归处理的输出为:

a3ad0d9bf5d4d40e03a902afa065005a.png

如下图通过 Softmax 层将神经网络的输出变成一个概率分布。

61f898135806539c5fd865e6c1909ed5.png

交叉熵一般会与 Softmax 回归一起使用,tf 对这两个功能提供了封装提供函数

tf.nn.softmax_cross_entropy_with_logits

对于回归问题区别与分类问题,需要预测的是一个任意实数,最常使用的损失函数是均方误差 MSE,定义如下:

9877ba784086672be6ef43795f14e09f.png

反向传播算法

反向传播算法是训练神经网络的核心算法,它可以根据定义好的损失函数优化神经网络的参数值,是神经网络模型的损失函数达到一个较小的值。

梯度下降算法是最常用的神经网络优化方法,假设用 θ 表示神经网络的参数, J(θ) 表示给定参数下的取值,梯度下降算法会迭代式的更新 θ,让迭代朝着损失最小的方向更新。梯度通过求偏导的方式计算,梯度为:

\frac{∂}{∂θ}J(θ)

然后定义一个学习率 η。参数更新公式如下:

θ_{n+1}=θ_n-η\frac{∂}{∂θ_n}J(θ_n)

优化过程分为两步:

  1. 通过向前传播算法得到预测值,将预测值与真实值之间对比差距。
  2. 通过反向传播算法计算损失函数对每一个参数的梯度,根据梯度和学习率是梯度下降算法更新每一个参数。

为了降低计算量和加速训练过程,可以使用随机梯度下降算法,选取一部分数据进行训练。

学习率的设置可以通过指数衰减法,逐步减小学习率,可以在开始时快速得到一个较优解,然后减小学习率,使后模型的训练更加稳定。tf 提供了tf.train.exponential_decay 函数实现指数衰减学习率。

每一轮优化的学习率 = 初始学习率 * 衰减系数 ^ (学习步数 / 衰减速度)

过拟合问题

通过损失函数优化模型参数的时候,并不是让模型尽量的模拟训练数据的行为,而是通过训练数据对未知数据给出判断,当一个模型能完美契合训练数据的时候,损失函数为0,但是无法对未知数据做出可靠的判断,这就是过拟合。

避免过拟合的常用方法是正则化,就是在损失函数中加入刻画模型复杂度的指标,我们对模型的优化则变为:

J(θ)+λR(w)

其中 R(w) 刻画的是模型的复杂程度,λ 表示模型复杂损失在总损失中的比例。下面是两种正则化函数:

L1正则化:会让参数变得稀疏,公式不可导

R(w) = \|~w~\Vert_1 = \sum_i\|w_i\|

L2正则化:不会让参数变得稀疏,公式可导

R(w) = \|~w~\Vert_2^2 = \sum_i\|w_i^2\|

在实际使用中会将 L1 正则化和 L2 正则化同时使用:

R(w) = \sum_iα|w_i|+(1-α)w_i^2

滑动平均模型

在采用随机梯度下降算法训练神经网络时,使用平均滑动模型可以在大部分情况下提高模型在测试数据上的表现。在 tf 中提供了 tf.train.ExponentialMovingAverage 来实现这个模型,通过设置一个衰减率来初始化,在其中维护一个影子变量,可以控制模型的更新速度。

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

为了让模型前期更新比较快,还提供了 num_updates 参数,每次使用的衰减率为:

min\left\{decay,\frac{1+num\_updates}{10+num\_updates}\right\}


笔记结束,如有错误还望帮忙指正。


最后,欢迎大家关注我的专栏 『知一周曝』,我会继续给大家分享开发生涯中的学习总结和生活感悟,一起探讨提高~~
我的个人学习笔记地址: 『Noogel's notes』,这里会先发布我平时的学习笔记,整理后会发到我的专栏。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值