pytorch学习杂记(二)

本文详细解释了深度学习模型训练中add和concat操作的区别,以及在YOLOv7框架中回归预测部分的loss计算过程,包括confidence,regression,objectness和classification的损失函数。
摘要由CSDN通过智能技术生成

在深度学习模型训练中 add 和 concat操作有什么区别?

add:逐元素按值相加
concat:按照指定的维度进行张量堆叠

  • torch.cat在行方向上堆叠:
    在这里插入图片描述
  • torch.cat在列方向上堆叠:
    在这里插入图片描述

ai = torch.arange(na, device=targets.device).float().view(na, 1).repeat(1, nt) 执行逻辑

  • torch.arange: 分配一个张量为左闭右开区间[0, na),默认是int类型, device参数可以将张量加载到指定的设备上
  • float: 将数据类型转换成float型
  • view(na, 1):view方法用于改变张量形状,而不改变数据。view(na, 1)表示由一维张量变为二维张量。第二维的大小为1
  • repeat(1, nt):表示在第二维的方向上重复nt次

targets = torch.cat((targets.repeat(na, 1, 1), ai[:, :, None]), 2) 的执行逻辑

  • targets.repeat(na, 1, 1) :targets 在行的方向上堆叠na次
  • ai[:, :, None]:用来扩展张量ai的维度,张量ai增加第三个维度,并且大小为1
  • torch.cat(…, 2):将两个张量沿着第三个维度拼接

torch.tensor(p[i].shape)[[3, 2, 3, 2]] 执行逻辑

  • p[i].shape:从p中找到索引为i的张量,并返回该张量的shape,用元组表示
  • torch.tensor(p[i].shape):将元组类型的元素转换成tensor类型
  • [[3,2,3,2]]:这是索引列表,返回索引指向的元素值

torch.max(r, 1. / r).max(2)[0] 执行逻辑

  • torch.max(r, 1. / r):

t = t[j] t的维度是[3, 42, 7] 的float张量 j是[3 , 42]的bool型张量,这是怎么过滤的?

j = torch.stack((torch.ones_like(j), j, k, l, m) 执行逻辑

  • torch.ones_like(j):创建一个与张量j形状相同的新张量,其中所有元素都是1。
  • (torch.ones_like(j), j, k, l, m):这是一个包含五个张量的元组。这些张量将被堆叠在一起。为了成功堆叠,所有张量的形状必须相同,除了堆叠的维度。

torch.cat([pxy, pwh], dim=-1)

-1表示最后一个维度

pair_wise_iou.shape[1]

获取张量pair_wise_iou 第二个维度的大小

F.one_hot(this_target[:, 1].to(torch.int64), self.nc)

将this_target[:, 1]上所有的元素值,用one-hot向量的形式表示,向量的维度为self.nc

unsqueeze(1)

第二个维度(索引为1)处添加一个大小为1的新维度。这通常用于增加张量的维度数。

先贴一段yolov7中回归预测值的代码

    def __call__(self, p, targets, imgs):  # predictions, targets, model   
        device = targets.device
        lcls, lbox, lobj = torch.zeros(1, device=device), torch.zeros(1, device=device), torch.zeros(1, device=device)
        bs, as_, gjs, gis, targets, anchors = self.build_targets(p, targets, imgs)
        pre_gen_gains = [torch.tensor(pp.shape, device=device)[[3, 2, 3, 2]] for pp in p] 
    

        # Losses

        for i, pi in enumerate(p):  # layer index, layer predictions
            b, a, gj, gi = bs[i], as_[i], gjs[i], gis[i]  # image, anchor, gridy, gridx
            # 置信度 gt和预测值的IOU
            tobj = torch.zeros_like(pi[..., 0], device=device)  # target obj

            n = b.shape[0]  # number of targets
            if n:
                ps = pi[b, a, gj, gi]  # prediction subset corresponding to targets

                # Regression
                grid = torch.stack([gi, gj], dim=1)
                pxy = ps[:, :2].sigmoid() * 2. - 0.5
                #pxy = ps[:, :2].sigmoid() * 3. - 1.
                pwh = (ps[:, 2:4].sigmoid() * 2) ** 2 * anchors[i]
                pbox = torch.cat((pxy, pwh), 1)  # predicted box
                selected_tbox = targets[i][:, 2:6] * pre_gen_gains[i]
                selected_tbox[:, :2] -= grid
                iou = bbox_iou(pbox.T, selected_tbox, x1y1x2y2=False, CIoU=True)  # CIOU重叠面积、中心点距离、宽高比同时加入了计算iou(prediction, target)
                lbox += (1.0 - iou).mean()  # iou loss

                # Objectness
                tobj[b, a, gj, gi] = (1.0 - self.gr) + self.gr * iou.detach().clamp(0).type(tobj.dtype)  # iou ratio当作置信度

                # Classification
                selected_tcls = targets[i][:, 1].long()
                if self.nc > 1:  # cls loss (only if multiple classes)
                    t = torch.full_like(ps[:, 5:], self.cn, device=device)  # targets
                    t[range(n), selected_tcls] = self.cp#onehot一下
                    lcls += self.BCEcls(ps[:, 5:], t)  # BCE

                # Append targets to text file
                # with open('targets.txt', 'a') as file:
                #     [file.write('%11.5g ' * 4 % tuple(x) + '\n') for x in torch.cat((txy[i], twh[i]), 1)]

            obji = self.BCEobj(pi[..., 4], tobj)#大部分都是背景
            lobj += obji * self.balance[i]  # obj loss
            if self.autobalance:
                self.balance[i] = self.balance[i] * 0.9999 + 0.0001 / obji.detach().item()

        if self.autobalance:
            self.balance = [x / self.balance[self.ssi] for x in self.balance]
        lbox *= self.hyp['box']
        lobj *= self.hyp['obj']
        lcls *= self.hyp['cls']
        bs = tobj.shape[0]  # batch size

        loss = lbox + lobj + lcls
        return loss * bs, torch.cat((lbox, lobj, lcls, loss)).detach()

__call__方法的使用,允许一个对象的实例像函数一样被调用,传入参数可以直接被调用,示例如下:

class YOLOv7Predictor:
    def __init__(self, model):
        self.model = model
    def __call__(self, x):
        # 在这里实现模型的预测逻辑
        return self.model.predict(x)
# 假设我们有一个已经加载好的模型
model = ...  # 加载YOLOv7模型

# 创建一个YOLOv7Predictor的实例
predictor = YOLOv7Predictor(model)

# 现在我们可以像调用函数一样调用predictor实例
# 假设x是我们要进行预测的数据
x = ...  # 输入数据
predictions = predictor(x)  # 调用__call__方法进行预测
  • 9
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值