【AI】Pytorch_损失函数优化器

建议点赞收藏关注!持续更新至pytorch大部分内容更完。
本文已达到10w字,故按模块拆开,详见目录导航。

整体框架如下
数据及预处理
模型及其构建
损失函数及优化器


本节目录

  • 损失函数
    • 创建损失函数 (共18个)
      • nn.CrossEntropyLoss
      • nn.NLLLoss
      • BCE Loss
      • BCEwithLogitsLoss
      • nn.L1Loss
      • nn.MSELoss
      • nn.SmoothL1Loss
      • nn.PoissonNLLLoss
      • nn.KLDivLoss
      • nn.MarginRankingLoss
      • nn.MultiLabelMarginLoss
      • nn.SoftMarginLoss
      • nn.MultiLabelSoftMarginLoss
      • nn.MultiMarginLoss
      • nn.TripletMarginLoss
      • nn.HingeEmbeddingLoss
      • nn.CosineEmbeddingLoss
      • nn.CTCLoss
    • 设置损失函数超参数
    • 选择损失函数
  • 优化器(共10个)
    • optim.SGD 随机梯度下降法
    • torch.optim.ASGD 随机平均梯度下降
    • torch.optim.Rprop 弹性反向传播
    • torch.optim.Adagrad 自适应学习率梯度下降法
    • torch.optim.Adadelta:Adagrad的改进
    • torch.optim.RMSprop:Adagrad的改进
    • torch.optim.Adam(AMSGrad):RMSprop结合Momentum
    • torch.optim.Adamax: Adam增加学习率上限
    • torch.optim.SparseAdam:稀疏版Adam
    • torch.optim.LBFGS:BFGS的改进
  • 优化算法
    • 梯度下降法
    • 管理模型参数
    • 管理多个参数组实现不同学习率
    • 调整学习率
  • 迭代训练
    • 观察训练效果
    • 绘制loss/accuracy曲线
    • 用TensorBoard分析
  • 模型应用
    • 图像分类
    • 图像分割
    • 目标检测
    • 对抗生成
    • 循环网络

损失函数

损失函数loss,代价函数cost,目标函数objective
在这里插入图片描述
交叉熵=信息熵+相对熵
(1)熵用来描述一个事件的不确定性,不确定性越大则熵越大.
(2)信息熵是自信息的期望,自信息用于衡量单个输出单个事件的不确定性.
(3)相对熵又叫做KL散度,用于衡量两个分布之间的差异,即两个分布之间的距离,但不是距离的函数,不具备对称性。
下图公式中都是,P是真实的分布,Q是模型输出的分布,Q需要逼近、拟合P的分布.
(4)交叉熵用于衡量两个分布之间的相似度.
(5)P是真实的分布,即训练集中样本的分布。由于训练集是固定的,概率分布也是固定的,H§是个常数.故优化交叉熵等价于优化相对熵。
在这里插入图片描述

在这里插入图片描述
上图是一个伯努利分布,可以发现当概率是0.5时熵最大(为0.69),0.69这个数字经常会碰到:模型训练坏了、模型的训练第一个iteration,此时不具备判断能力,因为对于任何输出判别的概率都是1/2。

创建损失函数 (共18个)

nn.CrossEntropyLoss

nn.CrossEntropyLoss(weight=None, ignore_index=- 100,  reduction='mean' )
'''
size_average=None, reduce=None,这俩个参数已废弃
weight:各类别loss设置权值
ignore_index:忽略某个类别而不计算它的loss
reduction:计算模式,可为none/sum/mean
none 逐个元素计算这么多个loss
sum 所有元素求和,返回标量
mean 加权平均,返回标量
'''

交叉熵这里的不是按照书中公式所计算的,这里其实是nn.LogSoftmax()与nn.NLLLoss()结合进行计算的。它采用softmax对数据进行了归一化,把数据值归一化到概率输出的形式。交叉熵损失函数常常用于分类任务中。交叉熵是衡量两个概率分布之间的差异,交叉熵值越低,表示两个概率分布越近。
运用softmax可以将输出值转换归一化到0~1之间作为概率。
在这里插入图片描述
首先上图 这里x是输出的一个概率值,class是一个类别值。
第二式中的(分式)就是softmax的公式,对比第一式即交叉熵公式,可知 这个xi是已经取到的,所以p(xi)=1,并且第二式只是计算其中一个的交叉熵,故也没有N项求和符号。
当调用这个方法时传入了weight参数,则计算公式为第三式

# fake data
#二分类任务,输出神经元2个,batchsize是3,即三个样本:[1,2] [1,3] [1,3]
inputs = torch.tensor([[1, 2], [1, 3], [1, 3]], dtype=torch.float)
#dtype必须是long,有多少个样本,tensor(1D)就有多长。而且这里的类别label也是从0开始标号的
target = torch.tensor([0, 1, 1], dtype=torch.long)# ----------------------------------- CrossEntropy loss: reduction -----------------------------------
flag = 0
# flag = 1
if flag:# def loss functionloss_f_none = nn.CrossEntropyLoss(weight=None, reduction='none')loss_f_sum = nn.CrossEntropyLoss(weight=None, reduction='sum')loss_f_mean = nn.CrossEntropyLoss(weight=None, reduction='mean')# forwardloss_none = loss_f_none(inputs, target)loss_sum = loss_f_sum(inputs, target)loss_mean = loss_f_mean(inputs, target)# viewprint("Cross Entropy Loss:\n ", loss_none, loss_sum, loss_mean)#输出为[1.3133, 0.1269, 0.1269] 1.5671 0.5224# --------------------------------- compute by hand
flag = 0
# flag = 1
if flag:idx = 0input_1 = inputs.detach().numpy()[idx]      # [1, 2]两个神经元target_1 = target.numpy()[idx]              # [0]# 第一项x_class = input_1[target_1]# 第二项 map指对其每一个神经元进行运算sigma_exp_x = np.sum(list(map(np.exp, input_1)))log_sigma_exp_x = np.log(sigma_exp_x)# 输出lossloss_1 = -x_class + log_sigma_exp_xprint("第一个样本loss为: ", loss_1)# ----------------------------------- weight -----------------------------------
flag = 0
# flag = 1
if flag:# def loss function
'''
有多少个类别weights这个向量就要设置多长,
每一个类别都必须设置weight,
如果不想关注这个weight,就将其设置为1就不会变的。如果类别是mean,则每个weight数值多大不重要,重要在于他们之间的比例。结果可以看出来,原先得到的loss基础上,如果数据label==0则用weight[0]=1倍,故与之前相等。而label==1的后两个数据的loss变成了之前的2倍(因为weight==2)在sum模式下,weight==2也代表label==1的这一个数据就占两份1在分母中,在本例中为 三个数据loss之和/(1+2+2)
'''weights = torch.tensor([1, 2], dtype=torch.float)# weights = torch.tensor([0.7, 0.3], dtype=torch.float)loss_f_none_w = nn.CrossEntropyLoss(weight=weights, reduction='none')loss_f_sum = nn.CrossEntropyLoss(weight=weights, reduction='sum')loss_f_mean = nn.CrossEntropyLoss(weight=weights, reduction='mean')# forwardloss_none_w = loss_f_none_w(inputs, target)loss_sum = loss_f_sum(inputs, target)loss_mean = loss_f_mean(inputs, target)# viewprint("\nweights: ", weights)print(loss_none_w, loss_sum, loss_mean)#权值为[1,2],则输出[1.3133, 0.2539, 0.2539] 1.8210 0.3642# target=[0,1,1]所以对应0的需要乘以权值1,对应1的需要乘以权值2.# 1.3133是1.3133*1=1.3133,0.2530是0.1269*2=0.2539,0.2530是0.1269*2=0.2539.#0.3642是1.8210/(1+2+2)=0.3642,分母是权值的份数(5).# --------------------------------- compute by hand :手动计算
flag = 0
# flag = 1
if flag:weights = torch.tensor([1, 2], dtype=torch.float)#weights_all=5 计算sum公式中除掉的分母,份数weights_all = np.sum(list(map(lambda x: weights.numpy()[x], target.numpy())))  # [0, 1, 1] ---> # [1 2 2]mean = 0loss_sep = loss_none.detach().numpy()for i in range(target.shape[0]):
#输出每一个样本在这平均值loss中贡献的数目x_class = target.numpy()[i]tmp = loss_sep[i] * (weights.numpy()[x_class] / weights_all)mean += tmpprint(mean)

nn.NLLLoss

nn.NLLLoss(weight=None, size_average=None, ignore_index=- 100, reduce=None, reduction='mean')
'''
实现负对数似然函数中的负号功能,简单来说就是取负号
'''# fake data
#二分类任务,输出神经元2个,batchsize是3,即三个样本:[1,2] [1,3] [1,3]
inputs = torch.tensor([[1, 2], [1, 3], [1, 3]], dtype=torch.float)
#dtype必须是long,有多少个样本,tensor(1D)就有多长。
target = torch.tensor([0, 1, 1], dtype=torch.long)# ----------------------------------- 2 NLLLoss -----------------------------------
flag = 0
# flag = 1
if flag:weights = torch.tensor([1, 1], dtype=torch.float)loss_f_none_w = nn.NLLLoss(weight=weights, reduction='none')loss_f_sum = nn.NLLLoss(weight=weights, reduction='sum')loss_f_mean = nn.NLLLoss(weight=weights, reduction='mean')# forwardloss_none_w = loss_f_none_w(inputs, target)loss_sum = loss_f_sum(inputs, target)loss_mean = loss_f_mean(inputs, target)# viewprint("NLL Loss", loss_none_w, loss_sum, loss_mean)#输出[-1,-3,-3] -7 -2.3333# target[0, 1, 1]#-1是因为第一个样本[1,2]是第0类,因此只对第一个神经元输出操作:-1*1。#-3是因为第二个样本[1,3]是第1类,因此只对第二个神经元输出操作:-1*3。#-3是因为第三个样本[1,3]是第1类,因此只对第二个神经元输出操作:-1*3。#求mean时的分母是权重weight的和。

BCE Loss

xn是模型输出的概率取值,yn是标签(二分类中对应0或1)。
在这里插入图片描述

nn.BCELoss(weight=None, size_average=None, reduce=None, reduction='mean')
'''
二分类交叉熵损失函数
注意:输入值取值在[0,1],利用sigmoid函数可实现
'''# ----------------------------------- 3 BCE Loss -----------------------------------
flag = 0
# flag = 1
if flag:
#同样是二分类,每个样本有两个神经元inputs = torch.tensor([[1, 2], [2, 2], [3, 4], [4, 5]], dtype=torch.float) #4个样本target = torch.tensor([[1, 0], [1, 0], [0, 1], [0, 1]], dtype=torch.float) #float类型,每个神经元一一对应去计算loss,而不是之前是整个向量去计算losstarget_bce = target#一定要加上sigmoid,将输入值取值在[0,1]区间inputs = torch.sigmoid(inputs)weights = torch.tensor([1, 1], dtype=torch.float)loss_f_none_w = nn.BCELoss(weight=weights, reduction='none')loss_f_sum = nn.BCELoss(weight=weights, reduction='sum')loss_f_mean = nn.BCELoss(weight=weights, reduction='mean')# forwardloss_none_w = loss_f_none_w(inputs, target_bce)loss_sum = loss_f_sum(inputs, target_bce)loss_mean = loss_f_mean(inputs, target_bce)# viewprint("\nweights: ", weights)print("BCE Loss", loss_none_w, loss_sum, loss_mean)#输出[[0.3133, 2.1269], [0.1269, 2.1269], [3.0486, 0.0181], [4.0181, 0.0067]] 11.7856 1.4732#每个神经元一一对应去计算loss,因此loss个数是2*4=8个# --------------------------------- compute by hand
flag = 0
# flag = 1
if flag:idx = 0x_i = inputs.detach().numpy()[idx, idx]y_i = target.numpy()[idx, idx]              ## loss# l_i = -[ y_i * np.log(x_i) + (1-y_i) * np.log(1-y_i) ]      # np.log(0) = nanl_i = -y_i * np.log(x_i) if y_i else -(1-y_i) * np.log(1-x_i)# 输出lossprint("BCE inputs: ", inputs)print("第一个loss为: ", l_i) #0.3133

BCEwithLogitsLoss

在这里插入图片描述
σ是sigmoid函数

nn.BCEWithLogitsLoss(weight=None, size_average=None, reduce=None, reduction='mean', pos_weight=None)
'''
结合sigmoid与二分类交叉熵
注意:网络最后不要加sigmoid函数,再加这个值就不准确了这个损失函数存在的原因:有的时候不希望模型里有sigmoid在最后一层。多了一个参数pos_weight 正样本权值
(1)pos_weight用于均衡正负样本,正样本的loss需要乘以pos_weight。
比如正样本100个,负样本300个,此时可以将pos_weight设置为3,就可以实现正负样本均衡。
(2)pos_weight里是一个tensor列表,需要和标签个数相同,比如现在有一个多标签分类,类别有200个,那么 pos_weight 就是为每个类别赋予的权重值,长度为200
(3)如果现在是二分类,只需要将正样本loss的权重写上即可,比如我们有正负两类样本,正样本数量为100个,负样本为400个,我们想要对正负样本的loss进行加权处理,将正样本的loss权重放大4倍,通过这样的方式缓解样本不均衡问题:'''
criterion = nn.BCEWithLogitsLoss(pos_weight=torch.tensor([4]))# ----------------------------------- 4 BCE with Logis Loss -----------------------------------
# flag = 0
flag = 1
if flag:inputs = torch.tensor([[1, 2], [2, 2], [3, 4], [4, 5]], dtype=torch.float)target = torch.tensor([[1, 0], [1, 0], [0, 1], [0, 1]], dtype=torch.float)target_bce = target# inputs = torch.sigmoid(inputs) 不能加sigmoid!!!weights = torch.tensor([1, 1], dtype=torch.float)loss_f_none_w = nn.BCEWithLogitsLoss(weight=weights, reduction='none')loss_f_sum = nn.BCEWithLogitsLoss(weight=weights, reduction='sum')loss_f_mean = nn.BCEWithLogitsLoss(weight=weights, reduction='mean')# forwardloss_none_w = loss_f_none_w(inputs, target_bce)loss_sum = loss_f_sum(inputs, target_bce)loss_mean = loss_f_mean(inputs, target_bce)# viewprint("\nweights: ", weights)print(loss_none_w, loss_sum, loss_mean)#输出[[0.3133, 2.1269], [0.1269, 2.1269], [3.0486, 0.0181], [4.0181, 0.0067]] 11.7856 1.4732# --------------------------------- pos weight# flag = 0
flag = 1
if flag:inputs = torch.tensor([[1, 2], [2, 2], [3, 4], [4, 5]], dtype=torch.float)target = torch.tensor([[1, 0], [1, 0], [0, 1], [0, 1]], dtype=torch.float)target_bce = target# itarget# inputs = torch.sigmoid(inputs)weights = torch.tensor([1], dtype=torch.float)#pos_w = torch.tensor([1], dtype=torch.float)  #设置为1时,loss输出与原先一致。pos_w = torch.tensor([3], dtype=torch.float)        # 3#设置为3时会对正样本的loss乘以3,即标签是1对应的loss。#输出[[0.3133*3, 2.1269], [0.1269*3, 2.1269], [3.0486, 0.0181*3], [4.0181, 0.0067*3]]loss_f_none_w = nn.BCEWithLogitsLoss(weight=weights, reduction='none', pos_weight=pos_w)loss_f_sum = nn.BCEWithLogitsLoss(weight=weights, reduction='sum', pos_weight=pos_w)loss_f_mean = nn.BCEWithLogitsLoss(weight=weights, reduction='mean', pos_weight=pos_w)# forwardloss_none_w = loss_f_none_w(inputs, target_bce)loss_sum = loss_f_sum(inputs, target_bce)loss_mean = loss_f_mean(inputs, target_bce)# viewprint("\npos_weights: ", pos_w)print(loss_none_w, loss_sum, loss_mean)

nn.L1Loss

计算Inputs与target之差的绝对值

nn.MSELoss

计算差的平方
在这里插入图片描述

# ------------------------------------------------- 5 L1 loss ----------------------------------------------
flag = 0
# flag = 1
if flag:inputs = torch.ones((2, 2)) #2*2,数值为1target = torch.ones((2, 2)) * 3 #2*2,数值为3loss_f = nn.L1Loss(reduction='none')loss = loss_f(inputs, target)print("input:{}\ntarget:{}\nL1 loss:{}".format(inputs, target, loss))#输出为[[2,2],[2,2]]# ------------------------------------------------- 6 MSE loss ----------------------------------------------loss_f_mse = nn.MSELoss(reduction='none')loss_mse = loss_f_mse(inputs, target)print("MSE loss:{}".format(loss_mse))#输出为[[4,4],[4,4]]

nn.SmoothL1Loss

平滑的L1 loss,看图就知道为什么要这样设置函数了,可以减轻离群点带来的影响。
在这里插入图片描述

# ------------------------------------------------- 7 Smooth L1 loss ----------------------------------------------
flag = 0
# flag = 1
if flag:inputs = torch.linspace(-3, 3, steps=500) #-3到3区间取500个数据点target = torch.zeros_like(inputs) #数值为0,维度与inputs一致loss_f = nn.SmoothL1Loss(reduction='none')loss_smooth = loss_f(inputs, target)loss_l1 = np.abs(inputs.numpy()-target.numpy())plt.plot(inputs.numpy(), loss_smooth.numpy(), label='Smooth L1 Loss')plt.plot(inputs.numpy(), loss_l1, label='L1 loss')plt.xlabel('x_i - y_i')plt.ylabel('loss value')plt.legend()plt.grid()plt.show()#画出的图像就是上图所示

nn.PoissonNLLLoss

泊松分布的负对数似然损失函数
在这里插入图片描述

nn.PoissonNLLLoss(log_input=True, full=False, size_average=None, eps=1e-08, reduce=None, reduction='mean')
'''
log_input:输入是否是对数形式,决定计算公式使用上图哪一个
full:计算所有loss,默认为False
eps:修正项,避免log(input)为nan(即避免输入取0时)
'''
# ------------------------------------------------- 8 Poisson NLL Loss ----------------------------------------------
flag = 0
# flag = 1
if flag:inputs = torch.randn((2, 2)) #2*2,标准正态分布target = torch.randn((2, 2)) #2*2,标准正态分布loss_f = nn.PoissonNLLLoss(log_input=True, full=False, reduction='none')loss = loss_f(inputs, target)print("input:{}\ntarget:{}\nPoisson NLL loss:{}".format(inputs, target, loss))# --------------------------------- compute by hand
flag = 0
# flag = 1
if flag:idx = 0loss_1 = torch.exp(inputs[idx, idx]) - target[idx, idx]*inputs[idx, idx] #计算第一个元素,即inputs[0,0]print("第一个元素loss:", loss_1)

nn.KLDivLoss

在这里插入图片描述
KL散度衡量两个分布的相似性或者“距离”
P:样本在真实分布的概率 即标签
Q:尽可能拟合逼近P的分布,即模型输出的分布
Q(xi)指其中xi样本的概率

第二个公式ln 是pytorch 的这个计算公式,xn是输入的数据,yn是标签
有一些区别,区别在于xn而非logQ(xi)即log(xn),这样就是下面提到的需要提前计算输入的log-probabilities

nn.KLDivLoss(size_average=None, reduce=None, reduction='mean', log_target=False)
'''
计算KLD即KL散度,相对熵
需提前将输入计算log-probablities,如通过nn.logsoftmax(),softmax生成probabilities 然后对其logbatchmean:batchsize维度求平均值,也就是说求平均值除以的分母不再是元素个数,而是batchsize
'''
# ------------------------------------------------- 9 KL Divergence Loss ----------------------------------------------
flag = 0
# flag = 1
if flag:# 3个神经元,第一批样本中第一个神经元输出为0.5,第二个0.3,第三个0.2# 第二批样本中第一个0.2,第二个0.3,第三个0.5inputs = torch.tensor([[0.5, 0.3, 0.2], [0.2, 0.3, 0.5]]) #2*3,2批样本,3个神经元 已经是概率值了不需要再softmaxinputs_log = torch.log(inputs)target = torch.tensor([[0.9, 0.05, 0.05], [0.1, 0.7, 0.2]], dtype=torch.float)loss_f_none = nn.KLDivLoss(reduction='none')loss_f_mean = nn.KLDivLoss(reduction='mean')loss_f_bs_mean = nn.KLDivLoss(reduction='batchmean')loss_none = loss_f_none(inputs, target)loss_mean = loss_f_mean(inputs, target) #所有元素相加/6,6是所有元素的个数loss_bs_mean = loss_f_bs_mean(inputs, target) #所有元素相加/2,2是batchsize一共是两批次,即两批样本print("loss_none:\n{}\nloss_mean:\n{}\nloss_bs_mean:\n{}".format(loss_none, loss_mean, loss_bs_mean))# --------------------------------- compute by hand
flag = 0
# flag = 1
if flag:idx = 0loss_1 = target[idx, idx] * (torch.log(target[idx, idx]) - inputs[idx, idx])print("第一个元素loss:", loss_1)

nn.MarginRankingLoss

在这里插入图片描述
计算公式如上,y=-1 或 1
当y=-1时,希望x2>x1,那么就不产生loss
当y= 1 时,希望x1>x2,那么就不产生loss

nn.MarginRankingLoss(margin=0.0, size_average=None, reduce=None, reduction='mean')
'''
计算两个向量之间相似度,用于排序任务该方法计算两组数据之间的差异,返回n*n的一个loss矩阵margin:边界值,x1与x2之间的差异值
'''
# ---------------------------------------------- 10 Margin Ranking Loss --------------------------------------------
flag = 0
# flag = 1
if flag:x1 = torch.tensor([[1], [2], [3]], dtype=torch.float) #3*1x2 = torch.tensor([[2], [2], [2]], dtype=torch.float) #3*1target = torch.tensor([1, 1, -1], dtype=torch.float) #向量,也是1*3loss_f_none = nn.MarginRankingLoss(margin=0, reduction='none')loss = loss_f_none(x1, x2, target)print(loss) #输出为[[1,1,0], [0,0,0], [0,0,1]]# loss中第一行第一列的元素1是用x1的第1个元素[1]与x2的第1个元素[2]比较,此时y=1,loss=1# loss中第一行第二列的元素1是用x1的第1个元素[2]与x2的第2个元素[2]比较,此时y=1,loss=1# loss中第一行第三列的元素0是用x1的第1个元素[3]与x2的第3个元素[2]比较,此时y=-1,loss=0# loss中第二行第一列的元素0是用x1的第2个元素[2]与x2的第1个元素[2]比较,此时y=1,loss=0,当两个值相等时,不论y是多少,loss=0# 后面计算同理,y的值与x2是第几个有关,比如x2取第1个值,则y取第一个值;x2取第3个值,则y取第三个值。

nn.MultiLabelMarginLoss

在这里插入图片描述
1)分母是神经元的个数。
2)x[y[j]]-x[i]=标签所在的神经元的值-不是标签所在的神经元的值。
目的是为了使标签所在的神经元的输出比非标签所在的神经元的输出越来越大,这样loss才会等于0。

nn.MultiLabelMarginLoss(size_average=None, reduce=None, reduction='mean')
'''
多标签边界损失函数,注意是多标签 不是多分类!比如 4分类任务,样本x属于0类和3类,则标签为[0,3,-1-1] 而非[1,0,0,1]'''
# ---------------------------------------------- 11 Multi Label Margin Loss -----------------------------------------
flag = 0
# flag = 1
if flag:x = torch.tensor([[0.1, 0.2, 0.4, 0.8]]) #1*4,1是一批样本,四分类,分别对应第0类、第1类、第2类、第3类y = torch.tensor([[0, 3, -1, -1]], dtype=torch.long) #标签,设置第0类第3类,不足的地方用-1填充占位,注意类型必须是longloss_f = nn.MultiLabelMarginLoss(reduction='none')loss = loss_f(x, y)print(loss) # 输出0.8500# --------------------------------- compute by hand
flag = 0
# flag = 1
if flag:#标签所在的神经元是第0类和第3类,所以要计算第0类神经元的loss和第3类神经元的loss,需要各自减去不是标签的神经元x = x[0] #取出第1批样本#第0类神经元需要减去第1类、第2类神经元item_1 = (1-(x[0] - x[1])) + (1 - (x[0] - x[2]))    # [0]#第3类神经元需要减去第1类、第2类神经元item_2 = (1-(x[3] - x[1])) + (1 - (x[3] - x[2]))    # [3]loss_h = (item_1 + item_2) / x.shape[0] #x.shape[0]=4print(loss_h)

nn.SoftMarginLoss

在这里插入图片描述
分母是样本数(nelement() 统计 tensor (张量) 中元素的个数)。
y可取1 或-1

nn.SoftMarginLoss(size_average=None, reduce=None, reduction='mean')
'''
计算二分类的logistic 损失'''
# ---------------------------------------------- 12 SoftMargin Loss -----------------------------------------
flag = 0
# flag = 1
if flag:inputs = torch.tensor([[0.3, 0.7], [0.5, 0.5]]) # 2*2#2个样本,每个样本里2个神经元target = torch.tensor([[-1, 1], [1, -1]], dtype=torch.float) # 2*2loss_f = nn.SoftMarginLoss(reduction='none')loss = loss_f(inputs, target)print("SoftMargin: ", loss) # 2*2# --------------------------------- compute by hand
flag = 0
# flag = 1
if flag:idx = 0inputs_i = inputs[idx, idx]target_i = target[idx, idx]loss_h = np.log(1 + np.exp(-target_i * inputs_i))print(loss_h)

nn.MultiLabelSoftMarginLoss

在这里插入图片描述
(1)C是样本个数,取平均。i是神经元个数。
(2)标签y[i]只能是0,1。
(3)当i是标签神经元时,y[i]=1,只需要计算前一项,因为后一项1-y[i]=0。反之,当i不是标签神经元时,y[i]=0,只需要计算后一项,因为前一项为0。

nn.MultiLabelSoftMarginLoss(weight=None, size_average=None, reduce=None, reduction='mean')
'''
softMarginLoss多标签版本weight:各类别loss设置权值
'''
# ---------------------------------------------- 13 MultiLabel SoftMargin Loss -----------------------------------------
flag = 0
# flag = 1
if flag:inputs = torch.tensor([[0.3, 0.7, 0.8]]) #三分类任务target = torch.tensor([[0, 1, 1]], dtype=torch.float)#即属于1类也属于2类,不属于0类loss_f = nn.MultiLabelSoftMarginLoss(reduction='none')loss = loss_f(inputs, target)print("MultiLabel SoftMargin: ", loss) #输出0.5429# --------------------------------- compute by hand
flag = 0
# flag = 1
if flag:#第1个元素的标签为0,只需要计算后一项。i_0 = torch.log(torch.exp(-inputs[0, 0]) / (1 + torch.exp(-inputs[0, 0])))#第2个元素的标签为1,只需要计算前一项。i_1 = torch.log(1 / (1 + torch.exp(-inputs[0, 1])))#第3个元素的标签为1,只需要计算前一项。i_2 = torch.log(1 / (1 + torch.exp(-inputs[0, 2])))loss_h = (i_0 + i_1 + i_2) / -3print(loss_h) #输出0.5429

nn.MultiMarginLoss

在这里插入图片描述
在这里插入图片描述
x[y]是标签所在神经元的输出值,x[i]是非标签所在神经元的输出值。

nn.MultiMarginLoss(p=1, margin=1.0, weight=None, size_average=None, reduce=None, reduction='mean')
'''
计算多分类折页损失p可选1或2
margin 边界值
weight 各类别设置loss权值
'''
# ---------------------------------------------- 14 Multi Margin Loss -----------------------------------------
flag = 0
# flag = 1
if flag:x = torch.tensor([[0.1, 0.2, 0.7], [0.2, 0.5, 0.3]])#在本损失函数的公式设定中:#第一个标签1对应x中第一个样本第1个元素(从第0个元素开始数)0.2#第二个标签2对应x中第二个样本第2个元素(从第0个元素开始数)0.3y = torch.tensor([1, 2], dtype=torch.long) loss_f = nn.MultiMarginLoss(reduction='none')loss = loss_f(x, y)print("Multi Margin Loss: ", loss) #输出[0.8000, 0.7000]# --------------------------------- compute by hand
flag = 0
# flag = 1
if flag:x = x[0] #取出第一个样本 ,所以后面减去的神经元不能是x[1]margin = 1i_0 = margin - (x[1] - x[0])# i_1 = margin - (x[1] - x[1])i_2 = margin - (x[1] - x[2])loss_h = (i_0 + i_2) / x.shape[0] #shape类别数=3print(loss_h) #输出0.8000

nn.TripletMarginLoss

三元组定义为 希望通过学习之后使得,anchor与positive的距离比anchor到negative的距离小;这里放在人脸识别中则anchor是当前样本,positive 这个样本真实对应的人脸,negative其他人脸
在这里插入图片描述
在这里插入图片描述
第二个公式指的是用p范数,默认用2范数

nn.TripletMarginLoss(margin=1.0, p=2.0, eps=1e-06, swap=False, size_average=None, reduce=None, reduction='mean')
'''
计算三元组损失,常用于人脸验证p:范数的阶,默认2
margin边界值
'''
# ---------------------------------------------- 15 Triplet Margin Loss -----------------------------------------
flag = 0
# flag = 1
if flag:anchor = torch.tensor([[1.]])pos = torch.tensor([[2.]])neg = torch.tensor([[0.5]])loss_f = nn.TripletMarginLoss(margin=1.0, p=1)loss = loss_f(anchor, pos, neg)print("Triplet Margin Loss", loss) #(2-1)-(1-0.5)+1 = 1.5#输出1.5000# --------------------------------- compute by hand
flag = 0
# flag = 1
if flag:margin = 1a, p, n = anchor[0], pos[0], neg[0]d_ap = torch.abs(a-p)d_an = torch.abs(a-n)loss = d_ap - d_an + marginprint(loss)

nn.HingeEmbeddingLoss

在这里插入图片描述
▲表示margin。

nn.HingeEmbeddingLoss(margin=1.0, size_average=None, reduce=None, reduction='mean')
'''
计算两个输入的相似性,常用于非线性embedding和半监督学习输入x应为两个输入之差的绝对值
'''
# ---------------------------------------------- 16 Hinge Embedding Loss -----------------------------------------
flag = 0
# flag = 1
if flag:inputs = torch.tensor([[1., 0.8, 0.5]])target = torch.tensor([[1, 1, -1]])loss_f = nn.HingeEmbeddingLoss(margin=1, reduction='none')loss = loss_f(inputs, target)print("Hinge Embedding Loss", loss)#输出[1.0000, 0.8000, 0.5000]# --------------------------------- compute by hand
flag = 0
# flag = 1
if flag:margin = 1.loss = max(0, margin - inputs.numpy()[0, 2])print(loss)

nn.CosineEmbeddingLoss

在这里插入图片描述

nn.CosineEmbeddingLoss(margin=0.0, size_average=None, reduce=None, reduction='mean')
'''
利用余弦相似度计算两个输入相似性,利用cos是关注方向上的差异
margin 取值范围[-1,1] 推荐为[0,0.5]
'''
# ---------------------------------------------- 17 Cosine Embedding Loss -----------------------------------------
flag = 0
# flag = 1
if flag:x1 = torch.tensor([[0.3, 0.5, 0.7], [0.3, 0.5, 0.7]])x2 = torch.tensor([[0.1, 0.3, 0.5], [0.1, 0.3, 0.5]])target = torch.tensor([[1, -1]], dtype=torch.float)loss_f = nn.CosineEmbeddingLoss(margin=0., reduction='none')loss = loss_f(x1, x2, target)print("Cosine Embedding Loss", loss)# 输出[0.0167, 0.9833]# --------------------------------- compute by hand
flag = 0
# flag = 1
if flag:margin = 0.def cosine(a, b):numerator = torch.dot(a, b) # 分子是点积denominator = torch.norm(a, 2) * torch.norm(b, 2) #分母是模长相乘return float(numerator/denominator)l_1 = 1 - (cosine(x1[0], x2[0]))l_2 = max(0, cosine(x1[1], x2[1]))print(l_1, l_2)# 输出0.0167 0.9833

nn.CTCLoss

原理后续补充。

nn.CTCLoss(blank=0, reduction='mean', zero_infinity=False)
'''
计算CTC损失,解决时序类数据的分类 connectionist temporal classification
blank:blank label
zero_infinity:无穷大的值或梯度置0例如OCR中输入输出不确定的情况,怎么计算分类,就要用到这个
'''
# ---------------------------------------------- 18 CTC Loss -----------------------------------------
# flag = 0
flag = 1
if flag:T = 50      # Input sequence lengthC = 20      # Number of classes (including blank)N = 16      # Batch sizeS = 30      # Target sequence length of longest target in batchS_min = 10  # Minimum target length, for demonstration purposes# Initialize random batch of input vectors, for *size = (T,N,C)inputs = torch.randn(T, N, C).log_softmax(2).detach().requires_grad_()# Initialize random batch of targets (0 = blank, 1:C = classes)target = torch.randint(low=1, high=C, size=(N, S), dtype=torch.long)input_lengths = torch.full(size=(N,), fill_value=T, dtype=torch.long)target_lengths = torch.randint(low=S_min, high=S, size=(N,), dtype=torch.long)ctc_loss = nn.CTCLoss()loss = ctc_loss(inputs, target, input_lengths, target_lengths)print("CTC loss: ", loss) #输出7.5385

设置损失函数超参数

选择损失函数

优化器(共10个)

由损失函数得到loss,经由模型参数自动求导得到梯度,优化器根据优化策略根据梯度更新模型中可学习参数的值,使得loss往下降的方向走,即使模型输出接近真实标签。

梯度:是一个向量,方向为方向导数取得最大值的方向。故沿着梯度方向是增长最快的,那么沿着梯度负方向是下降最快的。

学习率:控制学习更新步伐,防止梯度爆炸,【通常设置学习率为0.01】

动量momentum:结合当前梯度和上一次更新信息,用于当前更新,可以看成一个惯性,减少迭代次数,加速迭代收敛。利用指数加权平均,时间序列中离得越近的参数参考性越大,权重越大。
指数加权平均:v_t=p*v_t-1 +(1-p)*θt
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
beta类似于记忆周期,beta越小,记忆周期越短。比如beta=0.8,到第20天左右就记不住了,而beta=0.98可以记忆到80天左右。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
上述图中蓝色图像明显先达到了minimum,但又不断迂回缓冲,这是因为 momentum较大,而且受到之前迭代的大梯度值的影响。
在这里插入图片描述
合适的动量之一,可以发现蓝色早于黄色先收敛到最小值。

# -*- coding:utf-8 -*-
"""
@file name  : momentum.py
@brief      : 梯度下降的动量 momentum
"""
import torch
import numpy as np
import torch.optim as optim
import matplotlib.pyplot as plt
torch.manual_seed(1)def exp_w_func(beta, time_list):return [(1 - beta) * np.power(beta, exp) for exp in time_list]
# np.power(beta, exp) 即 beta**expbeta = 0.9
num_point = 100
time_list = np.arange(num_point).tolist() #创建time list# ------------------------------ exponential weight ------------------------------
flag = 0
# flag = 1
if flag:weights = exp_w_func(beta, time_list)plt.plot(time_list, weights, '-ro', label="Beta: {}\ny = B^t * (1-B)".format(beta))plt.xlabel("time")plt.ylabel("weight")plt.legend()plt.title("exponentially weighted average")plt.show()print(np.sum(weights))# ------------------------------ multi weights ------------------------------
flag = 0
# flag = 1
if flag:beta_list = [0.98, 0.95, 0.9, 0.8]w_list = [exp_w_func(beta, time_list) for beta in beta_list]for i, w in enumerate(w_list):plt.plot(time_list, w, label="Beta: {}".format(beta_list[i]))plt.xlabel("time")plt.ylabel("weight")plt.legend()plt.show()# ------------------------------ SGD momentum ------------------------------
# flag = 0
flag = 1
if flag:def func(x):return torch.pow(2*x, 2)    # y = (2x)^2 = 4*x^2        dy/dx = 8xiteration = 100m = 0.9     # .9 .63 可以修改不同的momentum去看效果图lr_list = [0.01, 0.03]momentum_list = list()loss_rec = [[] for l in range(len(lr_list))]iter_rec = list()for i, lr in enumerate(lr_list):x = torch.tensor([2.], requires_grad=True)momentum = 0. if lr == 0.03 else mmomentum_list.append(momentum)optimizer = optim.SGD([x], lr=lr, momentum=momentum)for iter in range(iteration):y = func(x)y.backward()optimizer.step()optimizer.zero_grad()loss_rec[i].append(y.item())for i, loss_r in enumerate(loss_rec):plt.plot(range(len(loss_r)), loss_r, label="LR: {} M:{}".format(lr_list[i], momentum_list[i]))plt.legend()plt.xlabel('Iterations')plt.ylabel('Loss value')plt.show()
class Optimizer(object):def __init__(self,params,defaults):self.defaults=defaults  self.state=defaultdict(dict)self.param_groups=[]...param_groups=[{'params':param_groups}]
'''
defaults:优化器超参数
state:参数缓存,如momentum缓存
param_groups:管理的参数组,是一个list,其中是dict键值对,value才是参数内容
_step_count:记录更新次数,学习率调整中使用
'''
优化器最基本的5个方法
zero_grad()#清空所管理参数的梯度
#pytorch中张量梯度不会自动清零,每次反向传播时计算的梯度是叠加的
step() #执行一次更新,反向传播后根据优化方法更新参数
add_param_group()#添加参数组在优化器中,可以不同阶段设置不同参数组(如设置不同的学习率)
state_dict()#获取优化器当前状态信息字典
load_state_dict()#加载状态信息字典 可以用于重新从一个state_dict状态开始训练
# -*- coding: utf-8 -*-
"""
# @file name  : optimizer_methods.py
# @brief      : optimizer's methods
"""
import os
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
import torch
import torch.optim as optim
from tools.common_tools import set_seedset_seed(1)  # 设置随机种子weight = torch.randn((2, 2), requires_grad=True) # 创建2*2的weight
weight.grad = torch.ones((2, 2)) # 权值梯度设为1optimizer = optim.SGD([weight], lr=0.1)# ----------------------------------- step -----------------------------------
flag = 0
# flag = 1
if flag:print("weight before step:{}".format(weight.data))#输出[[0.6614, 0.2669], [0.0617, 0.6213]]optimizer.step()       print("weight after step:{}".format(weight.data)) #输出[[0.5614, 0.1669], [-0.0383, 0.5213]]#0.5614 = 0.6614 - weight.grad (1) * lr (0.1)=0.6614-0.1,其余同理减去0.1# ----------------------------------- zero_grad -----------------------------------
flag = 0
# flag = 1
if flag:print("weight before step:{}".format(weight.data))optimizer.step()        # 修改lr=1 0.1观察结果print("weight after step:{}".format(weight.data))print("weight in optimizer:{}\nweight in weight:{}\n".format(id(optimizer.param_groups[0]['params'][0]), id(weight))) #输出一致#优化器中管理参数的内存地址和weight的内存地址一致,节省内存空间print("weight.grad is {}\n".format(weight.grad)) #输出[[1., 1.], [1., 1.]]optimizer.zero_grad()print("after optimizer.zero_grad(), weight.grad is\n{}".format(weight.grad)) #输出[[0., 0.], [0., 0.]]# ----------------------------------- add_param_group -----------------------------------
flag = 0
# flag = 1
if flag:print("optimizer.param_groups is\n{}".format(optimizer.param_groups))w2 = torch.randn((3, 3), requires_grad=True)optimizer.add_param_group({"params": w2, 'lr': 0.0001}) #添加一组超参数print("optimizer.param_groups is\n{}".format(optimizer.param_groups)) #有两组超参数# ----------------------------------- state_dict -----------------------------------
flag = 0
# flag = 1
if flag:optimizer = optim.SGD([weight], lr=0.1, momentum=0.9)opt_state_dict = optimizer.state_dict()print("state_dict before step:\n", opt_state_dict)for i in range(10):optimizer.step()print("state_dict after step:\n", optimizer.state_dict())#打印可以发现state中的key就是这个param的id地址torch.save(optimizer.state_dict(), os.path.join(BASE_DIR, "optimizer_state_dict.pkl"))#保存这个状态# -----------------------------------load state_dict -----------------------------------
flag = 0
# flag = 1
if flag:
#使用场景:比如说之前已经训练了100次,接着它的结果继续训练optimizer = optim.SGD([weight], lr=0.1, momentum=0.9)state_dict = torch.load(os.path.join(BASE_DIR, "optimizer_state_dict.pkl"))print("state_dict before load state:\n", optimizer.state_dict())optimizer.load_state_dict(state_dict)print("state_dict after load state:\n", optimizer.state_dict())

optim.SGD 随机梯度下降法

注意事项:
pytroch中使用SGD十分需要注意的是,更新公式与其他框架略有不同!
pytorch中是这样的:
v=ρ∗v+g
p=p−lr∗v = p - lr∗ρ∗v - lr∗g
其他框架:
v=ρ∗v+lr∗g
p=p−v = p - ρ∗v - lr∗g
ρ是动量,v是速率,g是梯度,p是参数,其实差别就是在ρ∗v这一项,pytorch中将此项也乘了一个学习率。

torch.optim.SGD(params, lr=<required parameter>, momentum=0, dampening=0, weight_decay=0, nesterov=False)
'''
params(必须参数): 这是一个包含了需要优化的参数(张量)的迭代器,例如模型的参数 model.parameters()。lr(必须参数): 学习率(learning rate)。它是一个正数,控制每次参数更新的步长。较小的学习率会导致收敛较慢,较大的学习率可能导致震荡或无法收敛。momentum(默认值为 0): 动量(momentum)是一个用于加速 SGD 收敛的参数。它引入了上一步梯度的指数加权平均。通常设置在 0 到 1 之间。当 momentum 大于 0 时,算法在更新时会考虑之前的梯度,有助于加速收敛。weight_decay(默认值为 0): 权重衰减,也称为 L2 正则化项。它用于控制参数的幅度,以防止过拟合。通常设置为一个小的正数。nesterov(默认值为 False): 是否采用NAG。Nesterov 动量。当设置为 True 时,采用 Nesterov 动量更新规则。Nesterov 动量在梯度更新之前先进行一次预测,然后在计算梯度更新时使用这个预测。
'''

torch.optim.ASGD 随机平均梯度下降

torch.optim.ASGD(params, lr=0.01, lambd=0.0001, alpha=0.75, t0=1000000.0, weight_decay=0)
'''
功能:
ASGD也成为SAG,均表示随机平均梯度下降(Averaged Stochastic Gradient Descent),简单地说ASGD就是用空间换时间的一种SGD,详细可参看论文:http://riejohnson.com/rie/stograd_nips.pdf
参数:
params(iterable)- 参数组(参数组的概念请查看 3.1 优化器基类:Optimizer),优化器要优化的那些参数。
lr(float)- 初始学习率,可按需随着训练过程不断调整学习率。
lambd(float)- 衰减项,默认值1e-4。
alpha(float)- power for eta update ,默认值0.75。
t0(float)- point at which to start averaging,默认值1e6。
weight_decay(float)- 权值衰减系数,也就是L2正则项的系数。
'''

torch.optim.Rprop 弹性反向传播

torch.optim.Rprop(params, lr=0.01, etas=(0.5, 1.2), step_sizes=(1e-06, 50))
'''
功能:
实现Rprop优化方法(弹性反向传播),优化方法原文《Martin Riedmiller und Heinrich Braun: Rprop - A Fast Adaptive Learning Algorithm. Proceedings of the International Symposium on Computer and Information Science VII, 1992》
该优化方法适用于full-batch,不适用于mini-batch,因而在min-batch大行其道的时代里,很少见到。
'''

torch.optim.Adagrad 自适应学习率梯度下降法

torch.optim.Adagrad(params, lr=0.01, lr_decay=0, weight_decay=0, initial_accumulator_value=0)
'''
功能:
实现Adagrad优化方法(Adaptive Gradient),Adagrad是一种自适应优化方法,是自适应的为各个参数分配不同的学习率。这个学习率的变化,会受到梯度的大小和迭代次数的影响。梯度越大,学习率越小;梯度越小,学习率越大。缺点是训练后期,学习率过小,因为Adagrad累加之前所有的梯度平方作为分母。
详细公式请阅读:Adaptive Subgradient Methods for Online Learning and Stochastic Optimization
John Duchi, Elad Hazan, Yoram Singer; 12(Jul):2121−2159, 2011.(http://www.jmlr.org/papers/volume12/duchi11a/duchi11a.pdf)
'''

torch.optim.Adadelta:Adagrad的改进

torch.optim.Adadelta(params, lr=1.0, rho=0.9, eps=1e-06, weight_decay=0)
'''
功能:
实现Adadelta优化方法。Adadelta是Adagrad的改进。Adadelta分母中采用距离当前时间点比较近的累计项,这可以避免在训练后期,学习率过小。
详细公式请阅读:https://arxiv.org/pdf/1212.5701.pdf
'''

torch.optim.RMSprop:Adagrad的改进

torch.optim.RMSprop(params, lr=0.01, alpha=0.99, eps=1e-08, weight_decay=0, momentum=0, centered=False)
'''
功能:
实现RMSprop优化方法(Hinton提出),RMS是均方根(root meam square)的意思。RMSprop和Adadelta一样,也是对Adagrad的一种改进。RMSprop采用均方根作为分母,可缓解Adagrad学习率下降较快的问题。并且引入均方根,可以减少摆动,详细了解可读:http://www.cs.toronto.edu/~tijmen/csc321/slides/lecture_slides_lec6.pdf
'''

torch.optim.Adam(AMSGrad):RMSprop结合Momentum

torch.optim.Adam(params, lr=0.001, betas=(0.9, 0.999), eps=1e-08, weight_decay=0, amsgrad=False)
'''
功能:
实现Adam(Adaptive Moment Estimation))优化方法。Adam是一种自适应学习率的优化方法,Adam利用梯度的一阶矩估计和二阶矩估计动态的调整学习率。吴老师课上说过,Adam是结合了Momentum和RMSprop,并进行了偏差修正。
参数:
amsgrad- 是否采用AMSGrad优化方法,asmgrad优化方法是针对Adam的改进,通过添加额外的约束,使学习率始终为正值。(AMSGrad,ICLR-2018 Best-Pper之一,《On the convergence of Adam and Beyond》)。
详细了解Adam可阅读,Adam: A Method for Stochastic Optimization(https://arxiv.org/abs/1412.6980)。
'''

torch.optim.Adamax: Adam增加学习率上限

torch.optim.Adamax(params, lr=0.002, betas=(0.9, 0.999), eps=1e-08, weight_decay=0)
'''
功能:
实现Adamax优化方法。Adamax是对Adam增加了一个学习率上限的概念,所以也称之为Adamax。
详细了解可阅读,Adam: A Method for Stochastic Optimization(https://arxiv.org/abs/1412.6980)(没错,就是Adam论文中提出了Adamax)。
'''

torch.optim.SparseAdam:稀疏版Adam

torch.optim.SparseAdam(params, lr=0.001, betas=(0.9, 0.999), eps=1e-08)
'''
功能:
针对稀疏张量的一种“阉割版”Adam优化方法。
only moments that show up in the gradient get updated, and only those portions of the gradient get applied to the parameters
'''

torch.optim.LBFGS:BFGS的改进

torch.optim.LBFGS(params, lr=1, max_iter=20, max_eval=None, tolerance_grad=1e-05, tolerance_change=1e-09, history_size=100, line_search_fn=None)
'''
功能:
实现L-BFGS(Limited-memory Broyden–Fletcher–Goldfarb–Shanno)优化方法。L-BFGS属于拟牛顿算法。L-BFGS是对BFGS的改进,特点就是节省内存。
使用注意事项:
1.This optimizer doesn’t support per-parameter options and parameter groups (there can be only one).
Right now all parameters have to be on a single device. This will be improved in the future.(2018-10-07)
'''

优化算法

对于几种优化算法,具体选择原则:
经验:先Adam(自适应,训练更快,但精度不一定比SGD高),SGD(最多)

梯度下降法

当学习率learning rate==1时 :w_i+1=w_i -g(w_i)
w_i指第i次迭代时的参数,g(w_i)指的是它所对应的梯度。

下面的代码展示了如何发生梯度爆炸。
在这里插入图片描述
在这里插入图片描述
所以这就是引入学习率的重要性,此时LR可以控制更新步伐
梯度下降公式扩展成 w_i+1=w_i -LR*g(w_i)【通常设置学习率为0.01】

当LR设置成0.2时,明显发现loss是逐渐下降的。
在这里插入图片描述

# -*- coding:utf-8 -*-
"""
@file name  : learning_rate.py
@brief      : 梯度下降的学习率演示
"""
import torch
import numpy as np
import matplotlib.pyplot as plt
torch.manual_seed(1)def func(x_t):"""y = (2x)^2 = 4*x^2      dy/dx = 8x"""return torch.pow(2*x_t, 2)# init
x = torch.tensor([2.], requires_grad=True)# ------------------------------ plot data ------------------------------
flag = 0
# flag = 1
if flag:
#画出func所示的笛卡尔坐标系x-y 曲线图x_t = torch.linspace(-3, 3, 100)y = func(x_t)plt.plot(x_t.numpy(), y.numpy(), label="y = 4*x^2")plt.grid()plt.xlabel("x")plt.ylabel("y")plt.legend()plt.show()# ------------------------------ gradient descent ------------------------------
flag = 0
# flag = 1
if flag:iter_rec, loss_rec, x_rec = list(), list(), list()lr = 0.01    # /1. /.5 /.2 /.1 /.125max_iteration = 20   # /1. 4     /.5 4   /.2 20 200for i in range(max_iteration):y = func(x)y.backward()#求取到x的梯度print("Iter:{}, X:{:8}, X.grad:{:8}, loss:{:10}".format(i, x.detach().numpy()[0], x.grad.detach().numpy()[0], y.item()))x_rec.append(x.item())x.data.sub_(lr * x.grad)    # x -= lr * x.grad  数学表达式意义:  x = x - lr * x.grad    # x是一个张量0.5 0.2 0.1 0.125x.grad.zero_()#清0 防止累加iter_rec.append(i)loss_rec.append(y)plt.subplot(121).plot(iter_rec, loss_rec, '-ro')plt.xlabel("Iteration")plt.ylabel("Loss value")x_t = torch.linspace(-3, 3, 100)y = func(x_t)plt.subplot(122).plot(x_t.numpy(), y.numpy(), label="y = 4*x^2")plt.grid()y_rec = [func(torch.tensor(i)).item() for i in x_rec]plt.subplot(122).plot(x_rec, y_rec, '-ro')plt.legend()plt.show()
#造成梯度爆炸# ------------------------------ multi learning rate ------------------------------# flag = 0
flag = 1
if flag:iteration = 100num_lr = 10lr_min, lr_max = 0.01, 0.2  # .5 .3 .2lr_list = np.linspace(lr_min, lr_max, num=num_lr).tolist()loss_rec = [[] for l in range(len(lr_list))]iter_rec = list()for i, lr in enumerate(lr_list):x = torch.tensor([2.], requires_grad=True)for iter in range(iteration):y = func(x)y.backward()x.data.sub_(lr * x.grad)  # x.data -= x.gradx.grad.zero_()loss_rec[i].append(y.item())for i, loss_r in enumerate(loss_rec):plt.plot(range(len(loss_r)), loss_r, label="LR: {}".format(lr_list[i]))plt.legend()plt.xlabel('Iterations')plt.ylabel('Loss value')plt.show()

管理模型参数

管理多个参数组实现不同学习率

调整学习率

迭代训练

观察训练效果

绘制loss/accuracy曲线

用TensorBoard分析

模型应用

图像分类

图像分割

目标检测

对抗生成

循环网络

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/878637.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【多场景应用】基于杰发科技AC7840x的Mini LED背光驱动设计

应用场景&#xff1a; 在汽车应用中&#xff0c;Mini LED背光驱动设计主要用于仪表盘、中控屏和车载娱乐系统等显示屏。这项技术可以显著提升显示效果&#xff0c;提供更高的亮度、更深的黑色和更广的色域&#xff0c;使得图像更加生动逼真&#xff0c;尤其在强光和宽温度范围…

Redis 篇-深入了解查询缓存与缓存所带来的问题(读写不一致、缓存穿透、缓存雪崩、缓存击穿)

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 本章目录 1.0 什么是缓存 2.0 项目中具体如何添加缓存 3.0 添加缓存后所带来的问题 3.1 读写不一致问题 3.1.1 缓存更新策略 3.1.2 具体实现缓存与数据库的双写一致 3.2 缓存穿…

【日记】想见珍一面怎么就这么难(985 字)

正文 想见珍一面怎么就这么难…… 事故频发。昨天说考试时间跟机票时间冲突了&#xff0c;最后结果出来了&#xff0c;改签了&#xff0c;并且差价不补。我不干&#xff0c;他们也不干。因为上级行给我们行长施压&#xff0c;于是我们行长给我施压。最后要到了国庆之前拔智齿的…

华为 HCIP-Datacom H12-821 题库 (6)

有需要题库的可以看主页置顶 V群仅进行学习交流 1.转发表中 FLAG 字段中B 的含义是&#xff1f; A、可用路由 B、静态路由 C、黑洞路由 D、网关路由 答案&#xff1a;C 解析&#xff1a; 可用路由用U 表示&#xff0c;静态路由用 S 表示&#xff0c;黑洞路由用 B 表示&#x…

笔试,牛客.kotori和n皇后​,牛客.AOE还是单体

目录 牛客.kotori和n皇后​编辑 牛客.AOE还是单体 牛客.kotori和n皇后 想起来&#xff0c;我之前还写过n皇后的题&#xff0c;但是这个我开始只能想到暴力解法 判断是不是斜对角线&#xff0c;联想yxb和y-xb,假如在一条线上&#xff0c;那么他们的x和y会对应成比例&#xff0c…

【弱监督时间动作定位】Probabilistic Vision-Language Representation for WSTAL 论文阅读

Probabilistic Vision-Language Representation for Weakly Supervised Temporal Action Localization 论文阅读 Abstract1 Introduction2 RELATEDWORK2.1 Weakly Supervised Temporal Action Localization2.2 Vision Language Pre-training2.3 Probabilistic Representation 3…

RocketMQ高级特性四-消息过滤

目录 前言 Broker端过滤 定义与概述 消息过滤分类 原理机制 使用场景 优缺点 Java代码示例 - Tag过滤 Java代码示例 - SQL92过滤 客户端过滤 定义与概述 原理机制 使用场景 优缺点 Java代码示例 总结 前言 消息过滤是RocketMQ的一项高级特性&#xff0c;它允许…

常见HTTP状态码、APUD响应状态字及含义

目录 一、HTTP状态码 二、APDU指令码 一、HTTP状态码 HTTP状态&#xff08;HTTP Status Code&#xff09;是用以表示网页服务器超文本传输协议响应状态的3位数字代码。 关于HTTP状态码更加详细介绍推荐阅读&#xff1a; http://t.csdnimg.cn/qSJv6http://t.csdnimg.cn/qSJv…

光敏电阻传感器详解(STM32)

目录 一、介绍 二、传感器原理 1.光敏电阻传感器介绍 2.原理图 三、程序设计 main.c文件 ldr.h文件 ldr.c文件 四、实验效果 五、资料获取 项目分享 一、介绍 光敏电阻器是利用半导体的光电导效应制成的一种电阻值随入射光的强弱而改变的电阻器&#xff0c;又称为光…

基于树莓派的儿童音频播发器—Yoto

Raspberry Pi 的开发可能性使吸引人的、以儿童为中心的音频播放器得以成型 Yoto Player 为孩子们提供了拥有和控制的绝佳体验&#xff0c;同时不会增加屏幕时间。得益于 Raspberry Pi 以及我们认可的经销商提供的支持和专业知识&#xff0c;Yoto Player 在英国取得了成功。 Yo…

七款最佳的渗透测试工具(非常详细)零基础入门到精通,收藏这一篇就够了

渗透测试工具是模拟对计算机系统、网络或 Web 应用程序的网络攻击的软件应用程序&#xff0c;它们的作用是在实际攻击者之前发现安全漏洞。它们可以作为系统的压力测试&#xff0c;揭示哪些区域可能会受到真正的威胁。 本文我将介绍七款最佳的渗透测试工具。 1 Kali Linux K…

Maven入门:自动化构建工具的基本概念与配置

一、什么是Maven 目前无论使用IDEA还是Eclipse等其他IDE&#xff0c;使用里面 ANT 工具帮助我们进行编译&#xff0c;打包运行等工作。Apache基于ANT进行了升级&#xff0c;研发出了全新的自动化构建工具Maven。 Maven使用项目对象模型&#xff08;POM-Project Object Model&…

视频合并在线工具哪个好?好用的视频合并工具推荐

当我们手握一堆零散却各有千秋的视频片段时&#xff0c;是否曾幻想过它们能像魔法般合并成一部完整、流畅的故事&#xff1f; 别担心&#xff0c;今天咱们就来一场“视频合并大冒险”&#xff0c;揭秘几款视频合并软件手机免费工具&#xff0c;帮助你在指尖上实现创意无限的视…

四、配置三层交换实验组网

一、实验拓扑 二、实验目的 通过配置交换机&#xff0c;令不同vlan间的主机能够互相通信 三、实验步骤 SW12 <Huawei>undo terminal monitor Info: Current terminal monitor is off. <Huawei>system-view Enter system view, return user view with CtrlZ. [H…

EDIUS X 10.34.9631 视频剪辑软件 下载 包含安装说明

下载地址(资源制作整理不易&#xff0c;下载使用需付费&#xff0c;不能接受请勿浪费时间下载) 链接&#xff1a;https://pan.baidu.com/s/1P2wKxVcSx5WzAtHXCaAp5A?pwd227i 提取码&#xff1a;227i

【Linux网络】应用层协议HTTP(1)

&#x1f389;博主首页&#xff1a; 有趣的中国人 &#x1f389;专栏首页&#xff1a; Linux网络 &#x1f389;其它专栏&#xff1a; C初阶 | C进阶 | 初阶数据结构 小伙伴们大家好&#xff0c;本片文章将会讲解 应用层协议HTTP 的相关内容。 如果看到最后您觉得这篇文章写得…

「深入理解」HTML Meta标签:网页元信息的配置

「深入理解」HTML Meta标签&#xff1a;网页元信息的配置 HTML的<meta>元素用于提供关于HTML文档的元数据&#xff08;metadata&#xff09;&#xff0c;这些信息对于浏览器和其他处理HTML文档的应用程序来说是非常有用的&#xff0c;如&#xff1a;<base>、<li…

【网络安全】服务基础第一阶段——第九节:Windows系统管理基础---- Windows_AD域

目录 一、域与活动目录 1.1 工作组 1.2 域 1.2.1 域&#xff08;Domain&#xff09; 1.2.2 域控制器&#xff08;Domain Controller&#xff0c;DC&#xff09; 1.2.3 功能和角色 1.2.4 管理和监控 1.2 5 域结构 1.3 组织单元&#xff08;Organizational Unit&#xff…

集成电路学习:什么是IP知识产权

一、IP&#xff1a;知识产权 IP是Intellectual Property的缩写&#xff0c;即知识产权。知识产权是一种无形的财产权&#xff0c;也称智力成果权&#xff0c;它指的是通过智力创造性劳动所获得的成果&#xff0c;并且是由智力劳动者对成果依法享有的专有权利。这种权利包括人身…

性能优化:自动化处理系统设计

性能优化&#xff1a;自动化处理系统设计 前言需求分析系统设计1. 调度中心2. 任务执行器3. 错误处理机制4. 通知系统5. 报表生成器6. 日志记录器 技术实现结语 前言 在当今这个信息爆炸、技术日新月异的时代&#xff0c;企业面临着前所未有的挑战和机遇。随着业务量的不断增长…