赞
踩
神经网络的基础概念非常重要,是后期深度学习的基石,对于初学神经网络的伙伴们来说,一般最好是从了解熟知感知机开始 :感知机(与门、与非门、或门、异或门)的实现
这节说的线性回归属于单层神经网络,将会学到什么是模型,怎么训练模型,怎么预测模型等,比如预测房价,其中影响房价的因素有很多,我们选取面积为x1、房龄为x2、真实售价为y,来预测房价,其中面积和房龄叫做房子(样本)的特征,真实价格叫做标签,我们从感知机可以写出它们的数学表达式
其中w1,w2是权重,b是偏差,它们是这个线性回归模型的参数,这样计算(预测)的价格的表达式就是模型
那为什么说是单层的神经网络呢?因为这个模型的输入层是没有涉及计算,所以层数是1,另外输出层的神经元和输入层的各个神经元完全连接,因此这里的输出层叫做全连接层或者叫做稠密层(Dense Layer)。这些涉及到的术语要很清楚指的是什么,不然后期多了,会有点糊涂。
模型设计好了,我们就开始进行训练,在本例中训练模型是为了更好的预测房价是吧,那换一种说法就是预测的房价尽可能的接近真实的房价,也就是让它们之间的误差尽可能的小,这样预测其他房子价格的时候,精度就会高,更接近真实的房价。
那如何来训练?首先我们需要大量的真实数据,通过这些真实数据(训练数据集或叫训练集)去做迭代,训练出泛化能力强的精度高的模型出来,在训练数据集的时候,我们会引用一个损失函数,这个损失函数的作用就是衡量误差的,一般来说,我们取训练集所有样本的误差的平均来衡量模型预测的质量。
对于怎么找到一组最优(近似最优)的模型参数呢?一般使用的最多最广泛的是随机梯度下降法(SGD),更完整详细的说明可以参看:
Python随机梯度下降法(一)
当学习出最优模型参数之后,就可以使用上面的线性回归模型来预测房价(除开训练集的其他数据集,或叫测试集)
线性回归模型的构建
- from mxnet import autograd,nd
-
- #生成一个训练数据集
- num_samples=1000 #样本个数
- num_features=2 #特征个数
- true_w=[5,-7.4] #真实权重
- true_b=8.8 #真实偏差
- features=nd.random.normal(scale=1,shape=(num_samples,num_features)) #根据批量样本和特征生成一个标准差为1,均值为0的正态分布的数据集
- labels=features[:,0]*true_w[0] + features[:,1]*true_w[1] + true_b #标签
- labels+=nd.random.normal(scale=0.01,shape=(labels.shape))#加一个噪声(数据集里的一些干扰信息)
-
- #读取数据集,每次返回batch_size个随机样本的特征和标签
- def data_iter(batch_size,features,labels):
- num_samples=len(features)
- indices=list(range(num_samples))
- random.shuffle(indices)
- for i in range(0,num_samples,batch_size):
- j=nd.array(indices[i : min(i+batch_size,num_samples)])
- yield features.take(j),labels.take(j) #take根据索引返回对应元素
-
- batch_size=10
- for X,y in data_iter(batch_size,features,labels):
- print(X,y)
- break
-
- #下面开始进行对参数的梯度迭代更新
- w=nd.random.normal(scale=0.01,shape=(num_features,1))
- b=nd.zeros(shape=(1,))
- w.attach_grad()
- b.attach_grad()
-
- #定义模型(在d2lzh包已定义)
- def linreg(X,w,b):
- return nd.dot(X,w)+b
-
- #平方损失函数(在d2lzh包已定义)
- def squared_loss(y_hat,y):
- return (y_hat-y.reshape(y_hat.shape))**2/2
-
- #随机梯度下降法(在d2lzh包已定义)
- def sgd(params,lr,batch_size):
- for param in params: #不直接使用-=,而使用for循环是MXNet不支持in-place
- param[:]=param-lr*param.grad/batch_size
-
- lr=0.03 #学习率(超参数)
- num_epochs=5 #迭代周期
- net=linreg
- loss=squared_loss
- for epoch in range(num_epochs):
- for X,y in data_iter(batch_size,features,labels):
- with autograd.record():
- l=loss(net(X,w,b),y) #小批量X和y的损失
- l.backward() #小批量损失对模型参数求梯度
- sgd([w,b],lr,batch_size)
- train_l=loss(net(features,w,b),labels)
- print('epoch %d,loss %f' % (epoch+1,train_l.mean().asnumpy()))
- print(w,b)
-
- [[ 0.86046714 0.06655062]
- [-1.0263956 -1.4340156 ]
- [-0.7464799 -1.1734369 ]
- [-0.5986544 -1.7862475 ]
- [ 0.5516758 0.2614431 ]
- [ 1.9585181 0.25282365]
- [ 1.1280887 1.2971296 ]
- [-0.5502624 0.6829922 ]
- [ 0.8451316 -1.2080427 ]
- [-0.819514 -1.2183683 ]]
- <NDArray 10x2 @cpu(0)>
- [12.610863 14.274499 13.760691 19.042149 9.634927 16.73366
- 4.8353267 0.984106 21.94241 13.718784 ]
- <NDArray 10 @cpu(0)>
- epoch 1,loss 0.196607
- epoch 2,loss 0.000572
- epoch 3,loss 0.000053
- epoch 4,loss 0.000052
- epoch 5,loss 0.000051
-
- [[ 4.9999046]
- [-7.4004917]]
- <NDArray 2x1 @cpu(0)>
- [8.799186]
- <NDArray 1 @cpu(0)>
- 从结果我们可以看出,训练出来的权重参数和预测的标签值与真实的权重和标签值非常接近
线性回归模型的简洁实现
实践当中我们一般都使用MXNet提供的Gluon接口来更方便地实现线性回归模型的训练操作。Gluon为我们提供了大量的预定义层,比如里面的nn模块,已经定义了大量的神经网络的层。其中导入模块一般写在最上面,这里为了更好的体现使用了Gluon接口来简洁的实现,所以就写在了需要的代码中间地方
- from mxnet import autograd,nd
-
- #生成一个训练数据集
- num_samples=1000 #样本个数
- num_features=2 #特征个数
- true_w=[5,-7.4] #真实权重
- true_b=8.8 #真实偏差
- features=nd.random.normal(scale=1,shape=(num_samples,num_features)) #根据批量样本和特征生成一个标准差为1,均值为0的正态分布的数据集
- labels=features[:,0]*true_w[0] + features[:,1]*true_w[1] + true_b #标签
- labels+=nd.random.normal(scale=0.01,shape=(labels.shape))#加一个噪声(数据集里的一些干扰信息)
-
- #读取数据集,使用gluon接口的data模块,由于data很多作为变量,所以别名为gdata
- from mxnet.gluon import data as gdata
-
- batch_size=10
- dataset=gdata.ArrayDataset(features,labels)#将训练集的特征和标签组合
- data_iter=gdata.DataLoader(dataset,batch_size,shuffle=True)#随机读取小批量
- for X,y in data_iter:
- print(X,y)
- break
-
- #定义模型
- from mxnet.gluon import nn
- net=nn.Sequential()#当作是串联各个层的一个容器
- net.add(nn.Dense(1))#Dense全连接层(稠密层),输出个数为1
-
- #初始化模型参数
- from mxnet import init
- net.initialize(init.Normal(sigma=0.01))#指定权重参数每个元素初始化为均值为0,标准差为0.01的正态分布,偏差参数默认为0
-
- #定义损失函数
- from mxnet.gluon import loss as gloss
- loss=gloss.L2Loss()#平方损失(L2范数损失)
-
- #指定训练算法并训练模型
- from mxnet import gluon
- trainer=gluon.Trainer(net.collect_params(),'sgd',{'learning_rate':0.03})
- num_epochs=5
- for epoch in range(1,num_epochs+1):
- for X,y in data_iter:
- with autograd.record():
- l=loss(net(X),y)
- l.backward()
- trainer.step(batch_size)#迭代模型参数
- l=loss(net(features),labels)
- print('epoch %d,loss:%f' % (epoch,l.mean().asnumpy()))
-
- dense=net[0]#Dense(2 -> 1, linear)
- print(dense.weight.data(),dense.bias.data())
-
- [[-0.52707773 -0.3183773 ]
- [-0.8742927 -0.4267638 ]
- [ 0.67303514 -0.49647954]
- [ 0.0672691 0.5915836 ]
- [ 0.10801227 0.5210501 ]
- [-1.0340341 0.32417756]
- [ 1.3193419 -0.7513297 ]
- [ 0.34880197 -0.3986237 ]
- [ 0.37714773 -2.389378 ]
- [-0.18407269 -0.02723058]]
- <NDArray 10x2 @cpu(0)>
- [ 8.544108 7.5977607 15.855234 4.7529902 5.484421 1.2227746
- 20.962944 13.484395 28.347012 8.074814 ]
- <NDArray 10 @cpu(0)>
- epoch 1,loss:0.144768
- epoch 2,loss:0.000310
- epoch 3,loss:0.000054
- epoch 4,loss:0.000053
- epoch 5,loss:0.000053
-
- [[ 5.0000153 -7.4002795]]
- <NDArray 1x2 @cpu(0)>
- [8.799638]
- <NDArray 1 @cpu(0)>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。