用浅层神经网络拟合数据
神经网络擅长拟合功能。 实际上,有证据表明,相当简单的神经网络可以满足任何实际功能。
例如,假设您有一家健康诊所的数据。 您想要设计一个网络,该网络可以根据13个解剖测量结果预测一个人的体内脂肪百分比。 您总共有252个示例人员,您为其拥有这13项数据及其相关的体内脂肪百分比。
您可以通过两种方式解决此问题:
•使用图形用户界面nftool,如第1-36页的“使用神经网络拟合应用程序”中所述。
•使用命令行功能,如第1-51页的“使用命令行功能”中所述。
通常最好先从GUI开始,然后使用GUI自动生成命令行脚本。 使用任何一种方法之前,请先通过选择数据集来定义问题。 每个GUI都可以访问许多示例数据集,您可以使用这些示例数据来试用工具箱(请参阅“浅层神经网络的示例数据集”)。 如果您有要解决的特定问题,可以将自己的数据加载到工作区中。 下一节描述数据格式。
- 定义问题
要定义工具箱的拟合问题,请将一组Q输入向量排列为矩阵中的列。 然后,将另一组Q目标向量(每个输入向量的正确输出向量)排列到第二矩阵中(有关静态和时序数据的数据格式的详细说明,请参见“数据结构”)。 例如,您可以为布尔AND门定义拟合问题,该逻辑与门具有四组两元素输入向量和一个元素目标,如下所示:
inputs = [0 1 0 1; 0 0 1 1];
targets = [0 0 0 1];
下一部分显示了如何使用神经网络拟合应用程序nftool训练网络以拟合数据集。 本示例使用工具箱随附的身体脂肪数据集。
使用神经网络拟合应用
1 使用以下命令打开神经网络启动GUI:
nnstart
2单击配件应用程序以打开神经网络配件应用程序。 (您也可以使用命令nftool。)
3单击“下一步”继续。
4在“选择数据”窗口中,单击“加载示例数据集”。 拟合数据集选择器窗口打开。
注意当需要从MATLAB工作区加载数据时,请使用“选择数据”窗口中的“输入和目标”选项。
5选择 Chemical,然后单击import。 这将使您返回“选择数据”窗口。
6单击“下一步”以显示“验证和测试数据”窗口,如下图所示。
验证和测试数据集分别设置为原始数据的15%。
通过这些设置,输入向量和目标向量将被随机分为三组,如下所示:
•70%用于训练。
•15%将用于验证网络是否泛化,并在过度拟合之前停止训练。
•最后的15%将用作网络泛化的完全独立测试。
7 单击下一步。
用于功能拟合的标准网络是两层前馈网络,在隐藏层具有S型传递函数,在输出层具有线性传递函数。 隐藏神经元的默认数量设置为10。如果网络训练性能较差,则可能需要稍后增加该数量。
8单击“下一步”。
9选择一种训练算法,然后单击“训练”。
对于大多数问题,建议使用Levenberg-Marquardt(trainlm),但对于某些嘈杂和小问题,建议使用贝叶斯正则化(trainbr)花费更长的时间,但可以获得更好的解决方案。 但是,对于大问题,建议使用比例共轭梯度(trainscg),因为它使用梯度计算,比其他两种算法使用的雅可比计算的存储效率更高。 本示例使用默认的LevenbergMarquardt。 (这是一些计算梯度的方法)
训连持续进行,直到验证错误未能减少六次迭代(验证停止)为止。
10在“plots”下,单击“Regression”。 这用于验证网络性能。
以下回归图显示了针对训练,验证和测试集目标的网络输出。 为了达到最佳拟合,数据应沿着45度线落下,网络输出应等于目标。 对于此问题,所有数据集的拟合度都相当好,R值分别为0.93或更高。 如果需要更准确的结果,则可以通过在nftool中单击“Retrain”来重新训练网络。 这将改变网络的初始权重和偏差,并且在重新训练后可以产生改进的网络。 在以下窗格中提供了其他选项。
1 查看错误直方图以获得网络性能的其他验证。
在“plot”窗格下,单击“Error Histogram”。
蓝色条形代表训练数据,绿色条形代表验证数据,红色条形代表测试数据。 直方图可以为您提供离群值的指示,离群值是拟合度明显比大多数数据差的数据点。 在这种情况下,您可以看到虽然大多数错误都在-5到5之间,但是有一个训练点的错误值为17,而验证点的错误值为12和13。
这些异常值在测试回归图上也可见。 第一个对应于该点的目标是50,输出接近33。最好检查异常值以确定数据是否不好,或者这些数据点是否与其余数据集不同。 如果离群值是有效数据点,但与其余数据不同,则网络将为这些点外推。 您应该收集更多看起来像异常值的数据,然后重新训练网络。
2在“神经网络拟合应用程序”中单击“下一步”以评估网络。
此时,您可以针对新数据测试网络。
如果您对原始或新数据的网络性能不满意,可以执行以下操作之一:
•再次训练。
•增加神经元的数量。
•获得更大的训练数据集。
如果训练集的性能良好,但测试集的性能却明显较差,这可能表明过拟合,那么减少神经元数量可以改善结果。 如果训练效果不佳,则可能需要增加神经元的数量。
3 如果您对网络性能满意,请单击“下一步”。
4 使用此面板生成用于模拟神经网络的MATLAB函数或Simulink®图。 您可以使用生成的代码或图表更好地了解神经网络如何计算输入的输出,或者使用MATLAB Compiler™工具和其他MATLAB代码生成工具来部署网络。
5 使用此屏幕上的按钮来生成脚本或保存结果。
•您可以单击“Simple Script”或“Advanced Script”来创建MATLAB代码,该代码可用于从命令行重现之前的所有步骤。如果您想学习如何使用工具箱的命令行功能来自定义训练过程,创建MATLAB代码可能会有所帮助。 在第1-51页的“使用命令行功能”中,您将更详细地研究生成的脚本。
•您也可以将网络另存为工作区中的网络。 您可以对其执行其他测试,也可以将其用于新输入。
6创建MATLAB代码并保存结果后,单击Finish。
使用命令行功能
学习如何使用工具箱的命令行功能的最简单方法是从GUI生成脚本,然后对其进行修改以自定义网络训练。
作为示例,请看在上一节的步骤14中创建的简单脚本。
% Solve an Input-Output Fitting problem with a Neural Network % Script generated by NFTOOL % % This script assumes these variables are defined: % % houseInputs - input data.
% houseTargets - target data.
inputs = houseInputs;
targets = houseTargets;
% Create a Fitting Network
hiddenLayerSize = 10;
net = fitnet(hiddenLayerSize); % Set up Division of Data for Training, Validation, Testing
net.divideParam.trainRatio = 70/100; net.divideParam.valRatio = 15/100; net.divideParam.testRatio = 15/100;
% Train the Network
[net,tr] = train(net,inputs,targets);
% Test the Network
outputs = net(inputs);
errors = gsubtract(outputs,targets);
performance = perform(net,targets,outputs)
% View the Network
view(net)
% Plots
% Uncomment these lines to enable various plots.
% figure, plotperform(tr)
% figure, plottrainstate(tr)
% figure, plotfit(targets,outputs)
您可以保存脚本,然后从命令行运行它以重现上一个GUI会话的结果。 您还可以编辑脚本以自定义训练过程。 在这种情况下,请按照脚本中的每个步骤进行操作。
- 该脚本假定输入向量和目标向量已经加载到工作空间中。 如果未加载数据,则可以按以下方式加载它们:
load bodyfat_dataset
inputs = bodyfatInputs;
targets = bodyfatTargets;
此数据集是工具箱中一部分的示例数据集(请参阅第1-137页的“浅层神经网络的示例数据集”)。 通过输入命令help nndatasets,可以查看所有可用数据集的列表。 load命令还允许您使用自己的变量名从任何这些数据集中加载变量。 例如,命令
[inputs,targets] = bodyfat_dataset;
将人体脂肪输入加载到数组输入中,并将人体脂肪目标加载到数组目标中。
2创建一个网络。 函数拟合(或回归)问题的默认网络fitnet是前馈网络,在隐藏层具有默认的tan-Sigmoid传递函数,在输出层具有线性传递函数。 您为上一节中的一个隐藏层分配了十个神经元(有些随意)。 该网络具有一个输出神经元,因为每个输入向量只有一个目标值。
hiddenLayerSize = 10;
net = fitnet(hiddenLayerSize);
注意:更多的神经元需要更多的计算,并且当数字设置得太高时,它们倾向于使数据过拟合,但是它们使网络能够解决更复杂的问题。 更多的层需要更多的计算,但是它们的使用可能会导致网络更有效地解决复杂的问题。 要使用多个隐藏层,请在fitnet命令中输入隐藏层大小作为数组的元素。
3设置数据划分。
net.divideParam.trainRatio = 70/100; net.divideParam.valRatio = 15/100; net.divideParam.testRatio = 15/100;
通过这些设置,输入向量和目标向量将被随机划分,其中70%用于训练,15%用于验证,而15%用于测试。 (有关数据划分过程的更多讨论,请参见“划分数据”。)
4训练网络。 网络使用默认的Levenberg-Marquardt算法(trainlm)进行训练。 对于Levenberg-Marquardt无法获得所需的准确结果的问题,或者对于大数据问题,请考虑分别将网络训练功能设置为贝叶斯正则化(trainbr)或缩放共轭梯度(trainscg),
net.trainFcn = 'trainbr';
net.trainFcn = 'trainscg';
要训练网络,请输入:
[net, tr] = train(net, inputs, targets);
在训练期间,将打开以下训练窗口。 该窗口显示训练进度,并允许您通过单击“停止训练”随时中断训练。
5测试网络。 训练完网络后,您可以使用它来计算网络输出。 以下代码计算网络输出,错误和整体性能。
outputs = net(inputs);
errors = gsubtract(targets, outputs);
performance = perform(net, targets, outputs)
通过使用位于训练记录中的测试索引,也可以仅在测试集上计算网络性能。
tInd = tr.testInd;
tstOutputs = net(inputs(:, tInd));
tstPerform = perform(net,targets(tInd),tstOutputs)
对网络响应进行一些分析。 如果在训练窗口中单击Regression,则可以在网络输出和相应目标之间执行线性回归。
下图显示了结果。
输出可以很好地跟踪目标以进行训练,测试和验证,并且总响应的R值超过0.96。 如果需要更精确的结果,则可以尝试以下任何一种方法:•使用init将初始网络权重和偏差重置为新值,然后再次进行训练(请参阅“初始化权重”(init))。
•增加隐藏神经元的数量。
•增加训练向量的数量。
•如果有更多相关信息,请增加输入值的数量。
•尝试其他训练算法(请参阅“训练算法”)。
在这种情况下,网络响应令人满意,您现在可以将网络用于新输入。
7查看网络图。
view(net)
要获得更多有关命令行操作的经验,请尝试以下一些任务:•在训练过程中,打开一个绘图窗口(例如回归绘图),并观看其动画。
•使用诸如plotfit,plotregression,plottrainstate和plotperform之类的功能从命令行进行打印。 (有关使用这些功能的更多信息,请参见其参考页。)另外,从命令行进行培训时,请参阅高级脚本以获取更多选项。
每次训练神经网络时,由于不同的初始权重和偏差值以及对训练,验证和测试集。 结果,针对相同问题训练的不同神经网络可以为相同输入提供不同的输出。 为了确保找到了精度较高的神经网络,请重新训练几次。
如果需要更高的精度,还有几种其他技术可以改善初始解决方案。 有关更多信息,请参见“改善浅层神经网络泛化并避免过度拟合”。