R神经网络-计算给出恒定答案


11

我正在尝试使用R的neuralnet软件包(此处的文档)进行预测。

这是我想做的:

library(neuralnet)
x <- cbind(runif(50, min=1, max=500), runif(50, min=1, max=500))
y <- x[, 1] * x[, 2]
train <- data.frame(x, y)
n <- names(train)
f <- as.formula(paste('y ~', paste(n[!n %in% 'y'], collapse = ' + ')))
net <- neuralnet(f, train, hidden = c(5, 5), threshold=0.01)
print(net)

all: neuralnet(formula = f, data = train, hidden = c(5, 5), threshold = 0.01)

1 repetition was calculated.

    Error Reached Threshold Steps
1 66136930789    0.004658283648 97938

test <- cbind(runif(10, min=1, max=500), runif(10, min=1, max=500))
res <- compute(net, test)
res$net.result
         [,1]
[1,] 58749.01798
[2,] 58749.01798
[3,] 58749.01798
[4,] 58749.01798
[5,] 58749.01798
[6,] 58749.01798
[7,] 58749.01798
[8,] 58749.01798
[9,] 58749.01798
[10,] 58749.01798

有人可以向我解释为什么误差如此之大以及为什么所有预测值几乎都恒定吗?

Answers:


6

我不是神经网络专家,但我认为以下几点可能对您有所帮助。也有一些不错的帖子,例如,关于隐藏单元的帖子,您可以在此站点上搜索可能有用的神经网络。

1大错误:为什么您的示例根本不起作用

为什么误差如此之大,为什么所有预测值都几乎恒定?

这是因为神经网络无法计算您赋予它的乘法函数,并且在范围的中间输出一个常数y,而不管x,这是最小化训练过程中错误的最佳方法。(注意58749如何非常接近将1和500之间的两个数字相乘的平均值。)

很难看到神经网络如何以合理的方式计算乘法函数。考虑网络中的每个节点如何合并先前计算的结果:您对先前节点的输出进行加权求和(然后对它应用S形函数,请参见神经网络简介,将输出压缩在和)。您将如何获得加权总和,以使两个输入相乘?(但是,我认为,可能有可能需要使用大量隐藏层才能以非常人为的方式使乘法工作。)11

2局部极小值:为什么理论上合理的例子可能不起作用

但是,即使尝试加法,您在示例中也会遇到问题:网络无法成功训练。我相信这是由于第二个问题:在培训期间获得局部最小值。实际上,对于加法而言,使用两个包含5个隐藏单元的层太复杂而无法计算加法。没有隐藏单位的网络训练得很好:

x <- cbind(runif(50, min=1, max=500), runif(50, min=1, max=500))
y <- x[, 1] + x[, 2]
train <- data.frame(x, y)
n <- names(train)
f <- as.formula(paste('y ~', paste(n[!n %in% 'y'], collapse = ' + ')))
net <- neuralnet(f, train, hidden = 0, threshold=0.01)
print(net) # Error 0.00000001893602844

当然,您可以通过记录日志将原来的问题转换为其他问题,但是我认为这不是您想要的,所以从此...

3培训实例数量与估计参数数量的比较

那么,像您最初那样用两层5个隐藏单元测试神经网络的合理方法是什么?神经网络通常用于分类,因此确定似乎是问题的合理选择。我使用和。请注意,有几个参数需要学习。xk>ck=(1,2,3,4,5)c=3750

在下面的代码中,我采用与您的方法非常相似的方法,只是我训练了两个神经网络,一个带有训练集中的50个示例,另一个带有500个示例。

library(neuralnet)
set.seed(1) # make results reproducible
N=500
x <- cbind(runif(N, min=1, max=500), runif(N, min=1, max=500), runif(N, min=1, max=500), runif(N, min=1, max=500), runif(N, min=1, max=500))
y <- ifelse(x[,1] + 2*x[,1] + 3*x[,1] + 4*x[,1] + 5*x[,1] > 3750, 1, 0)
trainSMALL <- data.frame(x[1:(N/10),], y=y[1:(N/10)])
trainALL <- data.frame(x, y)
n <- names(trainSMALL)
f <- as.formula(paste('y ~', paste(n[!n %in% 'y'], collapse = ' + ')))
netSMALL <- neuralnet(f, trainSMALL, hidden = c(5,5), threshold = 0.01)
netALL <- neuralnet(f, trainALL, hidden = c(5,5), threshold = 0.01)
print(netSMALL) # error 4.117671763
print(netALL) # error 0.009598461875

# get a sense of accuracy w.r.t small training set (in-sample)
cbind(y, compute(netSMALL,x)$net.result)[1:10,]
      y                 
 [1,] 1  0.587903899825
 [2,] 0  0.001158500142
 [3,] 1  0.587903899825
 [4,] 0  0.001158500281
 [5,] 0 -0.003770868805
 [6,] 0  0.587903899825
 [7,] 1  0.587903899825
 [8,] 0  0.001158500142
 [9,] 0  0.587903899825
[10,] 1  0.587903899825

# get a sense of accuracy w.r.t full training set (in-sample)
cbind(y, compute(netALL,x)$net.result)[1:10,]
      y                 
 [1,] 1  1.0003618092051
 [2,] 0 -0.0025677656844
 [3,] 1  0.9999590121059
 [4,] 0 -0.0003835722682
 [5,] 0 -0.0003835722682
 [6,] 0 -0.0003835722199
 [7,] 1  1.0003618092051
 [8,] 0 -0.0025677656844
 [9,] 0 -0.0003835722682
[10,] 1  1.0003618092051

显然,这样netALL做要好得多!为什么是这样?看一下您从plot(netALL)命令中得到的结果:

在此处输入图片说明

我将其设置为训练期间估计的66个参数(分别向11个节点中的5个输入和1个偏置输入)。您无法使用50个训练示例可靠地估算66个参数。我怀疑在这种情况下,您可能可以通过减少单位数量来减少要估算的参数数量。从构建神经网络进行加法可以看出,在训练过程中,较简单的神经网络不太可能出现问题。

但是作为任何机器学习(包括线性回归)的一般规则,您想要的训练示例比估计的参数多得多。


1
想了很多信息,谢谢!你是绝对正确的!如果对变量进行归一化,训练实例的数量更大,并且一个隐藏层上的神经元数量等于1,它将看起来更好。当然,不是乘法功能,而是类似的东西。嗯,如果2周前我得到如此出色的答复,事情就会变得容易些。但是,非常感谢您的答复,谢谢!
luckyi
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.