DeepLeaning入门——简单案例数据拟合

深度学习环境安装一文中,我们已经搭建了撸代码的基本环境。现在就可以来正式写代码了,鸡冻!我们今天的目的是模拟一些数据(线性),并通过调整参数(斜率k和b)找到和这些数据最匹配的函数。中间会穿插一些关于运算概念的解释

大概长这样

image.png

首先是引入pytorch,以及包含的variable

(所有代码都在jupyter notebook中完成)

import torch
from torch.autograd import Variable
复制代码

这个variable是用来干什么的呢? 它其实是一个自动微分变量,简单来说,他是将张量的运算“流程化”,在使用自动微分变量进行运算时,其实上是在构建一个计算图。 比如, 我们定义了两个py变量,并把他们打印出来看

//定义一个tensor
x = torch.tensor([[1.,2.],[3.,4.]])
//定一个variable
y = Variable(x,  requires_grad = True);
print('x',x);
print('y',y);
复制代码

image.png
后面那个 requires_grad = True的含义是让这个微分变量 可反向传播

tensor的方法variable几乎都能用,而variable有很多它自己独特的方法,比如反向传播(backward),对输入量求梯度值(grad())等等。别急,它们具体是什么含义我们稍后揭晓

知道了什么是自动微分变量之后,我们开始进入正题。

让我们再定一个variable变量, torch.linspace(0, 10)是创建在阈值为[0, 10]上均等划分出一个100维的向量,结果如图所示

x = Variable(torch.linspace(0, 10),  requires_grad = True)
print(x)
复制代码

image.png

然后我们对这个变量进行几步运算,得到一个变量z

y = x + 2  # y是一个100维的自动微分变量,值为x的每项+2
z = torch.mean(y*y) # torch.mean()的含义是求均值,z为一个数值(或者理解为0维的张量) 
print(z)
复制代码

image.png
接下来我们对z使用 backward()方法进行反向传播,从而获取到x的变化梯度。

z.backward() #反向传播操作
x.grad    #获取x反传后的梯度值
print(x.grad)
复制代码

image.png

到这一步你就会发现,这样的操作并没有什么实际的意义。所有的操作都只是为了解释这些基本概念

好了真实案例开搞

首先我们模拟一些离散的点。使用randn方法生成[0-1]区间内正态分布的随机点,它接收一个生成数量的参数

# 横坐标, 100维张量,分为100份
x = Variable(torch.linspace(0, 100).type(torch.FloatTensor)); 
# 我们现在要设置y,先生成一些随机分布的数
rand = Variable(torch.randn(100) * 10);
y = x + rand
复制代码

设置完了之后我们把这些点画出来,这里就用到了一个第三方的库matplotlib.pyplot官方文档在这里,上篇文章也带大家安装过。这里直接引入,并画图

# 引入绘图库
import matplotlib.pyplot as plt
# 画图操作,'ro'代表绘制离散的点
plt.plot(x.data.tolist(),y.data.tolist(), 'ro' )
复制代码

绘图结果如下

image.png

然后就开始去计算我们要求的函数的参数。这个图形是线性的,没有扭来扭去的波段,我们就可以将它设为一个一次函数y = k * x + b的形式,k和b就是我们最后要训练得到的参数

先随机生成k和b这两个参数,再设置学习率。

学习率的设置一般都在0.0001,如果太大会导致无法得到精确的结果,而太小又需要数量更多的运算过程。

# 先随机生成这个参数
k = Variable(torch.rand(1), requires_grad = True)
b = Variable(torch.rand(1), requires_grad = True)
# 设置一个学习率
learning_rate = 0.0001;#学习率
复制代码

现在开始训练


#这里的a和b都是一个1维的自动微分变量
for i in range(1000):
    # 为了之后的计算,k.expand_as(x) 方法将a的维度扩展到和x一致,x是100维,k就会也变成一个100维张量
    predictions = k.expand_as(x)*x  +b.expand_as(x)
    # 损失函数定义方法: 我们要使预测出来的y值到真实y值的距离最小
    loss = torch.mean((predictions - y) ** 2)  # **2代表平方
    # 使用loss进行反向传播
    # loss在逐渐减小
    loss.backward()
    #获得k和b的变化梯度
    # 根据变化梯度和学习率获取到新的a b值
    k.data.add_(-learning_rate * a.grad.data)
    b.data.add_(-learning_rate * b.grad.data)
    
    # 梯度记得清空
    k.grad.data.zero_()
    b.grad.data.zero_()
复制代码

经过训练步骤后我们就获得了新的k和b,那么我们就可以画出这条一次函数了. 这时候我们需要引入计算包numby,将tensor转为可以绘图的数据

# 设置绘图画布大小
plt.figure(figsize = (10, 7))
#为了对比把离散点也画上
plt.plot(x.data.numpy(),y.data.numpy(), 'ro')
# 绘制函数
plt.plot(x.data.numpy(), a.data.numpy() * x.data.numpy() + b.data.numpy())
复制代码

image.png

大功告成

over ~~

下回我会写一篇真正的神经网络训练过程,更复杂也更有趣~ 敬请期待

参考资料 火炬上的深度学习-集智AI学园 pytorch官网 matplotlib绘图库官网

猜你喜欢

转载自juejin.im/post/5bd907306fb9a05cec4dfd56