You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

lstm-time-series.py 5.7 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. # -*- coding: utf-8 -*-
  2. # ---
  3. # jupyter:
  4. # jupytext_format_version: '1.2'
  5. # kernelspec:
  6. # display_name: Python 3
  7. # language: python
  8. # name: python3
  9. # language_info:
  10. # codemirror_mode:
  11. # name: ipython
  12. # version: 3
  13. # file_extension: .py
  14. # mimetype: text/x-python
  15. # name: python
  16. # nbconvert_exporter: python
  17. # pygments_lexer: ipython3
  18. # version: 3.5.2
  19. # ---
  20. # # RNN 用于时间序列的分析
  21. # 前面我们讲到使用 RNN 做简单的图像分类的问题,但是 RNN 并不擅长此类问题,下面我们讲一讲如何将 RNN 用到时间序列的问题上,因为对于时序数据,后面的数据会用到前面的数据,LSTM 的记忆特性非常适合这种场景。
  22. # 首先我们可以读入数据,这个数据是 10 年飞机月流量,可视化得到下面的效果。
  23. import numpy as np
  24. import pandas as pd
  25. import matplotlib.pyplot as plt
  26. # %matplotlib inline
  27. data_csv = pd.read_csv('./data.csv', usecols=[1])
  28. plt.plot(data_csv)
  29. # 首先我们进行预处理,将数据中 `na` 的数据去掉,然后将数据标准化到 0 ~ 1 之间。
  30. # 数据预处理
  31. data_csv = data_csv.dropna()
  32. dataset = data_csv.values
  33. dataset = dataset.astype('float32')
  34. max_value = np.max(dataset)
  35. min_value = np.min(dataset)
  36. scalar = max_value - min_value
  37. dataset = list(map(lambda x: x / scalar, dataset))
  38. # 接着我们进行数据集的创建,我们想通过前面几个月的流量来预测当月的流量,比如我们希望通过前两个月的流量来预测当月的流量,我们可以将前两个月的流量当做输入,当月的流量当做输出。同时我们需要将我们的数据集分为训练集和测试集,通过测试集的效果来测试模型的性能,这里我们简单的将前面几年的数据作为训练集,后面两年的数据作为测试集。
  39. def create_dataset(dataset, look_back=2):
  40. dataX, dataY = [], []
  41. for i in range(len(dataset) - look_back):
  42. a = dataset[i:(i + look_back)]
  43. dataX.append(a)
  44. dataY.append(dataset[i + look_back])
  45. return np.array(dataX), np.array(dataY)
  46. # 创建好输入输出
  47. data_X, data_Y = create_dataset(dataset)
  48. # 划分训练集和测试集,70% 作为训练集
  49. train_size = int(len(data_X) * 0.7)
  50. test_size = len(data_X) - train_size
  51. train_X = data_X[:train_size]
  52. train_Y = data_Y[:train_size]
  53. test_X = data_X[train_size:]
  54. test_Y = data_Y[train_size:]
  55. train_Y.shape
  56. # 最后,我们需要将数据改变一下形状,因为 RNN 读入的数据维度是 (seq, batch, feature),所以要重新改变一下数据的维度,这里只有一个序列,所以 batch 是 1,而输入的 feature 就是我们希望依据的几个月份,这里我们定的是两个月份,所以 feature 就是 2.
  57. # +
  58. import torch
  59. train_X = train_X.reshape(-1, 1, 2)
  60. train_Y = train_Y.reshape(-1, 1, 1)
  61. test_X = test_X.reshape(-1, 1, 2)
  62. train_x = torch.from_numpy(train_X)
  63. train_y = torch.from_numpy(train_Y)
  64. test_x = torch.from_numpy(test_X)
  65. # -
  66. from torch import nn
  67. from torch.autograd import Variable
  68. # 这里定义好模型,模型的第一部分是一个两层的 RNN,每一步模型接受两个月的输入作为特征,得到一个输出特征。接着通过一个线性层将 RNN 的输出回归到流量的具体数值,这里我们需要用 `view` 来重新排列,因为 `nn.Linear` 不接受三维的输入,所以我们先将前两维合并在一起,然后经过线性层之后再将其分开,最后输出结果。
  69. # 定义模型
  70. class lstm_reg(nn.Module):
  71. def __init__(self, input_size, hidden_size, output_size=1, num_layers=2):
  72. super(lstm_reg, self).__init__()
  73. self.rnn = nn.LSTM(input_size, hidden_size, num_layers) # rnn
  74. self.reg = nn.Linear(hidden_size, output_size) # 回归
  75. def forward(self, x):
  76. x, _ = self.rnn(x) # (seq, batch, hidden)
  77. s, b, h = x.shape
  78. x = x.view(s*b, h) # 转换成线性层的输入格式
  79. x = self.reg(x)
  80. x = x.view(s, b, -1)
  81. return x
  82. # +
  83. net = lstm_reg(2, 4)
  84. criterion = nn.MSELoss()
  85. optimizer = torch.optim.Adam(net.parameters(), lr=1e-2)
  86. # -
  87. # 定义好网络结构,输入的维度是 2,因为我们使用两个月的流量作为输入,隐藏层的维度可以任意指定,这里我们选的 4
  88. # 开始训练
  89. for e in range(1000):
  90. var_x = Variable(train_x)
  91. var_y = Variable(train_y)
  92. # 前向传播
  93. out = net(var_x)
  94. loss = criterion(out, var_y)
  95. # 反向传播
  96. optimizer.zero_grad()
  97. loss.backward()
  98. optimizer.step()
  99. if (e + 1) % 100 == 0: # 每 100 次输出结果
  100. print('Epoch: {}, Loss: {:.5f}'.format(e + 1, loss.data[0]))
  101. # 训练完成之后,我们可以用训练好的模型去预测后面的结果
  102. net = net.eval() # 转换成测试模式
  103. data_X = data_X.reshape(-1, 1, 2)
  104. data_X = torch.from_numpy(data_X)
  105. var_data = Variable(data_X)
  106. pred_test = net(var_data) # 测试集的预测结果
  107. # 改变输出的格式
  108. pred_test = pred_test.view(-1).data.numpy()
  109. # 画出实际结果和预测的结果
  110. plt.plot(pred_test, 'r', label='prediction')
  111. plt.plot(dataset, 'b', label='real')
  112. plt.legend(loc='best')
  113. # 这里蓝色的是真实的数据集,红色的是预测的结果,我们能够看到,使用 lstm 能够得到比较相近的结果,预测的趋势也与真实的数据集是相同的,因为其能够记忆之前的信息,而单纯的使用线性回归并不能得到较好的结果,从这个例子也说明了 RNN 对于序列有着非常好的性能。
  114. # **小练习:试试改变隐藏状态输出的特征数,看看有没有什么改变,同时试试使用简单的线性回归模型,看看会得到什么样的结果**

机器学习越来越多应用到飞行器、机器人等领域,其目的是利用计算机实现类似人类的智能,从而实现装备的智能化与无人化。本课程旨在引导学生掌握机器学习的基本知识、典型方法与技术,通过具体的应用案例激发学生对该学科的兴趣,鼓励学生能够从人工智能的角度来分析、解决飞行器、机器人所面临的问题和挑战。本课程主要内容包括Python编程基础,机器学习模型,无监督学习、监督学习、深度学习基础知识与实现,并学习如何利用机器学习解决实际问题,从而全面提升自我的《综合能力》。