【PyTorch学习】分别使用Numpy和Tensor及Antograd实现机器学习

本文分别用Numpy、Tensor、autograd来实现同一个机器学习任务,比较它们之间的异同及各自优缺点,从而加深大家对PyTorch的理解。

一、使用Numpy实现机器学习

首先,我们用最原始的Numpy实现有关回归的一个机器学习任务,不用PyTorch中的包或类。

主要步骤包括:

  1. 首先,给出一个数组x,然后基于表达式y=3x2+2,加上一些噪音数据到达另一组数据y。
  2. 然后,构建一个机器学习模型,学习表达式y=wx2+b的两个参数w、b。利用数组x,y的数据为训练数据。
  3. 最后,采用梯度梯度下降法,通过多次迭代,学习到w、b的值。

以下为实战环节的具体步骤:
1)导入需要的库

import numpy as np
from matplotlib import pyplot as plt
%matplotlib inline

2)生成输入数据x及目标数据y

设置随机数种子,即生成同一份数据,以便使用多种方法进行比较。

np.random.seed(666)
x = np.linspace(-1, 1, 100).reshape(100, 1)
y = 3 * np.power(x, 2) + 2 + 0.2 * np.random.rand(x.size).reshape(100, 1)

3)查看x、y数据分布情况

# 绘图
plt.scatter(x,y)
plt.show()

4)初始化权重参数

# 随机初始化参数
w = np.random.rand(1,1)
b = np.random.rand(1,1)

5)训练模型

定义损失函数,假设批量大小为100:

对损失函数求导:

利用梯度下降法学习参数,学习率为lr。

用代码实现上面这些表达式:

lr = 0.001 # 学习率
for i in range(800):
    # 前向传播
    y_pred = np.power(x, 2) * w + b
    # 定义损失函数
    loss = 0.5 * (y_pred - y) ** 2
    loss = loss.sum()
    # 计算梯度
    grad_w = np.sum((y_pred - y) * np.power(x, 2))
    grad_b = np.sum(y_pred - y)
    # 使用梯度下降法,是loss最小
    w -= lr * grad_w
    b -= lr * grad_b

6)可视化结果

plt.plot(x, y_pred, 'r-', label='predict')
plt.scatter(x, y, color='blue', marker='o', label='true')

plt.xlim(-1, 1)
plt.ylim(2, 6)
plt.legend()
plt.show()
print(w, b)

[[2.99850472]] [[2.0989827]]

从结果看来,学习效果还是还是比较理想的。

 

二、使用Tensor及Antograd实现机器学习

上节可以说是纯手工完成一个机器学习任务,数据用Numpy表示,梯度及学习是自己定义并构建学习模型。这种方法适合于比较简单的情况,如果稍微复杂一些,代码量将几何级增加。那是否有更方便的方法呢?

本节我们将使用PyTorch的一个自动求导的包——antograd,利用这个包及对应的Tensor,便可利用自动反向传播来求梯度,无须手工计算梯度。

以下为实战环节的具体步骤:

1)导入需要的库

import torch as t
from matplotlib import pyplot as plt
%matplotlib inline

2)生成训练数据,并可视化数据分布情况

# 随机种子
torch.manual_seed(666)

# 生成x座标数据,x为tensor,需要把x的形状装换为100×1
x = torch.unsqueeze(torch.linspace(-1, 1, 100), dim=1)
# 生成y座标数据,y为tensor,形状为100×1,另加上一些噪声
y = 3 * x.pow(2) + 2 + 0.2 * torch.rand(x.size())

# 绘图,把tensor数据转换为numpy数据
plt.scatter(x.numpy(), y.numpy())
plt.show()

3)初始化权重参数

# 随机初始化参数,参数w,b为需要学习的,故需requires_grad=True
w = torch.randn(1, 1, dtype = torch.float, requires_grad=True)
b = torch.zeros(1, 1, dtype = torch.float, requires_grad=True)

4)训练模型

lr = 0.001 # 学习率
for i in range(800):
    # 前向传播
    y_pred = x.pow(2).mm(w) + b
    # 定义损失函数
    loss = 0.5 * (y_pred - y) ** 2
    loss = loss.sum()
    # 自动计算梯度,梯度存放在grad属性中
    loss.backward()
    # 手动更新参数,需要用torch.no_grad(),使上下文环境中切断自动求导的计算
    with torch.no_grad():
        w -= lr * w.grad
        b -= lr * b.grad
        
        # 梯度清零
        w.grad.zero_()
        b.grad.zero_()

5)可视化训练结果

plt.plot(x.numpy(), y_pred.detach().numpy(), 'r-', label='predict') # predict
plt.scatter(x.numpy(), y.numpy(), color='blue', marker='o', label='true') # true data

plt.xlim(-1, 1)
plt.ylim(2, 6)
plt.legend()
plt.show()
print(w, b)

tensor([[2.9578]], requires_grad=True) tensor([[2.0990]], requires_grad=True)

这个结果与使用Numpy实现机器学习差不多。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章