如何用 Python 和循环神经网络预测严重交通拥堵?

2019-01-09 13:22

如何用 Python 和循环神经网络预测严重交通拥堵?



  本文为你介绍,如何从 Waze 交通事件开放数据中,利用序列模型找到规律,进行分类预测。以便相关部门可以未雨绸缪,提前有效干预可能发生的严重拥堵。

如何用 Python 和循环神经网络预测严重交通拥堵?

  之前在《文科生如何理解循环神经网络(RNN)?》一文中,我为你讲解过循环神经网络的含义。《如何用 Python 和循环神经网络做中文文本分类?》一文,我又为你介绍了如何用循环神经网络对文本做分类。

  我不希望给你一种错误的简单关联,即“循环神经网络只能用来处理文本数据”。

如何用 Python 和循环神经网络预测严重交通拥堵?

  但是我一直不看好这种应用。因为金融产品的定价,应该是面向未来的。基于历史价格信息寻找波动规律,并对未来价格进行预测,实际上如同看着后视镜开车一般危险。

  原因在于,金融市场的参与者,并非理性的机器,而是由人组成的群体。从行为金融学的角度来看,进化给人类思考与行为带来了一些“快捷方式”,你可以利用它们从中渔利。

  如果没有大风浪,这种对市场参与者行为规律的洞察,确实可以帮你赚钱。你可以从价格的历史波动中,挖掘出这些规律的影响。但是这对没有模型可用的人来说,不公平。教你建模,就如同教你考试作弊。

  如果遇到黑天鹅事件,其影响大概率会超过市场参与者行为偏误带来的历史价格波动规律。那么你,可能会因为应用模型,而遭遇亏损。你大约不会认为这是自己的错误,而直接把我当做骗子,朝我扔鸡蛋。

  理性权衡后,我决定不用金融产品价格趋势分析,作为循环神经网络的应用样例。

  其他开放的序列数据,当然也有很多。例如共享单车租用数据、气温变化数据等。

  不过这些应用,一来别人都写过了,不新鲜。二来,气温变化,你看天气预报就好了。共享单车租用数量……你真的关心这里的规律吗?

  正在我犹豫的时候,一次偶然的机会,我接触到了一个新的序列数据样例——交通事件数据。我觉得,把它作为应用案例分享给你,可能更合适一些。

  比赛在 Frisco 的 UNT Inspire Park 举办。从早上8点开始,一直到晚上9点多才结束。中间可以自由吃免费提供的点心和水果,也可以到院子里晒晒太阳放放风。大家还可以自由交流和组队。

如何用 Python 和循环神经网络预测严重交通拥堵?

  主办方为参赛者提供了若干种开放数据,也提了一些问题供大家参考解答。当然,实际参赛的时候,你也可以自己拟定新的题目。

  我在中国开车,平时用的都是高德导航,对于 Waze 这款 App 不大熟悉。

如何用 Python 和循环神经网络预测严重交通拥堵?

  简而言之,这个 Waze 应用除了提供一般的导航功能之外,还有一个类似于众包的功能——让司机们自由提交路况信息。

如何用 Python 和循环神经网络预测严重交通拥堵?

  这样一来,Waze 就利用群体智慧形成了一个眼观六路耳听八方的巨大网络,随时依据用户提供的情况,汇总成实时交通参考。并且汇报给用户,以便于大家调整自己的行车路线。

  我觉得最有用的特点是,在堵车的时候,你可以了解到前面究竟发生了什么。其他导航也有实时交通状况提示,但是你对前面的情况一无所知。道路半幅施工?交通事故?

  Waze 从几年前开始,就和政府部门合作,进行数据开放共享。这样一来,政府可以通过 Waze 的数据了解交通实时状况,对于问题进行快速的响应处理;与此同时, Waze 用户也因为可以获取整合其他相关类型的政府开放数据(例如道路规划等),更加有效合理安排出行。

  这次比赛,主办方提供的数据,是 DFW (达拉斯-沃斯堡都会区)区域,11月1日到29日的 Waze 交通事件(Incidents)开放数据,这是政府开放数据的一部分。这些数据基本都是来自于 Waze 用户的提交。

  原始的数据,接近 300 MB。每一条事件信息,都包含了提交的经纬度,以及时间。因此在探索性数据分析阶段,我做了几个可视化图形。

如何用 Python 和循环神经网络预测严重交通拥堵?

  因为 QGIS 初学,用得不熟,我还是用 Python 进行了分类绘图。

如何用 Python 和循环神经网络预测严重交通拥堵?

  这只是前 3000 条数据中部分类型的可视化。其中红色代表交通拥堵,黄色代表事故发生,蓝色代表有车停在了路肩上。

如何用 Python 和循环神经网络预测严重交通拥堵?

  我看到,其中单是交通阻塞,也是分为若干级别的。其中最严重的,分别是“大型交通拥堵”(large traffic jam)和“超大型交通拥堵”(huge traffic jam)。

  于是,我把所有这两种严重交通拥堵事件,合并成一个集合;其他剩余事件,作为另一个集合。

  对于每一个严重拥堵事件,我追溯30分钟,把之前同一条道路上,发生的事件,按照顺序存成一个列表。这样的列表,有987个;但是,其中有一些,是骤然发生的,30分钟的区间里面,没有任何其他事件作为先兆。这样的空列表,我进行了清除。剩下了861个有效序列。

  同样,从剩余事件集合中,我们随机找到了861个非空有效序列。这些序列,后续紧随事件,都不是严重拥堵。

  我们对严重拥堵之前30分钟的事件序列,标记为1;对于非严重拥堵之前30分钟的事件序列,标记为0。

  于是,我们就把问题转换成了,能否利用事件序列,进行分类,预测后续是否会发生严重拥堵。

  靠着这个模型,我们团队(UNT IIA lab代表队,其实不过就是我和春迎俩人,团队昵称 watch-dumpling )在这次比赛中,获得第一名。

如何用 Python 和循环神经网络预测严重交通拥堵?

如何用 Python 和循环神经网络预测严重交通拥堵?

  UNT 网站也正式发布了这则新闻(),于是我周围尽人皆知。我才刚拿到手的奖金,立即就因为请客被扫荡一空了。

如何用 Python 和循环神经网络预测严重交通拥堵?

  夺冠纯属是个意外,幸运占得比重很大。但是我觉得我们做的这个模型,还是有些应用价值的。

  下面,我就以这组 Waze 交通事件数据,详细给你讲解一下,如何用 Python, Keras 和循环神经网络,来实现这个序列数据分类模型。

  要运行深度学习,你需要有 GPU 或者 TPU 的支持,否则会累坏你的笔记本电脑的。Google Colab 是个不错的实验平台,可以让你免费使用 TPU 来进行深度学习训练。你可以阅读《如何免费云端运行Python深度学习框架?》一文,查询更为详细的介绍。

  这里,请你使用 Chrome 浏览器,点击这个链接,安装一个插件 Colaboratory 。

如何用 Python 和循环神经网络预测严重交通拥堵?

  把它添加到 Google Chrome 之后,你会在浏览器的扩展工具栏里面,看见下图中间的图标:

  点击上图中红色标出的“复制到云端硬盘”按钮。Google 会为你新建一个属于你自己的副本。

  如果再次出现警告提示,反勾选“在运行前充值所有代码执行程序”选项,再次点击“仍然运行”即可。

  这次还要读入的一个软件包,是 Python 中间进行数据存取的利器,叫做 pickle 。

  它可以把 Python 数据,甚至是许多组数据,一起存储到指定文件。然后读出的时候,可以完全恢复原先数据的格式。这一点上,它比用 csv 进行数据存储和交换的效果更好,效率也更高。

  这里,我们利用的是 Pandas 的一个函数,叫做 idxmax() ,它可以帮助我们,把最大值对应的索引编号,传递回来。

如何用 Python 和循环神经网络预测严重交通拥堵?

  读一遍,你就会发现,在超级拥堵发生之前,确实还是有一些先兆的。当然,这是由人来阅读后,获得的观感。我们下面需要做的,是让机器自动把握这些列表的特征,并且做出区别分类。

  我们使用以下的一个小技巧,把原先的事件词典倒置,即变“序号:事件名称”,为“事件名称:序号”。这样,以事件名称查询起来,效率会高很多。

如何用 Python 和循环神经网络预测严重交通拥堵?

  系统自动提示我们,Keras 使用了 Tensorflow 作为后端框架。

  现在,作为人类,我们确实是看不清楚,列表里面的事件都是什么了。好在计算机对于数字,更加喜闻乐见。

如何用 Python 和循环神经网络预测严重交通拥堵?

  对于输入序列,我们希望它的长度都是一样的。因此,下面我们就用最长的序列长度作为标准,用 0 来填充其他短序列。

如何用 Python 和循环神经网络预测严重交通拥堵?

  为了咱们运行结果的一致性。我这里指定随机种子数值。你第一次尝试运行的时候,不要动它。但是后面自己动手操作的时候,可以任意修改它。

  好了,下面我们“洗牌”。打乱数据的顺序,但是注意序列和对应标记之间,要保持一致性。

如何用 Python 和循环神经网络预测严重交通拥堵?

  然后,我们取 80% 的数据,作为训练;另外 20% 的数据,作为验证。

  注意由于我们补充了“0”,作为填充,因此原先的32种事件类型的基础上,又加了一种。

  我们使用嵌入层,把事件标号,转换成一系列数字组成的向量。这样,可以避免模型把事件序号,当成数值型数据来处理。

  下面我们搭建一个循环神经网络模型。其中的 LSTM 层,包含了32位输出数字。

如何用 Python 和循环神经网络预测严重交通拥堵?

  这里,我假设你已经看过了《如何用 Python 和循环神经网络做中文文本分类?》一文,所以就不对细节进行讲述了。如果你没有看过,或者已经遗忘,可以点击这个链接复习一下。

  下面,是处理其中的嵌入层参数。我们直接把刚才随机生成的嵌入矩阵挪进来。而且,不让模型在训练中对嵌入层参数进行修改。

  训练过程结束之后,我们利用 matplotlib 绘图功能,看一下训练中,准确率和损失值的变化。

如何用 Python 和循环神经网络预测严重交通拥堵?

如何用 Python 和循环神经网络预测严重交通拥堵?

  可以看到,效果还是不错的。因为我们数据中,不同标记各占一半。因此如果构建一个 dummy model 作为标准线%。

  这里的准确率,已经达到了65%-75%之间,证明我们的模型是有意义的。只不过,抖动比较厉害,稳定性差。

如何用 Python 和循环神经网络预测严重交通拥堵?

  这个图看起来,就不是很美妙了。因为虽然训练集上面的损失值一路下降,但是验证集上,这个效果并不是很明显,一直剧烈波动。

  注意我们前面使用了嵌入矩阵。它随机生成,却又没有真正进行训练调整,这可能是个问题。

  因此,我们这里再次构建和跑一下模型。唯一改动的地方,在于让嵌入矩阵的参数也可以随着训练进行自动调整。

  这次的准确率曲线,看起来好多了。验证集波动没有这么剧烈,模型稳定性好了许多。而且,准确率的取值,也获得了提升。后半程稳定在了75%以上。这样的模型,就有应用价值了。

如何用 Python 和循环神经网络预测严重交通拥堵?

如何用 Python 和循环神经网络预测严重交通拥堵?

  立即增加数据,不太现实。因为我们手中,目前只有那29天里积攒的数据。但是降低模型复杂度,是可以利用 Dropout 来尝试完成的。

  Dropout 的实现机理,是在训练的时候,每次随机把一定比例的模型中神经元对应权重参数,设置为0,让它不起作用。这样,模型的复杂度,就会降低。

如何用 Python 和循环神经网络预测严重交通拥堵?

如何用 Python 和循环神经网络预测严重交通拥堵?

  这次的准确率曲线,看起来达到的数值,跟没有加入 Dropout 的差不多。

如何用 Python 和循环神经网络预测严重交通拥堵?

如何用 Python 和循环神经网络预测严重交通拥堵?

  这个曲线上,过拟合的去除效果就更为明显了。可以看到训练集和验证集两条曲线的波动基本保持了一致。这样我们更可以确信,模型预测能力是稳定的,对外界新的输入信息,适应性更好。

  如果把咱们的模型放在交通管理部门那里,可以期望它根据 Waze 获得的新序列数据,能以大约 75% 的准确率,预测严重交通拥堵的发生。这样,交管部门就可以未雨绸缪,提前做出干预了。

  用序列模型,欺负金融市场的散户,属于零和博弈。然而这种在交通管理上的应用,大概更能造福社会,体现科技的价值吧。

  希望这篇文章,可以帮助你了解循环神经网络的更多应用场景。在实际的工作和学习中,灵活运用它来处理序列数据的分类等任务。