python 读不懂的代码问题汇总1

Q1:

解惑(一) ----- super(XXX, self).__init__()到底是代表什么含义_奋斗の博客的博客-CSDN博客

class LocalCamNet(nn.Module):
    def __init__(self, args=None):
        super(LocalCamNet, self).__init__()

super(Net, self).__init__()指首先找到Net的父类(nn.Module),然后把类Net的对象self转换为类Module的对象,在子类init时会调用父类的_init_()

回过头来看看我们的我们最上面的代码,Net类继承nn.Module,super(Net, self).__init__()就是对继承自父类nn.Module的属性进行初始化。而且是用nn.Module的初始化方法来初始化继承的属性。

Q2:

if logit.dim() == 1:
    logit = logit.unsqueeze(0)

unsqueeze()在对应维度上增加一维,示例实验,可以看到示例输出,维度数确实增加了。

output = torch.tensor([2.,3.])
print (output)
dim = output.dim()
print(dim)
if output.dim() == 1:
    output = output.unsqueeze(0)
    print (output)
    dim = output.dim()
    print(dim)
tensor([2., 3.])
1
tensor([[2., 3.]])
2
tensor([[2., 3.],
        [4., 5.]])
2
tensor([[[2., 3.]],

        [[4., 5.]]])
3

Q3:

/root/anaconda3/envs/cpcnn/lib/python3.8/site-packages/torch/nn/functional.py:3722: UserWarning: nn.functional.upsample is deprecated. Use nn.functional.interpolate instead.
  warnings.warn("nn.functional.upsample is deprecated. Use nn.functional.interpolate instead.")

示例代码

import torch
import torch.nn as nn
import torch.nn.functional as F
# input = torch.tensor([[1.,1.],[2.,2.]])
x = torch.arange(1, 17, dtype=torch.float32).view(1,1,4,4)
y = torch.arange(1, 5, dtype=torch.float32).view(1,1,2,2)
print(y)
_, _, H, W = x.size()
m = F.upsample(y,size=(H, W), mode='bilinear', align_corners=True)
print (m)

n = F.interpolate(y,size=[H,W],mode='bilinear', align_corners=True)
print(n)

upsample 已经由interpolate替换,可以直接替换着写,得到的结果是一致的,参数的含义,upsample(input, size, scale_factor, mode, align_corners)

input:需要上采样的输入

size:上采样后的大小

scale_factor:空间大小的乘数。如果它是元组,则必须匹配输入大小。

mode:nearest 邻近  linear  线性  bilinear 双线性

align_corners:输入和输出tensor的角像素对齐,保留这些像素的值,默认Flase。

tensor([[[[1., 2.],
          [3., 4.]]]])
tensor([[[[1.0000, 1.3333, 1.6667, 2.0000],
          [1.6667, 2.0000, 2.3333, 2.6667],
          [2.3333, 2.6667, 3.0000, 3.3333],
          [3.0000, 3.3333, 3.6667, 4.0000]]]])
tensor([[[[1.0000, 1.3333, 1.6667, 2.0000],
          [1.6667, 2.0000, 2.3333, 2.6667],
          [2.3333, 2.6667, 3.0000, 3.3333],
          [3.0000, 3.3333, 3.6667, 4.0000]]]])

Q4:

 arange()  主要是用于生成数组

2.1 语法
numpy.arange(start, stop, step, dtype = None)

在给定间隔内返回均匀间隔的值。

值在半开区间 [开始,停止]内生成(换句话说,包括开始但不包括停止的区间),返回的是 ndarray 。

2.2 参数:
start —— 开始位置,数字,可选项,默认起始值为0
stop —— 停止位置,数字
step —— 步长,数字,可选项, 默认步长为1,如果指定了step,则还必须给出start。
dtype —— 输出数组的类型。 如果未给出dtype,则从其他输入参数推断数据类型。

Q5:

.detach() .clone

【python基础】PyTorch中clone()、detach()_Clark-dj的博客-CSDN博客_.clone().detach()

.detach()

Returns a new Tensor, detached from the current graph. The result will never require gradient.

即返回一个和源张量同shape、dtype和device的张量,与源张量共享数据内存,但不提供梯度计算。

操作后的tensor与原始tensor共享数据内存,当原始tensor在计算图中数值发生反向传播等更新之后,detach()的tensor值也会发生改变。

input_B = output_A.detach()

detach操作在共享数据内存的脱离计算图,所以常用在神经网络中仅要利用张量数值,而不需要追踪导数的场景下。

.clone()

返回一个和源张量同shape、dtype和device的张量,与源张量不共享数据内存,但提供梯度的回溯。

clone操作在一定程度上可以视为是一个identity-mapping函数。clone作为一个中间variable,会将梯度传给源张量进行叠加。张量数据非共享

clone操作在不共享数据内存的同时支持梯度回溯,所以常用在神经网络中某个单元需要重复使用的场景下。

⭐: 在pytorch中不可直接使用id相等来判断tensor在共享内存,这是必要条件,因为也许底层共享数据内存,但是仍是新的tensor,比如detach(),如果打印id就会不同,但其共享内存。

一起使用 .clone().detach()

clone实现非数据共享,detach不追踪梯度,clone和detach一起使用可以实现只做简单的数据复制,既不数据共享,也不对梯度共享,从此两个张量无关联。

Q6:

GAP (global average pooling)

全局平均池化其实就是对每一个通道图所有像素值求平均值,然后得到一个新的1 * 1的通道图。

没有现成的包可以调用,但可以利用自适应平均池化/自适应最大池化来实现。

nn.AdaptiveAvgPool2d(1)
nn.AdaptiveMaxPool2d(1)

Q7:

简单的python语法,名为“list”的列表末尾添加新的对象a。

list.append(a)

Q8:

model.eval() 模型预测模式

会将一些加了Dropout的层和batch normalization的层恢复。 测试时dropout和batch normalization是没有意义的。

Q9: 

参考python 中 __call__简单介绍_阿常呓语的博客-CSDN博客

python 中__call__。这是个很有趣的用法,是用于class的定义中。我们在定义类型的时候实现了__call__函数,这个类就变成了可以调用的。也就是说在类实现后,可以直接使用 示例对象() 来调用__call__方法。如一下例子,其实call_test(),和call_test.__call__()实现的功能一样。

 
class TestCall(object):
    def __init__(self, name):
        self.name = name
 
    def __call__(self, *args, **kwargs):
        print("self.name: %s. " % self.name, end='   ')
        print('__call__()  is  running ')
 
 
if __name__ == '__main__':
    call_test = TestCall(name='xiaoming')
    call_test()  # call_test.__call__()
 
    call_test.__call__()
 
 
 
self.name: xiaoming.    __call__()  is  running 
self.name: xiaoming.    __call__()  is  running 

Q10:

torch.argmax(input, dim=0, keepdim=False)

上述代码意思是,返回input中第0维最大值的索引,dim=-1,则是返回最后一维的索引。

Q11:

numpy.squeeze(a,axis = None) 

从矩阵中,去掉维度为1的维数。例如下面例子。

x = torch.arange(1, 17, dtype=torch.float32).view(4,4,1,1)
dim=x.dim()
print(x)
print(dim)

y= x.squeeze()
dim=y.dim()
print(y)
print(dim)
tensor([[[[ 1.]],

         [[ 2.]],

         [[ 3.]],

         [[ 4.]]],


        [[[ 5.]],

         [[ 6.]],

         [[ 7.]],

         [[ 8.]]],


        [[[ 9.]],

         [[10.]],

         [[11.]],

         [[12.]]],


        [[[13.]],

         [[14.]],

         [[15.]],

         [[16.]]]])
4
tensor([[ 1.,  2.,  3.,  4.],
        [ 5.,  6.,  7.,  8.],
        [ 9., 10., 11., 12.],
        [13., 14., 15., 16.]])
2

Q12:

register_hook的使用。使用时register_hook(),括号中必须是一个函数。看到的是grad_cam中的代码

    def save_gradient(self, grad):
        self.gradients.append(grad)

    def __call__(self, x):
        outputs = []
        self.gradients = []
        # for name, module in self.model._modules.items():
        for name, module in self.feature_extractor._modules.items():
            x = module(x)
            if name in self.target_layers:
                x.register_hook(self.save_gradient)
                outputs += [x]
        return outputs, x

PyTorch反向传播时默认只保存叶子结点的梯度,非叶子节点的梯度不被保存,这样设计是为了节省内存,如果你想查看中间变量的梯度的话,使用register_hook

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值