torch入门笔记2:用torch实现线性回归


代码地址:  https://github.com/vic-w/torch-practice/tree/master/linear-reg

神经网络是由很多逻辑回归的节点级联组成的。而所谓逻辑回归,就是一个线性变换连接一个Sigmoid函数。所以说线性回归是神经网络最基本的组成单元。
这里先介绍一下最简单的线性回归,也就是单输入单输出函数的拟合。它的效果等同于用最小二乘法在二维空间里拟合出一条直线。

X表示输入,Y是输出。他们的关系是Y=aX+b。其中a和b是两个可调的参数。

假设我们有一组x到y的映射。比如说x是2015年的月份,y是深圳当月房价均价。

X Y
1 28993
2 29110
3 29436
4 30791
5 33384
6 36762
7 39900
8 39972
9 40230
10 40146

我们认为这两个变量成线性关系y=ax+b(当然这只是假设)。
我们有了数据和模型,接下来我们要在Torch里面写一个程序来预测一下11月的房价是多少。

现在可以开始写程序了。

首先要包含一些必要的库
require 'torch' --Torch本身
require 'nn' --神经网络
require 'gnuplot' --画图的库

然后把我们的数据写进torch的tensor数据类型里。月份是1到10,价格是十个数字。
month = torch.range(1,10) --生成一个1维Tensor,其中有10个元素,元素的值为从1到10
price = torch.Tensor{28993,29110,29436,30791,33384,36762,39900,39972,40230,40146}

tensor这个东西翻如果译成中文是‘张量’,可以理解为高维的矩阵。它跟矩阵的区别是:矩阵只能是2维的,而张量可以是任意维度。所以在这里张量只是存放数据的一种形式,跟物理学上的张量没什么关系。

有了数据我们就要设计一个神经网络。这个网络非常简单,只有一个输入节点通过一条权重为a的边连接至输出节点。外加一个权重为b的偏置项。这个网络里只有a和b两个可调整的参数。a和b的初始状态是随机的。神经网络在初始化时参数必须是随机的,而不能是一个定值,否则用梯度下降法调整参数时所有的参数都将保持相等而不能达到最优化。这一点torch已经考虑到而且自动帮我们做了随机的初始化。



建立模型只需要一句代码
model = nn.Linear(1, 1)  --建立有1个输入,1个输出的线性回归模型
我们建立了一个模型model,这是一个线性回归模型,有1个输入和1个输出,模型的内部保存着两个参数,对应着前面所说的权重a和偏置b。

除了网络之外我们还要定义我们的训练评价标准。我们这里定义是MSECriterion。MSE就是Mean Squared Error均方误差。

criterion = nn.MSECriterion()


在开始迭代优化之前,我们还需要对我们的数据做一些处理。要把月份和价格的数据从1维的张量转换为一个2维的10x1的张量
month_train = month:reshape(10,1)
price_train = price:reshape(10,1)

这是Torch所能接受的格式。第一个维度10是batch size,也就是每次迭代放进去计算的数据的个数。因为我们只有10个数据,就全部放进去训练,这样的做法叫做full-batch,如果我们每次只放一部分数据进去,就叫做mini-batch。第二个维度1,表示我们的数据是1维的。

接下来就是做循环迭代了。
for i=1,1000 do
   price_predict = model:forward(month_train)  --model正向传播
   err = criterion:forward(price_predict, price_train) --criterion正向传播
   print(i, err)
   model:zeroGradParameters()
   gradient = criterion:backward(price_predict, price_train) --criterion反向传播
   model:backward(month_train, gradient) --model反向传播
   model:updateParameters(0.01) --更新参数
end

我们做了for循环1000次,在这个循环里面,我们做了几件事,就是我刚才描述反向传播算法。
第一,调用model:forward把月份的数据放进网络,得到价格的预测值。
第二,调用criterion:forward把预测值和实际值比较,得出误差
这两步是正向传播的过程,用图形来表示:



第三,把model内部的偏导数清零,这一句看起来有点无厘头,但还是不能不写。如果不清零的话,偏导数的值每次都会累加起来。Torch这么设计的目的应该是为了实现更复杂的梯度优化方法,但却让我们这个简单的程序白白多出一行看起来没用的语句。这就是我为什么说深度学习的这几个框架每个都有令人不爽的地方。

第四,调用criterion:backward通过误差值反向算出价格预测值的偏导数
第五,调用model:backward通过预测值的偏导数再反向推导出每个可调参数的偏导数



最后,调用model:updateParameters根据偏导数的大小调整参数,目的是使误差减小

ok,到这里为止,训练的代码就写完了。这一段循环内部的程序,是固定的样式,固定的顺序,你每次写一个神经网络训练程序的时候都要写这么一段。我十分不解,既然程序的模式是固定的,为什么torch在设计的时候为什么不把这一段程序封装起来,以免我每次写的时候出错。如果有朋友知道为什么,可以写信告诉我。

剩下的一段代码,是用我们训练好的网络去预测11月和12月的房价,方法就是再做一次正向传播。最后把数据在图上画出来,保存成png图片。
month_predict = torch.range(1,12)
local price_predict = model:forward(month_predict:reshape(12,1))
print(price_predict)

gnuplot.pngfigure('plot.png')
gnuplot.plot({month, price}, {month_predict, price_predict})
gnuplot.plotflush()


运行,在命令行键入
th linear-reg.lua
等待完成

打开图片我们看到,蓝色是实际的数据,绿色是我们预测得到的数据,他拟合出了一条最合适的直线。



但很明显这不太符合实际的情况。这种情况叫做high bias高偏置,解决的方法就是在网络里增加一些复杂度,也就是增加层数和节点数,让他能做出更加实际的判断。下一节,我将解释如何去实现。

本节完整的代码如下

require 'torch'
require 'nn'
require 'gnuplot'

month = torch.range(1,10)
price = torch.Tensor{28993,29110,29436,30791,33384,36762,39900,39972,40230,40146}

model = nn.Linear(1, 1)
criterion = nn.MSECriterion()

month_train = month:reshape(10,1)
price_train = price:reshape(10,1)

for i=1,1000 do
   price_predict = model:forward(month_train)
   err = criterion:forward(price_predict, price_train)
   print(i, err)
   model:zeroGradParameters()
   gradient = criterion:backward(price_predict, price_train)
   model:backward(month_train, gradient)
   model:updateParameters(0.01)
end

month_predict = torch.range(1,12)
local price_predict = model:forward(month_predict:reshape(12,1))
print(price_predict)

gnuplot.pngfigure('plot.png')
gnuplot.plot({month, price}, {month_predict, price_predict})
gnuplot.plotflush()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值