智慧城市道路通行时间预测(笔记未完成版)

news2024/11/29 20:32:49

数据与任务目标分析

数据

道路通行时间

当前道路在该时间段内有车通行的时间

道路长宽情况

道路连接情况

任务

基于历史数据预测某个时间段内,如预测未来一个月travel_time, 每2分钟内通行时间。

构建时间序列,基于时间序列预测

预测高峰点(如6 7 8 13 14 15 16 17 18 点)的车流量,不用预测每个点

数据预处理

缺失值

在这里插入图片描述

数据集筛选与标签转换

数据集中有些数据可能由于异常情况导致不适合建模(堵车,维修等)

*标签 数据不呈正太分布,取log值进行转换

df = df.drop(['time_interval'], axis=1)
df['travel_time'] = np.log1p(df['travel_time'])

在这里插入图片描述

  • 筛选离群点
#剔除掉一些离群点
def quantile_clip(group):     
    group[group < group.quantile(.05)] = group.quantile(.05)
    group[group > group.quantile(.95)] = group.quantile(.95)
    return group
#对每条道路,每天执行
df['travel_time'] = df.groupby(['link_ID', 'date'])['travel_time'].transform(quantile_clip)
df.head(5)
  • 根据需求来选择样本数据
#根据需求来选择样本数据
df = df.loc[(df['time_interval_begin'].dt.hour.isin([6, 7, 8, 13, 14, 15, 16, 17, 18]))]

项目仅需针对部分高峰时刻进行预测,所以只要选择相应时间的数据即可。

缺失值处理

  • 数据存在缺失,如时间段不连续
    建立连续的时间序列数据,再与原来的数据进行合并
df = pd.read_csv('data/raw_data.txt', delimiter=';', parse_dates=['time_interval_begin'], dtype={'link_ID': object})
df.head()
  • 构建时间序列数据,原始数据表中没有列出的数据均需要填充
date_range = pd.date_range("2017-03-01 00:00:00", "2017-07-31 23:58:00", freq='2min')
date_range[:5]

在这里插入图片描述

new_index = pd.MultiIndex.from_product([link_df['link_ID'].unique(), date_range],
                                       names=['link_ID', 'time_interval_begin'])
new_df = pd.DataFrame(index=new_index).reset_index()
new_df.head()

在这里插入图片描述

#合并,出现大量缺失值
df2 = pd.merge(new_df, df, on=['link_ID', 'time_interval_begin'], how='left')

在这里插入图片描述

  • 筛选所需时间段数据
df2 = df2.loc[(df2['time_interval_begin'].dt.hour.isin([6, 7, 8, 13, 14, 15, 16, 17, 18]))]
df2 = df2.loc[~((df2['time_interval_begin'].dt.year == 2017) & (df2['time_interval_begin'].dt.month == 7) & (
    df2['time_interval_begin'].dt.hour.isin([8, 15, 18])))]
df2 = df2.loc[~((df2['time_interval_begin'].dt.year == 2017) & (df2['time_interval_begin'].dt.month == 3) & (
    df2['time_interval_begin'].dt.day == 31))]

df2['date'] = df2['time_interval_begin'].dt.strftime('%Y-%m-%d')

在这里插入图片描述

补全时间序列

  • 用回归算法预测
  • 用插值填充
df = pd.read_csv('data/pre_training.txt', delimiter=';', parse_dates=['time_interval_begin'], dtype={'link_ID': object})
df['travel_time2'] = df['travel_time']
df.head()

多个月统计-季节性变化-小时

def date_trend(group):
    tmp = group.groupby('date_hour').mean().reset_index()

    def nan_helper(y):
        return np.isnan(y), lambda z: z.nonzero()[0]

    y = tmp['travel_time'].values
    nans, x = nan_helper(y)
    if group.link_ID.values[0] in ['3377906282328510514', '3377906283328510514', '4377906280784800514',
                                   '9377906281555510514']:
        tmp['date_trend'] = group['travel_time'].median()
    else:
        regr = linear_model.LinearRegression()
        regr.fit(x(~nans).reshape(-1, 1), y[~nans].reshape(-1, 1))
        tmp['date_trend'] = regr.predict(tmp.index.values.reshape(-1, 1)).ravel()
    group = pd.merge(group, tmp[['date_trend', 'date_hour']], on='date_hour', how='left')
    return group
df['date_hour'] = df.time_interval_begin.map(lambda x: x.strftime('%Y-%m-%d-%H'))
df.head()

在这里插入图片描述
蓝线回归得到的值存在df[‘date_trend’]里,此时travel_time就更新为df[‘travel_time’] = df[‘travel_time’] - df[‘date_trend’],表示date_trend作为大的趋势已经被线性回归决定了,剩下的就是研究这个残差了,之后训练和预测都是基于残差,最后用预测出来的残差加上相应的date_trend即可得到需要的预测值

df = df.drop(['date_hour', 'link_ID'], axis=1)
df = df.reset_index()
df = df.drop('level_1', axis=1)
df['travel_time'] = df['travel_time'] - df['date_trend']
df.head()

日变化量(分钟)

  • 插值法
def minute_trend(group):
    tmp = group.groupby('hour_minute').mean().reset_index()
    #s的值越小,对数据拟合越好,但是会过拟合的危险;
    spl = UnivariateSpline(tmp.index, tmp['travel_time'].values, s=0.5) # s代表复杂度,s越小越容易过拟合?(待了解)
    tmp['minute_trend'] = spl(tmp.index)
    group = pd.merge(group, tmp[['minute_trend', 'hour_minute']], on='hour_minute', how='left')

    return group

在这里插入图片描述

df['hour_minute'] = df.time_interval_begin.map(lambda x: x.strftime('%H-%M'))
df.head()

在这里插入图片描述

df = df.drop(['hour_minute', 'link_ID'], axis=1)
df = df.reset_index()
df = df.drop('level_1', axis=1)
df['travel_time'] = df['travel_time'] - df['minute_trend']

在这里插入图片描述

其他因素/特征的影响

  • 选择训练特征
link_infos = pd.read_csv('gy_contest_link_info.txt', delimiter=';', dtype={'link_ID': object})
link_tops = pd.read_csv('gy_contest_link_top.txt', delimiter=',', dtype={'link_ID': object})
link_infos = pd.merge(link_infos, link_tops, on=['link_ID'], how='left') #合并道路信息
link_infos['links_num'] = link_infos["in_links"]+link_infos["out_links"] #总和
link_infos['area'] = link_infos['length'] * link_infos['width'] #面积
df = pd.merge(df, link_infos[['link_ID', 'length', 'width', 'links_num', 'area']], on=['link_ID'], how='left') #组合特征
df.head()

在这里插入图片描述

  • 时间相关特征
    • 节假日判断
df.loc[df['date'].isin(
    ['2017-04-02', '2017-04-03', '2017-04-04', '2017-04-29', '2017-04-30', '2017-05-01',
     '2017-05-28', '2017-05-29', '2017-05-30']), 'vacation'] = 1

df.loc[~df['date'].isin(
    ['2017-04-02', '2017-04-03', '2017-04-04', '2017-04-29', '2017-04-30', '2017-05-01',
     '2017-05-28', '2017-05-29', '2017-05-30']), 'vacation'] = 0

df['minute'] = df['time_interval_begin'].dt.minute
df['hour'] = df['time_interval_begin'].dt.hour
df['day'] = df['time_interval_begin'].dt.day
df['week_day'] = df['time_interval_begin'].map(lambda x: x.weekday() + 1)
df['month'] = df['time_interval_begin'].dt.month
df.head()

在这里插入图片描述

  • linkID 是否可做特征
    可不用做特征
    如果

序列补全

标准化

def std(group):
    group['travel_time_std'] = np.std(group['travel_time'])
    return group
df = df.groupby('link_ID').apply(std)
df['travel_time'] = df['travel_time'] / df['travel_time_std']
df.head()

get_dummies

本项目中影响不大

建设回归模型来预测缺失值

params = {
        'learning_rate': 0.2,
        'n_estimators': 30,
        'subsample': 0.8,
        'colsample_bytree': 0.6,
        'max_depth': 10,
        'min_child_weight': 1,
        'reg_alpha': 0,
        'gamma': 0
    }
df = pd.get_dummies(df, columns=['links_num', 'width', 'minute', 'hour', 'week_day', 'day', 'month'])
df.head()

训练的数据train_df 为travel_time非空的数据,而测试集test_df为travel_time空的数据

feature = df.columns.values.tolist()
train_feature = [x for x in feature if
                 x not in ['link_ID', 'time_interval_begin', 'travel_time', 'date', 'travel_time2', 'minute_trend',
                           'travel_time_std', 'date_trend']]

train_df = df.loc[~df['travel_time'].isnull()]
test_df = df.loc[df['travel_time'].isnull()].copy()

print (train_feature)

训练数据切分

X = train_df[train_feature].values
y = train_df['travel_time'].values

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1, random_state=0)

eval_set = [(X_test, y_test)]
regressor = xgb.XGBRegressor(learning_rate=params['learning_rate'], n_estimators=params['n_estimators'],
                             booster='gbtree', objective='reg:linear', n_jobs=-1, subsample=params['subsample'],
                             colsample_bytree=params['colsample_bytree'], random_state=0,
                             max_depth=params['max_depth'], gamma=params['gamma'],
                             min_child_weight=params['min_child_weight'], reg_alpha=params['reg_alpha'])
regressor.fit(X_train, y_train, verbose=True, early_stopping_rounds=10, eval_set=eval_set)
print (test_df[train_feature].head())
print (test_df[train_feature].info())
test_df['prediction'] = regressor.predict(test_df[train_feature].values)
df = pd.merge(df, test_df[['link_ID', 'time_interval_begin', 'prediction']], on=['link_ID', 'time_interval_begin'],
                  how='left')
feature_vis(regressor,train_feature)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

构建特征

TIPS

  • 减去季节趋势项后预测残差,最后再加上趋势项
  • 季节趋势项包含:日、时 等方面
  • 利用回归模型来预测缺失值,建立完整的序列数据

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

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

相关文章

简单介绍Rope Crystal(类似Roop)项目

文章目录 &#xff08;一&#xff09;关于 Rope Crystal&#xff08;二&#xff09;安装 Rope Crystal&#xff08;三&#xff09;运行 Rope Crystal&#xff08;3.1&#xff09;选择目录&#xff08;3.2&#xff09;加载目录&#xff08;3.3&#xff09;选择并替换&#xff08…

MySQL安装validate_password_policy插件

功能介绍 validate_password_policy 是插件用于验证密码强度的策略。该参数可以设定三种级别&#xff1a;0代表低&#xff0c;1代表中&#xff0c;2代表高。 validate_password_policy 主要影响密码的强度检查级别&#xff1a; 0/LOW&#xff1a;只检查密码长度。 1/MEDIUM&am…

行业追踪,2023-09-13

自动复盘 2023-09-13 凡所有相&#xff0c;皆是虚妄。若见诸相非相&#xff0c;即见如来。 k 线图是最好的老师&#xff0c;每天持续发布板块的rps排名&#xff0c;追踪板块&#xff0c;板块来开仓&#xff0c;板块去清仓&#xff0c;丢弃自以为是的想法&#xff0c;板块去留让…

2023下半年创业风口项目:实景自动无人直播!揭秘3大好处!

实景自动无人直播就是2023下半年的创业风口项目&#xff0c;你踩中过风口吗&#xff1f;如果你还没有踩中过风口啊&#xff0c;就缺这么一个机会&#xff0c;那你要注意把握机遇了&#xff0c;建议你看完这篇文章。 为什么说实景自动无人直播将是2023下半年的创业风口项目呢&am…

golang面试官:for select时,如果通道已经关闭会怎么样?如果select中只有一个case呢?

问题 for循环select时&#xff0c;如果通道已经关闭会怎么样&#xff1f;如果select中的case只有一个&#xff0c;又会怎么样&#xff1f; 怎么答 for循环select时&#xff0c;如果其中一个case通道已经关闭&#xff0c;则每次都会执行到这个case。如果select里边只有一个ca…

【2023年Google 开发者大会】武侠风格讲述Gloud

文章目录 Google Cloud 如何加速创新&#xff0c;加强信息安全Google Cloud 如何加强信息安全&#xff1f;1.高级安全防护2.强大的身份验证和访问控制3.基于机器学习的威胁检测 Google Cloud 的 3 个 AI 重点发展领域&#xff0c;了解生成式 AI 功能如何助推创意落地Vertex AIV…

Leetcode刷题_贪心相关_c++版

&#xff08;1&#xff09;455分发饼干–简单 假设你是一位很棒的家长&#xff0c;想要给你的孩子们一些小饼干。但是&#xff0c;每个孩子最多只能给一块饼干。 对每个孩子 i&#xff0c;都有一个胃口值 g[i]&#xff0c;这是能让孩子们满足胃口的饼干的最小尺寸&#xff1b…

Web之tomcat

[TOC]&#xff08;文章目录&#xff09; 1.程序架构 1.C/S(client/server) 比如&#xff1a;QQ、 微信、 LOL 优点&#xff1a;有一部分代码写在客户端&#xff0c; 用户体验比较好。 缺点&#xff1a; 服务器更新&#xff0c;客户端也要随着更新。 占用资源大。 2. B/S(brows…

【盘点】设计师更偏爱Telerik Kendo UI界面库的4个理由!

就像许多开发人员(错误地)认为设计软件和工具对他们没有任何用处一样&#xff0c;许多设计人员也错误地认为&#xff0c;当涉及到以开发人员为中心的软件和工具时&#xff0c;对他们没有任何价值。事实上&#xff0c;如果双方都愿意走出自己的舒适区去探索&#xff0c;他们都会…

在微信小程序上怎么实现多门店管理功能

微信小程序已经成为连接线上与线下的重要工具&#xff0c;尤其对于拥有多家门店的企业来说&#xff0c;通过微信小程序可以实现多门店管理&#xff0c;提高管理效率和用户体验。下面&#xff0c;我将为大家详细介绍如何在微信小程序上实现多门店管理功能。 一、确定多门店管理功…

打印日志遇到的问题,logback与zookeeper冲突

在做项目时需要打印日志引入了logback打印日志&#xff0c;但是一直无法打印&#xff0c;于是一路查找原因。发现zookeeper中默认带的有个logback和我自己引入的logback版本冲突了&#xff0c;这样直接使用exclusions标签将zookeeper中自带的日志框架全部排除即可 按理说到这一…

【leetcode 力扣刷题】栈—波兰式///逆波兰式相关知识和题目

波兰式、逆波兰式相关知识和题目 波兰式、逆波兰式介绍常规表达式转换成逆波兰式编程让常规表达式转换成逆波兰式逆波兰式运算过程常规表达式转换成波兰式编程让常规表达式转换成波兰式波兰式运算过程 150. 逆波兰式表达式求值224. 基本计算器227. 基本计算器Ⅱ282. 给表达式添…

【每日一题】852. 山脉数组的峰顶索引

852. 山脉数组的峰顶索引 - 力扣&#xff08;LeetCode&#xff09; 符合下列属性的数组 arr 称为 山脉数组 &#xff1a; arr.length > 3存在 i&#xff08;0 < i < arr.length - 1&#xff09;使得&#xff1a; arr[0] < arr[1] < ... arr[i-1] < arr[i] ar…

Linux重装qemu和libvirt

要重装qemu和libvirtd在CentOS上&#xff0c;请按照以下步骤操作&#xff1a; 首先&#xff0c;请确保您具有root权限或sudo访问权限。 首先&#xff0c;您需要卸载现有的qemu和libvirt软件包。使用以下命令&#xff1a; sudo yum remove qemu-kvm qemu-img libvirt在卸载完成…

MySQL基础终端命令与Python简单操作MySQL

文章目录 MySQL终端命令1. 进入mysql2. 创建数据库3. 选择数据库4. 创建数据表1. 主键约束2. 外键约束3. 非空约束4. 唯一约束5. 使用默认约束6. 设置id为自增列 5. 查看数据表6. 修改数据表1. 修改表名2. 修改表的字段类型3. 修改表的字段名4. 为表添加字段5. 删除字段6. 调整…

HTML的学习 Day01

《网页设计与制作》是web前端开发技术中静态网页中的内容&#xff0c;主要包括html、css、js中的静态内容部分&#xff0c;是专业基础课程。 随着5G时代的到来&#xff0c;人工智能与物联网结合行业的飞速发展&#xff0c;更多的互联网的崛起。这肯定就比如伴随着对移动互联网…

05-Redis高可用集群之水平扩展

上一篇&#xff1a;04-Redis哨兵高可用架构 1.概要说明 Redis3.0以后的版本虽然有了集群功能&#xff0c;提供了比之前版本的哨兵模式更高的性能与可用性&#xff0c;但是集群的水平扩展却比较麻烦&#xff0c;今天就来带大家看看redis高可用集群如何做水平扩展&#xff0c;…

Houdini 灯光插件工作流程,如何将 HDR Light Studio 与 Houdini 结合使用?

如何不额外购买硬件&#xff0c;流畅的运行Houdini&#xff1a; Houdini项目渲染慢&#xff0c;本地硬件配置不够&#xff0c;想要加速渲染&#xff0c;在不增加额外的硬件成本投入的情况下&#xff0c;最好的解决方式是使用渲云云渲染&#xff0c;在云端批量渲染&#xff0c;…

高效通过指定秒数分割视频,定制你的片段!

大家好&#xff01;在处理电脑上的视频文件时&#xff0c;如果需要从指定秒数处进行分割视频&#xff0c;传统的方法可能会显得非常繁琐和费时。为了让您能够轻松实现这一需求&#xff0c;我们为您提供了一种高效的方法&#xff0c;让您能够精准地从指定秒数处分割视频&#xf…

出现线程安全问题的原因和解决方案

文章目录 一、什么是线程安全问题二、出现线程安全问题的原因三、解决方案3.1加锁 一、什么是线程安全问题 某些代码在单线程环境下执行结果完全正确&#xff0c;但在多线程环境下执行就会出现Bug&#xff0c;这就是“线程安全问题”。 下面以一个变量n自增两次&#xff0c;每…