MXNet网络模型(一)—— 线性回归
- 线性回归
- 网络模型
- Show me the code!
线性回归
线性回归是机器学习中一个简单的例子,使用线性回归,可以简单地入门机器学习。
在这个例子里面,我们使用的函数关系式是:y = x1 + 2 * x2
步骤如下:
- 生成随机数对 x1 和 x2
- 求 与 ( x1, x2 ) 对应的 y
- ( x1, x2 ) 作为数据样本,y 作为数据标签,输入到神经网络
- 在测试集上进行测试,将测试效果作为神经网络的评价
当然,在将数据输入到神经网络之前,我们还需要定义一个网络模型。
网络模型
对于简单的线性回归,我们只需要一个多层感知器(Multilayer Perceptron)就可以了。
我们可以看到包含输入、输出、中间层在内,一共有3层。但是一般来说,输入层是不算的,所以这个是2层感知器,也可以说是2层神经网络。
Show me the code!
# -*- coding: utf-8 -*-
import mxnet as mx
import numpy as np
import logging
logging.getLogger().setLevel(logging.DEBUG)
# 设置随机数种子
mx.random.seed(42)
# 批大小
batch_size = 10
'''
************************************************************
* 数据准备
************************************************************
'''
# 训练集数据
train_data = np.random.uniform(0, 1, [100, 2])
train_label = np.array([train_data[i][0] + 2 * train_data[i][1] for i in range(100)])
# 验证集数据
eval_data = np.random.uniform(0, 1, [20, 2])
eval_label = np.array([eval_data[i][0] + 2 * eval_data[i][1] for i in range(20)])
# 测试集数据
test_data = np.random.uniform(0, 1, [10, 2])
test_label = np.array([test_data[i][0] + 2 * test_data[i][1] for i in range(10)])
# 准备好的数据需要放入迭代器中
# 这里使用的是NDArrayIter迭代器,事实上,MXNet还提供了其他迭代器可以使用
train_iter = mx.io.NDArrayIter(
train_data,
train_label,
batch_size,
shuffle=True ,
label_name='lin_reg_label'
)
eval_iter = mx.io.NDArrayIter(
eval_data,
eval_label,
batch_size,
shuffle=False,
label_name='lin_reg_label'
)
test_iter = mx.io.NDArrayIter(
test_data,
test_label,
batch_size,
shuffle=False,
label_name='lin_reg_label'
)
'''
************************************************************
* 定义神经网络模型
************************************************************
'''
# 一个模型需要输入层、隐藏层、输出层
# MXNet定义模型使用使用sym/symbol来定义
# 输入层通常是var/Variable
# 输出层的后缀是Output,输出层包括了损失层
# 定义输入层
X = mx.sym.var('data') # X = mx.symbol.Variable('data') 两者等价
Y = mx.sym.var('lin_reg_label') # Y = mx.symbol.Variable('lin_reg_label') 两者等价
# 定义隐藏层
net = mx.sym.FullyConnected(name='fc1', data=X, num_hidden=1)
# 定义输出层
net = mx.sym.LinearRegressionOutput(name='lro', data=net, label=Y)
# 将一层一层的神经元拼凑成模型
model = mx.mod.Module(
symbol=net,
data_names=['data'],
label_names=['lin_reg_label']
)
# 模型可视化
# shape = {'data':(batch_size, 1, 1, 2)}
# mx.viz.plot_network(symbol=net, shape=shape).view() # 显示模型结构图
# mx.viz.print_summary(symbol=net, shape=shape) # 显示模型参数
'''
************************************************************
* 训练神经网络
************************************************************
'''
model.fit(
train_iter, # 设置训练迭代器
eval_data=eval_iter, # 设置验证迭代器
num_epoch=20, # 训练轮数
eval_metric='mse', # 损失函数
optimizer='sgd', # “随机梯度下降”求解器
optimizer_params={
'learning_rate': 0.01, # 学习率
"momentum": 0.9 # 惯性动量
}
)
'''
************************************************************
* 在测试集上测试网络
************************************************************
'''
metric = mx.metric.MSE() # 设置评价函数
mse = model.score(test_iter, metric) # 测试并评价
print( "\ntest's mse: " + str(mse[0][1]) ) # 打印测试结果
# end of file
运行后,我们可以得到类似这样的输出:
INFO:root:Epoch[0] Train-mse=0.309735
INFO:root:Epoch[0] Time cost=0.045
INFO:root:Epoch[0] Validation-mse=0.077212
INFO:root:Epoch[1] Train-mse=0.042582
INFO:root:Epoch[1] Time cost=0.039
INFO:root:Epoch[1] Validation-mse=0.023031
...
INFO:root:Epoch[18] Train-mse=0.000000
INFO:root:Epoch[18] Time cost=0.036
INFO:root:Epoch[18] Validation-mse=0.000000
INFO:root:Epoch[19] Train-mse=0.000000
INFO:root:Epoch[19] Time cost=0.042
INFO:root:Epoch[19] Validation-mse=0.000000
[('mse', 0.010015469044446945)]
一共训练了20轮;Train-mse
是训练集损失,Validation-mse
是验证集损失,Time cost
是每轮训练所消耗的时间。最后的mse是测试集损失。
可以看到通过训练,mse不断地下降,最后神经网络 “ 学会了 ” 线性回归。