两种方式都是把模型中参数的梯度设置为0。
当optimizer =optim.Optimizer(net.parameters())时,二者等效。其中Optimizer可以是Adam、SGD等优化器。
net.parameters()
其中:parameters意思是参数
在网络优化过程中,使用net.parameters传入优化器,对网络参数进行优化,网络开始训练时会随机初始化网络的参数,然后进行训练,也可根据设置,将网络参数设置为一个某一随机初始化开始学习,这样可能会加快网络的收敛。
网络中的parameters包含的参数有网络连接权重W和偏置bias
net.parameters使用过程:
首先定义网络
import torch
import torch.nn as nn
class Net(nn.Module):
def __init__(self,n_feature,n_hidden,n_output):
super(Net,self).__init__()#继承__init__功能
self.hidden1=nn.Linear(n_feature,n_hidden)
self.hidden2=nn.Linear(n_hidden,n_hidden)
self.hidden3=nn.Linear(n_hidden,n_output)
def forward(self,x):
x=torch.relu(self.hidden1(X))
x=torch.relu(self.hidden2(x))
x=self.hidden3(x)
return x
net=Net(2,5,3)
print(net)
#输出
#Net(
# (hidden1): Linear(in_features=2, out_features=5, bias=True)
# (hidden2): Linear(in_features=5, out_features=5, bias=True)
# (predict): Linear(in_features=5, out_features=3, bias=True)
# )
这样直接将网络参数输出是不可能的,会返回一个物理地址。
print(net.parameters())
#
如果想输出网络参数,需要调用list将其输出
paras=list(net.parameters())
for num,para in enumerate(paras):
print('number:',num)
print(para)
'''
number: 0
Parameter containing:
tensor([[ 0.2716, 0.2148],
[-0.2778, -0.6801],
[-0.2994, -0.1041],
[ 0.1952, 0.2283],
[ 0.3100, -0.2316]], requires_grad=True)
number: 1
Parameter containing:
tensor([-0.5341, -0.3627, -0.6704, 0.1555, 0.5890], requires_grad=True)
number: 2
Parameter containing:
tensor([[ 0.4079, 0.4126, 0.4069, -0.3596, 0.1664],
[ 0.2193, 0.3791, 0.0432, 0.3606, 0.0259],
[-0.1299, -0.3204, 0.0052, -0.2188, -0.0435],
[ 0.4316, 0.0585, 0.1447, 0.0377, -0.0123],
[-0.2324, -0.0413, -0.0764, 0.0903, 0.1902]], requires_grad=True)
number: 3
Parameter containing:
tensor([-0.3298, 0.2353, 0.0392, -0.4095, 0.3083], requires_grad=True)
number: 4
Parameter containing:
tensor([[ 0.2756, -0.2747, 0.2670, 0.3314, -0.3804],
[ 0.0831, -0.2045, -0.4173, -0.1978, -0.2467],
[-0.3439, 0.4270, 0.2299, -0.3743, 0.2392]], requires_grad=True)
number: 5
Parameter containing:
tensor([ 0.4458, -0.0684, 0.0096], requires_grad=True)
'''
requires_grad()
如果模型只在一块GPU上跑,则过程非常简单,只需要训练中途迭代model的parameters,然后改变各个param的requires_grad属性即可:
但如果模型是跑在多块GPU上,就要搞清楚pytorch是如何对同一个module对象进行分布式处理
pytorch将gpu_0上的模型进行复制,放到其他GPU上,可使用DataParallel类。
DataParallel类有一个数据成员:module,可获得该用于复制的basic module,通过改变该basic module的参数的requires_grad属性,即可达到模型在平行计算过程中,各个参数参与梯度回传迭代。
pytorch在每次前向传播过程中,都会将主GPU上的模型,分发给各个GPU上,所以,梯度更新只会在主GPU上,更新模型的requires_grad属性也只需要在主GPU上即可。