神经网络介绍

神经网络介绍

<1>神经网络概念

神经网络:ANN

是一种模仿生物神经网络结构和功能的计算模型,由众多神经元构成,各个神经元传递复杂电信号树突接收到输入信号,通过处理转换为输出信号

神经网络构建:

如何构建人工神经网络,如下图所示:

通过不同树突中含有的权重信息,进行加权计算,输入到细胞中做加和 ,在通过激活函数输出细胞值

神经网络构造图:输入层,隐藏层,输出层构造而成

使用多个神经元来构建神经网络,相邻层之间的神经元相互连接,并给每一个连接分配一个强度.

神经网络:

​ 神经网络中的信息只向一个方向移动,即输入节点向前移动,通过隐藏节点移动.其中的基本部分是:

​ 1. 输入层: 输入x的一层

​ 2. 隐藏层:输入x与y之间都为隐藏层

​ 3. 输出层:输出y的那一层

特点是:

  • 同一层神经元之间没有连接

  • 全连接神经网络:第N层的每个神经元和第N-层的所有神经元相连接

  • N-1层的输出为N层的输入

  • 每个链接都有一个权重值(w系数和b系数)

<2>激活函数

概述:用于对每层的输出数据进行变换.为整个网络注入非线性因素,神经网络就可拟合各种曲线.

  • 1.没有引入非线性因素的网络等价于使用一个线性模型来拟合

  • 2.通过给网络输出增加激活函数,引入非线性因素,使网络模型可以逼近任意函数,提升拟合能力

<3>常见的激活函数
1.sigmoid函数

激活函数公式:
f ( x ) = 1 1 + e − x f(x) = \frac{1}{1 + e^{-x}} f(x)=1+e−x1

激活函数求导公式:
f ′ ( x ) = f ( x ) ( 1 − f ( x ) ) f′(x)=f(x)(1−f(x)) f′(x)=f(x)(1−f(x))

sigmoid的函数图像,导数图像如下:

sigmoid函数介绍

将任意输入映射到(0,1)之间,当输入的值在-6或者>6时,意味着输入任何值得到的激活值都差不多的,这样会丢失部分信息.

通过导数数据取值范围为(0,0.25),在五层以后会出现梯度消失 情况,sigmoid一般只用于二分类

一般来说,sigmoid网络在5层之内就会产生梯度消失现象,而且该函数不是以0为中心点的,在实际中该函数很少使用,sigmoid函数一般用于二分类.

  • 代码展示
python 复制代码
import torch
import matplotlib.pyplot as plt

# 创建画布和坐标轴
_, 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_grad=True)
torch.sigmoid(x).sum().backward()
# x.detach():输入值x的数值
# x.grad:计算梯度,求导
axes[1].plot(x.detach(), x.grad)
axes[1].grid()
axes[1].set_title('Sigmoid 导数图像')
plt.show()
2.tanh函数

Tanh函数公式如下:
tanh ⁡ ( x ) = 1 − e − 2 x 1 + e − 2 x \tanh(x) =\frac{1 - e^{-2x}}{1 + e^{-2x}} tanh(x)=1+e−2x1−e−2x

函数求导公式:
tanh ⁡ ′ ( x ) = 1 − tanh ⁡ 2 ( x ) \tanh'(x) = 1 - \tanh^2(x) tanh′(x)=1−tanh2(x)

Tanh的函数图像,导数图像如下:

tanh函数介绍

  • tanh函数将输入映射到(-1,1)之间, 当输入大概<-3或者>3时将映射到(-1,1)之间,其导数值范围(0,1),当输入值大概子<-3或者>3时,导数近似于0

  • 梯度大于sigmoid,收敛速度比其快,减少迭代次数,如图所示导数两侧为零,也会梯度消失.

  • 若使用时在隐藏层使用tanh函数,在输出层使用sigmoid函数

python 复制代码
import torch
import matplotlib.pyplot as plt

# 创建画布和坐标轴
_, 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_grad=True)
torch.tanh(x).sum().backward()
axes[1].plot(x.detach(), x.grad)
axes[1].grid()
axes[1].set_title('Tanh 导数图像')
plt.show()
3.Relu函数

ReLu函数公式
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

Relu的函数图像如下:

Relu函数介绍:

  • Relu激活函数将小于0的值映射为0,大于0的值则保持不变,更加重视正信号,而忽略负信号,能提高模型的训练效率
  • 当x<0时,Relu导数为0,而当x>0时则存在饱和问题,所以Relu函数在x>0时保持梯度不衰减,从而缓解梯度消失问题,随着训练的推进,部分输入会落入小于0的区域,导致权重无法更新,被称为:神经元死亡.
  • Relu函数是目前最常用的激活函,与sigmoid函数相比Relu函数计算量较小Relu函数会使一部分神经元输出为0,使网络稀疏化,减少参数之间的依赖性,缓解过拟合发生

代码展示

python 复制代码
# 创建画布和坐标轴
import torch
from matplotlib import pyplot as plt

_, 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_grad=True)
torch.relu(x).sum().backward()
axes[1].plot(x.detach(), x.grad)
axes[1].grid()
axes[1].set_title('ReLU 导数图像')
plt.show()

Relu特点

  • 简单高效:计算简单,前向和反向传播速度快
  • 稀疏激活:可以产生零输出,有助于稀疏表示
  • 缓解梯度消失问题:对于正向输出,梯度恒为1,有助于缓解梯度消失问题
  • 死区问题:对于负输入,梯度为0,可能导致死区问题

其他常见Relu函数

1.Leaky ReLU函数:用于给 负数梯度输入提供一个非零梯度

公式定义:
f ( x ) = { x if x > = 0 α x if x < 0 \text{f}(x) = \begin{cases} x & \text{if } x >= 0 \\ αx & \text{if x < 0} \end{cases} f(x)={xαxif x>=0if x < 0

其中α是一个小的正数,通常取0.01

  • 特点:

    • 缓解死区问题:对于负输入的,梯度不为零,可以缓解ReLU死区问题
    • **保持简单:**计算任然简单,前向,反向传播速度快
  • 调用方式

python 复制代码
torch.nn.LeakyRelu(negative_slope = 0.01)

2.PReLU函数: 与Leaky Relu类似,但α参数 可以学习

公式定义
f ( x ) = { x if x > = 0 α x if x < 0 \text{f}(x) = \begin{cases} x & \text{if } x >= 0 \\ αx & \text{if x < 0} \end{cases} f(x)={xαxif x>=0if x < 0

其中,α是一个可学习的参数

  • 特点

    • 自适应:α是一个可学习的参数,可以自动调节 负半轴斜率
    • 灵活性:比Leaky ReLU更灵活,可以更好的适应于不同的数据分布
  • 调用方式:

python 复制代码
torch.nn.PReLU(num_parameters=1, init=0.25)

3.ELU函数:

数学定义:
f ( x ) = { x if x > = 0 α ( e x − 1 ) if x < 0 \text{f}(x) = \begin{cases} x & \text{if } x >= 0 \\ α(e^x - 1) & \text{if x < 0} \end{cases} f(x)={xα(ex−1)if x>=0if x < 0

其中,α为正数通常取1.0

  • 特点
    • 平滑过渡:负半轴上有平滑的过渡,有助于减少梯度消失问题
    • 均值接近于零:激活函数的输出均值接近零,有助于加速训练
  • 调用方式
python 复制代码
torch.nn.ELU(alpha=1.0)

总结

  • ReLU:简单高效,广泛使用,但存在死区问题。
  • Leaky ReLU:缓解死区问题,保持简单。
  • PReLU:自适应调整负半轴斜率,灵活性更高。
  • ELU:平滑过渡,均值接近零,有助于加速训练。
4.Softmax激活函数

适用于多分类,目的是将多分类的结果以概率的形式展示出来

函数公式:
s o f t m a x ( z i ) = e z i ∑ j e z j softmax(z_i)=\frac{e^{z_i}}{\sum_j{e{z_j}}} softmax(zi)=∑jezjezi

softmax函数介绍

就是将网络输出通过softmax函数,映射到(0,1)的值,这些值的累计和为1(满足概率的性质),可以将其理解为概率,选取概率最大的节点作为我们预测目标类别。

  • 代码展示
python 复制代码
import torch

scores = 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, dim=0)
print(probabilties)
激活函数选择方法
对于隐藏层:
  • 1.优先选择ReLU激活函数

  • 2.如果ReLU效果不好,可以尝试其他激活函数 ,如Leaky ReLU

  • 3 .如果使用ReLU函数,注意神经元死区问题,可更换Relu其他变体激活函数

  • 4.少使用sigmoid激活函数,可以尝试使用tanh激活函数

对于输出层
  • 二分类问题选择sigmoid函数

  • 多分类问题使用softmax函数

  • 回归问题选择identity 激活函数

<4>.参数初始化方法

均匀分布初始化:uniform_

权重参数初始化从区间均匀 随机取值即在(-1/√d,1/√d)均匀分布中生成当前神经元的权重,其中d为每个神经元的输入数量

python 复制代码
# 1.导入数据包
import torch
import torch.nn as nn

# 2.均匀分布初始化
def test01():
    # 全连接线性层
    linear = nn.Linear(5, 3)
    # 从0-1均匀分布 产生参数
    nn.init.uniform_(linear.weight)
    print(linear.weight.data)

正态分布初始化:normal_

随机初始化均值为0,标准差为1,使用一些很小的值对参数w进行初始化

python 复制代码
# 3.正态分布初始化
def test02():
    # 全连接线性层
    linear = nn.Linear(5, 3)
    # 正态分布
    nn.init.normal_(linear.weight, mean=0, std=1)
    print(linear.weight.data)

固定值初始化:constant_

将神经元 所有权重参数初始化固定为某个值

python 复制代码
# 4.固定值初始化
def test03():
    # 全连接线性层
    linear = nn.Linear(5, 3)
    # 固定值初始化
    nn.init.constant_(linear.weight, 0.1)
    print(linear.weight.data)

全零初始化:zreos_

将神经网络中的所有权重参数初始化为 0

python 复制代码
# 5.全零初始化
def test04():
    # 全连接线性层
    linear = nn.Linear(5, 3)
    # 全零初始化
    nn.init.zeros_(linear.weight)
    print(linear.weight.data)

全1初始化:ones_

将神经网络中的所有权重参数初始化为 1.

python 复制代码
# 6.全1初始化
def test05():
    # 全连接线性层
    linear = nn.Linear(5, 3)
    # 全1初始化
    nn.init.ones_(linear.weight)
    print(linear.weight.data)

Kaiming初始化,也叫HE初始化 适用于Relu激活函数以及变体

均匀分布初始化:unifrom_

python 复制代码
# 它从 [-limit,limit] 中的均匀分布中抽取样本, limit是 sqrt(6 / fan_in)
#  fan_in为输入神经元个数

# kaiming均匀分布
def test07():
    linear = nn.Linear(5, 3)
    nn.init.kaiming_uniform_(linear.weight)
    print(linear.weight.data)

正态化初始化:normal_

python 复制代码
# stddev = sqrt(2 / fan_in)
# sqrt:根号

# kaiming正态分布
def test06():
    linear = nn.Linear(5, 3)
    nn.init.kaiming_normal_(linear.weight)
    print(linear.weight.data)

Xavier初始化,也叫Glorot初始化 适用于sigmoid,tanh激活函数

正态化初始化:uniform_

python 复制代码
# stddev = sqrt(2 / (fan_in + fan_out))

# xavier正态分布
def test08():
    linear = nn.Linear(5, 3)
    nn.init.xavier_normal_(linear.weight)
    print(linear.weight.data

均匀分布初始化:normal_

python 复制代码
# [-limit,limit] 中的均匀分布中抽取样本, limit 是 sqrt(6 / (fan_in + fan_out))
# fan_in 是输入神经元的个数, fan_out 是输出的神经元个数

# xavier均匀分布
def test09():
    linear = nn.Linear(5, 3)
    nn.init.xavier_uniform_(linear.weight)
    print(linear.weight.data)
<5>.神经网络搭建及参数计算

在pytorch中定义深度神经网络 就是堆叠的过程,继承自nn.Model,实现两个方法:

  • __init__定义网络中的层结构,主要进行全连接层,并进行参数初始化:初始化权重系数和偏置值

  • forword方法,在实例化模型时,底层会自动调用该函数,该函数可定义学习率,为初始化定义的layer传入数据.

来构建如下图神经网络模型

编程设计如下

第1个隐藏层:权重初始化采用标准化的xavier初始化 激活函数使用sigmoid

第2个隐藏层:权重初始化采用标准化的He初始化 激活函数采用relu

out输出层线性层 假若二分类,采用softmax做数据归一化

python 复制代码
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:每一维度行数据相加为1
        x = torch.softmax(x, dim=-1)
        return x


if __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_size=5) 
    # 查看模型参数
    print("======查看模型参数w和b======")
    for name, parameter in my_model.named_parameters():
        print(name, parameter)

总结

神经网络搭建方法

1.定义继承nn.Model的模型类

2.在__init__ 方法中定义网络的结构:定义各个层的网络并初始化权重系数和偏置

3.在forward方法中定义数据传输方式:使用激活函数增加非线性因素提高拟合能力

激活函数使用

介绍几种常用的激活函数,具体使用还要结合遇到的问题

相关推荐
神奇霸王龙几秒前
2026旗舰六阶段MCP流水线实战指南
人工智能·ai·ai作画·prompt·aigc·mcp
山河不见老3 分钟前
【Cursor 、Qoder安装问题】Cursor 、Qoder安装卡在“正在准备安装”问题排查及解决
人工智能·windows·编辑器
新知图书3 分钟前
2.3 开发工作流
人工智能·agent·ai agent·智能体
tuanxiang5 分钟前
用免费 AI 改写工具处理批量文案的踩坑记录,附完整降噪脚本
人工智能
小邓的技术笔记6 分钟前
DeepSeek 大模型落地应用与场景实战指南
大数据·人工智能
石榴12 分钟前
从 Codex + Obsidian 到本地 RAG:我的私人知识库实践
人工智能
QZSJTR17 分钟前
技术解析|从SEO到GEO:生成式搜索时代实体企业数字化适配方案
人工智能
安逸sgr18 分钟前
如何减少 Prompt 引起的幻觉和答非所问?
人工智能·ai·大模型·prompt·agent·智能体
Vince的修炼之路18 分钟前
大模型 Skills 技术深度分析
人工智能·架构
小码哥哥20 分钟前
企业级AI知识库:高效安全的知识管理新范式
人工智能·安全