mlbo · 2020年05月13日

Effective PyTorch之 PyTorch基础知识(译)

作者:iotsharer
首发:玩转机器学习硬件写文章

一、PyTorch安装

PyTorch安装请参考PyTorch官网,安装最新版的即可,本文代码在PyTorch1.4上测试通过。

二、PyTorch基本操作

Pythorch是目前最流行的深度学习框架之一,在机器学习研究上被广泛使用。PyTorch与NumPy在许多方面很相似,如果你熟悉Numpy的话,使用PyTorch时不用对代码进行任何实质性更改,就可以在CPU、GPU和TPU上执行计算。PyTorch还可以方便地将计算分布到多个设备或机器上。PyTorch最重要的特性之一是自动微分(automatic differentiation)。它允许以有效的方式解析计算函数的梯度,这对于使用梯度下降法训练机器学习模型至关重要。 本文接下来将简要介绍PyTorch,并讨论使用PyTorch的最佳实践。

2.1.张量创建和操作

学习PyTorch,首先要了解张量的概念。 张量其实就是多维数组。 PyTorch张量和NumPy数组很相似,只是附加了一些神奇的功能。本节的目标是让您上手并运行PyTorch,主要介绍基本的数学和数值计算工具。在您阅读本文的过程中,这些工具将成为您的基础。 如果您很难理解一些数学概念或库函数,请不要担心。 接下来的几节将在实际例子的背景下使用它们。 另一方面,如果您已经有了一些背景知识,并且想要更深入地了解其他内容,只需跳过这一节即可。

# 导入PyTorch包
import torch
# 存储标量
a = torch.tensor(3)
print("a =", a)
# 存储数组
b = torch.tensor([1, 2])
print("b =", b)

# 存储矩阵
c = torch.zeros([2, 2])   # zeros表示组成张量的元素都是0
print("c =", c)
# 存储任意维度的张量
d = torch.rand([2, 2, 2])   # rand表示组成张量的元素为随机值
print("d =", d)
a = tensor(3)
b = tensor([1, 2])
c = tensor([[0., 0.],
        [0., 0.]])
d = tensor([[[0.8440, 0.6361],
         [0.8058, 0.6162]],

        [[0.1676, 0.0993],
         [0.6834, 0.9837]]])

张量可以用来有效地执行代数运算。 机器学习应用中最常用的操作之一是矩阵乘法。 假设您要将大小为3x5和5x4的两个随机矩阵相乘,这可以使用矩阵乘法运算(@)来完成:

x = torch.randn([3, 5])  # randn表示组成张量的元素为随机值
y = torch.randn([5, 4])
z = x @ y

print("z =", z)
z = tensor([[-1.7018, -0.0064, -0.6348, -0.3098],
        [-0.5254, -0.2301, -1.6038,  0.6338],
        [-0.7032,  1.8453, -0.4830, -1.5080]])

同样,要将两个向量相加,可以执行以下操作:

x = torch.ones([2, 2])  # randn表示组成张量的元素为随机值
y = torch.ones([2, 2])
z = x + y
print(z)
tensor([[2., 2.],
        [2., 2.]])

要将张量转换为numpy数组,可以调用张量的numpy()方法:

print(type(z), z)
z = z.numpy()
print(type(z))
<class 'torch.Tensor'> tensor([[2., 2.],
        [2., 2.]])
<class 'numpy.ndarray'>

您同样可以通过以下方式将numpy数组转换为张量:

import numpy as np
x = np.random.normal([3, 5])
print(type(x), x)
x = torch.tensor(np.random.normal([3, 5]))
print(x)
<class 'numpy.ndarray'> [3.42524568 4.58130771]
tensor([0.9831, 5.5200], dtype=torch.float64)

2.2.自动微分

与NumPy相比,PyTorch最重要的优势是它的自动微分功能,这在优化应用程序(如优化神经网络的参数)中非常有用。 让我们试着用一个例子来理解它。

假设您有一个复合函数,它是由两个函数组成:g(u(x))。 为了计算g对x的导数,我们可以使用链式规则:dg/dx=dg/du*du/dx。 PyTorch可以为我们地计算导数。

为了计算PyTorch中的导数,我们首先创建一个张量,并将其requires\_grad设为true。我们可以使用张量运算来定义函数.假设u是一个二次函数,g是一个简单的线性函数

x = torch.tensor(1.0, requires_grad=True)

def u(x):
  return x * x

def g(u):
  return -u

在这种情况下,我们的复合函数是g(u(x))=-x*x,所以它对x的导数是-2x。 在点x=1处,等于-2。

可以使用PyTorch中的grad函数来验证这一点:

dgdx = torch.autograd.grad(g(u(x)), x)[0]
print(dgdx)  # tensor(-2.)
tensor(-2.)

2.3.曲线拟合

为了理解自动微分的功能有多强大,让我们看看另一个例子。假设我们有一条曲线的样本(比如f(X)=5x^2+3),我们想要根据这些样本估计f(X)。定义一个参数函数g(x,w)=w0x^2+w1x+w2,它是输入x和潜在参数(latent parameters)w的函数,然后我们的目标是找到潜在参数使得g(x,w)≈f(X)。 这可以通过最小化以下损失函数来实现:l(W)=∑(f(X)-g(x,w))^2。尽管对于这个简单的问题有一个封闭形式的解决方案,但我们选择使用一种更一般的方法,它可以应用于任何可微函数,也就是使用随机梯度下降。我们简单地计算一组样本点上L(W)相对于w的平均梯度,然后朝相反的方向移动。

下面是如何在PyTorch中完成此操作:

import numpy as np
import torch

# 假设我们知道期望的函数是二次多项式
# 分配一个大小为3的向量来保存系数,并使用高斯噪声初始化
w = torch.tensor(torch.randn([3, 1]), requires_grad=True)

# 我们使用ADAM优化器,将学习率设置为0.1,来降低Loss。
opt = torch.optim.Adam([w], 0.1)

def model(x):
    # 我们把yhat定义为对y的估计值。
    f = torch.stack([x * x, x, torch.ones_like(x)], 1)
    yhat = torch.squeeze(f @ w, 1)
    return yhat

def compute_loss(y, yhat):
    # 损失被定义为对y的估计值与其真实值之间的均方误差距离。
    loss = torch.nn.functional.mse_loss(yhat, y)
    return loss

def generate_data():
    # 根据预设函数生成一些训练数据
    x = torch.rand(100) * 20 - 10
    y = 5 * x * x + 3
    return x, y

def train_step():
    x, y = generate_data()

    yhat = model(x)
    loss = compute_loss(y, yhat)

    opt.zero_grad()
    loss.backward()
    opt.step()

for _ in range(1000):
    train_step()

print(w.detach().numpy())

通过运行这段代码,您应该会看到类似以下内容的结果:

[4.9908338e+00, 1.0696074e-03, 3.5437376e+00]

这与我们预设的函数 y =5* x * x +3的参数比较接近。

这只是PyTorch的功能的冰山一角。许多问题,如在PyTorch中只需几行代码就可以优化具有数百万个参数的大型神经网络。PyTorch负责跨多个设备和线程进行扩展,并支持多种平台。

附录:

1、torch.rand和torch.randn有什么区别?

torch.rand(*sizes, out=None) → Tensor 返回一个张量,包含了从区间[0, 1)的均匀分布中抽取的一组随机数。张量的形状由参数sizes定义。
torch.randn(*sizes, out=None) → Tensor 返回一个张量,包含了从标准正态分布(均值为0,方差为1,即高斯白噪声)中抽取的一组随机数。

2、原文链接

https://github.com/vahidk/EffectivePyTorch​github.com

推荐阅读

定期更新,更多AIoT相关技术知识请关注动手学AIoT专栏。
推荐阅读
关注数
1211
内容数
19
关于AIoT相关的技术文章以及相关资源。
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息