PyTorch 问题汇总

记录一些自己遇到的有关 PyTroch 的问题。

关于Mask梯度的方法

  • 自己尝试过两种实现方式:
    • 模型 layer 使用自定义的 MaskedConv 等 layer 实现,layer中自带一个mask的tensor,在 init() 中定义 backward_hook(grad) ,并在其中执行 register_hook() 。之后只要改动 mask就好;
    • 不改动模型,在训练结束后手动添加 layer.mask,手动register_hook()

关于数组 Index

  • Pytorch 1.3之后如果要使用 Tensor_1[Tensor_2] 的写法,Tensor_2的dtype必须是torch.bool(以前可以是uint8),不然会疯狂报错。正确写法 Tensor_1[Tensor_2.bool()]
  • 此类错误不会给出traceback。手动开启traceback方法:
1
2
3
4
5
6
7
8
9
10
11
import traceback
import warnings
import sys

def warn_with_traceback(message, category, filename, lineno, file=None, line=None):

log = file if hasattr(file,'write') else sys.stderr
traceback.print_stack(file=log)
log.write(warnings.formatwarning(message, category, filename, lineno, line))

warnings.showwarning = warn_with_traceback

关于 backward

  • 需要一步内多次backward()的情况:loss.backward(retain_graph=True) 否则无法在之后再次 loss.backward()。注意此类型报错通常能以更高效的方式解决(?)

关于 apply(fn)

1
2
3
4
for module in self.children():
module.apply(fn)
fn(self)
return self

关于 tensor与numpy的转换

1
2
3
4
5
6
7
>>> a = torch.ones[5]
>>> a
tensor([1., 1., 1., 1., 1.])
>>> b = a.numpy()
>>> b[0] = 3
>>> a
tensor([3., 1., 1., 1., 1.])

两者指向同一地址。

对b进行改动时应使用inplace操作,否则b地址会被替换。

1
2
3
4
5
6
7
8
>>> c = numpy.zeros_like([5])
>>> b = c
>>> a
tensor([3., 1., 1., 1., 1.])
>>> b = a.numpy()
>>> b += (c - b)
>>> a
tensor([0., 0., 0., 0., 0.])
  • 需要注意的是,显卡上的tensor(device=GPU)需要取到cpu上才能转换为numpy A.cpu().numpy() 否则报错。
  • 还有一点是,注意维持其为同一个ndarray数组对象,否则仍然会替换地址(如 b = 1 则b不再和a共享地址)

关于 copy_(), clone(), detach(), = 的区别

  • 后两者复制地址,detach不复制梯度

  • 注意转换 A.cpu().detach().numpy() 所detach的是cpu上的临时tensor,不会对A (此时A的device是显卡) 造成任何影响,也不会对其他Tensor有影响。A.cpu() 是函数返回值,本身创造的临时tensor在创造完numpy数组后会被释放(大概吧)

    所以需要重新 register_buffer

    不需要,用 A.data.copy_(torch.as_tensor(A_np))

  • W.required_grad==True 的情况下不能使用 W.cpu().numpy() ,必须detach()


  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2019-2020 thiswinex
  • 访问人数: | 浏览次数:

请我喝奶茶~

支付宝
微信