CNN-RNN通用分类MATLAB代码
最后更新于:2026-07-28 07:39:47
本文介绍一套 MATLAB 版 CNN-RNN 通用分类代码。程序不把输入限制为单一的“序列分类”格式,而是允许用户在每条样本内部指定一个有顺序的维度,再把其他维度整理成每个位置上的特征,因此可以用同一个核心函数处理一维数组、多通道传感器序列、灰度图以及更高维数值样本。
- 提供 Iris 一维特征、UCI HAR 九通道人体活动序列、MNIST 二维灰度图三个演示案例。
- 可以通过
sampleDimension指定样本维,通过sequenceAxis指定 CNN-RNN 实际读取的有序轴。 - 可以自由设置卷积层数量、卷积通道数、卷积核、池化窗口、循环网络类型、隐藏单元和 Dropout。
- MATLAB 版支持 LSTM、GRU、BiLSTM 三种循环结构。
- 支持分层随机划分,也支持通过
splitLabels按人员、设备或批次预先指定训练集、验证集和测试集。 - 标准化参数只使用训练集计算,再应用到验证集和测试集,避免归一化阶段的数据泄漏。
- 程序运行后自动计算 Accuracy、宏平均 Precision、Recall、F1 和逐类别指标,并生成收敛图、混淆矩阵、逐类别指标、分类结果对比和三集合指标对比图。
- 可设置随机种子、求解器、训练轮数、学习率、批尺寸、早停、学习率衰减和训练设备。
- 需要做的主要工作是导入自己的
X、Y,选对序列轴并调整参数;固定流程已封装在FunClassCNNRNN中。
一、代码运行环境
推荐使用 MATLAB R2024a,并安装 Deep Learning Toolbox。代码使用了 convolution1dLayer、lstmLayer、gruLayer、bilstmLayer、trainNetwork、trainingOptions 和 exportgraphics 等函数。
公开版按 MATLAB R2022a 兼容格式制作,需使用 MATLAB R2022a 或更新版本;为了获得与本文测试一致的行为,推荐使用 MATLAB R2024a。
二、程序介绍
完整版文件结构如下:
CNN_RNN_Classification/
├── demoCNNRNNClassIris.m
├── demoCNNRNNClassHAR.m
├── demoCNNRNNClassMNIST.m
├── FunClassCNNRNN.m
├── EvaClassEffect.m
├── iris.csv
├── har_activity_data.mat
├── mnist_subset.mat
├── 数据来源与许可.txt
├── 代码说明.txt
└── figure/
注:三个 demo*.m 都是可以直接运行的脚本;FunClassCNNRNN.m 和 EvaClassEffect.m 是函数文件,需要由 demo 或自己的脚本传入数据后调用。
1. demoCNNRNNClassIris.m 文件
该脚本演示二维表格形式的一维特征分类。X 的尺寸是 150×4,150 表示样本数,4 表示每条样本的四个特征位置;Y 是150个类别标签。程序把四个特征位置作为长度为4的短序列,使用一层 CNN 和 LSTM 完成三分类。
核心调用为:
[foreData, foreDataTrain, net, info] = FunClassCNNRNN(X, Y, options);
本次完整复验的测试集 Accuracy 为 0.9000,Macro-F1 为 0.8977。

图 1 的行表示真实类别,列表示预测类别。主对角线数值越集中,说明三个类别越少互相混淆。
2. demoCNNRNNClassHAR.m 文件
该脚本演示真正的多通道传感器序列分类。X 的尺寸为 2700×9×128:2700条样本,每条样本有9个传感器通道和128个连续时间点;Y 对应行走、上楼、下楼、坐着、站立和躺着六种活动。
HAR 案例没有随机把相似片段拆到三个集合,而是通过 splitLabels 按受试者隔离:1500条训练样本、480条验证样本、720条测试样本。这样能减少同一个人的相似动作同时出现在训练集和测试集造成的指标虚高。
本次完整复验的测试集 Accuracy 为 0.9014,Macro-F1 为 0.9009。

图 2 左侧观察训练损失和验证损失是否一起下降,右侧观察两组准确率是否逐步稳定。若训练准确率继续上升而验证准确率明显下降,通常说明开始过拟合。

图 3 显示六种活动的具体混淆位置。人体活动识别中,“坐着”和“站立”通常比“行走”和“躺着”更容易相互混淆,因此不能只看总准确率,还要看矩阵中的错误流向。

图 4 分别展示每个活动类别的 Precision、Recall 和 F1,用于发现总准确率掩盖的薄弱类别。
3. demoCNNRNNClassMNIST.m 文件
该脚本演示二维灰度图分类。X 的尺寸为 5000×28×28,表示5000张高28、宽28的灰度图;程序沿图像宽度方向逐列读取,每一步把一整列28个像素作为特征,再由 CNN 提取相邻列的笔画模式,由 GRU 汇总整张图的信息。
本次完整复验的测试集 Accuracy 为 0.9250,Macro-F1 为 0.9248。

图 5 展示0~9十个数字的测试集混淆情况。除总准确率外,可以重点观察哪些笔画结构接近的数字更容易被混淆。
4. FunClassCNNRNN.m 文件
该文件是通用分类核心函数。它负责输入维度适配、数据划分、训练集标准化、CNN-RNN 网络搭建、训练与验证、分类预测、指标计算以及全部绘图。
[foreData, foreDataTrain, net, info] = FunClassCNNRNN(X, Y, options)
输入参数:
X:任意维度的有限数值数组,不能含 NaN 或 Inf。必须有一维对应样本,并在单条样本内部选择一个有实际顺序的sequenceAxis。Y:每条样本的类别标签,长度必须等于样本数。支持数值、categorical、string或cellstr。options:数据适配、划分、网络、训练和绘图设置;可省略部分字段,未设置字段采用默认值。
输出参数:
foreData:最终测试集预测标签。foreDataTrain:训练集预测标签。net:训练完成的 MATLAB 神经网络。info:包含训练/验证/测试索引和真实标签、验证集预测、三集合类别得分、Accuracy/Precision/Recall/F1、混淆矩阵、训练记录、标准化均值与标准差、输入尺寸适配记录、类别顺序和完整options。
输入适配参数
| 参数 | 默认值 | 允许取值 | 含义与注意事项 |
|---|---|---|---|
sampleDimension |
'auto' |
'auto' 或有效维度编号 |
指定 X 中哪一维是样本维。自动模式优先识别第一维,再兼容最后一维。明确编号按 MATLAB 从1开始。 |
sequenceAxis |
-1 |
单条样本内部的有效维度编号 | 指定哪一维具有顺序,按1开始;-1 表示最后一维。一维数组设1,[通道,时间] 设2,[高,宽] 逐列读图设2。选错轴时程序可能能运行,但模型学到的相邻关系没有实际意义。 |
程序会把样本维移到最前面,把序列轴移到最后,再把其余维度合并成每个序列位置上的特征,最终统一为“样本数×特征数×序列长度”。
数据划分参数
| 参数 | 默认值 | 允许取值 | 含义与调参影响 |
|---|---|---|---|
splitLabels |
[] |
与Y等长的1/2/3数组 | 预定义划分:1=训练集、2=验证集、3=测试集。适合按人员、设备、批次隔离;设置后随机划分参数不负责集合划分。 |
rTrain |
0.80 |
(0,1) |
训练+验证数据占全部样本的比例,剩余样本作为最终测试集。它不是纯训练集比例。 |
validationRatio |
0.15 |
(0,1) |
验证集占训练+验证数据的比例。验证集用于模型选择和早停,测试集只在训练结束后评估。 |
shuffle |
true |
true/false |
是否在分层划分前打乱独立样本。存在严格时间或分组关系时应提供 splitLabels,不能随意打乱。 |
seed |
42 |
非负整数 | 固定数据划分和初始化,便于复现;设0表示不固定随机过程。GPU底层算子仍可能产生末位波动。 |
网络结构参数
| 参数 | 默认值 | 允许取值 | 含义与调参影响 |
|---|---|---|---|
networkType |
'LSTM' |
'LSTM'/'GRU'/'BiLSTM' |
循环层类型。GRU更精简;BiLSTM同时读取窗口内两个方向,但参数量和计算量更大。 |
convChannels |
[32,64] |
正整数数组 | 每个一维卷积层的输出通道数,数组长度就是卷积层数。增大容量也会增加耗时和过拟合风险。 |
kernelSize |
5 |
正奇数 | 卷积核长度。越大一次观察的相邻位置越宽;短序列通常使用3。 |
poolSize |
2 |
正整数,不超过序列长度 | 最大池化窗口;设1表示不池化。池化过大会丢失短序列细节。 |
rnnHidden |
64 |
正整数 | 循环层隐藏单元数。增大可提升记忆容量,也会增加训练时间和过拟合风险。 |
dropout |
0.20 |
[0,1) |
分类层前随机失活比例。过拟合时可适当增大;过大可能导致欠拟合。 |
训练参数
| 参数 | 默认值 | 允许取值 | 含义与调参影响 |
|---|---|---|---|
solverName |
'adam' |
'adam'/'sgdm'/'rmsprop' |
参数更新方法。Adam通常适合作为初始选择。 |
maxEpochs |
40 |
正整数 | 最大训练轮数,可能因早停提前结束。轮数过少会欠拟合,过多会增加耗时。 |
learnRate |
0.001 |
正数 | 初始学习率。过大容易震荡,过小收敛缓慢。 |
batchSize |
64 |
正整数 | 批尺寸。大批次更平稳但占更多内存;小数据通常可使用16或32。 |
earlyStoppingPatience |
8 |
非负整数 | 验证损失连续多少次不改善后停止;设0关闭早停。 |
learnRateSchedule |
'none' |
'none'/'piecewise' |
是否分段降低学习率。 |
learnRateDropPeriod |
15 |
正整数 | piecewise 模式下每隔多少轮衰减一次。 |
learnRateDropFactor |
0.5 |
(0,1] |
每次衰减后学习率乘以的系数。 |
classWeight |
'auto' |
'auto'/'none' 或正数数组 |
auto 只根据训练集类别频数计算反比权重;自定义数组长度必须等于类别数。 |
executionEnvironment |
'auto' |
'auto'/'cpu'/'gpu' |
指定训练设备。没有合适GPU时可使用CPU。 |
数据处理与绘图参数
| 参数 | 默认值 | 允许取值 | 含义与注意事项 |
|---|---|---|---|
mapflag |
'on' |
'on'/'off' 或 logical |
是否标准化。开启时均值和标准差只从训练集计算,避免提前看到验证和测试数据。 |
figflag |
'on' |
'on'/'off' 或 logical |
是否生成并保存五张结果图。批量调参时可关闭。 |
showFigures |
'on' |
'on'/'off' 或 logical |
是否在运行时弹出图窗;关闭时仍可由 figflag 决定是否保存。 |
caseName |
'CNN-RNN' |
字符串 | 结果图文件名前缀,用于避免多个案例互相覆盖。 |
classNames |
[] |
与类别数一致的名称列表 | 绘图显示名称,顺序必须与排序后的真实类别一致。 |
5. EvaClassEffect.m 文件
该函数计算多分类指标:
ind = EvaClassEffect(realData, foreData, classOrder)
realData:真实类别。foreData:预测类别。classOrder:可选的固定类别顺序。ind:返回 Accuracy、MacroPrecision、MacroRecall、MacroF1、逐类别 Precision/Recall/F1、Support、ConfusionMatrix 和 ClassOrder。
6. 数据文件
iris.csv:Iris 三分类数据。har_activity_data.mat:UCI HAR 九通道传感器序列及受试者隔离划分。mnist_subset.mat:MNIST 0~9十分类的5000张灰度图子集。数据来源与许可.txt:记录数据来源与许可。其中 UCI HAR 按 CC BY 4.0 使用。
7. figure 文件夹
每个案例自动生成5张独立PNG,因此三个demo共生成15张图:收敛过程、测试集混淆矩阵、逐类别指标、测试集真实/预测类别对比、训练/验证/测试指标对比。完整版图片无水印。
8. 代码说明.txt 文件
该文件是随代码交付的离线使用手册,包含运行环境、所有入口参数、输出说明、数据替换方法和注意事项。
三、快速开始
1. 运行测试脚本
在 MATLAB 中打开代码文件夹并设为当前文件夹,根据自己的数据类型选择一个demo:
demoCNNRNNClassIris % 一维数组
demoCNNRNNClassHAR % 多通道序列
demoCNNRNNClassMNIST % 二维灰度图
程序无报错、命令行输出三集合指标,并在 figure/ 中生成对应的5张图片,即说明环境和代码正常。
2. 替换成自己的数据
复制一个最接近自己输入形状的demo,在副本中只修改数据导入部分。例如普通二维数组:
data = readmatrix('your_data.csv');
X = data(:, 1:end-1);
Y = data(:, end);
options.sequenceAxis = 1;
多通道序列建议整理为:
% X:[样本数, 通道数, 时间长度]
% Y:[样本数, 1]
options.sequenceAxis = 2;
灰度图建议整理为:
% X:[样本数, 高度, 宽度]
% Y:[样本数, 1]
options.sequenceAxis = 2; % 沿宽度逐列读取
彩色图也可以使用,但需要明确图像的维度排列和希望沿哪个方向读取。例如 [样本数,高度,宽度,通道] 沿宽度读取时,sequenceAxis=2,高度和通道会合并为每一步的特征。对于需要严格保持二维空间局部关系的图像任务,标准二维CNN通常更自然;本程序适合希望把某一图像方向作为序列读取的场景。
3. 选择正确的数据划分
独立样本可以使用 rTrain 和 validationRatio 分层随机划分。同一个人员、设备、工况或批次产生多条相似样本时,建议提前生成 splitLabels,确保相关样本不会跨集合泄漏。时间序列窗口也不应简单随机拆分未来数据。
4. 调整参数并运行
优先确认 sequenceAxis 的业务含义,再调整 networkType、convChannels、kernelSize、poolSize 和 rnnHidden。训练不稳定时检查学习率;训练集明显优于验证集和测试集时,考虑减小网络、增加 Dropout、增加数据或改进分组划分。
四、关于完整版与公开版代码
| 功能 | 完整版 | 公开版 |
|---|---|---|
| Iris一维特征演示 | √ | √,90条 |
| HAR多通道序列演示 | √ | √,96条 |
| MNIST图像演示 | 0~9十分类,5000张 | 0/1/2三分类,90张 |
| 自定义数据、参数设置 | √ | √ |
| 核心函数源码 | 提供 | 不提供 |
| 最大样本数 | 无人工限制,受内存和硬件约束 | 100条 |
| 最大卷积层数 | 无试用版限制 | 2层 |
| 最大训练轮数 | 无试用版限制 | 30轮 |
| 循环结构 | LSTM、GRU、BiLSTM | LSTM、GRU |
| 最大隐藏单元数 | 无试用版限制 | 64 |
| 自动分类指标和15张案例图 | √ | √ |
| 结果图水印 | 无水印 | 有“试用版@khsci.com/docs”水印 |
| 修改核心实现与二次开发 | √ | × |
公开版用于检查运行环境、理解输入格式并体验调用流程;正式训练、大样本任务和二次修改建议使用完整版。
五、获取公开版程序
注:公开版需要 MATLAB R2022a 或更新版本,最多支持100条样本,最多训练30轮,结果图带试用版水印。
六、获取完整版程序
点击本页面“立即支付”按钮,付款后获取完整版代码下载链接和售后联系方式。付款完成后刷新本页面即可看到下载链接。
(注意支付跳转失败的话,请使用浏览器打开本页面)
七、完整版代码重要更新
- 20260720:完成 MATLAB 版初版代码,支持一维数组、多通道序列、灰度图和更高维输入适配;提供 Iris、UCI HAR、MNIST 三个案例以及15张自动结果图。
八、常见问题
Q1:这是不是只能做时间序列分类?
不是。它做的是多分类,输入可以是一维特征、多通道序列或图像。关键要求不是“数据必须来自时间”,而是你指定的 sequenceAxis 必须有合理顺序,例如时间、波长、距离或图像扫描方向。
Q2:任意维度都能用,是不是所有数据都适合 CNN-RNN?
不是。程序可以整理任意维度数值数组,但模型会把序列轴上的相邻位置当成有意义的邻居。如果各列只是随意排列的表格字段,CNN和RNN的结构假设可能不成立。没有明确顺序时,应与普通全连接网络、树模型或SVM进行对比。
Q3:为什么 HAR 要使用 splitLabels?
同一个人的动作片段通常很相似。如果随机拆分,模型可能在测试集遇到训练阶段已经见过的人的动作模式,指标会虚高。splitLabels 可以按受试者、设备或批次隔离,更接近真实泛化场景。
Q4:训练集准确率很高,测试集却不高怎么办?
先检查是否存在数据泄漏和类别不平衡,再看验证集走势。可以减小 convChannels 或 rnnHidden、增大 dropout、启用早停、增加数据量,或使用更合理的分组划分。不要只靠增加训练轮数解决。
Q5:为什么图像分类不直接使用二维CNN?
本程序把图像的一个方向当作序列,适合演示 CNN-RNN 如何逐列或逐行读取图像。若任务高度依赖完整二维邻域结构,二维CNN通常更直接;如果图像某一方向天然具有扫描顺序或需要结合循环记忆,CNN-RNN才更有意义。
Q6:最少需要改哪些内容?
最少修改 X、Y 和 options.sequenceAxis。之后根据数据量与效果调整网络容量、训练轮数、学习率和批尺寸。建议先运行最接近自己输入形态的demo,再逐项替换。