多分支下loss.backward()过程与原理

loss原理

概述

在PyTorch中,loss.backward() 是反向传播的核心函数,它负责计算模型参数相对于损失函数的梯度。这个过程是基于自动微分(Automatic Differentiation,简称autodiff)技术实现的,具体来说是采用了反向模式的自动微分(Reverse-Mode AD)。

自动微分原理:
(1) 前向传播:首先,模型通过前向传播计算输出值。在这个过程中,PyTorch 会记录计算图(Computation Graph),这个计算图记录了从输入到输出的每一步运算及其依赖关系。每个张量(Tensor)都有一个.grad_fn属性,指向一个函数,这个函数描述了如何计算这个张量关于其输入的梯度。(loss产生的过程会有一张记录计算图

(2) 反向传播:当调用 loss.backward() 时,PyTorch 开始反向遍历计算图。这个过程从损失函数开始,沿着图反向传播误差,计算每一个参与运算的张量关于损失的梯度。这是通过链式法则(Chain Rule)完成的,即将损失对某个中间变量的导数分解为其后续操作导数的乘积。(根据计算图反向传播

(3)梯度计算:在反向传播过程中,每个运算都会计算其输出关于输入的梯度,并将这个梯度累积到输入张量的.grad属性中(如果是标量损失,它没有.grad属性)。这意味着如果一个张量被多个路径使用,它的.grad属性会累积从所有路径来的梯度。(张量计算过程)

(4) 梯度累加与同步:在分布式训练中,如果启用了梯度同步(例如使用DataParallel或DistributedDataParallel),PyTorch还会在所有设备之间同步计算出的梯度,确保每个参数的梯度是所有设备上相应梯度的平均值。

(5)梯度裁剪与优化:在反向传播完成后,用户通常会执行梯度裁剪以避免梯度爆炸问题,随后使用优化器(如SGD, Adam等)来更新模型参数,即执行optimizer.step()。这一步实际上根据计算出的梯度和优化算法更新参数。(loss=0,更新参数

					loss.backward()
                    self.optimizer.step()
                    self.scheduler.step()
                    self.optimizer.zero_grad()

前向传播(Forward Pass)

在前向传播过程中,PyTorch 记录所有操作以构建计算图

y = x * 2
z = y.mean()
w = z + y

反向传播(Backward Pass)

当我们调用 loss.backward() 时,PyTorch 会从计算图中的输出节点开始,沿着图的边缘向后遍历,并计算梯度。这一过程包括以下步骤:

(1)计算梯度:
PyTorch 会计算每个张量相对于最终标量输出(如损失)的梯度。

(2)链式法则(Chain Rule):
通过链式法则,PyTorch 会将局部梯度乘积从输出层向输入层传播。

z.backward()

只会影响x,y,z

拓展

在多分支任务下loss会根据对应的计算过程图找到返回的路径

for i, data in enumerate(tqdm(trainloader)): exemplar_imgs, instance_imgs, regression_target, conf_target = data regression_target, conf_target = regression_target.cuda(), conf_target.cuda() pred_score, pred_regression = model(exemplar_imgs.cuda(), instance_imgs.cuda()) pred_conf = pred_score.reshape(-1, 2, config.anchor_num * config.score_size * config.score_size).permute(0, 2, 1) pred_offset = pred_regression.reshape(-1, 4, config.anchor_num * config.score_size * config.score_size).permute(0, 2, 1) cls_loss = rpn_cross_entropy_balance(pred_conf, conf_target, config.num_pos, config.num_neg, anchors, ohem_pos=config.ohem_pos, ohem_neg=config.ohem_neg) reg_loss = rpn_smoothL1(pred_offset, regression_target, conf_target, config.num_pos, ohem=config.ohem_reg) loss = cls_loss + config.lamb * reg_loss #分类权重和回归权重 optimizer.zero_grad()#梯度 loss.backward() torch.nn.utils.clip_grad_norm_(model.parameters(), config.clip)#config.clip=10 ,clip_grad_norm_梯度裁剪,防止梯度爆炸 optimizer.step() step = (epoch - 1) * len(trainloader) + i summary_writer.add_scalar('train/cls_loss', cls_loss.data, step) summary_writer.add_scalar('train/reg_loss', reg_loss.data, step) train_loss.append(loss.detach().cpu())#当前计算图中分离下来的,但是仍指向原变量的存放位置,requires_grad=false loss_temp_cls += cls_loss.detach().cpu().numpy() loss_temp_reg += reg_loss.detach().cpu().numpy() if (i + 1) % config.show_interval == 0: tqdm.write("[epoch %2d][iter %4d] cls_loss: %.4f, reg_loss: %.4f lr: %.2e" % (epoch, i, loss_temp_cls / config.show_interval, loss_temp_reg / config.show_interval, optimizer.param_groups[0]['lr'])) loss_temp_cls = 0 loss_temp_reg = 0这是什么意思?
最新发布
11-22
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值