Se connecter
Date limite de participation :
1 février 2017

Blowout Prevention Analytics

L’objectif de ce Challenge est de prédire la probabilité de kick au cours des opérations de forage d’un puits.

Classement
1. Nommie KASHANI Score 0,649123
2. Eric TELLIEZ Score 0,543551
3. Yassine IDRISSI RHALBI Score 0,493767
Ce challenge est terminé.

74

contributions

12

participants

terminé
terminé

Le forage est une activité stratégique de la Branche Exploration Production. La construction des puits permet de découvrir, d’évaluer, de développer et in fine de produire des gisements d’hydrocarbures. Au cours des 10 dernières années, les foreurs du Groupe ont ainsi construit plus de 3000 puits répartis sur plus de 30 pays de par le Monde, dans des configurations opérationnelles très variées.

En forage, le Risque Majeur est un événement rare appelé blowout qui consiste en un rejet incontrôlé de fluides issus des terrains traversés vers l’atmosphère, les fonds marins, ou le sous-sol. Aussi un blowout peut-il avoir des conséquences catastrophiques: perte de vies humaines, dommages à l’environnement, pertes matérielles. Comme l’a démontré l’accident de Macondo en 2010, un blowout peut remettre en question l’existence même d’une Major pétrolière. Or en forage, 95% des blowouts sont initiés par un événement précurseur nommé « kick », qui est l’entrée inattendue de fluide de formation à l’intérieur du puits pendant les étapes de sa construction.

Pour évaluer le risque de blowout, l’Industrie s’appuie aujourd’hui sur des estimations génériques qui ne tiennent pas compte des caractéristiques propres à un projet de forage donné. Total cherche à aller plus loin en s’appuyant sur de grandes quantités de données à l’échelle de l’Industrie, et sur les observations de kicks qui y sont consignées.

Prédire la probabilité de kick à partir de l’histoire de notre Industrie, c’est améliorer l’évaluation du risque de blowout, et renforcer encore la Sécurité, valeur fondamentale du Groupe.

L’objectif de ce Challenge est de produire un modèle prédictif permettant de prédire pour chaque nouveau puits le risque que survienne un kick au cours de sa construction, et ce au vu de ses caractéristiques techniques et opérationnelles spécifiques.

2 fichiers de données vous sont remis :

  • Le fichier d’apprentissage à proprement parler (51244 observations + 1 ligne d’en-tête)
  • Le fichier des puits dont on veut prédire les kicks (12811 observations + 1 ligne d’en-tête)

Le fichier d’apprentissage et le fichier des puits ont des structures très proches : ils contiennent les mêmes colonnes à l’exception de la variable cible qui n’est présente que sur le fichier d’apprentissage.

Ils contiennent dans l’ordre :

  • 1 champ identifiant (UniqueID)
  • 20 autres champs d’identification de l’opération réalisée (informatifs) :
    • year : Année au cours de laquelle les opérations de forage du puits se sont terminées.
    • country : Pays dans lequel le puits foré est localisé.
    • group : Dénomination de l'éventuel groupement d'Opérateurs.
    • operator : Nom de l'Opérateur en charge de la conduite des opérations de forage.
    • previous.operator.name : Désignation précédente de l'opérateur.
    • formal.well.name : Nom Officiel du puits.
    • common.well.name : Nom du puits attribué par l'Opérateur.
    • business.unit : Nom de la business Unit (si applicable).
    • region : Zone géographique.
    • sub.region : Sous-Région (applicable à la zone Europe uniquement).
    • ...
  • La variable cible (Target, renseignée uniquement pour l’échantillon d’apprentissage)
  • 117 autres variables potentiellement explicatives et relatives à l’opération (Type de forage, longueur de l’intervalle foré...)

La totalité de la description des données peut être téléchargée ici :

Télécharger la description des données

Le format du fichier à soumettre est :

UniqueID;Target
1;0
2;0
3;0

Il vous est demandé de prédire non pas une probabilité de kick, mais directement une variable binaire indiquant si le puits risque de subir un kick ou non. Dans ce cadre, nous proposons d’évaluer votre modèle sur la base d’une statistique de bon / mauvais classement tenant compte de la similitude de votre classement avec ce qui a effectivement été observé sur les puits tests.

Pour matérialiser une approche conservative propre au thème de la Sécurité, nous avons choisi de dissymétriser les risques de première et de deuxième espèce en pénalisant plus le fait de rater un kick que d’en prédire un à tort.

Pour cela nous vous proposons la métrique suivante : $$ F_{0, 1} = \dfrac{1}{ \dfrac{0.1}{P} + \dfrac{0.9}{R} } $$ Qui est la moyenne harmonique pondérée de la précision \(P\) et du recall \(R\), lesquels sont calculés de la manière suivante : $$ P = \frac{VP}{VP + FP} ; R = \frac{VP}{VP + FN} $$ Où :

  • \(VP\) désigne les Vrais positifs, donc les puits avec kick prédits avec kick
  • \(FP\) désigne les Faux positifs, donc les puits sans kick prédits avec kick
  • \(FN\)  désigne les faux négatifs, donc les puits avec kick prédits sans kick

Le poids 9 fois plus important donné au Recall dans la moyenne harmonique des deux indicateurs traduit l’approche conservative qui maximise le Recall en minimisant les faux négatifs quitte à prendre trop de faux positifs, ie. d’alerter à tort sur un risque de kick.

Afin de vous simplifier le travail, nous vous proposons ci-dessous les codes R et Python permettant de calculer ces métriques (fonctions falpha( ), avec un alpha par défaut à 0.1 comme ici souhaité).

Code R

#' falpha
#' 
#' Fonction qui calcule le score pour un DF
#' 
#' @param DF: DataFrame
#' @param forecast : string
#' @param real : string
#' @param alpha : num 0>=alpha>=1 valeur par défaut = 0.1
#' 
#' @examples 
#' Id <- c(1,2,3,4,5)
#' Real <- c(1,1,1,0,0)
#' Pred <- c(1,0,0,1,0)
#' DF <- data.frame(Id,Pred,Real)
#' falpha(DF,"Pred","Real",0.5)
#' > 0.4
#' 
#' Id <- c(1,2,3,4,5)
#' Real <- c(1,1,1,0,0)
#' Pred <- c(0,0,0,0,0)
#' DFIndicNull <- data.frame(Id,Pred,Real)
#' falpha(DFIndicNull,"Pred","Real")
#' > Error in value[[3L]](cond) : 
#' >  None of the predicted target is set to 1, we can't calculate metric
falpha <- function(DF, forecast, real, alpha = 0.1){
  
  if (is.data.frame(DF)){
    pred_fact <- as.factor(DF[,forecast])
    real_fact <- as.factor(DF[,real])
    TP <- nrow(DF[DF[,real]== 1 & DF[,forecast] == DF[,real],])
    FP <- nrow(DF[DF[,real]== 0 & DF[,forecast]== 1,])
    FN <- nrow(DF[DF[,real]== 1 & DF[,forecast]== 0,])
    pred_fact <- tryCatch({
      relevel(pred_fact, ref = "1")
    },error = function(cond){
      stop("None of the predicted target is set to 1, we can't calculate metric")
    })
    real_fact <- relevel(real_fact, ref = "1")
    P <<- tryCatch({
      TP/(TP+FP)
    },error = function(cond){
      stop("Problem with Precision calculation, we can't calculate metric, please check your prediction")
    })

    R <<- tryCatch({
      TP/(TP+FN)
    },error = function(cond){
      stop("Problem with Recall calculation, we can't calculate metric, please check your prediction")
    })
    
    if ((alpha >= 0) && (alpha <= 1)){
      metric = 1/((alpha/P)+(1-alpha)/R)
      return (metric)
    }
    else{
      stop("Alpha value is not in interval [0,1]")
    }
  }
  else{
    stop("Your DataFrame does not exist")
  }
}

Code Python

import pandas as pd
import numpy as np
from sklearn.metrics import precision_score, recall_score

def falpha(DF, forecast, real, alpha=0.1):
    """
    Fonction qui calcule le score pour un DF
    :param DF: DataFrame
    :param forecast: String
    :param real: String
    :param alpha: Float 0> alpha <1 default set to 0.1
    :return:
    """
    if DF is not None:
        if (alpha >= 0) & (alpha <= 1):

            if 1 in list(DF[forecast]):
                try:
                    P = precision_score(DF[real], DF[forecast])
                except:
                    raise ValueError("Problem with Precision calculation, we can't calculate metric")
                    sys.exit(1)

                try:
                    R = recall_score(DF[real], DF[forecast])
                except:
                    raise ValueError("Problem with Recall calculation, we can't calculate metric")
                    sys.exit(1)

                metric = 1/((alpha/P)+(1-alpha)/R)

                return metric
            else:
                raise ValueError("Your prediction is uniformally 0, we can't calculate metric")

        else:
            raise ValueError("Alpha value is not in range [0,1]")
            sys.exit(1)
    else:
        raise ValueError("Your DataFrame does not exist")
        sys.exit(1)
1. Nommie KASHANI 12 contributions 01/02/17 11:03 Score 0,649123
2. Eric TELLIEZ 7 contributions 01/02/17 10:47 Score 0,543551
3. Yassine IDRISSI RHALBI 4 contributions 01/02/17 10:58 Score 0,493767
4. Arnaud Chanoine 13 contributions 01/02/17 11:05 Score 0,463369
5. Etienne Fayet 8 contributions 01/02/17 11:01 Score 0,259973
6. SEMMAU Denis 4 contributions 01/02/17 10:56 Score 0,211165
7. Aurélien Massiot 7 contributions 01/02/17 10:55 Score 0,183109
8. Antoine AUBINEAU 2 contributions 01/02/17 10:48 Score 0,162891
9. Boualam HASNOUN 1 contribution 01/02/17 11:04 Score 0,055995
10. Pierre Vaningelandt 1 contribution 01/02/17 10:50 Score 0,000000
Discussions
loading... Chargement...