可以做试题的网站阿里云手机网站建设
web/
2025/10/1 1:54:24/
文章来源:
可以做试题的网站,阿里云手机网站建设,优化设计七年级上册数学答案,广西壮族自治区皮肤病医院目录 一、损失函数是什么二、常见的损失函数2.1 nn.CrossEntropyLoss交叉熵损失函数2.1.1 交叉熵的概念2.2.2 交叉熵代码实现2.2.3 加权重损失 2.2 nn.NLLLoss2.2.1 代码实现 2.3 nn.BCELoss2.3.1 代码实现 2.4 nn.BCEWithLogitsLoss2.4.1 代码实现 三、优化器Optimizer3.1 什么… 目录 一、损失函数是什么二、常见的损失函数2.1 nn.CrossEntropyLoss交叉熵损失函数2.1.1 交叉熵的概念2.2.2 交叉熵代码实现2.2.3 加权重损失 2.2 nn.NLLLoss2.2.1 代码实现 2.3 nn.BCELoss2.3.1 代码实现 2.4 nn.BCEWithLogitsLoss2.4.1 代码实现 三、优化器Optimizer3.1 什么是优化器3.1.1梯度的概念 3.2 optimizer的属性3.3 optimizer的方法3.3.1 zero_grad()3.3.2 step()3.3.3 add_param_group()3.3.4 state_dict()3.3.5 load_state_dict() 3.3 梯度下降3.4 学习率3.5 多尺度学习率实验3.6 momentum动量3.6.1 指数加权平均3.6.2 加Momentum更新公式3.6.3 momentum实验 4.SGD优化器 四、常见的其他优化器 一、损失函数是什么 从下面的一元函数可以看出直线拟合的点和真实值之间存在误差这个误差就是损失函数。 损失函数计算一个样本的差异。 代价函数样本数据集所有损失的平均值。 目标函数代价函数Regularization(对模型的约束) Regularization为了防止模型过拟合需要添加该项对模型进行约束 一般用代价函数来表示模型的损失函数 二、常见的损失函数
2.1 nn.CrossEntropyLoss交叉熵损失函数 功能 nn.LogSoftmax() 与 nn.NLLLoss() 结合进行交叉熵计算 LogSoftmax将数据归一化到一个概率取值的范围 0~1 NLLLoss()使用概率值计算交叉熵 主要参数 • weight各类别的loss设置权值 • ignore_index忽略某个类别 • reduction 计算模式可为none/sum /mean none- 逐个元素计算 sum- 所有元素求和返回标量 mean- 加权平均返回标量 交叉熵损失函数继承的父类损失
class _Loss(Module):reduction: strdef __init__(self, size_averageNone, reduceNone, reduction: str mean) - None:super().__init__()if size_average is not None or reduce is not None:self.reduction: str _Reduction.legacy_get_string(size_average, reduce)else:self.reduction reduction2.1.1 交叉熵的概念
熵表示自信息的期望 自信息用于衡量单个事件的不确定性 右图表示信息熵当概率为0.5左右的时候信息熵最大。 P表示原始数据的概率分布Q表示模型输出的概率分布。 从公式可以看出优化交叉熵也就是优化相对熵因为H§是一个常数。
2.2.2 交叉熵代码实现
import torch
import torch.nn as nn
import torch.nn.functional as F
import numpy as np# fake data
inputs torch.tensor([[1, 2], [1, 3], [1, 3]], dtypetorch.float) # 设置输入数据两个神经元
target torch.tensor([0, 1, 1], dtypetorch.long) # 三个类别第一个样本类别为0第2,3个样本类别为1# ----------------------------------- CrossEntropy loss: reduction -----------------------------------# flag 0
flag 1
if flag:# def loss functionloss_f_none nn.CrossEntropyLoss(weightNone, reductionnone)loss_f_sum nn.CrossEntropyLoss(weightNone, reductionsum) # 将所有损失相加loss_f_mean nn.CrossEntropyLoss(weightNone, reductionmean) # 求损失的平均值# 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)# --------------------------------- 手算公式验证 只计算第一个样本的损失----------------------------------------
# flag 0
flag 1
if flag:idx 0 # 第一个样本input_1 inputs.detach().numpy()[idx] # 取第一个样本数据 [1, 2]target_1 target.numpy()[idx] # 取第一个样本的标签类别 [0]# 第一项x_class input_1[target_1]# 第二项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)输出结果 使用交叉熵损失计算和手动设计公式计算得到的结果相同。
2.2.3 加权重损失
代码实现 设计第一个样本的权重为1后两个样本的权重为2
# ----------------------------------- weight -----------------------------------
# flag 0
flag 1
if flag:# def loss functionweights torch.tensor([1, 2], dtypetorch.float)# weights torch.tensor([0.7, 0.3], dtypetorch.float)loss_f_none_w nn.CrossEntropyLoss(weightweights, reductionnone)loss_f_sum nn.CrossEntropyLoss(weightweights, reductionsum)loss_f_mean nn.CrossEntropyLoss(weightweights, reductionmean)# 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)
输出结果 注意在计算平均损失的时候不再是总损失/3个样本而是做了一个加权的求平均第一个样本的权值是1那就算1个样本第2,3个样本的权值为2所以算4个样本损失的平均值为1.821/50.3642。
2.2 nn.NLLLoss 功能实现负对数似然函数中的负号功能 主要参数 • weight各类别的loss设置权值 • ignore_index忽略某个类别 • reduction:计算模式可为none/sum/mean none-逐个元素计算 sum-所有元素求和返回标量 mean-加权平均返回标量 2.2.1 代码实现
flag 1
if flag:weights torch.tensor([1, 1], dtypetorch.float)loss_f_none_w nn.NLLLoss(weightweights, reductionnone)loss_f_sum nn.NLLLoss(weightweights, reductionsum)loss_f_mean nn.NLLLoss(weightweights, reductionmean)# 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(NLL Loss, loss_none_w, loss_sum, loss_mean)输出结果 该函数只是对输出结果进行添加符号处理
2.3 nn.BCELoss 功能二分类交叉熵,对每一个神经元一一计算loss 注意事项输入值取值在[0,1] 主要参数 • weight各类别的loss设置权值 • ignore_index忽略某个类别 • reduction 计算模式可为none/sum/mean none-逐个元素计算 sum-所有元素求和返回标量 mean-加权平均返回标量 2.3.1 代码实现
注意使用该函数如果输入的值不是0~1之间的数据需要添加sigmoid函数。
flag 1
if flag:inputs torch.tensor([[1, 2], [2, 2], [3, 4], [4, 5]], dtypetorch.float)target torch.tensor([[1, 0], [1, 0], [0, 1], [0, 1]], dtypetorch.float)target_bce target# 使用该函数一定要注意将输出值压缩到0~1之间使用sigmoid将输入值压缩到0~1之间inputs torch.sigmoid(inputs)weights torch.tensor([1, 1], dtypetorch.float)loss_f_none_w nn.BCELoss(weightweights, reductionnone)loss_f_sum nn.BCELoss(weightweights, reductionsum)loss_f_mean nn.BCELoss(weightweights, reductionmean)# 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)输出结果 对每一个神经元计算loss
2.4 nn.BCEWithLogitsLoss 功能结合Sigmoid与二分类交叉熵 注意事项使用该函数网络最后不加sigmoid函数 主要参数 • pos _weight 正样本的权值 • weight各类别的loss设置权值 • ignore_index忽略某个类别 • reduction 计算模式可为none/sum/mean none-逐个元素计算 sum-所有元素求和返回标量 mean-加权平均返回标量 2.4.1 代码实现
# ----------------------------------- 4 BCE with Logis Loss -----------------------------------
# flag 0
flag 1
if flag:inputs torch.tensor([[1, 2], [2, 2], [3, 4], [4, 5]], dtypetorch.float)target torch.tensor([[1, 0], [1, 0], [0, 1], [0, 1]], dtypetorch.float)target_bce target# inputs torch.sigmoid(inputs)weights torch.tensor([1, 1], dtypetorch.float)loss_f_none_w nn.BCEWithLogitsLoss(weightweights, reductionnone)loss_f_sum nn.BCEWithLogitsLoss(weightweights, reductionsum)loss_f_mean nn.BCEWithLogitsLoss(weightweights, reductionmean)# 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)输出结果
如果再使用sigmoid函数会导致损失函数发生变化如下
三、优化器Optimizer
3.1 什么是优化器
机器学习模型训练有以下几个步骤优化器是在哪一步开始使用呢 将数据输入到模型当中会得到一个output值将output值和target目标值放入到损失函数计算损失损失使用反向传播的方法求出训练过程中每一个参数的梯度优化器拿到梯度使用优化策略减少损失。
3.1.1梯度的概念 pytorch的优化器管理并更新模型中可学习参数的值使得模型输出更接近真实标签 导数函数在指定坐标轴上的变化率 方向导数指定方向上的变化率 梯度一个向量方向为方向导数取得最大值的方向 梯度下降朝着梯度的负方向取变化也就是变化最快的 3.2 optimizer的属性
基本属性 • defaults优化器超参数。 • state参数的缓存如momentum的缓存(前几次更新的梯度)。 • params_groups管理的参数组list类型中存储的字典类型。 • _step_count记录更新次数学习率调整中使用。
3.3 optimizer的方法
3.3.1 zero_grad()
作用清空所管理参数的梯度。 为什么使用该方法这是因为pytorch特性张量梯度不自动清零 代码实现
flag 1
if flag:print(weight before step:{}.format(weight.data))optimizer.step() # 修改lr1 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)))# 优化器当中存储的是参数变量的地址print(weight.grad is {}\n.format(weight.grad))optimizer.zero_grad()print(after optimizer.zero_grad(), weight.grad is\n{}.format(weight.grad))输出结果 通过输出可以看出优化器当中存储的是参数变量的地址不需要额外使用内存保存梯度
3.3.2 step()
作用执行一步更新 代码实现
import osBASE_DIR os.path.dirname(os.path.abspath(__file__))
import torch
import torch.optim as optim
from common_tools import set_seedset_seed(1) # 设置随机种子weight torch.randn((2, 2), requires_gradTrue)
weight.grad torch.ones((2, 2)) # 手动设置梯度为1optimizer optim.SGD([weight], lr1)
# optimizer optim.SGD([weight], lr0.1)# ----------------------------------- step -----------------------------------
# flag 0
flag 1
if flag:print(weight before step:{}.format(weight.data))optimizer.step() # 梯度下降方法 观察结果 输入-梯度输出print(weight after step:{}.format(weight.data))结果输出 当我们设置梯度为1学习率为1的时候输出结果输入数据-梯度 当我们设置梯度为1学习率为0.1的时候输出结果输入数据-梯度
3.3.3 add_param_group()
作用添加参数组 对于不同的组有不同的超参数设置例如一个深度学习模型我们对特征提取模块的学习率设置小一些让它更新慢一点在全连接层可以设置学习率大一些。 代码实现
flag 1
if flag:print(optimizer.param_groups is\n{}.format(optimizer.param_groups))w2 torch.randn((3, 3), requires_gradTrue)optimizer.add_param_group({params: w2, lr: 0.0001})print(optimizer.param_groups is\n{}.format(optimizer.param_groups))输出结果 将一个新的参数组
3.3.4 state_dict()
作用获取优化器当前状态信息字典 当我们训练需要中断的时候可以使用该方法将当前训练的参数保存下来。 代码实现
flag 1
if flag:optimizer optim.SGD([weight], lr0.1, momentum0.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())torch.save(optimizer.state_dict(), os.path.join(BASE_DIR, optimizer_state_dict.pkl)) # 将当前state_dict保存成为序列化信息输出结果 将10次step的结果保存在optimizer_state_dict.pkl当中同时会在当前文件夹生成一个新的文件。
3.3.5 load_state_dict()
作用加载状态信息字典 用于读取上一次训练所保存的参数 代码实现
flag 1
if flag:optimizer optim.SGD([weight], lr0.1, momentum0.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())输出结果
3.3 梯度下降
对y4 x 2 x^2 x2使用梯度下降的方法更新参数使其到达最低点发现在计算到第三次的时候y的值变的很大并没有减少参数反而变的更大。 代码实现
import torch
import numpy as np
import matplotlib.pyplot as plttorch.manual_seed(1)def func(x_t):y (2x)^2 4*x^2 dy/dx 8xreturn torch.pow(2 * x_t, 2) # 求平方# init
x torch.tensor([2.], requires_gradTrue)# ------------------------------ 绘制函数基本曲线图 ------------------------------
flag 0
# flag 1
if flag:x_t torch.linspace(-3, 3, 100)y func(x_t)plt.plot(x_t.numpy(), y.numpy(), labely 4*x^2)plt.grid()plt.xlabel(x)plt.ylabel(y)plt.legend()plt.show()# 横轴设为参数x纵轴设置为y# ------------------------------ gradient descent ------------------------------
# flag 0
flag 1
if flag:iter_rec, loss_rec, x_rec list(), list(), list() # 记录迭代次数和损失lr 1 # 学习率/1. /.5 /.2 /.1 /.125max_iteration 4 # 设置最大迭代次数for 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 - x.grad 数学表达式意义: x x - x.grad # 0.5 0.2 0.1 0.125x.grad.zero_()iter_rec.append(i)loss_rec.append(y.item())# plt.subplot(121).plot(iter_rec.detach().numpy(), loss_rec.detach().numpy(), -ro)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(), labely 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()输出结果 当学习率设置为1通过输出结果可以发现随着迭代次数的增加数值更新的步伐越大损失值越大。那么如何解决这个问题呢。 3.4 学习率
通过设置学习率可以控制每次梯度下降的更新步伐大小。 代码展示 输出结果 当学习率设置过小为0.01时10次迭代结果如下会发现需要迭代多长才能梯度下降到最优值
3.5 多尺度学习率实验
经过上次两次会发现学习率过大或者过小都不合适那么如何找到一个最优的学习率可以提高梯度下降的速率 使用多尺度学习率做测试选取学习率区间0.01~0.2在该区间划分10个等间距的学习率进行实验。
代码实现
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, numnum_lr).tolist() # 生成num_lr个等间距的数组loss_rec [[] for l in range(len(lr_list))]# iter_rec list()for i, lr in enumerate(lr_list):x torch.tensor([2.], requires_gradTrue)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, labelLR: {}.format(lr_list[i]))plt.legend()plt.xlabel(Iterations)plt.ylabel(Loss value)plt.show()实验结果 通过实验结果发现当学习率在0.136的时候此时会更快降低损失y的值更快到达最小值。 3.6 momentum动量 结合当前梯度与上一次更新信息用于当前更新 优化器中的momentum是指动量Momentum它是一种在优化算法中常用的技术用于加速参数的更新。动量是在每次更新参数时将之前的一次更新作为一部分权重加入到当前的更新中从而使得参数的更新更加平滑减少了震荡。 在优化过程中优化器会根据损失函数和模型参数计算梯度。但是由于模型参数可能存在多个局部最小值优化器可能会在损失函数曲面上跳跃式地移动导致参数更新剧烈甚至出现震荡。动量技术通过引入历史更新信息使得优化器能够更好地平滑地移动到最优解从而减少了震荡和过拟合的风险。 在PyTorch等深度学习框架中优化器通常会内置动量参数用户只需要在创建优化器时指定学习率和优化器类型框架会自动计算动量值并应用于优化过程。 3.6.1 指数加权平均
首先了解一下指数加权平均数学思想要求取当前时刻的平均值距离当前时刻越近的参数值参考价值越大所占的权重越大这个权重随着时间间隔的增大呈指数下降。 代码实现
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]
beta 0.9
num_point 100
time_list np.arange(num_point).tolist()
# ------------------------------ exponential weight ------------------------------
# flag 0
flag 1
if flag:weights exp_w_func(beta, time_list)plt.plot(time_list, weights, -ro, labelBeta: {}\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))实现结果 通过代码实现可以看出距离当前时刻越远它对当前时刻的平均值越小。 当设置多个beta值的实验结果如下
flag 1
if flag:beta_list [0.98, 0.95, 0.9, 0.8] #设置4中不同的beta 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, labelBeta: {}.format(beta_list[i]))plt.xlabel(time)plt.ylabel(weight)plt.legend()plt.show()通过实验可以看出beta 可以理解为记忆周期当beta值越小记忆周期越短beta0.8时当到达20天的时候就不再关注远期的一个记忆值beta值越大记忆周期也就越长。 3.6.2 加Momentum更新公式
添加momentum更新之后的公式不仅仅只考虑当前的梯度还要考虑上一次更新梯度乘以m的值以及上上次梯度* m 2 m^2 m2…距离当前时刻越远的值对当前的影响越小因为m是个小于1的数。
3.6.3 momentum实验
实验一设置momentum为0学习率分别为0.01和0.03时函数收敛速率。 代码
flag 1
if flag:def func(x):return torch.pow(2 * x, 2) # y (2x)^2 4*x^2 dy/dx 8xiteration 100m 0.0 # .9 .63lr_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_gradTrue)momentum 0. if lr 0.03 else mmomentum_list.append(momentum)optimizer optim.SGD([x], lrlr, momentummomentum)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, labelLR: {} M:{}.format(lr_list[i], momentum_list[i]))plt.legend()plt.xlabel(Iterations)plt.ylabel(Loss value)plt.show()实验结果 实验结果分析因为黄色部分学习率更高所以收敛的速率比较快。 实验二设置学习率0.01时momentum为0.9 实验结果如下 实验结果分析虽然0.01的学习率比较低但是添加momentum之后收敛速率增加为什么会出现波浪因为在收敛到最小值的时候仍然保留着之前的权重所以没法快速收敛到一个平稳值。 4.SGD优化器 • params管理的参数组 • lr初始学习率 • momentum动量系数贝塔 • weight_decayL2正则化系数 • nesterov是否采用NAG
四、常见的其他优化器
optim.SGD随机梯度下降法optim.Adagrad自适应学习率梯度下降法optim.RMSprop Adagrad的改进optim.Adadelta Adagrad的改进optim.AdamRMSprop结合Momentumoptim.AdamaxAdam增加学习率上限optim.SparseAdam稀疏版的Adamoptim.ASGD随机平均梯度下降optim.Rprop弹性反向传播optim.LBFGSBFGS的改进
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/84768.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!