diff --git a/module4/exo1_python_fr.org b/module4/exo1_python_fr.org new file mode 100644 index 0000000000000000000000000000000000000000..871d93b4c683572d4ea260e31745cb49d0ec9c28 --- /dev/null +++ b/module4/exo1_python_fr.org @@ -0,0 +1,219 @@ +#+TITLE: Analyse du risque de défaillance des joints toriques de la navette Challenger +#+AUTHOR: Arnaud Legrand +#+LANGUAGE: fr + +#+HTML_HEAD: +#+HTML_HEAD: +#+HTML_HEAD: +#+HTML_HEAD: +#+HTML_HEAD: +#+HTML_HEAD: + +#+LATEX_HEADER: \usepackage{a4} +#+LATEX_HEADER: \usepackage[french]{babel} + +# #+PROPERTY: header-args :session :exports both + +Le 27 Janvier 1986, veille du décollage de la navette /Challenger/, eu +lieu une télé-conférence de trois heures entre les ingénieurs de la +Morton Thiokol (constructeur d'un des moteurs) et de la NASA. La +discussion portait principalement sur les conséquences de la +température prévue au moment du décollage de 31°F (juste en dessous de +0°C) sur le succès du vol et en particulier sur la performance des +joints toriques utilisés dans les moteurs. En effet, aucun test +n'avait été effectué à cette température. + +L'étude qui suit reprend donc une partie des analyses effectuées cette +nuit là et dont l'objectif était d'évaluer l'influence potentielle de +la température et de la pression à laquelle sont soumis les joints +toriques sur leur probabilité de dysfonctionnement. Pour cela, nous +disposons des résultats des expériences réalisées par les ingénieurs +de la NASA durant les 6 années précédant le lancement de la navette +Challenger. + +* Chargement des données +Nous commençons donc par charger ces données: +#+begin_src python :results value :session *python* :exports both +import numpy as np +import pandas as pd +data = pd.read_csv("shuttle.csv") +data +#+end_src + +#+RESULTS: +#+begin_example + Date Count Temperature Pressure Malfunction +0 4/12/81 6 66 50 0 +1 11/12/81 6 70 50 1 +2 3/22/82 6 69 50 0 +3 11/11/82 6 68 50 0 +4 4/04/83 6 67 50 0 +5 6/18/82 6 72 50 0 +6 8/30/83 6 73 100 0 +7 11/28/83 6 70 100 0 +8 2/03/84 6 57 200 1 +9 4/06/84 6 63 200 1 +10 8/30/84 6 70 200 1 +11 10/05/84 6 78 200 0 +12 11/08/84 6 67 200 0 +13 1/24/85 6 53 200 2 +14 4/12/85 6 67 200 0 +15 4/29/85 6 75 200 0 +16 6/17/85 6 70 200 0 +17 7/29/85 6 81 200 0 +18 8/27/85 6 76 200 0 +19 10/03/85 6 79 200 0 +20 10/30/85 6 75 200 2 +21 11/26/85 6 76 200 0 +22 1/12/86 6 58 200 1 +#+end_example + +Le jeu de données nous indique la date de l'essai, le nombre de joints +toriques mesurés (il y en a 6 sur le lançeur principal), la +température (en Fahrenheit) et la pression (en psi), et enfin le +nombre de dysfonctionnements relevés. + +* Inspection graphique des données +Très bien, nous avons une variabilité de température importante mais +la pression est quasiment toujours égale à 200, ce qui devrait +simplifier l'analyse. +#+begin_src python :results value :session *python* :exports both +data['Pressure'].value_counts() +#+end_src + +#+RESULTS: +: 200 15 +: 50 6 +: 100 2 +: Name: Pressure, dtype: int64 + +Comment la fréquence d'échecs varie-t-elle avec la température ? +#+begin_src python :results output file :var matplot_lib_filename="freq_temp_python.png" :exports both :session *python* +import matplotlib.pyplot as plt + +plt.clf() +data["Frequency"]=data.Malfunction/data.Count +data.plot(x="Temperature",y="Frequency",kind="scatter",ylim=[0,1]) +plt.grid(True) + +plt.savefig(matplot_lib_filename) +print(matplot_lib_filename) +#+end_src + +#+RESULTS: +[[file:*c* argument looks like a single numeric RGB or RGBA sequence, which should be avoided as value-mapping will have precedence in case its length matches with *x* & *y*. Please use the *color* keyword-argument or provide a 2-D array with a single row if you intend to specify the same RGB or RGBA value for all points. +freq_temp_python.png]] +freq_temp_python.png]] +freq_temp_python.png]] + +À première vue, ce n'est pas flagrant mais bon, essayons quand même +d'estimer l'impact de la température $t$ sur la probabilité de +dysfonctionnements d'un joint. + +* Estimation de l'influence de la température + +Supposons que chacun des 6 joints toriques est endommagé avec la même +probabilité et indépendamment des autres et que cette probabilité ne +dépend que de la température. Si on note $p(t)$ cette probabilité, le +nombre de joints $D$ dysfonctionnant lorsque l'on effectue le vol à +température $t$ suit une loi binomiale de paramètre $n=6$ et +$p=p(t)$. Pour relier $p(t)$ à $t$, on va donc effectuer une +régression logistique. + +#+begin_src python :results output :session *python* :exports both +import statsmodels.api as sm + +data["Success"]=data.Count-data.Malfunction +data["Intercept"]=1 + + +# logit_model=sm.Logit(data["Frequency"],data[["Intercept","Temperature"]]).fit() +logmodel=sm.GLM( + data['Frequency'], + data[['Intercept','Temperature']], + family=sm.families.Binomial(), + var_weights=data['Count']).fit() + +print(logmodel.summary()) +#+end_src + +#+RESULTS: +#+begin_example +Generalized Linear Model Regression Results +============================================================================== +Dep. Variable: Frequency No. Observations: 23 +Model: GLM Df Residuals: 21 +Model Family: Binomial Df Model: 1 +Link Function: logit Scale: 1.0000 +Method: IRLS Log-Likelihood: -23.526 +Date: Thu, 04 Mar 2021 Deviance: 18.086 +Time: 15:53:18 Pearson chi2: 30.0 +No. Iterations: 6 +Covariance Type: nonrobust +=============================================================================== + coef std err z P>|z| [0.025 0.975] +------------------------------------------------------------------------------- +Intercept 5.0850 3.052 1.666 0.096 -0.898 11.068 +Temperature -0.1156 0.047 -2.458 0.014 -0.208 -0.023 +=============================================================================== +#+end_example + + +L'estimateur le plus probable du paramètre de température est -0.1156 +et l'erreur standard de cet estimateur est de 0.115 + +* Estimation de la probabilité de dysfonctionnant des joints toriques +La température prévue le jour du décollage est de 31°F. Essayons +d'estimer la probabilité de dysfonctionnement des joints toriques à +cette température à partir du modèle que nous venons de construire: + +#+begin_src python :results output file :var matplot_lib_filename="proba_estimate_python.png" :exports both :session *python* +import matplotlib.pyplot as plt + +data_pred = pd.DataFrame({'Temperature': np.linspace(start=30, stop=90, num=121), 'Intercept': 1}) +data_pred['Frequency'] = logmodel.predict(data_pred[['Intercept','Temperature']]) +data_pred.plot(x="Temperature",y="Frequency",kind="line",ylim=[0,1]) +plt.scatter(x=data["Temperature"],y=data["Frequency"]) +plt.grid(True) + +plt.savefig(matplot_lib_filename) +print(matplot_lib_filename) +#+end_src + +#+RESULTS: +[[file:proba_estimate_python.png]] + +On voit donc que la température semble avoir un impact direct sur la probabilité d'échec des +joints toriques. Utilisons ce modèle pour estimer la probabilité de défaillance des joints toriques dans les conditions du jour J: + +#+begin_src python :results output file :var matplot_lib_filename="prediction_with_ci.png" :session *python* :exports both +import seaborn as sns +#data = data.append([{'Temperature': t} for t in np.linspace(start=30, stop=90, num=121)], ignore_index=True) +fig = plt.figure() +ax = fig.add_subplot(111) +sns.set(color_codes=True) +ax.set_xlim(30,90) +ax.set_ylim(0,1) +sns.regplot(x='Temperature', y='Frequency', data=data, logistic=True, ax=ax) +plt.savefig(matplot_lib_filename) +print(matplot_lib_filename) +#+end_src + +#+RESULTS: +[[file:prediction_with_ci.png]] + + + +Cette probabilité est donc d'environ $p=1$, le décollage ne doit donc pas avoir +lieu demain comme il était prévu. + +Seulement, le lendemain, la navette Challenger explosera et emportera +avec elle ses sept membres d'équipages. L'opinion publique est +fortement touchée et lors de l'enquête qui suivra, la fiabilité des +joints toriques sera directement mise en cause. Au delà des problèmes +de communication interne à la NASA qui sont pour beaucoup dans ce +fiasco, l'analyse précédente comporte (au moins) un petit +problème... Saurez-vous le trouver ? Vous êtes libre de modifier cette +analyse et de regarder ce jeu de données sous tous les angles afin +d'expliquer ce qui ne va pas. + diff --git a/module4/freq_temp_python.png b/module4/freq_temp_python.png new file mode 100644 index 0000000000000000000000000000000000000000..f76fd7319c51be2a91eb4c685fc0f9865775a589 Binary files /dev/null and b/module4/freq_temp_python.png differ diff --git a/module4/prediction_with_ci.png b/module4/prediction_with_ci.png new file mode 100644 index 0000000000000000000000000000000000000000..c95749deefe627ffd6505e0a6411976ce654c9e2 Binary files /dev/null and b/module4/prediction_with_ci.png differ diff --git a/module4/proba_estimate_python.png b/module4/proba_estimate_python.png new file mode 100644 index 0000000000000000000000000000000000000000..e85df2d8bb30552d580b0dcd8f4824d4f2ab33a5 Binary files /dev/null and b/module4/proba_estimate_python.png differ diff --git a/module4/shuttle.csv b/module4/shuttle.csv new file mode 100644 index 0000000000000000000000000000000000000000..e59e1337ed61fc3862edb87cb94bb3a93c1bf583 --- /dev/null +++ b/module4/shuttle.csv @@ -0,0 +1,24 @@ +Date,Count,Temperature,Pressure,Malfunction +4/12/81,6,66,50,0 +11/12/81,6,70,50,1 +3/22/82,6,69,50,0 +11/11/82,6,68,50,0 +4/04/83,6,67,50,0 +6/18/82,6,72,50,0 +8/30/83,6,73,100,0 +11/28/83,6,70,100,0 +2/03/84,6,57,200,1 +4/06/84,6,63,200,1 +8/30/84,6,70,200,1 +10/05/84,6,78,200,0 +11/08/84,6,67,200,0 +1/24/85,6,53,200,2 +4/12/85,6,67,200,0 +4/29/85,6,75,200,0 +6/17/85,6,70,200,0 +7/29/85,6,81,200,0 +8/27/85,6,76,200,0 +10/03/85,6,79,200,0 +10/30/85,6,75,200,2 +11/26/85,6,76,200,0 +1/12/86,6,58,200,1