python - 为什么模型甚至不能预测正弦

标签 python keras lstm recurrent-neural-network

我正在尝试使用 Keras 使用 LSTM RNN 生成学习时间序列,因此我想预测一个数据点,并将其作为输入反馈回来以预测下一个数据点,依此类推,以便我可以实际生成时间序列(例如给定 2000 个数据点,预测下一个 2000 个) 我正在这样尝试,但测试分数 RMSE 为 1.28,预测基本上是一条直线

# LSTM for international airline passengers problem with regression framing
import numpy
import matplotlib.pyplot as plt
from pandas import read_csv
import math
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_squared_error
# convert an array of values into a dataset matrix
def create_dataset(dataset, look_back=1):
    dataX, dataY = [], []
    for i in range(len(dataset)-look_back-1):
        a = dataset[i:(i+look_back), 0]
        dataX.append(a)
        dataY.append(dataset[i + look_back, 0])
    return numpy.array(dataX), numpy.array(dataY)
# fix random seed for reproducibility
numpy.random.seed(7)

# load the dataset
dataset = np.sin(np.linspace(0,35,10000)).reshape(-1,1)
print(type(dataset))
print(dataset.shape)
dataset = dataset.astype('float32')

# normalize the dataset
scaler = MinMaxScaler(feature_range=(0, 1))
dataset = scaler.fit_transform(dataset)

# split into train and test sets
train_size = int(len(dataset) * 0.5)
test_size = len(dataset) - train_size
train, test = dataset[0:train_size,:], dataset[train_size:len(dataset),:]

# reshape into X=t and Y=t+1
look_back = 1
trainX, trainY = create_dataset(train, look_back)
testX, testY = create_dataset(test, look_back)
# reshape input to be [samples, time steps, features]
trainX = numpy.reshape(trainX, (trainX.shape[0], 1, trainX.shape[1]))
testX = numpy.reshape(testX, (testX.shape[0], 1, testX.shape[1]))

# create and fit the LSTM network
model = Sequential()
model.add(LSTM(16, input_shape=(1, look_back)))
model.add(Dense(1))
model.compile(loss='mean_squared_error', optimizer='adam')
model.fit(trainX, trainY, epochs=10, batch_size=1, verbose=2)

# make predictions
trainPredict = model.predict(trainX)
testPredict = list()
prediction = model.predict(testX[0].reshape(1,1,1))
for i in range(trainX.shape[0]):
    prediction = model.predict(prediction.reshape(1,1,1))
    testPredict.append(prediction)
testPredict = np.array(testPredict).reshape(-1,1)

# invert predictions
trainPredict = scaler.inverse_transform(trainPredict)
trainY = scaler.inverse_transform([trainY])
testPredict = scaler.inverse_transform(testPredict)
testY = scaler.inverse_transform([testY])

# calculate root mean squared error
trainScore = math.sqrt(mean_squared_error(trainY[0], trainPredict[:,0]))
print('Train Score: %.2f RMSE' % (trainScore))
testScore = math.sqrt(mean_squared_error(testY[0], testPredict[:,0]))
print('Test Score: %.2f RMSE' % (testScore))
# shift train predictions for plotting
trainPredictPlot = numpy.empty_like(dataset)
trainPredictPlot[:, :] = numpy.nan
trainPredictPlot[look_back:len(trainPredict)+look_back, :] = trainPredict
# shift test predictions for plotting
testPredictPlot = numpy.empty_like(dataset)
testPredictPlot[:, :] = numpy.nan
testPredictPlot[len(trainPredict)+(look_back*2)+1:len(dataset)-1, :] = testPredict

# plot baseline and predictions
plt.plot(scaler.inverse_transform(dataset))
plt.plot(trainPredictPlot)
plt.plot(testPredictPlot)
plt.show()

我做错了什么?

最佳答案

我发现您的代码存在多个问题。 look_back 的值为 1,这意味着 LSTM 一次只能看到一个样本,这显然不足以了解有关序列的任何信息。

您这样做可能是为了通过将上一步的预测作为新输入来在最后做出最终预测。要实现这项工作,正确的方法是使用更多时间步进行训练,然后将网络更改为具有单个时间步的有状态 LSTM。

此外,当您进行最终预测时,您必须向网络显示多个真实样本。否则正弦上的位置是不明确的。 (下一步是上升还是下降?)

我举了一个简单的例子。以下是我生成数据的方式:

import numpy as np

numSamples = 1000
numTimesteps = 50
width = np.pi/2.0

def getRandomSine(numSamples = 100, width = np.pi):
    return np.sin(np.linspace(0,width,numSamples) + (np.random.rand()*np.pi*2))

trainX = np.stack([getRandomSine(numSamples = numTimesteps+1) for _ in range(numSamples)])
valX = np.stack([getRandomSine(numSamples = numTimesteps+1) for _ in range(numSamples)])

trainX = trainX.reshape((numSamples,numTimesteps+1,1))
valX = valX.reshape((numSamples,numTimesteps+1,1))

trainY = trainX[:,1:,:]
trainX = trainX[:,:-1,:]

valY = valX[:,1:,:]
valX = valX[:,:-1,:]

在这里我训练了模型:

import keras
from keras.models import Sequential
from keras import layers


model = Sequential()
model.add(layers.recurrent.LSTM(32,return_sequences=True,input_shape=(numTimesteps, 1)))
model.add(layers.recurrent.LSTM(32,return_sequences=True))
model.add(layers.wrappers.TimeDistributed(layers.Dense(1,input_shape=(1,10))))
model.compile(loss='mean_squared_error',
              optimizer='adam')
model.summary()

model.fit(trainX, trainY, nb_epoch=50, validation_data=(valX, valY), batch_size=32)

在这里,我更改了训练模型以允许继续预测:

# serialize the model and get its weights, for quick re-building
config = model.get_config()
weights = model.get_weights()

config[0]['config']['batch_input_shape'] = (1, 1, 1)
config[0]['config']['stateful'] = True
config[1]['config']['stateful'] = True

from keras.models import model_from_config
new_model = Sequential().from_config(config)
new_model.set_weights(weights)

#create test sine
testX = getRandomSine(numSamples = numTimesteps*10, width = width*10)

new_model.reset_states()
testPredictions = []
# burn in
for i in range(numTimesteps):
    prediction = new_model.predict(np.array([[[testX[i]]]]))
    testPredictions.append(prediction[0,0,0])

# prediction
for i in range(numTimesteps, len(testX)):
    prediction = new_model.predict(prediction)
    testPredictions.append(prediction[0,0,0])

# plot result
import matplotlib.pyplot as plt
plt.plot(np.stack([testPredictions,testX]).T)
plt.show()

结果如下。预测误差累加起来,很快就会偏离输入正弦。但它清楚地了解了正弦的一般形状。您现在可以尝试通过尝试不同的层、激活函数等来改进这一点。 enter image description here

关于python - 为什么模型甚至不能预测正弦,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43881364/

相关文章:

Python GTK : confirm overwrite dialog blocks filechooser dialog

python - 为什么 DataFrame 列对于 json 转换必须是唯一的?

tensorflow - Keras 内存不足的后果

python - 如何遍历各种训练和测试拆分

lstm - 运行时错误 : Expected hidden[0] size (2, 20, 256), 得到 (2, 50, 256)

machine-learning - 在 Keras 中使用 LSTM 将一系列向量映射到单个向量

python - 如何使用 LSTM 在 python 中进行序列标记?

javascript - Node.js 与 Twisted 的用例是什么?

python - 在 Matplotlib 中获取图例作为单独的图片

python - Keras,为什么向模型添加层这么慢?