keras实现简单lstm_深度学习(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

如果觉得还不错

点这里???

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/551947.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

井下关于风速的规定_矿井有害气体最高允许浓度、温度、风速的规定

≥0.5%CH4≥0.5%CH4<0.5%CH4被串掘进巷道内全部非本质安全型电气设备回风流中机电设备硐室的进风侧≥0.5%CH4≥0.5%CH4<0.5%CH4机电设备硐室内全部非本质安全型电气设备关于温度的规定《煤矿安全规程》规定,生产矿井采煤工作面的空气温度不得…

linux 大数字 进制转换,Linux下用bc快速进行数字进制转换

介绍如何在Linux下用bc命令进行快速的数字进制转换。我想Windows里,数字进制转换最方便的就是自带的calc计算器,但是它原没有我们可爱的Linux方便。Linux下,我们在term里敲 几下键盘就可以做数字进制转换了。当然,你如果自己转换更…

python替换nan_python – 用NaN替换字典的空值

我有一个缺少值的字典(密钥在那里,但相关的值是空的).例如,我想要下面的字典:dct {ID:, gender:male, age:20, weight:, height:5.7}要改为这种形式:dct {ID:NaN, gender:male, age:20, weight:NaN, height:5.7}我怎样才能以最省时的方式写出来呢&…

commons-pool2-2.3 jar包_[漏洞复现]FastJson 1.2.61远程代码执行漏洞(From第三方jar包)

前言最近FastJson更新了黑名单,升级到了1.2.61版本,我尝试bypass其黑名单,在AutType打开的情况下成功绕过了黑名单防护.(目前暂未修复,官方即将更新)复现环境准备1.JDK 8U202.所需jar清单如下fastjson-1.2.61.jarcommons-configuration2-2.0.jarcommons-lang3-3.3.2.jarcommons…

linux安装dev命令,Linux安装与基础命令

首先准备一个liunx镜像和一台安装好虚拟机的电脑。配置好虚拟机,选在稍后安装。选择镜像文件,开启虚拟机进行安装。配置yum源。首先插入光盘。由于是虚拟机,用的光盘镜像,在/mnt/下面创建一个文件夹yum 。 复制所有光盘里的内…

python爬取京东评论_Python如何爬取京东的评价信息

Python如何爬取京东的评价信息 模块:requests,BeautifulSoup import re import time import csv import requests from bs4 import BeautifulSoup def write_a_row_in_csv(data, csv_doc): "save good information into a row in csv document"…

王思聪吃热狗的c语言小程序,王思聪吃热狗火了,开发各种恶搞小程序!王校长:我不要面子的啊...

原标题:王思聪吃热狗火了,开发各种恶搞小程序!王校长:我不要面子的啊近日王校长上了不少次热搜,其中有一条就是王校长吃热狗火了,接下来就出现了各种各样的表情包,手机壳,素描等等。…

python有什么内容_python能做什么

python能做什么?书声琅琅Python培训老师介绍,最近许多的朋友咨询,听说python很火,甚至可以超越JAVA,因此很想学这个python,但是不知道python能做什么,能完成一些什么项目呢?针对这个问题,今天…

酷狗音乐linux版_让父母也爱上音乐 酷狗音乐大字版成中老年人新宠

当智能手机成为人们日常生活中必不可少的一部分,手机早已从单纯的通话设备变成了功能强大的“百宝箱”,听音乐、看视频、拍照上网早已不是什么新鲜事。然而在我们玩手机玩的不亦乐乎时,你有没有关注过爸妈对使用智能手机的接受度?…

二分法求近似根c语言程序,求一C++风格程序,用二分法求f(x)=0的根

满意答案vwamuoor8000推荐于 2018.04.24#include #include typedef double (*F)(double);/* brief 二分法求解函数* param[in] f 求解的函数* param[in] a, b 求解的区间端点* param[in] 吵盯e 精度* pre f(a)*f(b)<0且f在该闭区间上连续* return 方程液枝的解 */double sol…

react的导出是怎么实现的_从零开始开发一个 React

这个是从零开始开发一个 React 系列的第七篇。想要访问之前的内容可以点击下方的链接进行访问&#xff1a;最简单的实现&#xff0c;包括 vdom 结构&#xff0c;createElement&#xff0c;ReactDOM.render增加 Class 的支持增加 JSX 的支持增加 state 支持增加声明周期增加 dom…

python io操作有什么_Python笔记:文件IO操作

读取文件 使用open()打开文件&#xff0c;文件不存在会抛出IOError错误。 try: f open(/path/to/file, r) print(f.read()) finally: if f: f.close() 文件读取完成一定要close()&#xff0c;为了保证在报错的时候也能close()&#xff0c;这里用了finally语句&#xff0c;更简…

c语言编程被当作病毒,为什么这个微不足道的C程序被检测为病毒?

我有点生锈在C,但我遇到了这个奇怪的问题&#xff1a;我写了这个程序&#xff1a;#include main(){int n;n1;while (n>0){puts("Write a number: ");scanf(" %d",&n);printf("This is the number you wrote: %d\n", n);}}显然绝对没有语法…

太极发送卡片软件_QQ卡片式消息一键发送app

QQ卡片式消息一键发送app这是一款能够帮助你有创意的发送广告的app。属于qq的辅助工具&#xff0c;能够让你发送属于自己的卡片信息。如果你想要给自己打广告或者发送某张图片&#xff0c;或者想要显示应用&#xff0c;就可以使用这款软件&#xff0c;它能够帮你迅速地生成卡片…

c语言中字符串 x,使用c语言解析字符串176x144中的数字

在做jpeg codec的时候&#xff0c;经常需要输入图片的大小&#xff0c;即长和宽。对于一个jpeg图片&#xff0c;它的大小几乎是任意的&#xff0c;所以只能用数字来表示&#xff0c;而不能选择cif&#xff0c;qcif等这类固定的图片格式。在用数字表示图片大小时&#xff0c;大家…

python列表生成式内必须定义匿名函数_Python基础-----基础概念总结

Python基础-----基础概念总结 Python程序的构成 构成图行连接符&#xff1a;\对象基本构成和内存示意图对象及其引用&#xff08;变量&#xff09;标识符 基本用法命名规则变量和简单的赋值语句 变量声明必须初始化删除变量和垃圾回收机制链式复制系列解包赋值常量&#xff08;…

英语四级c语言,2017年大学英语四级精选试题练习

2017年大学英语四级精选试题练习勤奋和智慧是双胞胎&#xff0c;懒惰和愚蠢是亲兄弟。以下是小编为大家搜索整理的2017年大学英语四级精选试题练习&#xff0c;希望能给大家带来帮助!更多精彩内容请及时关注我们应届毕业生考试网!1、Courses with the numbers 800 or above are…

如何获取图像的驱动_Adobe Camera Raw 12 Mac(Raw格式图像ps插件) v12.2.1.417

Adobe Camera Raw 12 Mac版可以让摄影师在熟悉的Photoshop界面内打开并编辑这些RAW文件&#xff0c;极大的方便了摄影师的工作。Adobe Camera Raw 12 for Mac安装教程下载完成后&#xff0c;双击CameraRaw_12_2_1.pkg文件打开&#xff0c;根据安装器提示进行安装即可。安装完成…

centos usb转网口_CentOS5.6系统中安装并使用USB无线网卡(配置成功) 转

最近一直在配置linux服务器&#xff0c;因为家里装修的时候没有在墙面预留网络接口&#xff0c;所以我的台式机也使用无线网卡连接网络。在CentOS6.2下安装无线网卡的方法和CentOS5.6的方法是一样的&#xff0c;只是CentOS6.2下安装后&#xff0c;右上角会自动出现NetworkManag…

c语言中执行一次的函数once,iOS只执行一次的方法

IOS开发(64)之GCD任务最多只执行一次1 前言使用 dispatch_once 函数 在 APP 的生命周期内来保证你想确保每段代码只执行一次,即使它在代码的不同地方多次调用(比如单例的初始化)。2 代码实例ZYAppDelegate.m[plain]/一个用于调度一次函数的标识static dispatch_once_t onceToke…