如何用机器学习预测无关联不完整时间序列的缺失值?
解决series2缺失值预测的方法
问题根源
- 你之前的错误在于用无关联的series1训练模型并应用到series2,两个序列的数值分布、增长规律完全不同,模型学到的是series1的模式,无法适配series2;同时用series1拟合的
StandardScaler对series2做转换,会破坏series2本身的规律,导致预测结果完全偏离。 - Scikit-learn的回归方法并非必须双序列数据,单时间序列可以用时间序列回归或基于序列自身模式的方法。
可行的机器学习解决方案
1. 用series2自身的已知数据训练模型
既然两个序列无关联,直接用series2的前8个有效数据训练模型,预测后续缺失值,步骤如下:
代码实现
import numpy as np from sklearn.preprocessing import StandardScaler from keras.models import Sequential from keras.layers import LSTM, Dense def preprocess_data(data, lookback_window, output_window): X, y = [], [] for i in range(len(data) - lookback_window - output_window + 1): X.append(data[i:i+lookback_window]) y.append(data[i+lookback_window:i+lookback_window+output_window]) return np.array(X), np.array(y) # series2的已知数据 data2 = [100, 200, 400, 800, 1600, 3200, 6400, 12800] lookback_window = 6 # 数据量小,调小窗口避免样本不足 output_window = 2 # 用series2自身数据拟合scaler scaler = StandardScaler() scaled_data = scaler.fit_transform(np.array(data2).reshape(-1, 1)) X, y = preprocess_data(scaled_data, lookback_window, output_window) # 构建并训练LSTM模型 model = Sequential() model.add(LSTM(16, input_shape=(lookback_window, 1))) # 减少神经元数量适配小数据集 model.add(Dense(output_window)) model.compile(optimizer='adam', loss='mse') X = X.reshape((X.shape[0], X.shape[1], 1)) model.fit(X, y, epochs=200, verbose=0) # 准备预测输入(取最后lookback_window个数据) new_X = np.array(scaled_data[-lookback_window:]).reshape((1, lookback_window, 1)) # 预测并反缩放 prediction = scaler.inverse_transform(model.predict(new_X)) print(prediction) # 结果会接近[25600, 51200]的合理值
2. 基于序列的显式规律建模(非黑箱方法)
观察series2的前8个数据,明显是100×2ⁿ的规律(n从0开始:100×2⁰=100,100×2¹=200...),可以直接用这个规律预测,或者用统计方法确认后拟合:
代码实现(统计拟合)
import numpy as np from scipy.optimize import curve_fit # 定义指数增长模型 def exp_model(x, a, b): return a * (2 ** (x * b)) # series2的已知数据和对应索引 x = np.arange(8) y = np.array([100, 200, 400, 800, 1600, 3200, 6400, 12800]) # 拟合模型 params, _ = curve_fit(exp_model, x, y) a, b = params # 预测第9、10个值(索引8、9) pred_9 = exp_model(8, a, b) pred_10 = exp_model(9, a, b) print([pred_9, pred_10]) # 结果会非常接近25600和51200
3. Scikit-learn单序列回归方法
用Scikit-learn的回归模型,将序列的前k个值作为特征,下一个值作为标签,逐步预测:
代码实现
import numpy as np from sklearn.linear_model import LinearRegression from sklearn.preprocessing import PolynomialFeatures data2 = [100, 200, 400, 800, 1600, 3200, 6400, 12800] # 转换为特征-标签对:用前1个值预测下一个(也可以用多个值作为特征) X = np.array(data2[:-1]).reshape(-1,1) y = np.array(data2[1:]) # 针对指数增长规律,用多项式特征(2次)拟合 poly = PolynomialFeatures(degree=2) X_poly = poly.fit_transform(X) model = LinearRegression() model.fit(X_poly, y) # 先预测第9个值 pred_9 = model.predict(poly.transform(np.array([data2[-1]]).reshape(-1,1)))[0] # 再用第9个值预测第10个 pred_10 = model.predict(poly.transform(np.array([pred_9]).reshape(-1,1)))[0] print([pred_9, pred_10])
关键注意事项
- 永远不要用无关联的数据集训练模型来预测目标序列,模型必须学习目标序列自身的模式。
- 小数据集下,LSTM这类复杂模型容易过拟合,优先尝试简单的统计规律拟合或轻量回归模型。
- 缩放数据时,必须用目标序列自身的数据拟合scaler,不能复用其他序列的scaler。
内容的提问来源于stack exchange,提问作者Sanjoy
相关产品推荐
相关产品推荐

