From c39bad5f7ae2004d63d1349de5827762bf6ad0fd Mon Sep 17 00:00:00 2001 From: 9a02f6b2244ebbd6e980567a3f35fb05 <9a02f6b2244ebbd6e980567a3f35fb05@app-learninglab.inria.fr> Date: Fri, 3 Apr 2020 13:34:52 +0000 Subject: [PATCH] Upload New File --- ...esures_asym\303\251triques__sujet_4_.html" | 18332 ++++++++++++++++ 1 file changed, 18332 insertions(+) create mode 100644 "module3/exo3/Estimation_de_la_latence_et_de_la_capacit\303\251_d_une_connexion_\303\240_partir_de_mesures_asym\303\251triques__sujet_4_.html" diff --git "a/module3/exo3/Estimation_de_la_latence_et_de_la_capacit\303\251_d_une_connexion_\303\240_partir_de_mesures_asym\303\251triques__sujet_4_.html" "b/module3/exo3/Estimation_de_la_latence_et_de_la_capacit\303\251_d_une_connexion_\303\240_partir_de_mesures_asym\303\251triques__sujet_4_.html" new file mode 100644 index 0000000..326d70e --- /dev/null +++ "b/module3/exo3/Estimation_de_la_latence_et_de_la_capacit\303\251_d_une_connexion_\303\240_partir_de_mesures_asym\303\251triques__sujet_4_.html" @@ -0,0 +1,18332 @@ + + +
+ +Nous cherchons dans cette étude à décrire la performance d'une connexion de réseau.
+Nous commençons par importer les packages basiques.
+ +%matplotlib inline
+import matplotlib.pyplot as plt
+import pandas as pd
+import numpy as np
+
Le jeu de données examine une connexion courte à l'intérieur d'un campus. Il est disponible avec l'URL suivante :
+ +data_url = "http://mescal.imag.fr/membres/arnaud.legrand/teaching/2014/RICM4_EP_ping/liglab2.log.gz"
+
Une ligne est de la forme suivante : +[1421761682.052172] 665 bytes from lig-publig.imag.fr (129.88.11.7): icmp_seq=1 ttl=60 time=22.5 ms
+La date de la mesure exprimée en seconde à compté du 1er janvier 1970 se trouve entre crochet. Puis, nous trouvons la taille du message en octets, suivie par le nom de la machine cible et son adresse IP entre parenthèse. La machine cible est normalement identique pour toutes les lignes à l'intérieur d'un jeu de données. Deux indications, icmp_seq et ttl, sont ensuite fournies mais elles ne nous seront pas utiles. Le temps d'envoi en milliseconde pour un aller-retour se trouve à la fin de la ligne.
+Nous pouvons importer ces données à l'aide de pandas. Nous utilisons l'espace pour délimiter les colonnes. Les colonnes n'ont pas de titre pour le moment.
+ +raw_data = pd.read_table(data_url,sep=' ',header=None)
+raw_data
+
Comme nous pouvons le voir, les colonnes 2, 3, 4, 5, 6, 7 et 9 ne sont pas utiles à notre études. Nous pouvons les laisser car elle n'impacteront pas note étude. Par contre, la ligne 12 nous montre que des données sont manquantes. Nous allons voir combien de lignes a des données manquantes.
+ + np.shape(raw_data[raw_data.isnull().any(axis=1)])[0]
+
377 lignes parmis les 44413 n'ont pas de données. Nous pouvons les supprimer sans qu'elles n'aient une grande insidence sur l'étude.
+ +data = raw_data.dropna().copy()
+data
+
Nous allons maintenant changer la forme des données. Commençons par les dates où les mesures ont été effectuées (colonne 0). Il faut supprimer les crochets et transformer en nombre décimale.
+ +def convert_time(time):
+ return float(time[1:-1])
+
+data['time_passed'] = [convert_time(time) for time in data[0]]
+
Nous allons maintenant transformer la colonne des tailles des messages en octets (colonne 1) en les changeant en entier.
+ +def convert_message(message):
+ return int(message)
+
+data['size_message'] = [convert_message(message) for message in data[1]]
+
Il nous reste à transformer la colonne des durées d'envoi (colonne 8) en supprimant le "time=" et en modifiant en nombre décimale.
+ +def convert_duration(duration):
+ return float(duration[5:])
+
+data['duration'] = [convert_duration(duration) for duration in data[8]]
+
Nous regardons maintenant comment évolue la durée d'envoi au cours du temps. En effet, la durée d'envoi pourrait évoluer avec le temps par exemple à cause de la dégradation du matériel.
+ +plt.figure(figsize=(12,9))
+plt.plot(data['time_passed'],data['duration'],'+')
+
A première vue, le temps ne semble pas impacter la durée d'envoi. Les zooms à plusieurs endroits renforcent cette opinion. En effet, les durées d'envoi sont généralement inférieures à 3 ms et des pics apparaissent de temps en temps peu importe le temps écoulé.
+ +plt.figure(figsize=(12,9))
+
+plt.subplots_adjust(wspace=0.1, hspace=0.3)
+
+plt.subplot(421)
+plt.plot(data['time_passed'][0:100],data['duration'][0:100],'+')
+
+plt.subplot(422)
+plt.plot(data['time_passed'][5000:5100],data['duration'][5000:5100],'+')
+
+plt.subplot(423)
+plt.plot(data['time_passed'][10000:10100],data['duration'][10000:10100],'+')
+
+plt.subplot(424)
+plt.plot(data['time_passed'][15000:15100],data['duration'][15000:15100],'+')
+
+plt.subplot(425)
+plt.plot(data['time_passed'][20000:20100],data['duration'][20000:20100],'+')
+
+plt.subplot(426)
+plt.plot(data['time_passed'][25000:25100],data['duration'][25000:25100],'+')
+
+plt.subplot(427)
+plt.plot(data['time_passed'][30000:30100],data['duration'][30000:30100],'+')
+
+plt.subplot(428)
+plt.plot(data['time_passed'][35000:35100],data['duration'][35000:35100],'+')
+
+plt.show()
+
Regardons l'évolution seulement entre 1 et 3. Pour se rendre compte qu'il n'y a pas de lieu entre durée d'envoi et date d'acquisition.
+ +plt.figure(figsize=(12,9))
+plt.plot(data['time_passed'],data['duration'],'+')
+plt.ylim(1,3)
+
Nous allons maintenant voir si la taille du message à une importance sur la durée d'envoi.
+ +plt.figure(figsize=(12,9))
+plt.plot(data['size_message'],data['duration'],'+')
+
A première vue, il semble y avoir un seuil sur la taille des messages à partir duquel les durées sont plus importes. Les deux données semblent liées. Estimons graphiquement ce seuil en zoomant sur la zone en question.
+ +plt.figure(figsize=(12,9))
+plt.plot(data['size_message'],data['duration'],'+')
+plt.axis([1450,1500,0,100])
+
Sur le graphique, nous voyons que le seuil est situé entre 1480 et 1481 octets.
+ +Nous allons évaluer ces deux zones séparément. Il faut donc commencer par séparer les données en deux groupes.
+ +data_low=data[data['size_message']<=1480]
+data_high=data[data['size_message']>=1481]
+
Nous allons maintenant effectué une régression. Pour savoir le type de régression, nous regardons l'évolution de la durée d'envoi par rapport à la taille du message entre 1 et 3, dans la partie où nous avons le plus de données.
+ +plt.figure(figsize=(12,9))
+plt.plot(data['size_message'],data['duration'],'+')
+plt.ylim(1,3)
+
Nous nous rendons compte que le plus adapté est une régression linéaire.
+ +from sklearn.linear_model import LinearRegression
+
+modele_low=LinearRegression()
+modele_low.fit(data_low['size_message'].values.reshape(-1, 1),data_low['duration'])
+
+modele_high=LinearRegression()
+modele_high.fit(data_high['size_message'].values.reshape(-1, 1),data_high['duration'])
+
Si nous calculons le R² score, nous obtenons ceci :
+ +print(modele_low.score(data_low['size_message'].values.reshape(-1, 1),data_low['duration']))
+
+print(modele_high.score(data_high['size_message'].values.reshape(-1, 1),data_high['duration']))
+
Les modèles sont très mauvais. Deux idées nous viennent en tête : ne conserver que les durées d'envoi faibles (là où nous avons le plus de données) ou faire la moyenne des durées d'envoi pour chaque taille de messages.
+Commençons par le cas de la moyenne. Nous commençons par créer les durées d'envoi moyennes pour chaque taille de message.
+ +size_low=list(set(data_low['size_message']))
+
+duration_low=np.empty(len(size_low))
+for k in range(len(size_low)) :
+ duration_low[k]=np.mean(data_low['duration'][data_low['size_message']==size_low[k]])
+
+size_high=list(set(data_high['size_message']))
+
+duration_high=np.empty(len(size_high))
+for k in range(len(size_high)) :
+ duration_high[k]=np.mean(data_high['duration'][data_high['size_message']==size_high[k]])
+
Effectuons de nouveau les modèles linéaires.
+ +modele_low_mean=LinearRegression()
+modele_low_mean.fit(np.reshape(size_low,(-1, 1)),duration_low)
+
+modele_high_mean=LinearRegression()
+modele_high_mean.fit(np.reshape(size_high,(-1, 1)),duration_high)
+
+print(modele_low_mean.score(np.reshape(size_low,(-1, 1)),duration_low))
+print(modele_high_mean.score(np.reshape(size_high,(-1, 1)),duration_high))
+
Les résultats se sont améliorés mais ne sont toujours pas bons.
+Nous allons maintenant essayer de supprimer les durées d'envoi trop élevées. Nous supprimons les durées inférieurs à 2 pour les messages inférieurs à 1480 octets et inférieurs à 3 pour les messages supérieurs à 1481 octets.
+ +data_low_reduced=data_low[data_low['duration']<=2]
+data_high_reduced=data_high[data_high['duration']<=2.6]
+
Regardons combien de données ont été supprimées.
+ +print(len(data_low_reduced)/len(data_low))
+print(len(data_high_reduced)/len(data_high))
+
Nous avons perdu plus de 15% des données. Notre modèle sera surement mieux adapté aux données réduites mais il ne prendra pas en compte une grande partie des données donc sera moins fiable sur les données complètes.
+ +modele_low_reduced=LinearRegression()
+modele_low_reduced.fit(data_low_reduced['size_message'].values.reshape(-1, 1),data_low_reduced['duration'])
+
+modele_high_reduced=LinearRegression()
+modele_high_reduced.fit(data_high_reduced['size_message'].values.reshape(-1, 1),data_high_reduced['duration'])
+
+print(modele_low_reduced.score(data_low_reduced['size_message'].values.reshape(-1, 1),data_low_reduced['duration']))
+print(modele_high_reduced.score(data_high_reduced['size_message'].values.reshape(-1, 1),data_high_reduced['duration']))
+
Le modèle dans ce cas n'est pas mauvais. Mais comment se comporte-t-il si nous revenons à la totalité des données ?
+ +print(modele_low_reduced.score(data_low['size_message'].values.reshape(-1, 1),data_low['duration']))
+print(modele_high_reduced.score(data_high['size_message'].values.reshape(-1, 1),data_high['duration']))
+
Lorsque nous utilisons toutes les données, ce modèle est inutile.
+ +Nous allons maintenant déterminer la latence et la capacité pour les trois modèles (complet, moyenne et réduit). Nous avons la relation T=L+S/C où T est la durée, L la latence, S la taille du message et C la capacité. Ayant nos données en millisecondes et octet. La latence s'exprimera en millisecondes et la capacité en octet par millisecondes.
+Commençons par le cas du modèle complet.
+ +print(modele_low.intercept_)
+print(1/modele_low.coef_[0])
+
+print(modele_high.intercept_)
+print(1/modele_high.coef_[0])
+
Nous avons une latence de 3.276 millisecondes et une capacité de 3065 octets par millisecondes pour les petits messages et une latence de 5.290 millisecondes et une capacité de 388 octets par millisecondes pour les gros messages.
+Etudions le cas du modèle avec les moyennes.
+ +print(modele_low_mean.intercept_)
+print(1/modele_low_mean.coef_[0])
+
+print(modele_high_mean.intercept_)
+print(1/modele_high_mean.coef_[0])
+
Nous avons une latence de 3.275 millisecondes et une capacité de 2996 octets par millisecondes pour les petits messages et une latence de 5.667 millisecondes et une capacité de 424 octets par millisecondes pour les gros messages.
+Regardons maintenant le cas avec le modèle réduit.
+ +print(modele_low_reduced.intercept_)
+print(1/modele_low_reduced.coef_[0])
+
+print(modele_high_reduced.intercept_)
+print(1/modele_high_reduced.coef_[0])
+
Nous avons une latence de 1.147 millisecondes et une capacité de 4125 octets par millisecondes pour les petits messages et une latence de 1.901 millisecondes et une capacité de 4371 octets par millisecondes pour les gros messages.
+Traçons maintenant les trois régressions avec les données expérimentales. La courbe rouge correspond au modèle complet, la verte au modèle moyen et la noir au modèle réduit.
+ +plt.figure(figsize=(12,9))
+plt.plot(data['size_message'],data['duration'],'b+',alpha=0.1)
+plt.plot(size_low,modele_low.predict(np.reshape(size_low,(-1, 1))),'r')
+plt.plot(size_high,modele_high.predict(np.reshape(size_high,(-1, 1))),'r')
+plt.plot(size_low,modele_low_mean.predict(np.reshape(size_low,(-1, 1))),'g')
+plt.plot(size_high,modele_high_mean.predict(np.reshape(size_high,(-1, 1))),'g')
+plt.plot(size_low,modele_low_reduced.predict(np.reshape(size_low,(-1, 1))),'k')
+plt.plot(size_high,modele_high_reduced.predict(np.reshape(size_high,(-1, 1))),'k')
+
Effectuons un léger zoom, un zoom plus conséquent et un zoom très important.
+ +plt.figure(figsize=(12,9))
+plt.plot(data['size_message'],data['duration'],'b+',alpha=0.2)
+plt.plot(size_low,modele_low.predict(np.reshape(size_low,(-1, 1))),'r')
+plt.plot(size_high,modele_high.predict(np.reshape(size_high,(-1, 1))),'r')
+plt.plot(size_low,modele_low_mean.predict(np.reshape(size_low,(-1, 1))),'g')
+plt.plot(size_high,modele_high_mean.predict(np.reshape(size_high,(-1, 1))),'g')
+plt.plot(size_low,modele_low_reduced.predict(np.reshape(size_low,(-1, 1))),'k')
+plt.plot(size_high,modele_high_reduced.predict(np.reshape(size_high,(-1, 1))),'k')
+plt.ylim(0,90)
+plt.show()
+plt.figure(figsize=(12,9))
+plt.plot(data['size_message'],data['duration'],'b+',alpha=0.2)
+plt.plot(size_low,modele_low.predict(np.reshape(size_low,(-1, 1))),'r')
+plt.plot(size_high,modele_high.predict(np.reshape(size_high,(-1, 1))),'r')
+plt.plot(size_low,modele_low_mean.predict(np.reshape(size_low,(-1, 1))),'g')
+plt.plot(size_high,modele_high_mean.predict(np.reshape(size_high,(-1, 1))),'g')
+plt.plot(size_low,modele_low_reduced.predict(np.reshape(size_low,(-1, 1))),'k')
+plt.plot(size_high,modele_high_reduced.predict(np.reshape(size_high,(-1, 1))),'k')
+plt.ylim(0,15)
+plt.show()
+plt.figure(figsize=(12,9))
+plt.plot(data['size_message'],data['duration'],'b+',alpha=0.2)
+plt.plot(size_low,modele_low.predict(np.reshape(size_low,(-1, 1))),'r')
+plt.plot(size_high,modele_high.predict(np.reshape(size_high,(-1, 1))),'r')
+plt.plot(size_low,modele_low_mean.predict(np.reshape(size_low,(-1, 1))),'g')
+plt.plot(size_high,modele_high_mean.predict(np.reshape(size_high,(-1, 1))),'g')
+plt.plot(size_low,modele_low_reduced.predict(np.reshape(size_low,(-1, 1))),'k')
+plt.plot(size_high,modele_high_reduced.predict(np.reshape(size_high,(-1, 1))),'k')
+plt.ylim(1,3)
+plt.show()
+
Le modèle complet et le modèle par moyenne sont très proches. Comme le montre le dernier graphique, le modèle réduit convient très bien au faible durée d'envoi.
+Le modèle réduit est de mon point de vue plus intéressant pour déterminer la latence et la capacité car il est moins sensible au bruit. Il sera ainsi plus simple de comparer la latence et la capacité entre deux connexions de réseaux. Néanmoins, ce modèle n'est pas bon pour prédire la durée d'envoi à partir de nouvelle information. Les deux autres modèles auront en moyenne même d'erreur.
+ +Nous allons effectuer le même travail avec un second jeu de données :
+ +data_url = 'http://mescal.imag.fr/membres/arnaud.legrand/teaching/2014/RICM4_EP_ping/stackoverflow.log.gz'
+raw_data = pd.read_table(data_url,sep=' ',header=None)
+raw_data
+
Nous regardons si des lignes sont manquantes. Puis nous les supprimons, comme leur nombre est faible.
+ +np.shape(raw_data[raw_data.isnull().any(axis=1)])[0]
+data = raw_data.dropna().copy()
+data
+
Nous changeons maintenant la forme des données utiles.
+ +def convert_time(time):
+ return float(time[1:-1])
+
+def convert_message(message):
+ return int(message)
+
+def convert_duration(duration):
+ return float(duration[5:])
+
+data['time_passed'] = [convert_time(time) for time in data[0]]
+data['size_message'] = [convert_message(message) for message in data[1]]
+data['duration'] = [convert_duration(duration) for duration in data[8]]
+
Nous allons vérifier que le temps n'a pas d'influence sur la durée d'envoi.
+ +plt.figure(figsize=(12,9))
+plt.plot(data['time_passed'],data['duration'],'+')
+
plt.figure(figsize=(12,9))
+
+plt.subplots_adjust(wspace=0.1, hspace=0.3)
+
+plt.subplot(321)
+plt.plot(data['time_passed'][0:100],data['duration'][0:100],'+')
+
+plt.subplot(322)
+plt.plot(data['time_passed'][1000:1100],data['duration'][1000:1100],'+')
+
+plt.subplot(323)
+plt.plot(data['time_passed'][2000:2100],data['duration'][2000:2100],'+')
+
+plt.subplot(324)
+plt.plot(data['time_passed'][3000:3100],data['duration'][3000:3100],'+')
+
+plt.subplot(325)
+plt.plot(data['time_passed'][4000:4100],data['duration'][4000:4100],'+')
+
+plt.subplot(326)
+plt.plot(data['time_passed'][5000:5100],data['duration'][5000:5100],'+')
+
+plt.show()
+
Comme pour le premier jeu de données, il ne semble pas y avoir de lien entre le temps et la durée d'envoi.
+Nous allons maintenant regarder l'évolution de la durée d'envoi en fonction de la taille du message.
+ +plt.figure(figsize=(12,9))
+plt.plot(data['size_message'],data['duration'],'+')
+
Nous allons supposer ici qu'il n'y a pas de seuil, contrairement au premier jeu de données.
+Nous pouvons effectuer une régression linéaire comme dans le cas précédent.
+ +modele=LinearRegression()
+modele.fit(data['size_message'].values.reshape(-1, 1),data['duration'])
+
+print(modele.score(data['size_message'].values.reshape(-1, 1),data['duration']))
+
Nous allons essayer le modèle réduit comme dans le premier cas. Le modèle moyen donnant des résultats similaires nous n'allons pas le faire pour ce jeu de données. Pour cela, nous ne conservons que les durées d'envoi inférieures ou égales à 113 ms.
+ +data_reduced=data[data['duration']<=113]
+print(len(data_reduced)/len(data))
+
Puis, nous appliquons la régression linéaire.
+ +modele_reduced=LinearRegression()
+modele_reduced.fit(data_reduced['size_message'].values.reshape(-1, 1),data_reduced['duration'])
+
+print(modele_reduced.score(data_reduced['size_message'].values.reshape(-1, 1),data_reduced['duration']))
+print(modele_reduced.score(data['size_message'].values.reshape(-1, 1),data['duration']))
+
Nous obtenons des résultats similaires à ceux obtenus avec le premier jeu de données.
+Nous pouvons maintenant déterminer la latence et la capacité pour les deux modèles.
+ +print(modele.intercept_)
+print(1/modele.coef_[0])
+print()
+print(modele_reduced.intercept_)
+print(1/modele_reduced.coef_[0])
+
Les latences sont assez similaires. Par contre, les capacités sont très différentes.
+Traçons maintenant les trois régressions linéaires avec le jeu de données.
+ +size=np.arange(0,2000)
+plt.figure(figsize=(12,9))
+plt.plot(data['size_message'],data['duration'],'b+',alpha=0.1)
+plt.plot(size,modele.predict(np.reshape(size,(-1, 1))),'r')
+plt.plot(size,modele_reduced.predict(np.reshape(size,(-1, 1))),'k')
+
Avec un zoom.
+ +plt.figure(figsize=(12,9))
+plt.plot(data['size_message'],data['duration'],'b+',alpha=0.1)
+plt.plot(size,modele.predict(np.reshape(size,(-1, 1))),'r')
+plt.plot(size,modele_reduced.predict(np.reshape(size,(-1, 1))),'k')
+plt.ylim(110,120)
+
Comme pour le premier jeu de données, il me semble que le modèle réduit est celui qui explique le mieux les données bien qu'il ne prenne pas les durées élevées en compte.
+ +
+