学习目标:
- 知道深度学习与机器学习的关系、
- 知道神经网络是什么
- 知道常见的激活函数
- 知道参数初始化的常见方法
- 能够利用tf.keras构建神经网络模型
- 了解神经网络的优缺点
1.神经网络简介
在介绍神经网络之前,我们先看下面这幅图:人工智能>机器学习>深度学习
深度学习是机器学习的⼀个⼦集,也就是说深度学习是实现机器学习的⼀
种⽅法。与机器学习算法的主要区别如下图所示:
传统机器学习依赖于人工设计特征,并进行特征提取,而深度学习算法不需要人工,而是依赖算法自动提取特征,这也是深度学习被看做黑盒子、可解释性差的原因。
随着计算机硬件的飞速发展,现阶段通过拥有众多层数神经网络来模拟人脑解释数据、处理图像,包括图像、文本、音频等内容,目前来看常见的神经网络包括:
- 卷积神经网络(CNN)
- 循环神经网络(RNN)
- 生成对抗网络(GAN)
- 深度强化网络(DRN)
2.什么是神经网络
人工神经网络,也简称为神经网络,是一种模拟生物神经网络结构和功能的计算模型。人脑可以看作是一个生物神经网络,有众多的神经元连接而成,各个神经元传递复杂的电信号,树突接收到信号,然后对信号进行处理,通过轴突输出信号,下面是生物神经网络示意图:
但其实本质上神经网络与生物学没有一点关系,只是借用这个好理解一下。
那么我们该如何构建神经网络中的神经元呢?
受神经元的启发,人工神经网络接受来自其他神经元或外部源的输入,每个输入都有一个相关的权重(w),它是根据输入对当前神经元的重要性来确认的,对该输入加权并与其他输入求和后,经过一个激活函数f,计算得到该神经元的输出。
那么,接下俩我们就利用神经元来构建神经网络,相近层之间的神经元相互连接,并给每一个链接分配一个强度,如下图所示:
神经网络中信息只像一个方向移动,即从输入节点向前移动,通过隐藏节点,在想输出节点移动,网络中没有循环或者环,其基本的结构为:
- 输入层:即输入x的那一层
- 输出层:即输出y的那一层
- 隐藏层:输入层与输出层之间的层都是隐藏层
特点是:
- 同一层的神经元之间没有连接
- 第N层的每个神经元和第N-1的所有神经元相连(即全连接),第N-1层神经元的输出就是第N层神经元的输入
- 每一个连接都有权重
3.神经元是如何工作的
人工神经元接收到一个或多个输入,对他们进行加权求和,总和通过一个非线性函数产生输出。
所有的输入xi,与相应的权重wi相乘并求和:
将求和结果送到激活函数中,得到最终的输出结果:
f(x)为激活函数
3.1激活函数
在神经元中引入了激活函数,它的本质是向神经网络中引⼊非线性因素
的,通过激活函数,神经网络就可以拟合各种曲线。如果不用激活函数,每一层输出都是上层输⼊的线性函数,无论神经网络有多少层,输出都是输⼊的线性组合,引⼊⾮线性函数作为激活函数,那输出不再是输⼊的线性组合,可以逼近任意函数。常⽤的激活函数有:
1.sigmoid函数
数学表达式为:
曲线图像为:
sigmoid 在定义域内处处可导,且两侧导数逐渐趋近于0。 如果X的值很⼤或者很⼩的时候,那么函数的梯度(函数的斜率)会⾮常⼩,在反向传播的过程中,导致了向低层传递的梯度也变得⾮常⼩。此时,⽹络参数很难得到有效训练。这种现象被称为梯度消失。 ⼀般来说, sigmoid ⽹络在 5层之内就会产⽣梯度消失现象。⽽且,该激活函数并不是以0为中⼼的,所以在实践中这种激活函数使⽤的很少。sigmoid函数⼀般只⽤于⼆分类的输出层。因为他是在(0,1)之间的。
实现方法:
import tensorflow as tf
import tensorflow.keras as keras
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(-10, 10, 100)
y = tf.nn.sigmoid(x)
plt.plot(x, y)
plt.grid() # 有网格显示
输出结果为:
2.tanh(双曲正切曲线)
数学表达式为:
曲线如下图:
tanh也是⼀种⾮常常⻅的激活函数。与sigmoid相⽐,它是以0为中⼼的,使得其收敛速度要⽐sigmoid快,减少迭代次数。然⽽,从图中可以看出,tanh两侧的导数也为0,同样会造成梯度消失。
若使⽤时可在隐藏层使⽤tanh函数,在输出层使⽤sigmoid函数。
实现方法为:
import tensorflow as tf
import matplotlib.pylab as plt
import numpy as np
x = np.linspace(-10, 10, 100)
y = tf.nn.tanh(x, y)
plt.plot(x, y)
plt.grid()
3.relu函数
数学表达式为:
曲线如下图所示:
ReLU是⽬前最常⽤的激活函数。 从图中可以看到,当x<0时,relu导数为0,⽽当x>0时,则不存在饱和问题。所以,ReLU 能够在x>0时保持梯度不衰减,从⽽缓解梯度消失问题。然⽽,随着训练的推进,部分输⼊会落⼊⼩于0区域,导致对应权重⽆法更新。这种现象被称为“神经元死亡”。
与sigmoid相⽐,RELU的优势是:
- 采⽤sigmoid函数,计算量⼤(指数运算),反向传播求误差梯度时,求导涉及除法,计算量相对⼤,⽽采⽤Relu激活函数,整个过程的计算量节省很多。
- sigmoid函数反向传播时,很容易就会出现梯度消失的情况,从⽽⽆法完成深层⽹络的训练。
- Relu会使⼀部分神经元的输出为0,这样就造成了⽹络的稀疏性,并且减少了参数的相互依存关系,缓解了过拟合问题的发⽣。
实现方法为:
import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(-10, 10, 100)
y = tf.nn.relu(x)
plt.plot(x, y)
plt.grid()
4.leaky_relu函数
它是relu的改进,数学表达式为:
曲线如下图:
leaky_relu解决了当x<10时,神经元消失的情况
实现方法为:
import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(-10, 10, 100)
y = tf.nn.leaky_relu(x)
plt.plot(x, y)
plt.grid()
5.softmax函数
softmax⽤于多分类过程中,它是⼆分类函数sigmoid在多分类上的推⼴,⽬的是将多分类的结果以概率的形式展现出来。
计算⽅法如下图所示:
使用方法:
softmax直⽩来说就是将⽹络输出的logits通过softmax函数,就映射成
为(0,1)的值,⽽这些值的累和为1(满⾜概率的性质),那么我们将它理解成概率,选取概率最⼤(也就是值对应最⼤的)接点,作为我们的预测⽬标类别。
示例:
import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np
x = tf.constant([0.2, 0.02, 0.15, 0.15, 1.3, 0.5, 0.06, 1.1, 0.05, 3.75])
y = tf.nn.softmax(x)
print(y)
输出结果为:
我们可以得到9的概率最大,那么这个数字就被识别成了9。
那么,我们如何选择激活函数呢?
1.隐藏层:
- 优先选择relu函数
- 如果relu函数效果不好,可以尝试一下leaky_relu等
- 如果使用了relu,需要注意一下神经元死亡问题,避免出现过多的神经元死亡
- 不要使用sigmoid函数,可以尝试使用tanh函数
2.输出层
- 二分类问题选择sigmoid激活函数
- 多分类问题选择softmax激活函数
- 回归问题选择identity激活函数
3.2参数的初始化
在深度学习中,神经网络的权重初始化方法对模型的收敛速度和性能有着至关重要的影响。说白了,神经网络其实就是对权重参数w 的不停迭代更新,以达到更好的性能。因此,对权重w 的初始化则显得至关重要,一个好的权重初始化虽然不能完全解决梯度消失和梯度爆炸的问题,但是对于处理这两个问题是有很大的帮助的,并且十分有利于模型性能和收敛速度。
对于某⼀个神经元来说,需要初始化的参数有两类:⼀类是权重W,还有⼀类是偏置b,偏置b初始化为0即可。⽽权重W的初始化⽐较重要,我们着重来介绍常⻅的初始化⽅式。
3.2.1随机初始化
随机初始化从均值为0,标准差为1的高斯分布中取样,使用一些很小的值对参数w进行初始化
3.2.2标准初始化
权重参数初始化从区间均匀随机取值,即在(-1/√d,1/√d)均匀分布中生成当前神经元的权重,其中d为每个神经元的输入数量。
3.2.3Xavier初始化(tf.keras中默认使用的)
网络训练的过程中, 容易出现梯度消失(梯度特别的接近0)和梯度爆炸(梯度特别的大)的情况,导致大部分反向传播得到的梯度不起作用或者起反作用. 研究人员希望能够有一种好的权重初始化方法: 让网络前向传播或者反向传播的时候, 卷积的输出和前传的梯度比较稳定. 合理的方差既保证了数值一定的不同, 又保证了数值一定的稳定.(通过卷积权重的合理初始化, 让计算过程中的数值分布稳定)
Xavier初始化也称为Glorot初始化,因为发明人为Xavier Glorot。Xavier initialization是 Glorot 等人为了解决随机初始化的问题提出来的另一种初始化方法,他们的思想就是尽可能的让输入和输出服从相同的分布,这样就能够避免后面层的激活函数的输出值趋向于0。
因为权重多使用高斯或均匀分布初始化,而两者不会有太大区别,只要保证两者的方差一样就可以了,所以高斯和均匀分布我们一起说。
1.正态化Xavier初始化(正态分布):Glorot 正态分布初始化器,也称为 Xavier 正态分布初始化器。以0为中心,标准差为stddev = sqrt(2 / (fan_in + fan_out))
的正态分布中抽取样本,其中fan_in是输入神经元的个数,fan_out是输出神经元的个数。
实现方法如下:
import tensorflow as tf
# 实例化
initailizer = tf.keras.initializers.glorot_normal()
values = initailizer((