Keras序列神经网络不能用完全解释变量学习为什么?

2024-09-28 01:26:53 发布

您现在位置:Python中文网/ 问答频道 /正文

我在Python中使用神经网络训练和预测时间序列时遇到了一些问题

我使用的数据集非常简单:目标列由0和1组成。只有一个解释变量,它是目标值。也就是说,如果在时间t,目标是预测1,那么在时间t-1的解释栏中会有一个1,因此我认为这个例子很容易预测。要使用与我相同的数据,可以执行以下操作:

# Load packages:
import pandas as pd
from pandas import read_csv
from keras.models import Sequential
from keras.layers import Dense
import random
from keras.layers import GRU
from sklearn.utils import class_weight
from matplotlib.patches import Patch
from matplotlib.lines import Line2D
import numpy as np
import matplotlib.pyplot as plt

# Create dataset
a = [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 1., 1., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 1., 1., 0., 0., 0., 1., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 1., 1., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 1., 1., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 1., 1., 1., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
1., 0., 0., 0., 1., 1., 0., 0., 0., 0., 1., 1., 0., 0., 0., 0., 0.,
0., 0., 1., 1., 1., 1., 0., 1., 0., 0., 1., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 1., 1., 0., 0., 0., 0., 0., 1., 0., 1., 1., 1., 1., 1., 1., 1.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 1., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 1., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0.]
b = [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 1., 0., 0., 0., 0., 0., 0.,
 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 1., 0., 0., 0., 1., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 1., 1.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 1., 1.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 1., 1., 1., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 1., 0., 0., 0., 1., 1., 0., 0., 0., 0., 1., 1., 0., 0., 0., 0.,
0., 0., 0., 1., 1., 1., 1., 0., 1., 0., 0., 1., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 1., 1., 0., 0., 0., 0., 0., 1., 0., 1., 1., 1., 1., 1., 1.,
1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 1., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 1., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0.]
dataset = pd.DataFrame({'a':a, 'b':b})

# Split into X and y data
class_X, class_y = dataset.values[:, :-1], dataset.values[:, -1]

# Last column in the dataframe should be the one we want to predict
def spitIntoTrainAndTest1(dataFrame):
values = dataFrame.values
# split into input and outputs
train_X, train_y = values[:, :-1], values[:, -1]
# reshape input to be 3D [samples, timesteps, features]
train_X = train_X.reshape((train_X.shape[0], 1, train_X.shape[1]))

return train_X, train_y

# Split classification into test and training data
X_clas2, y_clas2 = spitIntoTrainAndTest1(dataset)

# Used in RNN
X_clas_RNN = np.squeeze(X_clas2, axis=1)
y_clas_RNN = np.expand_dims(y_clas2, axis=1)

# Used in GRU
lengthOfDataset = len(X_clas2)
train_X_clas2 = np.squeeze(X_clas2, axis=1)
X_clas_GRU = np.reshape(train_X_clas2, (lengthOfDataset,1,1))
y_clas_GRU = y_clas_RNN

下一部分是关于将模型拟合到数据:

# Parameters in the fitting
numberOfEpochs = 100
batchSize = 50
printFit = 1# 1 = true
randomSeedNumber = 164
validationSplitRatio = 0.33

# ORDINARY RNN MODEL:

# create model
random.seed(randomSeedNumber)
model_RNN = Sequential()
model_RNN.add(Dense(32, input_dim=1, activation='relu'))
model_RNN.add(Dense(32, activation='relu'))
model_RNN.add(Dense(1, activation='sigmoid'))
model_RNN.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
RNN_history = model_RNN.fit(X_clas_RNN, y_clas_RNN, 
validation_split=validationSplitRatio, epochs=numberOfEpochs, 
batch_size=batchSize, verbose=1)

# WEIGHTED GRU MODEL:

model_GRU_weight = Sequential()
model_GRU_weight.add(GRU(1, input_shape=(1,1)))
model_GRU_weight.add(Dense(32, activation='relu'))
model_GRU_weight.add(Dense(32, activation='relu'))
model_GRU_weight.add(Dense(32, activation='relu'))
model_GRU_weight.add(Dense(32, activation='relu'))
model_GRU_weight.add(Dense(32, activation='relu'))
model_GRU_weight.add(Dense(32, activation='relu'))
model_GRU_weight.add(Dense(32, activation='relu'))
model_GRU_weight.add(Dense(32, activation='relu'))
model_GRU_weight.add(Dense(1, activation='softmax'))
model_GRU_weight.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
#model_GRU_weight.fit(train_X_clas3, train_y_class, epochs=100, batch_size=500, class_weight = 'auto')
GRU_weight_history = model_GRU_weight.fit(X_clas_GRU, y_clas_GRU, validation_split=validationSplitRatio, 
                                      epochs=numberOfEpochs, batch_size=batchSize, verbose = printFit, 
                                      class_weight = 'auto', shuffle=False)

最后,我要评估结果/预测:

# Combine the predictions on the test dataset

# Predicitons made
firstValObs = round(validationSplitRatio*len(X_clas_RNN))+1
valSet2 = X_clas_RNN[firstValObs:,:]
valSet3 = X_clas_GRU[firstValObs:,:]
actuals = pd.DataFrame(y_clas_RNN[firstValObs:,:])
predictions_RNN = np.round(model_RNN.predict(valSet2))
predictions_GRU_weight = np.round(model_GRU_weight.predict(valSet3))

timeSequence = np.r_[1:(len(predictions_GRU_weight)+1)]
firstValObs = round(validationSplitRatio*len(X_clas_RNN))+1

# Plot predictions
numberOfRows = 3
numberOfCols = 1
minY=-0.1
maxY = 1.1

plt.figure(1)

plt.subplot(numberOfRows, numberOfCols, 1)
plt.plot(timeSequence, actuals)
plt.ylim((minY,maxY))
plt.title('Actuals')
plt.xticks([])
plt.yticks([])
plt.subplot(numberOfRows, numberOfCols, 2)
plt.plot(timeSequence, predictions_RNN)
plt.ylim((minY,maxY))
plt.title('RNN predictions')
plt.xticks([])
plt.yticks([])
plt.subplot(numberOfRows, numberOfCols, 3)
plt.plot(timeSequence, predictions_GRU_weight)
plt.ylim((minY,maxY))
plt.title('GRU weighted predictions')
plt.xticks([])
plt.yticks([])
plt.tight_layout()

plt.show()

获得的绘图如下所示:

enter image description here

目前RNN正在做出正确的预测。如果我改代码为:

# create model
random.seed(randomSeedNumber)
model_RNN = Sequential()
model_RNN.add(Dense(32, input_dim=1, activation='relu'))
model_RNN.add(Dense(8, activation='relu'))
model_RNN.add(Dense(1, activation='sigmoid'))
model_RNN.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
RNN_history = model_RNN.fit(X_clas_RNN, y_clas_RNN, 
validation_split=validationSplitRatio, epochs=numberOfEpochs, 
batch_size=batchSize, verbose=1)

结果如下:

enter image description here

我觉得有些事情很奇怪

我有点惊讶,因为在我看来,它必须有足够数量的神经元在每一层作出这个简单的预测(移动一个周期的序列)。第二个代码片段中RNN中的神经元数量真的不够吗

我不明白为什么加权GRU不能做出更好的预测。如果第一个问题的答案是更多的神经元可以提高性能,那么我认为这里应该有足够的神经元。而且我发现很难接受它的过度适合,因为它应该是相当简单的,只是把它一个时期。然而,它总是预测1-你对此有什么解释吗

此外,我想知道输入参数的值(epochs、批量大小、层数、每层神经元数)是否有经验法则。我实际考虑的数据集长度与此相同(大约500个),但有5个输入变量(X),而不是上述示例中的一列

请不要犹豫,如果你对我做错了什么或应该考虑的事情有任何意见的话。p>

提前谢谢


Tags: importaddmodelnptrainpltactivationdense
1条回答
网友
1楼 · 发布于 2024-09-28 01:26:53

首先,谢谢你的回答,凯西

我试着做了一些改变:

# ORDINARY RNN MODEL:

# create model
random.seed(randomSeedNumber)
model_RNN = Sequential()
model_RNN.add(Dense(1, input_dim=1, activation='relu'))
model_RNN.add(Dense(1, activation='relu'))
model_RNN.add(Dense(1, activation='sigmoid'))
model_RNN.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
RNN_history = model_RNN.fit(X_clas_RNN, y_clas_RNN, validation_split=validationSplitRatio, epochs=numberOfEpochs, batch_size=batchSize, verbose=1)

# WEIGHTED GRU MODEL:

model_GRU_weight = Sequential()
model_GRU_weight.add(GRU(1, input_shape=(1,1)))
model_GRU_weight.add(Dense(1, activation='relu'))
model_GRU_weight.add(Dense(1, activation='softmax'))
model_GRU_weight.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
#model_GRU_weight.fit(train_X_clas3, train_y_class, epochs=100, batch_size=500, class_weight = 'auto')
GRU_weight_history = model_GRU_weight.fit(X_clas_GRU, y_clas_GRU, validation_split=validationSplitRatio, 
                                          epochs=numberOfEpochs, batch_size=batchSize, verbose = printFit, 
                                          class_weight = 'auto', shuffle=False)

我得到的结果仍然是这样的: enter image description here

关于过于复杂的模型:因为数据中没有噪音(它完全是干净的,因为它只是移动),我看不出它应该过度拟合什么。。?此外,我同意一个简单的模型就足够了,但我希望一个更灵活/复杂的模型也能够捕捉到它,因为没有噪音来“干扰它”。请随便谈谈你的想法

如上所述,我的成绩没有改善-我做了什么,你认为呢

相关问题 更多 >

    热门问题