我正在根据过去的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的图表分别呈现的效果。
以下是我使用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('值')
最后,当我运行代码时,神经模型似乎很好地捕捉到了信号的模式,如下图所示。
然而,我在这个输出中遇到的问题是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_x
和scaler_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)