Pytorch 随记 (看了书籍随手记录,无逻辑无重点所在)
在前向传播函数(forward)函数中,有意识的将输出变量都命名为x,是为了能让Python回收一些中间层的输出,从而节省内存。但并不是所有的中间结果都会被回收,有些变量虽然名字被覆盖,但其在反向传播时扔需要用到,此时Python的内存回收模块将通过检查引用计数,不会回收这一部分内存。
pytorch中实现的神经网络的绝大多数层layer 都继承于nn.Module,封装了可学习参数,并实现了forward函数,且专门针对GPU运算进行了CuDNN优化,其速度和性能十分优异。
网络中自定义的层都有对输入形状的假设:输入的不是单个数据,而是一个batch,若想输入一个数据,必须调用unsqueeze(0)函数,将数据伪装成batch_size= 1 的batch。
pytorch将深度学习中常用的优化方法全部封装在torch.optim中,设计灵活,方便扩展成自定义的优化方法。 所有的优化方法都是继承基类optim.Optimizer,并实现了自己的优化步骤。需重点掌握:优化方法的基本使用方法;如何对模型的不同部分设置不同的学习率;如何调整学习率。
nn.functional 模块的使用,nn中大多数layer在functional中都有一个与之相对应的函数。 nn.functional&nn.Module的主要区别是:后者实现的层是一个特殊的类,都是由classLayer(nn.Module)定义,会自动提取可学习的参数;而前者更像是一种纯函数,由 def function(input)定义。所以,对于不具备可学习参数的层(激活层。池化层等),用函数代替实现,这样可以不用放置在构造函数init中。有可学习参数的层为了方便实现,将参数单独拿出来,在构造函数中初始化为parameter(利用nn.Parameter())。
如果模型有可学习的参数,最好用nn.Module,否则nn.functional和nn.Module都可以使用,二者在性能上没有太大差异。
虽然pytorch中的nn.Module模块参数都采用了较合理的初始化策略,一般不用我们考虑,但当我们使用Parameter时,自定义初始化就显得尤为重要,因为t.Tensor()返回的是内存中的随机数,很可能会有极大值,这在实际训练网络中会造成溢出或梯度消失的现象。nn.init模块专门为初始化设计,实现了常用的初始化策略。
钩子技术,由于pytorch会自动舍弃图计算的中间结果,所以想要获取这些数值就需要使用钩子函数,包括Variable钩子和nn.Module钩子,用法相似。
1. hasattr(obj,name) # 判断obj中是否有name属性或name方法,返回布尔值
2. getattr(obj,name[,default]) # 获取obj的name属性或方法,如果存在就直接打印出对应属性,如果不存在就打印出默认值或直接报错;如果返回对象的方法,则返回的是方法的内存地址,如果要运行这个方法,就需要在命名后面加个(),eg:getattr(t,'run')()
3. setattr(obj,name,value) # 给obj的属性赋值,如果属性不存在,则先创建属性再赋值。 所以需要先使用hasattr判断属性存不存在,然后在给该属性赋值
这里都是杂记,相关的模块会在另起新篇详细记录。