2) Meteo et machine learning

Bon, cette fois c’est parti ! Pour commencer et s’échauffer pénardo sans se claquer un tendon ou une rustine, on va d’abord réduire notre jeu de données (conséquent, j’ai planté mon pc plusieurs fois) en une seule station, et voir ce que ça donne ensuite. Va-t-on pouvoir prévoir des trucs ? Est-ce que déféquer du marbre brut à apprendre python aura été utile ? Est-ce que ça vaut le coup de perdre du temps à lire mon article plutôt que courir nu dans un champ de blé en jouant de la lyre et en riant tel un farfadet facétieux ? Nous allons tenter ensemble de répondre à ces questions existentielles hô combien cruciales.

Précédemment on avait dit qu’on commencerait par une station météo fixe « à la maison » avant de voir pour la mettre sur un bateau. Dans tout ce bordel contenu par les 3 fichiers csv de météo France, il va donc falloir dénicher les données d’une station proche de chez moi, ayant aussi des données exploitables…Car ce jeu de données est parfois un gros gruyère. Des stations n’indiquent pas la pression atmosphérique, d’autres n’indiquent des infos que une fois par jour…Moi j’ai besoin d’une station météo qui me donne pour 2016,2017 et 2018 la pression, la direction du vent, la température et le pourcentage d’humidité sans trop de trous, car plus il manque de l’info, plus on va perdre de l’efficacité sur notre modèle prédictif ! Va falloir chercher un gouda plutôt qu’un gruyère…

I.Traiter les données avant usage.

Au départ on a environ 250 stations, mais seules 49 valent vraiment le détour à première vue, pour sélectionner ces 49 stations on va utiliser un peu la même trame que la fonction fon_changer précédente.

Bien, maintenant il va falloir rendre notre jeu de données présentable pour le soumettre aux différents modèles de machine learning de sklearn… Je vous cache pas que c’est le gros du boulot avec son lot de sueur, de sang, de larmes et de pointes de côté pour un novice informatico-geek prépubère…Mais merde pourquoi j’ai pas choisit des loisirs comme ping pong ou pelote basque…Enfin…En gros voilà comment on va procéder pour commencer:

  1. Se débarrasser du superflu.
  2. arranger nos données, les indexer selon le temps avec le package « datetime »pour faciliter les manips.
  3. gérer les données manquantes en interpolant.
  4. Modifier des variables pour les adapter à notre projet.

L’objectif final sera d’avoir un dataframe de 60 colonnes ou variables et de 1096 lignes ou échantillons. Pourquoi 1096 lignes ? parce que notre jeu de donnée dure trois ans, avec une année bissextile (2016) donc ça fait 366+365+365=1096 jours. Donc une ligne=un jour. Pourquoi 60 colonnes ? En fait on va garder seulement les données toutes les 2 heures, soit 12 fois 5 variables (pression,direction,température,humidité,force) et pis 12X5 bin ça fait 60. C’est ce dataframe qu’on va faire passer à la moulinette façon sklearn! En fait on va prendre le parti pris qu’une journée de données permet de prédire ce qui se passera dans les heures suivantes. Bon faut bien commencer quelque part de toute façon…

Voilà le programme pour traiter nos données et partir des fichiers météo France pour arriver aux données de Deauville en un dataframe de 1096 sur 60 :

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from datetime import datetime


def changer(data_1):
    
     
     data_1=data_1.sort_values(by=['date','number_sta'],ascending=True) #met les données dans l'ordre temporel par station.

     data_1['date']=pd.to_datetime(data_1['date']) # change la colonne date en objet datetime.

     data_1=data_1.set_index('date') #on indexe notre dataframe sur le temps.
     
     data_1=data_1.drop(['precip','td','lon','height_sta','lat'],axis=1) #on se débarrasse des colonnes inutiles pour nous.

     data_1=data_1.fillna(data_1.rolling(window=1).mean()) #remplit les nan par la valeur moyenne de la journée.

     data_1=data_1.dropna(axis=0) # on vire les données de stations pour dégraisser.
     
     

     
     heure_1=data_1[(data_1.index.hour==0) & (data_1.index.minute==0)]#on conserve juste les données toutes les deux heures.
     heure_2=data_1[(data_1.index.hour==2) & (data_1.index.minute==0)]
     heure_3=data_1[(data_1.index.hour==4) & (data_1.index.minute==0)]
     heure_4=data_1[(data_1.index.hour==6) & (data_1.index.minute==0)]
     heure_5=data_1[(data_1.index.hour==8) & (data_1.index.minute==0)]
     heure_6=data_1[(data_1.index.hour==10) & (data_1.index.minute==0)]
     heure_7=data_1[(data_1.index.hour==12) & (data_1.index.minute==0)]
     heure_8=data_1[(data_1.index.hour==14) & (data_1.index.minute==0)]
     heure_9=data_1[(data_1.index.hour==16) & (data_1.index.minute==0)]
     heure_10=data_1[(data_1.index.hour==18) & (data_1.index.minute==0)]
     heure_11=data_1[(data_1.index.hour==20) & (data_1.index.minute==0)]
     heure_12=data_1[(data_1.index.hour==22) & (data_1.index.minute==0)]
    
     
     heures=[heure_1,heure_2,heure_3,heure_4,heure_5,heure_6,heure_7,heure_8,heure_9,heure_10,heure_11,heure_12]
     
     data_one=pd.concat(heures,axis=0) # on remet les données en un seul dataframe
     
     
     
     
     
     
     data_one['t']=data_one['t'].map(lambda x:int(x-273.15)) #convertit les Kelvin en degrés celsius.
     data_one['psl']=data_one['psl'].map(lambda x:int(x/100)) #convertit les pascals en hectopascals.
     data_one['hu']=data_one['hu'].map(lambda x:int(x)) #change en entier
     data_one['dd']=data_one['dd'].map(lambda x:int(x)) #pareil
     data_one['ff']=data_one['ff'].map(lambda x:int(x*3600/1852)) #change la vitesse du vent en noeuds.
     
     
     
     return data_one # renvoie les données "filtrées"
 


chunksize=100000 # taille du morceau de données filtré à la fois.

chunks=[] # liste qui va prendre les morceaux filtrés de 2016.


for chunk in pd.read_csv('C:/Users/Psychopathe/Documents/cours tech/machine learning/meteonet-master/NW_Ground_Stations/Meteo_NW_2016.csv',chunksize=chunksize):
        filtered=changer(chunk)
        chunks.append(filtered)
    
    
Deauville_2016=pd.concat(chunks,axis=0)
Deauville_2016=Deauville_2016[Deauville_2016['number_sta']==14578001] # on garde les valeurs de Deauville seulement.
Deauville_2016=Deauville_2016.drop(['number_sta'],axis=1) #on vire cette colonne qui ne nous sert plus
Deauville_2016=Deauville_2016.resample('2H').ffill() #on comble les heures manquantes avec les données de l'heure précédente.


chunks2=[]

for chunk2 in pd.read_csv('C:/Users/Psychopathe/Documents/cours tech/machine learning/meteonet-master/NW_Ground_Stations/Meteo_NW_2017.csv',chunksize=chunksize):
    filtered2=changer(chunk2)
    chunks2.append(filtered2)
    
Deauville_2017=pd.concat(chunks2,axis=0)
Deauville_2017=Deauville_2017[Deauville_2017['number_sta']==14578001]
Deauville_2017=Deauville_2017.drop(['number_sta'],axis=1)
Deauville_2017=Deauville_2017.resample('2H').ffill()


chunks3=[]

for chunk3 in pd.read_csv('C:/Users/Psychopathe/Documents/cours tech/machine learning/meteonet-master/NW_Ground_Stations/Meteo_NW_2018.csv',chunksize=chunksize):
    filtered3=changer(chunk3)
    chunks3.append(filtered3)
    
Deauville_2018=pd.concat(chunks3,axis=0)
Deauville_2018=Deauville_2018[Deauville_2018['number_sta']==14578001]
Deauville_2018=Deauville_2018.drop(['number_sta'],axis=1)
Deauville_2018=Deauville_2018.resample('2H').ffill()


Deauville=[Deauville_2016,Deauville_2017,Deauville_2018]
Deauville=pd.concat(Deauville,axis=0)



liste_heures=[Deauville[Deauville.index.hour==0+2*i] for i in range(12)] # permet de mettre les données de façon à avoir un jour égal une ligne.
Deauville=np.concatenate(liste_heures,axis=1)
Deauville=pd.DataFrame(Deauville)


Deauville.to_csv('Deauville_2H.csv',sep='\t') # crée le fichier avec nos données exploitables.



    
    
    
    
    
    
    
    

Maintenant, on a notre dataframe noté dans le fichier csv « Deauville_2H ». Ouéééé champagne !!!

II. SKLEARN

Sklearn est un package pour faire du machine learning, il contient donc tout un lot de modules pour ça.. Des modules se destinent à l’usage de modèles particuliers (arbres, régression, SVM…) et d’autres au prétraitement et à l’analyse des données, car beaucoup de modèles ont besoin d’un traitement statistique des variables avant, sinon c’est pas terrible niveau résultat, d’autres n’en n’ont pas besoin comme les forêts aléatoires par exemple, enfin comme j’ai lu dans les bouquins à voir. Sklearn permet aussi de résoudre des problèmes de classement, de régression, d’apprentissage non-supervisé et supervisé… Bon pour notre cas c’est de l’apprentissage supervisé pour un problème de régression.

  1. Les problèmes de régression

C’est simplement quand le résultat recherché est un nombre, une donnée « continue » comme un prix ou encore une dimension, une taille, etc…Les autres problèmes sont appelés des problèmes de classement, donc là on va chercher un résultat « discret » comme oui ou non, blanc ou noir, Tom ou Jerry, Riri, Fifi ou Loulou, Joe, averell, Jack ou William…Bref vous voyez le truc quoi.

2. L’apprentissage supervisé

On va séparer nos données en 2 jeux de données distincts; un jeu pour « l’entrainement » du modèle, et un autre pour vérifier si ça marche bien. En général le ratio entre données d’entrainement et données de test est de 70 % / 30 % environ;pour notre jeu de Deauville on prendra un ratio 80%/20%. Ne jamais utiliser des données d’entrainement pour évaluer un modèle, sinon on dit que les données sont « corrompues », et alors on va accoucher d’un modèle qui va tout péter à l’éval test car il aura déjà vu les données mais sur le terrain ça va ramer. Pour faire tout ça on va utiliser la fonction « train_test_split ».

En fait, l’apprentissage supervisé consiste à entrainer un modèle à fournir un résultat proche de ce qui est attendu, le modèle a les variables et le résultat qu’on attend de lui, et avec ça il se modifie via généralement une fonction de coût pour coller au mieux à tout ça.

3. Le prétraitement

Pour presque tout les modèles il est nécessaire de modifier les variables au préalable de façon statistique pour faciliter l’entrainement et l’efficacité des modèles. Pour cela on va majoritairement utiliser le module « preprocessing » de sklearn, ainsi que « make_pipeline » et la fonction « greadsearchcv ».

a) Preprocessing

Pour notre cas, déjà on va pas être emmerdé par des soucis d’encodage (changer des noms en nombres, car un processeur ne sait pas calculer avec des mots) car toutes nos variables sont des nombres. On va utiliser et comparer les résultats de 3 fonctions:

MinMaxScaler

Décale et recalibre les données pour que toutes les caractéristiques soient comprises entre 0 et 1.

RobustScaler

Un peu comme StandardScaler, mais utilise la médiane et les quartiles au lieu de la moyenne et la variance. Son avantage est de gommer les données aberrantes (outliers pour les frimeurs).

StandardScaler

Pour chaque caractéristique, rend la moyenne nulle et la variance égale à 1 (permet à toutes les caractéristiques d’avoir la même amplitude).

b) Les pipelines

Ce sont des structures qui associent un transformateur (l’une des fonctions précédente) et un estimateur (un modèle de machine learning). Ca permet d’économiser des lignes de codes, donc de rendre le code plus clair avec moins de chances de se planter, et aussi d’éviter de corrompre les données. La fonction « make_pipeline » permet de rédiger un pipeline.

c) gridsearcv

Permet de faire de la validation croisée. Cette fonction découpe nos données en sections de taille identiques (dans notre cas, j’ai découpé en 5 parties), puis teste les données selon toutes les configurations de découpage des données (un coup une section est une section test, un autre coup c’est une section entrainement…) et aussi les différents paramètres. Bon désolé c’est pas clair mais j’ai pas trouvé mieux pour expliquer, ou alors j’ai pas compris.

4. Les modèles qu’on va utiliser

Ce sont des modèles adaptés pour l’apprentissage supervisé et la régression. Notre jeu de données comprend pas mal de variables (60), mais bon il y a pire. En effet certains modèles déconnent quand on augmente le nombre de variables, enfin il paraît. Pour tout les modèles les tableaux de résultats concernent une prévision à 12 heures, et l’évolution des scores selon l’étendue de la prédiction se base sur la moyenne des différents scores par traitement.

Les plus proches voisins

Comme on l’a vu rapidement dans le précédent article, cette technique compare notre échantillon avec tout ceux stockés en mémoire. Il détecte le ou les échantillons dont les variables sont les plus similaires, regarde leur « target » ou donnée test correspondante puis attribue cette donnée ou la majorité de ces données si on prend plusieurs voisins pour l’attribuer à notre échantillon. Le plus simple, mais également le moins efficace. Voilà le petit programme pour étudier notre dataframe de Deauville (pour une prévision à 12 heures):

import pandas as pd
import numpy as np
from datetime import datetime
import matplotlib.pyplot as plt
import seaborn as sns

Deauville=pd.read_csv('C:/Users/Psychopathe/Documents/Python Scripts/meteo/station maison/mercredi28octobre/Deauville_2H.csv',sep='\t')

Deauville=Deauville.drop(['Unnamed: 0'],axis=1) # on vire la colonne inutile



variables=Deauville.iloc[:-1,:] # pour l'entrainement on garde tout sauf la dernière ligne.

résultat_dd=Deauville.iloc[1:,30] # pour la direction du vent, on vire la première ligne.
résultat_ff=Deauville.iloc[1:,31] # pour la force du vent, on vire aussi la première ligne.
résultat_hu=Deauville.iloc[1:,32] # pour l'humidité.
résultat_te=Deauville.iloc[1:,33] # pour la température.
résultat_pr=Deauville.iloc[1:,34] # pour la pression.



from sklearn.neighbors import KNeighborsRegressor # technique des plus proches voisins en regression.

from sklearn.model_selection import train_test_split # partage nos données en données test et entrainement (ratio réglé ici via test_size à 20%/80%)
from sklearn.model_selection import GridSearchCV # permet de trouver plus facilement les meilleurs paramètres de réglage du modèle.
from sklearn.model_selection import learning_curve # estime la limite de performance d'un modèle.

from sklearn.pipeline import make_pipeline # assemble un ou des transfomateurs de données et un estimateur, évite les fuites de données et réduit le code, donc évite les erreurs aussi.

from sklearn.preprocessing import MinMaxScaler # traitement de données, normalisation où nos variables deviennent comprises entre 0 et 1.
from sklearn.preprocessing import RobustScaler # traitement de données moins sujet aux outliers (échantillons aberrantes).
from sklearn.preprocessing import StandardScaler # traitement de donnée, rend la moyenne nulle et l'écart-type égal à un.

''' on sépare données entrainement et test pour toutes nos variables que l'on veut tester '''

X_train_direction,X_test_direction,y_train_direction,y_test_direction=train_test_split(variables,résultat_dd,test_size=0.2,random_state=0)
X_train_force,X_test_force,y_train_force,y_test_force=train_test_split(variables,résultat_ff,test_size=0.2,random_state=0)
X_train_humidite,X_test_humidite,y_train_humidite,y_test_humidite=train_test_split(variables,résultat_hu,test_size=0.2,random_state=0)
X_train_temperature,X_test_temperature,y_train_temperature,y_test_temperature=train_test_split(variables,résultat_te,test_size=0.2,random_state=0)
X_train_pression,X_test_pression,y_train_pression,y_test_pression=train_test_split(variables,résultat_pr,test_size=0.2,random_state=0)

traitement_1=make_pipeline(MinMaxScaler(),KNeighborsRegressor()) # création de l'objet pipeline1.
traitement_2=make_pipeline(RobustScaler(),KNeighborsRegressor()) # création du pipeline2.
traitement_3=make_pipeline(StandardScaler(),KNeighborsRegressor()) # création du pipeline3.

meilleurs_parametres=[]
score=[]

''' premier essai sans prétraitement, à poil , direction du vent   '''

param_grid={
    'n_neighbors':np.arange(1,20),
    'metric':['euclidean','manhattan']
    }

grid_1_direction=GridSearchCV(KNeighborsRegressor(),param_grid,cv=5)
grid_1_direction.fit(X_train_direction,y_train_direction)
meilleurs_parametres.append(grid_1_direction.best_params_)
model_1_direction=grid_1_direction.best_estimator_
score.append(model_1_direction.score(X_test_direction,y_test_direction))

''' à poil, force du vent '''

grid_1_force=GridSearchCV(KNeighborsRegressor(),param_grid,cv=5)
grid_1_force.fit(X_train_force,y_train_force)
meilleurs_parametres.append(grid_1_force.best_params_)
model_1_force=grid_1_force.best_estimator_
score.append(model_1_force.score(X_test_force,y_test_force))

'''à poil, humidite  '''

grid_1_humidite=GridSearchCV(KNeighborsRegressor(),param_grid,cv=5)
grid_1_humidite.fit(X_train_humidite,y_train_humidite)
meilleurs_parametres.append(grid_1_humidite.best_params_)
model_1_humidite=grid_1_humidite.best_estimator_
score.append(model_1_humidite.score(X_test_humidite,y_test_humidite))

''' à poil, temperature '''
grid_1_temperature=GridSearchCV(KNeighborsRegressor(),param_grid,cv=5)
grid_1_temperature.fit(X_train_temperature,y_train_temperature)
meilleurs_parametres.append(grid_1_temperature.best_params_)
model_1_temperature=grid_1_temperature.best_estimator_
score.append(model_1_temperature.score(X_test_temperature,y_test_temperature))

''' à poil, pression'''

grid_1_pression=GridSearchCV(KNeighborsRegressor(),param_grid,cv=5)
grid_1_pression.fit(X_train_pression,y_train_pression)
meilleurs_parametres.append(grid_1_pression.best_params_)
model_1_pression=grid_1_pression.best_estimator_
score.append(model_1_pression.score(X_test_pression,y_test_pression))


''' avec le pipeline1, direction'''

param_grid2={
    'kneighborsregressor__n_neighbors':np.arange(1,20),
    'kneighborsregressor__metric':['manhattan','euclidean']
    }

grid_2_direction=GridSearchCV(traitement_1,param_grid2,cv=5)
grid_2_direction.fit(X_train_direction,y_train_direction)
meilleurs_parametres.append(grid_2_direction.best_params_)
model_2_direction=grid_2_direction.best_estimator_
score.append(model_2_direction.score(X_test_direction,y_test_direction))

''' avec le pipeline1, force '''

grid_2_force=GridSearchCV(traitement_1,param_grid2,cv=5)
grid_2_force.fit(X_train_force,y_train_force)
meilleurs_parametres.append(grid_2_force.best_params_)
model_2_force=grid_2_force.best_estimator_
score.append(model_2_force.score(X_test_force,y_test_force))

''' avec le pipeline1, humidite  '''

grid_2_humidite=GridSearchCV(traitement_1,param_grid2,cv=5)
grid_2_humidite.fit(X_train_humidite,y_train_humidite)
meilleurs_parametres.append(grid_2_humidite.best_params_)
model_2_humidite=grid_2_humidite.best_estimator_
score.append(model_2_humidite.score(X_test_humidite,y_test_humidite))

'''avec le pipeline1, temperature'''

grid_2_temperature=GridSearchCV(traitement_1,param_grid2,cv=5)
grid_2_temperature.fit(X_train_temperature,y_train_temperature)
meilleurs_parametres.append(grid_2_temperature.best_params_)
model_2_temperature=grid_2_temperature.best_estimator_
score.append(model_2_temperature.score(X_test_temperature,y_test_temperature))

'''avec le pipeline1, pression'''

grid_2_pression=GridSearchCV(traitement_1,param_grid2,cv=5)
grid_2_pression.fit(X_train_pression,y_train_pression)
meilleurs_parametres.append(grid_2_pression.best_params_)
model_2_pression=grid_2_pression.best_estimator_
score.append(model_2_pression.score(X_test_pression,y_test_pression))



'''avec le pipeline2, direction'''

grid_3_direction=GridSearchCV(traitement_2,param_grid2,cv=5)
grid_3_direction.fit(X_train_direction,y_train_direction)
meilleurs_parametres.append(grid_3_direction.best_params_)
model_3_direction=grid_3_direction.best_estimator_
score.append(model_3_direction.score(X_test_direction,y_test_direction))

'''avec le pipeline2, force'''

grid_3_force=GridSearchCV(traitement_2,param_grid2,cv=5)
grid_3_force.fit(X_train_force,y_train_force)
meilleurs_parametres.append(grid_3_force.best_params_)
model_3_force=grid_3_force.best_estimator_
score.append(model_3_force.score(X_test_force,y_test_force))

'''avec le pipeline2, humidite'''

grid_3_humidite=GridSearchCV(traitement_2,param_grid2,cv=5)
grid_3_humidite.fit(X_train_humidite,y_train_humidite)
meilleurs_parametres.append(grid_3_humidite.best_params_)
model_3_humidite=grid_3_humidite.best_estimator_
score.append(model_3_humidite.score(X_test_humidite,y_test_humidite))

'''avec le pipeline2,temperature'''

grid_3_temperature=GridSearchCV(traitement_2,param_grid2,cv=5)
grid_3_temperature.fit(X_train_temperature,y_train_temperature)
meilleurs_parametres.append(grid_3_temperature.best_params_)
model_3_temperature=grid_3_temperature.best_estimator_
score.append(model_3_temperature.score(X_test_temperature,y_test_temperature))

'''avec le pipeline2,pression'''

grid_3_pression=GridSearchCV(traitement_2,param_grid2,cv=5)
grid_3_pression.fit(X_train_pression,y_train_pression)
meilleurs_parametres.append(grid_3_pression.best_params_)
model_3_pression=grid_3_pression.best_estimator_
score.append(model_3_pression.score(X_test_pression,y_test_pression))

'''avec le pipeline3,direction'''

grid_4_direction=GridSearchCV(traitement_3,param_grid2,cv=5)
grid_4_direction.fit(X_train_direction,y_train_direction)
meilleurs_parametres.append(grid_4_direction.best_params_)
model_4_direction=grid_4_direction.best_estimator_
score.append(model_4_direction.score(X_test_direction,y_test_direction))

'''avec le pipeline3,force'''

grid_4_force=GridSearchCV(traitement_3,param_grid2,cv=5)
grid_4_force.fit(X_train_force,y_train_force)
meilleurs_parametres.append(grid_4_force.best_params_)
model_4_force=grid_4_force.best_estimator_
score.append(model_4_force.score(X_test_force,y_test_force))

'''avec le pipeline3,humidite'''

grid_4_humidite=GridSearchCV(traitement_3,param_grid2,cv=5)
grid_4_humidite.fit(X_train_humidite,y_train_humidite)
meilleurs_parametres.append(grid_4_humidite.best_params_)
model_4_humidite=grid_4_humidite.best_estimator_
score.append(model_4_humidite.score(X_test_humidite,y_test_humidite))

'''avec le pipeline3,temperature'''

grid_4_temperature=GridSearchCV(traitement_3,param_grid2,cv=5)
grid_4_temperature.fit(X_train_temperature,y_train_temperature)
meilleurs_parametres.append(grid_4_temperature.best_params_)
model_4_temperature=grid_4_temperature.best_estimator_
score.append(model_4_temperature.score(X_test_temperature,y_test_temperature))

'''avec le pipeline3, pression'''

grid_4_pression=GridSearchCV(traitement_3,param_grid2,cv=5)
grid_4_pression.fit(X_train_pression,y_train_pression)
meilleurs_parametres.append(grid_4_pression.best_params_)
model_4_pression=grid_4_pression.best_estimator_
score.append(model_4_pression.score(X_test_pression,y_test_pression))


tableau_data=pd.DataFrame([score])
tableau_data.to_csv('score_12H.csv',sep='\t')
print(score)
print(meilleurs_parametres)


N_direction,train_score_direction,val_score_direction=learning_curve(KNeighborsRegressor(),X_train_direction,y_train_direction,train_sizes=np.linspace(0.1,1,10),cv=5)
N_force,train_score_force,val_score_force=learning_curve(KNeighborsRegressor(),X_train_force,y_train_force,train_sizes=np.linspace(0.1,1,10),cv=5)
N_pression,train_score_pression,val_score_pression=learning_curve(KNeighborsRegressor(),X_train_pression,y_train_pression,train_sizes=np.linspace(0.1,1,10),cv=5)
N_humidite,train_score_humidite,val_score_humidite=learning_curve(KNeighborsRegressor(),X_train_humidite,y_train_humidite,train_sizes=np.linspace(0.1,1,10),cv=5)
N_temperature,train_score_temperature,val_score_temperature=learning_curve(KNeighborsRegressor(),X_train_temperature,y_train_temperature,train_sizes=np.linspace(0.1,1,10),cv=5)

plt.figure(figsize=[12,12])
plt.subplot(5,1,1)
plt.title("direction")
plt.plot(N_direction,train_score_direction.mean(axis=1),label='train')
plt.plot(N_direction,val_score_direction.mean(axis=1),label='validation')
plt.xlabel('train_sizes')
plt.legend()
plt.subplot(5,1,2)
plt.title("force")
plt.plot(N_force,train_score_force.mean(axis=1),label='train')
plt.plot(N_force,val_score_force.mean(axis=1),label='validation')
plt.xlabel('train_sizes')
plt.legend()
plt.subplot(5,1,3)
plt.title('pression')
plt.plot(N_pression,train_score_pression.mean(axis=1),label='train')
plt.plot(N_pression,val_score_pression.mean(axis=1),label='validation')
plt.xlabel('train_sizes')
plt.legend()
plt.subplot(5,1,4)
plt.title('humidite')
plt.plot(N_humidite,train_score_humidite.mean(axis=1),label='train')
plt.plot(N_humidite,val_score_humidite.mean(axis=1),label='validation')
plt.xlabel('train_sizes')
plt.legend()
plt.subplot(5,1,5)
plt.title('temperature')
plt.plot(N_temperature,train_score_temperature.mean(axis=1),label='train')
plt.plot(N_temperature,train_score_temperature.mean(axis=1),label='validation')
plt.xlabel('train_sizes')
plt.legend()

Et voilà comment évoluent les moyennes des scores selon l’étendue de notre prévision (2 heures après, 4 heures après…on change à chaque fois l’indexation des colonnes pour les résultats attendus, de 5 en 5) :

En abscisse nous avons les heures des prédictions et en ordonnée les pourcentages de réussite sur les prédictions (par exemple 0.22 correspond à 22%). A première vue on distingue une certaine linéarité pour la force, l’humidité, la pression. Le reste c’est assez irrégulier mais pour la température ça peut s’expliquer car la variation est relativement faible pour chaque score. C’est assez rassurant on voit un lien entre les variables et le résultat attendu à priori, en tout cas pour celles où c’est à peu prêt linéaire.

Et maintenant la courbe d’apprentissage :

Un peu étrange….Les courbes ne se rejoignent pas, peut être parce que l’algo des k voisins « n’apprend pas » mais compare juste les données…A voir.

quand on regarde les paramètres ils changent beaucoup d’une variable à l’autre; les scores varient autour de 20% pour la direction,15% pour la force, 20% pour l’humidité, 80% pour la température et 60% pour la pression. Pas terrible…Aussi efficace qu’une prédiction de Paco Rabanne pour le moment. Voilà les scores en détail:

directionforcehumiditétempératurepression
sans traitement
25%17%17%59%48%
pipeline1
(MinMaxScaler)
19%13%23%84%63%
pipeline2
(RobustScaler)
18%9%25%82%67%
pipeline3
(StandardScaler)
18%8%25%84%67%

La régression linéaire

Pour bien comprendre comment ça marche allez sur youtube et regardez les vidéos consacrées à la régression linéaire sur la chaîne machine learnia, comme celle sur la descente de gradient. Voilà le programme :

import pandas as pd
import numpy as np
from datetime import datetime
import matplotlib.pyplot as plt
import seaborn as sns

Deauville=pd.read_csv('C:/Users/Psychopathe/Documents/Python Scripts/meteo/station maison/samedi24octobre/Deauville_le_retour.csv',sep='\t')

Deauville=Deauville.drop(['Unnamed: 0'],axis=1) # on vire la colonne inutile



variables=Deauville.iloc[:-1,:] # pour l'entrainement on garde tout sauf la dernière ligne.

résultat_dd=Deauville.iloc[1:,30] # pour la direction du vent, on vire la première ligne.
résultat_ff=Deauville.iloc[1:,31] # pour la force du vent, on vire aussi la première ligne.
résultat_hu=Deauville.iloc[1:,32] # pour l'humidité.
résultat_te=Deauville.iloc[1:,33] # pour la température.
résultat_pr=Deauville.iloc[1:,34] # pour la pression.



from sklearn.linear_model import LinearRegression# technique  regression simple.

from sklearn.model_selection import train_test_split # partage nos données en données test et entrainement (ratio réglé ici via test_size à 20%/80%)
from sklearn.model_selection import GridSearchCV # permet de trouver plus facilement les meilleurs paramètres de réglage du modèle.
from sklearn.model_selection import learning_curve # estime la limite de performance d'un modèle.

from sklearn.pipeline import make_pipeline # assemble un ou des transfomateurs de données et un estimateur, évite les fuites de données et réduit le code, donc évite les erreurs aussi.

from sklearn.preprocessing import MinMaxScaler # traitement de données, normalisation où nos variables deviennent comprises entre 0 et 1.
from sklearn.preprocessing import RobustScaler # traitement de données moins sujet aux outliers (échantillons aberrantes).
from sklearn.preprocessing import StandardScaler # traitement de donnée, rend la moyenne nulle et l'écart-type égal à un.

''' on sépare données entrainement et test pour toutes nos variables que l'on veut tester '''

X_train_direction,X_test_direction,y_train_direction,y_test_direction=train_test_split(variables,résultat_dd,test_size=0.2,random_state=0)
X_train_force,X_test_force,y_train_force,y_test_force=train_test_split(variables,résultat_ff,test_size=0.2,random_state=0)
X_train_humidite,X_test_humidite,y_train_humidite,y_test_humidite=train_test_split(variables,résultat_hu,test_size=0.2,random_state=0)
X_train_temperature,X_test_temperature,y_train_temperature,y_test_temperature=train_test_split(variables,résultat_te,test_size=0.2,random_state=0)
X_train_pression,X_test_pression,y_train_pression,y_test_pression=train_test_split(variables,résultat_pr,test_size=0.2,random_state=0)

traitement_1=make_pipeline(MinMaxScaler(),LinearRegression()) # création de l'objet pipeline1.
traitement_2=make_pipeline(RobustScaler(),LinearRegression()) # création du pipeline2.
traitement_3=make_pipeline(StandardScaler(),LinearRegression()) # création du pipeline3.

meilleurs_parametres=[]
score=[]

''' premier essai sans prétraitement, à poil , direction du vent   '''

param_grid={
    
    }

grid_1_direction=GridSearchCV(LinearRegression(),param_grid,cv=5)
grid_1_direction.fit(X_train_direction,y_train_direction)
meilleurs_parametres.append(grid_1_direction.best_params_)
model_1_direction=grid_1_direction.best_estimator_
score.append(model_1_direction.score(X_test_direction,y_test_direction))

''' à poil, force du vent '''

grid_1_force=GridSearchCV(LinearRegression(),param_grid,cv=5)
grid_1_force.fit(X_train_force,y_train_force)
meilleurs_parametres.append(grid_1_force.best_params_)
model_1_force=grid_1_force.best_estimator_
score.append(model_1_force.score(X_test_force,y_test_force))

'''à poil, humidite  '''

grid_1_humidite=GridSearchCV(LinearRegression(),param_grid,cv=5)
grid_1_humidite.fit(X_train_humidite,y_train_humidite)
meilleurs_parametres.append(grid_1_humidite.best_params_)
model_1_humidite=grid_1_humidite.best_estimator_
score.append(model_1_humidite.score(X_test_humidite,y_test_humidite))

''' à poil, temperature '''
grid_1_temperature=GridSearchCV(LinearRegression(),param_grid,cv=5)
grid_1_temperature.fit(X_train_temperature,y_train_temperature)
meilleurs_parametres.append(grid_1_temperature.best_params_)
model_1_temperature=grid_1_temperature.best_estimator_
score.append(model_1_temperature.score(X_test_temperature,y_test_temperature))

''' à poil, pression'''

grid_1_pression=GridSearchCV(LinearRegression(),param_grid,cv=5)
grid_1_pression.fit(X_train_pression,y_train_pression)
meilleurs_parametres.append(grid_1_pression.best_params_)
model_1_pression=grid_1_pression.best_estimator_
score.append(model_1_pression.score(X_test_pression,y_test_pression))



''' avec le pipeline1, direction'''

param_grid2={
    
    }

grid_2_direction=GridSearchCV(traitement_1,param_grid2,cv=5)
grid_2_direction.fit(X_train_direction,y_train_direction)
meilleurs_parametres.append(grid_2_direction.best_params_)
model_2_direction=grid_2_direction.best_estimator_
score.append(model_2_direction.score(X_test_direction,y_test_direction))

''' avec le pipeline1, force '''

grid_2_force=GridSearchCV(traitement_1,param_grid2,cv=5)
grid_2_force.fit(X_train_force,y_train_force)
meilleurs_parametres.append(grid_2_force.best_params_)
model_2_force=grid_2_force.best_estimator_
score.append(model_2_force.score(X_test_force,y_test_force))

''' avec le pipeline1, humidite  '''

grid_2_humidite=GridSearchCV(traitement_1,param_grid2,cv=5)
grid_2_humidite.fit(X_train_humidite,y_train_humidite)
meilleurs_parametres.append(grid_2_humidite.best_params_)
model_2_humidite=grid_2_humidite.best_estimator_
score.append(model_2_humidite.score(X_test_humidite,y_test_humidite))

'''avec le pipeline1, temperature'''

grid_2_temperature=GridSearchCV(traitement_1,param_grid2,cv=5)
grid_2_temperature.fit(X_train_temperature,y_train_temperature)
meilleurs_parametres.append(grid_2_temperature.best_params_)
model_2_temperature=grid_2_temperature.best_estimator_
score.append(model_2_temperature.score(X_test_temperature,y_test_temperature))

'''avec le pipeline1, pression'''

grid_2_pression=GridSearchCV(traitement_1,param_grid2,cv=5)
grid_2_pression.fit(X_train_pression,y_train_pression)
meilleurs_parametres.append(grid_2_pression.best_params_)
model_2_pression=grid_2_pression.best_estimator_
score.append(model_2_pression.score(X_test_pression,y_test_pression))


'''avec le pipeline2, direction'''

grid_3_direction=GridSearchCV(traitement_2,param_grid2,cv=5)
grid_3_direction.fit(X_train_direction,y_train_direction)
meilleurs_parametres.append(grid_3_direction.best_params_)
model_3_direction=grid_3_direction.best_estimator_
score.append(model_3_direction.score(X_test_direction,y_test_direction))

'''avec le pipeline2, force'''

grid_3_force=GridSearchCV(traitement_2,param_grid2,cv=5)
grid_3_force.fit(X_train_force,y_train_force)
meilleurs_parametres.append(grid_3_force.best_params_)
model_3_force=grid_3_force.best_estimator_
score.append(model_3_force.score(X_test_force,y_test_force))

'''avec le pipeline2, humidite'''

grid_3_humidite=GridSearchCV(traitement_2,param_grid2,cv=5)
grid_3_humidite.fit(X_train_humidite,y_train_humidite)
meilleurs_parametres.append(grid_3_humidite.best_params_)
model_3_humidite=grid_3_humidite.best_estimator_
score.append(model_3_humidite.score(X_test_humidite,y_test_humidite))

'''avec le pipeline2,temperature'''

grid_3_temperature=GridSearchCV(traitement_2,param_grid2,cv=5)
grid_3_temperature.fit(X_train_temperature,y_train_temperature)
meilleurs_parametres.append(grid_3_temperature.best_params_)
model_3_temperature=grid_3_temperature.best_estimator_
score.append(model_3_temperature.score(X_test_temperature,y_test_temperature))

'''avec le pipeline2,pression'''

grid_3_pression=GridSearchCV(traitement_2,param_grid2,cv=5)
grid_3_pression.fit(X_train_pression,y_train_pression)
meilleurs_parametres.append(grid_3_pression.best_params_)
model_3_pression=grid_3_pression.best_estimator_
score.append(model_3_pression.score(X_test_pression,y_test_pression))

'''avec le pipeline3,direction'''

grid_4_direction=GridSearchCV(traitement_3,param_grid2,cv=5)
grid_4_direction.fit(X_train_direction,y_train_direction)
meilleurs_parametres.append(grid_4_direction.best_params_)
model_4_direction=grid_4_direction.best_estimator_
score.append(model_4_direction.score(X_test_direction,y_test_direction))

'''avec le pipeline3,force'''

grid_4_force=GridSearchCV(traitement_3,param_grid2,cv=5)
grid_4_force.fit(X_train_force,y_train_force)
meilleurs_parametres.append(grid_4_force.best_params_)
model_4_force=grid_4_force.best_estimator_
score.append(model_4_force.score(X_test_force,y_test_force))

'''avec le pipeline3,humidite'''

grid_4_humidite=GridSearchCV(traitement_3,param_grid2,cv=5)
grid_4_humidite.fit(X_train_humidite,y_train_humidite)
meilleurs_parametres.append(grid_4_humidite.best_params_)
model_4_humidite=grid_4_humidite.best_estimator_
score.append(model_4_humidite.score(X_test_humidite,y_test_humidite))

'''avec le pipeline3,temperature'''

grid_4_temperature=GridSearchCV(traitement_3,param_grid2,cv=5)
grid_4_temperature.fit(X_train_temperature,y_train_temperature)
meilleurs_parametres.append(grid_4_temperature.best_params_)
model_4_temperature=grid_4_temperature.best_estimator_
score.append(model_4_temperature.score(X_test_temperature,y_test_temperature))

'''avec le pipeline3, pression'''

grid_4_pression=GridSearchCV(traitement_3,param_grid2,cv=5)
grid_4_pression.fit(X_train_pression,y_train_pression)
meilleurs_parametres.append(grid_4_pression.best_params_)
model_4_pression=grid_4_pression.best_estimator_
score.append(model_4_pression.score(X_test_pression,y_test_pression))


tableau_data=pd.DataFrame([score])
tableau_data.to_csv('score_12H.csv',sep='\t')
print(score)
print(meilleurs_parametres)


N_direction,train_score_direction,val_score_direction=learning_curve(LinearRegression(),X_train_direction,y_train_direction,train_sizes=np.linspace(0.1,1,10),cv=5)
N_force,train_score_force,val_score_force=learning_curve(LinearRegression(),X_train_force,y_train_force,train_sizes=np.linspace(0.1,1,10),cv=5)
N_pression,train_score_pression,val_score_pression=learning_curve(LinearRegression(),X_train_pression,y_train_pression,train_sizes=np.linspace(0.1,1,10),cv=5)
N_humidite,train_score_humidite,val_score_humidite=learning_curve(LinearRegression(),X_train_humidite,y_train_humidite,train_sizes=np.linspace(0.1,1,10),cv=5)
N_temperature,train_score_temperature,val_score_temperature=learning_curve(LinearRegression(),X_train_temperature,y_train_temperature,train_sizes=np.linspace(0.1,1,10),cv=5)

plt.figure(figsize=[12,12])
plt.subplot(5,1,1)
plt.title("direction")
plt.plot(N_direction,train_score_direction.mean(axis=1),label='train')
plt.plot(N_direction,val_score_direction.mean(axis=1),label='validation')
plt.xlabel('train_sizes')
plt.legend()
plt.subplot(5,1,2)
plt.title("force")
plt.plot(N_force,train_score_force.mean(axis=1),label='train')
plt.plot(N_force,val_score_force.mean(axis=1),label='validation')
plt.xlabel('train_sizes')
plt.legend()
plt.subplot(5,1,3)
plt.title('pression')
plt.plot(N_pression,train_score_pression.mean(axis=1),label='train')
plt.plot(N_pression,val_score_pression.mean(axis=1),label='validation')
plt.xlabel('train_sizes')
plt.legend()
plt.subplot(5,1,4)
plt.title('humidite')
plt.plot(N_humidite,train_score_humidite.mean(axis=1),label='train')
plt.plot(N_humidite,val_score_humidite.mean(axis=1),label='validation')
plt.xlabel('train_sizes')
plt.legend()
plt.subplot(5,1,5)
plt.title('temperature')
plt.plot(N_temperature,train_score_temperature.mean(axis=1),label='train')
plt.plot(N_temperature,train_score_temperature.mean(axis=1),label='validation')
plt.xlabel('train_sizes')
plt.legend()

Comme vous pouvez le constater, les grilles des paramètres sont vides car il n’y a pas (à ma connaissance) de paramètres à ajuster pour la régression linéaire simple.

Et maintenant les résultats selon l’étendue de la prévision:

A première vue le constat est à peu prêt identique par rapport aux proches voisins, par contre la température semble plus linéaire.

Et maintenant voilà les courbes d’apprentissage pour la régression:

Pour les 4 premières variables on remarque une montée rapide de la validation jusqu’à environ 130 échantillons, ensuite ça devient bien plus lent. Pour la température c’est l’inverse jusqu’à 130 échantillons ça descend progressivement, ensuite ça met plus de temps à baisser.

Quand on observe nos résultats, ils ne varient quasiment pas entre nos données non traitées et nos données traitées, à chaque fois on a ça:

variablesdirectionforcehumiditétemperaturepression
scores en %20%19%18%86%85%

Bon ça reste aussi prédictif qu’un retard SNCF pour le moment.

La régression Ridge

Ce type de régression fonctionne comme celle d’avant sauf que le système va chercher à minimiser les poids au maximum. C’est une méthode particulièrement intéressante pour éviter le surapprentissage des modèles. Pour le programme c’est presque comme la régression sauf que là on peut jouer avec le paramètre alpha, présent cette fois dans les paramètres de grille:

import pandas as pd
import numpy as np
from datetime import datetime
import matplotlib.pyplot as plt
import seaborn as sns

Deauville=pd.read_csv('C:/Users/Psychopathe/Documents/Python Scripts/meteo/station maison/samedi24octobre/Deauville_le_retour.csv',sep='\t')

Deauville=Deauville.drop(['Unnamed: 0'],axis=1) # on vire la colonne inutile



variables=Deauville.iloc[:-1,:] # pour l'entrainement on garde tout sauf la dernière ligne.

résultat_dd=Deauville.iloc[1:,30] # pour la direction du vent, on vire la première ligne.
résultat_ff=Deauville.iloc[1:,31] # pour la force du vent, on vire aussi la première ligne.
résultat_hu=Deauville.iloc[1:,32] # pour l'humidité.
résultat_te=Deauville.iloc[1:,33] # pour la température.
résultat_pr=Deauville.iloc[1:,34] # pour la pression.



from sklearn.linear_model import Ridge# technique  regression ridge.

from sklearn.model_selection import train_test_split # partage nos données en données test et entrainement (ratio réglé ici via test_size à 20%/80%)
from sklearn.model_selection import GridSearchCV # permet de trouver plus facilement les meilleurs paramètres de réglage du modèle.
from sklearn.model_selection import learning_curve # estime la limite de performance d'un modèle.

from sklearn.pipeline import make_pipeline # assemble un ou des transfomateurs de données et un estimateur, évite les fuites de données et réduit le code, donc évite les erreurs aussi.

from sklearn.preprocessing import MinMaxScaler # traitement de données, normalisation où nos variables deviennent comprises entre 0 et 1.
from sklearn.preprocessing import RobustScaler # traitement de données moins sujet aux outliers (échantillons aberrantes).
from sklearn.preprocessing import StandardScaler # traitement de donnée, rend la moyenne nulle et l'écart-type égal à un.

''' on sépare données entrainement et test pour toutes nos variables que l'on veut tester '''

X_train_direction,X_test_direction,y_train_direction,y_test_direction=train_test_split(variables,résultat_dd,test_size=0.2,random_state=0)
X_train_force,X_test_force,y_train_force,y_test_force=train_test_split(variables,résultat_ff,test_size=0.2,random_state=0)
X_train_humidite,X_test_humidite,y_train_humidite,y_test_humidite=train_test_split(variables,résultat_hu,test_size=0.2,random_state=0)
X_train_temperature,X_test_temperature,y_train_temperature,y_test_temperature=train_test_split(variables,résultat_te,test_size=0.2,random_state=0)
X_train_pression,X_test_pression,y_train_pression,y_test_pression=train_test_split(variables,résultat_pr,test_size=0.2,random_state=0)

traitement_1=make_pipeline(MinMaxScaler(),Ridge()) # création de l'objet pipeline1.
traitement_2=make_pipeline(RobustScaler(),Ridge()) # création du pipeline2.
traitement_3=make_pipeline(StandardScaler(),Ridge()) # création du pipeline3.

meilleurs_parametres=[]
score=[]

''' premier essai sans prétraitement, à poil , direction du vent   '''

param_grid={
    'alpha':[10,1,0.1,0.01,0.001]
    }

grid_1_direction=GridSearchCV(Ridge(),param_grid,cv=5)
grid_1_direction.fit(X_train_direction,y_train_direction)
meilleurs_parametres.append(grid_1_direction.best_params_)
model_1_direction=grid_1_direction.best_estimator_
score.append(model_1_direction.score(X_test_direction,y_test_direction))

''' à poil, force du vent '''

grid_1_force=GridSearchCV(Ridge(),param_grid,cv=5)
grid_1_force.fit(X_train_force,y_train_force)
meilleurs_parametres.append(grid_1_force.best_params_)
model_1_force=grid_1_force.best_estimator_
score.append(model_1_force.score(X_test_force,y_test_force))

'''à poil, humidite  '''

grid_1_humidite=GridSearchCV(Ridge(),param_grid,cv=5)
grid_1_humidite.fit(X_train_humidite,y_train_humidite)
meilleurs_parametres.append(grid_1_humidite.best_params_)
model_1_humidite=grid_1_humidite.best_estimator_
score.append(model_1_humidite.score(X_test_humidite,y_test_humidite))

''' à poil, temperature '''
grid_1_temperature=GridSearchCV(Ridge(),param_grid,cv=5)
grid_1_temperature.fit(X_train_temperature,y_train_temperature)
meilleurs_parametres.append(grid_1_temperature.best_params_)
model_1_temperature=grid_1_temperature.best_estimator_
score.append(model_1_temperature.score(X_test_temperature,y_test_temperature))

''' à poil, pression'''

grid_1_pression=GridSearchCV(Ridge(),param_grid,cv=5)
grid_1_pression.fit(X_train_pression,y_train_pression)
meilleurs_parametres.append(grid_1_pression.best_params_)
model_1_pression=grid_1_pression.best_estimator_
score.append(model_1_pression.score(X_test_pression,y_test_pression))



''' avec le pipeline1, direction'''

param_grid2={
    'ridge__alpha':[10,1,0.1,0.01,0.001]
    }

grid_2_direction=GridSearchCV(traitement_1,param_grid2,cv=5)
grid_2_direction.fit(X_train_direction,y_train_direction)
meilleurs_parametres.append(grid_2_direction.best_params_)
model_2_direction=grid_2_direction.best_estimator_
score.append(model_2_direction.score(X_test_direction,y_test_direction))

''' avec le pipeline1, force '''

grid_2_force=GridSearchCV(traitement_1,param_grid2,cv=5)
grid_2_force.fit(X_train_force,y_train_force)
meilleurs_parametres.append(grid_2_force.best_params_)
model_2_force=grid_2_force.best_estimator_
score.append(model_2_force.score(X_test_force,y_test_force))

''' avec le pipeline1, humidite  '''

grid_2_humidite=GridSearchCV(traitement_1,param_grid2,cv=5)
grid_2_humidite.fit(X_train_humidite,y_train_humidite)
meilleurs_parametres.append(grid_2_humidite.best_params_)
model_2_humidite=grid_2_humidite.best_estimator_
score.append(model_2_humidite.score(X_test_humidite,y_test_humidite))

'''avec le pipeline1, temperature'''

grid_2_temperature=GridSearchCV(traitement_1,param_grid2,cv=5)
grid_2_temperature.fit(X_train_temperature,y_train_temperature)
meilleurs_parametres.append(grid_2_temperature.best_params_)
model_2_temperature=grid_2_temperature.best_estimator_
score.append(model_2_temperature.score(X_test_temperature,y_test_temperature))

'''avec le pipeline1, pression'''

grid_2_pression=GridSearchCV(traitement_1,param_grid2,cv=5)
grid_2_pression.fit(X_train_pression,y_train_pression)
meilleurs_parametres.append(grid_2_pression.best_params_)
model_2_pression=grid_2_pression.best_estimator_
score.append(model_2_pression.score(X_test_pression,y_test_pression))


'''avec le pipeline2, direction'''

grid_3_direction=GridSearchCV(traitement_2,param_grid2,cv=5)
grid_3_direction.fit(X_train_direction,y_train_direction)
meilleurs_parametres.append(grid_3_direction.best_params_)
model_3_direction=grid_3_direction.best_estimator_
score.append(model_3_direction.score(X_test_direction,y_test_direction))

'''avec le pipeline2, force'''

grid_3_force=GridSearchCV(traitement_2,param_grid2,cv=5)
grid_3_force.fit(X_train_force,y_train_force)
meilleurs_parametres.append(grid_3_force.best_params_)
model_3_force=grid_3_force.best_estimator_
score.append(model_3_force.score(X_test_force,y_test_force))

'''avec le pipeline2, humidite'''

grid_3_humidite=GridSearchCV(traitement_2,param_grid2,cv=5)
grid_3_humidite.fit(X_train_humidite,y_train_humidite)
meilleurs_parametres.append(grid_3_humidite.best_params_)
model_3_humidite=grid_3_humidite.best_estimator_
score.append(model_3_humidite.score(X_test_humidite,y_test_humidite))

'''avec le pipeline2,temperature'''

grid_3_temperature=GridSearchCV(traitement_2,param_grid2,cv=5)
grid_3_temperature.fit(X_train_temperature,y_train_temperature)
meilleurs_parametres.append(grid_3_temperature.best_params_)
model_3_temperature=grid_3_temperature.best_estimator_
score.append(model_3_temperature.score(X_test_temperature,y_test_temperature))

'''avec le pipeline2,pression'''

grid_3_pression=GridSearchCV(traitement_2,param_grid2,cv=5)
grid_3_pression.fit(X_train_pression,y_train_pression)
meilleurs_parametres.append(grid_3_pression.best_params_)
model_3_pression=grid_3_pression.best_estimator_
score.append(model_3_pression.score(X_test_pression,y_test_pression))

'''avec le pipeline3,direction'''

grid_4_direction=GridSearchCV(traitement_3,param_grid2,cv=5)
grid_4_direction.fit(X_train_direction,y_train_direction)
meilleurs_parametres.append(grid_4_direction.best_params_)
model_4_direction=grid_4_direction.best_estimator_
score.append(model_4_direction.score(X_test_direction,y_test_direction))

'''avec le pipeline3,force'''

grid_4_force=GridSearchCV(traitement_3,param_grid2,cv=5)
grid_4_force.fit(X_train_force,y_train_force)
meilleurs_parametres.append(grid_4_force.best_params_)
model_4_force=grid_4_force.best_estimator_
score.append(model_4_force.score(X_test_force,y_test_force))

'''avec le pipeline3,humidite'''

grid_4_humidite=GridSearchCV(traitement_3,param_grid2,cv=5)
grid_4_humidite.fit(X_train_humidite,y_train_humidite)
meilleurs_parametres.append(grid_4_humidite.best_params_)
model_4_humidite=grid_4_humidite.best_estimator_
score.append(model_4_humidite.score(X_test_humidite,y_test_humidite))

'''avec le pipeline3,temperature'''

grid_4_temperature=GridSearchCV(traitement_3,param_grid2,cv=5)
grid_4_temperature.fit(X_train_temperature,y_train_temperature)
meilleurs_parametres.append(grid_4_temperature.best_params_)
model_4_temperature=grid_4_temperature.best_estimator_
score.append(model_4_temperature.score(X_test_temperature,y_test_temperature))

'''avec le pipeline3, pression'''

grid_4_pression=GridSearchCV(traitement_3,param_grid2,cv=5)
grid_4_pression.fit(X_train_pression,y_train_pression)
meilleurs_parametres.append(grid_4_pression.best_params_)
model_4_pression=grid_4_pression.best_estimator_
score.append(model_4_pression.score(X_test_pression,y_test_pression))


tableau_data=pd.DataFrame([score])
tableau_data.to_csv('scoreridge_12H.csv',sep='\t')
print(score)
print(meilleurs_parametres)

"""
N_direction,train_score_direction,val_score_direction=learning_curve(Ridge(),X_train_direction,y_train_direction,train_sizes=np.linspace(0.1,1,10),cv=5)
N_force,train_score_force,val_score_force=learning_curve(Ridge(),X_train_force,y_train_force,train_sizes=np.linspace(0.1,1,10),cv=5)
N_pression,train_score_pression,val_score_pression=learning_curve(Ridge(),X_train_pression,y_train_pression,train_sizes=np.linspace(0.1,1,10),cv=5)
N_humidite,train_score_humidite,val_score_humidite=learning_curve(Ridge(),X_train_humidite,y_train_humidite,train_sizes=np.linspace(0.1,1,10),cv=5)
N_temperature,train_score_temperature,val_score_temperature=learning_curve(Ridge(),X_train_temperature,y_train_temperature,train_sizes=np.linspace(0.1,1,10),cv=5)

plt.figure(figsize=[12,12])
plt.subplot(5,1,1)
plt.title("direction")
plt.plot(N_direction,train_score_direction.mean(axis=1),label='train')
plt.plot(N_direction,val_score_direction.mean(axis=1),label='validation')
plt.xlabel('train_sizes')
plt.legend()
plt.subplot(5,1,2)
plt.title("force")
plt.plot(N_force,train_score_force.mean(axis=1),label='train')
plt.plot(N_force,val_score_force.mean(axis=1),label='validation')
plt.xlabel('train_sizes')
plt.legend()
plt.subplot(5,1,3)
plt.title('pression')
plt.plot(N_pression,train_score_pression.mean(axis=1),label='train')
plt.plot(N_pression,val_score_pression.mean(axis=1),label='validation')
plt.xlabel('train_sizes')
plt.legend()
plt.subplot(5,1,4)
plt.title('humidite')
plt.plot(N_humidite,train_score_humidite.mean(axis=1),label='train')
plt.plot(N_humidite,val_score_humidite.mean(axis=1),label='validation')
plt.xlabel('train_sizes')
plt.legend()
plt.subplot(5,1,5)
plt.title('temperature')
plt.plot(N_temperature,train_score_temperature.mean(axis=1),label='train')
plt.plot(N_temperature,train_score_temperature.mean(axis=1),label='validation')
plt.xlabel('train_sizes')
plt.legend()

Et maintenant les courbes des scores selon les heures de prédiction:

On voit bien la linéarité pour nos variables, pour la direction ça reste un peu les montagnes russes par contre. Ensuite on va pouvoir voir les courbes d’apprentissage du modèle Ridge:

A première vue ça ressemble assez à la régression linéaire simple, avec peut-être une progression un peu moins tranchée aux alentour des 130 écahntillons. Les résultats des scores à 12 heures selon les traitements maintenant:

directionforcehumiditétempératurepression
sans traitement20%19%19%86%85%
MinMaxScaler25%17%21%86%85%
RobustScaler23%20%20%86%85%
StandardScaler22%20%20%86%85%

Pour les meilleurs paramètres on a alpha à 10 très souvent, un peu à 1 et une fois à 0.01.

La régression Lasso

Ce modèle va cette fois descendre à 0 les poids « inutiles ». Pratique pour identifier les variables qui sont vraiment utiles des variables inutiles pour nos prédictions…Programme:

import pandas as pd
import numpy as np
from datetime import datetime
import matplotlib.pyplot as plt
import seaborn as sns

Deauville=pd.read_csv('C:/Users/Psychopathe/Documents/Python Scripts/meteo/station maison/samedi24octobre/Deauville_le_retour.csv',sep='\t')

Deauville=Deauville.drop(['Unnamed: 0'],axis=1) # on vire la colonne inutile



variables=Deauville.iloc[:-1,:] # pour l'entrainement on garde tout sauf la dernière ligne.

résultat_dd=Deauville.iloc[1:,30] # pour la direction du vent, on vire la première ligne.
résultat_ff=Deauville.iloc[1:,31] # pour la force du vent, on vire aussi la première ligne.
résultat_hu=Deauville.iloc[1:,32] # pour l'humidité.
résultat_te=Deauville.iloc[1:,33] # pour la température.
résultat_pr=Deauville.iloc[1:,34] # pour la pression.



from sklearn.linear_model import Lasso# technique  regression lasso.

from sklearn.model_selection import train_test_split # partage nos données en données test et entrainement (ratio réglé ici via test_size à 20%/80%)
from sklearn.model_selection import GridSearchCV # permet de trouver plus facilement les meilleurs paramètres de réglage du modèle.
from sklearn.model_selection import learning_curve # estime la limite de performance d'un modèle.

from sklearn.pipeline import make_pipeline # assemble un ou des transfomateurs de données et un estimateur, évite les fuites de données et réduit le code, donc évite les erreurs aussi.

from sklearn.preprocessing import MinMaxScaler # traitement de données, normalisation où nos variables deviennent comprises entre 0 et 1.
from sklearn.preprocessing import RobustScaler # traitement de données moins sujet aux outliers (échantillons aberrantes).
from sklearn.preprocessing import StandardScaler # traitement de donnée, rend la moyenne nulle et l'écart-type égal à un.

''' on sépare données entrainement et test pour toutes nos variables que l'on veut tester '''

X_train_direction,X_test_direction,y_train_direction,y_test_direction=train_test_split(variables,résultat_dd,test_size=0.2,random_state=0)
X_train_force,X_test_force,y_train_force,y_test_force=train_test_split(variables,résultat_ff,test_size=0.2,random_state=0)
X_train_humidite,X_test_humidite,y_train_humidite,y_test_humidite=train_test_split(variables,résultat_hu,test_size=0.2,random_state=0)
X_train_temperature,X_test_temperature,y_train_temperature,y_test_temperature=train_test_split(variables,résultat_te,test_size=0.2,random_state=0)
X_train_pression,X_test_pression,y_train_pression,y_test_pression=train_test_split(variables,résultat_pr,test_size=0.2,random_state=0)

traitement_1=make_pipeline(MinMaxScaler(),Lasso()) # création de l'objet pipeline1.
traitement_2=make_pipeline(RobustScaler(),Lasso()) # création du pipeline2.
traitement_3=make_pipeline(StandardScaler(),Lasso()) # création du pipeline3.

meilleurs_parametres=[]
score=[]
v_u=[]

''' premier essai sans prétraitement, à poil , direction du vent   '''

param_grid={
    'alpha':[10,1,0.1,0.01,0.001],
    'max_iter':[100000]
    }

grid_1_direction=GridSearchCV(Lasso(),param_grid,cv=5)
grid_1_direction.fit(X_train_direction,y_train_direction)
meilleurs_parametres.append(grid_1_direction.best_params_)
model_1_direction=grid_1_direction.best_estimator_
score.append(model_1_direction.score(X_test_direction,y_test_direction))
v_u.append(np.sum(model_1_direction.coef_!=0))

''' à poil, force du vent '''

grid_1_force=GridSearchCV(Lasso(),param_grid,cv=5)
grid_1_force.fit(X_train_force,y_train_force)
meilleurs_parametres.append(grid_1_force.best_params_)
model_1_force=grid_1_force.best_estimator_
score.append(model_1_force.score(X_test_force,y_test_force))
v_u.append(np.sum(model_1_force.coef_!=0))

'''à poil, humidite  '''

grid_1_humidite=GridSearchCV(Lasso(),param_grid,cv=5)
grid_1_humidite.fit(X_train_humidite,y_train_humidite)
meilleurs_parametres.append(grid_1_humidite.best_params_)
model_1_humidite=grid_1_humidite.best_estimator_
score.append(model_1_humidite.score(X_test_humidite,y_test_humidite))
v_u.append(np.sum(model_1_humidite.coef_!=0))

''' à poil, temperature '''
grid_1_temperature=GridSearchCV(Lasso(),param_grid,cv=5)
grid_1_temperature.fit(X_train_temperature,y_train_temperature)
meilleurs_parametres.append(grid_1_temperature.best_params_)
model_1_temperature=grid_1_temperature.best_estimator_
score.append(model_1_temperature.score(X_test_temperature,y_test_temperature))
v_u.append(np.sum(model_1_temperature.coef_!=0))

''' à poil, pression'''

grid_1_pression=GridSearchCV(Lasso(),param_grid,cv=5)
grid_1_pression.fit(X_train_pression,y_train_pression)
meilleurs_parametres.append(grid_1_pression.best_params_)
model_1_pression=grid_1_pression.best_estimator_
score.append(model_1_pression.score(X_test_pression,y_test_pression))
v_u.append(np.sum(model_1_pression.coef_!=0))

print(score)
print(meilleurs_parametres)
print(v_u)
print(model_1_direction.coef_)
print(model_1_force.coef_)
print(model_1_humidite.coef_)
print(model_1_temperature.coef_)
print(model_1_pression.coef_)


''' avec le pipeline1, direction'''

param_grid2={
    'lasso__alpha':[10,1,0.1,0.01,0.001],
    'lasso__max_iter':[100000]
    }

grid_2_direction=GridSearchCV(traitement_1,param_grid2,cv=5)
grid_2_direction.fit(X_train_direction,y_train_direction)
meilleurs_parametres.append(grid_2_direction.best_params_)
model_2_direction=grid_2_direction.best_estimator_
score.append(model_2_direction.score(X_test_direction,y_test_direction))


''' avec le pipeline1, force '''

grid_2_force=GridSearchCV(traitement_1,param_grid2,cv=5)
grid_2_force.fit(X_train_force,y_train_force)
meilleurs_parametres.append(grid_2_force.best_params_)
model_2_force=grid_2_force.best_estimator_
score.append(model_2_force.score(X_test_force,y_test_force))

''' avec le pipeline1, humidite  '''

grid_2_humidite=GridSearchCV(traitement_1,param_grid2,cv=5)
grid_2_humidite.fit(X_train_humidite,y_train_humidite)
meilleurs_parametres.append(grid_2_humidite.best_params_)
model_2_humidite=grid_2_humidite.best_estimator_
score.append(model_2_humidite.score(X_test_humidite,y_test_humidite))

'''avec le pipeline1, temperature'''

grid_2_temperature=GridSearchCV(traitement_1,param_grid2,cv=5)
grid_2_temperature.fit(X_train_temperature,y_train_temperature)
meilleurs_parametres.append(grid_2_temperature.best_params_)
model_2_temperature=grid_2_temperature.best_estimator_
score.append(model_2_temperature.score(X_test_temperature,y_test_temperature))

'''avec le pipeline1, pression'''

grid_2_pression=GridSearchCV(traitement_1,param_grid2,cv=5)
grid_2_pression.fit(X_train_pression,y_train_pression)
meilleurs_parametres.append(grid_2_pression.best_params_)
model_2_pression=grid_2_pression.best_estimator_
score.append(model_2_pression.score(X_test_pression,y_test_pression))


'''avec le pipeline2, direction'''

grid_3_direction=GridSearchCV(traitement_2,param_grid2,cv=5)
grid_3_direction.fit(X_train_direction,y_train_direction)
meilleurs_parametres.append(grid_3_direction.best_params_)
model_3_direction=grid_3_direction.best_estimator_
score.append(model_3_direction.score(X_test_direction,y_test_direction))

'''avec le pipeline2, force'''

grid_3_force=GridSearchCV(traitement_2,param_grid2,cv=5)
grid_3_force.fit(X_train_force,y_train_force)
meilleurs_parametres.append(grid_3_force.best_params_)
model_3_force=grid_3_force.best_estimator_
score.append(model_3_force.score(X_test_force,y_test_force))

'''avec le pipeline2, humidite'''

grid_3_humidite=GridSearchCV(traitement_2,param_grid2,cv=5)
grid_3_humidite.fit(X_train_humidite,y_train_humidite)
meilleurs_parametres.append(grid_3_humidite.best_params_)
model_3_humidite=grid_3_humidite.best_estimator_
score.append(model_3_humidite.score(X_test_humidite,y_test_humidite))

'''avec le pipeline2,temperature'''

grid_3_temperature=GridSearchCV(traitement_2,param_grid2,cv=5)
grid_3_temperature.fit(X_train_temperature,y_train_temperature)
meilleurs_parametres.append(grid_3_temperature.best_params_)
model_3_temperature=grid_3_temperature.best_estimator_
score.append(model_3_temperature.score(X_test_temperature,y_test_temperature))

'''avec le pipeline2,pression'''

grid_3_pression=GridSearchCV(traitement_2,param_grid2,cv=5)
grid_3_pression.fit(X_train_pression,y_train_pression)
meilleurs_parametres.append(grid_3_pression.best_params_)
model_3_pression=grid_3_pression.best_estimator_
score.append(model_3_pression.score(X_test_pression,y_test_pression))

'''avec le pipeline3,direction'''

grid_4_direction=GridSearchCV(traitement_3,param_grid2,cv=5)
grid_4_direction.fit(X_train_direction,y_train_direction)
meilleurs_parametres.append(grid_4_direction.best_params_)
model_4_direction=grid_4_direction.best_estimator_
score.append(model_4_direction.score(X_test_direction,y_test_direction))

'''avec le pipeline3,force'''

grid_4_force=GridSearchCV(traitement_3,param_grid2,cv=5)
grid_4_force.fit(X_train_force,y_train_force)
meilleurs_parametres.append(grid_4_force.best_params_)
model_4_force=grid_4_force.best_estimator_
score.append(model_4_force.score(X_test_force,y_test_force))


'''avec le pipeline3,humidite'''

grid_4_humidite=GridSearchCV(traitement_3,param_grid2,cv=5)
grid_4_humidite.fit(X_train_humidite,y_train_humidite)
meilleurs_parametres.append(grid_4_humidite.best_params_)
model_4_humidite=grid_4_humidite.best_estimator_
score.append(model_4_humidite.score(X_test_humidite,y_test_humidite))

'''avec le pipeline3,temperature'''

grid_4_temperature=GridSearchCV(traitement_3,param_grid2,cv=5)
grid_4_temperature.fit(X_train_temperature,y_train_temperature)
meilleurs_parametres.append(grid_4_temperature.best_params_)
model_4_temperature=grid_4_temperature.best_estimator_
score.append(model_4_temperature.score(X_test_temperature,y_test_temperature))

'''avec le pipeline3, pression'''

grid_4_pression=GridSearchCV(traitement_3,param_grid2,cv=5)
grid_4_pression.fit(X_train_pression,y_train_pression)
meilleurs_parametres.append(grid_4_pression.best_params_)
model_4_pression=grid_4_pression.best_estimator_
score.append(model_4_pression.score(X_test_pression,y_test_pression))


tableau_data=pd.DataFrame([score])
tableau_data.to_csv('scorelasso_12H.csv',sep='\t')
print(score)
print(meilleurs_parametres)
print(v_u)

N_direction,train_score_direction,val_score_direction=learning_curve(Lasso(),X_train_direction,y_train_direction,train_sizes=np.linspace(0.1,1,10),cv=5)
N_force,train_score_force,val_score_force=learning_curve(Lasso(),X_train_force,y_train_force,train_sizes=np.linspace(0.1,1,10),cv=5)
N_pression,train_score_pression,val_score_pression=learning_curve(Lasso(),X_train_pression,y_train_pression,train_sizes=np.linspace(0.1,1,10),cv=5)
N_humidite,train_score_humidite,val_score_humidite=learning_curve(Lasso(),X_train_humidite,y_train_humidite,train_sizes=np.linspace(0.1,1,10),cv=5)
N_temperature,train_score_temperature,val_score_temperature=learning_curve(Lasso(),X_train_temperature,y_train_temperature,train_sizes=np.linspace(0.1,1,10),cv=5)

plt.figure(figsize=[12,12])
plt.subplot(5,1,1)
plt.title("direction")
plt.plot(N_direction,train_score_direction.mean(axis=1),label='train')
plt.plot(N_direction,val_score_direction.mean(axis=1),label='validation')
plt.xlabel('train_sizes')
plt.legend()
plt.subplot(5,1,2)
plt.title("force")
plt.plot(N_force,train_score_force.mean(axis=1),label='train')
plt.plot(N_force,val_score_force.mean(axis=1),label='validation')
plt.xlabel('train_sizes')
plt.legend()
plt.subplot(5,1,3)
plt.title('pression')
plt.plot(N_pression,train_score_pression.mean(axis=1),label='train')
plt.plot(N_pression,val_score_pression.mean(axis=1),label='validation')
plt.xlabel('train_sizes')
plt.legend()
plt.subplot(5,1,4)
plt.title('humidite')
plt.plot(N_humidite,train_score_humidite.mean(axis=1),label='train')
plt.plot(N_humidite,val_score_humidite.mean(axis=1),label='validation')
plt.xlabel('train_sizes')
plt.legend()
plt.subplot(5,1,5)
plt.title('temperature')
plt.plot(N_temperature,train_score_temperature.mean(axis=1),label='train')
plt.plot(N_temperature,train_score_temperature.mean(axis=1),label='validation')
plt.xlabel('train_sizes')
plt.legend()

Les courbes scores sont presque pareilles, donc passons aux courbes d’apprentissage:

La courbe de validation se fait de façon encore plus progressive.

Voici les résultats trouvé pour une prédiction à 12 heures selon les divers traitements:

directionforcehumiditétempératurepression
sans traitement24%21%21%86%85%
MinMaxScaler25%18%24%86%85%
RobustScaler25%20%23%81%86%
StandardScaler24%20%22%86%85%

Et maintenant comme on a vu avant, avec le mode lasso on peut savoir quelles variables comptent pour nous, on a alors ça:

directionforcehumiditétempératurepression
nombre de variables utilisées pour la prédiction2541294050

J’ai fait le test pour des heures de prédiction plus proches et moins proches, ça varie mais ça reste aux alentours des mêmes valeurs grosso modo. La direction du vent utilise moins de variables. En exécutant le code on voit les variables « jetées » dans les arrays. Il faudra que je regarde tout ça plus en détail pour la suite.

Les forêts aléatoires

Pour avoir une bonne explication du bidule , allez sur wikipépé ou d’autres liens parce que je crois que je vais dire des conneries…Bon temps pis je me lance: on sélectionne un nombre d’arbres de décision pour notre forêt, pour chaque arbre on pioche au hasard des échantillon dans nos données. Du coup chaque arbre va être un peu différend des autres lors de leur construction à l’entrainement. Ensuite pour la prédiction on fait la moyenne (ou la majorité je ne sais plus) des résultats trouvés par nos arbres. Le prog ça donne ça:

from sklearn.ensemble import RandomForestRegressor # technique des forêts aléatoires pour les regressions.

from sklearn.model_selection import train_test_split # partage nos données en données test et entrainement (ratio réglé ici via test_size à 20%/80%)
from sklearn.model_selection import GridSearchCV # permet de trouver plus facilement les meilleurs paramètres de réglage du modèle.
from sklearn.model_selection import learning_curve # estime la limite de performance d'un modèle.

from sklearn.pipeline import make_pipeline # assemble un ou des transfomateurs de données et un estimateur, évite les fuites de données et réduit le code, donc évite les erreurs aussi.

from sklearn.preprocessing import MinMaxScaler # traitement de données, normalisation où nos variables deviennent comprises entre 0 et 1.
from sklearn.preprocessing import RobustScaler # traitement de données moins sujet aux outliers (échantillons aberrantes).
from sklearn.preprocessing import StandardScaler # traitement de donnée, rend la moyenne nulle et l'écart-type égal à un.


import numpy as np # permet de manipuler les array.
import pandas as pd # permet de manipuler les dataframes.

import matplotlib.pyplot as plt

deauville3=pd.read_csv('C:/Users/Psychopathe/Documents/Python Scripts/meteo/station maison/samedi24octobre/Deauville_le_retour.csv',sep='\t') # on importe les données.

deauville3=deauville3.drop(['Unnamed: 0'],axis=1) # on vire la colonne inutile pour pas pourrir l'entrainement du modèle.

Vars_training=deauville3.iloc[:-1,:] # les données d'entrainements sont reprises sauf la dernière ligne pour ajuster le nombre de lignes entre les données et les variables cibles.
direction_train=deauville3.iloc[1:,30] # données cibles. Ici c'est la direction du vent 6 heures après.
force_train=deauville3.iloc[1:,31] # données cibles. Ici c'est la force du vent 6 heures après.
humidite_train=deauville3.iloc[1:,32] # données cibles, ici pourcentage d'humidité 6 heures après.
temperature_train=deauville3.iloc[1:,33] # données cibles, ici la température 6 heures après.
pression_train=deauville3.iloc[1:,34] # données cibles, ici la pression atmosphérique 6 heures après.

''' on sépare données entrainement et test pour toutes nos variables que l'on veut tester '''

X_train_direction,X_test_direction,y_train_direction,y_test_direction=train_test_split(Vars_training,direction_train,test_size=0.2,random_state=0)
X_train_force,X_test_force,y_train_force,y_test_force=train_test_split(Vars_training,force_train,test_size=0.2,random_state=0)
X_train_humidite,X_test_humidite,y_train_humidite,y_test_humidite=train_test_split(Vars_training,humidite_train,test_size=0.2,random_state=0)
X_train_temperature,X_test_temperature,y_train_temperature,y_test_temperature=train_test_split(Vars_training,temperature_train,test_size=0.2,random_state=0)
X_train_pression,X_test_pression,y_train_pression,y_test_pression=train_test_split(Vars_training,pression_train,test_size=0.2,random_state=0)

traitement_1=make_pipeline(MinMaxScaler(),RandomForestRegressor()) # création de l'objet pipeline1.
traitement_2=make_pipeline(RobustScaler(),RandomForestRegressor()) # création du pipeline2.
traitement_3=make_pipeline(StandardScaler(),RandomForestRegressor()) # création du pipeline3.

''' premier essai sans prétraitement, à poil , direction du vent   '''

param_grid={
    'n_estimators':[5,10,50,100,150,200],
    
    
    }

grid_1_direction=GridSearchCV(RandomForestRegressor(),param_grid,cv=5)
grid_1_direction.fit(X_train_direction,y_train_direction)
print(grid_1_direction.best_params_)
model_1_direction=grid_1_direction.best_estimator_
print(model_1_direction.score(X_test_direction,y_test_direction))

''' à poil, force du vent '''

grid_1_force=GridSearchCV(RandomForestRegressor(),param_grid,cv=5)
grid_1_force.fit(X_train_force,y_train_force)
print(grid_1_force.best_params_)
model_1_force=grid_1_force.best_estimator_
print(model_1_force.score(X_test_force,y_test_force))

'''à poil, humidite  '''

grid_1_humidite=GridSearchCV(RandomForestRegressor(),param_grid,cv=5)
grid_1_humidite.fit(X_train_humidite,y_train_humidite)
print(grid_1_humidite.best_params_)
model_1_humidite=grid_1_humidite.best_estimator_
print(model_1_humidite.score(X_test_humidite,y_test_humidite))

''' à poil, temperature '''
grid_1_temperature=GridSearchCV(RandomForestRegressor(),param_grid,cv=5)
grid_1_temperature.fit(X_train_temperature,y_train_temperature)
print(grid_1_temperature.best_params_)
model_1_temperature=grid_1_temperature.best_estimator_
print(model_1_temperature.score(X_test_temperature,y_test_temperature))

''' à poil, pression'''

grid_1_pression=GridSearchCV(RandomForestRegressor(),param_grid,cv=5)
grid_1_pression.fit(X_train_pression,y_train_pression)
print(grid_1_pression.best_params_)
model_1_pression=grid_1_pression.best_estimator_
print(model_1_pression.score(X_test_pression,y_test_pression))


''' avec le pipeline1, direction'''

param_grid2={
    'randomforestregressor__n_estimators':[5,10,50,100,150,200]
    }

grid_2_direction=GridSearchCV(traitement_1,param_grid2,cv=5)
grid_2_direction.fit(X_train_direction,y_train_direction)
print(grid_2_direction.best_params_)
model_2_direction=grid_2_direction.best_estimator_
print(model_2_direction.score(X_test_direction,y_test_direction))

''' avec le pipeline1, force '''

grid_2_force=GridSearchCV(traitement_1,param_grid2,cv=5)
grid_2_force.fit(X_train_force,y_train_force)
print(grid_2_force.best_params_)
model_2_force=grid_2_force.best_estimator_
print(model_2_force.score(X_test_force,y_test_force))

''' avec le pipeline1, humidite  '''

grid_2_humidite=GridSearchCV(traitement_1,param_grid2,cv=5)
grid_2_humidite.fit(X_train_humidite,y_train_humidite)
print(grid_2_humidite.best_params_)
model_2_humidite=grid_2_humidite.best_estimator_
print(model_2_humidite.score(X_test_humidite,y_test_humidite))

'''avec le pipeline1, temperature'''

grid_2_temperature=GridSearchCV(traitement_1,param_grid2,cv=5)
grid_2_temperature.fit(X_train_temperature,y_train_temperature)
print(grid_2_temperature.best_params_)
model_2_temperature=grid_2_temperature.best_estimator_
print(model_2_temperature.score(X_test_temperature,y_test_temperature))

'''avec le pipeline1, pression'''

grid_2_pression=GridSearchCV(traitement_1,param_grid2,cv=5)
grid_2_pression.fit(X_train_pression,y_train_pression)
print(grid_2_pression.best_params_)
model_2_pression=grid_2_pression.best_estimator_
print(model_2_pression.score(X_test_pression,y_test_pression))

'''avec le pipeline2, direction'''

grid_3_direction=GridSearchCV(traitement_2,param_grid2,cv=5)
grid_3_direction.fit(X_train_direction,y_train_direction)
print(grid_3_direction.best_params_)
model_3_direction=grid_3_direction.best_estimator_
print(model_3_direction.score(X_test_direction,y_test_direction))

'''avec le pipeline2, force'''

grid_3_force=GridSearchCV(traitement_2,param_grid2,cv=5)
grid_3_force.fit(X_train_force,y_train_force)
print(grid_3_force.best_params_)
model_3_force=grid_3_force.best_estimator_
print(model_3_force.score(X_test_force,y_test_force))

'''avec le pipeline2, humidite'''

grid_3_humidite=GridSearchCV(traitement_2,param_grid2,cv=5)
grid_3_humidite.fit(X_train_humidite,y_train_humidite)
print(grid_3_humidite.best_params_)
model_3_humidite=grid_3_humidite.best_estimator_
print(model_3_humidite.score(X_test_humidite,y_test_humidite))

'''avec le pipeline2,temperature'''

grid_3_temperature=GridSearchCV(traitement_2,param_grid2,cv=5)
grid_3_temperature.fit(X_train_temperature,y_train_temperature)
print(grid_3_temperature.best_params_)
model_3_temperature=grid_3_temperature.best_estimator_
print(model_3_temperature.score(X_test_temperature,y_test_temperature))

'''avec le pipeline2,pression'''

grid_3_pression=GridSearchCV(traitement_2,param_grid2,cv=5)
grid_3_pression.fit(X_train_pression,y_train_pression)
print(grid_3_pression.best_params_)
model_3_pression=grid_3_pression.best_estimator_
print(model_3_pression.score(X_test_pression,y_test_pression))

'''avec le pipeline3,direction'''

grid_4_direction=GridSearchCV(traitement_3,param_grid2,cv=5)
grid_4_direction.fit(X_train_direction,y_train_direction)
print(grid_4_direction.best_params_)
model_4_direction=grid_4_direction.best_estimator_
print(model_4_direction.score(X_test_direction,y_test_direction))

'''avec le pipeline3,force'''

grid_4_force=GridSearchCV(traitement_3,param_grid2,cv=5)
grid_4_force.fit(X_train_force,y_train_force)
print(grid_4_force.best_params_)
model_4_force=grid_4_force.best_estimator_
print(model_4_force.score(X_test_force,y_test_force))

'''avec le pipeline3,humidite'''

grid_4_humidite=GridSearchCV(traitement_3,param_grid2,cv=5)
grid_4_humidite.fit(X_train_humidite,y_train_humidite)
print(grid_4_humidite.best_params_)
model_4_humidite=grid_4_humidite.best_estimator_
print(model_4_humidite.score(X_test_humidite,y_test_humidite))

'''avec le pipeline3,temperature'''

grid_4_temperature=GridSearchCV(traitement_3,param_grid2,cv=5)
grid_4_temperature.fit(X_train_temperature,y_train_temperature)
print(grid_4_temperature.best_params_)
model_4_temperature=grid_4_temperature.best_estimator_
print(model_4_temperature.score(X_test_temperature,y_test_temperature))

'''avec le pipeline3, pression'''

grid_4_pression=GridSearchCV(traitement_3,param_grid2,cv=5)
grid_4_pression.fit(X_train_pression,y_train_pression)
print(grid_4_pression.best_params_)
model_4_pression=grid_4_pression.best_estimator_
print(model_4_pression.score(X_test_pression,y_test_pression))




N_direction,train_score_direction,val_score_direction=learning_curve(traitement_1,X_train_direction,y_train_direction,train_sizes=np.linspace(0.1,1,10),cv=5)
N_force,train_score_force,val_score_force=learning_curve(traitement_1,X_train_force,y_train_force,train_sizes=np.linspace(0.1,1,10),cv=5)
N_pression,train_score_pression,val_score_pression=learning_curve(traitement_1,X_train_pression,y_train_pression,train_sizes=np.linspace(0.1,1,10),cv=5)
N_humidite,train_score_humidite,val_score_humidite=learning_curve(traitement_1,X_train_humidite,y_train_humidite,train_sizes=np.linspace(0.1,1,10),cv=5)
N_temperature,train_score_temperature,val_score_temperature=learning_curve(traitement_1,X_train_temperature,y_train_temperature,train_sizes=np.linspace(0.1,1,10),cv=5)

plt.figure(figsize=[12,12])
plt.subplot(5,1,1)
plt.title("direction")
plt.plot(N_direction,train_score_direction.mean(axis=1),label='train')
plt.plot(N_direction,val_score_direction.mean(axis=1),label='validation')
plt.xlabel('train_sizes')
plt.legend()
plt.subplot(5,1,2)
plt.title("force")
plt.plot(N_force,train_score_force.mean(axis=1),label='train')
plt.plot(N_force,val_score_force.mean(axis=1),label='validation')
plt.xlabel('train_sizes')
plt.legend()
plt.subplot(5,1,3)
plt.title('pression')
plt.plot(N_pression,train_score_pression.mean(axis=1),label='train')
plt.plot(N_pression,val_score_pression.mean(axis=1),label='validation')
plt.xlabel('train_sizes')
plt.legend()
plt.subplot(5,1,4)
plt.title('humidite')
plt.plot(N_humidite,train_score_humidite.mean(axis=1),label='train')
plt.plot(N_humidite,val_score_humidite.mean(axis=1),label='validation')
plt.xlabel('train_sizes')
plt.legend()
plt.subplot(5,1,5)
plt.title('temperature')
plt.plot(N_temperature,train_score_temperature.mean(axis=1),label='train')
plt.plot(N_temperature,train_score_temperature.mean(axis=1),label='validation')
plt.xlabel('train_sizes')
plt.legend()

la courbe d’apprentissage:

Ca rappelle un peu les voisins…Va falloir trouver une explication à ces courbes que je n’ai pas pour le moment. En général les paramètres les plus efficaces tournent à au moins 150 arbres. Si vous faites juste un potager avec 2 radis ça marchera pas trop.

Et maintenant les résultats selon le pré traitement, comme prévu ça ne varie pas beaucoup:

directionforcehumiditétempératurepression
sans traitement22%15%28%87%83%
MinMAxScaler23%15%29%87%84%
robustScaler24%14%31%89%83%
StandardScaler25%15%27%89%83%

BILAN

Au final, pour une précision à 12 heures il semblerait que notre jeu de données est un peu faiblard, particulièrement pour la direction du vent (au mieux un score de 25%), sa force (21% au mieux) et l’humidité (31%). La différence d’efficacité entre chaque modèle n’est pas vraiment tranchée pour le moment, tout comme les traitements différends. Ce qui est rassurant c’est de voir que toutes nos variables décroissent en score avec une prévision plus avancée, donc à priori si on rajoute des échantillons on va peut-être avoir une chance d’améliorer nos scores.

Donc pour la suite il va falloir:

  • Tester nos données en deep learning avec un réseau de neurones virtuels, pour commencer via un perceptron multicouches (MLP), le plus simple .
  • Tester nos données « densifiées » pour voir ce que ça donne via un dataframe de toujours 1096 lignes pour cette fois 120 colonnes (variables toutes les heures).
  • Evidemment, agrandir notre jeu, en prenant cette fois au moins 40 stations météo (ça fera donc un dataframe de 43840 échantillons pour 60 ou 120 colonnes ou autre à voir). On prendra si possible les stations plus gouda que gruyère, même si j’aime le gruyère dans les pâtes.
  • Creuser plus les fonctionnalités du mode Lasso pour bien voir quelles sont les variables utiles, ça va peut-être nous servir.
  • Eventuellement veiller à reconfigurer nos données ou leur mise en forme dans notre dataframe pour plus d’efficacité. En effet, nos variables sont de nature très différentes: on a des degrés, des degrés celsius, des vitesses, des pourcentages et des pressions.

Avec tout ça on devrait pas trop s’emmerder en somme.

1) Météo et machine learning

L’objectif final (actuel, ça changera peut-être au cours du temps on verra) de cette nouvelle suite d’articles sera de fabriquer une station météo embarquée fonctionnant en machine learning ou deep learning, bref capable de prédire avec le plus de précision possible le temps qu’il fera ensuite, un peu comme une miss météo de canal mais en moins sexy, et en moins lourdingue également.

Partie 1: machine/deep learning

Ce concept date en fait de plusieurs décennies; à l’époque on se creusait déjà le ciboulot pour rédiger des algorithmes capables de se modifier en comparant leur résultat au données réelles, bref capables « d’apprendre » pour petit à petit fournir des réponses de plus en plus efficaces. Même si on parle beaucoup de l’intelligence artificielle actuellement, le pitch ne date pas d’hier; c’est la puissance de calcul et de traitement de données de nos ordinateurs contemporains qui permettent d’exploiter pleinement le potentiel du bidule. Cette idée de « machine apprenante » est très utile dans des domaines comme la reconnaissance d’images ou de formes, voix, détecter des tumeurs, classer des objets, traduire des textes…

Pour tenter de résumer de façon extrêmement succinte ce concept (et en racontant le moins de conneries possibles)…

a) Le machine learning

Il regroupe tout un ensemble de techniques basées sur des statistiques, de calcul pour pouvoir écrire des programmes ; on peut les regrouper en 3 principales catégories comme:

  • L’apprentissage supervisé où on va entraîner le programme à devenir de plus en plus performant en comparant ses données calculées et le résultat attendu. Cette forme d’apprentissage est utilisée beaucoup dans les programmes de classement ou de prévision, et c’est la forme de machine learning la plus couramment rencontrée.
  • L’apprentissage non supervisé où là le programme va repérer des points communs entre les objets étudiés, pour ensuite faire émerger des catégories (les frimeurs parlent de « clustering »). Ces algos sont très utilisés pour les logiciels de proposition de vente sur internet selon le profil de l’utilisateur (son âge, ses goûts, son style de vie etc..) par exemple (mais si, les fenêtres qui s’affichent pour acheter du viagra quand vous ouvrez une page web et qui font bien chier souvenez vous).
  • L’apprentissage par renforcement où le programme va apprendre et s’améliorer un peu avec une logique « essai/erreur » ; il donne une bonne réponse il gagne un susucre, une mauvaise a pas de susucre (en gros). Bref plus il se gave de susucres, plus il est bon, sans les aléas du choléstérol, c’est fou.

Si l’on travaille sur des données qualitatives comme par exemple classer un objet dans une catégorie (problème de classement) ou alors quantitatives comme calculer un salaire moyen selon plusieurs critères (problème de régression), les techniques utilisées vont différer. Voici en gros quelques techniques répandues:

  • Les K plus proches voisins: technique la plus simple à comprendre. Le programme compare les caractéristiques d’un objet avec celles des objets enregistrés dans sa banque de données, puis classe l’objet dans la classe de l’objet (ou majorité de groupe d’objets) le plus proche. En gros plus la banque de données est conséquente, plus ça va fonctionner. Par contre le temps de calcul prédictif est de plus en plus long. Fonctionne pour les problèmes de classement et de régression.
  • Les Bayésien naifs: cette technique classe les objets selon leurs caractéristiques mais considère qu’il n’y a pas de corrélations entre ces caractéristiques (traite indépendamment les variables à la fois). Du coup rapide en calcul mais pas toujours précis en résultat. par rapport à d’autres modèles.
  • Les arbres de décision: ça fonctionne un peu comme un livre dont vous êtes le héro; on part d’une racine, puis à chaque étape un test du style « si/sinon »sépare le chemin de données en 2. l’arbre se termine par des « feuilles » correspondant à la classe de l’objet ou le nombre à trouver. Fonctionne pour les régressions et les classements.
  • La régression linéaire: la plus simple. On utilise une fonction linéaire pour prédire des données, pour cela on rédige une fonction linéaire qui ressemble à une fonction affine dont les paramètre sont les poids et les biais; ces paramètres vont nous permettre de rédiger une fonction calculant l’erreur (différence entre ce que l’on calcule et la réponse attendue,c’est la fonction de coût) que l’on va minimiser un maximum par rapport aux poids, généralement avec la technique de descente de gradient. Comme son nom l’indique, utilisé pour les régressions.
  • Régressions Ridge/lasso: c’est un modèle linéaire pour la régression mais cette fois il va chercher à minimiser les coefficients d’erreur (de pondération) pour limiter le surapprentissage pour le mode ridge. En configuration lasso certains coefficients tombent même à zéro donc c’est parfois utile pour simplifier un modèle ou repérer les caractéristiques qui comptent vraiment pour nos calculs.

Chaque modèle va avoir ses qualités et ses défauts selon l’usage. Le choix de l’un des ces modèles va dépendre de plusieurs facteurs comme le nombre de dimensions traitées dans notre tableau de données, le nombre de caractéristiques par rapport au nombre d’échantillons, le nombre de corrélations entre nos caractéristiques, si notre problème est un classement ou une régression, notre capacité de calcul, l’étendue de notre jeu de données, votre groupe sanguin ainsi que votre signe astral et si vous êtes plutôt slip ou caleçon.

b) Le deep learning

Cette fois on va mobiliser des réseaux de neurones « virtuels » (des fonctions telles que des sommes pondérées et des fonctions non linéaires la plupart du temps comme la fonction RELU par exemple) pour classer, prédire, faire le café…Actuellement ce type de modèle est l’un des plus efficace, mais son efficacité se fait au détriment d’une simplicité de configuration et d’un temps d’entrainement parfois long. On va chercher à minimiser une fonction de coût (l’erreur) par rétropropagation de l’information.

Partie 2: Le projet en plus détaillé

Pour le moment, l’idée finale va être d’utiliser une carte raspberry pi pour fabriquer une station météo embarquée. Cette station va capter la pression atmosphérique, la température et l’hygrométrie via un BME 280 (capteur électronique), la vitesse et la direction du vent via un anémo. En navigation, ce qui nous intéresse le plus c’est la force et la direction du vent, donc notre bidule devra prédire au moins ces 2 paramètres. Pour entraîner notre programme, on va se servir des données en open source de météo France. Voilà grosso merdo le projet actuellement. On se concentrera sur le nord ouest de la France pour le moment. Notre problème est donc ici clairement un problème de régression. Bon honnêtement ce serait bien prétentieux d’envisager des résultats conséquents sachant qu’il n’y a pas plus complexe et chaotique que la météo comme système, mais comme disait Jean-Louis Socrate (ou Bernard Platon je sais plus):

« En négo, si tu veux avoir un sandwich jambon fromage, vise l’américain

steak/oignons/salade/oeufs/poulet/cornichons !!! »

Si je peux décrocher un cornichon dans mon jambon fromage ce sera déjà pas si mal !

a) Les données de météo France

Accessibles via leur site ou sur kaggle (banque de données en ligne gratuite pour data scientists ou bidouilleurs) ces données comprennent les enregistrements sur 2016,2017 et 2018 de 262 stations dans le nord ouest de la France (donc pour nous la Manche, l’Atlantique) et aussi des stations dans le sud est (Mediterranée). Ces données intègrent : le numéro des stations, la date, la localisation (latitude/longitude) , la pression atmosphérique, l’altitude de la mesure, la température, le point de rosée, l’humidité, la vitesse du vent, la direction du vent, la quantité de précipitations. Les données sont enregistrées pour toutes les stations toutes les 6 minutes, ça fait donc un gros paquet d’infos !

b) Raspberry pi

C’est un peu comme un mini ordinateur avec un processeur ARM (moins puissant mais aussi plus économe et facilitant donc son utilisation en embarqué). On va s’en servir comme cerveau pour notre projet. Ici on va utiliser le modèle raspberry pi zero puis 3 b+.

Raspberry pi zero

Raspberry pi 3 b+

c) Ressources pour guider un bidouilleur complètement paumé

Pour pouvoir mener à bien ce projet je me suis servi des 30 vidéos de la chaine « machine learnia » sur youtube, qui propose un cour gratuit de machine learning/python très clair et très bien expliqué sur le sujet, le bouquin de Yann le Cun « quand la machine apprend », le bouquin d’Emmanuel Jakobowicz « Python pour le data scientist » (particulièrement bien pour apprendre pandas, numpy, matplotlib et comment bien préparer nos données avant usage), et aussi le livre « le machine learning avec python » de C Muller et S Guido (plutôt bon pour vulgariser et expliquer les différents modèles de machine/deep learning et comment les utiliser avec sklearn).

d) Ressources autres

Pour pouvoir programmer en python j’ai téléchargé anaconda. J’utilise principalement l’environnement de programmation spyder. Les packages (équivalents aux bibliothèques arduino par exemple) que l’on va manipuler pour bosser:

  • Numpy: permet de créer/manipuler des tableaux, des matrices de données (ndarray).
  • Pandas: permet de créer/manipuler des « dataframes »,structures de données un peu comme des dictionnaires de listes, ou encore des sortes de tableaux indexés.
  • Matplotlib: permet de faire de joli petits graphiques tout beaux tout mignons avec plein de couleurs, des chiffres…Et aussi d’identifier, visualiser les liens entre nos données (ou pas).
  • Seaborn: permet également de faire des graphiques, en se prenant moins la tête.
  • Sklearn: intègre presque tout les modèles/techniques de base en machine/deep learning. Il permet de tester et prédire nos données. Très intéressant car la méthode pour utiliser chaque modèle est quasiment la même à chaque fois, seul les hyperparamètres et leurs réglages diffèrent la plupart du temps.

e) Pourquoi ce projet, et surtout comment être à peu près sûr que ça devrait marcher (un peu).

La zone couverte par notre fichier comprend la Manche et également une bonne partie du Golfe de Gascogne; ces 2 zones ont une météo globale qui diffère c’est vrai mais en gros cet endroit est soumis au passage des dépressions, et on peut prédire à partir de variables notre position approximative dans le système en jeu. Par exemple Un vent qui tourne Nord Ouest avec une hausse rapide de pression et une baisse de l’humidité ainsi qu’une baisse de température augure généralement un passage de front froid, ou encore une montée de l’humidité, une baisse de pression et un passage du vent à l’ouest l’arrivée d’une dépression…

Evidemment notre système sera bien loin d’être aussi précis qu’une prévision normale bénéficiant d’une vue d’ensemble de toutes les balises météo en temps réel sur toute la zone avec une puissance de calcul conséquente, mais ça devrait peut-être rendre un truc intéressant. En tout cas pour l’étude de nos données on devrait pouvoir faire apparaître des liens entre nos variables:

  • Les stations ayant une altitude élevée devraient moins subir les forces de frottements, donc avoir une direction de vent ainsi qu’une force de vent enregistrées un peu différentes. En effet il ne faut pas oublier que le vent synoptique (vent à 10 mètres d’altitude) ne fait que 2/3 du vent géostrophique (plus haut, sans les frottements).
  • Les stations ayant une latitude plus élevée devraient être plus soumises à la force de Coriolis, donc avoir une direction de vent un peu différente pour les mêmes variables annexes en jeu, et un vent moins fort pour un même changement de pression. En effet sur les cartes isobariques de surface, plus on est bas en latitude et plus cet écart indique un vent géostrophique fort.
  • Plus les stations sont hautes en altitude, plus la pression atmosphérique va descendre pour un même relevé.
  • Comme indiqué précédemment, un changement de direction de vent couplé à un changement de pression, température, humidité est souvent un signe de passage de front chaud ou froid, donc utile pour prévoir ce qui va se passer.
  • L’équation d’état bien connue reliant la pression, le volume et la température : P*V=R*T (R constante).

Bref, va y avoir du boulot…

Partie 3: organiser les données et utiliser la bonne technique sur un pc portable (processeur basique x86 de 32 bits).

Pour le moment on va utiliser le pc portable; on verra ensuite avec notre raspberry. Les contraintes au niveau puissance de calcul, consommation d’énergie, architecture du processeur qui peut empêcher l’usage de certains packages, ce sera pour plus tard, comme on dit une emmerde à la fois (si possible).

a) Importer les données meteo-France

Comme les fichiers csv des données de 2016, 2017 et 2018 sont conséquents il n’est pas possible de directement les lire et les stocker dans un dataframe (ce serait trop simple…) donc il va falloir bidouiller. Au départ j’ai essayé d’utiliser le package « dask » pour pouvoir traiter les données comme dans pandas (dask permet au lieu de stocker l’info dans un dataframe, de la stocker dans plein de petits dataframes englobés dans un grand dataframe, donc de paralléliser le traitement des données). Dask regroupe quasiment toutes les fonctionnalités de pandas mais pas tout, et du coup c’était laborieux pour un novice innocent vierge de toute les vicissitudes amères de la vie comme moi…

Donc pour faire tenir tout dans un seul dataframe, j’ai lu, traité via une fonction (j’ai écrit le module « fon_changer » qui contient la fonction « changer ») et importé le csv par morceaux dans une liste que j’ai ensuite concaténé. La fonction « changer » agit comme un filtre qui en gros supprime les colonnes « point de rosée » et « précipitations » (inutiles pour nous), ne garde que les données toutes les quatre heures, et ne garde que les stations qui remplissent tout les champs de données (49 au final sur 262). Certaines données sont également converties pour être plus pertinentes ou prendre moins de mémoire (float en int).

Voici le module « fon_changer » avec la fonction « changer »:

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
from datetime import datetime

def changer(data_1):
    
     data_1=data_1.sort_values(by=['number_sta','date'],ascending=True) #met les données dans l'ordre de chacune station, puis dans l'ordre temporel.

     data_1=data_1.drop(['precip','td'],axis=1) #on se débarrasse des colonnes inutiles pour nous.

     data_1=data_1.set_index('date') #on indexe notre dataframe sur le temps.

     data_1=data_1.fillna(data_1.rolling(window=1).mean()) #remplit les nan par la valeur moyenne de la journée pour chaque station.

     data_1=data_1.dropna(axis=0) #on se débarrasse des stations dont un champ de données n'est pas renseigné du tout.

     data_1.index=pd.to_datetime(data_1.index) #on convertit les index en objets datetime pour mieux les manipuler.

     heure_1=data_1[(data_1.index.hour==0) & (data_1.index.minute==0) & (data_1.index.second==0)] #on conserve juste les données toutes les quatre heures pour chaque station.
     heure_2=data_1[(data_1.index.hour==4) & (data_1.index.minute==0) & (data_1.index.second==0)]
     heure_3=data_1[(data_1.index.hour==8) & (data_1.index.minute==0) & (data_1.index.second==0)]
     heure_4=data_1[(data_1.index.hour==12) & (data_1.index.minute==0) & (data_1.index.second==0)]
     heure_5=data_1[(data_1.index.hour==16) & (data_1.index.minute==0) & (data_1.index.second==0)]
     heure_6=data_1[(data_1.index.hour==20) & (data_1.index.minute==0) & (data_1.index.second==0)]

     liste2=[heure_1,heure_2,heure_3,heure_4,heure_5,heure_6]
     data_one=pd.concat(liste2,axis=0)
     data_one=data_one.sort_values(by=['number_sta','date'],ascending=True)

     data_one['t']=data_one['t'].map(lambda x:int(x-273.15)) #convertit les Kelvin en degrés celsius.
     data_one['psl']=data_one['psl'].map(lambda x:int(x/100)) #convertit les pascals en hectopascals.
     data_one['hu']=data_one['hu'].map(lambda x:int(x)) #change en entier
     data_one['dd']=data_one['dd'].map(lambda x:int(x)) #pareil
     data_one['height_sta']=data_one['height_sta'].map(lambda x:int(x)) #encore pareil
     data_one['ff']=data_one['ff'].map(lambda x:int(x*3600/1852)) #change la vitesse du vent en noeuds.
     
     return data_one # renvoie les données "filtrées"

« nan » signifie « not a number », en général il faut combler ces trous soit en virant complètement l’échantillon, soit en estimant la donnée manquante via différentes méthodes(moyennes, nombres quelconques,nombres précédents…).

Et maintenant le petit programme pour filtrer nos données pour chaque année (ici c’est 2016 dans notre exemple):

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from fon_changer import changer

chunksize=100000 # on définit la taille de chaque tronçon de données que l'on va passer à la moulinette.
chunks=[] # Cette liste va recueillir les tronçons filtrés.

for chunk in pd.read_csv("C:/Users/Psychopathe/Documents/cours tech/machine learning/meteonet-master/NW_Ground_Stations/Meteo_NW_2016.csv",chunksize=chunksize):
    filtered=changer(chunk) # on filtre le tronçon.
    chunks.append(filtered) # on remplit notre liste au fur et à mesure.
data_meteo_2016=pd.concat(chunks,axis=0) # on compile les données filtrées dans un seul dataframe.
data_meteo_2016.to_csv('data_meteo_2016.csv',sep='\t') # on stocke tout ça dans un fichier csv.

Une fois que l’on a fait tout ça pour les 3 années, il suffit d’importer les 3 fichiers csv puis les concaténer dans une liste afin d’obtenir un dataframe global pour les 3 ans du Nord-Ouest de la France, purgé des données inutiles pour nous.

b) Analyse des données traitées

Les pairplots

En utilisant seaborn, on peut faire un premier coup d’oeil rapide sur nos données du nord_ouest filtrées en faisant un « pairplot ». Ce tableau de graphiques met en corrélation des variables sélectionnées au préalable sur notre jeu de données; sur la diagonale ce sont les distributions de toutes les variables. J’ai fait deux pairplots sur les données; un où l’on visualise avec la couleur les variables selon la hauteur de l’observation, et un autre avec la latitude de l’observation. Ca donne ça:

Ce premier pairplot utilise la couleur pour voir les variables aussi selon la hauteur des stations météo (en mètres).

Ce second pairplot avec les couleurs indique nos variables selon la latitude d’observation.

Pour nos variables:

dd=direction du vent en degrés.

ff=force du vent en noeuds.

hu=humidité en pourcentage.

t=tétine en tétinou-octets. Meuh nan c’est la température !

psl=pression atmosphérique en hectopascals.

Premières observations :

  • La direction du vent est le plus souvent d’ouest, ensuite plutôt nord en moyenne (distplot dd).
  • La force du vent dépasse rarement les 25 noeuds en moyenne. La courbe des forces enregistrées décroit très vite (distplot ff).
  • L’humidité est le plus souvent élevée, autour de 80% environ (distplot hu).
  • La température est généralement autour de 10 °C (distplot t).
  • La pression tourne autour de 1015 hectopascals en moyenne (distplot psl).

Secondes observations:

  • Les stations ayant une latitude plus faible ont un pourcentage d’humidité global plus bas.
  • Il semblerait que plus l’humidité augmente, plus la force du vent peut potentiellement augmenter jusqu’à une sorte de seuil. Par exemple d’après nos données, une humidité de moins de 50% n’indique pas de vent au-dessus de 40 noeuds normalement.
  • Il semble que plus la température se rapproche de 10°C, plus elle peut potentiellement induire des vents forts.
  • C’est léger, mais il semble que plus la direction du vent se rapproche du Nord ouest, plus le vent peut potentiellement être fort.
  • Au-delà d’une pression de 1010 hectopascals environ, la force de vent potentielle maximale décroit progressivement.
  • Concernant la direction du vent il est bien plus délicat de trouver des corrélations avec les autres variables à priori.

Bon, pour le moment on est pas très avancé…

Maintenant que nous avons pu récupérer les données dans un dataframe, on va pouvoir les exploiter. Dans le prochain article on va voir comment les mettre en forme pour ensuite pouvoir soumettre nos données à un modèle prédictif comme les K voisins et les régressions linéaires, ridge et lasso. Dans un premier temps on va je pense orienter le projet sur une station météo « statique » (ça tombe bien, ma maison est assez bien exposée au vent sans trop subir d’effets de sites) avant de passer à l’embarqué.

Pour finir voilà en gros la distribution géographique des stations restantes:

Plus le rond est gros plus l’altitude de la station est élevée. On devine assez bien le Nord-Ouest de la France, ou alors un schtroumpf tuberculeux qui éternue.

Un petit générateur thermique (partie 3)

D’après ce qu’on a vu dernièrement, en récapitulant on sait que:

1) L’effet Seebeck permet à partir d’un différentiel de température de générer de l’électricité. Grâce à un composant électrique appelé module peltier, on convertit l’énergie thermique en énergie électrique. D’après une étude de l’insa de Rouen dispo sur le net (Rapport_P6-3_2008_32%20(1).pdf), si sur la face froide du module la température appliquée est de 38 °C et sur la face chaude 90 °C (donc avec un différentiel de 50°C environ) alors en voltage produit on a 1.161 Volts et en puissance on obtient 0.674 watts environ. Le rendement de cet effet reste très faible ( 2.4 %). L’usage du module est déconseillé pour des températures au-dessus de 100 °C (au risque de le cramer) d’après le fournisseur, mais sachant que ces modules sont constitués essentiellement de tellure de bismuth (fusion à 573°C), de cuivre (fusion à 1085°C) et de céramique (fusion au-delà de 2000°C) peut-être peut-on pousser un peu plus le chauffage avant de les faire claquer…

2) Pour avoir un générateur thermique efficace, il doit délivrer un courant électrique régulier, donc il faut que le différentiel de température soie stabilisé. Le problème c’est que généralement au bout d’un moment la partie froide a tendance à se réchauffer, à s’équilibrer avec la partie chaude car elle n’évacue pas toute la chaleur cumulée donc le différentiel de température diminue, et inévitablement c’est la puissance générée par le module qui finit par chuter.

3) Pour avoir une énergie électrique régulière, il faut peut-être envisager l’énergie thermique passant à travers le module un peu comme une rivière qui coule. Si le débit de la rivière est régulier, alors le moulin (le module) va fournir une énergie mécanique (électrique) régulière. L’énergie thermique doit avoir un débit régulier donc.

Donc comment améliorer la partie froide pour avoir un débit thermique régulier ?

Partie 1: un peu de thermodynamique.

La thermodynamique est une branche des sciences qui étudie les échanges d’énergie entre les systèmes, l’énergie se transmet sous forme de chaleur ou de travail (les 2 sont exprimés en joules donc); ici on va s’intéresser à la chaleur. La chaleur s’envisage comme un échange d’énergie entre systèmes sous forme microscopiquement désordonnée (plus la chaleur transmise est forte, plus les atomes véhicules de cette chaleur vibrent en gros), tandis que la température désigne plutôt l’état d’un système particulier (voir le bouquin « Thermodynamique » de R. Taillet par exemple).

Les échanges de chaleur sont souvent assimilés à des variations de température des systèmes impliqués dans ces échanges. On définit cette chaleur par la formule:

Q=CΔT (Q est la chaleur exprimée en joules reçue par le corps, C la capacité calorifique du corps exprimée en joules par kelvin, et ΔT sa variation de température). En étudiant bien cette formule on constate facilement que plus la capacité calorifique d’un corps ou système est élevée, plus ce corps est capable d’ emmagasiner de la chaleur (pour un différentiel de température identique entre 2 corps différents, celui ayant la plus grosse capacité thermique recevra, captera plus de chaleur). Plus la quantité de matière est importante, plus la capacité calorifique l’est (on va y revenir rapidement).

De façon globale un élément dense est meilleur conducteur de chaleur et a une capacité thermique volumique élevée, et un élément léger c’est le contraire (plus isolant, capacité calorifique faible). Les métaux sont de très bon conducteurs de chaleur.

Bref, il faut envisager un truc (avec du métal ?) dense avec beaucoup de matière pour faire une partie froide potable. La mer pourrait donc constituer un corps à capacité calorifique élevée voire même un thermostat idéal pour notre pile (la mer est capable de récupérer la chaleur produite par la pile sans varier de température, comme un thermostat).

Partie 2: pile thermique solaire.

1) Pile essai 1

P1190865

En premier essai j’avais construit une sorte de caisse rectangulaire, un coffrage isolé thermiquement sur les côtés chauffé à l’intérieur par des lentilles de Fresnel. Les rayons étaient focalisés à l’intérieur sur des collecteurs de chaleur en aluminium peints en noir (peinture de cheminée résistante à 1000°C) et isolés entre eux par du plâtre.

P1190867

Ces collecteurs étaient en contact avec les modules peltiers, et les modules étaient en contact avec des sections carrées en aluminium également à l’arrière du coffre servant de dissipateurs thermiques, bref de radiateurs. Cette pile comprenait 20 modules peltiers branchés de la façon suivante: 10 en série fois 2 puis les 2 séries de 10 modules en parallèle. Sur un collecteur on avait 2 modules disposés l’un au-dessus de l’autre.

P1190868

Au final après un essai en octobre par temps ensoleillé normand cette première pile a été capable de délivrer une tension de 4.5 volts de façon régulière pendant environ 20 minutes, pour une puissance très faible (on comptait environ 0.5 watts, c’est pas avec ça qu’on pouvait alimenter en jus le dernier concert de Jean Michel Jarre). Ensuite j’avais essayé de limiter les pertes thermiques en noyant les collecteur dans de la résine époxy (l’idée était de laisser passer les rayons lumineux jusqu’aux collecteurs, mais bloquer la chaleur sortante), mais les lentilles de fresnel ont trop focalisé les rayons (j’aurai dû rapprocher légèrement les lentilles des collecteurs) et du coup ça a tout cramé… Elle marche beaucoup moins bien maintenant, sauf comme table de chevet (lourde en plus) si on des goûts de chiotte.

2) Pile essai 2

P1190934

Cette fois pour ce nouveau modèle de pile bricolée j’ai utilisé 6 lentilles de Fresnel, 6 modules peltiers, une section rectangulaire en aluminium de 1 mètre de long, 2 tubes de cuivre de diamètre 18 mm, du CP pour fabriquer le support des lentilles, et un rouleau de tuyau de cuivre. Pour les jonctions j’ai utilisé des serflex et du mastique résistant à la température et l’humidité. Ha oui j’ai aussi utilisé un tuyau de jardin :

P1190864

P1190863

P1190862

 

Pour la fabriquer c’est tout con, sur la section en aluminium j’ai collé les modules peltiers (sur les coins seulement pour ne pas couper le transfert de chaleur), et sur les modules j’ai collé des morceaux de cuivre peints en noir pour bien absorber la lumière focalisée par les lentilles (peinture de cheminée). Ensuite dans la section alu j’ai glissé les 2 tubes de cuivre, puis j’ai bouché les 2 trou de la section avec du mastique en laissant dépasser les tubes de cuivre. Ensuite j’ai bricolé les supports des lentilles en bois en veillant bien à avoir une focalisation pas trop concentrée sur le cuivre peint (sinon ça fait cramer la peinture).

Ensuite j’ai bricolé 2 radiateurs avec le rouleau de tuyau de cuivre. Chaque radiateur est relié à une entrée et une sortie d’un tube de cuivre dans la section alu.

P1190925

P1190933

P1190930

P1190929

P1190931

Le fonctionnement est simple: la lentille focalise les rayons solaires sur le cuivre peint qui chauffe, chauffant le module également. Le module peltier est refroidit par la section rectangulaire en aluminium remplie d’eau qui contient les tubes de cuivres reliés aux radiateurs, eux aussi remplis d’eau. En fait la section alu sert d’échangeur thermique entre les modules et les radiateurs.

Résultats:

Cette pile a été testée entre 11h et 13h le 22 août. Comme le circuit des radiateurs n’était pas parfaitement étanche j’ai ajouté 3 bouteilles d’eau pendant ces 2 heures dans les radiateurs. J’ai utilisé de l’eau du robinet à 17°C environ.

11h10: 7.7 volts/plus de 200mA

11h20: 7.8 volts/plus de 200mA

11h30: 7.4 volts/plus de 200mA

11h40 (premier ajout d’eau): 7.8 volts/plus de 200mA

11h50: 7.9 volts/plus de 200mA

12h00: 7.7 volts/plus de 200mA

12h10: 7.4 volts/250 mA

12h20 (second ajout d’eau): 8.1 volts/300mA

12h30: 8 volts/280 mA

12h40: 7.7 volts/270 mA

12h50: 7.7 volts/260 mA

Donc cette pile fournit entre 1.85 et 2.4 watts de puissance. Lors des mesures il a fallu réorienter la pile légèrement toute les 10 minutes pour bien être aligné avec le soleil. Quel est son rendement du coup ?

Dans le bouquin « les indispensables astronomiques et mathématiques pour tous  » (A. Moatti), l’auteur nous dit que le flux thermique solaire que l’on capte au sol est en moyenne de 490 watts par m2. Cette valeur varie selon la position du soleil par rapport à notre zénith, l’albédo, la couverture nuageuse… Bref on va se contenter de ce chiffre pour simplifier. Les lentilles que j’ai utilisé ont une dimension chacune de 24.5/17 cm donc en surface 416.5 cm2. Comme j’en ai utilisé 6 ça fait donc 2499 cm2 soit 0.25 m2 environ. Du coup notre pile récupère du soleil à peu prêt 122.5 watts. Donc son rendement est situé environ entre 1.5 et 1.9 %. Il faudra refaire un essai en hiver cette fois pour comparer, après avoir amélioré l’étanchéité des radiateurs. On peut surement encore gratter un peu de rendement.

Partie 3: pile thermique à combustible.

Comme on l’a vu dans l’intro, la mer peut peut-être faire un excellent thermostat pour une pile thermique (donc faire très efficacement circuler la chaleur), du coup actuellement je suis en train de bricoler une pile immergeable qui fonctionnerait avec la combustion de l’huile (friture, colza, olive… Bref de l’huile). Des ou une grosse lampe à huile chaufferait du cuivre qui à son tour chaufferai des modules. La partie froide serait simplement une plaque de cuivre en contact direct avec la mer. Voici un petit schéma du projet:

0001

 

Pour le moment j’en suis juste à la bidouille de la partie chaude mais ça présente plusieurs problèmes:

– Pour la combustion de l’huile il faut de l’oxygène, or si la partie chaude est immergée, ça risque d’être compliqué d’amener un volume d’oxygène suffisant aux lampes à huile pour obtenir une chaleur efficace et suffisante.

– Si la pile est immergée, alors elle ne doit pas avoir un volume trop important pour ne pas avoir à trop la lester (principe d’Archimède) pour la maintenir sous l’eau.

– Si la pile n’est pas immergée mais flotte sur l’eau, alors il va falloir vraiment bien isoler la partie chaude qui fait le lien entre les lampes à huile et les modules car les pertes thermiques sont très rapides.

– Il va falloir moduler la partie chaude: soit en trouvant le compromis chaleur stabilisée/distance des lampes à huile idéal pour ne pas cramer les modules, ou alors fabriquer un thermostat (voir schéma) pour limiter la température de chauffage des modules (dans le cas du schéma à 100°C donc).

– Bien chauffé, le cuivre se dilate et se déforme un peu ce qui peut endommager les modules si ils sont en prise directe dessus.

Voilà des petites photos pour montrer où j’en suis actuellement:

P1190879

P1190880

boite2

P1190877

boite3

La boîte contient 9 pots blédina (parfum pomme/mangue, mes préférés) faisant office de lampes à huiles. Cette boîte s’insère dans un couvercle en bois et en cuivre avec 8 trous de 1 cm de diamètre pour laisser passer de l’oxygène pour la combustion. C’est insuffisant car après quelques secondes seul une des neuf lampes reste allumée (la centrale); si je laisse juste cette lampe au bout de 5 minutes elle chauffe la plaque de cuivre à 50 °C environ.

Bon à bientôt pour la partie 4 je vais essayer de pas mettre 2 ans pour la faire cette fois !

 

petit générateur thermique (partie 2)

D’après les précédents résultats, il a fallu ajouter ou modifier quelques trucs sur le générateur pour essayer de le rendre plus efficace; la partie froide a donc été changée en réservoir à eau (j’ai soudé à froid un autre moule en aluminium sur les bords du moule « partie froide »), les morceaux d’éponge collés sur le pourtour du moule partie froide ont été virés, et l’isolation du moule partie chaude a été améliorée de plusieurs épaisseurs et avec du mastic. Concernant l’emploi du bidule pour l’énergie solaire les miroirs ont aussi viré et ont été remplacé par un pare soleil de voiture argenté (plus efficace et en plus ça ne coûte rien, et c’est plus facile à trouver en récup), la vitre en pvc a été modifié en double vitrage pour améliorer l’isolation.

P1000457 (Copier)sur la photo on voit bien le moule soudé, puis l’ajout de silicone sur la soudure pour étanchéifier l’ensemble.

therm10 (Copier)trois couches d’isolant ont été ajoutées, collées à chaque fois au mastic. Sur le bord du moule « partie chaude » j’ai fait un joint en mastic bien plat sur le haut pour améliorer l’isolation de l’ensemble une fois la vitre posée dessus. Quand la vitre est appliquée, elle appuie d’abord sur la mousse de l’isolant avant de toucher ce joint (pour éviter au maximum les pertes de chaleur).

therm3 (Copier)J’ai gardé les charnières articulées avec les cintres, mais cette fois pour capter plus efficacement la lumière j’ai découpé un pare-soleil en 4 morceaux.

therm6 (Copier)Sur la vitre utilisée au début j’ai collé une deuxième vitre, entre les deux il y a un filet d’air de 5 mm environ. De cette façon on obtient une sorte de double vitrage capable d’optimiser l’isolation thermique du bidule.

1) énergie solaire

Quand le générateur est utilisé avec le soleil, comme pour un four solaire il doit être orienté de façon optimale vers la source d’énergie; comme le soleil n’est jamais éternellement fixe dans le ciel il faut donc de temps en temps repositionner correctement la couscoussière. pour que la vitre avec le pare soleil soie bien appliquée sur la pile afin d’ éviter toute perte thermique, j’utilise une paire de sandows.

Par une journée normande d’octobre bien ensoleillée, sans aucun nuage, et avec une eau du robinet à 15 degrés comme refroidissement on obtient ça :

14h55: départ

/15h00: 2V et 74 mA

/15h10: 2.45V et 88 mA

/15h20: 2.7V et 97 mA

/15h30: 2.62V et 87 mA

/15h40: 2.71V et 98 mA

/15h50: 2.92V et 103 mA

/16h05: 2.73V et 90 mA

/16h15: 2.75V et 92 mA

/16h25: 2.56V et 87 mA.

 

Toujours en octobre, cette fois avec des nuages de temps en temps:

16h20: 0.6V et 20 mA

/16h25: 1.57V et 58 mA(puis éclaircie)

/16h31: 2.55V et 83 mA(ensuite arrivée d’un gros nuage bien gras)

/16h40: 1.75 V et 63 mA (puis hop là bim éclaircie à nouveau)

/16h50: 2.65V et 95 mA

/17h00: 2.63V et 95 mA

/17h10: 2.7V et 96mA (ensuite ça se couvre définitivement)

/17h20: 0.8V et 23mA.

Conclusion: par rapport à la première tentative (réalisée en été, au mois d’août) on gagne environ 1 V de tension et plus d’intensité également. On peut encore optimiser l’ensemble; en améliorant l’isolation thermique de la jonction entre la vitre pvc et le bord de la pile, et pourquoi pas en améliorant le système de refroidissement (qui a tendance à se réchauffer dans le temps, donc à faire baisser la tension obtenue au fur et à mesure).

 2) Eau bouillante

Comme on l’a vu au début, on ne peut pas chauffer indéfiniment les modules peltier, si on dépasse les 100 degrés de température, on risque de les cramer tout simplement. si on les réchauffe avec de la vapeur d’eau en ébullition on sera sûr de ne pas dépasser cette limite des 100 degrés, donc de protéger correctement l’ensemble. On place la pile partie chaude vers le bas sur un couvercle aluminium troué pour laisser passer la vapeur, puis l’ensemble sur un récipient d’eau en ébullition:

therm5 (Copier)

 

Il n’y a pas contact direct entre le moule de la pile et le couvercle aluminium grâce au joint mastic ajouté sur le bord du moule « partie chaude » et l’isolation en mousse qui dépasse un peu. En ayant au préalable remplit la partie froide de la pile au maximum avec une eau à 15 degrés on obtient les résultats suivants:

16h13: début

/16h15: 0.5V et 23 mA

/16h20: 7.53V et 2.3 A

/16h25: 7.41V et 2.5 A

/16h30: 6.23V et 2A

/16h35: 5.19V et 1.8A/

16h40: 3.9V et 1.4A

/16h45: 3.4V et 1.1A.

A la fin l’eau du refroidissement était à 29.5 degrés.

Conclusion de l’histoire:

Afin d’avoir une pile thermique efficace, il est nécessaire d’avoir la meilleure circulation de chaleur possible entre la partie chaude et la partie froide (je pense que la chaleur est à envisager comme une rivière devant être à débit constant pour pouvoir entrainer efficacement la roue du moulin, c’est à dire les modules). On va donc essayer de faire 2 piles distinctes; l’une fonctionnant avec le soleil et l’autre avec un combustible simple (bois ou huile par exemple).

Pour la pile fonctionnant avec le soleil je vais essayer de faire une sorte de coffrage isolant chauffé avec des lentilles de Fresnel et refroidit à l’air ou à l’eau, et l’autre pile on verra (probablement chauffée avec un combustible puis refroidie à l’eau).

 

 

Le gros blème de Kepler

Pour faire un programme permettant de se positionner grâce au Soleil, il a fallu utiliser principalement ce qu’on appelle l’équation du temps, c’est-à-dire la différence entre le temps solaire moyen et le temps solaire vrai. Cette équation induit donc la vitesse  « réelle prise à l’instant t » de la Terre autour du Soleil, vitesse non constante dans le temps suite à sa trajectoire elliptique (voir lois de Kepler). Maintenant nous allons voir comment a été obtenue cette équation, la méthode trouvée devrait peut-être nous permettre de la réinvestir plus tard dans le calcul des trajectoires des planètes également utiles à la navigation (Mercure, Vénus, Mars, Jupiter, Saturne), sachant que pour établir un programme de positionnement avec les planètes il faudra également se taper un changement de référentiel (passer d’un référentiel héliocentrique à un référentiel géocentrique, un truc du genre). Pour rédiger la suite je me suis beaucoup aidé du bouquin « le minimum théorique » de Leonard Susskind (pas toujours évident à piger du premier coup mais super intéressant, j’ai utilisé son bouquin sur la mécanique classique) et aussi des cours de physique disponibles sur youtube de Richard Taillet (mécanique, semestre 2, cour 3), très clair et très bien expliqué où à partir des équations du mouvement il démontre la trajectoire elliptique et les lois de Kepler entre 2 corps. Bon j’espère ne pas avoir glissé trop de conneries dans le résumé de toutes ces étapes.

 

700px-Eqdt_wiki

(Avec le schéma ci-dessus, on voit bien le long de l’année le décalage entre le soleil moyen où la Terre tourne théoriquement autour en faisant un cercle parfait, et le soleil vrai)

1) Des trucs de mécanique classique

Un système physique peut-être résumé en mécanique comme la somme des énergies cinétiques (Ec) et potentielles (Ep) qui lui sont attribuées, c’est l’énergie totale du système (Et). L’énergie cinétique représente en gros « l’énergie du mouvement » de l’objet étudié, et l’énergie potentielle, comme son nom l’indique, l’énergie que l’objet pourrait potentiellement libérer (pas terrible comme définition mais j’ai du mal à le cerner autrement). Par exemple si on prend une balle en haut d’un immeuble en suspens, prête à être lâchée, alors à ce moment-là son énergie potentielle sera à son maximum, et son énergie cinétique sera nulle (car la balle est immobile par rapport au référentiel immeuble). Maintenant si on prend cette balle juste avant son impact au sol, son énergie cinétique sera alors à son maximum (la balle aura atteint sa vitesse max) mais cette fois son énergie potentielle sera presque au minimum (elle sera au minimum quand la balle aura touché le sol).

énercies différentes (Copier)

Donc en formule de physique l’énergie totale d’un système ça donne ça :

Et=Ec+Ep=1/2 mv^2 + V(x), avec V(x)=potentiel du système. Je l’ai noté V(x) car le potentiel dépend de la position de l’objet étudié dans un repère donné (en reprenant l’exemple du ballon sur le gratte-ciel, plus le gratte-ciel sera élevé et plus l’énergie potentielle du ballon sera forte c’est l’idée en gros).

Et bien à partir de tout ça on peut retrouver les équations du mouvement de l’objet. Mais avant d’aller plus loin on va définir d’autres trucs de physique (mais pas trop faut pas déconner non plus rassurez-vous).

  1. a) L’énergie potentielle

Pour les systèmes à force centrale (comme les planètes soumises à l’influence gravitationnelle d’un astre, que l’on apparentera à un point) on peut définir que les sommes des  forces appliquées à l’objet sont égales à la négative du gradient de l’énergie potentielle : ∑F=-grad(V), il y a un moins devant grad car l’objet est dirigé vers le point (donc l’accélération symbolisable par un vecteur serait dirigée vers le point si on schématisait l’ensemble). On peut aussi définir la force de la façon suivante :

Fi(x)=-∂V(x)/∂xi ; ce truc signifie que la force exprimée sur un degré de liberté spatial du système (ici xi) est égale à la dérivée partielle du potentiel par rapport à ce degré de liberté spatial…Enfin je crois. On peut aussi dire qu’une force c’est la divergence spatiale d’une énergie potentielle (en backflip mikado la plupart du temps mais bref passons ce détail).

D’après les lois de Newton la somme des forces est égale au produit d’une masse par l’accélération de cet objet. Donc ∑F=ma. Ca explique pourquoi lorsque l’accélération d’un objet est nulle (objet immobile ou en vitesse constante), alors la somme des forces qui lui sont appliquées est égale à 0. Une force c’est une masse accélérée.

Jupiter

 

  1. b) Dérivées, intégrales, dérivées partielles

Les dérivées, dérivées partielles

Pour l’énergie potentielle on a parlé de gradient, mais c’est quoi en fait ? He bien il s’agit simplement de la somme des dérivées partielles spatiales du potentiel V ; c’est-à-dire :

Grad (V(x))= ∂(Vx)/∂x+∂(Vy)/∂y+∂(Vz)/∂z

La dérivée d’une fonction par rapport au temps indique son taux de variation dans le temps (on va alors parler de vélocité, c’est-à-dire de vitesse de l’objet selon une orientation du repère choisit, cartésien par exemple) mais ça peut aussi se faire dans l’espace si la fonction est dérivée par rapport à l’espace. En fait on peut très bien dériver une fonction avec n’importe laquelle de ses paramètres (pour les fonctions à plusieurs variables), pas juste le temps.

La dérivée seconde d’une fonction indique le taux de variation de la dérivée première. Si la dérivée première est la vélocité, alors la dérivée seconde ce sera l’accélération de l’objet selon un des axes du repère.

En général les dérivées permettent de voir comment va évoluer une fonction (croissante, décroissante, stationnaire…) et les dérivées secondes permettent de trouver les maximums et les minimums locaux de la fonction, entre autre.

Les dérivées ne sont pas exclusivement réservées aux fonctions  à une variable, elles peuvent être aussi utilisées pour les fonctions dépendant de plusieurs variables ; on va alors parler de dérivées partielles. Le principe reste quasiment le même sauf que quand on dérive la fonction par rapport à l’un des paramètres, on considère les autres comme de simples coefficients fixes. Par exemple on envisage la fonction F(x ;y)=3x+2y. Si on fait ∂F(x ;y)/∂x ça donne =3, et si on fait ∂F(x ;y)/∂y on obtient =2.

 

mars

Les intégrales

C’est un peu la démarche inverse d’une dérivée, si on peut dire ça comme ça. Si on devait définir de façon un peu plus rigoureuse ce truc là on pourrait dire que c’est la limite d’une somme d’aires placées sous une fonction. On peut donc en déduire que le potentiel est égal à la négative d’une primitive d’une force plus une constante : V=-∫Fdx+constante. Par contre ici on laissera tomber la constante (voir le principe d’invariance de jauge pour les curieux). Donc ça donne V=-∫Fdx.

  1. c) Le Lagrangien

En physique, le Lagrangien permet de déterminer l’évolution du système dans le temps et l’espace, déduire les équations du mouvement, et repérer les symétries éventuelles, c’est un peu un couteau suisse quoi…Il est aussi indispensable pour déterminer l’action d’un système (voir le principe de moindre action pour les curieux).

Le Lagrangien : c’est simplement l’énergie cinétique moins l’énergie potentielle de l’objet étudié (en tout cas pour nos planètes, mais c’est pas toujours le cas pour tous les systèmes), donc ça donne : L=1/2 mv^2-V(x). Le Lagrangien peut être considéré comme une fonction dépendant de 2 variables, une variable d’espace (induite par l’énergie potentielle) et une variable de vitesse (induite par l’énergie cinétique). Cela nous fait donc L=L(xi ; dxi/dt). (Dx/dt=vélocité sur axe x et xi symbolise les axes x, y et z).

Une symétrie : En physique c’est quand on a une invariance du lagrangien lorsque l’objet se déplace dans tel ou tel degré de liberté du système (on parle ici d’espace des configurations avec trois degrés de liberté dans l’espace, x, y et z). Par exemple la conservation du moment angulaire est une symétrie par rotation du système. On a donc dL/dt=0 dans une symétrie du Lagrangien liée au temps.

 

mercure

 

  1. d) Les équations d’Euler-Lagrange

Elles nous permettent, avec l’apport du Lagrangien, de trouver le moment conjugué du système (il va nous servir pour détecter des symétries du système) et les équations du mouvement.

Moment conjugué : c’est la dérivée du Lagrangien par rapport à la vélocité.

Equation d’Euler-Lagrange : c’est simplement : (d/dt)( dL/dVx’) – (dL/dx)=0 (pour un seul degré de liberté, ici x. x’ est la dérivée de x).

2) Trouver les équations du mouvement d’un astre autour du Soleil.

  1. a) Le Lagrangien en coordonnées polaires

On va d’abord chercher à définir le Lagrangien du système dans un repère orthonormé (x, y, z), puis on va le modifier pour fonctionner dans un repère en coordonnées polaires(r et ө, avec r=rayon, c’est-à-dire la distance entre les 2 astres et ө=angle).

L’énergie cinétique : c’est simple, c’est Ec=1/2 m(dx/dt)^2+1/2 m(dy/dt)^2. On considère que l’objet se déplace dans un plan unique (x, y) donc on néglige z. Si on avait intégré z on aurait parlé de coordonnées polaires cylindriques.

L’énergie potentielle : on va faire un petit tour de passe-passe ; on sait presque tous que la force gravitationnelle entre 2 corps définie par Newton est égale à GMm/r^2 (proportionnelle au produit des masses et inversement proportionnelle au carré de leur distance d’éloignement). Or on a vu que V=-∫fdx ; donc si on intègre GMm/r^2 on va obtenir finalement V(r)=-GMm/r (car le potentiel dépend de la distance r qui est un paramètre variable, G, M et m sont considérés comme fixes, souvenez-vous de l’exemple du gratte-ciel et du ballon).

On sait que le Lagrangien est la différence entre l’énergie cinétique et l’énergie potentielle, donc :

L=Ec-Ep=1/2 m(dx/dt)^2+1/2 m(dy/dt)^2+GMm/r

Maintenant on va convertir notre Lagrangien en coordonnées polaires. C’est plus pratique pour étudier un objet en rotation autour d’un autre. Il va y avoir 2 degrés de liberté : r qui est la distance entre les 2 astres et ө qui représentera en degrés l’angle entre le périastre et la position de l’objet en rotation par rapport au foyer (le Soleil).

D’après le petit schéma on peut donc convertir les coordonnées cartésiennes en coordonnées polaires de la façon suivante :

 

rp_7_4 (Copier)

X=rcos(ө)

Y=rsin(ө)

Il suffit ensuite simplement de remplacer dans notre lagrangien ces nouvelles données ; cependant dans le Lagrangien on parle de vélocité alors qu’ici nous n’avons que des positions. Avant de trafiquer le Lagrangien il va donc être nécessaire de calculer les dérivées premières de X et Y. En prenant en compte le fait que ce sont des produits de fonctions (r avec cos(ө) et r avec sin(ө)), et que ө est à considérer comme une fonction dépendant du temps (donc cos(ө) et sin(ө) sont également à envisager comme des fonctions composées dans notre calcul de dérivées), on va trouver ça :

X’=r’cos(ө)-sin(ө)ө’r (les’ ça veut dire dérivée temporelle, c’est pour écrire plus vite et moins galérer. Par exemple r’ est la dérivée temporelle de r).

Y’=r’sin(ө)+ө’cos(ө)r

Si on prend nos dérivées et qu’on les fourre dans le Lagrangien à la place des coordonnées du début, on obtient :

L=1/2 m(r’^2+ө’^2r^2)+GMm/r, soit notre Lagrangien du système en coordonnées polaires.

  1. b) Les équations du mouvement

Cette fois on va sortir de notre boîte à outils et dégainer les équations d’Euler-Lagrange. On va l’utiliser pour nos 2 degrés de liberté et ça va nous donner :

(d/dt)( dL/dr’)- (dL/dr)=0 et (d/dt)(dL/dө’)-(dL/dө)=0

Quand on les résouds, on obtient donc 2 équations au total :

r’’=rө’^2-GM/r^2 (r’’ est la dérivée seconde temporelle de r, l’accélération quoi).

(d/dt) (mө’r^2)=0 (cette équation indique une symétrie du système, c’est-à-dire l’invariance du Lagrangien par rapport à la vitesse angulaire par rapport au temps. Autrement dit cela exprime la conservation du moment cinétique de l’objet quand il tourne autour du Soleil). On pourrait aussi écrire cette seconde équation sous cette forme : mө’r^2=constante.

Comme on sait que m est une masse considérée comme constante, alors on peut donc affiner et dire que r^2ө’=constante=C.

  1. c) Obtenir une fonction du type r(ө)

Cette fonction va nous permettre de déterminer la trajectoire d’un astre selon ses coordonnées polaires. Pour ça, reprenons le Lagrangien établis avant :

L= 1/2 m (r’^2+ө’^2r^2) + GMm/r

Nous avons établis également que C=r^2ө’. Cette constante n’est autre que la constante des aires, soit l’une des trois règles des lois de Kepler. Bon alors maintenant on va intégrer cette constante dans l’équation du Lagrangien et ça donne ça :

 1/2 r’^2+(1/2) (C^2/r^2)=GM/r+constante (on remarque qu’en simplifiant l’écriture m a disparu, soit la masse de l’objet en mouvement. Donc on peut en déduire que la masse de l’objet n’influe pas sur son déplacement autour de l’objet principal).

Maintenant on va chercher à transformer notre Lagrangien sous la forme d’une fonction r(ө).

Il va alors falloir établir r’ comme une fonction dépendant du paramètre ө, sachant que ө dépend du temps t ; on va poser mathématiquement :

r’=dr/dt=(dr/dө) (dө/dt) ; r’ se définit ici comme une fonction composée.

Donc en fait ça donne également dr(ө(t))/dt=(dr/dө)( dө/dt), donc au final ө’(dr/dө).

A partir de ça on remodifie l’écriture de la fonction trouvée précédemment et on obtient :

1/2 ө’^2 (dr/dө)^2 + 1/2 (C^2/r^2)- GM/r=constante

N’oublions pas que C=r^2 ө’ et donc ө’=C^2/r^4 , donc à partir de ça on remodifie encore l’écriture de notre équation et ça va nous servir ce truc :

(C^2/r^4) (dr/dө)^2 + C^2/r^2 – 2GM/r= constante

Pour simplifier nos prochains calculs,on va introduire une variable intermédiaire : u=1/r ou r=1/u.

Si on dérive r sur ө, en reprenant r=1/u on obtient dr/dө=(-1/u^2)( du/dө)

Bon bin c’est encore repartis pour modifier notre équation à partir de ces nouveaux éléments, en les insérant dans le paquet ça fait :

C^2 u^4 (1/u^4) (du/dө)^2 + C^2 u^2 – 2GMu= constante

On simplifie : C^2 (du/dө)^2 + C^2 u^2 – 2GMu= constante

On resimplifie encore : (du/dө)^2 + u^2 – 2GMu/C^2=constante

Maintenant on dérive tout part u, puis on dérive par ө :

2 (d^2 u/dө^2) (du/dө) + 2u (du/dө) – (2GM/C^2) (du/dө)=0

On remarque alors que l’équation peut être simplifiée, et ça nous donne :

(d^2 u/dө^2) + u=GM/C^2 , ça va nous permettre de calculer u selon ө donc r selon ө.

Bref là on a une équation différentielle à résoudre…Pas gagné cette histoire.  Si u est constante on a comme solution d’après l’équation GM/C^2, mais ça reste une solution particulière (ça c’est si la trajectoire de l’objet décrit un cercle dans l’espace, pas une ellipse). La solution ça va être l’oscillateur harmonique de la forme suivante Acos(ө) + Bsin(ө), égal aussi à Xcos(ө+ө0) avec X l’amplitude du mouvement. On retrouve aussi l’oscillateur harmonique dans l’étude des mouvements du pendule ou l’électricité par exemple. En fait on peut donc en déduire que :

u(ө) = GM/C^2 + Xcos(ө+ө0) ; et maintenant c’est bien gentil tout ça, mais nous on cherche r(ө) quand même merde ! Ha bin oui alors comme r=1/u, alors bon voilà :

u(ө)=GM/C^2 (1+ (AC^2/GM) cos (ө+ө0)) , – AC^2/GM c’est l’excentricité de l’ellipse notée e.

Donc : r(ө)= (C^2/GM)/(1-e cos(ө+ө0)). Le ө0 est négligeable(il est utile si on veut décaler la période de la fonction c’est tout) donc on obtient notre équation recherchée :

r(ө)=(C^2/GM)/(1- e cos(ө))

Si e est égal ou supérieur à 0 mais strictement inférieur à 1, alors on a une trajectoire en ellipse; si e=1 alors notre trajectoire va être parabolique, et enfin si e>1 alors on va avoir une hyperbole. Cette équation permet de tracer la trajectoire selon l’angle de rotation, mais comment tracer cette trajectoire par rapport au temps ? En fait on va faire le lien de façon d’abord géométrique, et ensuite par approximation en utilisant des suites de nombres.

Petit apparté sur l’oscillateur harmonique : à partir de l’oscillateur harmonique, solution de l’équation différentielle vue auparavant, on peut exprimer différemment l’équation de la trajectoire. En effet, cet oscillateur résous l’équation différentielle suivante :

x’’+ Wo^2x=0 , comme on peut le voir elle ressemble beaucoup à celle trouvée précédemment : (d^2 u/dө^2) + u=GM/C^2.

En fait l’équation de l’oscillateur décrit un système physique au cour du temps avec absence d’amortissement, frottements, au voisinage d’une position d’équilibre stable. Wo est un paramètre appelé la pulsation propre, il est égal à Wo=2π/To, To est la période propre du phénomène.

Comme on l’a vu la solution peut s’écrire x(t)=Acos(Wot) et y(t)=Bsin(Wot) (ce sont des coordonnées paramétriques), en fait A=xo (position de x à l’instant t=0) et B=Vo/Wo (vitesse initiale divisée par la pulsation). Pourquoi ? car quand on pose t=0 alors x(0)=A (car cos(0)=1 et sin(0)=0) et quand on dérive y(t) et x(t) par rapport au temps, on trouve y’(t)=WoBcos(Wot), et si on fait y’(o) on obtient y’(o)=WoB donc B=y’(o)/Wo (y’(o)=Vo).

 

oscillateur harmonique

 (En tapant sur google « oscillateur harmonique sans amortissement planètes », on tombe sur ce pdf très bien expliqué ci-dessus)

3) La trajectoire elliptique

P=C^2/(GM), c’est ce qu’on appelle le paramètre de l’ellipse, donc r=P/(1- e cos(ө)).

Pour calculer r max, soit la distance à l’aphélie il suffit de poser ө=0, on obtient donc r max=P/(1-e), et la distance au périhélie il suffit de poser ө=180° ce qui nous donne r min=P/(1+e). Ensuite pour obtenir le demi-diamètre de notre ellipse il suffit de poser l’opération (r min + r max)/2 qui est égal à a= P/(1-e)^2. Donc si ө=90°, c’est-à-dire si cos (ө)=0, alors P=a (1- e)^2. Pour définir géométriquement l’ensemble des paramètres de l’ellipse j’ai introduit un petit schéma pour être plus clair :

 

ellipse

C=ae et b=a√(1-e^2). F c’est le foyer du Soleil (l’astre immobile servant d’origine), e l’excentricité et a le demi grand axe de l’ellipse. C c’est la distance du foyer jusqu’au centre o de l’ellipse.

4) L’équation du temps

C’est l’équation qui permet de déterminer la vitesse réelle du Soleil autour de la Terre (quand on prend la Terre comme référentiel). D’après wikipédia elle se compose de l’équation du centre additionnée à l’équation de l’obliquité de la Terre. Il existe également sur wikipépé une version simplifiée de l’équation où on a construit une fonction en approximant le phénomène par le biais de fonctions trigonométriques, mais nous on va regarder plutôt la version complète, œuf, jambon, et fromage.

  1. a) L’équation du centre

Elle est ici rédigée sous la forme d’une fonction C dépendant de l’anomalie moyenne M, soit C(M). L’anomalie moyenne est simple à définir, c’est la vitesse angulaire moyenne de l’astre qui bouge (on peut également considérer que c’est la vitesse de l’objet si sa trajectoire était parfaitement circulaire, en fait c’est la distance parcourue par l’objet en une rotation divisée par le temps mis à faire cette rotation, c’est tout). Donc M est à envisager aussi comme une fonction dépendant du temps t cette fois (donc on peut considérer la fonction C comme une fonction composée puisque C dépend de M qui dépend de t, en fait C dépend indirectement de t).

 

Diagram_Anomalies_Kepler_orbit-fr.svg

Il existe l’équation de Kepler qui relie l’anomalie moyenne et l’anomalie excentrique : E-e sin(E)=M, avec M anomalie moyenne et E anomalie excentrique. En revanche l’équation ne contient pas l’anomalie vraie v. L’anomalie vraie dépend du temps, mais sur le schéma il n’y a pas de lien géométrique entre l’anomalie moyenne et les autres. Par contre l’équation précédente la relie à l’anomalie excentrique, mais problème : si on connaît l’anomalie moyenne (donc le temps…) on ne peut pas résoudre l’équation de Kepler de façon analytique, il va donc falloir approximer un résultat, trouver une solution approchée pour déterminer une position de l’astre par rapport au temps (et merde…).

Pour effectuer cette approximation on va utiliser des séries, et selon l’excentricité de la trajectoire on va employer :

. Pour une trajectoire d’excentricité avec e>e0=0.6627… Alors on va utiliser une série de Fourier (ici, c’est pour le cas d’objets avec de très fortes excentricités comme les comètes par exemple).

. Pour une trajectoire d’excentricité avec e<e0=0.6627… Alors on va utiliser une série entière (pour les planètes utiles à la navigation ce sera des séries entières donc, tout comme pour la Terre).

  1. b) L’équation de l’obliquité de la Terre

C’est une fonction qui dépend de la longitude écliptique LE donc on peut l’écrire R(LE). Elle permet de transvaser les coordonnées écliptiques du Soleil en coordonnées équatoriales, plus utiles à l’usage. Calculer LE est facile, c’est simplement la vitesse angulaire moyenne du Soleil autour de la Terre (référentiel géocentrique) avec en plus C(M) qui permet de corriger cette vitesse selon la forme elliptique de la trajectoire. R(LE) utilise une formule pour faire le lien entre longitude écliptique et coordonnées équatoriales (voir schéma suivant).

 

440px-Terre_pour_equation_du_temps_2.svg (1)

Dans le schéma ci-dessus, ϒ représente le point vernal (croisement de l’équateur et de l’écliptique au nœud ascendant) ; ϵ c’est l’angle d’inclinaison entre l’équateur et l’écliptique qui varie légèrement sur une longue période. A(t) est un point quelconque dépendant du temps t, et fixe sur la surface terrestre donc il fait un tour en un jour sidéral de façon régulière. Le point S(t) est aligné entre le centre de la Terre et le Soleil, et fait un tour en une année sidérale, donc il a une vitesse irrégulière sur un an (trajectoire elliptique). Et B(t) est  l’interception entre le méridien de S(t) et l’équateur. On obtient donc à la surface terrestre un triangle rectangle sphérique rectangle en B(t), ce qui donne cos(ϵ)=ϒB(t)/ϒS(t), donc ϒB(t)=cos(ϵ) ϒS(t). Jusqu’ici ça va après ça se complique un peu. Alors pour résumer, A(t) tourne de façon régulière, S(t) de façon irrégulière donc B(t) également, donc en fait A(t) est relié à l’anomalie moyenne et B(t) est relié à l’anomalie vraie…On peut en déduire que l’angle entre A(t) et B(t) est l’heure solaire vraie. Donc Hv(t)=angle BA= angle Bϒ+angleϒA.

Pour définir l’heure solaire moyenne, on va prendre le point A(t) car il se meut de façon régulière, et on va prendre un point fictif dérivé de S(t) qu’on va appeler Sv(t) ; mais celui-là on va imaginer qu’il bouge de façon régulière. Ca donne : Hm(t)=angleSvϒ+angleϒA. Comme l’équation du temps c’est la différence entre l’heure solaire moyenne et l’heure solaire vraie, alors E(t)=Hm(t)-Hv(t)=angleBϒ-angleSvϒ.

Mais on sait que ϒB(t)=cos(ϵ) ϒS(t), or ϒB(t)=tan(ϒB) et ϒS(t)=tan(ϒS), donc :

Tan(angleϒSv+E)=cos(ϵ) tan(angleϒS)

E(t)=-angleϒSv+arctan(cos(ϵ)tan(angleϒS))

En utilisant une série et en posant y=tan(ϵ/2) pour ϵ/2≈0,20, ça donne :

R= arctan (cos (ϵ) tan(ϒs))-ϒs

R= arctan (cos(ϵ) tan (λs-π))-(λs-π)

R= -arctan ((sin(2λs) y^2)/(1+y^2cos(2λs)))

R=-y^2sin (2λs) + ½ y^4sin(4λs)-1/3 y^6 sin (6λs)+….

 

Voilà, avec tout ça on peut faire un petit programme de positionnement avec le Soleil, et aussi peut-être avec les planètes utiles à la nav, avec la difficulté du changement de référentiel en plus. Pour la Lune c’est plus compliqué car elle est soumise à beaucoup de contraintes et effectue des mouvements plus complexes (problème à trois corps), plus nombreux en un temps plus court.

 

petit générateur thermique (partie 1)

thermo2 (Copier)Une couscoussière designée par les daft punk ? La maquette bidon d’un ovni de série Z ? à première vue ça ressemble à pas grand chose, mais ce bidule peut générer un peu de jus… En utilisant les différences de chaleur, soit l’effet Seebeck (pour faire bien).

En traînant un peu sur youtube on peut trouver des vidéos appelées « incroyables expériences », elles sont vraiment très intéressantes; on y apprend à faire une bobine Tesla, un chargeur portable, des piles, comment fonctionne l’induction… Et en fouillant on trouve la vidéo « thermopile ». Sur cette vidéo tout est expliqué, l’effet Seebeck, Peltier, la construction et le fonctionnement d’un module Peltier, la vidéo est avant tout une démo de l’effet Seebeck, mais la thermopile présentée et employée ne résiste pas à plus d’un usage (la lampe à huile crame les composants internes du module Peltier assez vite). Ce petit tuto propose un bricolage permettant un emploi éventuel à long terme de cet effet.

1) Effet Peltier, effet Seebeck

L’effet Peltier(ou effet thermoélectrique)est un phénomène physique capable de provoquer un déplacement de chaleur grâce au passage d’un courant électrique; pour cela on fait circuler le courant à travers deux matériaux conducteurs différents reliés entre eux par des jonctions, au fur et à mesure une jonction va refroidir et l’autre se réchauffer. On emploie ce principe dans la réfrigération. Certains couples de métaux seront plus efficaces que d’autres, un peu comme les réactions d’oxydoréductions, on parle de thermocouples.

L’effet Seebeck c’est un peu l’inverse tout simplement, c’est l’effet qui va nous intéresser.

2) Le module Peltier

A la base ce composant est conçu pour générer une différence de température à partir d’un courant continu, le type de module utilisé ici (12706) fonctionne sur du 12 volts. On l’utilise pour plusieurs choses, notamment le refroidissement de microprocesseurs, des petites glacières de voitures…Et aussi les tireuses à bière. Il a deux faces, l’une froide et l’autre chaude, l’objet à refroidir se place sur la face froide et on installe un système d’évacuation de la chaleur sur l’autre côté(comme dans la vidéo « incroyables expériences ») comme un petit ventilateur par exemple.

tec1-12706-module-peltier-refroidisseur-effet-ther (Copier)

Cependant même si il n’est pas spécifiquement conçu pour ça si on applique une source chaude sur la face chaude du module et une source froide sur la face froide, il va se créer une différence de potentiel entre ses deux bornes, donc passage de courant. Le rendement reste cependant très faible. Si on pose le module sur une table avec un voltmètre branché dessus, et que l’on pose juste sa main sur l’autre face on va voir la présence d’un léger courant électrique qui va décroître au fur et à mesure (rapidement la différence de température entre les deux faces va s’équilibrer). Après on peut s’amuser en faisant varier les sources froides ou chaudes: un sèche-cheveux, une loupe, des glaçons…On obtient évidemment de meilleurs résultats en utilisant une source froide et une source chaude en même temps, si ce n’est pas le cas à plus ou moins long terme les températures entre les deux faces du module finiront par s’équilibrer, la tension générée finira donc par chuter.

3) Ingrédients et coûts du bidule

La thermopile que l’on va bricoler devra répondre à un cahier des charges minimum : ne pas coûter trop cher (parce que quand même faut pas déconner) et fonctionner à partir d’une ou plusieurs sources d’énergie facilement utilisables, et employer une source chaude ne dépassant pas les 100°C maximum afin de ne pas endommager les modules Peltier.

Pour la fabriquer on va avoir besoin de plusieurs éléments :

moule aluminium (Copier)Deux moules à gâteaux en aluminium

tube carré aluminium (Copier)Un tube creux de section carrée aluminium

couverture-de-survie (Copier)Une couverture de survie

sodial booster (Copier)Un booster qui permet d’augmenter la tension d’entrée à 5 volts en sortie tout en la stabilisant(modèle CE8301).

Il va aussi nous falloir une plaque de polystyrène (aussi épaisse que le côté de la section alu du tube), du silicone en tube, une plaque de pvc transparent (et résistant aux UV) , des petits miroirs et un système de support pour les utiliser (des charnières de porte dans mon cas). Il va falloir aussi 10 modules Peltier, et si possible de la pâte thermique en tube. On ajoutera à tout ça des serviettes éponge.

En tout, si on fait de la récup pour environ 25 euros on peut la faire. Sur internet dix modules coûtent environ vingt euros, le booster moins de trois euros. Après si on a du bol on peut peut-être aussi récupérer des modules Peltier à droite à gauche dans des pc nazes, vieilles glacières ou encore mieux des bars en démontant discrètement la tireuse, après avoir délicatement saoulé le tenancier.

4) Le bricolage

On commence par décaper la peinture au cul des deux moules pour mettre l’aluminium à vif, sur l’un des deux on décape également le fond du moule jusqu’à l’aluminium; ce dernier sera la « partie froide » de la thermopile, et du coup le premier moule qui a juste le cul poncé sera la « partie chaude »(c’est mieux de garder le fond du moule noir pour la partie chaude afin de bien capter les rayons du soleil, donc la chaleur).

On découpe le tube alu en section carrée. Un module Peltier est de forme carrée avec des côtés à quatre cm. Par chance j’ai trouvé un tube de section deux sur deux cm, il m’a donc fallu découper vingt morceaux de tube (deux pour chaque module), un morceau est long de quatre cm. Le tube que j’avais était anodisé, du coup je l’ai décapé pour enlever la pellicule anodisée afin d’optimiser la conduction de chaleur.

On découpe la plaque de polystyrène en cercle de diamètre semblable au cul des moules, puis dans ce cercle on va découper dix carrés de quatre cm de côté. Ils vont accueillir chacun deux morceaux de tube alu juxtaposés. Cette plaque va jouer le rôle d’isolant entre les deux moules.

On peut ensuite coller avec du silicone (avec de la colle cyanocrylate ça fait fondre le polystyrène) le disque polystyrène sur le moule « face chaude » et disposer les morceau d’alu dans les trous sans les coller au moule.

On peut alors placer les modules Peltier sur les carrés alu obtenus pour les brancher et les souder en série:

branchements modules peltiers

Avant de les fixer aux morceaux d’alu, on met de la pâte thermique sur l’alu (pas trop, deux ou trois filets fin feront l’affaire) et de la colle forte en petite quantité aux quatre coins de chaque module. Avant de coller l’ensemble surtout bien faire gaffe à l’orientation des faces des modules par rapport aux « parties chaudes et parties froides », c’est pas mal de tester au multimètre avant.

construction en gros

Avant de coller le moule « partie froide » on remet de la pâte thermique sur la face restée libre des modules Peltier, puis on colle le moule avec du silicone.

Pour finir le collage on silicone les jonctions pour étanchéifier l’ensemble.

Maintenant que la partie principale de la pile est assemblée, on va isoler les deux moules; sur le pourtour du moule « chaud » on va coller un isolant si possible hydrophobe, pour ma part j’ai découpé un bout de tapis d’exercices au sol (bonne excuse pour plus m’en servir après c’est cool) puis on colle dessus un morceau de couverture de survie, face dorée vers l’extérieur. Sur le pourtour du moule « froid » on colle des morceaux de tissus éponge. Par dessus on mettra un morceau de couverture de survie mais cette fois la partie argentée sera tournée vers l’extérieur.

5) Fonctionnement

a. Avec le soleil:

pipile (Copier)

Sans isolation, le montage comme sur la photo, par temps presque complètement ensoleillé monte maximum à 1,1 volts pour 20 mA au bout de 15 minutes environ, puis redescend et s’équilibre à 0.8 volts environ. On utilise le même principe que l’effet de chaleur dans une véranda ou une voiture (effet de serre). La couleur noire du moule capte plus facilement la chaleur, et le pvc transparent « emprisonne » les rayonnements infrarouges, conservant  plus de chaleur dans le moule. Pour améliorer la tension obtenue il va donc falloir obligatoirement isoler les moules et essayer de capter encore plus de lumière pour la diriger à l’intérieur.

thermo3 (Copier)

Le moule « partie chaude »

 

 

 

 

Le moule « partie froide »:

thermo5 (Copier)

thermo4 (Copier)

Sur la dernière photo, on ajoute des miroirs fixés sur des petites charnières pliées à 90 degrés. Pour maintenir les charnières dans la position voulue, on peut les maintenir avec des morceaux de cintres:

pipile4 (Copier)

Au résultat final on obtient ça:

pipile5 (Copier)

Une fois notre couscoussière customisée, on obtient les résultats suivants (temps ensoleillé d’août normand):

+10 min=1.12 V; +20 min=1.6 V; +20 min=1.8 V; +30 min= 1.7 V (stabilisation ensuite à 1.6 V). 45 minutes plus tard si on vaporise la partie froide avec de l’eau tiède la tension monte à 2.6 V. En vaporisant davantage on peut monter jusqu’à 3.7 V. 15 minutes après la tension est revenue à 1.6 V pour 50 mA environ. A 3.7 V de tension on a 80 mA. Quand on vaporise la tension monte rapidement, chute et se stabilise un peu à 2 V (70 mA) pour retomber finalement à 1.6 V. En imbibant d’eau les morceaux de tissus éponge d’eau il ne se passe pas grand chose, mieux vaut vaporiser directement la partie froide dans le fond du moule « partie froide ».

b) avec de la vapeur d’eau bouillante

On place la couscoussière partie chaude vers le bas, sur une casserole d’eau bouillante avec un couvercle en aluminium dessus. il ne doit pas y avoir de contact direct entre le couvercle alu et le moule « partie chaude » (pour ne pas trop faire chauffer les modules Peltier par conduction de chaleur), on peut utiliser des morceaux de cartons par exemple. La vapeur d’eau va chauffer la partie chaude. On obtient:

début: augmente direct et se stabilise à 2.8 V; +5min=2.65 V et 90mA; +10min=2.55V et 85mA; +15min=2.47 V et 83mA; +20min=2.3 V et 75mA.

Si maintenant on ajoute de l’eau fraîche dans le moule de la partie froide, on a alors:

début: 7.5 V pour 2.5 A; +5min=8V et 2.5 A; +10min=7.5 V et 2.5V; +15min=6.85V et 2.2A; +20min=6.55V et 2.2A.(la puissance fournie diminue car l’eau ajoutée se réchauffe petit à petit).

Maintenant, on va voir si on peut utiliser l’énergie obtenue pour recharger un portable ou des piles AA, pour cela on va brancher en sortie du générateur le booster (DC-DC 0.9V-5V). D’après les données fabricant, en lui fournissant une tension d’entrée comprise entre 0.9V et 5V, il libère un courant stable de 5V environ. Il y a sur le circuit une diode rouge qui indique si la charge se fait.

A partir d’environ 1.12 V mon téléphone se met en charge, cependant après vérification sur le long terme la charge obtenue fonctionne mal; en effet bien qu’il s’affiche en recharge sur son écran ça semble plus décharger l’accu qu’autre chose. La charge du téléphone semble correcte quand la tension à l’entrée du booster fait au moins 2.6 V et 80 mA (ma batterie de téléphone est une batterie 3.7 V et 800 mah).

Dans le commerce j’ai trouvé un chargeur de piles AA en prise usb. On peut charger ses piles via une prise usb d’ordinateur ou une prise allume cigare 12 V, et on peut l’utiliser pour recharger un portable avec. En branchant le chargeur en sortie du booster il ne se passe rien (la led rouge témoin du chargeur ne s’allume pas), aussi bien avec le soleil que la vapeur d’eau chaude (sur le chargeur il est noté que pour fonctionner correctement il doit recevoir une tension de 5 V et une intensité de 0.5 A).

Pour améliorer le système il va falloir d’une part augmenter significativement l’isolation pour limiter au max les pertes thermiques, et d’autre part trouver un moyen plus efficace de capter les rayons du soleil, un peu comme les fours solaires fait maison. Concernant la source d’énergie solaire la principale difficulté va être de traiter un courant de sortie faible pour le rendre exploitable (l’ajout d’un composant crée une perte énergétique par effet joule…), même si on l’emploie juste pour recharger une seule pile AA rechargeable (1.2V 2100 mah). Pour la source de vapeur d’eau chaude il va falloir trouver un moyen de stabiliser la tension à 5 V, et peut-être aussi diminuer l’intensité fournie pour ne pas bousiller le chargeur ou les piles. On pourra aussi améliorer la partie froide du bidule en la modifiant en réservoir à eau. Peut-être y a t il aussi d’autres sources de chaleur exploitables pour la pile…(réactions chimiques exothermique avec de la chaux vive par exemple, à voir)

 

 

 

Le GPS

Plutôt facile d’utilisation(on appuie sur un bouton et hop ayé c ‘est bâché on a sa position), le principe de fonctionnement du gps est plus difficile à saisir, en gros il va utiliser le temps comme mesure pour déterminer des distances(entre nous et les satellites appropriés)et par recoupement de ces distances(un peu comme un point à 3 relèvements)il va afficher notre latitude et longitude. Actuellement le nombre de satellites utilisés pour ce système dépasse les 24, et ils orbitent autour de la terre à environ 11000 milles. Il y en a autant pour être sûr que au moins trois soient visibles en tout point de la terre en même temps. On va voir aussi que le gps fait intervenir les lois de la relativité restreinte et générale d’Einstein pour obtenir une très bonne précision, non non c’est pas des conneries!

1) Un point à trois relèvements en 3 dimensions

En navigation côtière lorsque l’on fait un point à trois relèvement et qu’on le trace sur la carte, on travaille dans un plan en deux dimensions.

navcotier4

Pour le positionnement avec le gps c’est pareil sauf que là on travaillera en 3D. Le relèvement d’un satellite ne nous situera pas sur une droite mais sur une sphère dont le centre sera le satellite. Le recoupement de ces trois sphères indique deux positions, une sur terre et une autre à l’extérieur qui du coup ne sera pas gardée. Le relèvement compas nous donne un angle et le relèvement du satellite nous donne une distance.

gps-triangulation

Sur ce schéma on remarque la présence d’un quatrième satellite, tiens c’est vrai qu’est-ce qu’il fout là celui là ?

La mesure de la distance entre nous et le satellite est le produit de la vitesse de la lumière(vitesse du signal, 300000 km/s environ dans le vide)avec le temps de réception du signal, donc pour avoir une mesure précise de cette distance il faut que l’horloge interne des satellites et du récepteur soient d’une part synchro et en plus extrêmement précises. Si un satellite envoie un signal au temps 1 et que le gps le reçoit au temps 2, le temps de trajet et donc la distance ne peut être connu que si les horloges sont synchro, si elles ne le sont pas le temps de trajet est faussé et du coup la distance calculée est faussée aussi.

Pour obtenir une précision à la nanoseconde les satellites sont équipés d’horloges atomiques internes, et elles sont toutes synchro entre elles. Problème: une horloge atomique coûtant la peau des fesses, un bras, les yeux de la tête et une bonne blinde  on ne pouvait en équiper tout les gps. On a donc trouvé une parade, on l’étalonne par rapport aux horloges des satellites grâce à un quatrième satellite. Si l’horloge du gps est bien réglée, la sphère de positionnement du quatrième satellite doit couper les autres au même endroit(le petit triangle sur le schéma). Si ce n’est pas le cas, le gps corrige le temps de son horloge pour que ça coincide, dingue non ? en fait le gps donne non seulement un point précis mais aussi le temps avec une précision atomique car il règle son temps en permanence avec celui des satellites, équipés d’horloges atomiques.

2) Tout est relatif…

Comme on vient de le voir le principe du gps se base sur la mesure du temps de parcours de signaux électroniques se déplaçant à la vitesse de la lumière, il est donc important que les horloges sur terre et celles des satellites soient synchro, or l’emploi d’un quatrième satellite n’est pas suffisant…car le temps local du récepteur(le gps) et des satellites n’évoluera pas de la même façon à cause notamment de la grande différence de vitesse entre les deux, bref c’est le bordel.

a. La relativité restreinte

En gros son principe remet en cause la notion de temps absolu. Auparavant on croyait que le temps s’écoulait de la même façon et à la même vitesse partout dans l’univers et pour tout le monde, et que la vitesse de la lumière était infinie. En fait c’est la vitesse de la lumière qui est une notion absolue et finie, le temps est relatif à son sujet selon sa vitesse par rapport à la vitesse de la lumière. Le paradoxe des jumeaux(appelé aussi paradoxe des horloges)illustre bien le problème. On prend deux jumeaux, on en met un dans un vaisseau spatial capable de se déplacer à un vitesse proche de la lumière, et l’autre reste sur terre. Si le premier part acheter du pain sur Osiris (une exoplanète)en navette spatiale, il va revenir plus jeune que celui resté sur terre! Pour comprendre le phénomène les plus courageux pourront s’intéresser aux équations de Lorentz, bien expliquées dans le bouquin « la relativité » d’Einstein, sinon en allant sur youtube il y a un épisode de la quatrième dimension qui illustre ce principe. Cela n’est valable que quand les différences de vitesses sont proches de la lumière, on ne vas pas vieillir plus lentement en faisant du 300 à l’heure sur l’autoroute! On risque même le contraire là…

Un satellite gps se déplace à environ 14000 km/heure, donc sa vitesse est non négligeable par rapport à celle de la lumière…

Petite équation simple pour se rendre compte du phénomène:

S=√(1-v²/c²)

S est le facteur de contraction, il indique le changement relatif du temps et de l’espace dans un objet à la vitesse v. Pour notre navette spatiale qui roule à 150000 km/s ça donne:

S=√(1-150000²/300000²)=0.87, le temps dans la navette évoluera à 87% du temps de référence(la terre), donc le temps dans la navette se déroulera 13% moins vite que celui de la terre.

Pour notre satellite qui se déplace bien vite par rapport à notre récepteur gps cela créer un décalage infime mais non négligeable de 8 microsecondes par jour de retard par rapport à notre temps.

b. La relativité générale

Tout le monde connaît l’effet Doppler, particulièrement les gendarmes qui en on fait leur fond de commerce… immobile dans la rue, si une moto se rapproche de nous son bruit de moteur va monter dans les aigus, et quand elle s’éloigne de nous ça bascule dans les graves.

doppler

Si on connait la vitesse du son dans l’air(environ 340m/s)on peut alors calculer la vitesse du véhicule. Et bien cet effet marche aussi avec la lumière! et comme la vitesse de la lumière est liée au temps…C’est la zone!

Dans notre cas on vas alors parler d’effet Doppler gravitationnel(pour le placer en soirée où à table celui là c’est chaud), explication: la lumière peut se présenter sous la forme d’un transfert d’informations via les photons, particules n’ayant pas de masse donc capable d’atteindre dans le vide la vitesse maximale de 300000 km/s. Mais même sans masse les photons sont déviés par la gravité, et la gravité est équivalente à une accélération. De plus la lumière est à la fois une onde(comme le son…)et un mouvement de particules. Conclusion: un champ de gravité accélère les photons et augmente les fréquences de la lumière. En gros la fréquence de la lumière sera augmentée quand le satellite enverra son signal vers nous, et elle sera ralentie quand le signal ira de bas en haut à cause de la gravité. En fait le champ gravitationnel plus fort sur terre ralenti la lumière et donc le temps par rapport au champ gravitationnel du satellite.

Ce principe de relativité générale provoque un décalage de 46 microsecondes par jour entre notre temps local et celui du satellite(46 microsecondes en moins pour nous donc).

Le gps doit donc corriger par jour un décalage de 38 microsecondes environ, sinon il perdrait chaque jours 12 km de précision!(299792458 m/s multiplié par ces 38 microsecondes donne presque 12 km) Malgré sa simplicité d’utilisation, le gps utilise finalement des concepts complexes.

Trouver sa latitude avec pas grand chose

A la recherche du salon annuel de la charentaise à Tripaille-en-Paumé, de renommée plutôt locale, vous réalisez avec une stupeur effrayante une erreur sur votre itinéraire. Au lieu d’emprunter la sortie d’autoroute A234 en direction de la zone indus de Létron-la-Trine, vous avez bifurqué trop tôt en prenant le chemin du siège social de l’amicale de sculpture sur boîtes à camembert au carrefour de Bermudaille-en-Paté… Waaah la tuile! Impossible de se situer sur la carte! Bon y a peut-être moyen au moins de définir sa latitude… Sinon on peut aussi allumer le gps ou demander son chemin se sera quand même plus efficace!

1) Le soleil, un bâton, un truc pour mesurer…Et le bon moment

On pense souvent que la découverte de la Terre ronde comme un ballon de foot est attribuée à Christophe Colomb, en fait la réalité est un peu plus complexe. Ce dernier a prouvé cela de façon empirique avec ses voyages, mais il a démontré une théorie déjà évoquée depuis longtemps. Plusieurs siècles plus tôt(5ème siècle avant JC)Platon considérait déjà la Terre comme sphérique. En effet les Grecs avaient déjà noté le caractère courbe de la surface terrestre(un bateau faisant cap sur l’horizon voit d’abord sa coque disparaître, puis le bas de son mât, et enfin le reste). Mais au 2ème siècle avant JC un grec a réussi grâce à une méthode très simple à calculer la circonférence de notre ballon de foot, avec une précision assez incroyable pour l’époque(700 km de différence seulement avec notre valeur actuelle!)c’est Eratosthène.

Son raisonnement était le suivant: comme la terre est courbe, alors les rayons du soleil atteignent la surface terrestre avec des angles différents. Il a ajouté à ça un peu de trigonométrie pour assaisonner et c’est tout.

eratosthène

Pour son calcul il considérait les rayons du Soleil parallèles entre eux(car cet astre par rapport à la Terre est bien plus volumineux et surtout très éloigné). A l’époque il savait que lors du 21 juin(solstice d’été), à midi local à Assouan les silhouettes verticales ne dessinaient pas d’ombre, il a donc déduit qu’à ce moment là le Soleil se situait sur la droite perpendiculaire à la tangente passant par Assouan. Après tout ça il est facile de deviner la distance angulaire  entre Assouan et Alexandrie(angla alpha sur le schéma), en plantant un bâton à Alexandrie et en observant son ombre à midi local le 21 juin, on trouve alpha.

eratosthène2

Il faut planter le bâton le plus droit possible(utiliser un fil à plomb)pour avoir une mesure la plus précise possible(pour être encore plus précis, utiliser de préférence un bâton grand et fin, et un sol bien plane). En connaissant la taille de notre bâton et en mesurant l’ombre on peut rapidement retrouver alpha avec un peu de trigo(l’ensemble forme un triangle rectangle). En effet Tan(alpha)=côté opposé/côté adjacent donc Tan(alpha)=ombre/bâton. Eratosthène a trouvé un angle alpha égal à 7, 2° environ.

Comme il connaissait la distance entre les deux villes, et que 7, 2° équivaut à 1/50ème de 360°(soit la circonférence totale de la Terre)il a alors multiplié la distance entre les deux villes par 50 ce qui donna 39350 km(la valeur réelle approximative est de 40033 km).

Bon vous allez dire c’est bien gentil tout ça mais pour aller à Tripaille-en-Paumé on est pas plus avancé là! Oui c’est sûr, mais en prenant le problème d’une autre façon on peut trouver sa latitude, à peu près en tout cas…

En connaissant la règle des quatre 21(voir article « la sphère céleste »)on sait environ la position du pied de l’astre du Soleil aux solstices(+ou-23°26′) et aux équinoxes(0°)en latitude. Donc si dans ce cas on veut connaître la latitude d’Alexandrie il suffit d’additionner l’angle alpha à la latitude d’Assouan. Assouan a une latitude d’environ 24°(logique puisqu’au solstice d’été, le 21 juin le pied de l’astre Solaire a une latitude de 23°26′, or à cette date il n’y a pas d’ombre pour les silhouettes verticales à Assouan)donc Alexandrie a une latitude de 31° à peu près.

Maintenant dans notre cas si nous sommes perdu le 22 septembre et que nous calculons alpha à midi local(pour trouver le midi local avec le bâton, c’est le moment où ce dernier dessinera sur le sol l’ombre la plus courte dans la journée, car à ce moment là le soleil sera le plus haut sur l’horizon), si alpha est égal à 51° cela veut dire que notre latitude est de 51°(car le jour de l’équinoxe d’automne la latitude du pied de l’astre Soleil=0° à midi local environ). Après pour avoir la position en latitude du pied de l’astre Soleil à l’année il faut trimballer les éphémérides dans la boîte à gants mais bon là…

Remarque: si on arrive à définir l’heure précise du midi local de notre lieu(grâce à l’ombre du bâton qui rétrécit jusqu’à midi local puis qui réaugmente ensuite), et que notre montre est pile réglée à l’heure UT, et que par miracle on a à disposition les éphémérides dans la boîte à gants alors on pourra trouver aussi approximativement notre longitude.

eratosthène3

Pour trouver notre midi local avec précision, on va faire un peu la même méthode employée pour la méridienne(voir article « La Méridienne »). Comme le soleil reste à son zénith un certain temps, difficile de trouver le temps exact du midi local en mesurant juste la taille de l’ombre quand elle semble être la plus réduite. En fait on va prendre une mesure de l’ombre quand le soleil est orienté sud-est (en notant l’heure à ce moment là) avec un fil tendu partant de la base du bâton, et on trace au sol un arc de cercle(de rayon égal à cette mesure). Quand l’ombre recoupe notre tracé(le soleil va se rapprocher de l’ouest) on note aussitôt l’heure; l’heure du midi local est alors la somme de ces deux heures divisée par deux.

Dans les éphémérides, on retrouve l’heure de passage du soleil au méridien de Greenwich(le midi local de Greenwich). Donc si notre montre est en heure UT précise, que l’on a réussit à définir notre midi local alors on trouvera notre longitude. Le soleil évolue autour de la Terre(dans notre référentiel bien sûr!)au rythme de 15° par heure environ(cette vitesse est de toute façon indiquée de façon plus précise dans les éphémérides), donc notre longitude=(heure midi local-heure midi local Greenwich)*15.

2) Le pendule du professeur Tournesol

Dans l’article « Coriolis », on a vu que plus l’on s’approchait des pôles et plus Coriolis avait tendance à dévier les corps en mouvement sur de longues distances(vent et courant)vers la droite dans l’hémisphère nord et la gauche dans l’hémisphère sud. Inversement plus l’on s’approche de l’équateur et plus cette « force » s’annule. Donc garé sur le parking de l’église entre Brignolle-la-Farfouillette et Létron-la-Trine, on est en droit de se demander si il n’existe pas un lien ou une formule entre Coriolis et le changement de latitude…Quand on s’ennuie faut bien s’occuper!

On peut effectivement trouver un lien par le biais du pendule de Foucault, son principe fonctionne un peu comme un gyroscope. En gros lorsque l’on fait osciller un pendule(on considère les forces de frottement nulles, le mouvement d’oscillation continue indéfiniment), son plan d’oscillation va rester fixe par rapport à la rotation de la terre sur elle-même, en fait c’est le plan sous le pendule qui va tourner par rapport à lui. Il est facile de déduire la vitesse de rotation du plan du pendule si il est situé pile sur l’un des deux pôles:

pendule

On vas dire que le pendule oscille entre A et B. Si le pendule se situe pile sur le pôle Nord alors le plan sous le pendule va tourner à la vitesse de 15° par heure environ dans le sens anti-horaire(car la terre tourne sur elle-même en 24 heures donc 360°/24 heures, et le soleil se couche à l’Ouest). Au pôle Sud se sera la même vitesse mais dans le sens horaire, et à l’équateur comme Coriolis est nulle le plan sera fixe par rapport au plan d’oscillation du pendule. Mais alors à Brignolle-la-Farfouillette, comment ça se passe? En fait cela crée un mouvement apparent du pendule dans le sens opposé(pôle Nord, le pendule tourne en sens horaire et au pôle sud en sens anti-horaire).

Et puis la vitesse de rotation va dépendre de la latitude du pendule, grâce à la différence de vitesse linéaire selon la latitude. Sur le schéma suivant les points B, A et C sont situés à des latitudes différentes, leur vitesse angulaire terrestre est la même(360° en 24 heures), mais pas leur vitesse linéaire(car la circonférence de la Terre diminue quand la latitude augmente, du coup le point aura moins de chemin à parcourir en 24 heures, donc sa vitesse linéaire sera plus lente si sa latitude augmente. Sur ce schéma le centre du pendule est A et il oscille entre B et C; la latitude de A est l’angle alpha et R le rayon de la Terre:

pendule2

La vitesse linéaire de A est égale à la vitesse angulaire de la Terre(w) multipliée par R1 donc Va=w*R1; R1=cos(alpha)*R. Du coup Va=w*cos(alpha)*R.

Vb=w*R2, et R2=R1-x. x=cos(bêta)*d d’après la trigo, or l’angle bêta=90°-alpha donc cos(90°-alpha)=sin(alpha). x=sin(alpha)*d. Donc R2=cos(alpha)*R-sin(alpha)*d, Vb=w*(cos(alpha)*R-sin(alpha)*d)

Avec un raisonnement analogue on trouve Vc=w*(cos(alpha)*R+sin(alpha)*d)

Au final on remarque que Vc>Va>Vb, et entre chacune de ces vitesses la différence est de w*sin(alpha)*d. Cette différence entre les vitesses va créer le mouvement apparent du plan sous le pendule. On peut en déduire que la vitesse angulaire de ce plan est de w*sin(alpha), autrement dit la vitesse de rotation angulaire de la Terre multipliée par le sinus de la latitude(on enlève d qui est la largeur du plan, indépendante de la vitesse angulaire). Pour conclure on peut écrire cette équation:

angle de rotation par heure=15*sin(latitude)

(Remarque: aux pôles avec une latitude de 90° on retrouve le principe énoncé au-dessus, tout comme avec une latitude de 0° à l’équateur.)

3) Rappel

La hauteur de l’étoile polaire sur l’horizon donne aussi notre latitude(article « se positionner sans gps ni calculatrice »). Après je n’ai pas encore essayé mais sachant que Mintaka(constellation d’Orion) est quasiment située sur l’équateur céleste, peut-être que sa hauteur sur l’horizon moins 90° donne notre latitude…à voir. Sinon pour retrouver son chemin on peut aussi demander sa position au premier piéton croisé, ça ira plus vite!

 

 

 

 

 

Fabriquer une boussole

Un après midi de toussaint pluvieux, alors que la télévision ne capte que derrick et que vous venez de recevoir vos factures, attention l’ennui et la déprime guette…mais tiens donc qu’est-ce que je peut faire? vider le frigo? compter les dalles de carrelage dans la salle de bain? apprendre l’annuaire par cœur pour le délire? organiser un tournoi de mikado avec mon chien? Bof… Ha ba non je peut faire une boussole au fait! Comme ça je saurai enfin si la porte de mes toilettes est exposée nord, sud… Depuis le temps que je me posait cette question fatidique, c’est merveilleux tout ça!

1) Matos nécessaire

On prend une aiguille à coudre, un bol ou une assiette creuse, un aimant, un petit bout de carton fin, une pile de 4,5 volts style grosse pile carrée dans les vieilles lampes torche, et si on a ça sous la main un peu de fil de cuivre émaillé(on en trouve dans les vieux postes radio par exemple, c’est du fil de cuivre avec un vernis isolant dessus).

2) Comment ça se passe

Tout d’abord on remplit le bol de flotte(avec un liquide moins dense comme l’huile ça marche mieux mais bon de l’eau c’est bien), puis on prend l’aiguille et l’aimant. On va ensuite frotter l’aiguille avec l’aimant mais toujours dans le même sens(pas de va et vient, on frotte de bas en haut, de bas en haut…)pendant 5 minutes puis on dépose l’aiguille sur le morceau de carton, et le carton sur l’eau au milieu du bol. Au bout d’un moment l’aiguille va arrêter de tourner et se stabiliser dans l’axe nord/sud(très efficace pour draguer en boîte de nuit).

boussole (Copier)

En frottant cette aiguille dans le sens tête/pointe, le côté piquant de l’aiguille indique le sud.

On peut aussi magnétiser l’aiguille en l’enroulant avec du fil de cuivre vernis, puis on connecte les 2 extrémités du fil avec les bornes de la pile(ne pas oublier de poncer le vernis aux extrémités du fil pour que ça fonctionne, si la pile chauffe après un petit délais alors ça marche)enfin bref avec un aimant c’est plus simple pour le même résultat.

3) Avec un aimant néodyme

Le truc le plus efficace est l’utilisation d’un aimant néodyme à la place de l’aiguille. Très rapidement il va se mettre dans l’axe nord/sud.

boussole2 (Copier)

L’aimant néodyme est tellement puissant que l’on peut même se passer du bol d’eau, en le maintenant en équilibre sur l’ongle du pouce il va tourner et se mettre dans l’axe nord/sud tout seul(Gérard Majax peut aller se rhabiller!).

(Remarque: Si on applique cette méthode et que l’on peut en même temps voir l’étoile polaire, on peut approximativement trouver la déclinaison de l’endroit où nous sommes sans gps ni compas, bon d’accord ça sert pas à grand chose mais au moins ça occupe la soirée…)

 

 

1)Fabriquer un sextant pour que dalle

Pour s’initier à la navigation astronomique, on pense qu’il est indispensable d’acheter un sextant. Le premier prix pour cet instrument est le mark 3 qui coûte une soixantaine d’euros. Pour avoir des mesures plus précises de sa position, le tarif devient par la suite rapidement exponentiel…et inversement proportionnel à la motivation d’apprendre qui peut vite décliner. C’est vrai, pourquoi s’embêter à dépenser de l’argent et faire des calculs alors qu’avec le même prix on peut s’offrir un gps de bonne qualité? La petite méthode suivante permet non seulement de ne pas débourser plus de dix euros, mais en plus elle permet de mesurer des hauteurs d’étoiles sans avoir besoin de pouvoir distinguer l’horizon.

1)Matériel

Il suffit d’avoir sous la main un simple rapporteur en plastique, un fil long (un mètre, un mètre cinquante)et fin, un truc qui fait lest(un ou plusieurs gros écrous par exemple)et un morceau de bois ou de plastique long, bien droit et de section carrée. Un petit tube de colle forte nous permettra de coller le rapporteur et la pièce en bois ou plastique de la façon suivante:

sextant brico (Copier)

Il faut bien faire attention à coller le bord droit du rapporteur bien parallèle au morceau de bois.

Ensuite on fait passer le fil dans le petit trou central du rapporteur, on fait un nœud d’arrêt tout bête et au bout du fil on attache le lest(pour la photo j’ai mis une clé, tant qu’il y a un peu de poids le reste n’a pas d’importance).

sextant brico2 (Copier)

Ayé finit! On l’utilise de la façon suivante:

sextantbricolo

Plus le bout de bois est long, droit, et plus le fil est fin et le lest lourd, plus on gagne en précision. On peut aussi installer l’ensemble sur un trépied avec un axe pivotant pour rendre la lecture encore plus précise sans les tremblements pendant la mesure.

La mesure de la hauteur de l’astre se fait en retirant 90° de X:

sextantbricoli

2)Avantages/inconvénients

Cette méthode présente le net avantage de mesurer la hauteur d’un astre sans avoir besoin de distinguer l’horizon, on peut donc s’exercer en ville par exemple, la vue de l’étoile suffit. Par contre à bord d’un bateau la mer doit être d’huile et le bateau à l’arrêt pour l’utiliser, sinon le lest bouge et on ne pourra pas mesurer la hauteur. Pour fabriquer un sextant plus élaboré vous pouvez aller lire la page du site sur comment fabriquer un sextant électronique avec arduino.