Jovian
⭐️
Sign In

https://mp.weixin.qq.com/s/o1Op8Ebly4bF8rWq9qptlA

这是「PyTorch: Zero to GANs」系列教程的第一篇,介绍了 PyTorch 模型的基本构件:张量和梯度。

完整系列教程包括:

PyTorch 基础:张量&梯度(本文) 线性回归 & 梯度下降:https://medium.com/jovian-io/linear-regression-with-pytorch-3dde91d60b50
用 Logistic 回归进行分类:https://medium.com/jovian-io/image-classification-using-logistic-regression-in-pytorch-ebb96cc9eb79 未完待续.. (神经网络、CNN、RNN、GAN 等)

本系列教程旨在让用户更好地利用 PyTorch 学习深度学习和神经网络。本文将介绍 PyTorch 模型的基本构件:张量和梯度。

In [4]:
import torch

张量
本质上来说,PyTorch 是一个处理张量的库。一个张量是一个数字、向量、矩阵或任何 n 维数组。我们用单个数字创建一个张量:

In [2]:
# Number
t1 = torch.tensor(4.)
t1
Out[2]:
tensor(4.)

4.是 4.0 的缩写。它用来表示你想创建浮点数的 Python(和 PyTorch)。我们可以通过检查张量的 dtype 属性来验证这一点:

In [5]:
t1.dtype
Out[5]:
torch.float32

我们可以试着创建复杂一点的张量:

In [6]:
# Vector
t2 = torch.tensor([1., 2, 3, 4])
t2
Out[6]:
tensor([1., 2., 3., 4.])
In [16]:
# Matrix
t3 = torch.tensor([[5., 6], [7, 8], [9, 10]])
t3
Out[16]:
tensor([[ 5.,  6.],
        [ 7.,  8.],
        [ 9., 10.]])
In [10]:
# 3-dimensional array
t4 = torch.tensor([
    [[11, 12, 13],
     [13, 14, 15]],
    [[15, 16, 17],
     [12, 18, 19.]]
])
t4
Out[10]:
tensor([[[11., 12., 13.],
         [13., 14., 15.]],

        [[15., 16., 17.],
         [12., 18., 19.]]])

张量可以有任何维数。每个维度有不同的长度。我们可以用张量的.shape 属性来查看每个维度的长度。

In [11]:
t1.shape
Out[11]:
torch.Size([])
In [12]:
t2.shape
Out[12]:
torch.Size([4])
In [17]:
t3.shape
Out[17]:
torch.Size([3, 2])
In [18]:
t4.shape
Out[18]:
torch.Size([2, 2, 3])

张量运算和梯度

我们可以将张量与常用的算数运算相结合。如下:

In [19]:
# Create tensors
x = torch.tensor(3.)
w = torch.tensor(4., requires_grad=True)
b = torch.tensor(5., requires_grad=True)

我们已经创建了 3 个张量:x、w 和 b。w 和 b 有额外的参数 requires_grad,设置为 True。一会儿就可以看看它能做什么。

通过结合这些张量,我们可以创建新的张量 y。

In [20]:
# Arithmetic operations
y = w * x + b
y
Out[20]:
tensor(17., grad_fn=<AddBackward0>)

如预期所料,y 是值为 3 * 4 + 5 = 17 的张量。PyTorch 的特殊之处在于,我们可以自动计算 y 相对于张量(requires_grad 设置为 True)的导数,即 w 和 b。为了计算导数,我们可以在结果 y 上调用.backward 方法。

In [21]:
# Compute derivatives
y.backward()

y 相对于输入张量的导数被存储在对相应张量的.grad 属性中。

In [22]:
# Display gradients
print('dy/dx', x.grad)
print('dy/dw', w.grad)
print('dy/db', b.grad)
dy/dx None dy/dw tensor(3.) dy/db tensor(1.)

如预期所料,dy/dw 的值与 x 相同(即 3),dy/db 的值为 1。注意,x.grad 的值为 None,因为 x 没有将 requires_grad 设为 True。w_grad 中的「grad」代表梯度,梯度是导数的另一个术语,主要用于处理矩阵。

与 Numpy 之间的互操作性

Numpy 是 Python 中用于数学和科学计算的流行开源库。它支持在大型多维数组上进行高效运算,拥有一个支持多个库的大型生态系统。这些库包括:

用于画图、可视化的 Matplotlib 用于图像和视频处理的 OpenCV 用于文件 I/O 和数据分析的 Pandas

PyTorch 并没有重新创造 wheel,而是与 Numpy 很好地交互,以利用它现有的工具和库生态系统。

In [23]:
import numpy as np

x = np.array([[1, 2], [3, 4]])
x
Out[23]:
array([[1, 2],
       [3, 4]])

可以用 torch.fron_numpy 将 Numpy 数组转化为 PyTorch 张量。

In [24]:
# Convert the numpy array to a torch tensor
y = torch.from_numpy(x)
y
Out[24]:
tensor([[1, 2],
        [3, 4]], dtype=torch.int32)

接下来可以验证 Numpy 数组和 PyTorch 张量是否拥有类似的数据类型。

In [25]:
x.dtype, y.dtype
Out[25]:
(dtype('int32'), torch.int32)

可以使用张量的.to_numpy 方法将 PyTorch 张量转化为 Numpy 数组。

In [26]:
# Convert a torch tensor to a numpy array
z = y.numpy()
z
Out[26]:
array([[1, 2],
       [3, 4]])

PyTorch 和 Numpy 之间的互操作性真的非常重要,因为你要用的大部分数据集都可能被读取并预处理为 Numpy 数组。

提交及上传 notebook

最后一步是保存并利用 jovian 库提交以上工作

In [31]:
import jovian
jovian.commit()
--------------------------------------------------------------------------- ModuleNotFoundError Traceback (most recent call last) <ipython-input-31-97223f28e913> in <module>() ----> 1 import jovian 2 jovian.commit() ModuleNotFoundError: No module named 'jovian'

Jovian 将 notebook 上传到 https://jvn.io (https://jvn.io/),用以上方式为你的 notebook 捕获 Python 环境并创建可共享的链接。你可以利用这一链接分享自己的作品,让任何人都可以利用 jovian clone 命令轻松复现。Jovian 还拥有一个强大的评论界面,供你和其他人讨论及评论你 notebook 中的某个部分:

延伸阅读

PyTorch 中的张量支持很多运算,这里列出的并不详尽。如果你想了解更多关于张量和张量运算的信息,可参考以下地址:

链接:https://pytorch.org/docs/stable/tensors.html

如果你想利用交互式 Jupyter 环境的优势来进行张量实验并尝试上述的各种不同运算组合,可以尝试下面这些:

  1. 如果上面提到的例子中,一个或多个「x」、「w」或「b」是矩阵,而不是数字,该怎么办?在这种情况下,结果「y」、梯度 w.grad 和 b.grad 看起来将是怎样的?
  2. 如果「y」是用 torch.tensor 创建的矩阵,矩阵的每个元素都表示为数字张量「x」、「w」和「b」的组合,该怎么办?
  3. 如果我们有一个运算链,而不止一个运算,即 y = x * w + b, z = l * y + m, e =c * z + d,该怎么办?调用 e.backward() 会发生什么?

如果你对此感兴趣,且想了解更多关于矩阵导数的信息,可以参考:

链接:https://en.wikipedia.org/wiki/Matrix_calculus#Derivatives_with_matrices

以上,我们完成了关于 PyTorch 中张量和梯度的讨论,下一步的主题将是线性回归。

该系列文章主要受到下面两篇文章的启发:

Yunjey Choi,PyTorch Tutorial for Deep Learning Researchers
地址:https://github.com/yunjey/pytorch-tutorial
Jeremy Howard,FastAI development notebooks
地址:https://github.com/fastai/fastai_docs/tree/master/dev_nb

In [ ]: