Outils pour utilisateurs

Outils du site


bts:python:ajustement

Ajustement avec Python

On se propose d'utiliser Python pour faire un ajustement. Les données sont placées dans un fichier. Voici ce que l'on souhaite faire :

  • extraire les données du fichier,
  • afficher le nuage de point,
  • l'ajustement affine ne sera pas possible → faire un changement de variable,
  • calculer les indicateurs statistiques (variance, covariance…)
  • calculer les paramètres de l'ajustement

Python est juste un langage parmi d'autres et n'est pas à votre programme. Je ne prétend pas ici vous donnez un cours de programmation. Je vous montre simplement ce qui est faisable en vous donnant quelques recettes pour ouvrir un fichier, faire un calcul sur tous les éléments d'une liste, etc.

Vous pourrez utiliser l'environnement EduPython. Vous écrirez tout votre programme dans un même fichier. Pensez à le sauvegarder dès le début. Pensez aussi à placer le fichier de données au même endroit que le fichier python.

L'expérience

On a exploité une résistance à coefficient de température négatif – CTN – c'est à dire, une résistance dont la valeur diminue quand la température augmente. On peut par exemple s'en servir pour faire un capteur de température.

Pour différentes températures on a relevé les valeurs présentes dans le fichier ctn_data.csv

Voici un aperçu du contenu (10 premières lignes) :

requested local CSV file does not exist

Attention : Les valeurs ne sont pas triées.

Mais ce qui précède est une version mise en forme. Le fichier est un simple fichier texte contenant les données sous une forme brutes. Voici à quoi ressemble son contenu (10 premières lignes)

T(°C),R
2,3478.9
0,3887.0
3,3237.0
0,3965.1
1,3600.6
5,2911.8
6,2645.8
9,2165.6
6,2576.0

Téléchargez le fichier csv. Surtout ne l'ouvrez pas avec Excel ! Inutile de l'ouvrir.

Chargement des données

Nous commençons le programme Python. Créez un nouveau fichier, par exemple dans EduPython. Sauvegardez-le tout de suite à côté (dans le même dossier) du fichier csv.

Première étape, utiliser Python pour ouvrir et extraire les données du fichier. Il faudra pour cela :

  • ouvrir le fichier – c'est à dire demander au système d'exploitation de donner accès en lecture au fichier demandé ;
  • lire ligne à ligne pour transformer le contenu du fichier de texte à nombre ;
  • stocker les valeurs obtenues dans des tableaux, un pour les températures et l'autre pour les résistances.
with open('ctn_data.csv', 'r') as f:
    lignes_brutes = f.readlines()

Nous avons ouvert 'ctn_data.csv' en mode 'r' (read = lecture). Nous avons produit un tableau lignes_brutes qui contient les lignes du fichier. Pour l'instant ces lignes ne sont que du texte.

with open('ctn_data.csv', 'r') as f:
    lignes_brutes = f.readlines()

liste_t = []
liste_r = []
for ligne in lignes_brutes[1:]:
    t_texte, r_texte = ligne.split(',')
    t = int(t_texte)
    r = float(r_texte)
    liste_t.append(t)
    liste_r.append(r)

Pour chaque ligne, on a découpé la ligne à la virgule (split) et on a converti le premier morceau en entier (int) et le 2e morceau en nombre à virgule (float). À mesure qu'on les lit, on les ajoute (append) dans leurs tableaux respectifs (liste_t et liste_r)

Premier graphique

On peut représenter le nuage de point correspondant. Pour cela on utilise la bibliothèque matplotlib. Nous devons ajouter en première ligne :

import matplotlib.pyplot as plt

Ainsi on pourra utiliser les fonctions graphiques de matplotlib en utilisant l'alias plt.

scatter permet de tracer un nuage de point. On ajoute à la fin :

plt.scatter(liste_t, liste_r)
plt.show()

L'affichage du graphique met le programme en pause. Il faut donc fermer la fenêtre pour que le programme continue. Maintenant que nous avons vu le graphique, vous pouvez supprimer les deux dernières lignes.

Changement de variable

Les points ne sont pas du tout alignés. On envisage de faire un changement de variables. La physique nous dit que le bon modèle est : $$R = \exp\left(\frac{A}{T} + B\right)$$ avec $T$ en Kelvin.

On propose donc le changement de variable : $y = \ln(R)$ et $x = \dfrac{1}{t + 273.15}$ où $t$ est la température en °C.

Nous aurons besoin des fonctions $\ln$ et $\exp$. Il faut les importer. Notez que les anglais notent $\log$ pour $\ln$.

Au début :

import matplotlib.pyplot as plt
from math import log, exp

Puis à la fin :

liste_y = [log(r) for r in liste_r]
liste_x = [1/(t + 273.15) for t in liste_t]

# affichage :
plt.scatter(liste_x, liste_y)
plt.show()

L'affichage nous montre des points bien alignés. On se propose de faire un ajustement affine de y en x.

Pensez à supprimer les lignes à partir de # affichage, elles ne serviront plus.

Calcul de l'ajustement

On cherche la droite d'équation $y = a\cdot x + b$ où $a = \dfrac{cov(x,y)}{var(x)}$ et $b = \overline{y} - a \cdot \overline{x}$. On cherche aussi $r^2 = \dfrac{cov(x,y)^2}{var(x)\cdot var(y)}$

Nous devons donc calculer $cov(x,y)$, $var(x)$, $\overline{x}$, $\overline{y}$.

Je vous propose cette fonction pour la moyenne :

def moyenne(liste):
    '''
    renvoie la moyenne des items de liste
    '''
    return sum(liste) / len(liste)

Pour la covariance c'est un peu plus compliqué :

def covariance(liste_a, liste_b):
    '''
    renvoie la covariance entre les items des listes a et b
    c'est à dire 1/N * somme(a*b) - moyenne a * moeynne b
    '''
    liste_ab = [a*b for a, b in zip(liste_a, liste_b)]
    N = len(liste_ab)
    return sum(liste_ab) / N - moyenne(liste_a) * moyenne(liste_b)

Inutile de faire une fonction pour la variance car $var(x) = cov(x,x)$.

Ajoutez les lignes de codes permettant de calculer $a$, $b$ et $r^2$.

a = # à vous
b = # à vous
r2 = # à vous

Final

Vous devriez en être là :

import matplotlib.pyplot as plt
from math import log, exp

with open('ctn_data.csv', 'r') as f:
    lignes_brutes = f.readlines()

liste_t = []
liste_r = []
for ligne in lignes_brutes[1:]:
    t_texte, r_texte = ligne.split(',')
    t = int(t_texte)
    r = float(r_texte)
    liste_t.append(t)
    liste_r.append(r)
    
liste_y = [log(r) for r in liste_r]
liste_x = [1/(t + 273.15) for t in liste_t]

def moyenne(liste):
    '''
    renvoie la moyenne des items de liste
    '''
    return sum(liste) / len(liste)

def covariance(liste_a, liste_b):
    '''
    renvoie la covariance entre les items des listes a et b
    c'est à dire 1/N * somme(a*b) - moyenne a * moeynne b
    '''
    liste_ab = [a*b for a, b in zip(liste_a, liste_b)]
    N = len(liste_ab)
    return sum(liste_ab) / N - moyenne(liste_a) * moyenne(liste_b)
    
a = # à vous
b = # à vous
r2 = # à vous

Pour $t$ donné, on peut calculer $x = \dfrac{1}{t + 273.15}$ puis $y = a\cdot x + b$ et enfin $R = \exp(y)$. Mettons tout cela dans une fonction :

def R(t):
    x = 1/(t + 273.15)
    y = a*x + b
    return exp(y)

On peut maintenant confronter notre modèle à l'expérience. Nous allons tracer de nouveau le nuage de point du début et nous allons ajouter la courbe de notre modèle.

t_modele = [t for t in range(100)]
r_modele = [R(t) for t in t_modele]
plt.scatter(liste_t, liste_r, label='expérience')
plt.plot(t_modele, r_modele, 'r', label='modèle') # 'r': en rouge
plt.legend() # affiche une légende
plt.show()

Conclusion

Ce programme n'est pas trop compliqué et peut facilement être adapté à diverses situation. On n'a pas besoin de voir le détail des données comme on le ferait dans Excel.

De plus, on pourrait adapter notre programme pour des cas de base de données contenant des milliers d'entrées, ce qui serait plus compliqué à faire sur un tableur.

Enfin, la qualité des graphiques de matplotlib est sans comparaison avec les graphiques de Excel…

bts/python/ajustement.txt · Dernière modification : de goupillwiki