MXnet实战之线性回归
2017-10-27 16:20
267 查看
线性回归介绍
线性回归模型的目标是找一根线,使得这根线能很好得拟合训练数据并且能够很好得泛化。当使用线性回归模型时,问题应该定义成回归问题,数据集应该处理成(X,Y),其中X是具体情况下每条样本得特征,维度按照实际情况定义,但要保证所有数据维度相同,Y为对应的目标值。特征X每个维度都有个权值,用向量w表示,b表示偏置,用数学符号表示为:Y^ = Xw + b
训练过程:首先我们随机初始化w和b(其实就是模型要训练得到的参数)。对于训练集,我们输入每个X,都有其对应的真实目标值Y,然后按照Xw + b可以计算出实际值Y^,模型训练的目标就是调整参数w和b,使得对于所有训练集,实际值和真实值越靠近越好。那么如何数学化这个问题呢?我们可以通过下面这个式子:
模型训练的目标就是调整w和b,最小化上式,这个在机器学习里面也叫损失函数或者成本函数(上式为平方损失函数)。
实际上线性回归是最简单的神经网络模型。对于线性回归而⾔,它是⼀个两层神经网络,其中第⼀层是(下图橙⾊点)输⼊,每个节点对应输⼊数据点的⼀个维度,第⼆层是单输出节点(下图绿⾊点),它使⽤函数(f(x) = x)作为激活函数。
从0开始学习实现线性回归
代码如下:#!/usr/bin/env python # -*- coding:utf-8 -*- #Author: yuquanle #2017/10/11 #沐神教程实战之线性回归 #本例子使用人工生成数据集做线性回归 import random from mxnet import ndarray as nd from mxnet import autograd num_inputs = 2 num_examples = 1000 batch_size = 10 # 按照Y[i] = 2 * X[i][0] -3.4 * X[i][1] + 4.2 + noise产生人工数据 true_w = [2, -3.4] true_b = 4.2 X = nd.random_normal(shape=(num_examples, num_inputs)) Y = true_w[0] * X[:, 0] + true_w[1] * X[:, 1] + true_b # 生成的Y加入噪声0.01 + nd.random_normal(shape=Y.shape) Y += 0.01 + nd.random_normal(shape=Y.shape) #print(X[0], Y[0]) # 数据生成器,每次随机num_examples/batch_size组数据样本,一组样本随机包含batch_size个数据点 def data_iter(): # 产生一个随机索引idx,相当与打乱数据集 idx = list(range(num_examples)) random.shuffle(idx) # i 从0开始,每隔10个数取一个,比如970,980,990 for i in range(0, num_examples, batch_size): # 选择idx中下标从i开始到i+batch_size的数组成j j = nd.array(idx[i:min(i+batch_size,num_examples)]) # take(X, j)表示去X中拿下表为j的数 yield nd.take(X, j), nd.take(Y, j) # for data, label in data_iter(): # print(data, label) # break # 初始化模型参数,w随机初始化,b初始化为0 w = nd.random_normal(shape=(num_inputs, 1)) b = nd.zeros((1,)) params = [w, b] # 后面的训练需要求导来更新这些参数的值,需要提前创建它们的梯度 for param in params: param.attach_grad() # 定义线性回归模型:y = Wx + b # w,b为模型需要学习的参数 def net(X): return nd.dot(X, w) + b # 定义模型的损失函数,这里使用常见的平方误差 def square_loss(yhat, y): # 把y变形为yhat的形状来避免自动广播 return (yhat - y.reshape(yhat.shape)) ** 2 # 定义优化方法 # 大多数模型没有显示解,常用梯度下降来(SGD)求解 def SGD(params, lr): for param in params: param[:] = param - lr * param.grad # 模型的训练 # 训练过程通常需要多次迭代数据,迭代一次为一个epoch。一次迭代里,随机读取固定batch_size个数据点,计算梯度并更新参数 epochs = 5 learning_rate = 0.001 for e in range(epochs): total_loss = 0 # 每次随机取batch_size个数据点 for data, label in data_iter(): with autograd.record(): output = net(data) loss = square_loss(output, label) loss.backward() # 梯度下降更新参数 SGD(params, learning_rate) total_loss += nd.sum(loss).asscalar() print("Epoch %d, average loss: %f" % (e, total_loss/num_examples)) # 训练完成之后,模型学到参数w,b。我们和真实参数比较 print(true_w, w) print(true_b, b)
实验结果:
线性回归—使用 Gluon
Gluon是一个基于MXnet更高层抽象的包,使用它可以更方便的实现一些模型使用Gluon实现的线性回归代码如下:
#!/usr/bin/env python # -*- coding:utf-8 -*- #Author: yuquanle #2017/10/14 #沐神教程实战之线性回归 #本例子使用人工生成数据集做线性回归,使用高层抽象包gluon实现 import random from mxnet import ndarray as nd from mxnet import autograd from mxnet import gluon num_inputs = 2 num_examples = 1000 # 按照Y[i] = 2 * X[i][0] -3.4 * X[i][1] + 4.2 + noise产生人工数据 true_w = [2, -3.4] true_b = 4.2 X = nd.random_normal(shape=(num_examples, num_inputs)) Y = true_w[0] * X[:, 0] + true_w[1] * X[:, 1] + true_b # 生成的Y加入噪声0.01 + nd.random_normal(shape=Y.shape) Y += 0.01 + nd.random_normal(shape=Y.shape) #print(X[0], Y[0]) # 数据生成器,每次随机num_examples/batch_size组数据样本,一组样本随机包含batch_size个数据点 def data_iter(): # 产生一个随机索引idx,相当与打乱数据集 idx = list(range(num_examples)) random.shuffle(idx) # i 从0开始,每隔10个数取一个,比如970,980,990 for i in range(0, num_examples, batch_size): # 选择idx中下标从i开始到i+batch_size的数组成j j = nd.array(idx[i:min(i+batch_size,num_examples)]) # take(X, j)表示去X中拿下表为j的数 yield nd.take(X, j), nd.take(Y, j) # 定义模型 # gluon提供大量提前定制好的层。线性模型就是使用对应的Dense层。 # 利用Sequential将所有层串起来 net = gluon.nn.Sequential() # 加入Dense层,Dense层唯一需要定义的参数是输出节点的个数,线性模型为1。 # 注意:这里没说输入节点个数,这个后面真正给数据的时候系统会自动赋值。 net.add(gluon.nn.Dense(1)) # 模型初始化 net.initialize() # gluon提供的平方误差函数 square_loss = gluon.loss.L2Loss() # 不需要手动实现SGD,只需创建一个Trainer的实例,并且将模型参数传递给它就行。 trainer = gluon.Trainer(net.collect_params(), 'sgd', {'learning_rate': 0.1}) # 训练过程基本一致,唯一区别是不再调用SGD而是用trainer.step更新模型 epochs = 5 batch_size = 10 for e in range(epochs): total_loss = 0 for data, label in data_iter(): with autograd.record(): output = net(data) loss = square_loss(output, label) loss.backward() trainer.step(batch_size) total_loss += nd.sum(loss).asscalar() print("Epoch %d, average loss: %f" % (e, total_loss / num_examples)) # 训练完成之后,模型学到参数w,b。我们与真实参数比较 # 先从net拿到需要的层 dense = net[0] print(true_w, dense.weight.data()) print(true_b, dense.bias.data())
实验结果如下:
Epoch 0, average loss: 1.380673 Epoch 1, average loss: 0.467346 Epoch 2, average loss: 0.463143 Epoch 3, average loss: 0.470569 Epoch 4, average loss: 0.470368 [2, -3.4] [[ 2.08668685 -3.4323175 ]] <NDArray 1x2 @cpu(0)> 4.2 [ 4.3376236] <NDArray 1 @cpu(0)>
我们可以发现,训练求得的参数w和b和真实参数基本一致。
相关文章推荐
- 用Mxnet对California房地产数据做线性回归分析
- MXnet代码实战之多类逻辑回归
- [MxNet]Lecture01-线性回归从零实现
- [MxNet]Lecture01-线性回归的gluon实现
- 用MXnet实战深度学习之二:Neural art
- 用MXnet入门实战深度学习之一:安装GPU版mxnet并跑一个MNIST手写数字识别
- Tensorflow实战学习(八)【机器学习基础 线性回归】
- MXnet实战心得---值得拥有
- python实战之线性回归、局部加权回归
- Python线性回归实战分析
- 用MXnet入门实战深度学习之一:安装GPU版mxnet并跑一个MNIST手写数字识别
- PyTorch:线性回归和逻辑回归实战
- 机器学习MatLab实战整理--线性回归
- 用MXnet入门实战深度学习之一:安装GPU版mxnet并跑一个MNIST手写数字识别
- SparkML实战之一:线性回归
- Windows上mxnet实战深度学习:Neural Net
- MLlib线性回归实战
- machine learning 线性回归实战
- 学习笔记【机器学习重点与实战】——1 线性回归
- MXnet代码实战之正则化