我不是神经网络专家,但我认为以下几点可能对您有所帮助。也有一些不错的帖子,例如,关于隐藏单元的帖子,您可以在此站点上搜索可能有用的神经网络。
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个隐藏单元测试神经网络的合理方法是什么?神经网络通常用于分类,因此确定似乎是问题的合理选择。我使用和。请注意,有几个参数需要学习。x⋅k>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个参数。我怀疑在这种情况下,您可能可以通过减少单位数量来减少要估算的参数数量。从构建神经网络进行加法可以看出,在训练过程中,较简单的神经网络不太可能出现问题。
但是作为任何机器学习(包括线性回归)的一般规则,您想要的训练示例比估计的参数多得多。