当前位置:   article > 正文

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

python代码看不懂

Q1:

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

  1. class LocalCamNet(nn.Module):
  2.     def __init__(self, args=None):
  3.         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:

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

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

  1. output = torch.tensor([2.,3.])
  2. print (output)
  3. dim = output.dim()
  4. print(dim)
  5. if output.dim() == 1:
  6. output = output.unsqueeze(0)
  7. print (output)
  8. dim = output.dim()
  9. print(dim)
  1. tensor([2., 3.])
  2. 1
  3. tensor([[2., 3.]])
  4. 2
  5. tensor([[2., 3.],
  6. [4., 5.]])
  7. 2
  8. tensor([[[2., 3.]],
  9. [[4., 5.]]])
  10. 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.")

示例代码

  1. import torch
  2. import torch.nn as nn
  3. import torch.nn.functional as F
  4. # input = torch.tensor([[1.,1.],[2.,2.]])
  5. x = torch.arange(1, 17, dtype=torch.float32).view(1,1,4,4)
  6. y = torch.arange(1, 5, dtype=torch.float32).view(1,1,2,2)
  7. print(y)
  8. _, _, H, W = x.size()
  9. m = F.upsample(y,size=(H, W), mode='bilinear', align_corners=True)
  10. print (m)
  11. n = F.interpolate(y,size=[H,W],mode='bilinear', align_corners=True)
  12. print(n)

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

input:需要上采样的输入

size:上采样后的大小

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

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

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

  1. tensor([[[[1., 2.],
  2. [3., 4.]]]])
  3. tensor([[[[1.0000, 1.3333, 1.6667, 2.0000],
  4. [1.6667, 2.0000, 2.3333, 2.6667],
  5. [2.3333, 2.6667, 3.0000, 3.3333],
  6. [3.0000, 3.3333, 3.6667, 4.0000]]]])
  7. tensor([[[[1.0000, 1.3333, 1.6667, 2.0000],
  8. [1.6667, 2.0000, 2.3333, 2.6667],
  9. [2.3333, 2.6667, 3.0000, 3.3333],
  10. [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的通道图。

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

  1. nn.AdaptiveAvgPool2d(1)
  2. 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__()实现的功能一样。

  1. class TestCall(object):
  2. def __init__(self, name):
  3. self.name = name
  4. def __call__(self, *args, **kwargs):
  5. print("self.name: %s. " % self.name, end=' ')
  6. print('__call__() is running ')
  7. if __name__ == '__main__':
  8. call_test = TestCall(name='xiaoming')
  9. call_test() # call_test.__call__()
  10. call_test.__call__()
  1. self.name: xiaoming. __call__() is running
  2. 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的维数。例如下面例子。

  1. x = torch.arange(1, 17, dtype=torch.float32).view(4,4,1,1)
  2. dim=x.dim()
  3. print(x)
  4. print(dim)
  5. y= x.squeeze()
  6. dim=y.dim()
  7. print(y)
  8. print(dim)
  1. tensor([[[[ 1.]],
  2. [[ 2.]],
  3. [[ 3.]],
  4. [[ 4.]]],
  5. [[[ 5.]],
  6. [[ 6.]],
  7. [[ 7.]],
  8. [[ 8.]]],
  9. [[[ 9.]],
  10. [[10.]],
  11. [[11.]],
  12. [[12.]]],
  13. [[[13.]],
  14. [[14.]],
  15. [[15.]],
  16. [[16.]]]])
  17. 4
  18. tensor([[ 1., 2., 3., 4.],
  19. [ 5., 6., 7., 8.],
  20. [ 9., 10., 11., 12.],
  21. [13., 14., 15., 16.]])
  22. 2

Q12:

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

  1. def save_gradient(self, grad):
  2. self.gradients.append(grad)
  3. def __call__(self, x):
  4. outputs = []
  5. self.gradients = []
  6. # for name, module in self.model._modules.items():
  7. for name, module in self.feature_extractor._modules.items():
  8. x = module(x)
  9. if name in self.target_layers:
  10. x.register_hook(self.save_gradient)
  11. outputs += [x]
  12. return outputs, x

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/375460
推荐阅读
相关标签
  

闽ICP备14008679号