本文讨论了深度学习中常用的损失函数,包括交叉熵损失函数、余弦相似度损失函数和双曲余弦对数损失函数,并对它们在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=1npilogpiH(X) = -sum_{i=1}^n p_i log p_iH(X)=−∑i=1npilogpi。用pip_ipi表示第 i 个输出的标签值,即真实值,用qiq_iqi表示第 i 个输出值,即预测值。将它们都视为概率值,pip_ipi与qiq_iqi之间的对数差在pip_ipi上的期望值称为相对熵:
DKL(p∣∣q)=Ep(logpi−logqi)=∑i=1npi(logpi−logqi)=∑i=1npilogpiqi(式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(logpi−logqi)=i=1∑npi(logpi−logqi)=i=1∑npilogqipi(式10-1)
将上述与熵的定义式进行对比,可见是用logqi−logpilog q_i - log p_ilogqi−logpi代替了logpilog p_ilogpi,用来度量两个分布之间的差异。计算 a 和 d 两项输出的相对熵:
Da=0×log00.07158904+1×log10.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×log00.11774177+1×log10.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×log00 imes log 00×log0计为 0。
可见,与直接观察的结论相同。相对熵越大的输出与标签值差距越大。如果pip_ipi与qiq_iqi相同,那么DKL(p∣∣q)=0D_{KL}(p||q) = 0DKL(p∣∣q)=0。
值得注意的是,相对熵不具有对称性。相对熵又称为 KL 散度。
将相对熵的定义式 10-1 进一步展开:
DKL(p∣∣q)=∑i=1npi(logpi−logqi) D_{KL}(p||q) = sum_{i=1}^{n} p_i(log p_i - log q_i)DKL(p∣∣q)=i=1∑npi(logpi−logqi)
=∑i=1npilogpi+[−∑i=1npilogqi](式10-2) = sum_{i=1}^{n} p_ilog p_i + left[ -sum_{i=1}^{n} p_ilog q_i ight] ag{式10-2}=i=1∑npilogpi+[−i=1∑npilogqi](式10-2)
=−H(pi)+[−∑i=1npilogqi] = -H(p_i) + left[ -sum_{i=1}^{n} p_ilog q_i ight]=−H(pi)+[−i=1∑npilogqi]
前一项正好是标签分布熵的负值,保持不变,因此一般用后一项作为两个分布之间差异的度量,称为交叉熵:
H(p,q)=−∑i=1npilogqi(式10-3) H(p,q) = -sum_{i=1}^{n} p_ilog q_i ag{式10-3}H(p,q)=−i=1∑npilogqi(式10-3)
如果只有正负两个分类(标签记为 1 和 0),记第iii个输出的标签值为yiy_iyi,记它被预测为正类的概率为pip_ipi,那么上式为:
H(y,p)=−1n∑i=1n[yilogpi+(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=1∑n[yilogpi+(1−yi)log(1−pi)]
交叉熵损失函数在梯度下降法中可以改善 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}X是nnn维实数向量空间Rnmathbb{R}^nRn,点xi,xj∈Xmathbf{x}_i , mathbf{x}_j in mathcal{X}xi,xj∈X,xi=(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∥∥xj∥xi⋅xj=∑k=1n(xi(k))2∑k=1n(xj(k))2∑k=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)的计算方法为:
logcosh(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=1∑nlog(2eqi−pi+e−(qi−pi))=i=1∑nlog(eqi−pi⋅(1+e−2(qi−pi))/2)=i=1∑n[log(eq
网站建设解决方案顺德网站建设
郑老师的NHANES Online平台,可零代码一键提取和分析数据!目前在持续快速更新指标中!(ps:感兴趣的指标可以和我们说一下
网站建设策划市网站建设
在锁屏或长时间不操作时,导致VS Code SSH连接断开的主要原因是网络中的防火墙或路由器会关闭长时间空闲的连接。你可以通过配置“心跳包”和让后台进程独立运行这两种方法来解决。下面我将
律师网站建设网站建设seo
创新ownCloud集群部署深度解析:三大技术方案对比与实战指南【免费下载链接】core:cloud: ownCloud web server core (Files, DAV, etc
网站建设中寿光网站建设
RuoYi-Vue3企业级后台管理系统终极使用指南:快速上手与完整部署教程【免费下载链接】RuoYi-Vue3🎉 (RuoYi)官方仓库 基于SpringBoot
门户网站建设杭州营销型网站建设
第一章:智谱清言Open-AutoGLM概述智谱清言Open-AutoGLM是基于AutoGLM技术构建的开放语言模型平台,旨在为开发者与研究者提供高效、灵活的大模型应用能
网站建设报价网站建设协议
Sonic数字人表情自然度评测:眨眼、微笑等细节表现优秀在虚拟内容创作需求爆发的今天,一个关键问题摆在开发者和创作者面前:如何以最低成本生成既流畅又富有情感表
网站建设一条龙海淀网站建设
传统的农业生产方式中,“随意浇水、用经验施肥”的习惯正逐步被智慧技术取代。烟台中盾信息科技有限公司深耕智慧农业领域,依托物联网技术开发的智能水肥一体化系统,将
建设网站娄底网站建设
搞懂Keil5断点机制:为什么你的调试总在关键时刻“失效”?你有没有遇到过这种情况:在Keil5里给一段启动代码打了个断点,结果程序死活不停
怎么建设网站十堰网站建设
Kotaemon配置热更新机制:无需重启服务的变更生效在企业级智能对话系统的实际部署中,一个看似微小的配置调整,往往可能引发一场“服务雪崩”——修改参数、提交
成都网站建设孝感网站建设
迈向 6G 移动通信的深度学习与联邦学习1. 机器学习与深度学习概述随着机器学习(ML)和人工智能(AI)的飞速发展,将 ML 应用于无线通信系统和网络的优化,成为了超越第五代(5G)和第六代(6G)