#+TITLE: Sujet 4 : Estimation de la latence et de la capacité d’une connexion à partir de mesures asymétriques #+AUTHOR: Samuel MEYNARD #+DATE: <2020-06-06 Sat> #+LANGUAGE: fr # #+PROPERTY: header-args :eval never-export #+HTML_HEAD: #+HTML_HEAD: #+HTML_HEAD: #+HTML_HEAD: #+HTML_HEAD: #+HTML_HEAD: * Énoncé Un modèle simple et fréquemment utilisé pour décrire la performance d'une connexion de réseau consiste à supposer que le temps d'envoi T pour un message dépend principalement de sa taille $S$ (nombre d'octets) et de deux grandeurs propres à la connexion : la latence $L$ (en secondes) et la capacité $C$ (en octets/seconde). La relation entre ces quatre quantités est $T(S) = L + S/C$. Ce modèle néglige un grand nombre de détails. D'une part, $L$ et $C$ dépendent bien sûr du protocole de communication choisi mais aussi dans une certaine mesure de $S$. D'autre part, la mesure de $T(S)$ comporte en général une forte composante aléatoire. Nous nous intéressons ici au temps moyen qu'il faut pour envoyer un message d'une taille donnée. Votre tâche est d'estimer $L$ et $C$ à partir d'une série d'observations de $T$ pour des valeurs différentes de $S$. Préparez votre analyse sous forme d'un document computationnel réplicable qui commence avec la lectures des données brutes, disponibles pour deux connexions différentes, qui ont été obtenues avec l'outil ping : - Le premier jeu de données examine une connexion courte à l'intérieur d'un campus : http://mescal.imag.fr/membres/arnaud.legrand/teaching/2014/RICM4_EP_ping/liglab2.log.gz - Le deuxième jeu de données mesure la performance d'une connexion vers un site Web éloigné assez populaire et donc chargé : http://mescal.imag.fr/membres/arnaud.legrand/teaching/2014/RICM4_EP_ping/stackoverflow.log.gz Les deux fichiers contiennent la sortie brute de l'outil ping qui a été exécuté dans une boucle en variant de façon aléatoire la taille du message. Chaque ligne a la forme suivante: #+BEGIN_SRC [1421761682.052172] 665 bytes from lig-publig.imag.fr (129.88.11.7): icmp_seq=1 ttl=60 time=22.5 ms #+END_SRC Au début, entre crochet, vous trouvez la date à laquelle la mesure a été prise, exprimée en secondes depuis le 1er janvier 1970. La taille du message en octets est donnée juste après, suivie par le nom de la machine cible et son adresse IP, qui sont normalement identiques pour toutes les lignes à l'intérieur d'un jeu de données. À la fin de la ligne, nous trouvons le temps d'envoi (aller-retour) en millisecondes. Les autres indications, =icmp_seq= et =ttl=, n'ont pas d'importance pour notre analyse. Attention, il peut arriver qu'une ligne soit incomplète et il faut donc vérifier chaque ligne avant d'en extraire des informations ! _Votre mission si vous l'acceptez :_ 1. Commencez par travailler avec le premier jeu de données (liglab2). Représentez graphiquement l'évolution du temps de transmission au cours du temps (éventuellement à différents instants et différentes échelles de temps) pour évaluer la stabilité temporelle du phénomène. Ces variations peuvent-elles être expliquées seulement par la taille des messages ? 2. Représentez le temps de transmission en fonction de la taille des messages. Vous devriez observer une "rupture", une taille à partir de laquelle la nature de la variabilité change. Vous estimerez (graphiquement) cette taille afin de traiter les deux classes de tailles de message séparément. 3. Effectuez une régression linéaire pour chacune des deux classes et évaluez les valeurs de L et de C correspondantes. Vous superposerez le résultat de cette régression linéaire au graphe précédent. 4. (Optionnel) La variabilité est tellement forte et asymétrique que la régression du temps moyen peut être considérée comme peu pertinente. On peut vouloir s'intéresser à caractériser plutôt le plus petit temps de transmission. Une approche possible consiste donc à filtrer le plus petit temps de transmission pour chaque taille de message et à effectuer la régression sur ce sous-ensemble de données. Cela peut également être l'occasion pour ceux qui le souhaitent de se familiariser avec la régression de quantiles (implémentée en R dans la bibliothèque quantreg et en Python dans la bibliothèque statsmodels). 5. Répétez les étapes précédentes avec le second jeu de données (stackoverflow) 6. Déposer dans FUN votre résultat * Cas 1 : Liglab2 ** Récupération du 1^er jeu de donnée *** Téléchargement #+BEGIN_SRC python :session :file step1.txt :results silent export code from urllib.request import urlretrieve from os import path liglab_file = "liglab2.log" liglab_filegz = liglab_file + ".gz" url = "http://mescal.imag.fr/membres/arnaud.legrand/teaching/2014/RICM4_EP_ping/liglab2.log.gz" if not path.exists(liglab_file): urlretrieve(url, liglab_filegz) #+END_SRC #+RESULTS: [[file:step1.txt]] *** Lecture du fichier #+BEGIN_SRC python :session :results silent export: code import gzip f = gzip.open(liglab_filegz) data = f.read().decode('latin-1').strip().splitlines() f.close() #+END_SRC #+RESULTS: *** Création d'un tableau sans les données incomplète #+BEGIN_SRC python :session :results replace export: code table = [row.split(' ') for row in data] cleantable = [] for row in table: if len(row) == 10: cleantable.append(row) cleantable[:4] #+END_SRC #+RESULTS: | [1421771203.082701] | 1257 | bytes | from | stackoverflow.com | (198.252.206.140): | icmp_seq=1 | ttl=50 | time=120 | ms | | [1421771203.408254] | 454 | bytes | from | stackoverflow.com | (198.252.206.140): | icmp_seq=1 | ttl=50 | time=120 | ms | | [1421771203.739730] | 775 | bytes | from | stackoverflow.com | (198.252.206.140): | icmp_seq=1 | ttl=50 | time=126 | ms | | [1421771204.056630] | 1334 | bytes | from | stackoverflow.com | (198.252.206.140): | icmp_seq=1 | ttl=50 | time=112 | ms | #+BEGIN_SRC python :session :results replace export: code from datetime import datetime date = [datetime.utcfromtimestamp(float(row[0][1:-1])) for row in cleantable] S = [int(row[1]) for row in cleantable] source = [str(row[4]) for row in cleantable] ip = [str(row[5][1:-1]) for row in cleantable] T = [float(row[8].split('=')[1]) for row in cleantable] dataset = list(zip(date,donnee, ltime)) T[:10] #+END_SRC #+RESULTS: | 22.5 | 21.2 | 21.2 | 23.3 | 1.41 | 21.9 | 78.7 | 25.1 | 24.0 | 19.5 | ** Analyse *** Cas 1 : evolution de la durée de transmission dans le temps #+BEGIN_SRC python :session :results silent :file test.png import matplotlib import matplotlib.pyplot as plt # Create figure and plot space fig, ax = plt.subplots(figsize=(12, 12)) # Add x-axis and y-axis ax.scatter(date, T, color='purple') # Set title and labels for axes ax.set(xlabel="Date", ylabel="Temps de transmission", title="Evolution de la dunée de transmission de transmission dans le temps") plt.savefig('evol_temps_transmission_dans_le_temps.png') #+END_SRC #+RESULTS: : None [[file:./evol_temps_transmission_dans_le_temps.png]] Après analyse visuelle, il ne semble pas avoir d'impact au travers le temps *** Cas 2 : Evolution du temps de transmission en fonction de la taille #+BEGIN_SRC python :session :results silent :file test2.png import matplotlib import matplotlib.pyplot as plt # Create figure and plot space fig, ax = plt.subplots(figsize=(12, 12)) # Add x-axis and y-axis ax.scatter(S, T, color='purple') # Set title and labels for axes ax.set(xlabel="Taille des donnee", ylabel="Temps de transmission", title="Evolution du temps de transmission en fonction de la taille des données") plt.savefig('evol_temps_transmission_en_fonction_de_la_taille.png') #+END_SRC [[file:./evol_temps_transmission_en_fonction_de_la_taille.png]] Ici, on voit l'impact de la MTU ici certainement à 1500 sur le temps de transport. Après mesure, celle ci est à 1485. ** Differenciation par rapport à la taille Nous allons découpé le corpus, en deux sous ensemble. Un inférieur à la MTU et un supérieur. *** Inférieur à la MTU #+BEGIN_SRC python :session table_l1500 = [row for row in cleantable if int(row[1]) <= 1485] date_l1500 = [datetime.utcfromtimestamp(float(row[0][1:-1])) for row in table_l1500] S_l1500 = [int(row[1]) for row in table_l1500] T_l1500 = [float(row[8].split('=')[1]) for row in table_l1500] dataset_l1500 = list(zip(date_l1500,S_l1500, T_l1500)) dataset_l1500[:10] #+END_SRC #+RESULTS: | datetime.datetime | (2015 1 20 13 48 2 52172) | 665 | 22.5 | | datetime.datetime | (2015 1 20 13 48 2 277315) | 1373 | 21.2 | | datetime.datetime | (2015 1 20 13 48 2 502054) | 262 | 21.2 | | datetime.datetime | (2015 1 20 13 48 2 729257) | 1107 | 23.3 | | datetime.datetime | (2015 1 20 13 48 2 934648) | 1128 | 1.41 | | datetime.datetime | (2015 1 20 13 48 3 160397) | 489 | 21.9 | | datetime.datetime | (2015 1 20 13 48 3 672157) | 1146 | 25.1 | | datetime.datetime | (2015 1 20 13 48 3 899933) | 884 | 24.0 | | datetime.datetime | (2015 1 20 13 48 4 122687) | 1422 | 19.5 | | datetime.datetime | (2015 1 20 13 48 4 344135) | 1180 | 18.0 | #+BEGIN_SRC python :session :results silent :file test2.png import matplotlib import matplotlib.pyplot as plt # Create figure and plot space fig, ax = plt.subplots(figsize=(12, 12)) # Add x-axis and y-axis ax.scatter(S_l1500, T_l1500, color='purple') # Set title and labels for axes ax.set(xlabel="Taille des donnee", ylabel="Temps de transmission", title="Evolution du temps de transmission en fonction de la taille des données") plt.savefig('l1500_evol_T-f(S).png') #+END_SRC *** Supérieur à la MTU Calcul d'un tableau avec les donnée supérieure à la MTU #+BEGIN_SRC python :session table_g1500 = [row for row in cleantable if int(row[1]) >= 1485] date_g1500 = [datetime.utcfromtimestamp(float(row[0][1:-1])) for row in table_g1500] S_g1500 = [int(row[1]) for row in table_g1500] T_g1500 = [float(row[8].split('=')[1]) for row in table_g1500] dataset_g1500 = list(zip(date_g1500,S_g1500, T_g1500)) dataset_g1500[:10] #+END_SRC #+RESULTS: | datetime.datetime | (2015 1 20 13 48 3 443055) | 1759 | 78.7 | | datetime.datetime | (2015 1 20 13 48 5 620117) | 1843 | 2.31 | | datetime.datetime | (2015 1 20 13 48 6 234464) | 1511 | 2.18 | | datetime.datetime | (2015 1 20 13 48 7 463275) | 1510 | 2.17 | | datetime.datetime | (2015 1 20 13 48 7 874230) | 1966 | 2.2 | | datetime.datetime | (2015 1 20 13 48 8 694652) | 1518 | 2.19 | | datetime.datetime | (2015 1 20 13 48 10 335289) | 1732 | 2.29 | | datetime.datetime | (2015 1 20 13 48 10 950126) | 1500 | 2.14 | | datetime.datetime | (2015 1 20 13 48 11 359824) | 1520 | 2.1 | | datetime.datetime | (2015 1 20 13 48 11 974735) | 1509 | 2.23 | #+BEGIN_SRC python :session :results silent :file test2.png import matplotlib import matplotlib.pyplot as plt # Create figure and plot space fig, ax = plt.subplots(figsize=(12, 12)) # Add x-axis and y-axis ax.scatter(S_g1500, T_g1500, color='purple') # Set title and labels for axes ax.set(xlabel="Taille des donnee", ylabel="Temps de transmission", title="Evolution du temps de transmission en fonction de la taille des données") plt.savefig('g1500_evol_T-f(S).png') #+END_SRC ** Régression linéaire Ici, nous allons procédé à une évaluation de C et L par la technique de la régression linéaire. ** Cas inférieur à la MTU #+BEGIN_SRC python :session :results replace import pandas as pd import matplotlib.pyplot as plt from matplotlib import dates import numpy as np from scipy import stats import seaborn as sns import statsmodels.api as sm from sklearn import linear_model @plt.FuncFormatter def fake_dates(x, pos): """ Custom formater to turn floats into e.g., 2016-05-08""" return dates.num2date(x).strftime('%Y-%m-%d') sns.set(color_codes=True) df = pd.DataFrame({ 'date': pd.to_datetime(date_l1500), 'datenum': dates.date2num(date_l1500), 'T': T_l1500, 'S': S_l1500}) fig, ax = plt.subplots() sns.regplot(x="datenum", y="T", color='purple', data=df, ax=ax) # here's the magic: ax.xaxis.set_major_formatter(fake_dates) # legible labels ax.tick_params(labelrotation=30) fig.savefig('l1500_reglineaireT-f(S).png') #+END_SRC [[file:./l1500_reglineaireT-f(S).png]] #+RESULTS: : None #+BEGIN_SRC python :session np.array(S_l1500).reshape(1, -1)[:9] #+END_SRC #+RESULTS: | 1759 | 1843 | 1511 | ... | 1503 | 1515 | 1875 | #+BEGIN_SRC python :session :results replace :exports both from sklearn.linear_model import LinearRegression from sklearn.metrics import mean_squared_error S_tt = [[value] for value in S_l1500] my_s = np.array(S_tt) my_t = np.array(T_l1500) #my_s = np.array([[1], [2], [3]]) lmodel = LinearRegression() lmodel.fit(my_s, my_t) f"Les coeff sont L = {lmodel.intercept_} et C = { 1 / lmodel.coef_}" #+END_SRC #+RESULTS: : Les coeff sont L = 3.257592785874401 et C = [2761.3155395] ** Cas supérieur à la MTU #+BEGIN_SRC python :session :results replace :exports both from sklearn.linear_model import LinearRegression from sklearn.metrics import mean_squared_error S_tt = [[value] for value in S_g1500] my_s = np.array(S_tt) my_t = np.array(T_g1500) #my_s = np.array([[1], [2], [3]]) lmodel = LinearRegression() lmodel.fit(my_s, my_t) f"Les coeff sont L = {lmodel.intercept_} et C = { 1 / lmodel.coef_}" #+END_SRC #+RESULTS: : Les coeff sont L = 5.867233082184833 et C = [441.71908009] * Cas 2 : Stackoverflow ** Récupération du jeu de donnée *** Téléchargement #+BEGIN_SRC python :session :file step1.txt :results replace from urllib.request import urlretrieve from os import path stacko_file = "stackoverflow.log" stacko_filegz = stacko_file + ".gz" url = "http://mescal.imag.fr/membres/arnaud.legrand/teaching/2014/RICM4_EP_ping/stackoverflow.log.gz" if not path.exists(stacko_file): urlretrieve(url, stacko_filegz) #+END_SRC #+RESULTS: : None *** Lecture du fichier #+BEGIN_SRC python :session :results output import gzip f = gzip.open(stacko_filegz) data = f.read().decode('latin-1').strip().splitlines() f.close() #+END_SRC #+RESULTS: #+BEGIN_SRC python :session :results replace table = [row.split(' ') for row in data] cleantable = [] for row in table: if len(row) == 10: cleantable.append(row) cleantable[:4] #+END_SRC #+RESULTS: | [1421771203.082701] | 1257 | bytes | from | stackoverflow.com | (198.252.206.140): | icmp_seq=1 | ttl=50 | time=120 | ms | | [1421771203.408254] | 454 | bytes | from | stackoverflow.com | (198.252.206.140): | icmp_seq=1 | ttl=50 | time=120 | ms | | [1421771203.739730] | 775 | bytes | from | stackoverflow.com | (198.252.206.140): | icmp_seq=1 | ttl=50 | time=126 | ms | | [1421771204.056630] | 1334 | bytes | from | stackoverflow.com | (198.252.206.140): | icmp_seq=1 | ttl=50 | time=112 | ms | #+BEGIN_SRC python :session :results replace from datetime import datetime date = [datetime.utcfromtimestamp(float(row[0][1:-1])) for row in cleantable] S = [int(row[1]) for row in cleantable] source = [str(row[4]) for row in cleantable] ip = [str(row[5][1:-1]) for row in cleantable] T = [float(row[8].split('=')[1]) for row in cleantable] dataset = list(zip(date,donnee, ltime)) T[:10] #+END_SRC #+RESULTS: | 120.0 | 120.0 | 126.0 | 112.0 | 111.0 | 111.0 | 112.0 | 111.0 | 111.0 | 111.0 | #+BEGIN_SRC python :session :results silent :file test.png import matplotlib import matplotlib.pyplot as plt # Create figure and plot space fig, ax = plt.subplots(figsize=(12, 12)) # Add x-axis and y-axis ax.scatter(date, T, color='purple') # Set title and labels for axes ax.set(xlabel="Date", ylabel="Temps de transmission", title="Evolution de la temps de transmission dans le temps") plt.savefig('stacko_evol_temps_transmission_dans_le_temps.png') #+END_SRC #+RESULTS: : None [[file:./evol_temps_transmission_dans_le_temps.png]] Après analyse visuelle, Il ne semble pas avoir d'impact au travers le temps ** Evolution du temps de transmission à travers le temps #+BEGIN_SRC python :session :results silent :file test2.png import matplotlib import matplotlib.pyplot as plt # Create figure and plot space fig, ax = plt.subplots(figsize=(12, 12)) # Add x-axis and y-axis ax.scatter(S, T, color='purple') # Set title and labels for axes ax.set(xlabel="Taille des donnee", ylabel="Temps de transmission", title="Evolution du temps de transmission en fonction de la taille des données") plt.savefig('stacko_evol_temps_transmission_en_fonction_de_la_taille.png') #+END_SRC [[file:./evol_temps_transmission_en_fonction_de_la_taille.png]] Ici, on voit l'impact de la MTU ici certainement à 1500 sur le temps de transport *** Differenciation par rapport à la taille **** Inférieur à la MTU #+BEGIN_SRC python :session table_l1500 = [row for row in cleantable if int(row[1]) <= 1485] date_l1500 = [datetime.utcfromtimestamp(float(row[0][1:-1])) for row in table_l1500] S_l1500 = [int(row[1]) for row in table_l1500] T_l1500 = [float(row[8].split('=')[1]) for row in table_l1500] dataset_l1500 = list(zip(date_l1500,S_l1500, T_l1500)) dataset_l1500[:10] #+END_SRC #+RESULTS: | datetime.datetime | (2015 1 20 16 26 43 82701) | 1257 | 120.0 | | datetime.datetime | (2015 1 20 16 26 43 408254) | 454 | 120.0 | | datetime.datetime | (2015 1 20 16 26 43 739730) | 775 | 126.0 | | datetime.datetime | (2015 1 20 16 26 44 56630) | 1334 | 112.0 | | datetime.datetime | (2015 1 20 16 26 44 372224) | 83 | 111.0 | | datetime.datetime | (2015 1 20 16 26 44 688367) | 694 | 111.0 | | datetime.datetime | (2015 1 20 16 26 45 321112) | 632 | 111.0 | | datetime.datetime | (2015 1 20 16 26 45 637464) | 405 | 111.0 | | datetime.datetime | (2015 1 20 16 26 45 953472) | 1419 | 111.0 | | datetime.datetime | (2015 1 20 16 26 46 269163) | 329 | 111.0 | #+BEGIN_SRC python :session :results silent :file test2.png import matplotlib import matplotlib.pyplot as plt # Create figure and plot space fig, ax = plt.subplots(figsize=(12, 12)) # Add x-axis and y-axis ax.scatter(S_l1500, T_l1500, color='purple') # Set title and labels for axes ax.set(xlabel="Taille des donnee", ylabel="Temps de transmission", title="Evolution du temps de transmission en fonction de la taille des données") plt.savefig('stacko_l1500_evol_T-f(S).png') #+END_SRC [[file:./stacko_l1500_evol_T-f(S).png]] **** Supérieur à la MTU Calcul d'un tableau avec les donnée supérieure à la MTU #+BEGIN_SRC python :session table_g1500 = [row for row in cleantable if int(row[1]) >= 1485] date_g1500 = [datetime.utcfromtimestamp(float(row[0][1:-1])) for row in table_g1500] S_g1500 = [int(row[1]) for row in table_g1500] T_g1500 = [float(row[8].split('=')[1]) for row in table_g1500] dataset_g1500 = list(zip(date_g1500,S_g1500, T_g1500)) dataset_g1500[:10] #+END_SRC #+RESULTS: | datetime.datetime | (2015 1 20 16 26 45 5514) | 1577 | 112.0 | | datetime.datetime | (2015 1 20 16 26 46 901972) | 1714 | 112.0 | | datetime.datetime | (2015 1 20 16 26 47 851148) | 1598 | 112.0 | | datetime.datetime | (2015 1 20 16 26 52 272504) | 1619 | 112.0 | | datetime.datetime | (2015 1 20 16 26 55 749652) | 1655 | 112.0 | | datetime.datetime | (2015 1 20 16 26 56 66885) | 1556 | 112.0 | | datetime.datetime | (2015 1 20 16 26 57 648057) | 1839 | 112.0 | | datetime.datetime | (2015 1 20 16 26 58 280820) | 1572 | 112.0 | | datetime.datetime | (2015 1 20 16 27 1 133246) | 1491 | 120.0 | | datetime.datetime | (2015 1 20 16 27 1 765499) | 1978 | 112.0 | #+BEGIN_SRC python :session :results silent :file test2.png import matplotlib import matplotlib.pyplot as plt # Create figure and plot space fig, ax = plt.subplots(figsize=(12, 12)) # Add x-axis and y-axis ax.scatter(S_g1500, T_g1500, color='purple') # Set title and labels for axes ax.set(xlabel="Taille des donnee", ylabel="Temps de transmission", title="Evolution du temps de transmission en fonction de la taille des données") plt.savefig('stacko_g1500_evol_T-f(S).png') #+END_SRC [[file:./stacko_g1500_evol_T-f(S).png]] ** Régression linéaire *** Cas inférieur à la MTU #+BEGIN_SRC python :session :results replace import pandas as pd import matplotlib.pyplot as plt from matplotlib import dates import numpy as np from scipy import stats import seaborn as sns import statsmodels.api as sm from sklearn import linear_model @plt.FuncFormatter def fake_dates(x, pos): """ Custom formater to turn floats into e.g., 2016-05-08""" return dates.num2date(x).strftime('%Y-%m-%d') sns.set(color_codes=True) df = pd.DataFrame({ 'date': pd.to_datetime(date_l1500), 'datenum': dates.date2num(date_l1500), 'T': T_l1500, 'S': S_l1500}) fig, ax = plt.subplots() sns.regplot(x="datenum", y="T", color='purple', data=df, ax=ax) # here's the magic: ax.xaxis.set_major_formatter(fake_dates) # legible labels ax.tick_params(labelrotation=30) fig.savefig('stacko_l1500_reglineaireT-f(S).png') #+END_SRC [[file:./stacko_l1500_reglineaireT-f(S).png]] #+RESULTS: : None #+BEGIN_SRC python :session np.array(S_l1500).reshape(1, -1)[:9] #+END_SRC #+RESULTS: | 1759 | 1843 | 1511 | ... | 1503 | 1515 | 1875 | #+BEGIN_SRC python :session :results replace :exports both from sklearn.linear_model import LinearRegression from sklearn.metrics import mean_squared_error S_tt = [[value] for value in S_l1500] my_s = np.array(S_tt) my_t = np.array(T_l1500) #my_s = np.array([[1], [2], [3]]) lmodel = LinearRegression() lmodel.fit(my_s, my_t) f"Les coeff sont L = {lmodel.intercept_} et C = { 1 / lmodel.coef_}" #+END_SRC #+RESULTS: : Les coeff sont L = 113.19744441078485 et C = [9479.50730539] *** Cas supérieur à la MTU #+BEGIN_SRC python :session :results replace import pandas as pd import matplotlib.pyplot as plt from matplotlib import dates import numpy as np from scipy import stats import seaborn as sns import statsmodels.api as sm from sklearn import linear_model @plt.FuncFormatter def fake_dates(x, pos): """ Custom formater to turn floats into e.g., 2016-05-08""" return dates.num2date(x).strftime('%Y-%m-%d') sns.set(color_codes=True) df = pd.DataFrame({ 'date': pd.to_datetime(date_g1500), 'datenum': dates.date2num(date_g1500), 'T': T_g1500, 'S': S_g1500}) fig, ax = plt.subplots() sns.regplot(x="datenum", y="T", color='purple', data=df, ax=ax) # here's the magic: ax.xaxis.set_major_formatter(fake_dates) # legible labels ax.tick_params(labelrotation=30) fig.savefig('stacko_g1500_reglineaireT-f(S).png') #+END_SRC [[file:./stacko_g1500_reglineaireT-f(S).png]] #+RESULTS: : None #+BEGIN_SRC python :session :results replace :exports both from sklearn.linear_model import LinearRegression from sklearn.metrics import mean_squared_error S_tt = [[value] for value in S_g1500] my_s = np.array(S_tt) my_t = np.array(T_g1500) #my_s = np.array([[1], [2], [3]]) lmodel = LinearRegression() lmodel.fit(my_s, my_t) f"Les coeff sont L = {lmodel.intercept_} et C = { 1 / lmodel.coef_}" #+END_SRC #+RESULTS: : Les coeff sont L = 120.04921279789215 et C = [-555.38712112] Etonnant pour C négatif alors que l'analyse graphique montre une pente positivew