本次命题: 数值预测
上一篇文章我们的小题目是使用LSTM预测字符顺序的下一个字符。
命题虽然简单, 可是实际上应用范围也很广。 比如输入法里面, 就一定会用到相关的技术。 只不过不一定是LSTM, 肯定也不止一维特征。这次这个命题相对来说, 比较实际一些:从历史预测监控数据预测即将来临的监控指标的数值。
比如下图就是本站在友盟上面的监控数据。 最右边的虚线部分就是友盟进行的预测的数值:
本文代码特别鸣谢:https://blog.csdn.net/aliceyangxi1987/article/details/73420583
预测代码做了简单修改就迁移过来直接用了。
具体修改与讨论放在最后进行。
获取数据并展示
因为X轴坐标太挤,显示不出来, 所以没有显示在这里。
数据介绍:
- 这个是我司某个监控指标的数值。 具体名字就不说啦:D
- 时间跨度: 一个月
- 粒度: 每个小时一个数值
- 数据下载: 链接
可以看到, 在前面一段时间, 数值的跳动是比较规律的。 当然中间也有一个异常点。 只不过后面忽然出现了几个大的波峰。 如果是异常检测, 在这里就一定要把后面几个波峰给挑出来。
开始炼丹 / 训练模型
完整代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
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 %matplotlib inline # 加载数据 dataframe = read_csv("monitor-metics-data.csv", usecols=[1]) dataset = dataframe.values # 将整型变为float dataset = dataset.astype('float32') # numpy.ndarray 类型 # 创建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) # 数据正则化, 方法: Min Max scaler = MinMaxScaler(feature_range=(0, 1)) dataset = scaler.fit_transform(dataset) # 【注意】因为在我们的周期是小时, 基本上按天进行变动, 可以设置为24. # 实际上, 也可以设置为1,误差比想象中的小很多 look_back = 24 # 切分train / test 数据 train_size = int(len(dataset) * 0.67) test_size = len(dataset) - train_size train, test = dataset[0:train_size,:], dataset[train_size:len(dataset),:] # 开始构建数据集 trainX, trainY = create_dataset(train, look_back) testX, testY = create_dataset(test, look_back) # 注意这里的reshape的操作。 trainX = numpy.reshape(trainX, (trainX.shape[0], trainX.shape[1], 1)) testX = numpy.reshape(testX, (testX.shape[0], testX.shape[1], 1)) # 开始训练模型 # 可以把epochs 训练次数加大, 当前时间不足, 只进行了10次 model = Sequential() model.add(LSTM(4, input_shape=(look_back,1))) model.add(Dense(1)) model.compile(loss='mean_squared_error', optimizer='adam') model.fit(trainX, trainY, epochs=10, batch_size=2, verbose=2) # 为了展示区别, 训练、测试数据都预测。 trainPredict = model.predict(trainX) testPredict = model.predict(testX) # invert predictions trainPredict = scaler.inverse_transform(trainPredict) trainY = scaler.inverse_transform([trainY]) testPredict = scaler.inverse_transform(testPredict) testY = scaler.inverse_transform([testY]) # 计算误差值/RMSE 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)) # 绘图 # plot baseline and predictions def plot_result() : raw = scaler.inverse_transform(dataset) x = read_csv("monitor-metics-data.csv", usecols=[0]).values.tolist() # 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 #创建绘图对象,figsize参数可以指定绘图对象的宽度和高度,单位为英寸,一英寸=80px fig, ax = plt.subplots(figsize=(20,5)) raw_line, = plt.plot(x,raw, "m--", linewidth=1, label="Raw Data") train_line, = plt.plot(x,trainPredictPlot, "b-", linewidth=1, label="Train Predict") test_line, = plt.plot(x,testPredictPlot, "g-", linewidth=1, label="Test Predict") plt.legend(handles=[raw_line, train_line, test_line]) xticks=list(range(0,len(x),40)) xlabels=[x[t] for t in xticks] xticks.append(len(x)) xlabels.append(x[-1]) ax.set_xticks(xticks) ax.set_xticklabels(xlabels, rotation=40) plt.show() plot_result() |
如上图所示:
- 红色虚线是原始数据,
- 蓝色为训练数据的预测值。重合度一般
- 绿色为测试数据的预测值。 虽然波峰突然起来, 预测的值也相应的升高。 只不过跟真实值还是有区别。 这就为我们使用LSTM做异常检测(Anomaly Detection) 打下了基础。
改动的地方
look_back
原文的look_back 是1, 个人觉得在实际生产之中, 应该不会这样使用
根据我们已知的时间窗口周期, 改成了24。
-
numpy.reshape
/input_shape
原文代码:
1234567# 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]))# ... 中间略model.add(LSTM(4, input_shape=(1, look_back)))我的修改:
12345trainX = numpy.reshape(trainX, (trainX.shape[0], trainX.shape[1], 1))testX = numpy.reshape(testX, (testX.shape[0], testX.shape[1], 1))# ... 中间略model.add(LSTM(4, input_shape=(look_back,1)))我的理解:
- 因为我们的数据的特征是一维, 因此
features
的值应该是1
, - 而我们往回看的时间窗口实际值是
look_back
的值。 在create_dateset
函数里面, 是的数据集的宽度就是look_back
, 即trainX.shape[1] == look_back
- 因为我们的数据的特征是一维, 因此
plot_result
函数原来的绘图函数太简陋, 在这里做了好一些优化,比如:
- 图放大
- 有legend
- x坐标的值间隔显示
本文原创, 转摘需要注明出处:
https://www.flyml.net/2018/08/13/lstm-prediction-for-monitoring-metric-data

文章评论
你好,这个应该是单指标的预测以及监控,请问您有接触过多指标的预测以及异常点检测吗?