pytroch基本概念
参考书目是来自中国工信出版社集团和电子工业出版社的《深度学习之PyTorch实战计算机视觉》,作者是唐进民,有兴趣的话请精读原版。
PyTorch是美国互联网巨头Facebook在深度学习框架Torch的基础上使用Python重写的一个全新的框架,更新世Numpy的替代产物,不仅继承了Numpy的众多优点,还支持GPUs计算,在计算效率上比NumPy有更明显的优势;不仅如此,PyTorch还有许多高级功能,比如拥有丰富的API,可以快速完成深度神经网络的搭建和训练。
PyTorch中的Tensor
Tensor在PyTorch中负责存储基本数据,Pytorch针对Tensor体重了丰富的函数和方法。
Tensor中的数据类型
- torch.FloatTensor:用于生成数据类型为浮点型的Tensor
input:列表或者维度值
1 2
| A = torch.FloatTensor(2,3) B = torch.FloatTensor([2,3,4,5])
|
- torch.IntTensor:用于生成数据类型为整形的Tensor
input:列表或者维度值
1 2
| A = torch.IntTensor(2,3) B = torch.IntTensor([2,3,4,5])
|
- torch.rand:用于生成数据类型为浮点型且维度指定的随机Tensor,和在Numpy中使用numpy.rand生成随机数的方法类似,随机生成的浮点数据在0~1区间均匀分布。
input:维度值
- torch.randn:用于生成数据类型为浮点型且维度指定的随机Tensor,和在Numpy中使用numpy.randn生成随机数的方法类似,随机生成的浮点数的取值满足均值为0,方差为1的正态分布。
input:维度值
- torch.range:用于生成数据类型为浮点型且自定义起始范围和结束范围的Tensor。
input:范围起始值、结束值和步长
1
| A = torch.range(1, 20, 1)
|
- torch.zeros:用于生成数据类型为浮点型且维度指定的Tensor,不过这个浮点型的Tensor中的元素值全部为0。
input:维度值
Tensor的运算
这里列出一些常用的Tensor运算
- torch.abs:将参数传递到torch.abs后返回输入参数的绝对值作为输出,输入参数必须是一个Tensor数据类型的变量
input:Tensor (Variable?)
- torch.add:将参数传递到torch.add后返回输入参数的求和结果作为输出,输入参数既可以全部是Tensor数据类型的变量,也可以一个是Tensor数据类型的变量,另一个是标量,计算方法都和NumPy中的数组的加法如出一辙。
input:Tensor或者Tensor与scalar的组合
- torch.clamp:对输入参数按照自定义的范围进行裁剪,最后将参数裁剪的结果作为输出。具体过程:使用变量中的每个元素分别和裁剪的上边界及裁剪的下边界进行比较,如果元素的值小于裁剪的下边界的值,该元素就被重写成裁剪的下边界的值;上边界同理(软阈值?)。
input:一共三个,分别是需要进行裁剪的Tensor数据类型的变量,裁剪的上边界 和裁剪的下边界。
- torch.div:将参数传递到torch.div后返回输入参数的求商结果作为输出。
input:Tensor或者Tensor与scalar的组合
- torch.mul:将参数传递到torch.mul后返回输入参数求积的结果作为输出。
input:Tensor或者Tensor与scalar的组合
- torch.pow:将参数传递到torch.pow后返回输入参数的求幂结果作为输出。
input:Tensor或者Tensor与scalar的组合
- torch.mm:将参数传递到torch.mm后返回输入参数的求积结果作为输出,不过求积方式与torch.mul不太一样,torch.mm按照矩阵之间的乘法规则进行计算,所以被传入的参数会被当成矩阵进行处理,参数的维度自然也要满足矩阵乘法的前提条件,即前一个矩阵的行数和后一个矩阵的列数相等。
input:Tensor,且需要满足矩阵乘法规则
- torch.mv:将参数传递到torch.mv后返回输入参数的求积结果作为输出,函数运用矩阵与向量之间的乘法规则进行计算。
input:第一个参数代表矩阵,第二个参数代表向量
1 2 3
| A = torch.randn(2,3) B = torch.randn(3) C = torch.mv(a,b)
|
自动梯度
PyTorch中提供了一种非常方便的方法,可以帮我们实现对模型中后向传播梯度的自动计算,即torch.autograd包。通过该包,可以使模型参数自动计算在优化过程中需要用到的梯度值,在很大程度上帮助降低了实现后向传播代码的复杂度。
torch.autograd与Variable
实现自动梯度功能的过程大致为:先通过输入的Tensor数据类型的变量在神经网络的前向传播过程中生成一张计算图,然后根据这个计算图和输出结果准确计算出每个参数需要更新的梯度,并通过完成后向传播完成对参数的梯度的更新。
在实际使用过程中需要用到torch.autograd包中的Variable类对我们定义的Tensor数据类型变量进行封装,在封装后,计算图中的各个节点就是一个Variable对象,这样才能应用自动梯度的功能。
如果已经按照如上方式完成了相关操作,则在选中了计算图中的某个节点时,这个节点必定会是一个Variable对象,用X来代表我们选中的节点,那么X.data代表Tensor数据类型的变量,X.grad也是一个Variable对象,不过它表示的是X的梯度,在想访问梯度值时需要使用X.grad.data。
示例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| import torch import torch.autograd import Variable batch_n = 100 input_data = 1000 output_data = 10
、 x = Variable(torch.randn(batch_n, input_data), requires_grad = False) y = Variable(torch.randn(batch_n, output_data), requires_grad = False)
w1 = Variable(torch.randn(input_data, hidden_layers), requires_grad = True) x2 = Variable(torch.randn(hidden_layers, output_data), requires_grad = True)
/ epoch_n = 20 learning_rate = 1e-6
for epoch in range(epoch_n): y_pred = x.mm(w1).clamp(min=10).mm(w2) loss = (y_pred - y).pow(2).sum() print(“Epoch:{}, Loss:{:.4f}”.format(epoch, loss.data[0]) / loss.backward() w1.data -= learning_rate*w1.grad.data w2.data -= learning_rate*w2.grad.data w1.grad.data.zero_() w2.grad.data.zero_()
|
自定义传播函数
我们还可以通过构建一个继承了torch.no.Module的新类,来完成对前向传播函数和后向传播函数的重写。在这个新类中,我们使用forward作为前向传播函数的关键字,使用backward作为后向传播函数的关键字。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| import torch import torch.autograd import Variable batch_n = 100 input_data = 1000 output_data = 10 class Model(torch.no.Module): def __init__(self): super(Model, self).__init__() def forward(self, input, w1, w2): x = torch.mm(input, w1) x = torch.clamp(x, min = 0) x = torch.mm(x, w2) return x def backward(self): pass model = Model() x = Variable(torch.randn(batch_n, input_data), requires_grad = False) y = Variable(torch.randn(batch_n, output_data), requires_grad = False) w1 = Variable(torch.randn(input_data, hidden_layers), requires_grad = True) x2 = Variable(torch.randn(hidden_layers, output_data), requires_grad = True)
epoch_n = 20learning_rate = 1e-6 for epoch in range(epoch_n): y_pred = model(x, w1, w2) loss = (y_pred - y).pow(2).sum() print(“Epoch:{}, Loss:{:.4f}”.format(epoch, loss.data[0])) loss.backward() w1.data -= learning_rate*w1.grad.data w2.data -= learning_rate*w2.grad.data w1.grad.data.zero_() w2.grad.data.zero_()
|
整个模型训练部分的代码被简化了
模型搭建和参数优化
Pytorch之torch.nn
- torch.nn.Sequential:
- torch.nn.Linear:
- torch.nn.ReLU:
- torch.nn.MSELoss
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| import torchimport torch.autograd import Variable batch_n = 100 input_data = 1000 output_data = 10 hidden_layers = 100 input_data = 1000 output_data = 10 models = torch.nn.Sequential( torch.nn.Linear(input_data, hidden_layer), torch.nn.ReLU(), torch.nn.Linear(hidden_layer, output_layer) )
models = torch.nn.Sequential(OrderdDict([ (“Line1”, torch.nn.Linear(input_data, hidden_layer)), (“Relu1”, torch.nn.ReLU()), (“Line2”, torch.nn.Linear(hidden_layer, output_dataL))]) ) for epoch in range(epoch_n): y_pred = models(x) loss = loss_fn(y_pred, y) if epoch%1000 == 0: print(“Epoch:{}, Loss:{:.4f}”.format(epoch, loss.data[0])) models.zero_grad() loss.backward() for param in models.parameters(): param.data -= param.grad.data*learning_rate
|
PyTorch之torch.optim
到目前为止,代码中的神经网络全中的参数优化和更新还没有实现自动化,并且使用的优化方法都有固定的学习速率,所以优化函数向对劲啊单。在PyTorch的torch.optim包中提供了非常多的可实现参数自动化的类,比如SDG, AdaGrad, RMSProp, Adam等。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import torchimport torch.autograd import Variable batch_n = 100 input_data = 1000 output_data = 10 hidden_layers = 100 input_data = 1000 output_data = 10 models = torch.nn.Sequential( torch.nn.Linear(input_data, hidden_layer), torch.nn.ReLU(), torch.nn.Linear(hidden_layer, output_layer) ) optimizer = torch.optim.Adam(models.parameters(), lr = learning_rate) for epoch in range(epoch_n): y_pred = models(x) loss = loss_fn(y_pred, y) print(“Epoch:{}, Loss:{:.4f}”.format(epoch, loss.data[0])) optimizer.zero_grad() loss.backward() optimizer.step()
|
实战中还需要用到
torch和torchvision
数据预览和数据装载
模型搭建和参数优化