<jupyter_start><jupyter_text>2A.ml - 2016 - Compétition ENSAE - Premiers modèlesUne compétition était proposée dans le cadre du cours *Python pour un Data Scientist* à l'[ENSAE](http://www.ensae.fr/ensae/fr/). Ce notebook facilite la prise en main des données et propose de mettre en oeuvre un modèle logit.<jupyter_code>from jyquickhelper import add_notebook_menu
add_notebook_menu()<jupyter_output><empty_output><jupyter_text>La première étape constiste à mettre en forme les données pour que les fonctions des modules statsmodels et skitlearn fonctionnent comme on le souhaite<jupyter_code>from pyensae.datasource import download_data
download_data("ensae_competition_2016.zip",
              url="https://github.com/sdpython/ensae_teaching_cs/raw/master/_doc/competitions/2016_ENSAE_2A/")
import pandas as pd
import statsmodels.api as sm
import pylab as pl
import numpy as np

fichier_train = "./ensae_competition_train.txt"
fichier_test = "./ensae_competition_test_X.txt"

df = pd.read_csv(fichier_train, header=[0,1], sep="\t", index_col=0)<jupyter_output>c:\python36_x64\lib\site-packages\statsmodels\compat\pandas.py:56: FutureWarning: The pandas.core.datetools module is deprecated and will be removed in a future version. Please use the pandas.tseries module instead.
  from pandas.core import datetools<jupyter_text>Mise en forme des données pour la régression Pour mieux analyser les données présentes dans la base de données, il faut passer par quelques manipulations.Par exemple, il faut transformer les variables SEX, EDUCATION, MARRIAGE en indictatrices afin qu'elles ne soient pas prise en compte comme des variables continues dans le modèle.<jupyter_code>#### Gender dummies
df['X2'] = df['X2'].applymap(str)
gender_dummies = pd.get_dummies(df['X2'] )
### education dummies
df['X3'] = df['X3'].applymap(str)
educ_dummies = pd.get_dummies(df['X3'] )
#### marriage dummies
df['X4'] = df['X4'].applymap(str)
mariage_dummies = pd.get_dummies(df['X4'] )
### On va aussi supprimer les multi index de la table
df.columns = df.columns.droplevel(0)
#### on aggrège ensuite les 3 tables ensemble
data = df.join(gender_dummies).join(educ_dummies).join(mariage_dummies)
data.head(n=2)<jupyter_output><empty_output><jupyter_text>Régression logistique en utilisant statsmodels Pour notre premier modèle, nous allons voir comment fonctionne le module statsmodelsPar défaut, la regression logit n'a pas de beta zéro pour le module statsmodels : il faut donc l'ajouter<jupyter_code># première étape pour ce module, il faut ajouter à la main le beta zéro - l'intercept
data['intercept'] = 1.0
data.rename(columns = {'default payment next month' : "Y"}, inplace = True)
data.columns
# variable = ['AGE', 'BILL_AMT1', 'BILL_AMT2', 'BILL_AMT3', 'BILL_AMT4',
#       'BILL_AMT5', 'BILL_AMT6', 'LIMIT_BAL', 'PAY_0',
#       'PAY_2', 'PAY_3', 'PAY_4', 'PAY_5', 'PAY_6', 'PAY_AMT1', 'PAY_AMT2',
#       'PAY_AMT3', 'PAY_AMT4', 'PAY_AMT5', 'PAY_AMT6', 'SEX_1',
#       'EDUCATION_0', 'EDUCATION_1', 'EDUCATION_2', 'EDUCATION_3',
#       'EDUCATION_4', 'EDUCATION_5', 'MARRIAGE_0', 'MARRIAGE_1',
#       'MARRIAGE_2', 'intercept']

train_cols = ["SEX_1", "AGE", "MARRIAGE_0", 'PAY_0','intercept']
# Cette cellule n'est nécessaire que si vous utilisez scipy 1.0 avec statsmodels 0.8.
from pymyinstall.fix import fix_scipy10_for_statsmodels08
fix_scipy10_for_statsmodels08()
logit = sm.Logit(data['Y'], data[train_cols].astype(float))

# fit the model
result = logit.fit()
print(result.summary())<jupyter_output>Optimization terminated successfully.
         Current function value: 0.475306
         Iterations 6
                           Logit Regression Results                           
==============================================================================
Dep. Variable:                      Y   No. Observations:                22500
Model:                          Logit   Df Residuals:                    22495
Method:                           MLE   Df Model:                            4
Date:                Wed, 01 Nov 2017   Pseudo R-squ.:                  0.1008
Time:                        20:48:54   Log-Likelihood:                -10694.
converged:                       True   LL-Null:                       -11893.
                                        LLR p-value:                     0.000
==============================================================================
                 coef    std err          z      P>|z|      [0.025      0.975]
-----------------------------[...]<jupyter_text>Prédiction sur la base de testOn va prédire les probabilités de défaut de paiement sur notre base de test.Il faut commencer par transformer la base de test comme on l'a fait pour la base de train.<jupyter_code>data_test = pd.read_csv(fichier_test, header=[0,1], sep="\t", index_col=0)
#### Gender dummies
data_test['X2'] = data_test['X2'].applymap(str)
gender_dummies_test = pd.get_dummies(data_test['X2'] )
### education dummies
data_test['X3'] = data_test['X3'].applymap(str)
educ_dummies_test = pd.get_dummies(data_test['X3'] )
#### marriage dummies
data_test['X4'] = data_test['X4'].applymap(str)
mariage_dummies_test = pd.get_dummies(data_test['X4'] )
### On va aussi supprimer les multi index de la table
data_test.columns = data_test.columns.droplevel(0)
#### on aggrège ensuite les 3 tables ensemble
data_test = data_test.join(gender_dummies_test).join(educ_dummies_test).join(mariage_dummies_test)
data_test['intercept'] = 1.0
data_test[train_cols].head()<jupyter_output><empty_output><jupyter_text>Maintenant que la base de test est également transformée, nous allons appliqué les résultats de notre modèle à cette table en utilisant la fonction predict<jupyter_code>data_test['prediction_statsmodel'] = result.predict(data_test[train_cols])
data_test['prediction_statsmodel'].describe()<jupyter_output><empty_output><jupyter_text>On trouve un taux moyen de défaut de 22%, ce qui est très proche du taux observé dans la base de train<jupyter_code># puis on l'exporte
data_test['prediction_statsmodel'].to_csv("./answer.csv", index=False)<jupyter_output><empty_output><jupyter_text>Regression logistique en utilisant Scikit-learnA présent, nous allons utiliser le module scikit learn pour estimer le même modèle que précédemment et comparer les résultats.Ici pas besoin d'ajouter une variable égale à 1 (l'intercept) car Scikit learn considère qu'il y a un intercept par défaut.<jupyter_code>from sklearn import linear_model
logistic = linear_model.LogisticRegression()
print("l'estimation des coefficients", logistic.fit(data[train_cols], data['Y']).coef_, "\n")

print("l'intercept : ", logistic.fit(data[train_cols], data['Y']).intercept_)<jupyter_output>l'estimation des coefficients [[ 0.10899192  0.00751036 -0.56310513  0.72994068 -0.85555264]] 

l'intercept :  [-0.85555264]<jupyter_text>A la différence de statsmodels, Scikit-learn ne propose pas une belle table de résultat : seulement les arrays qui contiennent les coefficientsPour le détail des p-value et intervalles de confiance, il faudra les recalculer à la main. Par contre, la fonction de prédiction existe et elle renvoit  la probabilité de Y = 0 et Y = 1<jupyter_code>logistic.predict_proba(data_test[train_cols])
# pour calculer la moyenne du taux de défaut prédit 
logistic.predict_proba(data_test[train_cols]).mean(axis=0)

# on trouve à nouveau 22%<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1259821186670279, 'fraction_numerical': 0.02926036304524519, 'mean_word_length': 4.281115879828326, 'pattern_counts': {'":': 0, '<': 34, '<?xml version=': 0, '>': 35, 'https://': 1, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '9', 'dir': 'jupyter-structured-clean-dedup', 'id': '336565', 'license': 'MIT', 'n_tokens_mistral': 2599, 'n_tokens_neox': 2476, 'n_words': 654, 'path': '_doc/notebooks/competitions/2016/td2a_eco_competition_modeles_logistiques.ipynb', 'repo_name': 'Jerome-maker/ensae_teaching_cs', 'size': '7382'}