您的位置:首页 > 汽车 > 新车 > 最好的免费网站空间_无加盟费先铺货的项目_网站域名备案查询_软文广告经典案例

最好的免费网站空间_无加盟费先铺货的项目_网站域名备案查询_软文广告经典案例

2025/1/8 2:36:22 来源:https://blog.csdn.net/l15202833159/article/details/144090173  浏览:    关键词:最好的免费网站空间_无加盟费先铺货的项目_网站域名备案查询_软文广告经典案例
最好的免费网站空间_无加盟费先铺货的项目_网站域名备案查询_软文广告经典案例

目录

一、损失函数

1、线性回归损失函数

1.MAE损失

2.MSE损失

3.SmoothL1Loss

2、多分类损失函数--CrossEntropyLoss

3、二分类损失函数--BCELoss

4、总结

二、BP算法

1、前向传播

1.输入层(Input Layer)到隐藏层(Hidden Layer)

2.隐藏层(Hidden Layer)到输出层(Output Layer)

2、反向传播

1.原理

2.链式法则 

3.案例

神经元计算

损失计算

参数更新

反向传播写法01

反向传播写法02(更常用)


一、损失函数

1、线性回归损失函数

1.MAE损失

MAE(Mean Absolute Error,平均绝对误差)通常也被称为 L1-Loss,通过对预测值和真实值之间的绝对差取平均值来衡量他们之间的差异。

公式

\text{MAE} = \frac{1}{n} \sum_{i=1}^{n} \left| y_i - \hat{y}_i \right|

特点

  1. 鲁棒性:与均方误差(MSE)相比,MAE对异常值(outliers)更为鲁棒,因为它不会像MSE那样对较大误差平方敏感。

  2. 物理意义直观:MAE以与原始数据相同的单位度量误差,使其易于解释。

应用场景

MAE通常用于需要对误差进行线性度量的情况,尤其是当数据中可能存在异常值时,MAE可以避免对异常值的过度惩罚。

import torch
import torch.nn as nndef test01():"""MAE 平均绝对误差 通常也被称为 L1-Loss预测值和真实值之间的绝对差取平均值"""l1_loss_fn = nn.L1Loss()y_pred = torch.tensor([1,2,3],dtype=torch.float32)y_true = torch.tensor([1.5,2.5,3.5],dtype=torch.float32)loss = l1_loss_fn(y_pred,y_true)print(loss) # tensor(0.5000)
2.MSE损失

MSE(Mean Squared Error,均方误差),平均评分误差通过对预测值和真实值之间的误差平方取平均值,来衡量预测值与真实值之间的差异。

公式

\text{MSE} = \frac{1}{n} \sum_{i=1}^{n} \left( y_i - \hat{y}_i \right)^2

特点

  1. 平方惩罚:因为误差平方,MSE 对较大误差施加更大惩罚,所以 MSE 对异常值更为敏感。

  2. 凸性:MSE 是一个凸函数,这意味着它具有一个唯一的全局最小值,有助于优化问题的求解。

应用场景

MSE被广泛应用在神经网络中。

def test02():"""MSE 平均平方误差 通常也被称为 L2-Loss测值和真实值之间的误差平方取平均值"""l2_loss_fn = nn.MSELoss()y_pred = torch.tensor([1,2,3],dtype=torch.float32)y_true = torch.tensor([1.5,2.5,3.5],dtype=torch.float32)loss = l2_loss_fn(y_pred,y_true)print(loss) # tensor(0.2500)
3.SmoothL1Loss

SmoothL1Loss可以做到在损失较小时表现为 L2 损失,而在损失较大时表现为 L1 损失。

公式

\text{SmoothL1Loss}(x) = \begin{cases} 0.5 \cdot x^2, & \text{if } |x| < 1 \\ |x| - 0.5, & \text{otherwise} \end{cases}

所有样本的平均损失:\\L=\frac{1}{n} \sum_{i=1}^{n} L_{i} 

特点

  1. 平滑过渡:当误差较小时,损失函数表现为 L2 Loss(平方惩罚);当误差较大时,损失函数逐渐向 L1 Loss过渡。这种平滑过渡既能对大误差有所控制,又不会对异常值过度敏感。

  2. 稳健性:对于异常值更加稳健,同时在小误差范围内提供了较好的优化效果。

应用场景

SmoothL1Loss常用于需要对大误差进行一定控制但又不希望完全忽略小误差的回归任务。特别适用于目标检测任务中的边界框回归,如 Faster R-CNN 等算法中。

def test03():"""SmoothL1Loss 平滑损失函数在损失较小时表现为 L2 损失,而在损失较大时表现为 L1 损失"""# 方式一loss_fn = nn.SmoothL1Loss()# 方式二loss_fn = nn.funtional.smooth_l1_lossy_pred = torch.tensor([1,2,3,6],dtype=torch.float32)y_true = torch.tensor([1.5,2.5,3.5,4.5],dtype=torch.float32)loss = loss_fn(y_pred,y_true)print(loss)

2、多分类损失函数--CrossEntropyLoss

交叉熵损失函数,使用在输出层使用softmax激活函数进行多分类时,一般都采用交叉熵损失函数。

公式

\text{CrossEntropyLoss}(y, \hat{y}) = - \sum_{i=1}^{C} y_i \log(\hat{y}_i)

其中,样本的实际标签 y 和模型预测的概率分布\hat{y}_i​, y 是one-hot编码形式,表示真实类别 ,\hat{y}_i 表示第 i 类的概率估计值(经过 softmax 后的概率分布) 。

*one-hot 编码

假设我们有一个三分类问题,三个可能的类别分别是0、1和2。如果某个样本的真实标签是1,那么它的one-hot编码就是 [0,1,0]。这意味着:

  • 第一个位置(索引0)是0,表示该样本不属于类别0。
  • 第二个位置(索引1)是1,表示该样本属于类别1。
  • 第三个位置(索引2)是0,表示该样本不属于类别2。

特点

Softmax 直白来说就是将网络输出的 logits 通过 softmax 函数,就映射成为(0,1)的值,而这些值的累和为1(满足概率的性质),那么我们将它理解成概率,选取概率最大(也就是值对应最大的)节点,作为我们的预测目标类别

def test04():"""CrossEntropyLoss 交叉熵损失函数使用在输出层使用softmax激活函数进行多分类"""# 初始化criterion = nn.CrossEntropyLoss()# 设有三个类别,模型输出是未经softmax的logitsone_hot = torch.tensor([[1.5, 2.0, 0.5], [0.5, 1.0, 1.5]]) # 两个输出loss = criterion(one_hot, labels) # (L1+L2)/2print(loss.item()) # 0.6422001123428345

3、二分类损失函数--BCELoss

二分类交叉熵损失函数,使用在输出层使用sigmoid激活函数进行二分类时。对于二分类问题,CrossEntropyLoss 的简化版本称为二元交叉熵(Binary Cross-Entropy Loss)

公式

\text{BinaryCrossEntropy}(y, \hat{y}) = - \left[ y \log(\hat{y}) + (1 - y) \log(1 - \hat{y}) \right]

 log的底数一般默认为e,y是真实类别目标,根据公式可知L是一个分段函数 :

  • y=1时,L = -log(sigmoid 激活值)
  • y=0时,L = -log(1-sigmoid 激活值)
def test05():"""BCELoss 二分类交叉熵损失函数使用在输出层使用sigmoid激活函数进行二分类时"""# y 是模型的输出,已经被sigmoid处理过,确保其值域在(0,1)y = torch.tensor([[0.7], [0.2], [0.9], [0.7]])# targets 是真实的标签,0或1t = torch.tensor([[1], [0], [1], [0]], dtype=torch.float)# 方式一bce_loss_fn = nn.BCELoss()loss = bce_loss_fn(y,t)# 方式二loss = nn.functional.binary_cross_entropy(y,t)print(loss)

4、总结

以上损失函数是一个样本的损失值,总样本的损失值是求损失均值即可。

  • 当输出层使用softmax多分类时,使用交叉熵损失函数;

  • 当输出层使用sigmoid二分类时,使用二分类交叉熵损失函数, 比如在逻辑回归中使用;

  • 当功能为线性回归时,使用smooth L1损失函数或均方差损失-L2 loss;

二、BP算法

多层神经网络的学习能力比单层网络强得多。想要训练多层网络,需要更强大的学习算法。误差反向传播算法(Back Propagation)是其中最杰出的代表,它是目前最成功的神经网络学习算法。

现实任务使用神经网络时,大多是在使用 BP 算法进行训练,值得指出的是 BP 算法不仅可用于多层前馈神经网络,还可以用于其他类型的神经网络。

通常说 BP 网络时,一般是指用 BP 算法训练的多层前馈神经网络。

误差反向传播算法(BP)的基本步骤 

  1. 前向传播:正向计算得到预测值。

  2. 计算损失:通过损失函数 L(y{\text{pred}}, y{\text{true}})  计算预测值和真实值的差距。

  3. 梯度计算:反向传播的核心是计算损失函数 L 对每个权重和偏置的梯度。

  4. 更新参数:一旦得到每层梯度,就可以使用梯度下降算法来更新每层的权重和偏置,使得损失逐渐减小。

  5. 迭代训练:将前向传播、梯度计算、参数更新的步骤重复多次,直到损失函数收敛或达到预定的停止条件。

1、前向传播

前向传播(Forward Propagation)把输入数据经过各层神经元的运算并逐层向前传输,一直到输出层为止。

 一个简单的三层神经网络(输入层、隐藏层、输出层)前向传播的基本步骤分析:

1.输入层(Input Layer)到隐藏层(Hidden Layer)

给定输入 x 和权重矩阵 W 及偏置向量 b,隐藏层的输出(激活值)计算如下:

z^{(1)} = W_1 \cdot x + b_1

将z通过激活函数激活:

a^{(1)} = \sigma(z^{(1)})

2.隐藏层(Hidden Layer)到输出层(Output Layer)

隐藏层的输出a^{(1)}经过输出层的权重矩阵 W 和偏置 b 生成最终输出:

z^{(2)} = W_2 \cdot a^{(1)} + b_2

z通过输出层的激活函数激活后就是最终预测结果:

y_{\text{pred}} = a^{(2)} = \sigma(z^{(2)})

前向传播的主要作用

  1. 计算神经网络的输出结果,用于预测或计算损失。

  2. 在反向传播中使用,通过计算损失函数相对于每个参数的梯度来优化网络。

2、反向传播

反向传播(Back Propagation,简称BP)通过计算损失函数相对于每个参数的梯度来调整权重,使模型在训练数据上的表现逐渐优化。

反向传播结合了链式求导法则和梯度下降算法,是神经网络模型训练过程中更新参数的关键步骤。

1.原理

利用链式求导法则对每一层进行求导,直到求出输入层x的导数,然后利用导数值进行梯度更新。

2.链式法则 

链式求导法则(Chain Rule)是微积分中的一个重要法则,用于求复合函数的导数。在深度学习中,链式法则是反向传播算法的基础,这样就可以通过分层的计算求得损失函数相对于每个参数的梯度,以下面函数为例:

\mathrm{f(x)=\frac{1}{1+e^{-(wx+b)}}}

\begin{aligned} \frac{\partial f(x;w,b)}{\partial w}|_{x=1,w=0,b=0}& =\frac{\partial f(x;w,b)}{\partial h_6}\frac{\partial h_6}{\partial h_5}\frac{\partial h_5}{\partial h_4}\frac{\partial h_4}{\partial h_3}\frac{\partial h_3}{\partial h_2}\frac{\partial h_2}{\partial h_1}\frac{\partial h_1}{\partial w} \\ &=1\times-0.25\times1\times1\times-1\times1\times1 \\ &=0.25 \end{aligned}

import torchdef test01():"""链式求导"""x = torch.tensor(1.0)w = torch.tensor(0.0,required_grad=True)b = torch.tensor(0.0,required_grad=True)fx = torch.sigmoid(w*x + b)fx.backward() # fx对w求导print(w.grad) # tensor(0.2500)print(b.grad) # tensor(0.2500)if __name__ == '__main__':test01()
3.案例

神经元计算

输入层到隐藏层:

\mathrm{h}_{1}=\mathrm{w}_{1}*\mathrm{i}_{1}+\mathrm{w}_{2}*\mathrm{i}_{2}+\mathrm{b}_{1}\quad =0.15 * 0.05 + 0.20 * 0.10 + 0.35 =0.3775 \\ k_{1}=sigmoid(h1)=sigmoid(0.3775)=0.5933

同理 h2=0.3925, k2=0.5969

隐藏层到输出层:

\mathrm{o}_{1}=\mathrm{w}_{5}*\mathrm{k}_{1}+\mathrm{w}_{6}*\mathrm{k}_{2}+\mathrm{b}_{2}\quad =0.40 * 0.5933 + 0.45 * 0.5969 + 0.60 =1.1059 \\ m_{1}=sigmoid(o1)=sigmoid(1.1059)=0.7514

同理 o2=1.2249, m2 =0.7729

所以,最终的预测结果分别为: 0.7514、0.7729

损失计算

预测值和真实值(target)进行比较计算损失:

MSELoss = \frac{1}{2}((\mathrm{m}_{1}\mathrm{-target}_{1})^{2}+((\mathrm{m}_{2}\mathrm{-target}_{2})^{2}) \\ = \frac{1}{2}((0.7514-0.01)^{2}+((0.7729-0.99)^{2}) =0.2984

import torch"""手动计算代码过程"""
i1 = 0.05
i2 = 0.10b1 = 0.35
b2 = 0.60def h1():w1 = 0.15w2 = 0.20l1 = i1 * w1 + i2 * w2 + b1l1 = torch.tensor(l1)return torch.sigmoid(l1) # 1/(1+torch.e**(-l1))
print(f'h1:{h1()}') # 0.5933def h2():w3 = 0.25w4 = 0.30l2 = i1 * w3 + i2 * w4 + b1l2 = torch.tensor(l2)return torch.sigmoid(l2) # 1/(1+torch.e**(-l2))
print(f'h2:{h2()}') # 0.5969def o1():w5 = 0.40w6 = 0.45l3 = h1() * w5 + h2() * w6 + b2l3 = torch.tensor(l3)m1 = torch.sigmoid(l3) # 1/(1+torch.e**(-l3))return m1
print(f'o1:{o1()}') # 0.7514def o2():w7 = 0.50w8 = 0.55l4 = h1() * w7 + h2() * w8 + b2l4 = torch.tensor(l4)m2 = torch.sigmoid(l4) # 1/(1+torch.e**(-l4))return m2
print(f'o2:{o2()}') # 0.7729# 手动反向传播
def mse():o1_target = 0.01o2_target = 0.99return 0.5*((o1() - 0.01)**2 + (o2() - 0.99)**2)loss = mse()

 梯度计算

使用链式法则计算w1,w5,w7梯度:

\begin{aligned} \frac{\partial\mathrm{L}}{\partial\mathrm{w}_{5}}& =\frac{\partial\mathrm{L}}{\partial\mathrm{m}_{1}}*\frac{\partial\mathrm{m}_{1}}{\partial\mathrm{o}_{1}}*\frac{\partial\mathrm{o}_{1}}{\partial\mathrm{w}_{5}} \\ &=(\mathrm{m}_{1}-\mathrm{target}_{1})*\mathrm{sigmoid}(\mathrm{o}_{1})*\left(1-\mathrm{sigmoid}(\mathrm{o}_{1})\right)*\mathrm{k}_{1} \\ &=(0.7514-0.01)*sigmoid(1.1059)*\left(1-sigmoid(1.1059)\right)*0.5933 \\ &=0.0822 \end{aligned}

 \begin{aligned} \frac{\partial\mathrm{L}}{\partial\mathrm{w}_7}& =\frac{\partial\mathrm{L}}{\partial\mathrm{m}_2}*\frac{\partial\mathrm{m}_2}{\partial\mathrm{o}_2}*\frac{\partial\mathrm{o}_2}{\partial\mathrm{w}_7} \\ &=(\mathrm{m}_{2}-\mathrm{target}_{2})*\mathrm{sigmoid}(\mathrm{o}_{2})*\left(1-\mathrm{sigmoid}(\mathrm{o}_{2})\right)*\mathrm{k}_{1} \\ &=(0.7729-0.99)*sigmoid(1.2249)*\left(1-sigmoid(1.2249)\right)*0.5933 \\ &=-0.0226 \end{aligned}

 

import torch"""反向传播api手动实现"""
def train():# 前向传播# x1 x2i=torch.tensor([[0.05,0.1]])model1=torch.nn.Linear(2,2)# w1 w2 w3 w4model1.weight.data=torch.tensor([[0.15,0.20],[0.25,0.30]])# b1model1.bias.data=torch.tensor([0.35,0.35])l1_l2=model1(i)h1_h2=torch.sigmoid(l1_l2)model2=torch.nn.Linear(2,2)# w5 w6 w7 w8model2.weight.data=torch.tensor([[0.40,0.45],[0.50,0.55]])# b2model2.bias.data=torch.tensor([0.60,0.60])l3_l4=model2(h1_h2)o1_o2=torch.sigmoid(l3_l4)# 误差计算o1_o2_true=torch.tensor([[0.01,0.99]])loss=torch.sum((o1_o2 - o1_o2_true) ** 2) / 2# mse=torch.nn.MSELoss()# loss=mse(o1_o2,o1_o2_true)# 反向传播loss.backward()print(model1.weight.grad)print(model2.weight.grad)train()
参数更新

现在就可以进行权重更新了:假设学习率是0.5:

w_5=0.40-0.5*0.0822=0.3589 \\ w_7=0.50+0.5*0.0226=0.5113 \\ w_1=0.15-0.5*0.0004=0.1498

整合一下,完整的反向传播写法:

反向传播代码写法01
import torch
import torch.nn as nn
import torch.optim as optimclass MyNet(nn.Module):def __init__(self):super(MyNet, self).__init__()# 定义网络结构self.linear1 = nn.Linear(2, 2)self.linear2 = nn.Linear(2, 2)self.activation = torch.sigmoid# 网络参数初始化# 隐藏层权重self.linear1.weight.data = torch.tensor([[0.15, 0.20], [0.25, 0.30]])# 输出层权重self.linear2.weight.data = torch.tensor([[0.40, 0.45], [0.50, 0.55]])# 隐藏层偏置self.linear1.bias.data = torch.tensor([0.35, 0.35])# 输出层偏置self.linear2.bias.data = torch.tensor([0.60, 0.60])def forward(self, x):x = self.linear1(x)x = self.activation(x)x = self.linear2(x)x = self.activation(x)return xdef train():net = MyNet()# 优化方法optimizer = optim.SGD(net.parameters(), lr=0.1)inputs = torch.tensor([[0.05, 0.10]])target = torch.tensor([[0.01, 0.99]])# 获得网络输出值pred = net(inputs) # module父类已实现前向传播mes = torch.nn.MSELoss()# 计算误差loss = mes(pred, target)# 梯度清零optimizer.zero_grad()# 反向传播loss.backward()# 打印(w1-w8)观察w5、w7、w1 的梯度值是否与手动计算一致print(net.linear1.weight.grad.data)print(net.linear2.weight.grad.data)#更新梯度optimizer.step()# 打印更新后的网络参数# print(net.state_dict())train()
反向传播代码写法02(更常用)
import torch
import torch.nn as nn
import torch.optim as optimclass MyNet(nn.Module):def __init__(self):super(MyNet, self).__init__()# 定义网络结构# self.linear1 = nn.Linear(2, 2)# self.linear2 = nn.Linear(2, 2)# self.activation = torch.sigmoidself.hide1 = torch.nn.Sequential(nn.Linear(2, 2),torch.nn.Sigmoid())self.out = torch.nn.Sequential(nn.Linear(2, 2),torch.nn.Sigmoid())# 网络参数初始化 线性层# # 隐藏层权重# self.linear1.weight.data = torch.tensor([[0.15, 0.20], [0.25, 0.30]])# # 输出层权重# self.linear2.weight.data = torch.tensor([[0.40, 0.45], [0.50, 0.55]])# # 隐藏层偏置# self.linear1.bias.data = torch.tensor([0.35, 0.35])# # 输出层偏置# self.linear2.bias.data = torch.tensor([0.60, 0.60])self.hide1[0].weight.data = torch.tensor([[0.15, 0.20], [0.25, 0.30]])self.out[0].weight.data = torch.tensor([[0.40, 0.45], [0.50, 0.55]])self.hide1[0].bias.data = torch.tensor([0.35, 0.35])self.out[0].bias.data = torch.tensor([0.60, 0.60])def forward(self, x):# x = self.linear1(x)# x = self.activation(x)# x = self.linear2(x)# x = self.activation(x)x = self.hide1(x)x = self.out(x)return xdef train():net = MyNet()# 优化方法optimizer = optim.SGD(net.parameters(), lr=0.1)inputs = torch.tensor([[0.05, 0.10]])target = torch.tensor([[0.01, 0.99]])# 获得网络输出值pred = net(inputs) # module父类已实现前向传播mes = torch.nn.MSELoss()# 计算误差loss = mes(pred, target)# 梯度清零optimizer.zero_grad()# 反向传播loss.backward()# 打印(w1-w8)观察w5、w7、w1 的梯度值是否与手动计算一致print(net.hide1[0].weight.grad.data) # 0:线性层 1:激活函数print(net.out[0].weight.grad.data) # 0:线性层 1:激活函数#更新梯度optimizer.step()# 打印更新后的网络参数# print(net.state_dict())train()

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com