什么是 PyTorch?
PyTorch 是基于以下两个目的而打造的python科学计算框架:
- 无缝替换NumPy,并且通过利用GPU的算力来实现神经网络的加速。
- 通过自动微分机制,来让神经网络的实现变得更加容易。
预热:Numpy
Numpy 提供了一个 n 维数组对象,以及许多用于操纵这些数组的函数。 Numpy 是用于科学计算的通用框架。 它对计算图,深度学习或梯度一无所知。 但是,通过使用 numpy 操作手动实现网络的前向和后向传递,我们可以轻松地使用 numpy 使三阶多项式适合正弦函数:
# -*- coding: utf-8 -*-
import numpy as np
import math
# Create random input and output data
x = np.linspace(-math.pi, math.pi, 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 predicted 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)
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
中, 神经网络的输入、输出以及网络的参数等数据, 都是使用张量来进行描述。张量的使用和Numpy
中的ndarrays
很类似, 区别在于张量可以在GPU
或其它专用硬件上运行, 这样可以得到更快的加速效果。
在这里,我们使用 PyTorch 张量将三阶多项式拟合为正弦函数。 像上面的 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()
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 using gradient descent
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.item()} + {
b.item()} x + {
c.item()} x^2 + {
d.item()} x^3')
张量初始化
-
直接生成张量 ,由原始数据直接生成张量, 张量类型由原始数据类型决定。
data = [[1, 2], [3, 4]] x_data = torch.tensor(data)
-
通过Numpy数组来生成张量
np_array = np.array(data) x_np = torch.from_numpy(np_array)
-
通过已有的张量来生成新的张量,新的张量将继承已有张量的数据属性(结构、类型), 也可以重新指定新的数据类型。
x_ones = torch.ones_like(x_data) # 保留 x_data 的属性 print(f"Ones Tensor: \n { x_ones} \n") x_rand = torch.rand_like(x_data, dtype=torch.float) # 重写 x_data 的数据类型 int -> float print(f"Random Tensor: \n { x_rand} \n")
-
通过指定数据维度来生成张量
shape = (2,3,) rand_tensor = torch.rand(shape) ones_tensor = torch.ones(shape) zeros_tensor = torch.zeros(shape) print(f"Random Tensor: \n { rand_tensor} \n") print(f"Ones Tensor: \n { ones_tensor} \n") print(f"Zeros Tensor: \n { zeros_tensor}")
张量属性
从张量属性我们可以得到张量的维数、数据类型以及它们所存储的设备(CPU或GPU)。
tensor = torch.rand(3,4)
print(f"Shape of tensor: {
tensor.shape}")
print(f"Datatype of tensor: {
tensor.dtype}")
print(f"Device tensor is stored on: {
tensor.device}")
张量运算
有超过100种张量相关的运算操作, 例如转置、索引、切片、数学运算、线性代数、随机采样等。更多的运算可以在这里查看。
所有这些运算都可以在GPU上运行(相对于CPU来说可以达到更高的运算速度)。如果你使用的是Google的Colab环境, 可以通过 Edit > Notebook Settings
来分配一个GPU使用。
# 判断当前环境GPU是否可用, 然后将tensor导入GPU内运行