在本文,我们将介绍如何通过使用 mxnet
的 api
实现线性回归。
Note:This blog without all the resources that are outside the original,reproduced please indicate the source.
官网指导:mxnet.incubator.apache.org,文中如有任何错漏的地方请谅解并指出,不胜感激.
我们尝试去学习的函数是 : (y = X1 + 2* X2 ),(X1,X2)
是输入特征,Y
是相应的标签.
前提
为了完成教程,我们需要做一下准备:
- 安装好mxnet.(可以看我相关的安装演示)
- 安装Jupyter Notebook
$ pip install jupyter
在实验之前,我们需要导入必要的包,在接下来的练习中会使用到他们.
import mxnet as mx
import numpy as np
import logging
logging.getLogger().setLevel(logging.DEBUG)
准备数据
在mxnet中,数据是通过数据迭代器输入的。在这里,我们将说明如何将数据转化为一个迭代器,MXNet可以使用。示例中使用的数据是由具有相应整数标签的2D
数据点组成的。
#Training data
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)])
batch_size = 1
#Evaluation Data
eval_data = np.array([[7,2],[6,10],[12,2]])
eval_label = np.array([11,26,16])
当我们准备好了数据,我们需要把�数据放进一个迭代器和指定参数,如batch_size
和shuffle
(混排)。batch_size
指定数量的例子证明我们每次更新模型参数和洗牌告诉迭代器随机化在其中显示的模型实例的顺序。
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)
在上面的例子中,我们使用了NDArrayIter
,这在numpy ndarrays
和 MXNet NDArrays
的迭代中是很有用的。总的来说,MXNet有很多不同类型的迭代器,你可以使用基于你正在处理的数据类型的迭代器。更多关于迭代器的文档请看这里
mxnet 类
-
IO
:我们已经看到过IO
类在数据上工作,并且执行批处理数据和混排等操作. -
Symbol
:实际上mxnet的神经网络是使用标识符组成的.mxnet有多种不同的标识符,例如:用于输入数据的变量占位符,神经网络层以及操作NDArrays
的操作符. -
Moudle
:�mxnet
中,�模块类用于定义总体计算.�模块会�跟随我们想要训练的模型一起初始化,一起初始化的还有:训练输入(数据和标签),一些额外的参数(如学习率),还有我们要使用的优化算法.
定义模型
mxnet
使用标识符来定义模型.标识符建立模块与组成模型的各个部分.标识通常用于:
- 变量:变量是未来数据的占位符。这个标识符用于定义将来训练时将填充训练数据/标签的一个点。
- 神经网络层:网络层或者其他�任意模型都是有标识符定义.这样的标识符接受一个或多个以前的符号作为输入,对它们执行一些转换,并创建一个或多个输出。�一个典型的例子就是
全连接标识符
(FullyConnected symbol
),她指定一个完全连接的圣经网络层. - 输出:输出标识符是mxnet定义损失的一种方式.他们的后缀都带有"
Output
"(例如 theSoftmaxOutput
layer),你也可以�创建你自己的损失函数,戳进去看看 . 现有损失的一些例子是:LinearRegressionOutput
,它计算输入符号和提供给它的标签之间的L2损失;SoftmaxOutput
,它计算范畴的交叉熵。
上面描述的和其他符号被链接在一起,一个符号的输出作为输入到下一个,以构建网络拓扑。
X = mx.sym.Variable('data')
Y = mx.symbol.Variable('lin_reg_label')
fully_connected_layer = mx.sym.FullyConnected(data=X, name='fc1', num_hidden = 1)
lro = mx.sym.LinearRegressionOutput(data=fully_connected_layer, label=Y, name="lro")
以上网络使用了以下层:
-
FullyConnected
: 这个全连接标识符代表了一个全连接的神经网络(不适用任何激活),本质上,这只是对输入属性的线性回归。它采用以下参数:-
data
:输入到层(指定符号的输出应该在这里提供) -
num_hidden
:层中隐含神经元数,与层输出维数相同。
-
-
LinearRegressionOutput
:mxnet
的输出层计算训练损失,它用来评估模型预测的精确度.训练的目的就是为了最小化训练损失.在例子中,LinearRegressionOutput
层根据其输入和提供给它的标签计算L2损失.这个LinearRegressionOutput
层的参数是:-
data
: 输入到层(指定符号的输出应该在这里提供) -
label
: 训练标签依靠我们输入与层的比较以计算L2损失.
-
注意命名约定:传入训练数据迭代器的标签变量命名应该像label_name
参数那样.他的默认命名是softmax_label
,但是我们可以把它改成lin_reg_label
,就像�上面的例子那样:
Y = mx.symbol.Variable('lin_reg_label')
train_iter = mx.io.NDArrayIter(..., label_name='lin_reg_label').
最后,�这个网络是模块的输入,我们在其中指定需要最小化输出的符号(在例子中是lro
或lin_reg_output
),并且学习率将用于优化过程�和影响我们想要训练模型的训练次数.
model = mx.mod.Module(
symbol = lro ,
data_names=['data'],
label_names = ['lin_reg_label']# network structure
)
我们可以通过绘制它来可视化我们创建的网络:
mx.viz.plot_network(symbol=lro)
模型训练
我们构件好模型结构后,下一步就是训练模型参数,使得他适用于训练数据.这可以用�Module
类的fit()
函数来实现:
model.fit(train_iter, eval_iter,
optimizer_params={'learning_rate':0.005, 'momentum': 0.9},
num_epoch=50,
eval_metric='mse',
batch_end_callback = mx.callback.Speedometer(batch_size, 2))
使用已经训练了的模型(测试和推理)
当我们有了已经训练好的模型后,我们可以用它来做一些事情.我们不仅可以用它来推理,还可以用它在测试数据的基础上对�已经训练好的模型进行评估.后者如下所示:
model.predict(eval_iter).asnumpy()
我们也可以根据一些指标来评估我们的模型.在这个例子中,我们在评估数据上评估我们模型的均方误差(MSE).
metric = mx.metric.MSE()
model.score(eval_iter, metric)
我们可以尝试给评估数据添加一些噪声,看看均方误差(MSE)会怎样变化:
eval_data = np.array([[7,2],[6,10],[12,2]])
eval_label = np.array([11.1,26.1,16.1]) #Adding 0.1 to each of the values
eval_iter = mx.io.NDArrayIter(eval_data, eval_label, batch_size, shuffle=False)
model.score(eval_iter, metric)
我们也可以建立一些常规的指标来评估�模型.更多的关于指标的信息请看API 文档 API documentation
网友评论