辽宁网站建设上海网站建设的

安徽绿恒农业科技有限公司 2026/09/09 17:52:54

本文讨论了深度学习中常用的损失函数,包括交叉熵损失函数、余弦相似度损失函数和双曲余弦对数损失函数,并对它们在PyTorch中的应用细节进行了介绍,通过MNIST手写体数字识别实验展示它们的应用。损失函数有很多,读者可以在了解基本知识的基础上,要求AI大模型给出相关损失函数的原理细节,并给出相应的应用代码供使用或参考。

本专栏之三中简要讨论了损失函数的概念及最容易理解的损失函数MSE,MSE是基于欧氏距离的损失函数。多层神经网络中常用的损失函数还有KL(Kullback-Leibler Divergence)散度损失函数、交叉熵(Crossentropy)损失函数、余弦相似度损失函数、双曲余弦对数(logarithm of the hyperbolic cosine)损失函数等。

了解不同损失函数对优化的影响,以及它们应用的特点,是设计深度学习模型、指导AI大模型调整模型的重要知识。

本文还进一步讨论了凸函数理论,供想深入研究的读者参考。

1.相对熵损失函数和交叉熵损失函数

交叉熵可以用来衡量两个分布之间的差距,还是以示例入手讨论。

在本专栏之五的讨论误差反向传播学习算法时,使用了一个用神经网络模拟异或运算的例子,其中使用的示例的最后预测输出与实际标签值的对比如下:

a)[ 0.07158904 0.92822515 ] -> [ 0. 1.]

b)[ 0.9138734 0.08633152 ] -> [ 1. 0.]

c)[ 0.91375259 0.08644981 ] -> [ 1. 0.]

d)[ 0.11774177 0.88200493 ] -> [ 0. 1.]

对于a和d两项输出,标签值都是[ 0. 1.],直观来看a的预测应该更准一些。如何形式化地度量它们与标签值的差距呢?

将预测输出值看作概率,如 a 项中,预测为 1 的概率为 0.07158904,预测为 0 的概率为 0.92822515。

信息熵(有关信息熵及其在机器学习领域中的应用,可参考文献[1]中的4.1节)的定义为:H(X)=−∑i=1npilog⁡piH(X) = -sum_{i=1}^n p_i log p_iH(X)=i=1npilogpi。用pip_ipi表示第 i 个输出的标签值,即真实值,用qiq_iqi表示第 i 个输出值,即预测值。将它们都视为概率值,pip_ipiqiq_iqi之间的对数差在pip_ipi上的期望值称为相对熵:
DKL(p∣∣q)=Ep(log⁡pi−log⁡qi)=∑i=1npi(log⁡pi−log⁡qi)=∑i=1npilog⁡piqi(式10-1) D_{KL}(p||q) = E_p(log p_i - log q_i) = sum_{i=1}^n p_i (log p_i - log q_i)=sum_{i=1}^n p_i log frac{p_i}{q_i} ag{式10-1}DKL(p∣∣q)=Ep(logpilogqi)=i=1npi(logpilogqi)=i=1npilogqipi(10-1)
将上述与熵的定义式进行对比,可见是用log⁡qi−log⁡pilog q_i - log p_ilogqilogpi代替了log⁡pilog p_ilogpi,用来度量两个分布之间的差异。计算 a 和 d 两项输出的相对熵:

Da=0×log⁡00.07158904+1×log⁡10.92822515=0.07447962 D_a = 0 imes log frac{0}{0.07158904} + 1 imes log frac{1}{0.92822515} = 0.07447962Da=0×log0.071589040+1×log0.928225151=0.07447962

Dd=0×log⁡00.11774177+1×log⁡10.88200493=0.12555622 D_d = 0 imes log frac{0}{0.11774177} + 1 imes log frac{1}{0.88200493} = 0.12555622Dd=0×log0.117741770+1×log0.882004931=0.12555622

式中,0×log⁡00 imes log 00×log0计为 0。

可见,与直接观察的结论相同。相对熵越大的输出与标签值差距越大。如果pip_ipiqiq_iqi相同,那么DKL(p∣∣q)=0D_{KL}(p||q) = 0DKL(p∣∣q)=0

值得注意的是,相对熵不具有对称性。相对熵又称为 KL 散度。

将相对熵的定义式 10-1 进一步展开:

DKL(p∣∣q)=∑i=1npi(log⁡pi−log⁡qi) D_{KL}(p||q) = sum_{i=1}^{n} p_i(log p_i - log q_i)DKL(p∣∣q)=i=1npi(logpilogqi)

=∑i=1npilog⁡pi+[−∑i=1npilog⁡qi](式10-2) = sum_{i=1}^{n} p_ilog p_i + left[ -sum_{i=1}^{n} p_ilog q_i ight] ag{式10-2}=i=1npilogpi+[i=1npilogqi](10-2)

=−H(pi)+[−∑i=1npilog⁡qi] = -H(p_i) + left[ -sum_{i=1}^{n} p_ilog q_i ight]=H(pi)+[i=1npilogqi]

前一项正好是标签分布熵的负值,保持不变,因此一般用后一项作为两个分布之间差异的度量,称为交叉熵:

H(p,q)=−∑i=1npilog⁡qi(式10-3) H(p,q) = -sum_{i=1}^{n} p_ilog q_i ag{式10-3}H(p,q)=i=1npilogqi(10-3)

如果只有正负两个分类(标签记为 1 和 0),记第iii个输出的标签值为yiy_iyi,记它被预测为正类的概率为pip_ipi,那么上式为:

H(y,p)=−1n∑i=1n[yilog⁡pi+(1−yi)log⁡(1−pi)] H(y,p) = -frac{1}{n}sum_{i=1}^{n} [y_ilog p_i + (1-y_i)log(1-p_i)]H(y,p)=n1i=1n[yilogpi+(1yi)log(1pi)]

交叉熵损失函数在梯度下降法中可以改善 MSE 学习速率降低的问题,得到了广泛的应用。

PyTorch中实现的交叉熵损失函数有:多分类交叉熵损失函数torch.nn.CrossEntropyLoss()、 二元交叉熵损失函数torch.nn.BCELoss()和带Sigmoid的二元交叉熵损失函数torch.nn.BCEWithLogitsLoss()等,实现KL散度损失函数的有:torch.nn.KLDivLoss()。使用CrossEntropyLoss()时,不需要提前将标签值转换成独热编码,这是使用它的一个便利特性。

仍然采用MNIST数据集进行手写体数字识别实验示例如代码10-1.1 所示,采用SGD优化方法,三层分别采用relu、relu和softmax激活函数,训练 10 轮,不同的损失函数会有不同的识别率。要注意的是,本示例仅示意各损失函数的差异,并没有严格地定义实验条件,因此结果并不具备广泛性。

代码10-1.1 损失函数应用示例

### 1.导入和设置环境importtorchimporttorch.nnasnnimporttorch.optimasoptimfromtorch.utils.dataimportDataLoader,TensorDatasetimportdatetimefromtorchvisionimportdatasets,transforms# 设置随机种子torch.manual_seed(0)### 2.训练样本和验证样本数据预处理# 数据预处理方式transform=transforms.Compose([transforms.ToTensor(),# 转换为 torch.Tensor])# 加载MNIST数据集train_dataset=datasets.MNIST('./data',train=True,download=True,transform=transform)val_dataset=datasets.MNIST('./data',train=False,transform=transform)# 样本拉平、归一化后X_train=train_dataset.data.float().view(-1,784)/255.0y_train=train_dataset.targets X_val=val_dataset.data.float().view(-1,784)/255.0y_val=val_dataset.targets# 转换为独热编码y_train=torch.nn.functional.one_hot(y_train,num_classes=10).float()y_val=torch.nn.functional.one_hot(y_val,num_classes=10).float()# 创建数据加载器batch_size=200train_loader=DataLoader(TensorDataset(X_train,y_train),batch_size=batch_size,shuffle=True)val_loader=DataLoader(TensorDataset(X_val,y_val),batch_size=batch_size)### 3.定义神经网络模型# relu-relu-softmaxclassMNISTModel(nn.Module):def__init__(self):super(MNISTModel,self).__init__()self.fc1=nn.Linear(784,784)self.fc2=nn.Linear(784,784)self.fc3=nn.Linear(784,10)self.relu=nn.ReLU()self.softmax=nn.Softmax()defforward(self,x):x=self.relu(self.fc1(x))x=self.relu(self.fc2(x))x=self.softmax(self.fc3(x))returnx### 4.采用不同的损失函数进行对比试验criterion=nn.CrossEntropyLoss()# 定义损失函数model=MNISTModel()# 实例化模型类得到模型对象optimizer=optim.SGD(model.parameters(),lr=0.15)# 定义优化器# 训练模型,开始计时start_time=datetime.datetime.now()epochs=10forepochinrange(epochs):# 每轮中的训练model.train()train_loss=0.0forbatch_X,batch_yintrain_loader:optimizer.zero_grad()outputs=model(batch_X)loss=criterion(outputs,batch_y)loss.backward()optimizer.step()train_loss+=loss.item()# 看一下该轮训练后的效果model.eval()correct=0total=0withtorch.no_grad():forbatch_X,batch_yintrain_loader:outputs=model(batch_X)_,predicted=torch.max(outputs.data,1)# 模型预测值的独热编码_,labels=torch.max(batch_y.data,1)# 真实标签值的独热编码total+=labels.size(0)correct+=(predicted==labels).sum().item()# 准确率print(f'Epoch{epoch+1}/{epochs}, 对训练样本进行预测的准确率(Train Acc):{100*correct/total:.2f}%')# 训练结束,终止计时end_time=datetime.datetime.now()print(f"训练用时:{end_time-start_time}")

输出:

Epoch 1/10, 对训练样本进行预测的准确率(Train Acc): 64.97% Epoch 2/10, 对训练样本进行预测的准确率(Train Acc): 82.14% Epoch 3/10, 对训练样本进行预测的准确率(Train Acc): 83.63% Epoch 4/10, 对训练样本进行预测的准确率(Train Acc): 84.34% Epoch 5/10, 对训练样本进行预测的准确率(Train Acc): 84.81% Epoch 6/10, 对训练样本进行预测的准确率(Train Acc): 91.00% Epoch 7/10, 对训练样本进行预测的准确率(Train Acc): 91.88% Epoch 8/10, 对训练样本进行预测的准确率(Train Acc): 92.22% Epoch 9/10, 对训练样本进行预测的准确率(Train Acc): 93.04% Epoch 10/10, 对训练样本进行预测的准确率(Train Acc): 93.51% 训练用时: 0:01:25.518433

通过设置MSE损失函数、多分类交叉熵损失函数、二元交叉熵损失函数、带Sigmoid的二元交叉熵损失函数BCEWithLogitsLoss损失函数、KL散度损失函数进行试验,对训练样本的预测准确率为:89.14%、93.51%、93.23%、68.93%、56.66%,详见本文所附代码文件。

交叉熵系列损失函数中,还可以通过设置weight和pos_weight参数来处理样本类别不平衡的问题。样本类别不平衡问题详见本专栏之九的文章。

2.余弦相似度损失函数

余弦相似度刻画的是两个向量之间的夹角,它适合于与向量方向相关的距离度量。

设特征空间Xmathcal{X}Xnnn维实数向量空间Rnmathbb{R}^nRn,点xi,xj∈Xmathbf{x}_i , mathbf{x}_j in mathcal{X}xi,xjXxi=(xi,1,xi,2,…,xi,m)mathbf{x}_i = (x_{i,1}, x_{i,2}, dots, x_{i,m})xi=(xi,1,xi,2,,xi,m)xj=(xj,1,xj,2,…,xj,m)mathbf{x}_j = (x_{j,1}, x_{j,2}, dots, x_{j,m})xj=(xj,1,xj,2,,xj,m)

xi,xjmathbf{x}_i, mathbf{x}_jxi,xj的余弦相似度为:
cos⁡θ=xi⋅xj∥xi∥∥xj∥=∑k=1nxi(k)xj(k)∑k=1n(xi(k))2∑k=1n(xj(k))2(式10-4) cos heta = frac{mathbf{x}_i cdot mathbf{x}_j}{|mathbf{x}_i||mathbf{x}_j|} = frac{sum_{k=1}^n x_i^{(k)} x_j^{(k)}}{sqrt{sum_{k=1}^n (x_i^{(k)})^2} sqrt{sum_{k=1}^n (x_j^{(k)})^2}} quad ag{式10-4}cosθ=xi∥∥xjxixj=k=1n(xi(k))2k=1n(xj(k))2k=1nxi(k)xj(k)(10-4)
将标签和预测看作值向量,可用式10-4计算得到余弦相似度作为损失函数(Cosine Similarity Loss)。

余弦相似度损失函数主要用于需要衡量向量方向一致性的任务,特别适用于处理高维特征且关注相对关系的场景,主要有图像分类与人脸识别、文本检索与语义匹配‌、推荐系统‌等。

使用余弦相似度损失函数的示例如代码10-1.2所示。

代码10-1.2 余弦相似度损失函数应用示例

### 使用余弦相似度损失函数需要先自定义一个适配器classCosineLossAdapter(nn.Module):def__init__(self,margin=0.5):super(CosineLossAdapter,self).__init__()self.cosine_loss=nn.CosineEmbeddingLoss(margin=margin)defforward(self,predictions,targets):# CosineEmbeddingLoss需要两个输入张量和一个目标张量# 我们将预测视为第一个输入,目标视为第二个输入# 目标标签设为1(表示我们希望它们相似)target_labels=torch.ones(predictions.size(0)).to(predictions.device)# 计算损失loss=self.cosine_loss(predictions,targets,target_labels)returnloss criterion=CosineLossAdapter(margin=0.5)# 使用适配器model=MNISTModel()# 实例化模型类得到模型对象optimizer=optim.SGD(model.parameters(),lr=0.15)# 定义优化器# 训练模型,开始计时start_time=datetime.datetime.now()epochs=10forepochinrange(epochs):# 每轮中的训练model.train()train_loss=0.0forbatch_X,batch_yintrain_loader:optimizer.zero_grad()outputs=model(batch_X)loss=criterion(outputs,batch_y)# 现在只需要两个参数loss.backward()optimizer.step()train_loss+=loss.item()# 看一下该轮训练后的效果model.eval()correct=0total=0withtorch.no_grad():forbatch_X,batch_yintrain_loader:outputs=model(batch_X)_,predicted=torch.max(outputs.data,1)# 模型预测值的独热编码_,labels=torch.max(batch_y.data,1)# 真实标签值的独热编码total+=labels.size(0)correct+=(predicted==labels).sum().item()# 准确率print(f'Epoch{epoch+1}/{epochs}, 对训练样本进行预测的准确率(Train Acc):{100*correct/total:.2f}%')# 训练结束,终止计时end_time=datetime.datetime.now()print(f"训练用时:{end_time-start_time}")

输出:

Epoch 1/10, 对训练样本进行预测的准确率(Train Acc): 89.40% Epoch 2/10, 对训练样本进行预测的准确率(Train Acc): 91.37% Epoch 3/10, 对训练样本进行预测的准确率(Train Acc): 92.52% Epoch 4/10, 对训练样本进行预测的准确率(Train Acc): 93.10% Epoch 5/10, 对训练样本进行预测的准确率(Train Acc): 93.67% Epoch 6/10, 对训练样本进行预测的准确率(Train Acc): 94.39% Epoch 7/10, 对训练样本进行预测的准确率(Train Acc): 94.86% Epoch 8/10, 对训练样本进行预测的准确率(Train Acc): 95.37% Epoch 9/10, 对训练样本进行预测的准确率(Train Acc): 95.69% Epoch 10/10, 对训练样本进行预测的准确率(Train Acc): 96.10% 训练用时: 0:01:13.835299

3. 双曲余弦对数损失函数

双曲余弦对数(Log-Cosh Loss)的计算方法为:
log⁡cosh⁡(p,q)=∑i=1nlog⁡(eqi−pi+e−(qi−pi)2)=∑i=1nlog⁡(eqi−pi⋅(1+e−2(qi−pi))/2)=∑i=1n[log⁡(eqi−pi)+log⁡(1+e−2(qi−pi))−log⁡(2)]=∑i=1n[(qi−pi)+log⁡(1+e−2(qi−pi))−log⁡(2)]=∑i=1n[(qi−pi)+softplus(−2(qi−pi))−log⁡(2)](式10-5) egin{align*} log cosh(p, q) &= sum_{i=1}^n logleft(frac{e^{q_i - p_i} + e^{-(q_i - p_i)}}{2} ight) \ &=sum_{i=1}^n log(e^{q_i - p_i} cdot (1 + e^{-2(q_i - p_i)})/2) \ &=sum_{i=1}^n [ log(e^{q_i - p_i}) + log(1 + e^{-2(q_i - p_i)}) - log(2)] \ &=sum_{i=1}^n [ (q_i - p_i) + log(1 + e^{-2(q_i - p_i)}) - log(2) ]\ &=sum_{i=1}^n [ (q_i - p_i) + ext{softplus}(-2(q_i - p_i)) - log(2)] end{align*} ag{式10-5}logcosh(p,q)=i=1nlog(2eqipi+e(qipi))=i=1nlog(eqipi(1+e2(qipi))/2)=i=1n[log(eq

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

河南网站建设公司网站建设排名

第一章:VSCode远程调试性能优化的必要性在现代软件开发中,远程开发与调试已成为常态,尤其是在处理分布式系统、云原生应用或跨平台项目时。VSCode凭借其轻

2026/06/30 11:23:55

莆田网站建设镇江网站建设

Rust终极安全操作系统:Redox OS完整实践指南【免费下载链接】redoxMirror of https://gitlab.redox-os.org/redox-os/redox项

2026/06/30 09:47:17

诸城网站建设黄冈网站建设

PyTorch-CUDA-v2.9镜像加速铁路故障检测模型在高速铁路日均运行里程突破数万公里的今天,传统依赖人工巡检的运维模式正面临前所未有的挑战。轨道裂纹、扣件松动、异物侵入等问题若未

2026/06/30 10:45:51

淮安网站建设宝山网站建设

红外避障传感器在Proteus中的仿真实战:从原理到智能小车闭环控制你有没有过这样的经历?焊好电路、接上电源,结果单片机一通电就“冒烟”;或者反

2026/06/30 12:36:02

台州网站建设都江堰网站建设

在锁屏或长时间不操作时,导致VS Code SSH连接断开的主要原因是网络中的防火墙或路由器会关闭长时间空闲的连接。你可以通过配置“心跳包”和让后台进程独立运行这两种方法来解决。下面我将

2026/06/30 13:24:35

岳阳网站建设马鞍山网站建设

PyTorch Hub模型加载:Miniconda环境中的使用技巧在人工智能项目开发中,一个常见的痛点是:“代码跑通了,但换台机器就报错。” 更

2026/06/30 10:57:52

贵阳网站建设青岛网站建设公司

Windows网络与浏览器实用指南1. Windows邮件客户端在Vista系统上寻找一个能流畅运行的第三方电子邮件客户端有点困难。在产品测试中,Windows Mail表现尚可。虽然它还远不是一个能

2026/06/30 11:58:58

江门网站建设宁波网站建设公司

PyTorch-CUDA-v2.8镜像安装全攻略:GPU加速深度学习训练一步到位在深度学习项目开发中,最令人沮丧的场景之一莫过于:代码写完后,却

2026/06/30 10:00:17

青岛网站建设东莞手机网站建设

2.1 Cursor核心功能全解析:文档集成与行为定制化在第一章中,我们初步了解了AI编程工具的基本概念,并通过实战项目体验了AI如何提升开发效率。从本章开始,我们将深入学习Cursor这款专为AI编

2026/06/30 10:24:50