<jupyter_start><jupyter_text>Descriptif du projet :Le projet consiste à prévoir le nombre de vélos loués à chaque heure dans des bornes libres-services de la ville (système type Vélib'). La variable cible est ici la variable **count**<jupyter_code># Ignorer les avertissements
import warnings
warnings.filterwarnings('always')
warnings.filterwarnings('ignore')

import pandas as pd
import numpy as np

import matplotlib.pyplot as plt
import seaborn as sns

%matplotlib inline<jupyter_output><empty_output><jupyter_text>Descriptif de l'ensemble des variables :* *datetime* - date et heure du relevé * *season* - 1 = printemps , 2 = été, 3 = automne, 4 = hiver * *holiday* – indique si le jour est un jour de vacances scolaires * *workingday* - indique si le jour est travaillé (ni week-end ni vacances) * *weather* - 1: Dégagé à nuageux, 2 : Brouillard, 3 : Légère pluie ou neige, 4 : Fortes averses ou neiges * *temp* – température en degrés Celsius * *atemp* – température ressentie en degrés Celsius * *humidity* – taux d’humidité * *windspeed* – vitesse du vent * *casual* - nombre de locations d’usagers non abonnés * *registered* – nombre de locations d’usagers abonnés * *count* – nombre total de locations de vélos  Quel type de problème dois-je traiter : Il s'agit ici d'un problème de prédiction, par apprentissage supervisé.La valeur à prédire est réelle.<jupyter_code>df = pd.read_csv("./data/velo.csv")
df.head(10)<jupyter_output><empty_output><jupyter_text>Ici, toutes les variables ou features sont numériques et la variable cible que nous avons à prédire est la variable COUNT. C’est donc un cas typique d’un problème de régression puisque la variable COUNT est une variable continue.<jupyter_code>df.info()
df.isnull().sum()  # Pas de valeur nulle dans notre jeu de données, donc pas d'imputation nécessaire.<jupyter_output><empty_output><jupyter_text>ExplorationMaintenant, nous pouvons explorer nos variables. Premièrement, explorons la distribution des diverses variables discrètes comme le temps, la saison, etc ....<jupyter_code># considérons la saison.
df.season.value_counts()
#sns.factorplot(x='season',data=df,kind='count',size=5,aspect=1)
sns.catplot(x='season',data=df,kind='count',height=5,aspect=1.5)
#holiday
df.holiday.value_counts()
sns.catplot(x='holiday',data=df,kind='count',height=5,aspect=1)<jupyter_output><empty_output><jupyter_text>Nous remarquons que la majorité des données concerne les jours non fériés (Pas de vacance scolaire).<jupyter_code>#workingday
df.workingday.value_counts()
sns.catplot(x='workingday',data=df,kind='count',height=5,aspect=1)<jupyter_output><empty_output><jupyter_text>La majorité des données concerne les jours ouvrables (travaillés).<jupyter_code>#weather
df.weather.value_counts()
sns.catplot(x='weather',data=df,kind='count',height=5,aspect=1)  
# 1-> Dégagé à nuageux
# 2-> Brouillard
# 3-> Légère pluie ou neige
# 4-> Fortes averses ou neiges<jupyter_output><empty_output><jupyter_text>Maintenant, nous pouvons également voir la distribution de variables continues.<jupyter_code>df.describe()<jupyter_output><empty_output><jupyter_text>Visualisation du diagramme à moustache des variables continues<jupyter_code>sns.boxplot(data=df[['temp',
       'atemp', 'humidity', 'windspeed', 'casual', 'registered', 'count']])
fig=plt.gcf()
fig.set_size_inches(10,10)<jupyter_output><empty_output><jupyter_text>Peut également être visualisée à l'aide d'histogrammes pour toutes les variables continues<jupyter_code>df.temp.unique()
fig,axes=plt.subplots(2,2)
axes[0,0].hist(x="temp",data=df,edgecolor="black",linewidth=2,color='#ff4125')
axes[0,0].set_title("Variation de la température")
axes[0,1].hist(x="atemp",data=df,edgecolor="black",linewidth=2,color='#ff4125')
axes[0,1].set_title("Variation de la température ressentie")
axes[1,0].hist(x="windspeed",data=df,edgecolor="black",linewidth=2,color='#ff4125')
axes[1,0].set_title("Variation de la vitesse du vent")
axes[1,1].hist(x="humidity",data=df,edgecolor="black",linewidth=2,color='#ff4125')
axes[1,1].set_title("Variation de l'hummidité")
fig.set_size_inches(10,10)<jupyter_output><empty_output><jupyter_text>Maintenant que nous avons visualisé les distributions des variables continues et discrètes, nous allons analyser la corrélation qui existe entre elles à l'aide d'une matrice de corrélation.<jupyter_code>#Matrice de corrélation.
cor_mat= df[:].corr()
mask = np.array(cor_mat)
mask[np.tril_indices_from(mask)] = False
fig=plt.gcf()
fig.set_size_inches(30,12)
sns.heatmap(data=cor_mat,mask=mask,square=True,annot=True,cbar=True)<jupyter_output><empty_output><jupyter_text>Analyse de la matrice de corrélation (HeatMap) ci dessus :* *temp* et *atemp* sont très liés comme prévu.* L'humidité *(humidity)* est inversement proportionnelle au nombre total de locations de vélos *(count)*, car quand le  temps est humide, les gens n'aiment pas voyager à vélo.* Le nombre de locations d'usagers non abonnés *(casual)* et le jour travaillé ou pas *(workingday)* sont très inversement liés, comme on peut s'y attendre.* Nous notons également que la température *temp (ou atemp)* influe fortement sur le nombre total de locations de vélos *(count)*.* Notons également que la météo *(weather)* et le nombre total de locations de vélos *(count)* sont très inversement liés. C’est une bonne donnée, car les conditions météorologiques augmentent de (1 à 4), ce qui signifie que plus les conditions météorologiques s’aggravent, moins de gens louent des vélos.* Enregistrés/occasionnels *(registered/casual)* et le nombre total de locations de vélos *(count)* sont très liés, ce qui indique que la plupart des vélos loués sont enregistrés.* De même, nous pouvons tirer d'autres conclusions comme le temps qu'il fait, l'humidité, etc.  Features engineeringNous allons procéder à la transformation de certaines variables afin d'obtenir de nouvellesvariables pertinentes ou moins pertinentes. Dans l'optique d'améliorer les fonctionnalités, séparons selon les valeurs les variables suivantes :* *season,** *weather*Chacune de cesvariables possèdent 04 modalités distinctes.<jupyter_code>#season
season=pd.get_dummies(df['season'],prefix='season')
df=pd.concat([df,season],axis=1)
#weather
weather=pd.get_dummies(df['weather'],prefix='weather')
df=pd.concat([df,weather],axis=1)
df.head(2)
# Nous pouvons maintenant supprimer les variables weather et season.
df.drop(['season','weather'],inplace=True,axis=1)
df.head(2)<jupyter_output><empty_output><jupyter_text>Maintenant, nous allons segmenter la date et l’heure car il est prévu que l’heure de la journée affecte le nombre total de locations de vélos *(count)*. par exemple, aux heures de bureau comme tôt le matin ou le soir, on peut s'attendre à une plus forte demande de vélos à location .<jupyter_code>df["hour"] = [t.hour for t in pd.DatetimeIndex(df.datetime)]
df["day"] = [t.dayofweek for t in pd.DatetimeIndex(df.datetime)] 
df["month"] = [t.month for t in pd.DatetimeIndex(df.datetime)]
df['year'] = [t.year for t in pd.DatetimeIndex(df.datetime)]
df['year'] = df['year'].map({2011:0, 2012:1})
df.head()<jupyter_output><empty_output><jupyter_text>Important : Notre modèle fonctionne avec les jours de la semaine:* 1 : Lundi,* 2 : Mardi,* 3 : Mercredi,* 4 : Jeudi,* 5 : Vendredi,* 6 : Samedi,* 0 : Dimanche.<jupyter_code># Nous pouvons maintenant supprimer la variable datetime.
df.drop('datetime',axis=1,inplace=True)
df.head(2)<jupyter_output><empty_output><jupyter_text>Regardons maintenant les corrélations entre les nouvelles Variables (Features)<jupyter_code>cor_mat= df[:].corr()
mask = np.array(cor_mat)
mask[np.tril_indices_from(mask)] = False
fig=plt.gcf()
fig.set_size_inches(30,12)
sns.heatmap(data=cor_mat,mask=mask,square=True,annot=True,cbar=True)<jupyter_output><empty_output><jupyter_text>L'analyse de la matrice de corrélation (HeatMap) ci dessus montre que les features suivantes sont trop explicatives:* *casual* : correlé à ~ 70% avec le nombre total de locations de vélos *(count)** *registered* : correlé à ~ 97% avec le nombre total de locations de vélos *(count)*Nous procédons donc à la suppression de ces variables.<jupyter_code>df.drop(['casual','registered'],axis=1,inplace=True)
df.head(3)<jupyter_output><empty_output><jupyter_text>Voyons maintenant comment le nombre total de locations de vélos (count) varie selon les variables<jupyter_code># avec la variable hour
sns.catplot(x="hour",y="count",data=df,kind='bar',height=5,aspect=1.5)<jupyter_output><empty_output><jupyter_text>Nous observons que les picks de demande les plus élévés se situent de 7 à 10 heures et de 15 à 19 heures. dans la plupart des villes métropolitaines, c’est l’heure de pointe pour les bureaux et plus de gens louent des vélos.ce n'est qu'une des raisons plausibles.<jupyter_code># avec la variable month
sns.catplot(x="month",y="count",data=df,kind='bar',height=5,aspect=1.5)<jupyter_output><empty_output><jupyter_text>Notons que le mois affecte la saison et que les gens prennent le vélo ou non. En fonction des conditions climatiques : Dégagé à nuageux, Brouillard, etc ...<jupyter_code># avec la variable year
sns.catplot(x="year",y="count",data=df,kind='bar',height=5,aspect=1.5)<jupyter_output><empty_output><jupyter_text>Nous constatons que le nombre total de locations de vélos (count) a donc augmenté entre 2011 et 2012:* 0 pour 2011,* 1 pour 2012.<jupyter_code># avec la variable day
sns.catplot(x="day",y='count',kind='bar',data=df,height=5,aspect=1)
# avec la variable temp
plt.scatter(x="temp",y="count",data=df,color='#ff4125')<jupyter_output><empty_output><jupyter_text>Notons que de cette façon, il est difficile de visualiser. un meilleur moyen est de convertir la variable *temp* en intervalles ou «bacs», puis de la traiter comme une variable discrète.<jupyter_code>new_df=df.copy()
new_df.temp.describe()
new_df['temp_bin']=np.floor(new_df['temp'])//5
new_df['temp_bin'].unique()
# now we can visualize as follows
sns.catplot(x="temp_bin",y="count",data=new_df,kind='bar')<jupyter_output><empty_output><jupyter_text>Nous remarquons que la demande est la plus forte pour les casiers 6 et 7, ce qui correspond aux températures 30 à 35 (cas 6) et 35 à 40 (cas 7).  Après avoir procédé aux phases d'exploration de données, d'analyse, de visualisation et de pré-traitement, nous pouvons passer à la modélisation.<jupyter_code>df.columns.to_series().groupby(df.dtypes).groups<jupyter_output><empty_output><jupyter_text>Afin de conserver l'ordre chronologique et la stabilité dans le jeu de données, nous allons procéder au classement de ces dernières. Classement par date, du tuple le plus ancien au plus récent, en tenant compte du poids des éléments temporels dans le tri *(hour-->day-->month-->year)*, à savoir trier séquentiellement et par ordre ascendant les variables suivantes :* L'heure *(hour),** Le jour *(day),** Le mois *(month),** L'année *(year).*<jupyter_code>df = df.sort_values(by=['year','month','day','hour'], ascending=[1,1,1,1])
#importer les algorithmes de modélisation nécessaires.

#regression
from sklearn.linear_model import LinearRegression,Ridge,Lasso,RidgeCV
from sklearn.ensemble import RandomForestRegressor,BaggingRegressor,GradientBoostingRegressor,AdaBoostRegressor
from sklearn.svm import SVR
from sklearn.neighbors import KNeighborsRegressor
from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import GradientBoostingRegressor

#selection des modèles
from sklearn.model_selection import train_test_split,cross_validate
from sklearn.model_selection import KFold
from sklearn.model_selection import GridSearchCV

#evaluation des métriques
from sklearn.metrics import mean_squared_log_error,mean_squared_error, r2_score,mean_absolute_error # Pour la regression<jupyter_output><empty_output><jupyter_text>Segmentation du jeu de données déjà trié en train et test :* 80% pour le train,* 20% pour le test.<jupyter_code>len(df)
train_size = int(len(df) * 0.80)
x_train, x_test = df[0:train_size], df[train_size:len(df)]
y_train, y_test = (df['count'])[0:train_size], (df['count'])[train_size:len(df)]
print('Observations dans le jeu de données : %d' % (len(df)))
print('Observations du Training : %d' % (len(x_train)))
print('Observations du test: %d' % (len(x_test)))
plt.plot(y_train)
plt.plot([None for i in y_train] + [x for x in y_test])
plt.show()

x_train.drop(['count'],inplace=True,axis=1)
x_test.drop(['count'],inplace=True,axis=1)<jupyter_output>Observations dans le jeu de données : 10886
Observations du Training : 8708
Observations du test: 2178<jupyter_text>Comme le montre le plot ci dessus,notre jeu de données a bien été séparé en deux ensemble (**train[80%] -- bleu** et **test[20%] -- Orange**) tout en conservant **l'ordre temporel des observations**.Nous utiliserons les algorithmes suivants :* GradientBoostingRegressor(),* DecisionTreeRegressor(), * LinearRegression(),* RandomForestRegressor(),* AdaBoostRegressor(),* BaggingRegressor(),* SVR(),* KNeighborsRegressor()Nous aurions pu utiliser d'autres algorithmes de modélisation comme *RIDGE* et *RIDGECV*, mais le problème est que cesmodèles prédisent souvent des valeurs négatives pour la cible *(le nombre total de locations de vélos [count])*, ce qui n'est pas possible dans notre cas d'études.<jupyter_code>alpha = 0.99
models=[GradientBoostingRegressor(loss='quantile', alpha=alpha,
                                n_estimators=250, max_depth=3,
                                learning_rate=.1, min_samples_leaf=9,
                                min_samples_split=9),DecisionTreeRegressor(), LinearRegression(),RandomForestRegressor(),AdaBoostRegressor(),BaggingRegressor(),SVR(),KNeighborsRegressor()]
model_names=['GradientBoosting','DecisionTree','LinearRegression','RandomForest','AdaBoost','Bagging','SVR','KNeighborsRegressor']
rmsle=[]

d={}
for model in range (len(models)):
    clf=models[model]
    clf.fit(x_train,y_train)
    test_pred=clf.predict(x_test)
    
    rmsle.append(np.sqrt(mean_squared_log_error(test_pred,y_test)))
    
    
    
rmsle_frame=pd.DataFrame({'Algorithme':model_names,'RMSLE':rmsle})
rmsle_frame.sort_values(by=['RMSLE'], ascending=[1])<jupyter_output><empty_output><jupyter_text>La variable cible étant une variable continue, nous avons utilisés une métrique d'évaluation des modèles linéaires.Nous avons choisis d'utiliser le *mean_squared_log_error (Dans notre cas, retourne Une valeur en virgule flottante non négative (la meilleure valeur est 0,0) pour chaque cible)*. Nous aurions pu utiliser d'autres métriques à linstar de :* explained_variance,	 * neg_mean_absolute_error,	 * neg_mean_squared_error,  * neg_median_absolute_error,	 * r2.<jupyter_code>sns.catplot(x='Algorithme',y='RMSLE',data=rmsle_frame,kind='point',height=5,aspect=2)<jupyter_output><empty_output><jupyter_text>Les modèles suivants possèdent le RMSLE les plus bas :* Bagging 	    0.360411* RandomForest 	0.361429Notons que plus cette métrique est proche de 0.0,meilleur le modèle de régression est. Nous allons éssayer d'améliorer les performances du RamdomForest (éssayer de rapprocher de 0.0 la métrique RMSLE pour ce modèle) en recherchant la valeur optimale de ses hyper paramètres (*n_estimators*, *max_features*)<jupyter_code>alg = []
score = []
bp = []
#Pour RandomForestRegressor.
no_of_test=[500]
params_dict={'n_estimators':no_of_test,'n_jobs':[-1],'max_features':["auto",'sqrt','log2']}
clf_rf=GridSearchCV(estimator=RandomForestRegressor(),param_grid=params_dict,scoring='neg_mean_squared_log_error')
clf_rf.fit(x_train,y_train)
pred=clf_rf.predict(x_test)
alg.append('RandomForestRegressor')
score.append(np.sqrt(mean_squared_log_error(pred,y_test)))
bp.append(clf_rf.best_params_)

# Pour KNN (KNeighborsRegressor)
n_neighbors=[]
for i in range (0,50,5):
    if(i!=0):
        n_neighbors.append(i)
params_dict={'n_neighbors':n_neighbors,'n_jobs':[-1]}
clf_knn=GridSearchCV(estimator=KNeighborsRegressor(),param_grid=params_dict,scoring='neg_mean_squared_log_error')
clf_knn.fit(x_train,y_train)
pred=clf_knn.predict(x_test)
print((np.sqrt(mean_squared_log_error(pred,y_test))))

alg.append('KNeighborsRegressor')
score.append(np.sqrt(mean_squared_log_error(pred,y_test)))
bp.append(clf_knn.best_params_)

o_rmsle_frame=pd.DataFrame({'Algorithme':alg,'RMSLE':score,'Best_params':bp})
o_rmsle_frame.sort_values(by=['RMSLE'], ascending=[1])
sns.catplot(y='Algorithme',x='RMSLE',data=o_rmsle_frame,kind='bar',height=5,aspect=2)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11882998171846434, 'fraction_numerical': 0.015051797684338817, 'mean_word_length': 7.267506297229219, 'pattern_counts': {'":': 0, '<': 104, '<?xml version=': 0, '>': 111, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '26', 'dir': 'jupyter-structured-clean-dedup', 'id': '456091', 'license': 'MIT', 'n_tokens_mistral': 6025, 'n_tokens_neox': 5766, 'n_words': 1482, 'path': 'Projet Velos/Projet_velo.ipynb', 'repo_name': 'DeNdiki/Machine-Learning', 'size': '16410'}