使用R语言和neuralnet
包,我尝试对如下所示的数据进行建模:
这些是几天内每10分钟间隔的温度读数(上图显示的是两天的截取部分)。使用下面的代码,我将神经网络拟合到数据上。虽然可能有更简单的方法来建模这些特定的数据,但将来数据可能会有很大不同。使用一个包含2个神经元的隐藏层可以得到令人满意的结果:
这种方法在大多数情况下也适用于更多的层和神经元。然而,当使用一个包含一个神经元的隐藏层,以及在某些情况下使用两层(我的情况是分别有3个和2个神经元)时,我得到的效果相当差,并且总是呈现相同的形态:
唯一随机的因素是初始权重的设置,因此我认为这与此有关。然而,我必须承认我对神经网络的理论还没有完全掌握。我想知道的是,较差的结果是否是因为陷入了局部最小值(’neuralnet’默认使用具有权重回溯的弹性反向传播),我只是运气不好,还是我可以避免这种情况。我认为对于拟合例如2、5、10次的多项式,可能存在一个最佳的隐藏节点数量。如果不是这样,我的最佳行动方案是什么?更大的学习率?更小的误差阈值?先谢谢了。
我还没有尝试调整rprop参数,所以解决方案可能就在那里。
代码:
# DATA ----------------------minute <- seq(0, 6*24 - 1)temp <- rep.int(17, 6*24)temp[(6*7):(6*20)] <- 20n <- 10dta <- data.frame(Zeit = minute, Status = temp)dta <- dta[rep(seq_len(nrow(dta)), n), ]# Scale everythingmaxs <- apply(dta, 2, max) mins <- apply(dta, 2, min)nnInput <- data.frame(Zeit = dta$Zeit, Status = dta$Status)nnInput <- as.data.frame(scale(nnInput, center = mins, scale = maxs - mins))trainingData <- nnInput[seq(1, nrow(nnInput), 2), ]testData <- nnInput[seq(2, nrow(nnInput), 2), ]# MODEL ---------------------model <- as.formula("Status ~ Zeit")net <- neuralnet::neuralnet(model, trainingData, hidden = 2, threshold = 0.01, linear.output = TRUE, lifesign = "full", stepmax = 100000, rep = 1)net.results <- neuralnet::compute(net, testData$Zeit)results <- net.results$net.result * (maxs["Status"] - mins["Status"]) + mins["Status"]testData <- as.data.frame(t(t(testData) * (maxs - mins) + mins))cleanOutput <- data.frame(Actual = testData$Status, Prediction = results, diff = abs(results - testData$Status))summary(cleanOutput)plot(cleanOutput$Actual[1:144], main = "Zeittabelle", xlab = paste("Min. seit 0:00 *", n), ylab = "Temperatur")lines(cleanOutput$Prediction[1:144], col = "red", lwd = 3)
回答:
基本上 – 初始化非常重要。如果你不进行随机初始化,那么你的网络可能完全无法工作(例如,将所有权重设置为0
)。也已证明,对于sigmoid和relu,某种类型的激活函数可能有助于训练你的网络。
但在你的情况下 – 我认为差异主要是由问题的复杂性造成的。模型的复杂性似乎与你的问题复杂性相匹配时,表现很好。其他模型可能因为以下原因表现不佳:
- 复杂性过低 – 只有一个节点可能无法学习到正确的函数。
- 复杂性过高 – 使用两层网络时,你可能会陷入局部最小值。增加网络参数的数量也会增加参数空间的大小。当然 – 一方面你可能会得到更好的模型 – 另一方面 – 你可能会落入参数空间的某个区域,导致较差的解决方案。也许尝试使用不同的初始化来运行相同的模型,并选择最佳模型可以克服这个问题。
更新:
-
对于小型网络 – 陷入局部最小值是很常见的。根据你训练网络所需的时间,你可以使用以下技术来克服这个问题:
- Dropout / 批量归一化 / 批量学习随机化: 当你能够稍微延长训练时间时 – 你可以使用dropout或批量归一化的随机化特性。由于这些随机波动,你可以从通常被认为是相对浅的较差局部最小值中脱离出来。
- 交叉验证 / 多次运行: 当你多次启动训练时 – 你最终陷入较差最小值的概率显著降低。
-
关于层大小与多项式次数之间的关系 – 我认为这个问题没有明确说明。你必须提供更多细节,例如激活函数。我还认为,多项式和经典神经网络能够建模的函数的性质有很大不同。在多项式中 – 参数值的微小变化通常会导致比神经网络更大的差异。通常,神经网络的导数是一个有界函数,而多项式的导数在次数大于2时是无界的。由于这些事实,我认为 – 寻找多项式次数与隐藏层大小之间的依赖关系可能不值得认真考虑。