我已经按照这个教程 https://www.youtube.com/watch?v=QIUxPv5PJOY 来预测苹果公司股票价格的未来一天。代码如下:
#导入库import mathimport pandas_datareader as webimport numpy as npimport pandas as pdfrom sklearn.preprocessing import MinMaxScalerfrom keras.models import Sequential from keras.layers import Dense, LSTMimport matplotlib.pyplot as pltplt.style.use('fivethirtyeight')#获取股票报价df = web.DataReader('AAPL', data_source='yahoo', start='2012-01-01', end='2020-12-07')#显示数据df#获取数据集中的行数和列数df.shape#可视化收盘价历史#我们创建一个名为'Close Price History'的图表plt.figure(figsize=(16,8))plt.title('Close Price History')#我们给图表提供数据(我们的股票收盘价)plt.plot(df['Close'])#我们标记轴plt.xlabel('Date', fontsize=18)plt.ylabel('Close Price USD ($)', fontsize=18)#我们显示图表plt.show()
#创建一个只包含'Close'列的新数据框data = df.filter(['Close'])#将数据框转换为numpy数组dataset = data.values#获取用于训练模型的行数training_data_len = math.ceil( len(dataset) * 0.8 )training_data_len#缩放数据scaler = MinMaxScaler(feature_range=(0,1))scaled_data = scaler.fit_transform(dataset)scaled_data#创建训练数据集 #创建缩放后的训练数据集train_data = scaled_data[0:training_data_len, :]#将数据拆分为x_train和y_train数据集x_train = []y_train = []#我们创建一个循环for i in range(60, len(train_data)): x_train.append(train_data[i-60:i, 0]) #将包含60个值(0-59) y_train.append(train_data[i, 0]) #将包含第61个值(60) if i <= 60: print(x_train) print(y_train) print()#将x_train和y_train转换为numpy数组x_train, y_train = np.array(x_train), np.array(y_train)#重塑数据x_train = np.reshape(x_train, (x_train.shape[0], x_train.shape[1], 1))x_train.shape#构建LSTM模型model = Sequential()model.add(LSTM(50, return_sequences=True, input_shape=(x_train.shape[1], 1)))model.add(LSTM(50, return_sequences=False))model.add(Dense(25))model.add(Dense(1))#编译模型model.compile(optimizer='adam', loss='mean_squared_error')#训练模型model.fit(x_train, y_train, batch_size=1, epochs=1)#创建测试数据集#创建一个包含从索引1738到2247的缩放值的新数组test_data = scaled_data[training_data_len - 60:]#创建数据集x_test和y_testx_test = []y_test = dataset[training_data_len:, :]for i in range(60, len(test_data)): x_test.append(test_data[i-60:i, 0])#将数据转换为numpy数组x_test = np.array(x_test)#重塑数据x_test = np.reshape(x_test, (x_test.shape[0], x_test.shape[1], 1))#获取模型对x_test数据集的预测价格值predictions = model.predict(x_test)predictions = scaler.inverse_transform(predictions)predictions#评估模型(获取均方根误差(RMSE))rmse = np.sqrt( np.mean( predictions - y_test )**2 )rmse#绘制数据train = data[:training_data_len]valid = data[training_data_len:]valid['Predictions'] = predictions#可视化数据plt.figure(figsize=(16,8))plt.title('Model')plt.xlabel('Date', fontsize=18)plt.ylabel('Close Price USD ($)', fontsize=18)plt.plot(train['Close'])plt.plot(valid[['Close', 'Predictions']])plt.legend(['Train', 'Validation', 'Predictions'], loc='lower right')plt.show()
现在我想扩展图表的预测部分,以显示未来的日期(未来’x’天)。我想我可以通过获取下一天的预测价格,然后用这个价格作为输入来获取下一天的价格,再用那一天的价格来获取下一天的价格,依此类推。我该怎么做呢?我考虑过将下一天的预测价格添加到用于训练模型的数据集中,但没有成功。谢谢你的帮助。
回答:
你的直觉是正确的。我按照你所想的方式做了如下操作:
X_FUTURE = 100predictions = np.array([])last = x_test[-1]for i in range(X_FUTURE): curr_prediction = model.predict(np.array([last])) print(curr_prediction) last = np.concatenate([last[1:], curr_prediction]) predictions = np.concatenate([predictions, curr_prediction[0]])predictions = scaler.inverse_transform([predictions])[0]print(predictions)
我基本上是通过新的预测构建了移位数组
之后我构建了包含新预测的数据框:
import datetimefrom datetime import timedeltadicts = []curr_date = data.index[-1]for i in range(X_FUTURE): curr_date = curr_date + timedelta(days=1) dicts.append({'Predictions':predictions[i], "Date": curr_date})new_data = pd.DataFrame(dicts).set_index("Date")
然后我绘制了结果:
#绘制数据train = data#可视化数据plt.figure(figsize=(16,8))plt.title('Model')plt.xlabel('Date', fontsize=18)plt.ylabel('Close Price USD ($)', fontsize=18)plt.plot(train['Close'])plt.plot(new_data['Predictions'])plt.legend(['Train', 'Predictions'], loc='lower right')plt.show()
为什么看起来这么糟糕(当然我们不知道未来…)?我确实对整个数据集重新训练了模型,但问题在于预测的越远,不确定性就越大。我对时间序列预测不是很在行,但我认为模型在时间序列下没有学到任何好的模式。但作为一个例子,它确实完成了它需要做的工作