from jyquickhelper import add_notebook_menu
add_notebook_menu()

%matplotlib inline

"""
Explanation: 2A.ml - Classification binaire avec features textuelles - correction
Ce notebook propose de voir comment incorporer des features pour voir l'amélioration des performances sur une classification binaire.
End of explanation
"""


from pyensae.datasource import download_data
data_train = download_data("off_train_all.zip", 
                           url="https://raw.githubusercontent.com/sdpython/data/master/OpenFoodFacts/")

data_test = download_data("off_test_all.zip", 
                           url="https://raw.githubusercontent.com/sdpython/data/master/OpenFoodFacts/")

import pandas
df = pandas.read_csv("off_test_all.txt", sep="\t", encoding="utf8", low_memory=False)

df.head()

"""
Explanation: Récupérer les données
Les données sont téléchargeables Compétition 2017 - additifs alimentaires ou encore avec le code :
End of explanation
"""


sample = df.sample(n=10000)
sample.shape

"""
Explanation: Exercice 1 : extraire un échantillon aléatoire
Les données sont volumineuses. Prenons un échantillon pour aller plus vite. On se sert de la méthode sample.
End of explanation
"""


sample_num = sample.select_dtypes((float, bool))
sample_num.shape

X = sample_num.drop("hasE", axis=1).fillna(0)
Y = sample_num["hasE"]

from sklearn.linear_model import LogisticRegression
clf = LogisticRegression()
clf.fit(X, Y)

"""
Explanation: Exercice 2 : caler un premier modèle de classification binaire
Avec les variables numériques uniquement. La cible est la variable hasE. On sélectionne les variables numériques et on cale un premier modèle et la variable hasE dont le type est booléen. On remplace les valeurs manquantes par zéro.
End of explanation
"""


from sklearn.metrics import confusion_matrix
conf = confusion_matrix(Y, clf.predict(X))
conf

"""
Explanation: On vérifie que le modèle fonctionne à peu près.
End of explanation
"""


from sklearn.ensemble import RandomForestClassifier
clrf = RandomForestClassifier()
clrf.fit(X, Y)

conf = confusion_matrix(Y, clrf.predict(X))
conf

"""
Explanation: Ca ne marche pas vraiment. On essaye avec une forêt d'arbres.
End of explanation
"""


sample2 = df.sample(n=10000)
sample2_num = sample2.select_dtypes((float, bool))
X2 = sample2_num.drop("hasE", axis=1).fillna(0)
Y2 = sample2_num["hasE"]
conf2 = confusion_matrix(Y2, clrf.predict(X2))
conf2

"""
Explanation: Beaucoup mieux. Les performances semblent incroyables mais il ne faut pas oublier qu'on évalue le modèle sur la base d'apprentissage. Essayons sur un autre échantillon aléatoire.
End of explanation
"""


from sklearn.metrics import roc_curve
y_proba = clrf.predict_proba(X2)
y_pred = clrf.predict(X2)
# y_pred est plein de booléen. Il faut les convertir en entier.
prob_pred = y_proba[:, 1]
fpr, tpr, th = roc_curve(Y2, prob_pred)

import matplotlib.pyplot as plt
plt.figure()
lw = 2
plt.plot(fpr, tpr, color='darkorange', lw=lw, label='Courbe ROC')
plt.plot([0, 1], [0, 1], color='navy', lw=lw, linestyle='--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel("Proportion mal classée")
plt.ylabel("Proportion bien classée")
plt.title('ROC')
plt.legend(loc="lower right")

"""
Explanation: Pas si mal.
Exercice 3 : tracer une courbe ROC
On trace la courbe ROC avec le second échantillon.
End of explanation
"""


fig, ax = plt.subplots(1, 1)
ax.hist(y_proba[Y2==1, 1], alpha=0.5, label="score class 1")
ax.hist(y_proba[Y2==0, 1], alpha=0.5, label="score class 0")
ax.legend();

"""
Explanation: La courbe ROC paraît fidèle à la matrice de confusion, on vérifie avec la distribution des scores.
End of explanation
"""


