一、神经网络

1 感知神经网络

神经网络(Neural Networks)是一种模拟人脑神经元网络结构的计算模型,用于处理复杂的模式识别、分类和预测等任务。生物神经元如下图:

人脑神经元处理信息的过程:

多个信号到达树突,然后整合到细胞体的细胞核中

当积累的信号超过某个阈值,细胞就会被激活

产生一个输出信号,由轴突传递。

而神经网络由多个互相连接的节点(即人工神经元)组成。

2 人工神经元

人工神经元(Artificial Neuron)是神经网络的基本构建单元,模仿了生物神经元的工作原理。其核心功能是接收输入信号,经过加权求和和非线性激活函数处理后,输出结果。

2.1 构建人工神经元

人工神经元接受多个输入信息,对它们进行加权求和,再经过激活函数处理,最后将这个结果输出。

2.2 组成部分

输入(Inputs): 代表输入数据,通常用向量表示,每个输入值对应一个权重。

权重(Weights): 每个输入数据都有一个权重,表示该输入对最终结果的重要性。

偏置(Bias): 一个额外的可调参数,作用类似于线性方程中的截距,帮助调整模型的输出。

加权求和: 神经元将输入乘以对应的权重后求和,再加上偏置。

激活函数(Activation Function): 用于将加权求和后的结果转换为输出结果,引入非线性特性,使神经网络能够处理复杂的任务。常见的激活函数有Sigmoid、ReLU(Rectified Linear Unit)、Tanh等。

2.3 数学表示

如果输入有n个,x1,x2,……,xn,权重分别为w1,w2,……,wn,偏置为b,则神经元的输出y表示为:

z=\sum_{i=1}^{n}wi*xi+b

y=\sigma (z)

其中,y=\sigma (z) 是激活函数。

线性回归:y=\sum_{i=1}^{n}wi*xi+b,线性回归不需要激活函数。

逻辑回归:z=\sum_{i=1}^{n}wi*xi+by=\sigma (z)=sigmoid(z)=\tfrac{1}{1+_{e}^{-z}}

2.4 对比生物神经元

生物神经元人工神经元
细胞核节点 (加权求和 + 激活函数)
树突输入
轴突带权重的连接
突触输出

3 深入神经网络

神经网络是由大量人工神经元按层次结构连接而成的计算模型。每一层神经元的输出作为下一层的输入,最终得到网络的输出。

3.1 基本结构

神经网络有下面三个基础层构建而成:

输入层(Input): 神经网络的第一层,负责接收外部数据,不进行计算。

隐藏层(Hidden): 位于输入层和输出层之间,进行特征提取和转换。隐藏层一般有多层,每一层有多个神经元。

输出层(Output): 网络的最后一层,产生最终的预测结果或分类结果

3.2 网络构建

我们使用多个神经元来构建神经网络,相邻层之间的神经元相互连接,并给每一个连接分配一个权重,同一层的各个神经元之间是没有连接的。

3.3 全连接神经网络

前馈神经网络(Feedforward Neural Network,FNN)是一种最基本的神经网络结构,其特点是信息从输入层经过隐藏层单向传递到输出层,没有反馈或循环连接。

全连接神经网络(Fully Connected Neural Network,FCNN)是前馈神经网络的一种,每一层的神经元与上一层的所有神经元全连接,常用于图像分类、文本分类等任务。

3.3.1 特点
  • 全连接层: 层与层之间的每个神经元都与前一层的所有神经元相连。

  • 权重数量: 由于全连接的特点,权重数量较大,容易导致计算量大、模型复杂度高。

  • 学习能力: 能够学习输入数据的全局特征,但对于高维数据却不擅长捕捉局部特征(如图像就需要CNN)。

3.3.2 计算步骤
  1. 数据传递: 输入数据经过每一层的计算,逐层传递到输出层。

  2. 激活函数: 每一层的输出通过激活函数处理。

  3. 损失计算: 在输出层计算预测值与真实值之间的差距,即损失函数值。

  4. 反向传播(Back Propagation): 通过反向传播算法计算损失函数对每个权重的梯度,并更新权重以最小化损失。

3.3.3 基本组件认知
线性层组件

nn.Linear,用于实现全连接层。主要用于将输入数据通过线性变换映射到输出空间。

torch.nn.Linear(input_features, out_features, bias=True)

input_features:输入数据的维度,若输入是一个长度为100的向量,则是100。

out_features:输入数据的维度,输出长度为50,则为50。

bias:是否使用偏置项,默认为True。

构建3层全连接神经网络:

import torch
from torch import nn
class MyNet(nn.Module):
    def __init__(self,input_size,out_size):
        super(MyNet,self).__init__()
        self.fc1=nn.Linear(input_size,32)
        self.fc2=nn.Linear(32,16)
        self.fc3=nn.Linear(16,out_size)
    def forward(self,x):
        x=self.fc1(x)
        x=self.fc2(x)
        x=self.fc3(x)
input_size=64
out_size=1
model=MyNet(input_size,out_size)
print(model)
        
#%%

结果:
MyNet(
  (fc1): Linear(in_features=64, out_features=32, bias=True)
  (fc2): Linear(in_features=32, out_features=16, bias=True)
  (fc3): Linear(in_features=16, out_features=1, bias=True)
)

模型中线性层可以不按顺序叠加,如果按顺序可以使用nn.Sequential构建模型。

nn.Sequential是一个顺序容器,会制动将输入数据依次传递给其中的每一层,并执行前向传播,二不用显式定义:

import torch
from torch import nn
model=nn.Sequential(
    nn.Linear(128,64),
    nn.Linear(64,32),
    nn.Linear(32,1)
)
print(model)

结果:
Sequential(
  (0): Linear(in_features=128, out_features=64, bias=True)
  (1): Linear(in_features=64, out_features=32, bias=True)
  (2): Linear(in_features=32, out_features=1, bias=True)
)

激活函数组件

隐藏层引入非线性,让网络能够学习和表示复杂的函数关系,使网络具备非线性能力。在神经网络上运行的函数将神经元的输入映射到输出。

1、sigmoid函数

f(x)=\tfrac{1}{1+_{e}^{-x}}

单增和反函数单增,可以将变量映射到[0,1]。

import torch.nn.functional as F 

sigmoid=F.sigmoid

2、tanh函数 

双曲正切。

f(x)=\frac{​{e}^{x}-{e}^{-x}}{e^{x}+e^{-x}}

[-1,1]

import torch.nn.functional as F 

tanh=f.tanh

3、ReLU函数 

用于隐层神经元输出。

f(x)=max(0,X)

ReLU(x)=

                x, if x>0

                0,if x<=0

import torch.nn as nn

relu=nn.ReLU()

 4、LeakyReLU函数

LeakyReLU(x) = max(0, x) + α * min(0, x)

ReLU激活函数的变种,可以解决ReLU函数在负输入值时导致的神经元死亡问题。

import torch.nn as nn

leaky_relu = nn.LeakyReLU(negative_slope=0.01)

5、 softmax函数

归一化指数函数,将一个实数向量转换为概率分布,使得每个元素的值介于0到1之间,所有元素的总和为1。适合神经网络输出层的激活函数,用于预测类别的概率。

\sigma (t)=\frac{1}{1+{e_{}}^{-t}}

import torch.nn.functional as F 

softmax = F.softmax

损失函数组件 

量化模型预测值与真实值的差异。一般,损失函数的值越小,表示模型预测越接近真实值

可以通过优化算法(梯度下降)最小化损失函数,从而调正模型的参数。

回归任务的损失函数

1、均方误差损失(MSE Loss)

import torch.nn as nn

loss_MSE=nn.MSELoss()

2、L1损失(L1 Loss)

MAE,平均绝对误差

import torch.nn as nn

loss_L1=nn.L1Loss(()

分类任务的损失函数 

1、交叉熵损失(Cross-Entropy Loss)

用于多分类任务

import torch.nn as nn

cross_entropy_loss = nn.CrossEntropyLoss()

参数:reduction:mean-平均值;sum-总和

2、二元交叉熵损失

用于二分类任务

import torch.nn as nn

bce_loss = nn.BCELoss()
bce_with_logits_loss = nn.BCEWithLogitsLoss()

 比较:BCEWithLogitsLoss()更稳定,结合了Sigmoid激活函数和BCE损失。

但是在使用BCELoss,需要确保预测值经过sigmoid函数处理

如果预测值是logits,也就是没有用sigmoid处理的预测值,可以使用BCEWithLogitsLoss(),内部会自动应用sigmoid函数。

优化器

更新模型参数最小化损失函数。

pytorch在torch.optim提供优化器

1、常用的优化器

随机梯度下降,SGD;

每次迭代随机选择一个或者一小批样本计算梯度,按照负梯度方向更新参数。

学习率固定,可能会收敛较慢。

自适应梯度,Adagrad;

为每个参数自适应地调整学习率,对频繁更新的参数使用较小的学习率,反之则用较大的学习率。

适合稀疏数据,自动调整学习率,随着历史梯度平方的累积单调递增,学习率会趋近于零,导致训练提前终止。

均方根传播,RMSprop;

改进Adagrad的激进学习率衰减问题,引入指数移动平均(EMA)来累积梯度。缓解Adagrad的学习率消失问题,适合非平稳目标(如RNN)。

自适应矩估计,Adam;

结合动量(Momentum)和RMSprop,同时考虑梯度的一阶矩(均值)和二阶矩(方差)。

适应不同参数、收敛快、鲁棒性强,适合大多数深度学习任务。

优化器优势缺点适用场景
SGD简单,理论清晰收敛慢,易陷鞍点需要精细调参时
Adagrad自适应学习率学习率过早衰减稀疏数据(如NLP)
RMSprop解决Adagrad缺陷需手动调参非平稳问题(如RNN)
Adam快,鲁棒性强可能过拟合大多数深度学习任务
2、核心方法

zero_grad():清空模型参数的梯度,将梯度置零。必须在loss.backward()之前调用zero_grad(),避免梯度累积。

step():参数更新,优化器核心方法,用于根据得到的梯度更新的模型参数。优化器会根据梯度和学习率等参数,调整模型的权重和偏置。

import torch
'''包含层:linear层、损失函数:MSELoss'''
import torch.nn as nn
'''优化算法,SGD,用于更新模型参数'''
import torch.optim as optim
def test():
    
    '''创建全连接层,输入维度32,输出特征60
    weight:32*64,bias:64
    '''
    model=nn.Linear(32,64)
    
    '''定义损失函数'''
    criterion=nn.MSELoss()
    
    '''定义优化器,optim.SGD:随机梯度下降优化器,
    model.parameter:生成器,获取模型所有可以训练的参数:weight、bias'''
    optimizer=optim.SGD(model.parameters(),lr=0.01)
    
    '''生成形状为128*20的随机张量,模拟128个样本,每个样本20维特征'''
    input_features=torch.randn(128,32)
    
    '''将输入通过线性曾计算输出,形状为128*64'''
    output_features=model(input_features)
    
    '''计算损失,随机生成目标值,形状与output一致
    criterion(output_features,target):计算预测输出与目标值的均方误差'''
    loss=criterion(output_features,torch.randn(128,64))
    
    '''梯度清零,情况模型参数的梯度缓存,必须在loss.backward()之前'''
    optimizer.zero_grad()
    
    '''反向传播'''
    loss.backward()
    
    '''根据梯度更新模型参数'''
    optimizer.step()
    
    '''打印损失值'''
    print(f'损失值:{loss.item()}')
if __name__=="__main__":
    test()

结果:损失值:1.3465300798416138

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐