热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

keras实现简单lstm_深度学习(LSTM)在交通建模中的应用

上方点击蓝字关注?在简单了解了LSTM原理之后,本期我将以航班延误预测为例为大家介绍一下如何利用Python编程来构建LSTM模型。这里我们要用到一个高级的深度学习链

上方点击蓝字关注?

1292b18b8b6addd3873ccfa6c0b5fd4e.png

在简单了解了LSTM原理之后,本期我将以航班延误预测为例为大家介绍一下如何利用Python编程来构建LSTM模型。

这里我们要用到一个高级的深度学习链接库——Keras,它以TensorFlow或者Theano作为后端引擎,只处理模型的建立、训练和预测等功能,至于底层操作细节,Keras会帮你转化成Theano或TensorFlow相对指令。

2fd768eb4a58b14d7246e79c5ed4758f.gif

Windows下用Anaconda安装TensorflowKeras

关于Tensorflow和Keras的安装,大家可以参考以下的博客。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议

本文链接:https://blog.csdn.net/lzy_shmily/article/details/80803433

需要注意的两点是:

  • 一定要先安装Tensorflow再安装Keras

  • 一定要在刚刚创建的tensorflow的环境下安装cpu版本的TensorFlow

利用Keras建立深度学习模型

利用Keras建立深度学习模型,就像在蛋糕架上面一层一层地插蛋糕。在这里,我们选择的“蛋糕架”是Sequential模型,它是多个神经网络层的线性堆叠。那么对于Sequential更多的信息,请参考Keras的中文官方文档(https://keras.io/zh/models/sequential/)。

1b948a7aa57d23f529d0a9c7d843333e.png

构建LSTM模型来预测航班延误

接下来我们以航班延误预测为例来说明如何构建LSTM模型。

在航空领域,一架飞机每天要完成多个航班的飞行任务,这就形成了一个航班序列,如果飞机在一个航班任务中发生了延误,那该延误可能会沿着航班序列进行传播。

d99fb84a41eae3f870e5d6965de7e9c3.png

注:图片来源于网络

当然,飞机也可能通过中途加速或者沿着直线飞行从而将延误抵消。那么我们在这里利用Python构建LSTM模型来预测一架飞机在下一个时刻的到港延误。

数据来源:美国交通部运输统计局提供的公开的航班数据

代码来源:https://www.evolutionarylearn.com/paper/python-keras-tensorflow-mts/

数据预处理

  • 剔除掉航班取消和改航记录

  • 将数据整理成时间序列数据,也就是将计划到港时间(年-月-日-时-分)作为数据表的索引

导入模块

import time
import math
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from datetime import datetime
from keras.models import Sequential
from keras.layers import LSTM, Dense, Dropout
from sklearn.preprocessing import MinMaxScaler
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import OneHotEncoder
from sklearn.metrics import r2_score
from keras import backend as K  # Keras解决OOM超内存问题

建立LSTM类

LSTM类的基本框架是初始化,数据集分割,网络创建与训练,网络评估和结果可视化。

【初始化】:初始化主要是将基本的参数和数据导入进将要创建的实例。代码如下:

    def __init__(self, dataset, hyper_params):
        self.dataset = dataset  # Initialize data sets/数据集初始化
        self.num_neur = hyper_params[0]  # Initialize number of layer and number of neurons in each layer/初始化隐层数和各层神经元个数
        self.look_back = hyper_params[1]  # Initialize length of windows/初始化窗口长度
        self.epochs = hyper_params[2]  # Initialize training times/初始化训练次数
        self.batch_size = hyper_params[3]  # Initialize batch size/初始化批数
        self.selected_feature = hyper_params[4]  # Initialize the selected features/初始化选择特征
        self.train_ratio = hyper_params[5]  # Initialize the splitted ratio of training/初始化训练集分割比例
        self.feature_num = hyper_params[6]  # Initialize the number of features/初始化特征数量
        self.dropoutrate = hyper_params[7]
        self.x_train = []  # Initialize training features of training data set/初始化训练集x部分-训练特征
        self.y_train = []  # Initialize supervisory signals of training data set/初始化训练集y部分-监督信号
        self.x_test = []  # Initialize test features of training data set/初始化测试集x部分-测试特征
        self.y_test = []  # Initialize supervisory signals of training data set/初始化测试集y部分-监督信号

【数据集分割】:数据集分割包括两部分,一部分是特征选择,一部分是分割测试集和训练集。

        def create_dataset(dataset, look_back):
            dataX, dataY = [], []
            for i in range(len(dataset) - look_back):
                a = dataset[i:(i + look_back), 0:dataset.shape[1]]
                dataX.append(a)
                dataY.append(dataset[i + look_back, 0])
            return np.array(dataX), np.array(dataY)

        selected_list = feature_selection(self.selected_feature)  # Index list of selected feature/选择特征列表索引
        train_size = int(len(self.dataset) * self.train_ratio)  # Size of training data set/训练集大小
        train_data = self.dataset[0:train_size, selected_list]  # Training data set/训练集
        test_data = self.dataset[train_size - self.look_back - 1:len(self.dataset), selected_list]  # Test data set/测试集
        self.feature_num = len(selected_list)  # Update the number of selected feature/更新特征数量

        # Data set detail/具体分割后数据集
        x_train, self.y_train = create_dataset(train_data, self.look_back)
        x_test, self.y_test = create_dataset(test_data, self.look_back)

        # Reshape input to be [samples, feature_num, features]/整理特征数据的格式
        self.x_train = np.reshape(x_train, (x_train.shape[0], self.feature_num, x_train.shape[1]))
        self.x_test = np.reshape(x_test, (x_test.shape[0], self.feature_num, x_test.shape[1]))

这段代码中的测试集划分用的是test_data = self.dataset[train_size - self.look_back - 1:len(self.dataset), selected_list],为什么不是test_data = self.dataset[train_size :len(self.dataset), selected_list]呢?这个是为了保证测试集中有更多样本,后面一种会由于存在窗口损失掉一部分数据,减一应该是为了作图时连接训练部分和测试部分。

【网络创建】:开始在蛋糕架上插蛋糕~

    def lstm(self):
        start_cr_a_fit_net = time.time()  # Record time/记录网络创建与训练时间
        self.split_dataset()  # Split the data set/数据分割

        # Create and fit the LSTM network/创建并拟合LSTM网络
        LSTM_model = Sequential()
        for i in range(len(self.num_neur)):  # 构建多层网络
            if len(self.num_neur) == 1:
                LSTM_model.add(LSTM(self.num_neur[i], input_shape=(None, self.look_back),dropout=self.dropoutrate))
            else:
                if i 1:
                    LSTM_model.add(LSTM(self.num_neur[i], input_shape=(None, self.look_back), return_sequences=True))
                    LSTM_model.add(Dropout(self.dropoutrate))
                else:
                    LSTM_model.add(LSTM(self.num_neur[i], input_shape=(None, self.look_back)))

        LSTM_model.add(Dense(1))
        LSTM_model.summary()  # Summary the structure of neural network/网络结构总结
        LSTM_model.compile(loss='mean_squared_error', optimizer='adam')  # Compile the neural network/编译网络
        LSTM_model.fit(self.x_train, self.y_train, epochs=self.epochs, batch_size=self.batch_size
                       , verbose=2)  # Fit the LSTM network/拟合LSTM网络
        end_cr_a_fit_net = time.time() - start_cr_a_fit_net
        print('Running time of creating and fitting the LSTM network: %.2f Seconds' % (end_cr_a_fit_net))

        # LSTM prediction/LSTM进行预测
        trainPredict = LSTM_model.predict(self.x_train)  # Predict by training data set/训练集预测
        testPredict = LSTM_model.predict(self.x_test)  # Predict by test data set/测试集预测
        return trainPredict, testPredict, self.y_train, self.y_test

【网络评估】这里我们的评估指标选用的是f0a7743501756defe7b0d7cb16532cda.png

    def mape(self, scaler, trainPredict, testPredict):
        # Invert predictions start / 将预测值转换为正常数值
        # Create empty table like the dataset/创建一个空的数组, 结构同dataset
        trainPredict_dataset_like = np.zeros(shape=(len(trainPredict), self.dataset.shape[1]))
        # Put the predicted values in the right field/将预测值填充进新建数组
        trainPredict_dataset_like[:, 0] = trainPredict[:, 0]
        # Inverse transform and then select the right field/数据转换
        trainPredict = scaler.inverse_transform(trainPredict_dataset_like)[:, 0]

        y_train_dataset_like = np.zeros(shape=(len(self.y_train), self.dataset.shape[1]))
        y_train_dataset_like[:, 0] = self.y_train
        self.y_train = scaler.inverse_transform(y_train_dataset_like)[:, 0]

        testPredict_dataset_like = np.zeros(shape=(len(testPredict), self.dataset.shape[1]))
        testPredict_dataset_like[:, 0] = testPredict[:, 0]
        testPredict = scaler.inverse_transform(testPredict_dataset_like)[:, 0]

        y_test_dataset_like = np.zeros(shape=(len(self.y_test), self.dataset.shape[1]))
        y_test_dataset_like[:, 0] = self.y_test
        self.y_test = scaler.inverse_transform(y_test_dataset_like)[:, 0]
        # Invert predictions end/数据转换结束

        # 计算R2值
        train_R2 = r2_score(self.y_train, trainPredict)
        test_R2 = r2_score(self.y_test, testPredict)
        #trainMAPE = np.mean(np.abs(self.y_train - trainPredict) / self.y_train)
        #testMAPE = np.mean(np.abs(self.y_test - testPredict) / self.y_test)

        print("Train R2: " + str(round(train_R2, 2)))
        print("Test R2: " + str(round(test_R2, 2)))
        return trainPredict, testPredict, train_R2, test_R2

【可视化】

    def plot(self, scaler, trainPredict, testPredict):
        # Shift training predictions for plotting/转换数据结构用于作图-训练预测结果
        sub_traindataset = [[data] for data in self.dataset[:, 0]]
        trainPredictPlot = np.empty_like(sub_traindataset)
        trainPredictPlot[:, 0] = np.nan
        trainPredictPlot[self.look_back:len(trainPredict) + self.look_back, 0] = trainPredict

        # Shift test predictions for plotting/转换数据结构用于作图-测试预测结果
        sub_testdataset = [[data] for data in self.dataset[:, 0]]
        testPredictPlot = np.empty_like(sub_testdataset)
        testPredictPlot[:] = np.nan
        testPredictPlot[len(trainPredict) + self.look_back - 1:len(self.dataset), 0] = testPredict

        # plot baseline and predictions/作图
        datasety_like = np.zeros(shape=(self.dataset.shape[0], self.dataset.shape[1]))
        datasety_like[:, 0] = self.dataset[:, 0]
        y = scaler.inverse_transform(datasety_like)[:, 0]

        #dates = pd.date_range('2010-12', periods=len(y), freq='M')
        xs = [d for d in dataframe.index]
        # 配置横坐标
        #plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m'))
        #plt.gca().xaxis.set_major_locator(mdates.MonthLocator(bymonth=[1, 7]))

        A, = plt.plot(xs, y[0:len(y)], linewidth='2', color='cornflowerblue')  # 真实值
        B, = plt.plot(xs, trainPredictPlot, linewidth='1.5', color='lightgreen')  # LSTM训练集结果
        C, = plt.plot(xs, testPredictPlot, linewidth='4', color='lightcoral')  # LSTM测试集结果

        # plt.plot(NpredYPlot,linewidth = '3',color='k')
        #plt.axvline(xs[76], linewidth='2', color='black')  # 画直线区分训练部分与测试部分
        plt.legend((A, B, C), ('real_value', 'LSTM_train', 'LSTM_test'), loc='best')
        plt.gcf().autofmt_xdate()  # 自动旋转日期标记
        plt.xticks([])#由于时间太多,不显示横坐标轴
        #plt.xlabel('Date', family='Times New Roman', fontsize=16)  # X轴
        plt.ylabel('Delay', family='Times New Roman', fontsize=16)  # Y轴

        plt.title('LSTM', family='Times New Roman', fontsize=16)  # 添加标题

        #plt.savefig(r'C:\Users\10321\Desktop\result.png', dpi=900)  # 保存图片

        plt.show()
        del trainPredictPlot, testPredictPlot

导入参数

num_neur=[15, 10]表示这个LSTM网络有两个隐藏层,第一层的神经元个数为15,第二层的神经元个数为10;select_feature = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]表示我选择了数据集中所有的特征,不选择的设为0就好。所选特征包括:到港延误、季度、周几、出发机场、到达机场、计划和实际运行时间、距离、在空时间、计划过站时间、到达机场每小时的计划离港流量和计划到港流量。

if __name__ == "__main__":
    # Load the dataset/导入数据集
    file = r'E:/ZhangBo/data/aircraft_sequential_sarr.csv'
    dataframe = pd.read_csv(file, index_col=0)
    dataframe = dataframe.dropna(axis=0,how='any')
    encoder = LabelEncoder()
    dataset = dataframe.values
    dataset[:, 3] = encoder.fit_transform(dataset[:, 3])
    dataset[:, 4] = encoder.fit_transform(dataset[:, 4])
    dataset = dataset.astype('float32')

    # Normalize the dataset/标准化数据集
    scaler = MinMaxScaler(feature_range=(0, 1))
    dataset = scaler.fit_transform(dataset)

    # Set hyper-parameters/设定超参数
    num_neur = [15,10]  # Number of layer and number of neurons in each layer/隐藏层数和各层神经元个数
    look_back = 15 # Length of windows/窗口长度
    epochs = 30  # Training times/训练次数
    batch_size = 10 # Batch size/批数大小
    select_feature = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]# Selected features list/被选择特征列表
    train_ratio = 0.832  # Splitted ratio of training data set/训练集分割比例
    feature_num = dataset.shape[1]  # Feature number+y/特征数量+1,也将预测项作为特征
    dropoutrate = 0.02
    # Hyper-parameter list/超参数列表
    hyper_params = [num_neur, look_back, epochs, batch_size, select_feature, train_ratio, feature_num, dropoutrate]

    # Start an LSTM model/开始一个LSTM网络
    model = lstm(dataset, hyper_params)  # Create instance of LSTM/实例化模型
    trainPredict, testPredict, y_train, y_test = model.lstm()  # Create and fit the LSTM network/创建并拟合LSTM网络
    trainPredict, testPredict,train_R2, test_R2 = model.mape(scaler, trainPredict , testPredict)  # Evaluate network performance/评估网络效果
    model.plot(scaler, trainPredict, testPredict)  # Visualization results/可视化结果
    K.clear_session()  # 关掉内存中神经网络

程序运行结果

【网络结构】

351ecc5839bcab9451284b61b6f87b36.png

【拟合网络、训练和测试结果】

07fe2e8cb82fe50fcbffe56476e9b7fd.pnge3dee14d147b63c71ebb5990f4ca20ed.png

我们创建和拟合LSTM网络所需的时间为225.81秒,训练集的值为0.55,测试集的值为0.44,可以看出,模型的预测结果并不是很好,因为这里我们并没有对超参数进行选择,而且航班延误的一个很重要的影响因素——天气的相关数据我们并没有加进去。

本期结语

到这里,LSTM网络的理论及其在交通建模中的应用的相关介绍就全部结束了。

如果你有问题和不同的看法,可以在后台留言,我们互相交流,互相学习,共同进步~

编辑:庄桢

f18392451e457d2bb6fe6cb3828a3f8f.gif

“交通科研Lab”:分享学习点滴,期待科研交流!

b7bae4988b2d00bdf93db684476bbfad.png

如果觉得还不错

点这里!???



推荐阅读
  • 本文介绍如何使用OpenCV和线性支持向量机(SVM)模型来开发一个简单的人脸识别系统,特别关注在只有一个用户数据集时的处理方法。 ... [详细]
  • 使用Tkinter构建51Ape无损音乐爬虫UI
    本文介绍了如何使用Python的内置模块Tkinter来构建一个简单的用户界面,用于爬取51Ape网站上的无损音乐百度云链接。虽然Tkinter入门相对简单,但在实际开发过程中由于文档不足可能会带来一些不便。 ... [详细]
  • 本文详细介绍了如何使用Python的多进程技术来高效地分块读取超大文件,并将其输出为多个文件。通过这种方式,可以显著提高读取速度和处理效率。 ... [详细]
  • Spring Data JdbcTemplate 入门指南
    本文将介绍如何使用 Spring JdbcTemplate 进行数据库操作,包括查询和插入数据。我们将通过一个学生表的示例来演示具体步骤。 ... [详细]
  • 在Windows系统中安装TensorFlow GPU版的详细指南与常见问题解决
    在Windows系统中安装TensorFlow GPU版是许多深度学习初学者面临的挑战。本文详细介绍了安装过程中的每一个步骤,并针对常见的问题提供了有效的解决方案。通过本文的指导,读者可以顺利地完成安装并避免常见的陷阱。 ... [详细]
  • 通过使用 `pandas` 库中的 `scatter_matrix` 函数,可以有效地绘制出多个特征之间的两两关系。该函数不仅能够生成散点图矩阵,还能通过参数如 `frame`、`alpha`、`c`、`figsize` 和 `ax` 等进行自定义设置,以满足不同的可视化需求。此外,`diagonal` 参数允许用户选择对角线上的图表类型,例如直方图或密度图,从而提供更多的数据洞察。 ... [详细]
  • 岭回归及其应用
    本文介绍了岭回归的基本原理,并通过Python中的sklearn库实现了岭回归模型。岭回归通过在代价函数中加入L2正则项,有效解决了多重共线性问题。 ... [详细]
  • Java 中的等时日期(int,int)方法,示例 ... [详细]
  • 普通树(每个节点可以有任意数量的子节点)级序遍历 ... [详细]
  • 目录预备知识导包构建数据集神经网络结构训练测试精度可视化计算模型精度损失可视化输出网络结构信息训练神经网络定义参数载入数据载入神经网络结构、损失及优化训练及测试损失、精度可视化qu ... [详细]
  • C#实现文件的压缩与解压
    2019独角兽企业重金招聘Python工程师标准一、准备工作1、下载ICSharpCode.SharpZipLib.dll文件2、项目中引用这个dll二、文件压缩与解压共用类 ... [详细]
  • 本文详细介绍了如何使用 Python 进行主成分分析(PCA),包括数据导入、预处理、模型训练和结果可视化等步骤。通过具体的代码示例,帮助读者理解和应用 PCA 技术。 ... [详细]
  • 使用多项式拟合分析淘宝双11销售趋势
    根据天猫官方数据,2019年双11成交额达到2684亿元,再次刷新历史记录。本文通过多项式拟合方法,分析并预测未来几年的销售趋势。 ... [详细]
  • 第二十五天接口、多态
    1.java是面向对象的语言。设计模式:接口接口类是从java里衍生出来的,不是python原生支持的主要用于继承里多继承抽象类是python原生支持的主要用于继承里的单继承但是接 ... [详细]
  • 为了确保iOS应用能够安全地访问网站数据,本文介绍了如何在Nginx服务器上轻松配置CertBot以实现SSL证书的自动化管理。通过这一过程,可以确保应用始终使用HTTPS协议,从而提升数据传输的安全性和可靠性。文章详细阐述了配置步骤和常见问题的解决方法,帮助读者快速上手并成功部署SSL证书。 ... [详细]
author-avatar
lluuaalulua619
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有