Académique Documents
Professionnel Documents
Culture Documents
MODELISATION STATISTIQUE
Par :
AHBACH Hamza et AIT ZAABOUL Khawla
Ce projet s'inscrit dans une vision plus large de l'utilisation de science des donnés
pour optimiser la gestion du trafic routier, contribuant ainsi à la création de villes
intelligentes et à une mobilité urbaine plus fluide. À travers cette exploration, nous
détaillerons les différentes étapes de notre analyse, soulignant les enjeux
spécifiques et envisageant des solutions innovantes pour une gestion du trafic plus
intelligente.
Présentation du Dataset
December 3, 2023
Realisé par
AHBACH Hamza – AIT ZAABOUL Khawla
Encadré par
Pr ASMAA BENGHABRIT
L’étape d’exploration des données revêt une importance capitale dans notre démarche analytique.
Notre objectif est de comprendre en profondeur la structure, les tendances et les particularités du
jeu de données “train.xlsx”.
Cette exploration approfondie constitue le socle sur lequel nous construisons nos modèles prédictifs.
Importons les biblotheques necessaires
import numpy as np
import pandas as pd
import plotly.express as px
import matplotlib.pyplot as plt
%matplotlib inline
import seaborn as sns
import time
from scipy.signal import find_peaks
from scipy.stats import gamma
import statsmodels.api as sm
import warnings
from datetime import datetime
import statsmodels.api as sm
import scipy.stats as stats
import os
1
$$
importons le dataset
[ ]: data = pd.read_csv("/train_ML_IOT.csv")
data
• Le dataset contient les enregstriement pour chaque junction durant les 20 mois depuis 2015-
11-01 jusqu’au 2017-06-30 et durant chaque heure
informations sur le dataset
[ ]: data.describe(), data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 48120 entries, 0 to 48119
Data columns (total 4 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 DateTime 48120 non-null object
1 Junction 48120 non-null int64
2 Vehicles 48120 non-null int64
3 ID 48120 non-null int64
dtypes: int64(3), object(1)
memory usage: 1.5+ MB
[ ]: ( Junction Vehicles ID
count 48120.000000 48120.000000 4.812000e+04
mean 2.180549 22.791334 2.016330e+10
std 0.966955 20.750063 5.944854e+06
min 1.000000 1.000000 2.015110e+10
25% 1.000000 9.000000 2.016042e+10
50% 2.000000 15.000000 2.016093e+10
75% 3.000000 29.000000 2.017023e+10
max 4.000000 180.000000 2.017063e+10,
2
None)
[ ]: data['DateTime'] = pd.to_datetime(data['DateTime'])
data['Weekday'] = [datetime.weekday(date) for date in data.DateTime]
data['Year'] = [date.year for date in data.DateTime]
data['Month'] = [date.month for date in data.DateTime]
data['Day'] = [date.day for date in data.DateTime]
data['Hour'] = [date.hour for date in data.DateTime]
data['Week'] = [date.week for date in data.DateTime]
data['Quarter'] = [date.quarter for date in data.DateTime]
data["IsWeekend"] = data["Weekday"] >= 5
data.head(10)
3
if (data.isnull().sum()).sum() != 0 :
# Fill Missing Values with Forward Fill (Previous Row Value as␣
Current Row in Table) :
,→
if "Forward_Fill" in fill_types :
data[ column ] = data[ column ].ffill(axis = 0)
# Fill Missing Values with Backward Fill (Next Row Value as Current␣
,→Row in Table) :
if "Backward_Fill" in fill_types :
data[ column ] = data[ column ].bfill(axis = 0)
return data
fill_types = [ "Forward_Fill"]
fill_value = 0
data.isna().sum()
[ ]: DateTime 0
Junction 0
Vehicles 0
ID 0
Weekday 0
Year 0
Month 0
Day 0
Hour 0
Week 0
4
Quarter 0
IsWeekend 0
dtype: int64
[ ]: junction_1 = data[data["Junction"]==1]
junction_2 = data[data["Junction"]==2]
junction_3 = data[data["Junction"]==3]
junction_4 = data[data["Junction"]==4]
statistique descriptive
[ ]: i = 1
print("Junction",i,"\n")
print("Std: ",junction['Vehicles'].std())
print("Skewness: ",junction['Vehicles'].skew())
print("Kurtosis: ",junction['Vehicles'].kurt(),"\n\n")
print("Mean: ",junction['Vehicles'].mean())
print("Median: ",junction['Vehicles'].median())
print("Min: ",junction['Vehicles'].min())
print("Max: ",junction['Vehicles'].max() , end='\n')
print("___", end='\n')
i+=1
Junction 1
Std: 23.0083451392927
Skewness: 0.8012975778113662
Kurtosis: 0.19188209363777453
Mean: 45.05290570175438
Median: 40.0
Min: 5
Max: 156
___
5
Junction 2
Std: 7.401306635266316
Skewness: 1.2873364898588882
Kurtosis: 1.783596555414265
Mean: 14.253220942982455
Median: 13.0
Min: 1
Max: 48
___
Junction 3
Std: 10.436005075710996
Skewness: 3.490206183724324
Kurtosis: 27.36437504960055
Mean: 13.694010416666666
Median: 11.0
Min: 1
Max: 180
___
Junction 4
Std: 3.5214545458330613
Skewness: 1.3326967458513121
Kurtosis: 4.737325243604408
Mean: 7.251611418047882
Median: 7.0
Min: 1
Max: 36
___
Junction 1:
Moyenne (Mean): Environ 45.05 véhicules par heure.—- Médiane (Median): 40 véhicules par
heure.—- Écart-type (Std): Environ 23.01, indiquant une certaine variabilité.— Skewness: 0.80,
ce qui suggère une légère asymétrie positive.— Kurtosis: 0.19, indiquant une légère pointe.—-
Junction 2:
Moyenne (Mean): Environ 14.25 véhicules par heure.—- Médiane (Median): 13 véhicules par
heure.—– Écart-type (Std): Environ 7.40, montrant une variabilité modérée.—– Skewness: 1.29, in-
diquant une asymétrie positive plus prononcée.—- Kurtosis: 1.78, montrant une pointe plus pronon-
cée.
6
Junction 3
Moyenne (Mean): Environ 13.69 véhicules par heure.—- Médiane (Median): 11 véhicules par
heure.—- Écart-type (Std): Environ 10.44, indiquant une variabilité plus importante.—– Skew-
ness: 3.49, montrant une asymétrie positive très prononcée.—– Kurtosis: 27.36, indiquant une
pointe extrêmement prononcée.
Junction 4:
Moyenne (Mean): Environ 7.25 véhicules par heure.——- Médiane (Median): 7 véhicules par
heure.—— Écart-type (Std): Environ 3.52, montrant une faible variabilité.—— Skewness: 1.33,
indiquant une asymétrie positive prononcée.——- Kurtosis: 4.74, montrant une pointe modérée.
Tendances des junctions
Évolution du trafic au fil du temps
Nous visualisons ici comment le trafic évolue dans chacun de nos junctions au fil du temps. Chaque
graphique représente le nombre de véhicules observés, avec une courbe pour les données réelles
et une autre pour la moyenne mobile sur une fenêtre de 30 jours. Cela nous permet de voir les
tendances générales du trafic en atténuant les variations à court terme. Ces graphiques nous aident
à comprendre comment le trafic fluctue dans nos carrefours au fil des années et des mois.
[ ]: sns.set(rc={'figure.figsize':(18, 10)})
plt.xlabel("Year/Month")
plt.ylabel("Vehicles")
plt.legend()
plt.show()
7
8
• Une série temporelle est considérée comme stationnaire lorsqu’elle ne présente pas de ten-
dance claire. Cependant, dans notre analyse exploratoire des données, nous avons identifié
une saisonnalité hebdomadaire ainsi qu’une tendance à la hausse au fil des années. Cette
observation est confirmée par le graphique ci-dessus, soulignant spécifiquement une tendance
à la hausse pour les carrefours 1 et 2. Pour mieux visualiser la saisonnalité hebdomadaire,
9
il serait bénéfique de limiter la période d’observation. Cela nous permettra d’analyser plus
précisément les variations sur une base hebdomadaire.
Exemple decomposition pour la junction 1
time_series_data = junction_1.Vehicles
,→saisonnalité et le résidu.
result.plot()
[ ]:
10
• Cette décomposition permet d’analyser visuellement la tendance et la saisonnalité présentes
dans la série temporelle de la jonction 1.
• La période saisonnière de 24 heures suggère que la série temporelle présente une saisonnalité
quotidienne.
• La composante de tendance montre que la série temporelle présente une tendance globale à la
hausse
• La visualisation de ces composantes peut aider à mieux comprendre la structure temporelle
des données et à prendre des décisions éclairées pour la modélisation ultérieure.
[ ]:
junctions_tuple = data.groupby('Junction')
x = np.arange(len(junction_data))
x = sm.add_constant(x)
11
model = sm.OLS(junction_data['Vehicles'], x).fit()
trend_slope = model.params[1]
trend_intercept = model.params[0]
plt.figure(figsize=(15, 4))
plt.subplot(1, 2, 1)
plt.plot(junction_data['DateTime'], junction_data['Vehicles'], label='Data')
plt.plot(junction_data['DateTime'], trend_slope * x[:, 1] + trend_intercept,␣
,→label='Trend', color='red')
plt.xlabel('Date')
plt.ylabel('Vehicle Count')
plt.title(f'Junction {junction_id} - Trend Analysis')
plt.legend()
plt.subplot(1, 2, 2)
plt.plot(junction_data['DateTime'], detrended_data, label='Noise',␣
,→color='green')
plt.xlabel('Date')
plt.ylabel('Noise')
plt.title(f'Junction {junction_id} - Noise Examination')
plt.legend()
seasonal_period = 24*90
decomposition = seasonal_decompose(junction_data['Vehicles'],␣
,→period=seasonal_period)
seasonal_component = decomposition.seasonal
# plt.figure(figsize=(15, 4))
# plt.plot(junction_data['DateTime'], seasonal_component, label='Seasonal␣
,→Component', color='blue')
# plt.xlabel('Date')
# plt.ylabel('Seasonal Component')
# plt.title(f'Junction {junction_id} - Seasonal Component Analysis')
# plt.legend()
plt.tight_layout()
plt.show()
seasonal_mean = np.mean(seasonal_component)
seasonal_std = np.std(seasonal_component)
print(f'Junction {junction_id} - Seasonal Mean: {seasonal_mean}')
print(f'Junction {junction_id} - Seasonal Standard Deviation:␣
,→{seasonal_std}')
12
mean_noise = np.mean(detrended_data)
std_noise = np.std(detrended_data)
print(f'Junction {junction_id} - Trend Slope: {trend_slope}')
print(f'Junction {junction_id} - Trend Intercept: {trend_intercept}')
print(f'Junction {junction_id} - Mean Noise: {mean_noise}')
print(f'Junction {junction_id} - Standard Deviation of Noise: {std_noise}')
13
Junction 3 - Seasonal Mean: -0.10288614422958331
Junction 3 - Seasonal Standard Deviation: 6.525518378313682
Junction 3 - Trend Slope: 0.0007725622288921175
Junction 3 - Trend Intercept: 8.057782675784228
Junction 3 - Mean Noise: -4.549966641270817e-15
Junction 3 - Standard Deviation of Noise: 9.915254195083062
14
• Trend Intercept (Interception de la tendance) - 5.7684 :
L’interception de la tendance représente la valeur initiale de la série temporelle.
Pour Junction 2, cette valeur de départ est d’environ 5.7684, indiquant le point de départ de la série
temporelle.
• Mean Noise (Moyenne du bruit) - Proche de 0 :
La moyenne du bruit représente la moyenne statistique des fluctuations imprévisibles dans les don-
nées.
Une moyenne proche de zéro indique que le bruit est centré autour de la moyenne globale des
données.
• Standard Deviation of Noise (Écart type du bruit) - 5.5475 :
L’écart type mesure la variabilité des données.
La valeur d’environ 5.5475 indique que le bruit présente une certaine variabilité au-dessus et en
dessous de la moyenne.
$$
Nous traçons la distribution du nombre de véhicules à chaque intersection sous la forme
d’un histogramme (graphique de distribution de fréquence).
print()
Junction # 1
weekday vehicle mean 49.76685823754789
weekend vehicle mean 33.19990366088632
Junction # 2
weekday vehicle mean 15.834291187739463
weekend vehicle mean 10.277697495183045
15
Junction # 3
weekday vehicle mean 13.793199233716475
weekend vehicle mean 13.44460500963391
Junction # 4
weekday vehicle mean 7.648397435897436
weekend vehicle mean 6.240196078431373
Cols = range(24)
Index = ["Mon","Tue","Wed","Thu","Fri","Sat","Sun"]
junction_map = pd.DataFrame(data=junction_map.to_numpy(),index=Index,␣
,→columns=Cols)
ax = sns.heatmap(junction_map,cmap="Reds")
ax.set(xlabel='Hour', ylabel='Weekday')
ax.set_title('Hour-Weekday Relation of Junction %d'%(i+1))
16
ax.invert_yaxis()
plt.show()
17
18
Pour la Jonction 1 et 2,de 10h à 23h, les colonnes présentent une intensité de couleur très marquée
tout au long de la semaine, à l’exception du week-end. Cette forte concentration de rouge suggère
une activité significative de circulation pendant ces heures spécifiques en semaine. La diminution
notable du rouge pendant le week-end pourrait indiquer une réduction des déplacements ou une
dynamique différente de trafic pendant cette période.
Pour la Jonction 3 ,un pic significatif de trafic est observé le samedi entre 19h et 23h, représenté
par des colonnes très rouges. En comparaison, les autres jours montrent une activité modérée, avec
une diminution notable entre 1h et 9h du matin.
la Jonction 4 montre une activité routière constante et élevée tout au long de la journée, avec une
diminution marquée tôt le matin entre 3 heures et 8 heures du matin.
[ ]:
[ ]: corr = data.corr()
f, ax = plt.subplots(figsize=(16, 7))
sns.heatmap(corr, annot=True, fmt='.2f', vmin=-1, vmax=1, square=True,␣
,→linewidths=1)
<ipython-input-26-75d069209dab>:1: FutureWarning:
19
Cette visualisation offre un aperçu visuel des corrélations entre les variables du notre dataset.
Des valeurs proches de 1 indiquent une forte corrélation positive, telles que la corrélation de 0,97
entre “month” et “quarter”, suggérant une relation linéaire positive presque parfaite entre ces deux
variables. À l’inverse, des valeurs proches de -1, comme la corrélation de -0,61 entre “junction”
et “vehicles”, signalent une relation inverse. Cela peut signifier, par exemple, que le nombre de
véhicules a tendance à diminuer lorsque la jonction change. Des corrélations proches de 0 indiquent
une faible corrélation entre les variables.
2 Analyse de la variance
[ ]: !pip install scikit-posthocs
20
stat, p_value = kstest(data['Vehicles'], 'norm')
21
alpha = 0.05
if p_value > alpha:
print("Homogénéité des variances (l'hypothèse nulle n'est pas rejetée)")
else:
print("Non homogène des variances (l'hypothèse nulle est rejetée)")
22
[ ]: import seaborn as sns
import matplotlib.pyplot as plt
On observe que les boîtes des jonctions 2 et 4 ont une dispersion similaire avec des médianes proches
et des quartiles similaires, cela suggère en effet une similitude dans la distribution du nombre de
véhicules entre ces deux jonctions. le nombre de véhicules dans la jonction 1 est significativement
plus élevé que dans les autres jonctions, cela pourrait indiquer que la jonction 1 est plus fréquentée
3 Modélisation Prédictive :
A ce stade nous allons entrainer et tester notre modele de prediction, pour juger sa
validité pour des previsions futures
23
[ ]: #importons les biblothques necessaires
[ ]: df = pd.read_csv("/train_ML_IOT.csv")
df = df[df['Junction'] == 1]
df = df.drop(['Junction', 'ID'], axis=1)
df = df.set_index('DateTime')
df.index = pd.to_datetime(df.index)
[ ]: df.plot(style='.',
figsize=(15, 5),
color=color_pal[0],
title='Traffic for Junction 1')
plt.show()
[ ]: df['Vehicles'].plot(kind='hist', bins=500)
[ ]: <Axes: ylabel='Frequency'>
24
On observe une distribution asymétrique dans l’histogramme, suggérant que les données sur le
nombre de véhicules ne suivent pas une distribution parfaitement équilibrée. De plus, la présence
de barres isolées et d’occurrences très faibles au-delà de 130 indique la présence potentielle de valeurs
aberrantes.
On représente graphiquement les points de données où le nombre de véhicules est supérieur à 130
25
Nous identifions ici des points de données extrêmes , caractérisés par des valeurs nettement dif-
férentes de la tendance globale des données. Ces points, que l’on qualifie de valeurs aberrantes, se
distinguent par leur écart significatif par rapport à la tendance générale observée dans l’ensemble
des données.
On filtre les données pour exclure les lignes où le nombre de véhicules est égal ou supérieur à 130,
considérant ainsi les valeurs au-dessus de ce seuil comme des points de données aberrants.
[ ]: Vehicles
DateTime
2015-11-01 00:00:00 15
2015-11-01 01:00:00 13
2015-11-01 02:00:00 10
2015-11-01 03:00:00 7
2015-11-01 04:00:00 9
... ...
2017-06-30 19:00:00 105
2017-06-30 20:00:00 96
2017-06-30 21:00:00 90
2017-06-30 22:00:00 84
2017-06-30 23:00:00 78
[ ]:
Division des données avant et après le 31 mai 2017, et l’affichage de la division dans un graphique.
26
[ ]:
Validation croisée temporelle (Time Series Cross Validation) : Nous utilisons TimeSeriesS-
plit pour diviser les données en plis temporels, et nous affichons ces plis.
Diviser un ensemble de données en seulement des ensembles d’entraînement et de test
peut entraîner le surajustement du modèle, car certaines données ne sont pas utilisées
dans l’entraînement. Dans ce cas, la validation croisée (CV) divise les données en
plusieurs sous-ensembles (plis) et utilise chaque sous-ensemble séquentiellement comme
ensemble de test. Ainsi, chaque élément de données participe à l’entraînement et aux
tests au moins une fois.
fold = 0
for train_idx, val_idx in tss.split(df):
train = df.iloc[train_idx]
test = df.iloc[val_idx]
train['Vehicles'].plot(ax=axs[fold],
label='Training Set',
title=f'Data Train/Test Split Fold {fold}')
test['Vehicles'].plot(ax=axs[fold],
label='Test Set')
axs[fold].axvline(test.index.min(), color='black', ls='--')
fold += 1
plt.show()
27
test
[ ]: Vehicles
DateTime
2017-05-31 21:00:00 89
2017-05-31 22:00:00 85
2017-05-31 23:00:00 83
2017-06-01 00:00:00 80
2017-06-01 01:00:00 71
... ...
2017-06-30 19:00:00 105
2017-06-30 20:00:00 96
2017-06-30 21:00:00 90
28
2017-06-30 22:00:00 84
2017-06-30 23:00:00 78
[ ]:
Création de caractéristiques :
L’augmentation des fonctionnalités en utilisant des dérivées de l’index temporel, comme l’heure, le
jour de la semaine, le trimestre, le mois, l’année, etc.
Nous ajoutons de nouvelles caractéristiques dérivées de l’index temporel pour enrichir nos données
et les utiliser dans la suite du travail.
[ ]: def create_features(df):
"""
Create time series features based on time series index.
"""
df = df.copy()
df['hour'] = df.index.hour
df['dayofweek'] = df.index.dayofweek
df['quarter'] = df.index.quarter
df['month'] = df.index.month
df['year'] = df.index.year
df['dayofyear'] = df.index.dayofyear
df['dayofmonth'] = df.index.day
df['weekofyear'] = df.index.isocalendar().week
return df
df = create_features(df)
df
29
2015-11-01 00:00:00 305 1 44
2015-11-01 01:00:00 305 1 44
2015-11-01 02:00:00 305 1 44
2015-11-01 03:00:00 305 1 44
2015-11-01 04:00:00 305 1 44
... ... ... ...
2017-06-30 19:00:00 181 30 26
2017-06-30 20:00:00 181 30 26
2017-06-30 21:00:00 181 30 26
2017-06-30 22:00:00 181 30 26
2017-06-30 23:00:00 181 30 26
[ ]: def add_lags(df):
target_map = df['Vehicles'].to_dict() # target = Vehicles
df['lag1'] = (df.index - pd.Timedelta('24 hours')).map(target_map)
print(df['lag1'])
df['lag2'] = (df.index - pd.Timedelta('48 hours')).map(target_map)
print(df['lag2'])
df['lag3'] = (df.index - pd.Timedelta('72 hours')).map(target_map)
print(df['lag3'])
return df
target_map = df['Vehicles'].to_dict() # target = Vehicles
df = add_lags(df)
DateTime
2015-11-01 00:00:00 NaN
2015-11-01 01:00:00 NaN
2015-11-01 02:00:00 NaN
2015-11-01 03:00:00 NaN
2015-11-01 04:00:00 NaN
...
2017-06-30 19:00:00 113.0
2017-06-30 20:00:00 110.0
2017-06-30 21:00:00 101.0
2017-06-30 22:00:00 96.0
2017-06-30 23:00:00 95.0
Name: lag1, Length: 14580, dtype: float64
DateTime
2015-11-01 00:00:00 NaN
2015-11-01 01:00:00 NaN
2015-11-01 02:00:00 NaN
2015-11-01 03:00:00 NaN
2015-11-01 04:00:00 NaN
...
2017-06-30 19:00:00 124.0
2017-06-30 20:00:00 112.0
30
2017-06-30 21:00:00 102.0
2017-06-30 22:00:00 96.0
2017-06-30 23:00:00 96.0
Name: lag2, Length: 14580, dtype: float64
DateTime
2015-11-01 00:00:00 NaN
2015-11-01 01:00:00 NaN
2015-11-01 02:00:00 NaN
2015-11-01 03:00:00 NaN
2015-11-01 04:00:00 NaN
...
2017-06-30 19:00:00 124.0
2017-06-30 20:00:00 121.0
2017-06-30 21:00:00 111.0
2017-06-30 22:00:00 98.0
2017-06-30 23:00:00 98.0
Name: lag3, Length: 14580, dtype: float64
Prédiction avec le modele XGBOOST :
fold = 0
preds = []
scores = []
scores_r2 = []
for train_idx, val_idx in tss.split(df):
train = df.iloc[train_idx]
test = df.iloc[val_idx]
train = create_features(train)
test = create_features(test)
X_train = train[FEATURES]
y_train = train[TARGET]
X_test = test[FEATURES]
y_test = test[TARGET]
31
objective='reg:linear',
max_depth=3,
learning_rate=0.01)
reg.fit(X_train, y_train,
eval_set=[(X_train, y_train), (X_test, y_test)],
verbose=100)
y_pred = reg.predict(X_test)
preds.append(y_pred)
score = np.sqrt(mean_squared_error(y_test, y_pred))
score_r2 = r2_score(y_test, y_pred)
scores_r2.append(score_r2)
scores.append(score)
32
/usr/local/lib/python3.10/dist-packages/xgboost/core.py:160: UserWarning:
[23:26:28] WARNING: /workspace/src/objective/regression_obj.cu:209: reg:linear
is now deprecated in favor of reg:squarederror.
warnings.warn(smsg, UserWarning)
[200] validation_0-rmse:9.20359 validation_1-rmse:14.63685
[300] validation_0-rmse:6.65322 validation_1-rmse:9.42352
[400] validation_0-rmse:5.99378 validation_1-rmse:8.12358
[500] validation_0-rmse:5.74498 validation_1-rmse:7.67068
[600] validation_0-rmse:5.62773 validation_1-rmse:7.49401
[700] validation_0-rmse:5.53594 validation_1-rmse:7.39162
[800] validation_0-rmse:5.43512 validation_1-rmse:7.32979
[900] validation_0-rmse:5.34247 validation_1-rmse:7.25516
[999] validation_0-rmse:5.26145 validation_1-rmse:7.20366
[0] validation_0-rmse:45.94239 validation_1-rmse:72.50179
[100] validation_0-rmse:18.56933 validation_1-rmse:34.43908
/usr/local/lib/python3.10/dist-packages/xgboost/core.py:160: UserWarning:
[23:26:34] WARNING: /workspace/src/objective/regression_obj.cu:209: reg:linear
is now deprecated in favor of reg:squarederror.
warnings.warn(smsg, UserWarning)
[200] validation_0-rmse:9.39631 validation_1-rmse:20.44075
[300] validation_0-rmse:6.73683 validation_1-rmse:14.85433
[400] validation_0-rmse:6.08245 validation_1-rmse:12.82178
[500] validation_0-rmse:5.84305 validation_1-rmse:11.95146
[600] validation_0-rmse:5.72337 validation_1-rmse:11.48660
[700] validation_0-rmse:5.63102 validation_1-rmse:11.20053
[800] validation_0-rmse:5.53206 validation_1-rmse:11.18978
[900] validation_0-rmse:5.43868 validation_1-rmse:11.15002
[990] validation_0-rmse:5.36324 validation_1-rmse:11.15003
[0] validation_0-rmse:47.61980 validation_1-rmse:76.87245
[100] validation_0-rmse:19.29965 validation_1-rmse:36.65566
/usr/local/lib/python3.10/dist-packages/xgboost/core.py:160: UserWarning:
[23:26:36] WARNING: /workspace/src/objective/regression_obj.cu:209: reg:linear
is now deprecated in favor of reg:squarederror.
warnings.warn(smsg, UserWarning)
[200] validation_0-rmse:9.79066 validation_1-rmse:21.45403
[300] validation_0-rmse:7.05655 validation_1-rmse:14.20530
[400] validation_0-rmse:6.32166 validation_1-rmse:11.21340
[500] validation_0-rmse:6.04414 validation_1-rmse:9.49877
[600] validation_0-rmse:5.90016 validation_1-rmse:8.89502
[700] validation_0-rmse:5.79814 validation_1-rmse:8.58045
[800] validation_0-rmse:5.70837 validation_1-rmse:8.37385
[900] validation_0-rmse:5.62641 validation_1-rmse:8.22018
[999] validation_0-rmse:5.55078 validation_1-rmse:8.10271
33
[ ]: test['prediction'] = y_pred
y_test_ = pd.DataFrame(y_test)
y_test_ = y_test_.merge(test[['prediction']], how='left', left_index=True,␣
,→right_index=True)
ax = y_test_[['Vehicles']].plot(figsize=(15, 5))
y_test_['prediction'].plot(ax=ax, style='.')
plt.legend(['Truth Data', 'Predictions'])
ax.set_title('Raw Dat and Prediction')
plt.show()
[ ]: y_test_['prediction'] = y_pred
ax = y_test_[['Vehicles', 'prediction']].plot(figsize=(15, 5))
plt.legend(['Truth Data', 'Predictions'])
ax.set_title('Raw Data and Prediction')
plt.show()
34
print(f'R2 Score across folds {scores_r2}', end='\n')
print(f'R2 Score across folds {np.mean(scores_r2):0.4f}', end='\n')
35
KHAWLA_REGRESSION
December 3, 2023
[ ]: import numpy as np
import pandas as pd
import os
for dirname, _, filenames in os.walk('/kaggle/input'):
for filename in filenames:
print(os.path.join(dirname, filename))
[ ]: import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import missingno as msno
import seaborn as sns
from datetime import datetime
from scipy.stats import skew
from scipy.stats import kurtosis
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import r2_score
[ ]: train = pd.read_csv("/train_ML_IOT.csv")
[ ]: j1=train[train["Junction"]==1].Vehicles.to_numpy()
j2=train[train["Junction"]==2].Vehicles.to_numpy()
js = [j1, j2]
1
for i in range(len(dataset)-look_back-1):
a = dataset[i:(i+look_back), 0]
X.append(a)
Y.append(dataset[i + look_back, 0])
return np.array(X), np.array(Y)
rows_train = X_train.shape[0]
cols_train = X_train.shape[2]
rows_test = X_test.shape[0]
cols_test = X_test.shape[2]
[ ]: def feature_extraction(X):
length = X.shape[0]
feature_min = np.min(X, axis=1).reshape(length,1)
feature_max = np.max(X, axis=1).reshape(length,1)
feature_median = np.median(X, axis=1).reshape(length,1)
feature_mean = np.mean(X, axis=1).reshape(length,1)
feature_var = np.var(X, axis=1).reshape(length,1)
feature_energy = np.sum(X**2, axis=1).reshape(length,1)
feature_skew = skew(X, axis=1).reshape(length,1)
feature_kurt = kurtosis(X, axis=1).reshape(length,1)
2
[ ]: look_back = [12,24,48,72,168]
[ ]: mae_mat_forest = np.zeros((len(js),len(look_back)))
mape_mat_forest = np.zeros((len(js),len(look_back)))
r2_mat_forest = np.zeros((len(js),len(look_back)))
mae_mat_tree = np.zeros((len(js),len(look_back)))
mape_mat_tree = np.zeros((len(js),len(look_back)))
r2_mat_tree = np.zeros((len(js),len(look_back)))
Y_pred = regressor.predict(X_test_feat)
Y_pred = scaler.inverse_transform(Y_pred.reshape(-1,1)).reshape(-1)
Y_test = scaler.inverse_transform(Y_test.reshape(-1,1)).reshape(-1)
sns.set(rc={'figure.figsize':(16, 4)})
plt.title('Random Forest Regressor for Junction ' + str(i+1) + " |␣
↪Window Size = " + str(m))
tree_regressor = DecisionTreeRegressor(max_depth=5)
tree_regressor.fit(X_train_feat, Y_train)
Y_pred = tree_regressor.predict(X_test_feat)
Y_pred = scaler.inverse_transform(Y_pred.reshape(-1,1)).reshape(-1)
3
mape_mat_tree[i][k] = np.mean(np.abs((Y_test - Y_pred)/Y_test))*100
r2_mat_tree[i][k] = r2_score(Y_test, Y_pred)
sns.set(rc={'figure.figsize':(16, 4)})
plt.title('Decision Tree Regressor for Junction ' + str(i+1) + " |␣
↪Window Size = " + str(m))
plt.plot(Y_test[0:200], label="actual")
plt.plot(Y_pred[2:202], label="prediction")
plt.legend()
plt.show()
4
5
6
7
8
On calcule R2 et l’erreur absolue moyenne (MAE) pour la régression par forêt aléatoire (Random
Forest Regression)
axs[1].axis("off")
axs[1].title.set_text('Mean Absolute Percentage Error (Random Forest)')
the_table = axs[1].table(cellText=mape_mat_forest, loc='center right',
rowLabels=[" 1 "," 2 "],colLabels=look_back)
#the_table.scale(2, 2)
axs[2].axis("off")
axs[2].title.set_text('R2 score (Random Forest)')
the_table = axs[2].table(cellText=r2_mat_forest, loc='center right',
rowLabels=[" 1 "," 2 "],colLabels=look_back)
#the_table.scale(2, 2)
plt.show()
9
Pour la jonction 1, le Mean Absolute Error (MAE) augmente légèrement à mesure que la fenêtre
temporelle augmente, passant de 17 à 22. Cela suggère que pour cette jonction, des fenêtres
temporelles plus courtes peuvent être plus appropriées, mais la performance reste relativement
stable.
Pour la jonction 2, le MAE reste assez constant autour de 6-7, indépendamment de la taille de la
fenêtre temporelle. Cela peut indiquer que cette jonction est moins sensible à la variation de la
fenêtre temporelle et que le modèle maintient une performance cohérente.
Le coefficient de détermination R2 pour les jonctions 1 et 2 est proche de zéro, cela suggère que
le modèle a du mal à expliquer les données. Les prédictions du modèle ne concordent pas de
manière significative avec les observations réelles, indiquant une performance limitée du modèle
pour représenter la variabilité des données.
On calcule R2 et l’erreur absolue moyenne (MAE) pour la régression par arbre de décision (Decision
10
Tree Regression)
axs[1].axis("off")
axs[1].title.set_text('Mean Absolute Percentage Error (Decision Tree)')
the_table = axs[1].table(cellText=mape_mat_tree, loc='center right',
rowLabels=[" 1 "," 2 "],colLabels=look_back)
#the_table.scale(2, 2)
axs[2].axis("off")
axs[2].title.set_text('R2 score (Decision Tree)')
the_table = axs[2].table(cellText=r2_mat_tree, loc='center right',
rowLabels=[" 1 "," 2 "],colLabels=look_back)
#the_table.scale(2, 2)
plt.show()
11
De même pour ce cas, le coefficient de détermination R2 est très proche de zéro pour la régression
par arbre de décision suggère que ce modèle spécifique éprouve des difficultés à expliquer les données.
Les prédictions générées par l’arbre de décision ne s’alignent pas de manière significative avec les
observations réelles, ce qui indique une faible performance prédictive.
Conclusion:
En conclusion, après avoir comparé trois modèles - XGBoost, la régression par arbre de décision et
la régression par forêt aléatoire , il est observé que XGBoost se distingue comme le modèle le plus
performant pour faire les prévisions.
12