使用Keras进行LSTM预测

我正在根据过去的X值预测Y。我们格式化的CSV数据集有三列(时间戳、X和Y – 其中Y是实际值),其样本格式如下:

time,X,Y0.000561,0,100.000584,0,100.040411,5,100.040437,10,100.041638,12,100.041668,14,100.041895,15,100.041906,19,10 ... ... ...

在训练预测模型之前,以下是X和Y的图表分别呈现的效果。

enter image description here

enter image description here

以下是我使用Keras在Python中通过LSTM循环神经网络解决这个问题的步骤。

import numpy as npfrom keras.models import Sequentialfrom keras.layers import LSTM, Densefrom sklearn.preprocessing import MinMaxScalerimport pandas as pdimport matplotlib.pyplot as pltfrom sklearn.metrics import mean_squared_errornp.random.seed(7)# 加载数据df = pd.read_csv('test32_C_data.csv')n_features = 100def create_sequences(data, window=15, step=1, prediction_distance=15):    x = []    y = []    for i in range(0, len(data) - window - prediction_distance, step):        x.append(data[i:i + window])        y.append(data[i + window + prediction_distance][1])    x, y = np.asarray(x), np.asarray(y)    return x, y# 在分割前进行缩放scaler = MinMaxScaler(feature_range=(0.01, 0.99))scaled_data = scaler.fit_transform(df.loc[:, ["X", "Y"]].values)# 构建序列x_sequence, y_sequence = create_sequences(scaled_data)# 创建测试/训练分割test_len = int(len(x_sequence) * 0.90)valid_len = int(len(x_sequence) * 0.90)train_end = len(x_sequence) - (test_len + valid_len)x_train, y_train = x_sequence[:train_end], y_sequence[:train_end]x_valid, y_valid = x_sequence[train_end:train_end + valid_len], y_sequence[train_end:train_end + valid_len]x_test, y_test = x_sequence[train_end + valid_len:], y_sequence[train_end + valid_len:]# 初始化RNNmodel = Sequential()# 添加输入层和LSTM层model.add(LSTM(15, input_shape=(15, 2)))# 添加输出层model.add(Dense(1))# 编译RNNmodel.compile(loss='mse', optimizer='rmsprop')# 训练RNNmodel.fit(x_train, y_train, epochs=5)# 获取预测值y_pred = model.predict(x_test)#y_pred = scaler.inverse_transform(y_pred)plot_colors = ['#332288', '#3cb44b']# 绘制结果pd.DataFrame({"实际值": y_test, "预测值": np.squeeze(y_pred)}).plot(color=plot_colors)plt.xlabel('时间[索引]')plt.ylabel('值')

最后,当我运行代码时,神经模型似乎很好地捕捉到了信号的模式,如下图所示。

enter image description here

然而,我在这个输出中遇到的问题是Y的范围。正如前两个图表所示,范围应该是0-400,如上所示。为了解决这个问题,我尝试使用scaler进行inverse_transform,如y_pred = scaler.inverse_transform(y_pred),但这会抛出错误:ValueError: non-broadcastable output operand with shape (7625,1) doesn't match the broadcast shape (7625,2)。我们如何解决这个broadcast shape错误?


回答:

基本上,scaler记住了它被输入了2个特征(/列)。所以它期望有2个特征来反转变换。

这里有两个选项。

1) 你可以创建两个不同的scaler:scaler_xscaler_y,如下所示:

# 在分割前进行缩放scaler_x = MinMaxScaler(feature_range=(0.01, 0.99))scaler_y = MinMaxScaler(feature_range=(0.01, 0.99))scaled_x = scaler_x.fit_transform(df.loc[:, "X"].reshape([-1, 1]))scaled_y = scaler_y.fit_transform(df.loc[:, "Y"].reshape([-1, 1]))scaled_data = np.column_stack((scaled_x, scaled_y))

然后你就可以这样做:

y_pred = scaler_y.inverse_transform(y_pred)

2) 你可以在输出中伪造X列,如下所示:

y_pred_reshaped = np.zeros((len(y_pred), 2))y_pred_reshaped[:,1] = y_predy_pred = scaler.inverse_transform(y_pred_reshaped)[:,1]

这有帮助吗?

编辑

这里是所需的完整代码

import numpy as npfrom keras.models import Sequentialfrom keras.layers import LSTM, Densefrom sklearn.preprocessing import MinMaxScalerimport pandas as pdimport matplotlib.pyplot as pltfrom sklearn.metrics import mean_squared_errornp.random.seed(7)# 加载数据#df = pd.read_csv('test32_C_data.csv')df = pd.DataFrame(np.random.randint(0,100, size=(100,3)), columns = ['time', 'X', 'Y'])n_features = 100def create_sequences(data, window=15, step=1, prediction_distance=15):    x = []    y = []    for i in range(0, len(data) - window - prediction_distance, step):        x.append(data[i:i + window])        y.append(data[i + window + prediction_distance][1])    x, y = np.asarray(x), np.asarray(y)    return x, y# 在分割前进行缩放scaler_x = MinMaxScaler(feature_range=(0.01, 0.99))scaler_y = MinMaxScaler(feature_range=(0.01, 0.99))scaled_x = scaler_x.fit_transform(df.loc[:, "X"].reshape([-1,1]))scaled_y = scaler_y.fit_transform(df.loc[:, "Y"].reshape([-1,1]))scaled_data = np.column_stack((scaled_x, scaled_y))# 构建序列x_sequence, y_sequence = create_sequences(scaled_data)test_len = int(len(x_sequence) * 0.90)valid_len = int(len(x_sequence) * 0.90)train_end = len(x_sequence) - (test_len + valid_len)x_train, y_train = x_sequence[:train_end], y_sequence[:train_end]x_valid, y_valid = x_sequence[train_end:train_end + valid_len], y_sequence[train_end:train_end + valid_len]x_test, y_test = x_sequence[train_end + valid_len:], y_sequence[train_end + valid_len:]# 初始化RNNmodel = Sequential()# 添加输入层和LSTM层model.add(LSTM(15, input_shape=(15, 2)))# 添加输出层model.add(Dense(1))# 编译RNNmodel.compile(loss='mse', optimizer='rmsprop')# 训练RNNmodel.fit(x_train, y_train, epochs=5)# 获取预测值y_pred = model.predict(x_test)y_pred = scaler_y.inverse_transform(y_pred)

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注