简介:面向Matlab初学与进阶者,资源基于MNIST手写数字数据集,演示从数据读取、归一化到网络训练与测试的完整流程。压缩包共5个文件,含2个.m脚本、2个csv数据文件和1个md说明文档:脚本分别实现ANN与DNN网络的构建和验证,csv文件提供训练集与测试集,md文件梳理运行步骤与参数含义。通过该资源可掌握feedforwardnet、trainNetwork等关键函数的使用,理解隐藏层数量、学习率、迭代次数对分类准确率的影响,并学会用分类混淆矩阵、准确率曲线评估模型性能。文件体量仅247KB,轻便易用。已有118人学习下载,适合毕业设计、课程设计或自学神经网络分类的读者快速上手与二次开发。
1. 基于Matlab的ANN、DNN分类网络:不是学术玩具,是能落地的分类方案
你从网上下载一个“基于Matlab的ANN、DNN分类网络实现.zip”,大概率是拿到一堆.m文件和训练好的模型,第一反应是赶紧跑通,然后在自己的数据上验证。但真跑起来你会发现,Matlab里做分类网络的上手门槛比Python低很多,因为不需要手动写反向传播,train一行就能完成训练;可一旦涉及数据划分、归一化、工具箱路径和训练选项,翻车率又出奇地高。这篇文章围绕ANN和DNN两类分类网络,从数据准备、网络搭建、参数调整到部署验证完整走一遍,既适合刚接触分类的本科生,也适合想用Matlab快速验证模型落地可行性的工程师。我的结论是先明确目标:你要的是可复现的分类精度和稳定预测,而不是一个训练过程好看的模型。
2. 先理解ANN和DNN在Matlab里到底在算什么:从张量到损失函数
2.1 单层ANN就是一个带权重的线性映射加激活
很多人刚接触Matlab神经网络时,看到newff、feedforwardnet、patternnet这些函数就懵了。实际上ANN分类器的核心计算量很小:输入向量与权重矩阵相乘,加上偏置,然后过一个非线性激活函数。比如一个输入维度为4、隐层神经元数为10的单隐层网络,第一层做的事情就是X * W1 + b1,维度从150×4变成150×10,再通过tansig或relu做非线性变换,第二层把10维压缩到3维,最后通过softmax得到三个类别的概率。
Matlab里你很少需要自己写这些矩阵乘法和反向传播,工具箱已经把训练过程封装成train函数。但理解这个计算过程仍然重要,因为很多参数设置和报错都源于维度不匹配。例如train要求输入矩阵的每一列是一个样本,还是每一行是一个样本?老版本工具箱默认“样本按列存放”,所以train(net, X', T')这种转置写法非常常见。Deep Learning Toolbox中的trainNetwork则反过来,要求“每一行是一个观测”,这是两个不同的数据约定,也是新手最容易搞混的地方。
损失函数方面,分类问题用的不是均方误差,而是交叉熵。Matlab的crossentropy函数可以直接计算两组概率分布的损失;在patternnet训练过程中,工具箱会自动在输出层使用softmax并配合交叉熵目标函数,因此你不需要像手写神经网络那样自己求导。理解这一层的实际意义是:当你想比较两个不同模型时,不能只看训练集上的错误率,还要看损失曲线是否收敛、验证集损失是否反弹。
2.2 DNN比ANN多了“深度”,Matlab里用网络层对象而不是手写矩阵乘法
DNN和传统ANN在Matlab里的最大区别,不是激活函数,而是网络构建方式。传统ANN用feedforwardnet(10)一句话定义一个隐层网络,最多再加一个隐层;DNN则需要用“层对象”显式堆叠,例如fullyConnectedLayer、reluLayer、softmaxLayer、classificationLayer。这样的好处是每一层的输出尺寸、激活函数和初始化方式都清清楚楚,坏处是如果你不熟悉层对象的拼装顺序,报错信息会非常难懂。
一个典型的DNN分类网络是:输入层 → 全连接层 → ReLU → 全连接层 → ReLU → 输出层 → softmax → 分类层。这个过程看起来就是不断做线性映射和非线性激活,但“深度”的价值在于自动学习高阶特征组合。以鸢尾花分类为例,4维特征用单层ANN和三层DNN都能做到95%以上准确率,因为数据太简单;真正能体现深度优势的是图像、文本和传感器时序数据。
Matlab里DNN的搭建分为两个阶段:先用层数组定义网络结构,然后调用trainNetwork训练。层数组中的featureInputLayer确定了特征维度,fullyConnectedLayer的第二个参数是输出维数,classificationLayer是终点的分类层。这种编程范式更接近PyTorch和Keras,所以如果你有Python深度学习的经验,切回Matlab的时间成本很低;反过来也一样,从传统ANN切换到DNN,需要改变的是对“层”的思维方式,而不是对分类问题的理解。
2.3 分类网络设计前的数据归一化与标签编码示例
无论训练ANN还是DNN,数据准备都要走在网络搭建之前。这里给出一个最小可用的数据准备脚本,使用Matlab内置的鸢尾花数据集,方便你在一分钟内复现。需要说明的是,脚本里特意采用了“先划分再归一化”的顺序,这是避免测试集信息泄漏的关键。
% 加载鸢尾花数据集 load fisheriris X = meas; % 150×4的特征矩阵 Y = categorical(species); % 150×1的分类标签 % 分层划分训练集和测试集,70%训练,30%测试 rng(42); cv = cvpartition(Y, 'HoldOut', 0.3); idxTrain = training(cv); idxTest = test(cv); X_train = X(idxTrain, :); X_test = X(idxTest, :); Y_train = Y(idxTrain, :); Y_test = Y(idxTest, :); % 只用训练集统计量做归一化,测试集沿用同样的均值和标准差 mu = mean(X_train); sigma = std(X_train); sigma(sigma == 0) = 1; % 防止零方差特征导致除零 X_train_norm = (X_train - mu) ./ sigma; X_test_norm = (X_test - mu) ./ sigma; % 标签编码:显示前三行的类别 head(table(X_train_norm(:,1), Y_train))代码的逻辑说明:cvpartition按分层抽样方式划分数据,保证训练集和测试集中三个类别的比例一致,避免因随机划分导致某一类在测试集中缺失。categorical把元胞数组标签转换成分类变量,这样后续函数可以自动识别出类别数。归一化时用训练集的mu和sigma,测试集数据也减去训练集的均值和标准差,而不是重新计算,这是同行经常忽略的细节。
参数说明:HoldOut后面的0.3表示留出30%作为测试集;rng(42)固定随机种子,让实验结果可以复现;sigma(sigma == 0) = 1是防御性写法,当某个特征在所有训练样本中完全相同时,标准差不做除数。如果你的数据已经做了归一化但性能仍然不好,优先检查这一步是否把测试集统计量混了进来。
3. 用ANN先跑通第一个分类任务:trainlm、patternnet和模型保存
3.1 一个完整的ANN分类脚本:从原始数据到性能报告
拿到一个基于Matlab的ANN分类实现,我一般会先把它改造成一个完整闭环的脚本:数据加载、划分、归一化、训练、评估、保存。这里给出一个可以直接运行的ann_classifier_demo.m示例,后面会对每个部分做逐段说明。这个脚本使用的是patternnet,它是Matlab里专门处理分类问题的前馈网络,和feedforwardnet的区别在于输出层默认带了softmax,更适合多分类任务。
% ann_classifier_demo.m % 基于Matlab的ANN分类网络最小实现 clear; clc; close all; rng(42); % 1. 加载数据 load fisheriris; X = meas; Y = categorical(species); % 2. 划分训练/测试集(分层抽样) cv = cvpartition(Y, 'HoldOut', 0.3); X_train = X(training(cv), :); X_test = X(test(cv), :); Y_train = categorical(Y(training(cv), :)); Y_test = categorical(Y(test(cv), :)); % 3. 归一化,只使用训练集统计量 mu = mean(X_train); sigma = std(X_train); sigma(sigma == 0) = 1; X_train_norm = (X_train - mu) ./ sigma; X_test_norm = (X_test - mu) ./ sigma; % 4. 将目标标签转换为独热矩阵 Y_train_mat = double(onehotencode(Y_train, 2)); Y_test_mat = double(onehotencode(Y_test, 2)); % 5. 创建并训练模式识别网络 net = patternnet(10, 'trainlm'); net.trainParam.epochs = 1000; net.trainParam.goal = 1e-5; net.trainParam.min_grad = 1e-6; % 训练时不预先划分,手动控制验证策略 net.divideFcn = 'divideblock'; net.divideParam.trainRatio = 1; net.divideParam.valRatio = 0; net.divideParam.testRatio = 0; [net, tr] = train(net, X_train_norm', Y_train_mat'); % 6. 在测试集上预测 Y_pred_mat = net(X_test_norm'); [~, Y_pred] = max(Y_pred_mat, [], 1); Y_pred = categorical(Y_pred, 1:3, categories(Y_test)); % 7. 输出准确率 acc = mean(Y_pred == Y_test); fprintf('测试集准确率: %.2f%%\n', acc * 100); % 8. 保存模型和归一化参数 save('ann_model.mat', 'net', 'mu', 'sigma');代码的逻辑说明:第2步使用cvpartition先划出测试集,测试集从训练阶段彻底隔离。第4步onehotencode(Y_train, 2)把类别变量展开成150×3的独热矩阵,每个类别对应一列,这一步是patternnet的标准输入格式。第5步patternnet(10, 'trainlm')表示隐含层有10个神经元,训练算法选用Levenberg-Marquardt。注意这里显式关闭了工具箱自带的再次划分,因为我们已经手动预留了测试集。
参数说明:trainlm适合中小数据集,它通过拟牛顿法逼近二阶导数,收敛快,但内存占用随权重数量和样本数增加而快速升高;如果你有几千上万条数据并且特征维度很高,建议改成trainscg或trainbr。divideFcn设置为divideblock只是为了不自动划分,实际上只要divideParam.trainRatio = 1,工具箱就不会从传入数据里再抽取验证集。最后保存模型时一定要带上mu和sigma,因为以后的预测输入必须是同样归一化后的特征。
3.2 trainlm、trainscg和trainbr的选择:数据量、内存和收敛速度的权衡
很多初学Matlab神经网络的人会把训练算法当成无关紧要的选项,实际上这是影响实验结果最直观的旋钮之一。下表给出三种常见训练算法的适用场景,你可以按照自己的数据量快速选择。
| 训练算法 | 适用数据规模 | 内存压力 | 特点 |
|---|---|---|---|
| trainlm | 小规模(千条以内) | 高 | 收敛快,精度高,容易过拟合 |
| trainscg | 中等规模 | 低 | 不需要大量内存,适合模式识别 |
| trainbr | 任意规模 | 中 | 自动正则化,适合小样本和噪声大 |
参数说明:trainlm的默认mu为0.001,控制梯度下降与高斯牛顿法的切换,训练过程中如果误差不下降,工具箱会自动调大mu,所以一般不需要手动改。trainscg对学习率不敏感,无需手动设置学习率,这也是我喜欢把它作为高维稀疏特征首选的原因。trainbr会引入贝叶斯正则化,相当于自动调整权重衰减系数,代价是训练时间会变长,而且保存的模型对过拟合的抵抗能力更强。如果你发现测试集准确率远低于训练集,先把patternnet的算法改成trainbr试一轮,往往比盲目增加隐层神经元更有效。
3.3 训练完成后怎么评估和保存模型,避免重新训练
训练完成后,你通常需要三个东西:准确率、混淆矩阵、可部署的模型文件。准确率的计算已在上一小节代码中给出,但准确率只能反映整体好坏,如果数据类别不平衡,还要看每个类别的查准率和查全率。Matlab里一行命令就能画出混淆矩阵:
figure; plotconfusion(Y_test_mat, Y_pred_mat);plotconfusion的左侧输入是期望输出的独热矩阵,右侧是网络输出的原始实数矩阵,工具箱会自动取最大值位置作为预测类别。图中对角线格子表示预测正确,非对角线格子表示两个类别互相混淆。如果某一类的行和列都没有数值,说明该类别在训练集中可能数量过少,这时你需要重新检查分层划分是否生效。
模型保存方面,我见过很多人只保存net,不保存归一化参数,结果换一台机器后预测结果完全不对。正确做法是像前面代码中那样save('ann_model.mat', 'net', 'mu', 'sigma')。重新加载后,预测接口也要保持归一化一致:
S = load('ann_model.mat'); x_new_norm = (x_new - S.mu) ./ S.sigma; y_new = S.net(x_new_norm');y_new是一个行向量,最大值所在的列位置就是预测类别索引。如果你希望把它封装成一个独立函数,可以用genFunction(net, 'predict_ann.m')生成一个可脱离训练工具箱运行的函数,这个能力在DNN导出时会再次用到,但需要注意genFunction生成的是数值输出,不包含类别名称映射,部署时要自己维护一个categories(Y)列表。
4. DNN分类网络实现:从全连接到卷积,三个必调参数
4.1 用Deep Learning Toolbox搭一个三层DNN分类器
当传统ANN的隐层数量增加到两层以上,我就直接切到trainNetwork来搭建DNN了。与patternnet不同,trainNetwork不需要手动转置数据,它要求X_train_norm是一个每行一个观测的矩阵,标签是分类变量。下面是一个三层全连接DNN的完整定义:
% 构建DNN分类网络 dnnLayers = [ featureInputLayer(size(X_train_norm, 2), 'Name', 'input') fullyConnectedLayer(32, 'Name', 'fc1') reluLayer('Name', 'relu1') fullyConnectedLayer(16, 'Name', 'fc2') reluLayer('Name', 'relu2') fullyConnectedLayer(3, 'Name', 'fc_out') softmaxLayer('Name', 'softmax') classificationLayer('Name', 'output') ]; % 训练选项 options = trainingOptions('adam', ... 'InitialLearnRate', 0.01, ... 'MaxEpochs', 50, ... 'MiniBatchSize', 16, ... 'ValidationData', {X_test_norm, Y_test}, ... 'ValidationFrequency', 10, ... 'Plots', 'training-progress', ... 'Verbose', true); % 训练 netDNN = trainNetwork(X_train_norm, Y_train, dnnLayers, options);代码的逻辑说明:featureInputLayer的第一参数是输入特征数,这里用size(X_train_norm, 2)自动获取。fullyConnectedLayer(32)表示该层输出32维特征。最后一个fullyConnectedLayer(3)的输出维度等于类别数,后面接softmaxLayer得到概率分布,再由classificationLayer计算交叉熵损失。trainNetwork的输入是特征矩阵和分类变量,不需要提供独热编码,分类层会自动处理标签映射。
参数说明:MiniBatchSize表示每轮参数更新前一次送入多少条样本。16在小型数据集上是一个常用起点,太小会导致损失曲线抖动,太大会让单轮迭代时间变长。ValidationFrequency设置为10,意思是每处理10个mini-batch计算一次验证集上的损失和准确率,这个参数直接影响你能否及时在训练过度前拦下模型。
4.2 分类层、交叉熵损失与训练选项的关系
在DNN分类任务中,classificationLayer虽然叫“层”,但它的作用更像是一个损失函数计算器。训练时它会比较网络输出与真实标签,自动计算交叉熵的梯度;推理时它不做任何输出变换,真正给出概率的是前面的softmaxLayer。所以你看到netDNN.predict(X_test_norm)返回的是每个类别的后验概率,而netDNN.classify(X_test_norm)返回的是类别名称向量。
交叉熵损失对输出层的激活值非常敏感。当网络最后几层的权重初始化过大时,softmax输出很容易变成接近0或1的极端分布,导致交叉熵损失出现Inf甚至NaN。要缓解这个问题,最常见的手段是调低InitialLearnRate。在Matlab里你还可以使用'L2Regularization'来增加权重衰减,一般设置在1e-4到1e-2之间。如果训练集只有几百条样本,我还会开启'Shuffle', 'every-epoch',让每个epoch内的mini-batch顺序重新打乱,增强随机性。
有一个经常被忽略的点是:trainingOptions里的'Plots', 'training-progress'会启动一个GUI进度窗口,它本身不消耗多少内存,但在批量跑实验或远程无桌面环境下会报错。如果你通过命令行跑脚本,建议把Plots改成'none',否则可能因为无法创建图形窗口而中断训练。
4.3 当数据是图像时,换成卷积网络的两个关键命令
DNN分类并不一定全是全连接层,很多来自传感器和图像的数据需要保留空间结构,这时第一个关键命令是把featureInputLayer换成imageInputLayer。第二个关键命令是引入convolution2dLayer。下面是一个适应32×32×3图像的极小卷积分类网络:
imgLayers = [ imageInputLayer([32 32 3], 'Name', 'input') convolution2dLayer(3, 16, 'Padding', 'same', 'Name', 'conv1') reluLayer('Name', 'relu1') fullyConnectedLayer(10, 'Name', 'fc') softmaxLayer('Name', 'softmax') classificationLayer('Name', 'output') ]; optionsCnn = trainingOptions('sgdm', ... 'InitialLearnRate', 0.001, ... 'MaxEpochs', 20, ... 'MiniBatchSize', 32); netCNN = trainNetwork(X_img_train, Y_train, imgLayers, optionsCnn);convolution2dLayer的第一参数是卷积核尺寸,第二参数是输出通道数。Padding设为'same'可以保证卷积后特征图尺寸不变,这对连接后面的全连接层很重要,因为fullyConnectedLayer需要固定的输入维数。如果输入图像大小不固定,可以使用resize函数统一尺寸。卷积网络对数据量的要求比全连接DNN更高,如果只有几千张图,建议在卷积层后加maxPooling2dLayer(2, 'Stride', 2)来降低特征维数并保留一定平移不变性。
4.4 DNN训练的三个必调参数:学习率、mini-batch size和验证频率
在Matlab的DNN训练中,百分之八十的调试时间都会花在这三个参数上。学习率控制梯度更新的步长,InitialLearnRate太高网络会震荡甚至发散,太低则收敛极慢。MiniBatchSize影响梯度估计的稳定性和显存占用;数据量小时,较小的batch size反而能带来正则化效果。ValidationFrequency决定每隔多少迭代验证一次,它在使用验证集早停时是核心参数,因为只有当验证频率足够密,你才能及时发现验证损失开始上升。
| 参数 | 默认值 | 影响 | 我的建议 |
|---|---|---|---|
| InitialLearnRate | 0.01 | 每步更新的幅度 | 小数据集用0.001起步,观察损失曲线后再增大 |
| MiniBatchSize | 128 | 梯度的稳定性与训练速度 | 数据量小于500时用16或32 |
| ValidationFrequency | 50 | 早停的敏感度 | 总迭代数少时设为10左右 |
这三个参数互相耦合,比如增大了MiniBatchSize后,学习率通常也应适当调大。我的习惯是先固定MiniBatchSize=16,用InitialLearnRate=0.001跑20个epoch,观察训练损失是否在下降;如果损失在前几个epoch内抖动剧烈,改为0.0001;如果收敛太慢,改成0.01。ValidationFrequency则要看MaxEpochs与一次epoch包含的迭代次数来定,保证整个训练过程至少有十几次验证点,否则早停条件很难触发。
5. 基于Matlab分类网络实现的避坑与排查:5个让人翻车的细节
5.1 中文注释乱码导致脚本无法运行
现象:从网上下载的.m文件里有中文注释,打开后全部变成乱码,有时整个文件会被Matlab标红,提示语法错误,但代码逻辑本身没有错。
原因:Matlab 2023之前版本在中文Windows上默认使用GBK编码,而新版本和很多在Linux系统上生成的脚本使用UTF-8编码。文件编码与编辑器当前编码不一致时,中文字符可能被错误读取,甚至把后一行的代码内容吃掉。
解决:我在处理这类问题时会先用Notepad++或VS Code打开该.m文件,查看右下角编码格式。如果文件是UTF-8,而你的Matlab是2022b或更早版本,可以在命令窗执行feature('DefaultCharacterSet', 'UTF-8')后重启Matlab,或者直接把文件另存为GBK编码。反过来,如果文件是GBK而你用2023版,建议把文件另存为UTF-8,因为新版默认编码已经切到UTF-8。养成新建脚本时统一用英文字符写注释,能彻底避开这个坑。
5.2 工具箱缺失导致 trainNetwork 未定义
现象:调用trainNetwork或patternnet时,命令窗口报“未定义函数或变量 trainNetwork”,甚至提示Undefined function 'trainNetwork' for input arguments of type 'double'。
原因:你的Matlab发行版中没有安装Deep Learning Toolbox,或者安装后并没有激活许可证。还有一些情况是工具箱安装在了某个未添加到路径的目录,导致命令窗找不到函数。
解决:先用ver查看已安装工具箱列表,确认是否出现Deep Learning Toolbox。如果没有输出,说明没有安装;如果列表里有但仍报错,执行rehash toolboxcache并重启Matlab。检查许可证可以用license('test', 'Neural_Network_Toolbox'),返回1表示可用。如果许可证到期,需要续订;工具箱安装可以通过Matlab附加功能资源管理器完成,但要注意版本兼容,2023a的Deep Learning Toolbox最好对应2023a的Matlab主程序。
5.3 全量归一化导致测试集信息泄漏
现象:训练模型时准确率很高,测试集也有95%以上,但换另一批新数据后准确率骤降至70%,说明训练出的模型在新的分布上失效了。
原因:很多人在划分数据之前直接对全集执行zscore(X)或normalize(X),这样测试集的均值和方差都混进了训练过程,网络在训练时已经“见过”测试数据的分布信息。这种情况在Kaggle和论文里被称作数据泄漏,结果是验证指标虚高,实际部署跑不动。
解决:严格遵守“先划分、再归一化”的顺序。训练集计算mu和sigma,测试集和未来的新样本一律使用训练集的mu和sigma。这条原则在传统ANN和DNN中完全一致。我在写代码时会顺手加一个注释提醒自己:mu和sigma只能来自训练集,否则后面的所有评估都是自欺欺人。
5.4 训练过程中出现 NaN 或损失不下降
现象:使用trainNetwork训练时,训练损失在几个迭代内变成NaN,进度窗口中的曲线直接断开;或者损失值始终在某个高位不变,完全没有下降趋势。
原因:NaN最常见的来源是学习率过大导致梯度爆炸,使权重变成Inf或NaN;另一个常见原因是输入特征中存在缺失值或无穷值。损失不下降则多与特征尺度过大或标签类别不连续有关,即使归一化后,如果某一维特征方差接近0,也会让归一化后的数值变得病态。
解决:先用sum(isnan(X))检查输入矩阵,确认没有缺失值;再用isfinite检查是否有无穷。如果数据没问题,就把InitialLearnRate从0.01降到0.001甚至0.0001,同时开启'GradientThreshold', 1限制梯度最大范数。损失不下降时,检查是否忘记在目标标签上使用categorical,Matlab的classificationLayer不接受数值标签是隐藏的常见问题。
5.5 保存的模型重新加载后预测结果和训练时不一致
现象:训练结束后立即用net(X_test_norm')预测,准确率正常;保存到.mat文件重新加载后,相同输入得到的结果却完全不同,甚至报错。
原因:如果你只保存了net,没有保存归一化参数mu和sigma,那么新样本没有经过正确的特征缩放。另一种情况是保存的网络包含trained之后的自定义属性,比如net.userdata中记录的数据映射,在跨版本加载时这些属性不会自动恢复。
解决:保存模型时把net和预处理参数放在同一个结构体里,例如save('model.mat', 'net', 'mu', 'sigma', 'labelNames')。加载模型后,先用保存的mu和sigma归一化输入,再调用net。如果模型是在远程Linux服务器上训练、在Windows上预测,还要确认网络中的char类属性没有被乱码影响,这种情况我会直接用genFunction把网络变为独立的函数文件,彻底绕开跨平台兼容问题。
6. 进阶:用交叉验证选网络结构,再导出为可部署的分类模型
6.1 手动实现K折交叉验证,避免结构选择靠直觉
选择隐层神经元数或网络深度时,单次划分的准确率波动很大。我更信赖K折交叉验证。核心代码只需要循环cvpartition:
k = 5; cv = cvpartition(Y, 'KFold', k); acc = zeros(k, 1); for i = 1:k trIdx = training(cv, i); teIdx = test(cv, i); % 这里复用第3章的归一化和训练过程 ... acc(i) = currentAcc; end fprintf('K折平均准确率: %.2f%%\n', mean(acc) * 100);在循环内,每一折都要只用训练集的mu和sigma做归一化,否则第5.3节的信息泄漏又会回来。比较不同结构时,固定随机种子和训练选项,这样准确率差异才可信。
6.2 用analyzeNetwork检查结构,再用genFunction导出单点预测函数
DNN训练完成后,我习惯先执行analyzeNetwork(netDNN),它会画出整个网络结构图,并检查各层尺寸是否匹配,很多维度错误在这个阶段就能暴露。接着用genFunction(netDNN, 'myDNNPredict.m')把网络导出为一个独立函数,导出的函数可以脱离训练数据运行,方便集成到实时控制或Web服务中。需要注意的是,genFunction对输出要求是数值矩阵,分类结果需要自己映射回类别名称。我一般会再写一层封装函数,把归一化、网络预测、类别映射包到一起,这样后续调用时不需要关心内部流程。我的习惯是导出前用一个随机样本跑通一次,确保输入尺寸和输出维度一致。希望这个方法能帮你在Matlab的ANN和DNN分类项目上少走弯路。
本文还有配套的精品资源,点击获取