使用tiny-cnn实现MNIST手写数字识别教程

使用tiny-cnn实现MNIST手写数字识别教程

tiny-dnn tiny-dnn 项目地址: https://gitcode.com/gh_mirrors/tin/tiny-dnn

前言

MNIST手写数字数据集是深度学习领域的"Hello World"项目,它包含了0-9的手写数字图片,每张图片都是28x28像素的灰度图。本文将介绍如何使用tiny-cnn这个轻量级深度学习框架来实现MNIST手写数字识别。

模型架构

我们采用经典的LeNet-5网络结构,这是Yann LeCun在1998年提出的卷积神经网络,专为手写数字识别设计。原始LeNet-5包含7层网络,包括卷积层、池化层和全连接层。

在tiny-cnn中实现的LeNet-5变体包含以下层次结构:

  1. 输入层(32x32,原始MNIST图片被填充到32x32)
  2. 卷积层C1(5x5卷积核,输出6个特征图)
  3. Tanh激活层
  4. 平均池化层S2(2x2)
  5. Tanh激活层
  6. 卷积层C3(5x5卷积核,输出16个特征图)
  7. Tanh激活层
  8. 平均池化层S4(2x2)
  9. Tanh激活层
  10. 卷积层C5(5x5卷积核,输出120个特征图)
  11. Tanh激活层
  12. 全连接层F6(120→10)
  13. Tanh激活层

代码实现详解

1. 网络构建

network<sequential> nn;
adagrad optimizer;

// 定义连接表(实现稀疏连接)
static const bool tbl [] = {
    O, X, X, X, O, O, O, X, X, O, O, O, O, X, O, O,
    // ...省略部分连接表数据
};

// 构建网络
nn << convolutional_layer(32, 32, 5, 1, 6, padding::valid, true, 1, 1)
   << tanh_layer(28, 28, 6)
   << average_pooling_layer(28, 28, 6, 2)
   // ...其他网络层
   << fully_connected_layer(120, 10, true)
   << tanh_layer(10);

这里有几个关键点需要注意:

  • 使用Adagrad优化器
  • 连接表(tbl)实现了S2到C3层的稀疏连接
  • 每层卷积后都使用Tanh激活函数
  • 使用平均池化而非最大池化

2. 数据加载与预处理

parse_mnist_labels("train-labels.idx1-ubyte", &train_labels);
parse_mnist_images("train-images.idx3-ubyte", &train_images, -1.0, 1.0, 2, 2);

数据预处理包括:

  • 将像素值从[0,255]归一化到[-1.0,1.0]
  • 在图像四周添加2像素的边框(28x28→32x32)
  • 自动解析MNIST的IDX格式文件

3. 训练过程

int minibatch_size = 10;
int num_epochs = 30;

// 定义回调函数
auto on_enumerate_epoch = [&](){
    // 每个epoch结束时测试准确率
    tiny_dnn::result res = nn.test(test_images, test_labels);
    std::cout << res.num_success << "/" << res.num_total << std::endl;
};

// 开始训练
nn.train<mse>(optimizer, train_images, train_labels, 
             minibatch_size, num_epochs,
             on_enumerate_minibatch, on_enumerate_epoch);

训练参数说明:

  • 使用均方误差(MSE)作为损失函数
  • 小批量大小为10
  • 训练30个epoch
  • 每个epoch结束后在测试集上评估性能

4. 模型保存与加载

// 保存模型
nn.save("LeNet-model");

// 加载模型
nn.load("LeNet-model");

tiny-cnn提供了简单的模型序列化功能,可以将整个网络结构和训练好的权重保存到单个文件中。

模型应用示例

训练完成后,我们可以使用模型进行手写数字识别:

// 加载图像并预处理
vec_t data;
convert_image("4.bmp", -1.0, 1.0, 32, 32, data);

// 预测
auto res = nn.predict(data);

// 输出top-3预测结果
for (int i = 0; i < 3; i++)
    cout << scores[i].second << "," << scores[i].first << endl;

输出示例:

4,78.1403
7,33.5718
8,14.0017

这表示模型以78.14%的置信度认为输入图片是数字"4"。

可视化分析

tiny-cnn还提供了可视化工具,可以查看各层的输出和卷积核:

// 保存各层输出
for (size_t i = 0; i < nn.depth(); i++) {
    auto out_img = nn[i]->output_to_image();
    out_img.save("layer_" + std::to_string(i) + ".png");
}

// 保存第一层卷积核
auto weight = nn.at<convolutional_layer>(0).weight_to_image();
weight.save("weights.png");

这些可视化可以帮助我们理解网络是如何处理输入图像的,以及卷积核学习到了什么样的特征。

性能优化建议

  1. 学习率调整:Adagrad优化器的初始学习率可以根据批量大小进行调整
  2. 批量大小:适当增大批量大小可以提高训练速度,但可能影响模型性能
  3. 激活函数:可以尝试使用ReLU替代Tanh,可能会获得更好的效果
  4. 数据增强:对训练数据进行旋转、平移等变换可以提高模型泛化能力

总结

通过tiny-cnn实现MNIST手写数字识别,我们展示了如何:

  1. 构建卷积神经网络
  2. 加载和预处理数据
  3. 训练和评估模型
  4. 保存和加载模型
  5. 使用模型进行预测
  6. 可视化网络内部状态

tiny-cnn作为一个轻量级深度学习框架,非常适合学习和快速原型开发。虽然功能不如大型框架全面,但其简洁的API和易于理解的实现使其成为入门深度学习的优秀工具。

tiny-dnn tiny-dnn 项目地址: https://gitcode.com/gh_mirrors/tin/tiny-dnn

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

周屹隽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值