<jupyter_start><jupyter_text>Introduction Objectif : - Créer un pipeline de re entrainement et drop du modéle - Créer un pipeline de consommation du modéle Je re import mes scripts crées dans le nb 02 , comme je suis dans un dossier paralélle à ma lib je dois avoir une importation différente.Dans ce note book je ne droperai pas les scripts avec l'outils %% writeline mais je copierai mon code dans des scripts python à la racine ou dans lib avec les modifications nécassire par rapport à l'archi du repo. - PS : il y'a plein de façon de faire ce qui va être fait dans ce notebook, mon idée ici étant de me le créer sur mesure, mais en fonction des choix de déploiement d'un modéle ca necessiterai ajustement- PS2 : Les docstrings seront ajoutées au script python pas ici<jupyter_code>import sys
sys.path.append('..')
import warnings
warnings.simplefilter(action='ignore', category=FutureWarning)
import pandas as pd


import lib
from lib.data_clean import DataClean
from lib.classifier_trainer import ClassifierJob
from lib.plot import roc

from sklearn.ensemble import GradientBoostingClassifier
from sklearn.ensemble import RandomForestClassifier
import xgboost as xgb
from joblib import dump, load
from lib import consume_validation
from lib.data_explore import DataExplore
import datetime

from sklearn import metrics<jupyter_output><empty_output><jupyter_text>Je reprend les solutions du nb 02 :  Custom train pipeline<jupyter_code>class custom_train_pip():
    
    def __init__(self,df_init):
        self.df = df_init
        self.df_clean = None
        self.model_train = None
        self.unique_key = str(datetime.datetime.now()).replace(" ","_").replace(":","_").replace(".","_")
        
    def clean_job(self):
        try:
            cleandata = DataClean(self.df)
            self.df_clean = cleandata.clean_job() ### SET cleandata.clean_job(self.unique_key) if databricks needed
            return self.df_clean
        except Exception as e:
            raise Exception(f"clean failed : {e}")
    
    def retrain_job(self, model_init, test_size=0.2, seed=69, learning_curve_mod=False, normalize=False, 
                    list_col_name_drop=None):
        try:
            cl = ClassifierJob(self.df_clean,model_init)
            if list_col_name_drop != None:
                x_full, y_full = cl.split_features_target(list_col_name_drop)
            else:
                x_full, y_full = cl.split_features_target()
            self.model_train = cl.fit_and_eval(test_size, seed,
                                            learning_curve_mod=learning_curve_mod, normalize=normalize)
            return self.model_train
        except Exception as e:
            raise Exception(f"Train failed : {e}")
    
    def drop_model(self):
        if (self.model_train != None):
            try:
                path = str(f'../Model/clf_model_{self.unique_key}.joblib')
                dump(self.model_train, path)
                return str(f"Model succesfully Create at {self.unique_key}")
            except Exception as e:
                raise Exception(f"Create model failed : {e}")
        else:
            raise Exception(f"Create model failed : self.model_train == None")
## je reprends les données de train de base et je reproduis l'expérience
init_df = pd.read_excel("../data/Données projet LAP Cas-témoin 02-10-20.xlsx")
model_retrain = xgb.XGBClassifier(n_estimators=300, max_depth=2)

## instance de toute la pipeline de rentrainement
train_job = custom_train_pip(init_df)
train_job.clean_job()

list_col_name_drop = ['Sex_M_F_(0_1)', 'Hematies_(T_L)', 'Mono_(G_L)', 'PNE_(%)',
       'Hemoglobine_(g_L)', 'Hematocrite_(%)', 'TCMH_(pg)','IDR-CV_(%)', 'PNN_(%)',
       'PNE_(G_L)', 'PNB_(%)', 'PNB_(G_L)', 'Lymphos_(G_L)',
       'Mono_(%)', 'Blastes_(%)', 'Plq_(G_L)', 'VPM_(fL)',
       'Ret_(G_L)', 'Ratio_TCA_',
       'PDF_(ug_mL)_', 'LDH_(U_L)', 'Calcium_(Ca2+)_(mmol_L)',
       'Phosphore_(mmol_L)', 'Uree_(mmol_L)', 'Creatinine',
       'Acide_urique_(umol_L)', 'Ferritine_(ug_L)', 'CRP_(mg_L)']



## Precision : si normalize=True le joblib contiandra le job de standardscaler, 
## on aura rien à faire pour la consommation du model 
model = train_job.retrain_job(model_retrain,normalize=False,list_col_name_drop=list_col_name_drop)<jupyter_output>Score train : 1.0
-----------
Score test : 0.91
-----------
AUC: 0.96 (std:0.0108), (splits = 5)<jupyter_text>Le bloc ci dessous drop le modéle dans le dossier.Il a un id unique dans son nom (date et heure).<jupyter_code># get_return = train_job.drop_model()
# print(get_return)
# Visualiser ce que contient le modéle qui a été drop

# Example si normalized :
#     Pipeline(steps=[('pipeline',
#                  Pipeline(steps=[('standardscaler', StandardScaler())])),
#                 ('gradientboostingclassifier', GradientBoostingClassifier())])
#  sinon :
#         GradientBoostingClassifier()
        

model<jupyter_output><empty_output><jupyter_text>Observation du Train on retrouve nos éléments de train, on doit rajouter une condition avant le drop du modéle par exemple si on souhaite automatiser le projet - if accuracy > a 0.93 and accuracy_classe_1 >0.88:     // drop jobdans ce projet on a pas stockées ces informations mais si on avait un deploiement cloud on peut, ou alors depuis une bdd dans un env docker ect...  Consommer le modéle<jupyter_code>def iso_id(df,p_number):
    """return df with only data for patient number"""
    df = df[df['Patient_numbers'].isin([p_number])]
    return df


# toutes les data de  validations ensemble
validation_df = pd.read_csv("../data/cohorte_full_data.csv")
validation_df
list_col_name_drop = ["PNE_(%)", "Mono_(G_L)", "Plq_(G_L)", "LDH_(U_L)","Chu"]
# validation_df.head(10)
# validation_df = iso_id(validation_df,42)
dataviz = DataExplore(validation_df)
na_count = dataviz.count_na()
len(na_count)
na_count
id_list = validation_df["Patient_numbers"]
id_list = [str(element) for element in id_list]
## Test pour charger le modèle depuis le joblib
model = load("../Model/clf_model_2021-03-05_15_13_20_270634.joblib") 
databrick = load("../Model/databrick_model_2021-02-21_14_37_04_740893.joblib") 

## Bloc pour excécuter la prédiction, il est en mode notebook, il est plus simple sur le sricpt.
cleandata = DataClean(validation_df)
validation_df = cleandata.prod_clean_job(databrick)
cl = ClassifierJob(validation_df,model)
x_valid, y_valid = cl.split_features_target(list_col_name_drop) #list_col_name_drop

m_val_step = consume_validation.ConsumeModelClf(x_valid,model,validation=True,true_y=y_valid.values)
m_val_step.predict_job()

## retourne la matrice de résultat dans un df et expose la figure explicative
final_df = m_val_step.show_result()
m_val_step.explain()
final_df["Id"] = id_list
final_df
def apply_thresh(df,thres=95):
    if df["Predictions"] == 0.0 :
        if df["Trust%"] <=thres:
            return 1.0
        else:
            return 0.0
    else:
        return 1.0     
final_df['Correction'] = final_df.apply(apply_thresh, axis=1)
final_df
def details_score(final_df, key_analytics='Correction'):
    ac = metrics.accuracy_score(final_df['True_value'].values, final_df[f'{key_analytics}'].values)
    print("Score :",round(ac,2))
    df_cl1 = final_df[final_df['True_value'].isin([1.0])]
    df_cl1 = df_cl1.reset_index()
    ac = metrics.accuracy_score(df_cl1['True_value'].values, df_cl1[f'{key_analytics}'].values)
    print("Score classe 1 :",round(ac,2))
    df_cl0 = final_df[final_df['True_value'].isin([0.0])]
    ac = metrics.accuracy_score(df_cl0['True_value'].values, df_cl0[f'{key_analytics}'].values)
    print("Score classe 0 :",round(ac,2))
    return df_cl1
    
print("Sans Seuil")
print("------")
df_cl1 = details_score(final_df, key_analytics='Predictions')

print("------------------------------")

print("Avec Seuil")
print("------")
df_cl1 = details_score(final_df)
def apply_is_error(df):
    if df["Predictions"] == df["True_value"]:
        return 0
    else:
        return 1
    
final_df['is_error'] = final_df.apply(apply_is_error, axis=1)
error_df = final_df[final_df["is_error"].isin([1])]
error_df = error_df.drop(columns=["is_error"])
error_df<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.12026862026862027, 'fraction_numerical': 0.014896214896214897, 'mean_word_length': 3.855364552459988, 'pattern_counts': {'":': 1, '<': 17, '<?xml version=': 0, '>': 18, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '4', 'dir': 'jupyter-structured-clean-dedup', 'id': '339987', 'license': 'BSD-3-Clause', 'n_tokens_mistral': 2886, 'n_tokens_neox': 2776, 'n_words': 680, 'path': 'Notebook_Prepa_Leukemia/03-Custom_Pipeline_Train+Consume.ipynb', 'repo_name': 'Nico-Facto/Leukemia-Apl-Classification', 'size': '8190'}