PyTorch
backward
pytorch学习笔记(十三):backward过程的底层实现解析
基于PyTorch的深度学习入门教程(七)——PyTorch重点综合实践
『PyTorch』第五弹_深入理解autograd_上:Variable属性方法
backward只能被应用在一个标量上,也就是一个一维tensor,或者传入跟变量相关的梯度。
在反向传播过程中非叶子节点的导数计算完之后即被清空。只有叶子节点的梯度继续保留。
对于继承自nn.Module的某一网络net或网络层,定义好后,发现默认情况下,net.paramters的requires_grad是True的,这跟普通的Variable张量不同。
backward()里面的一个参数retain_variables,这个参数默认是False,也就是反向传播之后这个计算图的内存会被释放,这样你需要再次执行backward的话就需要再次执行一遍图,执行backward需要的tensor(目的是重新建立高级节点,而不是复用之前的,你可以发现它们前后的地址都不一样,可以用id显示内存地址),然后才能再次执行backward。或者执行的时候参数设置为retain_variables=True,这样可以再执行一次backward。执行的时候要切记梯度重新设置为0,因为梯度会累加。
tensor.max()不是高级节点。
实际上高级节点在创建(不是复用)时,会缓存用于输入的低级节点的信息(值,用于梯度计算)(图上的节点是依赖buffer记录来完成反向传播),但是这些buffer在backward之后会被清空(推测是节省内存),而这个buffer实际也体现了上面说的动态图的”动态”过程,之后继续进行反向传播但需要的数据被清空,则会报错。我们上面过程分别从:保留数据不被删除&重建数据两个角度实现了多次backward过程。
m = v(t.FloatTensor([[2, 3]]), requires_grad=True) # requires_grad表示需要记住梯度,即叶节点。
m.grad.data.zero_() # 梯度清除
hook
pytorch学习笔记(七):pytorch hook 和 关于pytorch backward过程的理解
PyTorch中view()、squeeze()、unsqueeze()、torch.max()
pytorch使用view()在不改变张量数据的情况下随意改变张量的大小和形状
网络搭建
class Net(torch.nn.Module)
利用torch.nn.Sequential()容器进行快速搭建,模型的各层被顺序添加到容器中。缺点是每层的编号是默认的阿拉伯数字,不易区分。
torch.nn.Sequential(
torch.nn.Conv2d(3, 32, 3, 1, 1),
torch.nn.ReLU())
对第二种方法的改进:通过add_module()添加每一层,并且为每一层增加了一个单独的名字。
self.conv=torch.nn.Sequential()
self.conv.add_module("conv1",torch.nn.Conv2d(3, 32, 3, 1, 1))
第三种方法的另外一种写法,通过字典的形式添加每一层,并且设置单独的层名称。
self.conv = torch.nn.Sequential(
OrderedDict(
[
("conv1", torch.nn.Conv2d(3, 32, 3, 1, 1)),
("relu1", torch.nn.ReLU()),
("pool", torch.nn.MaxPool2d(2))
]
))
和gluon不一样,神经网络的参数在神经网络层中直接就初始化了。所以不需要单独初始化模型参数。当然,我们也可以按照自己需求对参数初始化,如下所示。
对某一层初始化:
self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3)
init.xavier_uniform(self.conv1.weight)
init.constant(self.conv1.bias, 0.1)
对整个网络参数初始化:
def weights_init(m):
if isinstance(m, nn.Conv2d):
xavier(m.weight.data)
xavier(m.bias.data)
net = Net()
net.apply(weights_init) # apply函数会递归地搜索网络内的所有module并把参数表示的函数应用到所有的module上。
loss function
持久化
网络、网络参数持久化:
torch.save(net1, 'net.pkl') # 保存整个网络
torch.save(net1.state_dict(), 'net_params.pkl') # 只保存网络中的参数 (速度快, 占内存少)
# restore entire net1 to net2
net2 = torch.load('net.pkl')
# 新建 net3
net3 = torch.nn.Sequential(
torch.nn.Linear(1, 10),
torch.nn.ReLU(),
torch.nn.Linear(10, 1)
)
# 将保存的参数复制到 net3
net3.load_state_dict(torch.load('net_params.pkl'))
数据集生成,batch数据读取
TensorDataset、DataLoader
import torch.utils.data as Data
torch_dataset = Data.TensorDataset(data_tensor=x, target_tensor=y) # 转换成torch能识别的Dataset
loader = Data.DataLoader(
dataset=torch_dataset, # torch TensorDataset format
batch_size=BATCH_SIZE, # mini batch size
shuffle=True, # 要不要打乱数据 (打乱比较好)
num_workers=2, # 多线程来读数据
) # 把dataset放入DataLoader中
for step, (batch_x, batch_y) in enumerate(loader): # 每一步loader释放一小批数据用来学习