一、神经网络
1、神经网络
人工神经网络(Artificial Neural Network,即ANN)也简称为神经网络(NN)是一种模仿生物神经网络结构 和功能的计算模型。
2、基本部分
输入层:输入 x
输出层:输出 y
隐藏层:输入与输出之间所有层
3、特点
同一层的神经元之间没有连接
第 N 层的每个神经元和第 N-1层 的所有神经元相连(full connected),即全连接神经网络
第 N-1层神经元的输出就是第 N 层神经元的输入
每个连接都有一个权重值(w系数和b系数)
二、激活函数
用于对每层的输出数据进行变换,进而为整个网络注入了非线性因素。此时, 神经网络就可以拟合各种曲线
1、sigmoid 激活函数
公式:
求导公式:
绘制函数图像:
import torch
import matplotlib.pyplot as plt# 函数图像
x = torch.linspace(-20,20,1000)
# 输入值x 通过 sigmoid函数 转换成 激活值y
y = torch.sigmoid(x)# 创建画布、坐标轴
plt.plot(x,y)
plt.grid()
plt.show()# 导数图像
x = torch.linspace(-20,20,1000,requires_grad=True)
# 自动微分
torch.sigmoid(x).sum().backward()plt.plot(x.detach(),x.grad)
plt.grid()
plt.show()
sigmoid 函数可以将任意的输入映射到 (0, 1) 之间,当输入的值大致在 <-6 或者 >6 时,意味着输入任何值 得到的激活值都是差不多的,这样会丢失部分信息。比如:输入 100 和输出 10000 经过 sigmoid 的激活值几乎都是等于 1 的,但是输入的数据之间相差 100 倍的信息就丢失了。
对于 sigmoid 函数而言,输入值在 [-6, 6] 之间输出值才会有明显差异,输入值在 [-3, 3] 之间才会有比较好的效果。
2、tanh 激活函数
公式:
求导公式:
函数图像:
3、ReLU 激活函数
公式: f (x) = max (0,x)
求导公式: f '(x) = 0 或 1
函数图像:
ReLU 激活函数将小于 0 的值映射为 0,而大于 0 的值则保持不变,它更加重视正信号,而忽略负信号,这种激活函数运算更为简单,能够提高模型的训练效率
当x<0时,ReLU导数为0,而当x>0时,则不存在饱和问题。所以,ReLU 能够在x>0时保持梯度不衰减,从而缓解梯度消失问题。然而,随着训练的推进,部分输入会落入小于0区域,导致对应权重无法更新。这种现象被称为“神经元死亡”
ReLU是目前最常用的激活函数。与sigmoid相比,ReLU的优势是:采用sigmoid函数,计算量大(指数运算),反向传播求误差梯度时,计算量相对大,而采用Relu激活函数,整个过程的计算量节省很多。 sigmoid函数反向传播时,很容易就会出现梯度消失的情况,从而无法完成深层网络的训练。 Relu会使一部分神经元的输出为0,这样就造成了网络的稀疏性,并且减少了参数的相互依存关系,缓解了过拟合问题的发生。
4、SoftMax 激活函数
softmax用于多分类过程中,它是二分类函数sigmoid在多分类上的推广,目的是将多分类的结果以概率的形式展现出来,公式如下:
Softmax 就是将网络输出的 logits 通过 softmax 函数,就映射成为(0,1)的值,而这些值的累和 为1(满足概率的性质),那么我们将它理解成概率,选取概率最大(也就是值对应最大的)节点,作为我们的预测目标类别。
scores = torch.tensor([0.2, 0.02, 0.15, 0.15, 1.3, 0.5, 0.06, 1.1, 0.05, 3.75])
probabilities = torch.softmax(scores,dim=0)
print(probabilities)
输出结果:
5、其他激活函数
6、选择方法
对于 隐藏层
1. 优先选择 ReLU激活函数
2. 如果ReLu效果不好,那么尝试其他激活,如Leaky ReLu等。
3. 如果使用了ReLU, 需要注意Dead ReLU问题, 避免出现大的梯度从而导致过多的神经元死亡。
4. 少用sigmoid激活函数,可以尝试使用tanh激活函数
对于 输出层
三、参数初始化
1、均匀分布 初始化
权重参数初始化从区间均匀随机取值,即在(,)均匀分布中生成当前神经元的权重(d为每个神经元的输入数量)
import torch
import torch.nn.functional as F
import torch.nn as nn
# 均匀分布 随机初始化
def test01():linear = nn.Linear(5, 3)# 从 0 ~ 1 均匀分布产生参数nn.init.uniform_(linear.weight)print(linear.weight.data)
2、正态分布 初始化
随机初始化从均值为0,标准差为1的高斯分布中取样,使用一些很小的值对参数W进行初始化
# 正态分布随机初始化
def test05():linear = nn.Linear(5, 3)nn.init.normal_(linear.weight, mean=0, std=1)print(linear.weight.data)
3、全0 初始化
将神经网络中的所有权重参数初始化为 0
# 全0初始化
def test03():linear = nn.Linear(5, 3)nn.init.zeros_(linear.weight)print(linear.weight.data)
4、全1 初始化
将神经网络中的所有权重参数初始化为 1
# 全1初始化
def test04():linear = nn.Linear(5, 3)nn.init.ones_(linear.weight)print(linear.weight.data)
5、固定值初始化
将神经网络中的所有权重参数初始化为 某个固定值
# 固定初始化
def test02():linear = nn.Linear(5, 3)nn.init.constant_(linear.weight, 5)print(linear.weight.data)
6、kaiming 初始化
正态化的HE初始化:均值为0,stddev(方差)=
均匀分布的HE初始化:从 [ -limit,limit ] 的均匀分布中抽取样本,limit =
input:输入神经元的个数
# kaiming 初始化
def test06():# kaiming 正态分布初始化linear = nn.Linear(5, 3)nn.init.kaiming_normal_(linear.weight)print(linear.weight.data)# kaiming 均匀分布初始化linear = nn.Linear(5, 3)nn.init.kaiming_uniform_(linear.weight)print(linear.weight.data)
7、xavier 初始化
正态化的Xavier初始化:均值为0,stddev(方差)=
均匀分布的Xavier初始化:从 [ -limit,limit ] 的均匀分布中抽取样本,limit =
input:输入神经元的个数,output:输出神经元的个数
# xavier 初始化
def test07():# xavier 正态分布初始化linear = nn.Linear(5, 3)nn.init.xavier_normal_(linear.weight)print(linear.weight.data)# xavier 均匀分布初始化linear = nn.Linear(5, 3)nn.init.xavier_uniform_(linear.weight)print(linear.weight.data)