地点:鉴主
时间:2017-1130
本文主要记录学习 Pytorch Tutorials 过程中的笔记及相关问题。
PyTorch 的相关背景就不做介绍了,网上很多。
在实际的使用过程中来看,对比之前用过的 TensorFlow 和 Keras 而言,使用 PyTorch 就像是在写一个普通的 Python 程序,而不是像 TF 和 Keras 一样限制颇多,因此在使用的过程中,相比于其他框架能够很清楚自己做的是什么,非常的新手友好。
PyTorch 基本概念
机器学习方面的几个重要概念在 PyTorch 主要通过 Tensors, Autograd, nn module 进行体现。
Tensors
Numpy 是一个很好的计算工具,但是它无法使用 GPUs 加速数值计算,因此性能不能满足要求。
首先引入最基本的 PyTorch 概念: Tensor. Tensor 是一个 n 维数组,同时 PyTorch 提供了多种函数对它进行操作。与 Numpy.array 相同的是, PyTorch 的 Tensors 不包含任何 深度学习,计算图或者梯度 这些科学计算的工具。
然而不同于 numpy 的是,PyTorch 的 Tensors 能够利用 GPUs 来进行加速数值计算。在 GPU 上运行 PyTorch 的 Tensor, 我们需要将它简单转换一下数据格式。
# -*- coding: utf-8 -*-
import torch
dtype = torch.FloatTensor
# dtype = torch.cuda.FloatTensor # 在 GPU 上运行调用的函数
# N is 批数目; D_in is 输入维数;
# H is 隐藏层维数; D_out is 输出层维数.
N, D_in, H, D_out = 64, 1000, 100, 10
# 创建随机输入输出数据
x = torch.randn(N, D_in).type(dtype)
y = torch.randn(N, D_out).type(dtype)
# 随机初始化权重文件
w1 = torch.randn(D_in, H).type(dtype)
w2 = torch.randn(H, D_out).type(dtype)
# 设置学习率
learning_rate = 1e-6
for t in range(500):
# 前向传播,计算预测的 y 值
h = x.mm(w1)
h_relu = h.clamp(min=0)
y_pred = h_relu.mm(w2)
# 计算并且输出 loss 值
loss = (y_pred - y).pow(2).sum()
print(t, loss)
# 基于 loss 值 反向传播计算 w1 和 w2 的梯度
grad_y_pred = 2.0 * (y_pred - y)
grad_w2 = h_relu.t().mm(grad_y_pred)
grad_h_relu = grad_y_pred.mm(w2.t())
grad_h = grad_h_relu.clone()
grad_h[h < 0] = 0
grad_w1 = x.t().mm(grad_h)
# 使用梯度下降更新权值
w1 -= learning_rate * grad_w1
w2 -= learning_rate * grad_w2
可以看出,在实际的操作上面,其使用方法和 numpy 非常相似。
Autograd
上面的例子实现了前向传播和反向传播,这是神经网络的基础。在实际的过程中,我们可以使用 Automatic Differentiation 来自动计算神经网络的反向传播值。PyTorch 中的 autograd 包就是用于提供这个功能。
When using autograd, the forward pass of your network will define a computational graph; nodes in the graph will be Tensors, and edges will be functions that produce output Tensors from input Tensors. Backpropagating through this graph then allows you to easily compute gradients.
当使用 autograd 时,你网络中的前向传播将会定义一个计算图,在这个图中的每个节点都是张量,边可以提供从输入张量到输出张量的处理功能。随后图中的反向传播过程能够让你简单计算梯度。
在实际的使用中非常简单。我们将 PyTorch 的 Tensors 包装进 Variable ; 一个 Varible 展示了计算图中的一个节点。如果 x 是一个 Variable ,x.data 既是张量,x.grad 是另一个 Variable,其中包含了通过变换值求出的 x 梯度。
PyTorch Variable 的操作基本和 PyTorch Tensors 一样。区别在于使用 Variable 定义的是一个计算图,允许网络自动求梯度。
随后使用 Variables 和 autograd 来实现上文的神经网络, 现在我们不需要再实现上文的 backward pass 过程。
import torch
from torch.autograd import Variable
dtype = torch.FloatTensor
# dtype = torch.cuda.FloatTensor # gpu 运行时的代码
# N is 批数目; D_in is 输入维数;
# H is 隐藏层维数; D_out is 输出层维数.
N, D_in, H, D_out = 64, 1000, 100, 10
# 创建随机 Tensors 来保存 输入和输出, 随后将它们包进 Variables
# 设置 requires_grad = False 来表示我们无需计算梯度
# with respect to these Variables during the backward pass.
x = Variable(torch.randn(N, D_in).type(dtype), requires_grad=False)
y = Variable(torch.randn(N, D_out).type(dtype), requires_grad=False)
# 为权值创建随机 Tensor, 并且将它们包进 Variables
# 设置 requires_grad = True 表示我们需要计算梯度
# respect to these Variables during the backward pass.
w1 = Variable(torch.randn(D_in, H).type(dtype), requires_grad=True)
w2 = Variable(torch.randn(H, D_out).type(dtype), requires_grad=True)
learning_rate = 1e-6
for t in range(500):
# Forward pass: 使用 Variables 中的值计算 y;这个操作和我们使用 Tensors 计算
# 时一样, 但是我们不需要保持对中间值的引用,因为我们无需动手实现 backward pass .
y_pred = x.mm(w1).clamp(min=0).mm(w2)
# 使用 Variable 中的函数计算并且输出 loss 值
# 此时 loss 值是一个 shape (1, ) 的 Variable,并且 loss.data 是一个形状为 (1, ) 的 Tensor。
# loss.data[0] 是一个保存 loss 值的标量
loss = (y_pred - y).pow(2).sum()
print(t, loss.data[0])
# 使用 autograd 计算 backward pass. 这个调用将会计算 loss 值的梯度,依据的是
# 所有 requires_grad = True 的 Variable。
# After this call w1.grad and w2.grad will be Variables holding the gradient
# of the loss with respect to w1 and w2 respectively.
loss.backward()
# 使用 梯度下降更新权值;w1.data 和 w2.data 是 Tensors。
# w1.grad 和 w2.grad 是 Variable; w1.grad.data 和 w2.grad.data 是 Tensors
w1.data -= learning_rate * w1.grad.data
w2.data -= learning_rate * w2.grad.data
# 更新权值之后将梯度归 0
w1.grad.data.zero_()
w2.grad.data.zero_()
PyTorch : Variables and autograd
nn module
PyTorch CNN
为了进行实际操作,用 PyTorch 构建一个 CNN 是很常见的方法。
首先需要导入基本的包。
参考
http://pytorch.org/tutorials/beginner/pytorch_with_examples.html