为什么RNN总是输出1
Why does RNN always output 1
我正在使用递归神经网络 (RNN) 进行预测,但由于某些奇怪的原因,它总是输出 1。这里我用一个玩具示例来解释这一点:
例子
考虑一个维度为 (360, 5) 的矩阵 M
,以及一个包含行和 M
的向量 Y
。现在,使用 RNN,我想从 M
预测 Y
。使用 rnn
R
包,我将模型训练为
library(rnn)
M <- matrix(c(1:1800),ncol=5,byrow = TRUE) # Matrix (say features)
Y <- apply(M,1,sum) # Output equls to row sum of M
mt <- array(c(M),dim=c(NROW(M),1,NCOL(M))) # matrix formatting as [samples, timesteps, features]
yt <- array(c(Y),dim=c(NROW(M),1,NCOL(Y))) # formatting
model <- trainr(X=mt,Y=yt,learningrate=0.5,hidden_dim=10,numepochs=1000) # training
我在训练时观察到的一件奇怪的事情是历元误差总是 4501。理想情况下,历元误差应该随着历元数的增加而减少。
接下来,我创建了一个与上面结构相同的测试数据集:
M2 <- matrix(c(1:15),nrow=3,byrow = TRUE)
mt2 <- array(c(M2),dim=c(NROW(M2),1,NCOL(M2)))
predictr(model,mt2)
通过预测,我得到的输出总是 1。
持续的纪元错误和相同的输出可能是什么原因?
更新#1
@Barker 提供的答案不适用于我的问题。为了打开它,我在这里通过 dropbox 链接分享简约数据 traindata, testadata,我的 R
代码分享为
数据详细信息:第 'power' 列是响应变量,它是前几天从第 1 天到第 14 天消耗的温度、湿度和功率的函数。
normalize_data <- function(x){
normalized = (x-min(x))/(max(x)-min(x))
return(normalized)
}
#read test and train data
traindat <- read.csv(file = "train.csv")
testdat <- read.csv(file = "test.csv")
# column "power" is response variable and remaining are predictors
# predictors in traindata
trainX <- traindat[,1:dim(traindat)[2]-1]
# response of train data
trainY <- traindat$power
# arrange data acc. to RNN as [samples,time steps, features]
tx <- array(as.matrix(trainX), dim=c(NROW(trainX), 1, NCOL(trainX)))
tx <- normalize_data(tx) # normalize data in range of [0,1]
ty <- array(trainY, dim=c(NROW(trainY), 1, NCOL(trainY))) # arrange response acc. to predictors
# train model
model <- trainr(X = tx, Y = ty, learningrate = 0.08, hidden_dim = 6, numepochs = 400)
# predictors in test data
testX <- testdat[,1:dim(testdat)[2]-1]
testX <- normalize_data(testX) # normalize data in range of [0,1]
#testY <- testdat$power
# arrange data acc. to RNN as [samples,time steps, features]
tx2 <- array(as.matrix(testX), dim=c(NROW(testX), 1, NCOL(testX))) # predict
pred <- predictr(model,tx2)
pred
我改变了参数 learning rate, hidden_dim, numepochs
,但结果仍然是 0.9 或 1。
大多数 RNN 不喜欢没有常量均值的数据。处理此问题的一种策略是区分数据。要了解其工作原理,让我们使用基础 R
时间序列 co2
。这是一个具有良好平滑季节性和趋势的时间序列,因此我们应该能够预测它。
对于我们的模型,我们的输入矩阵将是 co2
时间序列的 "seasonality" 和 "trend",使用 stl
分解创建。因此,让我们像以前一样制作我们的训练和测试数据并训练模型(注意我减少了运行时的 numepochs
)。我会用到最后一年半的所有数据做训练,然后用最后一年半做测试:
#Create the STL decomposition
sdcomp <- stl(co2, s.window = 7)$time.series[,1:2]
Y <- window(co2, end = c(1996, 6))
M <- window(sdcomp, end = c(1996, 6))
#Taken from OP's code
mt <- array(c(M),dim=c(NROW(M),1,NCOL(M)))
yt <- array(c(Y),dim=c(NROW(M),1,NCOL(Y)))
model <- trainr(X=mt,Y=yt,learningrate=0.5,hidden_dim=10,numepochs=100)
现在我们可以根据去年的测试数据创建预测:
M2 <- window(sdcomp, start = c(1996,7))
mt2 <- array(c(M2),dim=c(NROW(M2),1,NCOL(M2)))
predictr(model,mt2)
output:
[,1]
[1,] 1
[2,] 1
[3,] 1
[4,] 1
[5,] 1
[6,] 1
[7,] 1
[8,] 1
[9,] 1
[10,] 1
[11,] 1
[12,] 1
[13,] 1
[14,] 1
[15,] 1
[16,] 1
[17,] 1
[18,] 1
Ewe,又是所有的,就像你的例子一样。现在让我们再试一次,但这次我们将对数据进行差分。由于我们试图做出一年半的预测,因此我们将使用 18 作为差分滞后,因为这些值是我们提前 18 个月知道的值。
dco2 <- diff(co2, 18)
sdcomp <- stl(dco2, s.window = "periodic")$time.series[,1:2]
plot(dco2)
太好了,趋势现在已经消失,所以我们的神经网络应该能够更好地找到模式。让我们用新数据再试一次。
Y <- window(dco2, end = c(1996, 6))
M <- window(sdcomp, end = c(1996, 6))
mt <- array(c(M),dim=c(NROW(M),1,NCOL(M)))
yt <- array(c(Y),dim=c(NROW(M),1,NCOL(Y)))
model <- trainr(X=mt,Y=yt,learningrate=0.5,hidden_dim=10,numepochs=100)
M2 <- window(sdcomp, start = c(1996,7))
mt2 <- array(c(M2),dim=c(NROW(M2),1,NCOL(M2)))
(preds <- predictr(model,mt2))
output:
[,1]
[1,] 9.999408e-01
[2,] 9.478496e-01
[3,] 6.101828e-08
[4,] 2.615463e-08
[5,] 3.144719e-08
[6,] 1.668084e-06
[7,] 9.972314e-01
[8,] 9.999901e-01
[9,] 9.999916e-01
[10,] 9.999916e-01
[11,] 9.999916e-01
[12,] 9.999915e-01
[13,] 9.999646e-01
[14,] 1.299846e-02
[15,] 3.114577e-08
[16,] 2.432247e-08
[17,] 2.586075e-08
[18,] 1.101596e-07
好的,现在有东西了!让我们看看它与我们试图预测的相比如何,dco2
:
不理想,但我们正在寻找数据的一般 "up down" 模式。现在你所要做的就是调整你的学习率并开始优化所有那些可爱的 hyper-parameters ,这使得使用神经网络变得如此快乐。当它按照您想要的方式工作时,您可以只获取最终输出并在过去 18 个月的训练数据中添加回来。
根据我对包示例的回顾(参见 ?trainr
),训练函数的输入必须是二进制的。包中有函数int2bin
和bin2int
。
我无法让它们正常工作,但似乎需要转换为二进制文件。
我正在使用递归神经网络 (RNN) 进行预测,但由于某些奇怪的原因,它总是输出 1。这里我用一个玩具示例来解释这一点:
例子
考虑一个维度为 (360, 5) 的矩阵 M
,以及一个包含行和 M
的向量 Y
。现在,使用 RNN,我想从 M
预测 Y
。使用 rnn
R
包,我将模型训练为
library(rnn)
M <- matrix(c(1:1800),ncol=5,byrow = TRUE) # Matrix (say features)
Y <- apply(M,1,sum) # Output equls to row sum of M
mt <- array(c(M),dim=c(NROW(M),1,NCOL(M))) # matrix formatting as [samples, timesteps, features]
yt <- array(c(Y),dim=c(NROW(M),1,NCOL(Y))) # formatting
model <- trainr(X=mt,Y=yt,learningrate=0.5,hidden_dim=10,numepochs=1000) # training
我在训练时观察到的一件奇怪的事情是历元误差总是 4501。理想情况下,历元误差应该随着历元数的增加而减少。
接下来,我创建了一个与上面结构相同的测试数据集:
M2 <- matrix(c(1:15),nrow=3,byrow = TRUE)
mt2 <- array(c(M2),dim=c(NROW(M2),1,NCOL(M2)))
predictr(model,mt2)
通过预测,我得到的输出总是 1。 持续的纪元错误和相同的输出可能是什么原因?
更新#1
@Barker 提供的答案不适用于我的问题。为了打开它,我在这里通过 dropbox 链接分享简约数据 traindata, testadata,我的 R
代码分享为
数据详细信息:第 'power' 列是响应变量,它是前几天从第 1 天到第 14 天消耗的温度、湿度和功率的函数。
normalize_data <- function(x){
normalized = (x-min(x))/(max(x)-min(x))
return(normalized)
}
#read test and train data
traindat <- read.csv(file = "train.csv")
testdat <- read.csv(file = "test.csv")
# column "power" is response variable and remaining are predictors
# predictors in traindata
trainX <- traindat[,1:dim(traindat)[2]-1]
# response of train data
trainY <- traindat$power
# arrange data acc. to RNN as [samples,time steps, features]
tx <- array(as.matrix(trainX), dim=c(NROW(trainX), 1, NCOL(trainX)))
tx <- normalize_data(tx) # normalize data in range of [0,1]
ty <- array(trainY, dim=c(NROW(trainY), 1, NCOL(trainY))) # arrange response acc. to predictors
# train model
model <- trainr(X = tx, Y = ty, learningrate = 0.08, hidden_dim = 6, numepochs = 400)
# predictors in test data
testX <- testdat[,1:dim(testdat)[2]-1]
testX <- normalize_data(testX) # normalize data in range of [0,1]
#testY <- testdat$power
# arrange data acc. to RNN as [samples,time steps, features]
tx2 <- array(as.matrix(testX), dim=c(NROW(testX), 1, NCOL(testX))) # predict
pred <- predictr(model,tx2)
pred
我改变了参数 learning rate, hidden_dim, numepochs
,但结果仍然是 0.9 或 1。
大多数 RNN 不喜欢没有常量均值的数据。处理此问题的一种策略是区分数据。要了解其工作原理,让我们使用基础 R
时间序列 co2
。这是一个具有良好平滑季节性和趋势的时间序列,因此我们应该能够预测它。
对于我们的模型,我们的输入矩阵将是 co2
时间序列的 "seasonality" 和 "trend",使用 stl
分解创建。因此,让我们像以前一样制作我们的训练和测试数据并训练模型(注意我减少了运行时的 numepochs
)。我会用到最后一年半的所有数据做训练,然后用最后一年半做测试:
#Create the STL decomposition
sdcomp <- stl(co2, s.window = 7)$time.series[,1:2]
Y <- window(co2, end = c(1996, 6))
M <- window(sdcomp, end = c(1996, 6))
#Taken from OP's code
mt <- array(c(M),dim=c(NROW(M),1,NCOL(M)))
yt <- array(c(Y),dim=c(NROW(M),1,NCOL(Y)))
model <- trainr(X=mt,Y=yt,learningrate=0.5,hidden_dim=10,numepochs=100)
现在我们可以根据去年的测试数据创建预测:
M2 <- window(sdcomp, start = c(1996,7))
mt2 <- array(c(M2),dim=c(NROW(M2),1,NCOL(M2)))
predictr(model,mt2)
output:
[,1]
[1,] 1
[2,] 1
[3,] 1
[4,] 1
[5,] 1
[6,] 1
[7,] 1
[8,] 1
[9,] 1
[10,] 1
[11,] 1
[12,] 1
[13,] 1
[14,] 1
[15,] 1
[16,] 1
[17,] 1
[18,] 1
Ewe,又是所有的,就像你的例子一样。现在让我们再试一次,但这次我们将对数据进行差分。由于我们试图做出一年半的预测,因此我们将使用 18 作为差分滞后,因为这些值是我们提前 18 个月知道的值。
dco2 <- diff(co2, 18)
sdcomp <- stl(dco2, s.window = "periodic")$time.series[,1:2]
plot(dco2)
太好了,趋势现在已经消失,所以我们的神经网络应该能够更好地找到模式。让我们用新数据再试一次。
Y <- window(dco2, end = c(1996, 6))
M <- window(sdcomp, end = c(1996, 6))
mt <- array(c(M),dim=c(NROW(M),1,NCOL(M)))
yt <- array(c(Y),dim=c(NROW(M),1,NCOL(Y)))
model <- trainr(X=mt,Y=yt,learningrate=0.5,hidden_dim=10,numepochs=100)
M2 <- window(sdcomp, start = c(1996,7))
mt2 <- array(c(M2),dim=c(NROW(M2),1,NCOL(M2)))
(preds <- predictr(model,mt2))
output:
[,1]
[1,] 9.999408e-01
[2,] 9.478496e-01
[3,] 6.101828e-08
[4,] 2.615463e-08
[5,] 3.144719e-08
[6,] 1.668084e-06
[7,] 9.972314e-01
[8,] 9.999901e-01
[9,] 9.999916e-01
[10,] 9.999916e-01
[11,] 9.999916e-01
[12,] 9.999915e-01
[13,] 9.999646e-01
[14,] 1.299846e-02
[15,] 3.114577e-08
[16,] 2.432247e-08
[17,] 2.586075e-08
[18,] 1.101596e-07
好的,现在有东西了!让我们看看它与我们试图预测的相比如何,dco2
:
不理想,但我们正在寻找数据的一般 "up down" 模式。现在你所要做的就是调整你的学习率并开始优化所有那些可爱的 hyper-parameters ,这使得使用神经网络变得如此快乐。当它按照您想要的方式工作时,您可以只获取最终输出并在过去 18 个月的训练数据中添加回来。
根据我对包示例的回顾(参见 ?trainr
),训练函数的输入必须是二进制的。包中有函数int2bin
和bin2int
。
我无法让它们正常工作,但似乎需要转换为二进制文件。