在网站设计公司上班好吗,上海市建设执业资格注册中心网站,收录网站的二级域名,怎么免费建立自己的网站神经网络基础 前言一、神经网络1.1 基本概念1.2 工作原理 二、激活函数2.1 sigmoid激活函数2.1.1 公式2.1.2 注意事项 2.2 tanh激活函数2.2.1 公式2.2.2 注意事项 2.3 ReLU激活函数2.3.1 公式2.3.2 注意事项 2.4 SoftMax激活函数2.4.1 公式2.4.2 Softmax的性质2.4.3 Softmax的应… 神经网络基础 前言一、神经网络1.1 基本概念1.2 工作原理 二、激活函数2.1 sigmoid激活函数2.1.1 公式2.1.2 注意事项 2.2 tanh激活函数2.2.1 公式2.2.2 注意事项 2.3 ReLU激活函数2.3.1 公式2.3.2 注意事项 2.4 SoftMax激活函数2.4.1 公式2.4.2 Softmax的性质2.4.3 Softmax的应用2.4.4 代码演示2.4.5 数学计算举例2.4.6 Softmax的注意事项 三、参数初始化3.1 均匀分布初始化3.2 正态分布初始化3.3 全0初始化3.4 全1初始化3.5 固定值初始化3.6 Kaiming 初始化也叫做 HE 初始化3.6.1 正态化的Kaiming 初始化3.6.2 均匀分布的Kaiming 初始化 3.7 Xavier 初始化也叫做 Glorot初始化3.7.1 正态化的Xavier初始化3.7.2 均匀分布的Xavier初始化 四、构建简单的神经网络总结 前言
前面我们学习了深度学习当中的基础——张量接下来我们了解神经网络中的知识。 一、神经网络
神经网络是一种模拟人脑神经元结构和功能的计算模型旨在解决复杂的模式识别和预测问题
1.1 基本概念 神经元神经元是神经网络的基本组成单元它接收输入信号通过对输入信号的处理产生输出信号。每个神经元都有多个输入和一个输出输入可以是其他神经元的输出也可以是外部输入信号。 层级结构神经网络由多个层级结构组成包括输入层、隐藏层和输出层。输入层接收来自外部环境的数据每个神经元代表一个输入特征隐藏层负责对输入数据进行非线性变换提取特征输出层输出预测结果每个神经元代表一个输出值。 连接权重连接不同神经元之间的权重决定信号的传递强度。这些权重在神经网络的训练过程中不断调整以实现更好的预测性能。 激活函数激活函数用于对神经元输出进行非线性变换引入非线性特性。常见的激活函数包括sigmoid函数、ReLU函数、tanh函数等。不同的激活函数有不同的性质可以根据具体的任务需求选择不同的激活函数。
1.2 工作原理
层级传播信号通过逐层传递最终到达输出层。输出预测输出层的神经元输出预测结果。误差反向传播根据预测结果与真实值的误差通过反向传播算法更新连接权重。反向传播算法通过从输出层向输入层反向传播误差依次更新权重和偏置使得网络的预测能力逐渐提高。
二、激活函数
用于对每层的输出数据进行变换从而为整个网络注入了非线性因素此时的神经网络就可以拟合各种曲线提高应对复杂问题的拟合能力。
2.1 sigmoid激活函数
2.1.1 公式 f ( x ) 1 1 e − x f(x)\frac{1}{1e^{-x}} f(x)1e−x1
求导后的公式 f ′ ( x ) ( 1 1 e − x ) ′ 1 1 e − x ( 1 − 1 1 e − x ) f ( x ) ( 1 − f ( x ) ) f(x)(\frac{1}{1e^{-x}})\frac{1}{1e^{-x}}(1-\frac{1}{1e^{-x}})f(x)(1-f(x)) f′(x)(1e−x1)′1e−x1(1−1e−x1)f(x)(1−f(x)) 代码演示 import torch
import matplotlib.pyplot as pltplt.rcParams[font.sans-serif] [SimHei] # 用来正常显示中文标签
plt.rcParams[axes.unicode_minus] False # 用来正常显示负号# 创建画布和坐标轴
_, axes plt.subplots(1, 2)
# sigmoid函数图像
x torch.linspace(-20, 20, 1000)
# 输入值x通过sigmoid函数转换成激活值y
y torch.sigmoid(x)
axes[0].plot(x, y)
axes[0].grid()
axes[0].set_title(Sigmoid 函数图像)# sigmoid导数图像
x torch.linspace(-20, 20, 1000, requires_gradTrue)
torch.sigmoid(x).sum().backward()# y 2 * torch.dot(x, x)
# y.backward()
# x.detach():输入值x的数值
# x.grad:计算梯度求导
axes[1].plot(x.detach(), x.grad)
axes[1].grid()
axes[1].set_title(Sigmoid 导数图像)
plt.show()函数图像如下
2.1.2 注意事项
sigmoid函数可以将任意值的输入映射到01之间从图中我们可以看出当输入的值大致在 -6 或者 6 的时候此时输入任何值得到的激活值都差不多这样就会导致丢失部分信息。对于sigmoid函数而言输入值在[-6,6]之间才会有明显差异输入值在[-3,3]之间才会有比较好的结果。由导函数的图像导数的数值范围是0,025当输入* -6 或者 6 的时候sigmoid激活函数图像的导数接近于0此时网络参数将更新缓慢或者无法更新。一般来说sigmoid的网络在五层之内就会产生梯度消失的现象而且该激活函数不以0为中心所以在实践中使用很少。一般只用于二分类的输出层。
2.2 tanh激活函数
2.2.1 公式 f ( x ) 1 − e − 2 x 1 e − 2 x f(x)\frac{1-e^{-2x}}{1e^{-2x}} f(x)1e−2x1−e−2x
求导后的公式 f ′ ( x ) ( 1 − e − 2 x 1 e − 2 x ) ′ 1 − f 2 ( x ) f(x)(\frac{1-e^{-2x}}{1e^{-2x}})1-f^2(x) f′(x)(1e−2x1−e−2x)′1−f2(x) 代码演示 import torch
import matplotlib.pyplot as pltplt.rcParams[font.sans-serif] [SimHei] # 用来正常显示中文标签
plt.rcParams[axes.unicode_minus] False # 用来正常显示负号# 创建画布和坐标轴
_, axes plt.subplots(1, 2)
# 函数图像
x torch.linspace(-20, 20, 1000)
y torch.tanh(x)
axes[0].plot(x, y)
axes[0].grid()
axes[0].set_title(Tanh 函数图像)# 导数图像
x torch.linspace(-20, 20, 1000, requires_gradTrue)
torch.tanh(x).sum().backward()
axes[1].plot(x.detach(), x.grad)
axes[1].grid()
axes[1].set_title(Tanh 导数图像)
plt.show()2.2.2 注意事项
Tanh函数将输入映射在-1,1之间图像以0为中心在0点对称当输入 -3 或者 3 的时会被映射成 -1 或者 1 。导函数的取值范围01当输入的值 -3 或者 3 的时其导函数近似0。与sigmoid相比它是以0为中心并且梯度相对于sigmoid大使得其收敛速度要比sigmoid快减少迭代刺水。然而从图中可以看出Tanh两侧的导数也为0同样会出现梯度消失的情况。若使用的时候可以再隐藏层使用Tanh函数在输出层使用sigmoid函数。
2.3 ReLU激活函数
2.3.1 公式 f ( x ) m a x ( 0 , x ) f(x)max(0, x) f(x)max(0,x)
求导后的公式 f ′ ( x ) 0 或者 1 f(x)0或者1 f′(x)0或者1 代码演示 # 创建画布和坐标轴
import torch
from matplotlib import pyplot as pltplt.rcParams[font.sans-serif] [SimHei] # 用来正常显示中文标签
plt.rcParams[axes.unicode_minus] False # 用来正常显示负号_, axes plt.subplots(1, 2)
# 函数图像
x torch.linspace(-20, 20, 1000)
y torch.relu(x)
axes[0].plot(x, y)
axes[0].grid()
axes[0].set_title(ReLU 函数图像)
# 导数图像
x torch.linspace(-20, 20, 1000, requires_gradTrue)
torch.relu(x).sum().backward()
axes[1].plot(x.detach(), x.grad)
axes[1].grid()
axes[1].set_title(ReLU 导数图像)
plt.show()2.3.2 注意事项
ReLU 激活函数将小于0的值映射为 0而大于 0 的值则保持不变它更加重视正信号而忽略负信号这种激活函数运算更为简单能够提高模型的训练效率。当x0时ReLU导数为0而当x0时则不存在饱和问题。所以ReLU能够在x0时保持梯度不衰减从而缓解梯度消失问题。然而随着训练的推进部分输入会落入小于0区域导致对应权重无法更新。这种现象被称为“神经元死亡”ReLU是目前最常用的激活函数。 与sigmoid相比RELU的优势是:采用sigmoid函数计算量大(指数运算)反向传播求误差梯度时计算量相对大而采用Relu激活函数整个过程的计算量节省很多。siqmoid函数反向传播时很容易就会出现梯度消失的情况从而无法完成深层网络的训练。Relu会使一部分神经元的输出为0这样就造成了网络的稀疏性并且减少了参数的相互依存关系缓解了过拟合问题的发生。
2.4 SoftMax激活函数
2.4.1 公式 Softmax函数的本质是一种归一化函数它将一个数值向量归一化为一个概率分布向量且各个概率之和为1。对于一个给定的实数向量zSoftmax函数首先计算每一个元素的指数e的幂然后每个元素的指数与所有元素指数总和的比值就形成了Softmax函数的输出。 Softmax ( z i ) e z i ∑ j 1 K e z j \text{Softmax}(z_i) \frac{e^{z_i}}{\sum_{j1}^{K} e^{z_j}} Softmax(zi)∑j1Kezjezi 其中 z i z_i zi 表示输入向量 z z z 的第 i i i 个分量 K K K 是类别总数即向量 z z z 的维度 e e e 是自然对数的底数。 实际计算的时候需要输入向量减去向量中的最大值 在实际应用中直接计算 e z i e^{z_i} ezi 可能会导致数值溢出特别是当输入值很大时。为了防止这种情况可以在计算前减去向量中的最大值。
2.4.2 Softmax的性质
归一化Softmax保证所有输出值的和为1使其可以被解释为概率。可微性Softmax函数在整个定义域内可微这使得它可以在基于梯度的优化算法中使用例如反向传播。敏感性Softmax对输入值非常敏感尤其是当有一个输入远大于其他输入时。
2.4.3 Softmax的应用
多类别分类问题Softmax函数常用于多类别分类问题中将输入向量映射为各个类别的概率。在神经网络中Softmax通常作为输出层的激活函数将网络的输出转换为类别概率。交叉熵损失函数在训练神经网络时Softmax函数通常与交叉熵损失函数结合使用。交叉熵损失函数用于衡量预测概率分布与真实标签之间的差异从而进行模型的训练和优化。
2.4.4 代码演示 代码演示 import torchscores torch.tensor([0.2, 0.02, 0.15, 0.15, 1.3, 0.5, 0.06, 1.1, 0.05, 3.75])
# dim 0,按行计算
probabilities torch.softmax(scores, dim0)
print(probabilities)2.4.5 数学计算举例
0、背景 假设我们有一个神经网络用于识别手写数字0 到 9。神经网络的输出层有 10 个神经元每个神经元对应一个数字类别。在训练完成后对于一个新的输入图像神经网络的输出层会产生一个 10 维的实数向量。我们需要将这个向量转换为一个概率分布以便确定哪个数字最有可能是正确的。 1、输入向量 z [ 1.0 , 2.0 , 3.0 , 4.0 , 1.0 , 0.5 , 0.0 , − 1.0 , − 2.0 , − 3.0 ] z [1.0,2.0,3.0,4.0,1.0,0.5,0.0,−1.0,−2.0,−3.0] z[1.0,2.0,3.0,4.0,1.0,0.5,0.0,−1.0,−2.0,−3.0] 2、减去最大值 为了防止数值溢出我们先减去向量中的最大值4.0 z ′ [ 1.0 − 4.0 , 2.0 − 4.0 , 3.0 − 4.0 , 4.0 − 4.0 , 1.0 − 4.0 , 0.5 − 4.0 , 0.0 − 4.0 , − 1.0 − 4.0 , − 2.0 − 4.0 , − 3.0 − 4.0 ] z[1.0−4.0,2.0−4.0,3.0−4.0,4.0−4.0,1.0−4.0,0.5−4.0,0.0−4.0,−1.0−4.0,−2.0−4.0,−3.0−4.0] z′[1.0−4.0,2.0−4.0,3.0−4.0,4.0−4.0,1.0−4.0,0.5−4.0,0.0−4.0,−1.0−4.0,−2.0−4.0,−3.0−4.0] z ′ [ − 3.0 , − 2.0 , − 1.0 , 0.0 , − 3.0 , − 3.5 , − 4.0 , − 5.0 , − 6.0 , − 7.0 ] z [−3.0,−2.0,−1.0,0.0,−3.0,−3.5,−4.0,−5.0,−6.0,−7.0] z′[−3.0,−2.0,−1.0,0.0,−3.0,−3.5,−4.0,−5.0,−6.0,−7.0] 3、计算指数 e z ′ [ e − 3.0 , e − 2.0 , e − 1.0 , e 0.0 , e − 3.0 , e − 3.5 , e − 4.0 , e − 5.0 , e − 6.0 , e − 7.0 ] e^{z} [e^{-3.0},e^{-2.0},e^{-1.0},e^{0.0},e^{-3.0},e^{-3.5},e^{-4.0},e^{-5.0},e^{-6.0},e^{-7.0}] ez′[e−3.0,e−2.0,e−1.0,e0.0,e−3.0,e−3.5,e−4.0,e−5.0,e−6.0,e−7.0] import numpy as npz_prime np.array([-3.0, -2.0, -1.0, 0.0, -3.0, -3.5, -4.0, -5.0, -6.0, -7.0])
exp_z_prime np.exp(z_prime)
print(exp_z_prime)[‘0.0497870684’, ‘0.1353352832’, ‘0.3678794412’, ‘1.0000000000’, ‘0.0497870684’, ‘0.0301973834’, ‘0.0183156389’, ‘0.0067379470’, ‘0.0024787522’, ‘0.0009118820’] 4、计算分母 ∑ i 1 10 e z ′ 0.0497870684 0.1353352832 0.3678794412 1.0000000000 0.0497870684 0.0301973834 0.0183156389 0.0067379470 0.0024787522 0.0009118820 \sum_{i1}^{10}e^{z} 0.04978706840.13533528320.36787944121.00000000000.04978706840.03019738340.01831563890.00673794700.00247875220.0009118820 ∑i110ez′0.04978706840.13533528320.36787944121.00000000000.04978706840.03019738340.01831563890.00673794700.00247875220.0009118820 ∑ i 1 10 e z ′ 1.6614304647 \sum_{i1}^{10}e^{z} 1.6614304647 ∑i110ez′1.6614304647 5、计算Softmax 将每个指数除以总和得到概率分布 s o f t m a x ( z i ) e z ′ ∑ i 1 10 e z ′ softmax(z_i) \frac{e^{z}}{\sum_{i1}^{10}e^{z}} softmax(zi)∑i110ez′ez′
sum_exp_z_prime np.sum(exp_z_prime)
softmax_output exp_z_prime / sum_exp_z_prime
print(softmax_output)- 输出结果为[0.0299663871,0.0814570854,0.2214233150,0.6018909737,0.0299663871,0.0181755325,0.0110240177,0.0040555095,0.0014919386,0.0005488535]6、结果解释 第四个元素的概率最高为0.6018909737所以预测为 数字 3其他数字概率较小所以表示其他数字的可能性较小
2.4.6 Softmax的注意事项
输入值范围Softmax函数的输入值可以是任意实数但通常在实际应用中输入值是经过神经网络计算得到的logits即未归一化的得分或置信度。数值稳定性在计算Softmax函数时由于涉及到指数运算可能会出现数值溢出或下溢的问题。为了解决这个问题通常会对输入值进行适当的缩放或平移处理。互斥类别Softmax函数适用于类别互斥的情况即每个样本只能属于一个类别。如果问题是多标签分类即一个样本可能属于多个类别则需要使用其他方法如sigmoid函数或其他多标签分类算法。
三、参数初始化 导包 import torch
import torch.nn.functional as F
import torch.nn as nn3.1 均匀分布初始化
权重参数初始化从区间均匀随机取值。即在( − 1 d , 1 d \frac{-1}{\sqrt{d}},\frac{1}{\sqrt{d}} d −1,d 1 )均匀分布中生成当前神经元的权重其中 d d d 为每个神经元的输入数量 代码演示 linear nn.Linear(5, 3)
# 从0-1均匀分布产生参数
nn.init.uniform_(linear.weight)
print(linear.weight.data)3.2 正态分布初始化
随机初始化从均值为0标准差是1的高斯分布中取样使用一些很小的值对参数 W W W 进行初始化 代码演示 linear nn.Linear(5, 3)
nn.init.normal_(linear.weight, mean0, std1)
print(linear.weight.data)3.3 全0初始化
将神经网络中的所有权重参数初始化为 0 代码演示 linear nn.Linear(5, 3)
nn.init.zeros_(linear.weight)
print(linear.weight.data)3.4 全1初始化
将神经网络中的所有权重参数初始化为 1 代码演示 linear nn.Linear(5, 3)
nn.init.ones_(linear.weight)
print(linear.weight.data)
3.5 固定值初始化
将神经网络中的所有权重参数初始化为某个固定值 代码演示 linear nn.Linear(5, 3)
nn.init.constant_(linear.weight, 5) # 里边写 几 就是 用哪个值初始化
print(linear.weight.data)3.6 Kaiming 初始化也叫做 HE 初始化
3.6.1 正态化的Kaiming 初始化 s t d d e v 2 f a n i n stddev \sqrt{\frac{2}{fan_{in}}} stddevfanin2 f a n i n fan_{in} fanin 输入神经元的个数 代码演示 # kaiming 正态分布初始化
linear nn.Linear(5, 3)
nn.init.kaiming_normal_(linear.weight)
print(linear.weight.data)3.6.2 均匀分布的Kaiming 初始化 f a n i n fan_{in} fanin 输入神经元的个数它从 [ − l i m i t l i m i t ] [-limitlimit] [−limitlimit] 中的均匀分布中抽取样本, l i m i t limit limit 是 6 f a n i n \sqrt{\frac{6}{fan_{in}}} fanin6 代码演示 # kaiming 均匀分布初始化
linear nn.Linear(5, 3)
nn.init.kaiming_uniform_(linear.weight)
print(linear.weight.data)3.7 Xavier 初始化也叫做 Glorot初始化
3.7.1 正态化的Xavier初始化 s t d d e v 2 f a n i n f a n o u t stddev \sqrt{\frac{2}{fan_{in}fan_{out}}} stddevfaninfanout2 f a n i n fan_{in} fanin 输入神经元的个数 f a n o u t fan_{out} fanout 输出的神经元个数 代码演示 # xavier 正态分布初始化
linear nn.Linear(5, 3)
nn.init.xavier_normal_(linear.weight)
print(linear.weight.data)3.7.2 均匀分布的Xavier初始化
它从 [ − l i m i t l i m i t ] [-limitlimit] [−limitlimit] 中的均匀分布中抽取样本, l i m i t limit limit 是 6 f a n i n f a n o u t \sqrt{\frac{6}{fan_{in}fan_{out}}} faninfanout6 代码演示 # xavier 均匀分布初始化
linear nn.Linear(5, 3)
nn.init.xavier_uniform_(linear.weight)
print(linear.weight.data)四、构建简单的神经网络
案例我们构建如下网络 要求如下 第1个隐藏层权重初始化采用标准化的xavier初始化 激活函数使用sigmoid第2个隐藏层权重初始化采用标准化的He初始化 激活函数采用reluout输出层线性层采用 softmax 做数据分类输出 代码演示 在pytorch中定义深度神经网络其实就是层堆叠的过程继承自nn.Module实现两个方法1、__init__方法中定义网络中的层结构主要是全连接层并进行初始化2、forward方法在实例化模型的时候底层会自动调用该函数。该函数中可以定义学习率为初始化定义的layer传入数据等。import torch
import torch.nn as nn
from torchsummary import summary # 计算模型参数,查看模型结构, pip install torchsummary# 创建神经网络模型类
class Model(nn.Module):# 初始化属性值def __init__(self):super(Model, self).__init__() # 调用父类的初始化属性值self.linear1 nn.Linear(3, 3) # 创建第一个隐藏层模型, 3个输入特征,3个输出特征nn.init.xavier_normal_(self.linear1.weight) # 初始化权# 创建第二个隐藏层模型, 3个输入特征(上一层的输出特征),2个输出特征self.linear2 nn.Linear(3, 2)# 初始化权重nn.init.kaiming_normal_(self.linear2.weight)# 创建输出层模型self.out nn.Linear(2, 2)# 创建前向传播方法,自动执行forward()方法def forward(self, x):# 数据经过第一个线性层x self.linear1(x)# 使用sigmoid激活函数x torch.sigmoid(x)# 数据经过第二个线性层x self.linear2(x)# 使用relu激活函数x torch.relu(x)# 数据经过输出层x self.out(x)# 使用softmax激活函数# dim-1:每一维度行数据相加为1x torch.softmax(x, dim-1)return xif __name__ __main__:# 实例化model对象my_model Model()# 随机产生数据my_data torch.randn(5, 3)print(mydata shape, my_data.shape)# 数据经过神经网络模型训练output my_model(my_data)print(output shape--, output.shape)# 计算模型参数# 计算每层每个神经元的w和b个数总和summary(my_model, input_size(3,), batch_size5) # 查看模型参数print(查看模型参数w和b)for name, parameter in my_model.named_parameters():print(name, parameter)总结
我们通过学习了激活函数和参数初始化后我们能实现搭建一个简单的神经网络。