注意:这是旧版本的PyTorch教程的一部分。你可以在Learn the Basics查看最新的开始目录。
该教程通过几个独立的例子介绍了PyTorch的基本概念。
核心是:PyTorch提供了两个主要的特性:
一个n维的Tensor,与Numpy相似但可以在GPU上运行
构建和训练神经网络的自动微分
我们将使用一个三阶多项式拟合 y=sin(x) 的问题作为我们的运行示例。该网络会有4个参数,将使用梯度下降来训练,通过最小化神经网络输出和真值之间的欧氏距离来拟合随机数据。
Tensors
热身:numpy
在介绍PyTorch之前,我们首先使用numpy实现网络
Numpy提供了一个n维的array对象,以及对数组操作的多种方法。Numpy是一个用于科学计算的通用框架,它没有关于计算图、深度学习、梯度的任何内容。但是我们可以利用numpy操作,通过人工实现贯穿网络的前向和后向传递,从而简单的向sin函数拟合一个三阶多项式。
-- coding: utf-8 --
import numpy as np
import math
Create random input and output data
x = np.linspace(-math.pi, math.pi, 2000) # 生成含有2000个数的-π到π的等差数列
y = np.sin(x)
Randomly initialize weights
a = np.random.randn() # 返回浮点数
b = np.random.randn()
c = np.random.randn()
d = np.random.randn()
learning_rate = 1e-6
for t in range(2000):
# Forward pass: compute predict y
# y = a + b x + c x^2 + d x^3
y_pred = a + b * x + c * x ** 2 + d * x ** 3
# Compute and print loss
loss = np.square(y_pred - y).sum() # 所有样本与真值的差值平方的和
if t % 100 == 99:
print(t, loss)
# Backprop to compute gradients of a, b, c, d with respect to loss
grad_y_pred = 2.0 * (y_pred - y) # loss关于y_pred的偏导(梯度),这里没有对所有样本求和
grad_a = grad_y_pred.sum() # 这里及下面都要对所有样本得到的梯度求和
grad_b = (grad_y_pred * x).sum()
grad_c = (grad_y_pred * x ** 2).sum()
grad_d = (grad_y_pred * x ** 3).sum()
# Update weights
a -= learning_rate * grad_a
b -= learning_rate * grad_b
c -= learning_rate * grad_c
d -= learning_rate * grad_d
print(f"Result: y = {a} + {b} x + {c} x^2 + {d} x^3")
PyTorch: Tensors
Numpy是一个强大的框架,但是它无法使用GPUs加速数值计算。对于现代的深度神经网络,GPUs通常提供了50倍或更高的加速性能,所以很遗憾,numpy对于现代的深度学习是不够的。
现在介绍PyTorch基础中的基础:Tensor。PyTorch Tensor概念上来说与numpy array相同:一个Tensor就是一个n维数组,并且PyTorch提供了许多用于tensor的操作。在幕后,张量可以跟踪计算图和梯度,但它们也可用作科学计算的通用工具。
而且不像numpy,PyTorch Tensors可以使用GPUs加速数值计算。简单地制定正确的设备,即可在GPU上运行PyTorch tensor。
这里我们使用PyTorch Tensors为sin函数拟合一个3阶多项式。像上面的numpy例子一样,我们需要手动实现贯穿网络的前向和后向传递:
-- coding: utf-8 --
import torch
import math
dtype = torch.float
device = torch.device(‘cpu’)
device = torch.device(‘cuda:0’) # Uncomment this to run on GPU
Create random input and output data
x = torch.linspace(-math.pi, math.pi, 2000, device=device, dtype=dtype)
y = torch.sin(x)
Randomly initialize weights
a = torch.randn((), device=device, dtype=dtype)
b = torch.randn((), device=device, dtype=dtype)
c = torch.randn((), device=device, dtype=dtype)
d = torch.randn((), device=device, dtype=dtype)
learning_rate = 1e-6
for t in range(2000):
# Forward pass: compute predicted y
y_pred = a + b * x + c * x ** 2 + d * x ** 3
# Compute and print loss
loss = (y_pred - y).pow(2).sum().item() # .item()是取tensor的数值
if t % 100 == 99:
print(t, loss)
# Backprop to compute gradients of a, b, c, d with respect to loss
grad_y_pred = 2.0 * (y_pred - y)
grad_a = grad_y_pred.sum()
grad_b = (grad_y_pred * x).sum()
grad_c = (grad_y_pred * x ** 2).sum()
grad_d = (grad_y_pred * x ** 3).sum()
# Update weights
a -= learning_rate * grad_a
b -= learning_rate * grad_b
c -= lear