尝试在MATLAB中自行模拟神经网络

我尝试创建一个神经网络来估计y = x ^ 2。因此,我创建了一个拟合神经网络,并为其提供了输入和输出的样本。我尝试在C++中构建这个网络,但结果与我预期的不同。

使用以下输入:

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71

以及以下输出:

0 1 4 9 16 25 36 49 64 81 100 121 144 169 196 225 256 289 324 361 400 441 484 529 576 625 676 729 784 841 900 961 1024 1089 1156 1225 1296 1369 1444 1521 1600 1681 1764 1849 1936 2025 2116 2209 2304 2401 2500 2601 2704 2809 2916 3025 3136 3249 3364 3481 3600 3721 3844 3969 4096 4225 4356 4489 4624 4761 4900 5041 1 4 9 16 25 36 49 64 81 100 121 144 169 196 225 256 289 324 361 400 441 484 529 576 625 676 729 784 841 900 961 1024 1089 1156 1225 1296 1369 1444 1521 1600 1681 1764 1849 1936 2025 2116 2209 2304 2401 2500 2601 2704 2809 2916 3025 3136 3249 3364 3481 3600 3721 3844 3969 4096 4225 4356 4489 4624 4761 4900 5041

我使用了拟合工具网络,采用矩阵行。训练数据占70%,验证数据和测试数据各占15%。隐藏层神经元数量为两个。然后我在命令行中输入了以下代码:

purelin(net.LW{2}*tansig(net.IW{1}*inputTest+net.b{1})+net.b{2})

其他信息:

我的net.b[1]是:-1.16610230053776 1.16667147712026

我的net.b[2]是:51.3266249426358

我的net.IW(1)是:0.344272596370387 0.344111217766824

我的net.LW(2)是:31.7635369693519 -31.8082184881063

当我的inputTest为3时,该命令的结果是16,而它应该大约是9。我在哪里犯了错误吗?

我在Stack Overflow上找到了一篇帖子在MATLAB中使用神经网络,其中描述的问题与我的问题类似,但有一点不同,那就是在那个问题中,输入和输出的范围是相同的,而在我的问题中则不是。那个解决方案说我需要对结果进行缩放,但我该如何缩放我的结果呢?


回答:

你关于缩放的说法是正确的。正如链接的回答中提到的,神经网络默认将输入和输出缩放到[-1,1]范围内。这可以在网络处理函数配置中看到:

>> net = fitnet(2);>> net.inputs{1}.processFcnsans =    'removeconstantrows'    'mapminmax'>> net.outputs{2}.processFcnsans =    'removeconstantrows'    'mapminmax'

应用于输入/输出的第二个预处理函数是mapminmax,其参数如下:

>> net.inputs{1}.processParams{2}ans =    ymin: -1    ymax: 1>> net.outputs{2}.processParams{2}ans =    ymin: -1    ymax: 1

将两者映射到[-1,1]范围内(在训练之前)。

这意味着训练后的网络期望输入值在这个范围内,输出值也在相同的范围内。如果你想手动向网络输入数据,并自己计算输出,你必须在输入时缩放数据,并在输出时反转映射。

最后要记住的一点是,每次你训练人工神经网络时,你会得到不同的权重。如果你想要可重复的结果,你需要固定随机数生成器的状态(每次用相同的种子初始化)。阅读关于rngRandStream等函数的文档。

你还必须注意,如果你将数据分为训练/测试/验证集,你必须每次使用相同的分割(可能也受到我提到的随机性方面的影响)。


这里有一个例子来说明这个想法(改编自我的另一篇帖子):

%%# datax = linspace(-71,71,200);            %# 1D inputy_model = x.^2;                      %# modely = y_model + 10*randn(size(x)).*x;  %# add some noise%%# create ANN, train, simulatenet = fitnet(2);                     %# one hidden layer with 2 nodesnet.divideFcn = 'dividerand';net.trainParam.epochs = 50;net = train(net,x,y);y_hat = net(x);%%# plotplot(x, y, 'b.'), hold onplot(x, x.^2, 'Color','g', 'LineWidth',2)plot(x, y_hat, 'Color','r', 'LineWidth',2)legend({'data (noisy)','model (x^2)','fitted'})hold off, grid on%%# manually simulate network%# map input to [-1,1] range[~,inMap] = mapminmax(x, -1, 1);in = mapminmax('apply', x, inMap);%# propagate values to get output (scaled to [-1,1])hid = tansig( bsxfun(@plus, net.IW{1}*in, net.b{1}) ); %# hidden layeroutLayerOut = purelin( net.LW{2}*hid + net.b{2} );     %# output layer%# reverse mapping from [-1,1] to original data scale[~,outMap] = mapminmax(y, -1, 1);out = mapminmax('reverse', outLayerOut, outMap);%# compare against MATLAB outputmax( abs(out - y_hat) )        %# this should be zero (or in the order of `eps`)

我选择使用mapminmax函数,但你也可以手动完成。公式是一个非常简单的线性映射:

y = (ymax-ymin)*(x-xmin)/(xmax-xmin) + ymin;

Screenshot

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注