#include <ccv.h>
int main()
{
// 加载 MNIST 数据集
ccv_array_t* const train_set = ccv_digits_read("train-images-idx3-ubyte.gz", "train-labels-idx1-ubyte.gz");
ccv_array_t* const test_set = ccv_digits_read("t10k-images-idx3-ubyte.gz", "t10k-labels-idx1-ubyte.gz");
// 创建神经网络模型
ccv_convnet_t* const convnet = ccv_convnet_new(
1, 28, 28, // 输入图像的通道数、宽度和高度
CCV_CATEGORICAL, 10, // 输出类别数
(ccv_convnet_layer_param_t []){
// 第一层为卷积层,采用 5x5 的卷积核,输出 20 个特征图
{
.type = CCV_CONVNET_CONVOLUTIONAL,
.input = CCV_CONVNET_INPUT_SAME,
.output = 20,
.kernel_size = 5,
.stride = 1,
.dilation = 0,
.count = 1,
.border_mode = 0,
.bias = 1,
.acts = CCV_RELU,
.rnorm = 0,
.size = {
.dim = { 0, 28, 28 },
.channels = 1,
},
},
// 第二层为最大池化层,采用 2x2 的池化窗口
{
.type = CCV_CONVNET_MAX_POOL,
.input = CCV_CONVNET_INPUT_SAME,
.output = 0,
.kernel_size = 2,
.stride = 2,
.dilation = 0,
.count = 1,
.border_mode = 0,
.size = {
.dim = { 0, 14, 14 },
.channels = 20,
},
},
// 第三层为全连接层,包含 500 个神经元
{
.type = CCV_CONVNET_FULL_CONNECT,
.input = CCV_CONVNET_INPUT_WHOLE,
.output = 500,
.bias = 1,
.acts = CCV_RELU,
.dropout = 0,
},
// 第四层为输出层,包含 10 个神经元,对应 0-9 十个数字的类别
{
.type = CCV_CONVNET_FULL_CONNECT,
.input = CCV_CONVNET_INPUT_WHOLE,
.output = 10,
.bias = 1,
.acts = CCV_SOFTMAX,
.dropout = 0,
},
}
);
// 设置训练参数
ccv_convnet_train_param_t params = {
.max_epoch = 10, // 最大训练轮数
.minibatch = 128, // 每个小批量的样本数
.momentum = 0.9, // 动量系数
.learning_rate = 0.001, // 初始学习率
.decay_rate = 0.0001, // 学习率衰减系数
.batch_normalize = 0, // 是否对每一层进行批量归一化
.gradient_clipping = 1, // 是否进行梯度裁剪
};
// 训练神经网络
ccv_convnet_supervised_train(convnet, train_set, test_set, params);
// 保存模型
ccv_convnet_save(convnet, "convnet-mnist.bin");
// 释放资源
ccv_array_free(train_set);
ccv_array_free(test_set);
ccv_convnet_free(convnet);
return 0;
}