做企业网站要用什么软件,phpstudy2016快速搭建网站,手机网站 兼容,网站做任务佣金文章最前#xff1a; 我是Octopus#xff0c;这个名字来源于我的中文名–章鱼#xff1b;我热爱编程、热爱算法、热爱开源。所有源码在我的个人github #xff1b;这博客是记录我学习的点点滴滴#xff0c;如果您对 Python、Java、AI、算法有兴趣#xff0c;可以关注我的… 文章最前 我是Octopus这个名字来源于我的中文名–章鱼我热爱编程、热爱算法、热爱开源。所有源码在我的个人github 这博客是记录我学习的点点滴滴如果您对 Python、Java、AI、算法有兴趣可以关注我的动态一起学习共同进步。 一般来说监督学习的目标函数由损失函数和正则化项组成。(Objective Loss Regularization)
Pytorch中的损失函数一般在训练模型时候指定。
注意Pytorch中内置的损失函数的参数和tensorflow不同是y_pred在前y_true在后而Tensorflow是y_true在前y_pred在后。
对于回归模型通常使用的内置损失函数是均方损失函数nn.MSELoss 。
对于二分类模型通常使用的是二元交叉熵损失函数nn.BCELoss (输入已经是sigmoid激活函数之后的结果) 或者 nn.BCEWithLogitsLoss (输入尚未经过nn.Sigmoid激活函数) 。
对于多分类模型一般推荐使用交叉熵损失函数 nn.CrossEntropyLoss。 (y_true需要是一维的是类别编码。y_pred未经过nn.Softmax激活。)
此外如果多分类的y_pred经过了nn.LogSoftmax激活可以使用nn.NLLLoss损失函数(The negative log likelihood loss)。 这种方法和直接使用nn.CrossEntropyLoss等价。
如果有需要也可以自定义损失函数自定义损失函数需要接收两个张量y_predy_true作为输入参数并输出一个标量作为损失函数值。
Pytorch中的正则化项一般通过自定义的方式和损失函数一起添加作为目标函数。
如果仅仅使用L2正则化也可以利用优化器的weight_decay参数来实现相同的效果。
一内置损失函数
内置的损失函数一般有类的实现和函数的实现两种形式。
如nn.BCE 和 F.binary_cross_entropy 都是二元交叉熵损失函数前者是类的实现形式后者是函数的实现形式。
实际上类的实现形式通常是调用函数的实现形式并用nn.Module封装后得到的。
一般我们常用的是类的实现形式。它们封装在torch.nn模块下并且类名以Loss结尾。
常用的一些内置损失函数说明如下。 nn.MSELoss均方误差损失也叫做L2损失用于回归 nn.L1Loss L1损失也叫做绝对值误差损失用于回归 nn.SmoothL1Loss (平滑L1损失当输入在-1到1之间时平滑为L2损失用于回归) nn.BCELoss (二元交叉熵用于二分类输入已经过nn.Sigmoid激活对不平衡数据集可以用weigths参数调整类别权重) nn.BCEWithLogitsLoss (二元交叉熵用于二分类输入未经过nn.Sigmoid激活) nn.CrossEntropyLoss (交叉熵用于多分类要求label为稀疏编码输入未经过nn.Softmax激活对不平衡数据集可以用weigths参数调整类别权重) nn.NLLLoss (负对数似然损失用于多分类要求label为稀疏编码输入经过nn.LogSoftmax激活) nn.KLDivLoss (KL散度损失也叫相对熵等于交叉熵减去信息熵用于标签为概率值的多分类要求输入经过nn.LogSoftmax激活) nn.CosineSimilarity(余弦相似度可用于多分类) nn.AdaptiveLogSoftmaxWithLoss (一种适合非常多类别且类别分布很不均衡的损失函数会自适应地将多个小类别合成一个cluster)
重点介绍一下 二元交叉熵、多元交叉熵、对数损失LogLoss、负对数似然损失NLLLoss、KL散度之间的区别和联系。
1二分类的交叉熵的计算公式是什么为什么是这样一种形式 B i n a r y C r o s s E n t r o p y L o s s ( Y , Y ^ ) − 1 N ∑ i 0 N − 1 ( y i l o g y i ^ ( 1 − y i ) l o g ( 1 − y i ^ ) ) BinaryCrossEntropyLoss(Y,\hat{Y}) - \frac{1}{N}\sum_{i0}^{N-1} (y_i log \hat{y_i} (1-y_i) log(1-\hat{y_i})) BinaryCrossEntropyLoss(Y,Y^)−N1i0∑N−1(yilogyi^(1−yi)log(1−yi^))
该公式由极大似然原理推导得来。由于 y i ^ \hat{y_i} yi^表示的是样本标签为1的概率 1 − y i ^ 1-\hat{y_i} 1−yi^表示的是样本标签为0的概率 那么训练集中的全部样本取得对应标签的概率即似然函数可以写成如下形式 L ( Y , Y ^ ) ∏ i 0 N − 1 y i ^ y i ( 1 − y i ^ ) ( 1 − y i ) L(Y,\hat{Y}) \prod_{i0}^{N-1} \hat{y_i}^{y_i} (1-\hat{y_i})^{(1-y_i)} L(Y,Y^)i0∏N−1yi^yi(1−yi^)(1−yi)
注意当 y i 1 y_i 1 yi1为时连乘中的项为 y i ^ \hat{y_i} yi^当 y i 0 y_i 0 yi0为时连乘中的项为 ( 1 − y i ^ ) (1-\hat{y_i}) (1−yi^)、
转换成对数似然函数得到 l n L ( Y , Y ^ ) ∑ i 0 N − 1 y i l n y i ^ ( 1 − y i ) l n ( 1 − y i ^ ) lnL(Y,\hat{Y}) \sum_{i0}^{N-1} y_i ln{\hat{y_i}} (1-y_i)ln{(1-\hat{y_i})} lnL(Y,Y^)i0∑N−1yilnyi^(1−yi)ln(1−yi^)
对数似然函数求极大值等价于对对数似然函数的负数求极小值考虑样本数量维度归一化于是得到了二元交叉熵损失函数的形式。
2多元交叉熵的计算公式是什么和二元交叉熵有什么联系? C r o s s E n t r o p y L o s s ( Y , Y ^ ) − 1 N ∑ i 0 N − 1 ∑ k 0 K − 1 I ( y i k ) l o g y i , k ^ where I ( x ) is the Indicator function I ( T r u e ) 1 and I ( F a l s e ) 0 CrossEntropyLoss(Y,\hat{Y}) - \frac{1}{N}\sum_{i0}^{N-1} \sum_{k0}^{K-1} I(y_ik) log \hat{y_{i,k}} \\ \text{where} I(x) \text{ is the Indicator function} \\ I(True) 1 \text{ and } I(False) 0 CrossEntropyLoss(Y,Y^)−N1i0∑N−1k0∑K−1I(yik)logyi,k^whereI(x) is the Indicator functionI(True)1 and I(False)0
多元交叉熵是二元交叉熵的自然拓展其中 y i y_i yi取0~K-1其中的一个类别编码序号 y i ^ \hat{y_i} yi^ 是一个长度为K的概率向量。多元交叉熵的类别数K取2时即可得到二元交叉熵对应的公式。
3sklearncatboost等库中常常看到logloss对数损失函数这个损失函数如何计算和交叉熵有什么关系 L o g L o s s ( Y , Y ^ ) − 1 N ∑ i 0 N − 1 l o g ( y i ^ [ y i ] ) LogLoss(Y,\hat{Y}) - \frac{1}{N}\sum_{i0}^{N-1} log(\hat{y_{i}}[y_i]) LogLoss(Y,Y^)−N1i0∑N−1log(yi^[yi])
公式中的方括号和Python中的索引的用法一致表示取 y i ^ \hat{y_{i}} yi^ 的第 y i y_i yi个元素。
容易证明对数损失函数与交叉熵函数完全等价是交叉熵的另外一种视角: 即每个样本对其标签对应类别的预测概率值求对数求平均再取负数即可。
4pytorch中的 nn.NLLLoss 和 nn.CrossEntropyLoss有什么区别和联系
NLLoss 全称是 Negative Log Likelihood Loss即 负对数似然损失。其计算公式如下 N L L o s s ( Y , Z ^ ) − 1 N ∑ i 0 N − 1 z i [ y i ] NLLoss(Y,\hat{Z}) - \frac{1}{N}\sum_{i0}^{N-1} {z_{i}}[y_i] NLLoss(Y,Z^)−N1i0∑N−1zi[yi]
公式中的方括号和Python中的索引的用法一致表示取 z i ^ \hat{z_{i}} zi^ 的第 y i y_i yi个元素。
注意的是这里的 Z ^ \hat{Z} Z^实际上不是概率值而是概率值取了对数所以和LogLoss一对比很容易发现LogSoftmaxNLLLoss 等价于 SoftmaxLogLoss,等价于 SoftmaxCrossEntropyLoss。为了数值精度考虑pytorch中的nn.CrossEntropyLoss要求输入未经过Softmax激活所以有 nn.LogSoftmaxnn.NLLLoss 等价于 nn.CrossEntropyLoss.
5KL散度的计算公式是什么有什么现实含义和交叉熵有什么关系
KL散度也叫相对熵可以衡量两个概率分布之间的差异。
KL散度的计算公式是交叉熵减去信息熵。注意KL散度是不对称的, 即 K L ( P , Q ) ≠ K L ( Q , P ) KL(P,Q)\neq KL(Q,P) KL(P,Q)KL(Q,P), 所以不能够叫做KL距离。
两个随机变量P和Q之间的KL散度定义如下 K L ( P , Q ) ∑ k 0 K − 1 p k l n ( p k q k ) ∑ k 0 K − 1 p k ( l n p k − l n q k ) KL(P,Q) \sum_{k0}^{K-1}p_k ln(\frac{p_k}{q_k}) \sum_{k0}^{K-1} p_k (ln{p_k} - ln{q_k}) KL(P,Q)k0∑K−1pkln(qkpk)k0∑K−1pk(lnpk−lnqk)
对二分类情况下有 K L ( Y , Y ^ ) − 1 N ∑ i 0 N − 1 ( y i l o g y i ^ ( 1 − y i ) l o g ( 1 − y i ^ ) ) 1 N ∑ i 0 N − 1 ( y i l o g y i ( 1 − y i ) l o g ( 1 − y i ) ) KL(Y,\hat{Y}) - \frac{1}{N}\sum_{i0}^{N-1} (y_i log \hat{y_i} (1-y_i) log(1-\hat{y_i})) \frac{1}{N}\sum_{i0}^{N-1} (y_i log y_i (1-y_i) log(1- y_i)) KL(Y,Y^)−N1i0∑N−1(yilogyi^(1−yi)log(1−yi^))N1i0∑N−1(yilogyi(1−yi)log(1−yi))
在 y i y_i yi取0或1的情况下信息熵部分为0所以KL散度就等于交叉熵但是在一些情况下例如使用标签平滑处理技术后 y i y_i yi的取值不是0或1这时候KL散度相当于在交叉熵的基础上减去了一个常数KL散度作为损失函数去优化模型的效果和交叉熵是完全一样的但是在这种情况下当模型完美拟合标签的情况下KL散度的最小值可取到0而此时交叉熵能够取到的最小值是信息熵不为0所以这种情况下使用KL散度更符合我们对Loss的一般认识。
import numpy as np
import pandas as pd
import torch
from torch import nn
import torch.nn.functional as F # nn.BCELoss() 和 nn.BCEWithLogitsLoss() 关系y_pred torch.tensor([5.0,3,10,-5,-3,-10.0])
y_true torch.tensor([1.0,1,1,0,0,0])bce nn.BCELoss()(torch.sigmoid(y_pred),y_true)
print(bce)bce_logits nn.BCEWithLogitsLoss()(y_pred,y_true)
print(bce_logits)
tensor(0.0184)
tensor(0.0184)# nn.CrossEntropyLoss() 和 nn.NLLLoss() 关系y_pred torch.tensor([[10.0,0.0,-10.0],[8.0,8.0,8.0]])
y_true torch.tensor([0,2])# 直接调用交叉熵损失
ce nn.CrossEntropyLoss()(y_pred,y_true)
print(ce)# 等价于先计算nn.LogSoftmax激活再调用nn.NLLLoss
y_pred_logsoftmax nn.LogSoftmax(dim 1)(y_pred)
nll nn.NLLLoss()(y_pred_logsoftmax,y_true)
print(nll)
tensor(0.5493)
tensor(0.5493)# nn.CrossEntropyLoss() 和 KLDivLoss 关系
import torch.nn.functional as F y_pred torch.tensor([[10.0,0.0,-10.0],[8.0,8.0,8.0]],requires_gradTrue)
y_true torch.tensor([0,2])ce nn.CrossEntropyLoss(reductionmean)(y_pred,y_true)
print(ce)#KLDivLoss要求target为向量形式编码且preds经过LogSoftmax激活
pred F.log_softmax(y_pred,dim1)
target F.one_hot(y_true).float()
kl nn.KLDivLoss(reductionbatchmean)(pred,target)
print(kl)tensor(0.5493, grad_fnNllLossBackward0)
tensor(0.5493, grad_fnDivBackward0)二自定义损失函数
自定义损失函数接收两个张量y_pred,y_true作为输入参数并输出一个标量作为损失函数值。
也可以对nn.Module进行子类化重写forward方法实现损失的计算逻辑从而得到损失函数的类的实现。
下面演示两个比较著名的范例。
1自定义损失函数之FocalLoss范例
下面是一个Focal Loss的自定义实现示范。Focal Loss是一种对binary_crossentropy的改进损失函数形式。
它在样本不均衡和存在较多易分类的样本时相比binary_crossentropy具有明显的优势。
它有两个可调参数alpha参数和gamma参数。其中alpha参数主要用于衰减负样本的权重gamma参数主要用于衰减容易训练样本的权重。
从而让模型更加聚焦在正样本和困难样本上。这就是为什么这个损失函数叫做Focal Loss。
详见《5分钟理解Focal Loss与GHM——解决样本不平衡利器》
https://zhuanlan.zhihu.com/p/80594704 f o c a l _ l o s s ( y , p ) { − α ( 1 − p ) γ log ( p ) if y 1 − ( 1 − α ) p γ log ( 1 − p ) if y 0 focal\_loss(y,p) \begin{cases} -\alpha (1-p)^{\gamma}\log(p) \text{if y 1}\\ -(1-\alpha) p^{\gamma}\log(1-p) \text{if y 0} \end{cases} focal_loss(y,p){−α(1−p)γlog(p)−(1−α)pγlog(1−p)if y 1if y 0
import torch
from torch import nn
class FocalLoss(nn.Module):def __init__(self,gamma2.0,alpha0.75):super().__init__()self.gamma gammaself.alpha alphadef forward(self,y_pred,y_true):bce torch.nn.BCELoss(reduction none)(y_pred,y_true)p_t (y_true * y_pred) ((1 - y_true) * (1 - y_pred))alpha_factor y_true * self.alpha (1 - y_true) * (1 - self.alpha)modulating_factor torch.pow(1.0 - p_t, self.gamma)loss torch.mean(alpha_factor * modulating_factor * bce)return loss
#困难样本
y_pred_hard torch.tensor([[0.5],[0.5]])
y_true_hard torch.tensor([[1.0],[0.0]])#容易样本
y_pred_easy torch.tensor([[0.9],[0.1]])
y_true_easy torch.tensor([[1.0],[0.0]])focal_loss FocalLoss()
bce_loss nn.BCELoss()print(focal_loss(easy samples):, focal_loss(y_pred_easy,y_true_easy))
print(bce_loss(easy samples):, bce_loss(y_pred_easy,y_true_easy))print(focal_loss(hard samples):, focal_loss(y_pred_hard,y_true_hard))
print(bce_loss(hard samples):, bce_loss(y_pred_hard,y_true_hard))#可见 focal_loss让容易样本的权重衰减到原来的 0.0005/0.1054 0.00474
#而让困难样本的权重只衰减到原来的 0.0866/0.69310.12496# 因此相对而言focal_loss可以衰减容易样本的权重。
focal_loss(easy samples): tensor(0.0005)
bce_loss(easy samples): tensor(0.1054)
focal_loss(hard samples): tensor(0.0866)
bce_loss(hard samples): tensor(0.6931)FocalLoss的使用完整范例可以参考下面中自定义L1和L2正则化项中的范例该范例既演示了自定义正则化项的方法也演示了FocalLoss的使用方法。
2SCELoss
Symmetric Cross Entropy Loss 也是一种对交叉熵损失的改进损失主要用在标签中存在明显噪声的场景。 s c e _ l o s s ( y , p ) α c e _ l o s s ( y , p ) β r c e _ l o s s ( y , p ) c e _ l o s s ( y , p ) − y l o g ( p ) − ( 1 − y ) l o g ( 1 − p ) r c e _ l o s s ( y , p ) c e _ l o s s ( p , y ) r c e _ l o s s ( y , p ) − p l o g ( y ) − ( 1 − p ) l o g ( 1 − y ) sce\_loss(y,p) \alpha\;ce\_loss(y,p) \beta\;rce\_loss(y,p)\\ ce\_loss(y,p) - y log(p) -(1-y) log(1-p) \\ rce\_loss(y,p) ce\_loss(p,y) \\ rce\_loss(y,p) - p log(y) -(1-p) log(1-y) sce_loss(y,p)αce_loss(y,p)βrce_loss(y,p)ce_loss(y,p)−ylog(p)−(1−y)log(1−p)rce_loss(y,p)ce_loss(p,y)rce_loss(y,p)−plog(y)−(1−p)log(1−y)
其基本思想可以简单描述如下
当 y是正常标签的时候y和p较容易取得一致【例如 y1时p取到0.8】这时候 rce与ce的比值相对较大引入rce可以增加正常标签样本在总Loss中的贡献。
当y时噪声标签的时候y和p很难取得一致相当于困难样本 【例如 y0时p取到0.8】这时候rce与ce的比值相对较小引入rce可以减小噪声标签样本在总Loss中的贡献。
参考文章
《SCE 损失》 https://zhuanlan.zhihu.com/p/420827592
《噪声损失 》https://zhuanlan.zhihu.com/p/420913134
def ce(y,p):p torch.clamp(p,min1e-4,max1-1e-4)y torch.clamp(y,min1e-4,max1-1e-4)return -y*torch.log(p) - (1-y)*torch.log(1-p)def rce(y,p):return ce(p,y)#正常标签
y torch.tensor(1.0)
p torch.tensor(0.8)
print(rce(y,p)/ce(y,p))#噪声标签
y torch.tensor(0.0)
p torch.tensor(0.8)
print(rce(y,p)/ce(y,p))
tensor(8.2502)
tensor(4.5786)import torch
from torch import nn
import torch.nn.functional as F class SCELoss(nn.Module):def __init__(self, num_classes10, a1, b1):super(SCELoss, self).__init__()self.num_classes num_classesself.a a #两个超参数self.b bself.cross_entropy nn.CrossEntropyLoss()def forward(self, pred, labels):# CE 部分正常的交叉熵损失ce self.cross_entropy(pred, labels)# RCEpred F.softmax(pred, dim1)pred torch.clamp(pred, min1e-4, max1.0)label_one_hot F.one_hot(labels, self.num_classes).float().to(pred.device)label_one_hot torch.clamp(label_one_hot, min1e-4, max1.0) #最小设为 1e-4即 A 取 -4rce (-1 * torch.sum(pred * torch.log(label_one_hot), dim1))loss self.a * ce self.b * rce.mean()return loss ## 三L1和L2正则化项L1正则、L2正则、Dropout、Early_stopping是神经网络常用的正则化方法。1L1正则和L2正则的效果有什么差异?为什么通常认为L1 正则化可以产生稀疏权值矩阵即产生一个参数稀疏的模型。而L2 正则化可以让模型的参数取绝对值较小的数。考虑两种正则化函数的等值面与原始Loss函数的等值面的关系。以二维情况为例L1正则化函数的等值面是个菱形L2正则化函数的等值面是个圆形。最优参数必定取在正则化函数的某条等值面和原始Loss函数的某条等值面的切点处。从求导角度考虑最优参数是个极值点要求该处 正则化函数的梯度等于 原始Loss函数的梯度的负数。而梯度方向必定垂直于等值面的切线方向所以可以推断必定极值点必定在正则化函数某条等值面和原始Loss函数的某条等值面的切点处。从数值角度考虑如果该极值点不在两个等值面的切点那么沿着原始函数Loss的等值面(原始Loss不变)一定可以找到一个点正则化函数取值更小。这样就用反证法证明了最优参数必定取在正则化函数的某条等值面和原始Loss函数的某条等值面的切点处。由于L1正则化函数的等值面是个菱形更容易和凸的Loss函数的等值面相切在坐标轴上所以倾向于取得参数稀疏的模型而L2正则化则更倾向于使得极小点到坐标原点的距离更近但不会导致参数稀疏。参考文章《L1正则化与L2正则化》https://zhuanlan.zhihu.com/p/35356992 python
import torch
# L2正则化
def L2Loss(model,alpha):l2_loss torch.tensor(0.0, requires_gradTrue)for name, param in model.named_parameters():if bias not in name: #一般不对偏置项使用正则l2_loss l2_loss (0.5 * alpha * torch.sum(torch.pow(param, 2)))return l2_loss# L1正则化
def L1Loss(model,beta):l1_loss torch.tensor(0.0, requires_gradTrue)for name, param in model.named_parameters():if bias not in name:l1_loss l1_loss beta * torch.sum(torch.abs(param))return l1_loss
四L1L2正则项使用完整范例
下面以一个二分类问题为例演示给模型的目标函数添加自定义L1和L2正则化项的方法。
这个范例同时演示了以下FocalLoss的使用。
1准备数据
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
import torch
from torch import nn
import torch.nn.functional as F
from torch.utils.data import Dataset,DataLoader,TensorDataset
import torchkeras
%matplotlib inline
%config InlineBackend.figure_format svg#正负样本数量
n_positive,n_negative 1000,6000#生成正样本, 小圆环分布
r_p 5.0 torch.normal(0.0,1.0,size [n_positive,1])
theta_p 2*np.pi*torch.rand([n_positive,1])
Xp torch.cat([r_p*torch.cos(theta_p),r_p*torch.sin(theta_p)],axis 1)
Yp torch.ones_like(r_p)#生成负样本, 大圆环分布
r_n 8.0 torch.normal(0.0,1.0,size [n_negative,1])
theta_n 2*np.pi*torch.rand([n_negative,1])
Xn torch.cat([r_n*torch.cos(theta_n),r_n*torch.sin(theta_n)],axis 1)
Yn torch.zeros_like(r_n)#汇总样本
X torch.cat([Xp,Xn],axis 0)
Y torch.cat([Yp,Yn],axis 0)#可视化
plt.figure(figsize (6,6))
plt.scatter(Xp[:,0],Xp[:,1],c r)
plt.scatter(Xn[:,0],Xn[:,1],c g)
plt.legend([positive,negative]);
ds TensorDataset(X,Y)ds_train,ds_val torch.utils.data.random_split(ds,[int(len(ds)*0.7),len(ds)-int(len(ds)*0.7)])
dl_train DataLoader(ds_train,batch_size 100,shuffleTrue,num_workers2)
dl_val DataLoader(ds_val,batch_size 100,num_workers2)features,labels next(iter(dl_train))
2定义模型 class Net(nn.Module):def __init__(self):super().__init__()self.fc1 nn.Linear(2,4)self.fc2 nn.Linear(4,8) self.fc3 nn.Linear(8,1)def forward(self,x):x F.relu(self.fc1(x))x F.relu(self.fc2(x))y self.fc3(x)return ynet Net() from torchkeras import summarysummary(net,features);
--------------------------------------------------------------------------
Layer (type) Output Shape Param #Linear-1 [-1, 4] 12
Linear-2 [-1, 8] 40
Linear-3 [-1, 1] 9Total params: 61
Trainable params: 61
Non-trainable params: 0
--------------------------------------------------------------------------
Input size (MB): 0.000069
Forward/backward pass size (MB): 0.000099
Params size (MB): 0.000233
Estimated Total Size (MB): 0.000401
--------------------------------------------------------------------------3训练模型
# L2正则化
def L2Loss(model,alpha):l2_loss torch.tensor(0.0, requires_gradTrue)for name, param in model.named_parameters():if bias not in name: #一般不对偏置项使用正则l2_loss l2_loss (0.5 * alpha * torch.sum(torch.pow(param, 2)))return l2_loss# L1正则化
def L1Loss(model,beta):l1_loss torch.tensor(0.0, requires_gradTrue)for name, param in model.named_parameters():if bias not in name:l1_loss l1_loss beta * torch.sum(torch.abs(param))return l1_loss
from torchkeras import KerasModel
from torchkeras.metrics import AUCnet Net()# 将L2正则和L1正则添加到FocalLoss损失一起作为目标函数
def focal_loss_with_regularization(y_pred,y_true):y_probs torch.sigmoid(y_pred)focal FocalLoss()(y_probs,y_true) l2_loss L2Loss(net,0.001) #注意设置正则化项系数l1_loss L1Loss(net,0.001)total_loss focal l2_loss l1_lossreturn total_lossoptimizer torch.optim.Adam(net.parameters(),lr 0.002)
model KerasModel(netnet,loss_fn focal_loss_with_regularization ,metrics_dict {auc:AUC()},optimizer optimizer )dfhistory model.fit(train_datadl_train,val_datadl_val,epochs20,ckpt_pathcheckpoint,patience3,monitorval_auc,modemax,plotTrue,cpuTrue)[0;31m cpu is used [0m100% [20/20] [00:54] ████████████████████100.00% [21/21] [val_loss0.0276, val_auc0.9819] # 结果可视化
fig, (ax1,ax2) plt.subplots(nrows1,ncols2,figsize (12,5))
ax1.scatter(Xp[:,0],Xp[:,1], cr)
ax1.scatter(Xn[:,0],Xn[:,1],c g)
ax1.legend([positive,negative]);
ax1.set_title(y_true);Xp_pred X[torch.squeeze(torch.sigmoid(net.forward(X))0.5)]
Xn_pred X[torch.squeeze(torch.sigmoid(net.forward(X))0.5)]ax2.scatter(Xp_pred[:,0],Xp_pred[:,1],c r)
ax2.scatter(Xn_pred[:,0],Xn_pred[:,1],c g)
ax2.legend([positive,negative]);
ax2.set_title(y_pred); 五通过优化器实现L2正则化
如果仅仅需要使用L2正则化那么也可以利用优化器的weight_decay参数来实现。
weight_decay参数可以设置参数在训练过程中的衰减这和L2正则化的作用效果等价。
before L2 regularization:gradient descent: w w - lr * dloss_dw after L2 regularization:gradient descent: w w - lr * (dloss_dwbeta*w) (1-lr*beta)*w - lr*dloss_dwso 1-lr*betais the weight decay ratio.Pytorch的优化器支持一种称之为Per-parameter options的操作就是对每一个参数进行特定的学习率权重衰减率指定以满足更为细致的要求。
weight_params [param for name, param in model.named_parameters() if bias not in name]
bias_params [param for name, param in model.named_parameters() if bias in name]optimizer torch.optim.SGD([{params: weight_params, weight_decay:1e-5},{params: bias_params, weight_decay:0}],lr1e-2, momentum0.9)