#+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[utf8]{inputenc} #+LATEX_HEADER: \usepackage[T1]{fontenc} #+LATEX_HEADER: \usepackage[a4paper,margin=.8in]{geometry} #+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 R :results output :session *R* :exports both data = read.csv("shuttle.csv",header=T) data original_data = data #+end_src #+RESULTS: #+begin_example Date Count Temperature Pressure Malfunction 1 4/12/81 6 66 50 0 2 11/12/81 6 70 50 1 3 3/22/82 6 69 50 0 4 11/11/82 6 68 50 0 5 4/04/83 6 67 50 0 6 6/18/82 6 72 50 0 7 8/30/83 6 73 100 0 8 11/28/83 6 70 100 0 9 2/03/84 6 57 200 1 10 4/06/84 6 63 200 1 11 8/30/84 6 70 200 1 12 10/05/84 6 78 200 0 13 11/08/84 6 67 200 0 14 1/24/85 6 53 200 2 15 4/12/85 6 67 200 0 16 4/29/85 6 75 200 0 17 6/17/85 6 70 200 0 18 7/29/85 6 81 200 0 19 8/27/85 6 76 200 0 20 10/03/85 6 79 200 0 21 10/30/85 6 75 200 2 22 11/26/85 6 76 200 0 23 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 Les vols où aucun incident n'est relevé n'apportant aucune information sur l'influence de la température ou de la pression sur les dysfonctionnements, nous nous concentrons sur les expériences où au moins un joint a été défectueux. #+begin_src R :results output :session *R* :exports both data = data[data$Malfunction>0,] data #+end_src #+RESULTS: : : Date Count Temperature Pressure Malfunction : 2 11/12/81 6 70 50 1 : 9 2/03/84 6 57 200 1 : 10 4/06/84 6 63 200 1 : 11 8/30/84 6 70 200 1 : 14 1/24/85 6 53 200 2 : 21 10/30/85 6 75 200 2 : 23 1/12/86 6 58 200 1 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. Comment la fréquence d'échecs varie-t-elle avec la température ? #+begin_src R :results output graphics :file "freq_temp.png" :exports both :width 600 :height 400 :session *R* plot(data=data, Malfunction/Count ~ Temperature, ylim=c(0,1)) #+end_src #+RESULTS: À 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. ** Admettons qu'en fait les tests sans défaut de joint soient importants Comment les représenterait-on alors ? #+begin_src R :results output graphics :file (org-babel-temp-file "figure" ".png") :exports both :width 600 :height 400 :session *R* plot(data=original_data, Malfunction/Count ~ Temperature, ylim=c(0, 1)) #+end_src #+RESULTS: Toutes les observations en dessous de 66°F ont rencontré au moins une défaillance de joint torique. Ce n'est probablement pas une information à négliger ! ** Et si la pression avait un rôle ? #+begin_src R :results output graphics :file (org-babel-temp-file "figure" ".png") :exports both :width 600 :height 400 :session *R* plot(data=original_data, Malfunction/Count ~ Pressure, ylim=c(0, 1)) #+end_src #+RESULTS: Une fois encore, nous avons très peu de données, mais il ne semble rien y avoir à en tirer. * 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. > Les joints peuvent défaillir en même temps s'ils sont le produit d'une même série de production, ce qui limite le réalisme de l'hypothèse d'indépendance des probabilités de défaut d'un joint. #+begin_src R :results output :session *R* :exports both logistic_reg = glm(data=data, Malfunction/Count ~ Temperature, weights=Count, family=binomial(link='logit')) summary(logistic_reg) #+end_src #+RESULTS: #+begin_example Call: glm(formula = Malfunction/Count ~ Temperature, family = binomial(link = "logit"), data = data, weights = Count) Deviance Residuals: 2 9 10 11 14 21 23 -0.3015 -0.2836 -0.2919 -0.3015 0.6891 0.6560 -0.2850 Coefficients: Estimate Std. Error z value Pr(>|z|) (Intercept) -1.389528 3.195752 -0.435 0.664 Temperature 0.001416 0.049773 0.028 0.977 (Dispersion parameter for binomial family taken to be 1) Null deviance: 1.3347 on 6 degrees of freedom Residual deviance: 1.3339 on 5 degrees of freedom AIC: 18.894 Number of Fisher Scoring iterations: 4 #+end_example L'estimateur le plus probable du paramètre de température est 0.001416 et l'erreur standard de cet estimateur est de 0.049, autrement dit on ne peut pas distinguer d'impact particulier et il faut prendre nos estimations avec des pincettes. ** Refaisons l'analyse avec toutes les données De même que dans la section précédente, prenons en compte les événements sans défaut de joint. #+begin_src R :results output :session *R* :exports both logistic_reg_full = glm(data=original_data, Malfunction/Count ~ Temperature, weights=Count, family=binomial(link='logit')) summary(logistic_reg) #+end_src #+RESULTS: #+begin_example Call: glm(formula = Malfunction/Count ~ Temperature, family = binomial(link = "logit"), data = data, weights = Count) Deviance Residuals: 2 9 10 11 14 21 23 -0.3015 -0.2836 -0.2919 -0.3015 0.6891 0.6560 -0.2850 Coefficients: Estimate Std. Error z value Pr(>|z|) (Intercept) -1.389528 3.195752 -0.435 0.664 Temperature 0.001416 0.049773 0.028 0.977 (Dispersion parameter for binomial family taken to be 1) Null deviance: 1.3347 on 6 degrees of freedom Residual deviance: 1.3339 on 5 degrees of freedom AIC: 18.894 Number of Fisher Scoring iterations: 4 #+end_example Cette fois-ci, avec la même erreur standard, on obtient un coefficient bien supérieur, donc une corrélation bien plus forte entre la température et les défaillances. Je ne suis pas cappable d'évaluer la signification de ces résultats, n'ayant pas eu le temps d'étudier la régression logistique. J'admets donc, pour pouvoir continuer, que l'incertitude n'est pas trop élevée. * 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 R :results output graphics :file "proba_estimate.png" :exports both :width 600 :height 400 :session *R* # shuttle=shuttle[shuttle$r!=0,] tempv = seq(from=30, to=90, by = .5) rmv <- predict(logistic_reg,list(Temperature=tempv),type="response") plot(tempv,rmv,type="l",ylim=c(0,1)) points(data=data, Malfunction/Count ~ Temperature) #+end_src #+RESULTS: [[file:proba_estimate.png]] Comme on pouvait s'attendre au vu des données initiales, la température n'a pas d'impact notable sur la probabilité d'échec des joints toriques. Elle sera d'environ 0.2, comme dans les essais précédents où nous il y a eu défaillance d'au moins un joint. Revenons à l'ensemble des données initiales pour estimer la probabilité de défaillance d'un joint: #+begin_src R :results output :session *R* :exports both data_full = read.csv("shuttle.csv",header=T) sum(data_full$Malfunction)/sum(data_full$Count) #+end_src #+RESULTS: : : [1] 0.06521739 Cette probabilité est donc d'environ $p=0.065$, sachant qu'il existe un joint primaire un joint secondaire sur chacune des trois parties du lançeur, la probabilité de défaillance des deux joints d'un lançeur est de $p^2 \approx 0.00425$. La probabilité de défaillance d'un des lançeur est donc de $1-(1-p^2)^3 \approx 1.2%$. Ça serait vraiment pas de chance... Tout est sous contrôle, le décollage peut donc avoir lieu demain comme 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. ** En prenant en compte les situations sans défaillance #+begin_src R :results output graphics :file "proba_estimate_all.png" :exports both :width 600 :height 400 :session *R* # shuttle=shuttle[shuttle$r!=0,] tempv = seq(from=30, to=90, by = .5) rmv <- predict(logistic_reg_full, list(Temperature=tempv), type="response") plot(tempv, rmv, type="l", ylim=c(0, 1)) points(data=data, Malfunction/Count ~ Temperature) #+end_src #+RESULTS: Et maintenant la probabilité de défaillance d'un joint: #+begin_src R :results output :session *R* :exports both rmv[1] #+end_src #+RESULTS: : 1 : 0.834373 The probability is here far too high to consider taking off, admitting that the pressure for the takeoff day was 200 PSI.