From 2fae7985e4186775532449bdebfd56b53797bb15 Mon Sep 17 00:00:00 2001
From: benjas <909336740@qq.com>
Date: Wed, 2 Dec 2020 22:23:18 +0800
Subject: [PATCH] =?UTF-8?q?Add=20=E6=97=B6=E9=97=B4=E5=BA=8F=E7=9A=84?=
=?UTF-8?q?=E8=A1=A5=E5=85=A8=E6=96=B9=E6=B3=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../道路通行时间预测-checkpoint.ipynb | 1389 +++++++++++++++++
.../assets/20201202221436.png | Bin 0 -> 366678 bytes
.../道路通行时间预测.ipynb | 520 +++++-
3 files changed, 1907 insertions(+), 2 deletions(-)
create mode 100644 机器学习竞赛实战_优胜解决方案/智慧城市-道路通行时间预测/assets/20201202221436.png
diff --git a/机器学习竞赛实战_优胜解决方案/智慧城市-道路通行时间预测/.ipynb_checkpoints/道路通行时间预测-checkpoint.ipynb b/机器学习竞赛实战_优胜解决方案/智慧城市-道路通行时间预测/.ipynb_checkpoints/道路通行时间预测-checkpoint.ipynb
index bfa7f57..af3985e 100644
--- a/机器学习竞赛实战_优胜解决方案/智慧城市-道路通行时间预测/.ipynb_checkpoints/道路通行时间预测-checkpoint.ipynb
+++ b/机器学习竞赛实战_优胜解决方案/智慧城市-道路通行时间预测/.ipynb_checkpoints/道路通行时间预测-checkpoint.ipynb
@@ -342,6 +342,1395 @@
"构建时间序列,基于前几天或者前几十天的数据预测"
]
},
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 数据集筛选与标签转换\n",
+ "数据集中有些数据可能由于异常情况导致不适合建模(堵车,维修等)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "
\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " link_ID | \n",
+ " date | \n",
+ " time_interval | \n",
+ " travel_time | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 4377906283422600514 | \n",
+ " 2017-05-06 | \n",
+ " [2017-05-06 11:04:00,2017-05-06 11:06:00) | \n",
+ " 3.0 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 3377906289434510514 | \n",
+ " 2017-05-06 | \n",
+ " [2017-05-06 10:42:00,2017-05-06 10:44:00) | \n",
+ " 1.0 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 3377906285934510514 | \n",
+ " 2017-05-06 | \n",
+ " [2017-05-06 11:56:00,2017-05-06 11:58:00) | \n",
+ " 35.2 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 3377906285934510514 | \n",
+ " 2017-05-06 | \n",
+ " [2017-05-06 17:46:00,2017-05-06 17:48:00) | \n",
+ " 26.2 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 3377906287934510514 | \n",
+ " 2017-05-06 | \n",
+ " [2017-05-06 10:52:00,2017-05-06 10:54:00) | \n",
+ " 10.4 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " link_ID date time_interval \\\n",
+ "0 4377906283422600514 2017-05-06 [2017-05-06 11:04:00,2017-05-06 11:06:00) \n",
+ "1 3377906289434510514 2017-05-06 [2017-05-06 10:42:00,2017-05-06 10:44:00) \n",
+ "2 3377906285934510514 2017-05-06 [2017-05-06 11:56:00,2017-05-06 11:58:00) \n",
+ "3 3377906285934510514 2017-05-06 [2017-05-06 17:46:00,2017-05-06 17:48:00) \n",
+ "4 3377906287934510514 2017-05-06 [2017-05-06 10:52:00,2017-05-06 10:54:00) \n",
+ "\n",
+ " travel_time \n",
+ "0 3.0 \n",
+ "1 1.0 \n",
+ "2 35.2 \n",
+ "3 26.2 \n",
+ "4 10.4 "
+ ]
+ },
+ "execution_count": 12,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "df.head()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " link_ID | \n",
+ " date | \n",
+ " time_interval | \n",
+ " travel_time | \n",
+ " time_interval_begin | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 4377906283422600514 | \n",
+ " 2017-05-06 | \n",
+ " [2017-05-06 11:04:00,2017-05-06 11:06:00) | \n",
+ " 3.0 | \n",
+ " 2017-05-06 11:04:00 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 3377906289434510514 | \n",
+ " 2017-05-06 | \n",
+ " [2017-05-06 10:42:00,2017-05-06 10:44:00) | \n",
+ " 1.0 | \n",
+ " 2017-05-06 10:42:00 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 3377906285934510514 | \n",
+ " 2017-05-06 | \n",
+ " [2017-05-06 11:56:00,2017-05-06 11:58:00) | \n",
+ " 35.2 | \n",
+ " 2017-05-06 11:56:00 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 3377906285934510514 | \n",
+ " 2017-05-06 | \n",
+ " [2017-05-06 17:46:00,2017-05-06 17:48:00) | \n",
+ " 26.2 | \n",
+ " 2017-05-06 17:46:00 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 3377906287934510514 | \n",
+ " 2017-05-06 | \n",
+ " [2017-05-06 10:52:00,2017-05-06 10:54:00) | \n",
+ " 10.4 | \n",
+ " 2017-05-06 10:52:00 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " link_ID date time_interval \\\n",
+ "0 4377906283422600514 2017-05-06 [2017-05-06 11:04:00,2017-05-06 11:06:00) \n",
+ "1 3377906289434510514 2017-05-06 [2017-05-06 10:42:00,2017-05-06 10:44:00) \n",
+ "2 3377906285934510514 2017-05-06 [2017-05-06 11:56:00,2017-05-06 11:58:00) \n",
+ "3 3377906285934510514 2017-05-06 [2017-05-06 17:46:00,2017-05-06 17:48:00) \n",
+ "4 3377906287934510514 2017-05-06 [2017-05-06 10:52:00,2017-05-06 10:54:00) \n",
+ "\n",
+ " travel_time time_interval_begin \n",
+ "0 3.0 2017-05-06 11:04:00 \n",
+ "1 1.0 2017-05-06 10:42:00 \n",
+ "2 35.2 2017-05-06 11:56:00 \n",
+ "3 26.2 2017-05-06 17:46:00 \n",
+ "4 10.4 2017-05-06 10:52:00 "
+ ]
+ },
+ "execution_count": 13,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "#截取开始时间\n",
+ "df['time_interval_begin'] = pd.to_datetime(df['time_interval'].map(lambda x: x[1:20]))\n",
+ "df.head()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "标签转换\n",
+ "
\n",
+ "对于travel_time,我们希望是右边的图,越是正态分布,越好预测"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df = df.drop(['time_interval'],axis=1)\n",
+ "df['travel_time'] = np.log1p(df['travel_time'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "筛选方法"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 17,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "#剔除一些离群点:如travel_time突然有几百分钟的时间,可能是意外、道路维修或者统计错误\n",
+ "def quantile_clip(group):\n",
+ " # 选择一定的百分比过滤\n",
+ " group[group < group.quantile(.05)] = group.quantile(.05)\n",
+ " group[group > group.quantile(.95)] = group.quantile(.95)\n",
+ " return group"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 18,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " link_ID | \n",
+ " date | \n",
+ " travel_time | \n",
+ " time_interval_begin | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 4377906283422600514 | \n",
+ " 2017-05-06 | \n",
+ " 1.386294 | \n",
+ " 2017-05-06 11:04:00 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 3377906289434510514 | \n",
+ " 2017-05-06 | \n",
+ " 0.693147 | \n",
+ " 2017-05-06 10:42:00 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 3377906285934510514 | \n",
+ " 2017-05-06 | \n",
+ " 3.589059 | \n",
+ " 2017-05-06 11:56:00 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 3377906285934510514 | \n",
+ " 2017-05-06 | \n",
+ " 3.303217 | \n",
+ " 2017-05-06 17:46:00 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 3377906287934510514 | \n",
+ " 2017-05-06 | \n",
+ " 2.251292 | \n",
+ " 2017-05-06 10:52:00 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " link_ID date travel_time time_interval_begin\n",
+ "0 4377906283422600514 2017-05-06 1.386294 2017-05-06 11:04:00\n",
+ "1 3377906289434510514 2017-05-06 0.693147 2017-05-06 10:42:00\n",
+ "2 3377906285934510514 2017-05-06 3.589059 2017-05-06 11:56:00\n",
+ "3 3377906285934510514 2017-05-06 3.303217 2017-05-06 17:46:00\n",
+ "4 3377906287934510514 2017-05-06 2.251292 2017-05-06 10:52:00"
+ ]
+ },
+ "execution_count": 18,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "#对每条道路(link_ID),每天执行(date)\n",
+ "df['travel_time'] = df.groupby(['link_ID','date'])['travel_time'].transform(quantile_clip)\n",
+ "df.head(5)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 21,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "#根据需求选择样本数据,比如预测高峰时刻,如早上6-8、中午下午13-18\n",
+ "df = df.loc[(df['time_interval_begin'].dt.hour.isin([6,7,8,13,14,15,16,17,18]))]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 23,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "#保存处理结果\n",
+ "df.to_csv('raw_data.txt',header=True,index=None,sep=';',mode='w')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 缺失值预处理"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 25,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " link_ID | \n",
+ " date | \n",
+ " travel_time | \n",
+ " time_interval_begin | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 3377906285934510514 | \n",
+ " 2017-05-06 | \n",
+ " 3.303217 | \n",
+ " 2017-05-06 17:46:00 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 3377906287934510514 | \n",
+ " 2017-05-06 | \n",
+ " 1.887070 | \n",
+ " 2017-05-06 14:36:00 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 3377906287674510514 | \n",
+ " 2017-05-06 | \n",
+ " 1.931521 | \n",
+ " 2017-05-06 06:30:00 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 3377906287886510514 | \n",
+ " 2017-05-06 | \n",
+ " 3.616309 | \n",
+ " 2017-05-06 07:32:00 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 4377906283759500514 | \n",
+ " 2017-05-06 | \n",
+ " 2.140066 | \n",
+ " 2017-05-06 13:24:00 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " link_ID date travel_time time_interval_begin\n",
+ "0 3377906285934510514 2017-05-06 3.303217 2017-05-06 17:46:00\n",
+ "1 3377906287934510514 2017-05-06 1.887070 2017-05-06 14:36:00\n",
+ "2 3377906287674510514 2017-05-06 1.931521 2017-05-06 06:30:00\n",
+ "3 3377906287886510514 2017-05-06 3.616309 2017-05-06 07:32:00\n",
+ "4 4377906283759500514 2017-05-06 2.140066 2017-05-06 13:24:00"
+ ]
+ },
+ "execution_count": 25,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "df = pd.read_csv('raw_data.txt',delimiter=';',parse_dates=['time_interval_begin'],dtype={'link_ID':object})\n",
+ "df.head()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "如上第一行中,2017-05-06 17:46:00,那么是不是没有17:48、17:50,所以我们需要补充"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 26,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " link_ID | \n",
+ " length | \n",
+ " width | \n",
+ " link_class | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 4377906289869500514 | \n",
+ " 57 | \n",
+ " 3 | \n",
+ " 1 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 4377906284594800514 | \n",
+ " 247 | \n",
+ " 9 | \n",
+ " 1 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 4377906289425800514 | \n",
+ " 194 | \n",
+ " 3 | \n",
+ " 1 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 4377906284525800514 | \n",
+ " 839 | \n",
+ " 3 | \n",
+ " 1 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 4377906284422600514 | \n",
+ " 55 | \n",
+ " 12 | \n",
+ " 1 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " link_ID length width link_class\n",
+ "0 4377906289869500514 57 3 1\n",
+ "1 4377906284594800514 247 9 1\n",
+ "2 4377906289425800514 194 3 1\n",
+ "3 4377906284525800514 839 3 1\n",
+ "4 4377906284422600514 55 12 1"
+ ]
+ },
+ "execution_count": 26,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "link_df.head()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 27,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "DatetimeIndex(['2017-03-01 00:00:00', '2017-03-01 00:02:00',\n",
+ " '2017-03-01 00:04:00', '2017-03-01 00:06:00',\n",
+ " '2017-03-01 00:08:00'],\n",
+ " dtype='datetime64[ns]', freq='2T')"
+ ]
+ },
+ "execution_count": 27,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "date_range = pd.date_range('2017-03-01 00:00:00','2017-07-31 23:58:00',freq='2min')\n",
+ "date_range[:5]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 29,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " link_ID | \n",
+ " time_interval_begin | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 4377906289869500514 | \n",
+ " 2017-03-01 00:00:00 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 4377906289869500514 | \n",
+ " 2017-03-01 00:02:00 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 4377906289869500514 | \n",
+ " 2017-03-01 00:04:00 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 4377906289869500514 | \n",
+ " 2017-03-01 00:06:00 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 4377906289869500514 | \n",
+ " 2017-03-01 00:08:00 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " link_ID time_interval_begin\n",
+ "0 4377906289869500514 2017-03-01 00:00:00\n",
+ "1 4377906289869500514 2017-03-01 00:02:00\n",
+ "2 4377906289869500514 2017-03-01 00:04:00\n",
+ "3 4377906289869500514 2017-03-01 00:06:00\n",
+ "4 4377906289869500514 2017-03-01 00:08:00"
+ ]
+ },
+ "execution_count": 29,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "#给每个ID,做出每一个时刻\n",
+ "new_index = pd.MultiIndex.from_product([link_df['link_ID'].unique(),date_range],\n",
+ " names=['link_ID', 'time_interval_begin'])\n",
+ "new_df = pd.DataFrame(index=new_index).reset_index()\n",
+ "new_df.head() # 此时每个ID都有从2017-03-01 00:00:00到2017-03-71 23:58:00的时间间隔"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 32,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " link_ID | \n",
+ " time_interval_begin | \n",
+ " date | \n",
+ " travel_time | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 4377906289869500514 | \n",
+ " 2017-03-01 00:00:00 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 4377906289869500514 | \n",
+ " 2017-03-01 00:02:00 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 4377906289869500514 | \n",
+ " 2017-03-01 00:04:00 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 4377906289869500514 | \n",
+ " 2017-03-01 00:06:00 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 4377906289869500514 | \n",
+ " 2017-03-01 00:08:00 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " link_ID time_interval_begin date travel_time\n",
+ "0 4377906289869500514 2017-03-01 00:00:00 NaN NaN\n",
+ "1 4377906289869500514 2017-03-01 00:02:00 NaN NaN\n",
+ "2 4377906289869500514 2017-03-01 00:04:00 NaN NaN\n",
+ "3 4377906289869500514 2017-03-01 00:06:00 NaN NaN\n",
+ "4 4377906289869500514 2017-03-01 00:08:00 NaN NaN"
+ ]
+ },
+ "execution_count": 32,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "#原来的表里也有部分值,进行合并,出现大量缺失值\n",
+ "df2 = pd.merge(new_df, df,on=['link_ID','time_interval_begin'],how='left')\n",
+ "df2.head()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 41,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "#筛选时间段数据\n",
+ "df2 = df2.loc[(df2['time_interval_begin'].dt.hour.isin([6,7,8,13,14,15,16,17,18]))]\n",
+ "df2 = df2.loc[~((df2['time_interval_begin'].dt.year == 2017) & \n",
+ " (df2['time_interval_begin'].dt.month == 7) & \n",
+ " (df2['time_interval_begin'].dt.hour.isin([8,15,18])))]\n",
+ "df2 = df2.loc[~((df2['time_interval_begin'].dt.year == 2017) & \n",
+ " (df2['time_interval_begin'].dt.month == 3) & \n",
+ " (df2['time_interval_begin'].dt.day == 31))]\n",
+ "\n",
+ "df2['date'] = df2['time_interval_begin'].dt.strftime('%Y-%m-%d')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 42,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " link_ID | \n",
+ " time_interval_begin | \n",
+ " date | \n",
+ " travel_time | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 180 | \n",
+ " 4377906289869500514 | \n",
+ " 2017-03-01 06:00:00 | \n",
+ " 2017-03-01 | \n",
+ " 2.174752 | \n",
+ "
\n",
+ " \n",
+ " 181 | \n",
+ " 4377906289869500514 | \n",
+ " 2017-03-01 06:02:00 | \n",
+ " 2017-03-01 | \n",
+ " 2.174752 | \n",
+ "
\n",
+ " \n",
+ " 182 | \n",
+ " 4377906289869500514 | \n",
+ " 2017-03-01 06:04:00 | \n",
+ " 2017-03-01 | \n",
+ " 2.174752 | \n",
+ "
\n",
+ " \n",
+ " 183 | \n",
+ " 4377906289869500514 | \n",
+ " 2017-03-01 06:06:00 | \n",
+ " 2017-03-01 | \n",
+ " 2.174752 | \n",
+ "
\n",
+ " \n",
+ " 184 | \n",
+ " 4377906289869500514 | \n",
+ " 2017-03-01 06:08:00 | \n",
+ " 2017-03-01 | \n",
+ " 2.174752 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " link_ID time_interval_begin date travel_time\n",
+ "180 4377906289869500514 2017-03-01 06:00:00 2017-03-01 2.174752\n",
+ "181 4377906289869500514 2017-03-01 06:02:00 2017-03-01 2.174752\n",
+ "182 4377906289869500514 2017-03-01 06:04:00 2017-03-01 2.174752\n",
+ "183 4377906289869500514 2017-03-01 06:06:00 2017-03-01 2.174752\n",
+ "184 4377906289869500514 2017-03-01 06:08:00 2017-03-01 2.174752"
+ ]
+ },
+ "execution_count": 42,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "df2.head()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 43,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "#保存中间结果\n",
+ "df2.to_csv('pre_trainning.txt',header=True,index=None,sep=';',mode='w')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### 补全时间序列"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 44,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " link_ID | \n",
+ " time_interval_begin | \n",
+ " date | \n",
+ " travel_time | \n",
+ " travel_time2 | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 180 | \n",
+ " 4377906289869500514 | \n",
+ " 2017-03-01 06:00:00 | \n",
+ " 2017-03-01 | \n",
+ " 2.174752 | \n",
+ " 2.174752 | \n",
+ "
\n",
+ " \n",
+ " 181 | \n",
+ " 4377906289869500514 | \n",
+ " 2017-03-01 06:02:00 | \n",
+ " 2017-03-01 | \n",
+ " 2.174752 | \n",
+ " 2.174752 | \n",
+ "
\n",
+ " \n",
+ " 182 | \n",
+ " 4377906289869500514 | \n",
+ " 2017-03-01 06:04:00 | \n",
+ " 2017-03-01 | \n",
+ " 2.174752 | \n",
+ " 2.174752 | \n",
+ "
\n",
+ " \n",
+ " 183 | \n",
+ " 4377906289869500514 | \n",
+ " 2017-03-01 06:06:00 | \n",
+ " 2017-03-01 | \n",
+ " 2.174752 | \n",
+ " 2.174752 | \n",
+ "
\n",
+ " \n",
+ " 184 | \n",
+ " 4377906289869500514 | \n",
+ " 2017-03-01 06:08:00 | \n",
+ " 2017-03-01 | \n",
+ " 2.174752 | \n",
+ " 2.174752 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " link_ID time_interval_begin date travel_time \\\n",
+ "180 4377906289869500514 2017-03-01 06:00:00 2017-03-01 2.174752 \n",
+ "181 4377906289869500514 2017-03-01 06:02:00 2017-03-01 2.174752 \n",
+ "182 4377906289869500514 2017-03-01 06:04:00 2017-03-01 2.174752 \n",
+ "183 4377906289869500514 2017-03-01 06:06:00 2017-03-01 2.174752 \n",
+ "184 4377906289869500514 2017-03-01 06:08:00 2017-03-01 2.174752 \n",
+ "\n",
+ " travel_time2 \n",
+ "180 2.174752 \n",
+ "181 2.174752 \n",
+ "182 2.174752 \n",
+ "183 2.174752 \n",
+ "184 2.174752 "
+ ]
+ },
+ "execution_count": 44,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "df = df2\n",
+ "df['travel_time2'] = df['travel_time']\n",
+ "df.head()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "多个月统计-季节性变化"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 45,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def date_trend(group):\n",
+ " tmp = group.groupby('date_hour').mean().reset_index()\n",
+ " \n",
+ " def nan_helper(y):\n",
+ " return np.isnan(y), lambda z: z.nonzero()[0]\n",
+ " \n",
+ " y = tmp['travel_time'].values\n",
+ " nans, x = nan_helper(y)\n",
+ " if group.link_ID.values[0] in ['3377906282328510514','3377906283328510514',\n",
+ " '4377906280784800514','9377906281555510514']:\n",
+ " tmp['date_trend'] = group['travel_time'].median()\n",
+ " else:\n",
+ " regr = linear_model.LinearRegression()\n",
+ " regr.fit(x(~nans).reshape(-1,1), y[~nans].reshape(-1,1))\n",
+ " tmp['date_trend'] = regr.predict(tmp.index.values.reshape(-1,1)).ravel()\n",
+ " group = pd.merge(group,tmp[['date_trend','date_hour']], on='date_hour',how='left')\n",
+ " return group"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 46,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " link_ID | \n",
+ " time_interval_begin | \n",
+ " date | \n",
+ " travel_time | \n",
+ " travel_time2 | \n",
+ " date_hour | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 180 | \n",
+ " 4377906289869500514 | \n",
+ " 2017-03-01 06:00:00 | \n",
+ " 2017-03-01 | \n",
+ " 2.174752 | \n",
+ " 2.174752 | \n",
+ " 2017-03-01-06 | \n",
+ "
\n",
+ " \n",
+ " 181 | \n",
+ " 4377906289869500514 | \n",
+ " 2017-03-01 06:02:00 | \n",
+ " 2017-03-01 | \n",
+ " 2.174752 | \n",
+ " 2.174752 | \n",
+ " 2017-03-01-06 | \n",
+ "
\n",
+ " \n",
+ " 182 | \n",
+ " 4377906289869500514 | \n",
+ " 2017-03-01 06:04:00 | \n",
+ " 2017-03-01 | \n",
+ " 2.174752 | \n",
+ " 2.174752 | \n",
+ " 2017-03-01-06 | \n",
+ "
\n",
+ " \n",
+ " 183 | \n",
+ " 4377906289869500514 | \n",
+ " 2017-03-01 06:06:00 | \n",
+ " 2017-03-01 | \n",
+ " 2.174752 | \n",
+ " 2.174752 | \n",
+ " 2017-03-01-06 | \n",
+ "
\n",
+ " \n",
+ " 184 | \n",
+ " 4377906289869500514 | \n",
+ " 2017-03-01 06:08:00 | \n",
+ " 2017-03-01 | \n",
+ " 2.174752 | \n",
+ " 2.174752 | \n",
+ " 2017-03-01-06 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " link_ID time_interval_begin date travel_time \\\n",
+ "180 4377906289869500514 2017-03-01 06:00:00 2017-03-01 2.174752 \n",
+ "181 4377906289869500514 2017-03-01 06:02:00 2017-03-01 2.174752 \n",
+ "182 4377906289869500514 2017-03-01 06:04:00 2017-03-01 2.174752 \n",
+ "183 4377906289869500514 2017-03-01 06:06:00 2017-03-01 2.174752 \n",
+ "184 4377906289869500514 2017-03-01 06:08:00 2017-03-01 2.174752 \n",
+ "\n",
+ " travel_time2 date_hour \n",
+ "180 2.174752 2017-03-01-06 \n",
+ "181 2.174752 2017-03-01-06 \n",
+ "182 2.174752 2017-03-01-06 \n",
+ "183 2.174752 2017-03-01-06 \n",
+ "184 2.174752 2017-03-01-06 "
+ ]
+ },
+ "execution_count": 46,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# 基于小时进行预测,如果基于整体预测,结果可能不准确定,我们先算小时对结果的影响\n",
+ "df['date_hour'] = df.time_interval_begin.map(lambda x: x.strftime('%Y-%m-%d-%H'))\n",
+ "df.head()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "道路每小时通行时间的回归结果\n",
+ "
\n",
+ "左图:回归预测,蓝色线是回归线,红色是时间\n",
+ "右图:对某几个道路,直接用中位数预测"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 47,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " | \n",
+ " link_ID | \n",
+ " time_interval_begin | \n",
+ " date | \n",
+ " travel_time | \n",
+ " travel_time2 | \n",
+ " date_hour | \n",
+ " date_trend | \n",
+ "
\n",
+ " \n",
+ " link_ID | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 3377906280028510514 | \n",
+ " 0 | \n",
+ " 3377906280028510514 | \n",
+ " 2017-03-01 06:00:00 | \n",
+ " 2017-03-01 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 2017-03-01-06 | \n",
+ " 1.960745 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 3377906280028510514 | \n",
+ " 2017-03-01 06:02:00 | \n",
+ " 2017-03-01 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 2017-03-01-06 | \n",
+ " 1.960745 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 3377906280028510514 | \n",
+ " 2017-03-01 06:04:00 | \n",
+ " 2017-03-01 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 2017-03-01-06 | \n",
+ " 1.960745 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 3377906280028510514 | \n",
+ " 2017-03-01 06:06:00 | \n",
+ " 2017-03-01 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 2017-03-01-06 | \n",
+ " 1.960745 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 3377906280028510514 | \n",
+ " 2017-03-01 06:08:00 | \n",
+ " 2017-03-01 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 2017-03-01-06 | \n",
+ " 1.960745 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " link_ID time_interval_begin date \\\n",
+ "link_ID \n",
+ "3377906280028510514 0 3377906280028510514 2017-03-01 06:00:00 2017-03-01 \n",
+ " 1 3377906280028510514 2017-03-01 06:02:00 2017-03-01 \n",
+ " 2 3377906280028510514 2017-03-01 06:04:00 2017-03-01 \n",
+ " 3 3377906280028510514 2017-03-01 06:06:00 2017-03-01 \n",
+ " 4 3377906280028510514 2017-03-01 06:08:00 2017-03-01 \n",
+ "\n",
+ " travel_time travel_time2 date_hour date_trend \n",
+ "link_ID \n",
+ "3377906280028510514 0 NaN NaN 2017-03-01-06 1.960745 \n",
+ " 1 NaN NaN 2017-03-01-06 1.960745 \n",
+ " 2 NaN NaN 2017-03-01-06 1.960745 \n",
+ " 3 NaN NaN 2017-03-01-06 1.960745 \n",
+ " 4 NaN NaN 2017-03-01-06 1.960745 "
+ ]
+ },
+ "execution_count": 47,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "df = df.groupby('link_ID').apply(date_trend)\n",
+ "df.head()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "蓝线回归得到的值存在 df['date trend']里,此时 travel_time 就更新为 df['travel_time']= df['travel_time']-df['date_trend'],表示date_trend作为大的趋势已经被线性回归决定了,剩下的就是研究这个残差了,之后训练和预测都是基于残差,最后用预测出来的残差加上相应的date_trend即可得到需要的预测值"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 48,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " link_ID | \n",
+ " time_interval_begin | \n",
+ " date | \n",
+ " travel_time | \n",
+ " travel_time2 | \n",
+ " date_trend | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 3377906280028510514 | \n",
+ " 2017-03-01 06:00:00 | \n",
+ " 2017-03-01 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 1.960745 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 3377906280028510514 | \n",
+ " 2017-03-01 06:02:00 | \n",
+ " 2017-03-01 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 1.960745 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 3377906280028510514 | \n",
+ " 2017-03-01 06:04:00 | \n",
+ " 2017-03-01 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 1.960745 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 3377906280028510514 | \n",
+ " 2017-03-01 06:06:00 | \n",
+ " 2017-03-01 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 1.960745 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 3377906280028510514 | \n",
+ " 2017-03-01 06:08:00 | \n",
+ " 2017-03-01 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 1.960745 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " link_ID time_interval_begin date travel_time \\\n",
+ "0 3377906280028510514 2017-03-01 06:00:00 2017-03-01 NaN \n",
+ "1 3377906280028510514 2017-03-01 06:02:00 2017-03-01 NaN \n",
+ "2 3377906280028510514 2017-03-01 06:04:00 2017-03-01 NaN \n",
+ "3 3377906280028510514 2017-03-01 06:06:00 2017-03-01 NaN \n",
+ "4 3377906280028510514 2017-03-01 06:08:00 2017-03-01 NaN \n",
+ "\n",
+ " travel_time2 date_trend \n",
+ "0 NaN 1.960745 \n",
+ "1 NaN 1.960745 \n",
+ "2 NaN 1.960745 \n",
+ "3 NaN 1.960745 \n",
+ "4 NaN 1.960745 "
+ ]
+ },
+ "execution_count": 48,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "df = df.drop(['date_hour','link_ID'],axis=1)\n",
+ "df = df.reset_index()\n",
+ "df = df.drop('level_1',axis=1)\n",
+ "df['travel_time'] = df['travel_time'] - df['date_trend']\n",
+ "df.head()"
+ ]
+ },
{
"cell_type": "code",
"execution_count": null,
diff --git a/机器学习竞赛实战_优胜解决方案/智慧城市-道路通行时间预测/assets/20201202221436.png b/机器学习竞赛实战_优胜解决方案/智慧城市-道路通行时间预测/assets/20201202221436.png
new file mode 100644
index 0000000000000000000000000000000000000000..8a5f4f1c507d3c0818e38f522804f5c407c30abf
GIT binary patch
literal 366678
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