本文的完整代码托管在我的Github PY131/Practice-of-Machine-Learning,欢迎访问。
深度学习的概念起源于人工神经网络,本文所采用的包含多隐层的多层感知机(MLP)就是其中的典型模型。长期以来,由模型复杂度所带来的计算效率低下问题一直是抑制深度学习进一步发展的瓶颈。近年来,随着大数据、云计算的兴起以及进步的算法设计,以“深度学习”为代表的大容量复杂模型开始突破其效率瓶颈,走向实用。深度学习正被愈发广泛地应用于计算机视觉、语音识别、自然语言处理等领域,其所具备的强大学习能力已初现威力。
Theano是一个基于python的科学计算框架,它在集成了numpy/scipy的基础上,实现了对GPU的透明支持,theano常被用作深度学习的基础框架。下面回顾theano的几个基础概念(核心概念):
- tensor variable(张量)
- theano function(theano函数)
- shared variable(共享变量)
- gradient(梯度)
这里我们采用简单的单隐层MLP来实现,具体过程可参考:MNIST_Multilayer Perceptron。
这里列出一些建模过程中所要注意的内容:
查看完整代码和数据集
这里我采用规约好的MNIST数据集,相关内容可参考:Getting Started - Datasets - MNIST Dataset,数据集(mnist.pkl.gz)相关统计内容如下:
- 维度属性:
数据集包含3个子数据集,对应train_set、valid_set、test_set,样本规模分别为50000、10000、10000;
每条样本包含:
输入向量[1*784],对应输入图片灰度矩阵[28*28];
输出值,对应图片类别标签(数字0-9);
- 完整度:
样本完整;
- 平衡度:
未知;
- 更多信息:
手写字符所覆盖的灰度已被人工调整到了图片的中部。
根据上面的分析,在数据处理时需要对数据进行维度转换。
下面是一些样例图片:
首先给出基于python-theano编程实现MLP的步骤如下:
其中训练函数体的流程概述如下:
1. 加载数据,生成训练集、验证集、测试集;
2. 根据数据维度,生成对应的MLP网络结构;
3. 训练模型,更新参数,实时记录训练误差、分时记录验证误差和测试误差(泛化误差);
4. 达到训练停止条件(迭代次数、耐心指数),输出模型与相关记录信息;
简化的模型训练程序块样例如下:完整程序
# 函数参数包括相关参数设置
def test_mlp(learning_rate=0.01, # 学习率 (等号右边为默认值)
L1_reg=0.00, L2_reg=0.0001, # 正则化系数
n_epochs=1000, # 迭代次数
batch_size=20, # mini-batch大小
n_hidden=500, # 隐层节点数
dataset='mnist.pkl.gz' # 数据集
):
# 加载数据、获取训练集、验证集、测试集
datasets = load_data(dataset)
train_set_x, train_set_y = datasets[0]
valid_set_x, valid_set_y = datasets[1]
test_set_x, test_set_y = datasets[2]
...
# 初始化MLP网络结构和参数
classifier = MLP(
rng=rng,
input=x,
n_in=28 * 28,
n_hidden=n_hidden,
n_out=10
)
# 生成“似然+正则化”损失函数体
cost = (
classifier.negative_log_likelihood(y)
+ L1_reg * classifier.L1
+ + L2_reg * classifier.L2_sqr
)
# “模型测试”函数体
test_model = theano.function(...)
# “模型验证”函数体
validate_model = theano.function(...)
# “梯度计算”函数体
gparams = [T.grad(cost, param) for param in classifier.params]
# “参数更新”机制
updates = [
(param, param - learning_rate * gparam)
for param, gparam in zip(classifier.params, gparams)
]
# 训练函数体
train_model = theano.function(...)
###############
# 模型训练主体 #
###############
# 早停机制设计
...
# 迭代主体
while (epoch < n_epochs) and (not done_looping):
epoch = epoch + 1
# 一个块的迭代训练
for minibatch_index in range(n_train_batches):
# 一条样本迭代训练(前向计算、基于梯度的参数更新)
train_outputs = train_model(minibatch_index)
# 训练损失计算
minibatch_avg_cost = train_outputs[0]
# 验证块
# 达到验证所要求迭代次数 - 进行验证
validation_losses = [validate_model(i) for i in range(n_valid_batches)] # 计算0-1损失
this_validation_loss = numpy.mean(validation_losses) # 平均验证误差计算
# 记录最优信息
...
# 是否达到测试所要求条件 - 进行测试
test_losses = [test_model(i) for i in range(n_test_batches)] # 计算0-1损失
test_score = numpy.mean(test_losses) # 测试误差计算
...
# 早停判断
...
...
# 过程信息反回
return err_train, err_valid, err_test
通过合适的参数设置,记录训练过程中的训练误差(每iteration记录一次),验证误差(每epoch记录一次),测试误差(当验证精度提高时计算一次),得出三种误差的收敛曲线如下图示:
最终的分类结果如下:
Optimization complete. Best validation score of 1.880000 % (验证误差结果)
obtained at iteration 2077500, with test performance 1.840000 % (测试误差结果)
而整个程序运行时间为:
The code for file MLP.py ran for 68.32m (分钟)
我们可以对结果作如下分析:
这里采用python-theano实现了一个简单的多层感知机网络,并基于MNIST手写字符数据集实现了分类实验。
在这个过程中,我们回顾了神经网络的基础知识,练习了theano计算框架的使用,采用了相关辅助方法来优化训练,为后面开展“深度学习”研究积累了经验。
通过实验我们看到,一方面,神经网络模型训练往往伴随着巨大的计算量,相关参数设置也需要谨慎考虑并结合实验结果科学调整;另一方面,通过大量训练所得到的神经网络模型能够表现出优异的性能。
相关重要参考列出如下:
核心参考:
其他参考: