library(ggplot2)
library(dplyr)
library("ggfortify")
library("questionr")
On a relevé l’âge et la présence (1) ou l’absence (0) d’une maladie cardiovasculaire chez 100 individus. Les données sont stockées dans le fichier : sur une ligne donnée, la variable fournit l’âge d’un individu tandis que la variable prend la valeur 1 en cas de présence d’une maladie cardiovasculaire chez cet individu et la valeur 0 sinon. Les variables et donnent respectivement le numéro d’un individu et sa classe d’âge.
On acquière les données et on en visualise les premières lignes grâce aux commandes
#Données
maladie= read.table('maladie_cardiovasculaire.txt',header=TRUE)
attach(maladie)
glimpse(maladie)
## Observations: 100
## Variables: 4
## $ ID <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17...
## $ AGRP <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, ...
## $ AGE <int> 20, 23, 24, 25, 25, 26, 26, 28, 28, 29, 30, 30, 30, 30, 3...
## $ CHD <int> 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, ...
#Transformation
maladie$CHD = factor(CHD, levels = c(0,1), labels = c("No","Yes"))
maladie$AGRP = factor(AGRP)
glimpse(maladie)
## Observations: 100
## Variables: 4
## $ ID <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17...
## $ AGRP <fctr> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2,...
## $ AGE <int> 20, 23, 24, 25, 25, 26, 26, 28, 28, 29, 30, 30, 30, 30, 3...
## $ CHD <fctr> No, No, No, No, Yes, No, No, No, No, No, No, No, No, No,...
summary(maladie)
## ID AGRP AGE CHD
## Min. : 1.00 7 :17 Min. :20.00 No :57
## 1st Qu.: 25.75 2 :15 1st Qu.:34.75 Yes:43
## Median : 50.50 4 :15 Median :44.00
## Mean : 50.50 5 :13 Mean :44.38
## 3rd Qu.: 75.25 3 :12 3rd Qu.:55.00
## Max. :100.00 1 :10 Max. :69.00
## (Other):18
maladie.logit = glm(CHD~AGE, family=binomial(link="logit"),data=maladie)
coef(maladie.logit)
## (Intercept) AGE
## -5.3094534 0.1109211
#Resumé complet de la régression logistique
summary(maladie.logit)
##
## Call:
## glm(formula = CHD ~ AGE, family = binomial(link = "logit"), data = maladie)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -1.9718 -0.8456 -0.4576 0.8253 2.2859
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -5.30945 1.13365 -4.683 2.82e-06 ***
## AGE 0.11092 0.02406 4.610 4.02e-06 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 136.66 on 99 degrees of freedom
## Residual deviance: 107.35 on 98 degrees of freedom
## AIC: 111.35
##
## Number of Fisher Scoring iterations: 4
Une manière de tester la qualité d’un modèle est le calcul d’une matrice de confusion, c’est-à-dire le tableau croisé des valeurs observées et celles des valeurs prédites en appliquant le modèle aux données d’origine.
#score
score.glm = predict.glm(maladie.logit, maladie, type="response")
#Matrice de confusion (au seuil fixé 0.5)
pred.glm = as.numeric(score.glm >=0.5)
pred.glm = factor(pred.glm, levels = c(0,1), labels = c("No","Yes"))
table(maladie$CHD,pred.glm)
## pred.glm
## No Yes
## No 45 12
## Yes 14 29
mean(maladie$CHD!=pred.glm)
## [1] 0.26
maladie.logit.2 = glm(CHD~I(AGE^2), family=binomial(link="logit"))
summary(maladie.logit.2)
##
## Call:
## glm(formula = CHD ~ I(AGE^2), family = binomial(link = "logit"))
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -2.1019 -0.8149 -0.5149 0.8191 2.1253
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -2.9117530 0.6184278 -4.708 2.50e-06 ***
## I(AGE^2) 0.0012218 0.0002636 4.635 3.57e-06 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 136.66 on 99 degrees of freedom
## Residual deviance: 107.39 on 98 degrees of freedom
## AIC: 111.39
##
## Number of Fisher Scoring iterations: 4
# Motivation pour la prediction et courbe du ROC
n = nrow(maladie);
p=0.75; ntrain=floor(p*n) ; ntest = n-ntrain
ind=sample(n); ind_train=ind[1:ntrain] ; ind_test=ind[(ntrain+1):n]
maladie.train=maladie[ind_train,] ; maladie.test=maladie[ind_test,]
#score
score.glm = predict.glm(maladie.logit, maladie.test, type="response")
#Matrice de confusion (au seuil fixé 0.5)
pred.glm = as.numeric(score.glm >=0.5)
pred.glm = factor(pred.glm, levels = c(0,1), labels = c("No","Yes"))
table(maladie.test[,4],pred.glm)
## pred.glm
## No Yes
## No 9 2
## Yes 3 11
mean(maladie.test[,4]!=pred.glm)
## [1] 0.2
#Proportion de vrais positifs (au seuil fixé 0.5)
sum( score.glm >= 0.5 & maladie.test[,4]=="Yes")/sum(maladie.test[,4]=="Yes")
## [1] 0.7857143
#Proportion de vrais negatifs
sum( score.glm < 0.5 & maladie.test[,4]=="No")/sum(maladie.test[,4]=="No")
## [1] 0.8181818
#Proportion de faux poistifs
sum( score.glm >= 0.5 & maladie.test[,1]=="No")/sum(maladie.test[,4]=="No")
## [1] 0
Nous traitons un problème de défaut bancaire. Nous cherchons à déterminer quels clients seront en défaut sur leur dette de carte de crédit (ici = 1 si le client fait défaut sur sa dette). La variable est la variable réponse.
Nous disposons d’un échantillon de taille \(10000\) et 3 variables explicativesLes variables explicatives sont les suivantes :
: variable à 2 niveaux {0,1} (student = 1 si le client est un étudiant).
: montant moyen mensuel d’utilisation de la carte de crédit.
: revenu du client.
library(ISLR)
data(Default); attach(Default)
glimpse(Default)
## Observations: 10,000
## Variables: 4
## $ default <fctr> No, No, No, No, No, No, No, No, No, No, No, No, No, N...
## $ student <fctr> No, Yes, No, No, No, Yes, No, Yes, No, No, Yes, Yes, ...
## $ balance <dbl> 729.5265, 817.1804, 1073.5492, 529.2506, 785.6559, 919...
## $ income <dbl> 44361.625, 12106.135, 31767.139, 35704.494, 38463.496,...
#résumé des données (un peu de stats descriptive)
summary(Default)
## default student balance income
## No :9667 No :7056 Min. : 0.0 Min. : 772
## Yes: 333 Yes:2944 1st Qu.: 481.7 1st Qu.:21340
## Median : 823.6 Median :34553
## Mean : 835.4 Mean :33517
## 3rd Qu.:1166.3 3rd Qu.:43808
## Max. :2654.3 Max. :73554
qplot(data = Default, default)
qplot(data = Default, balance)
qplot(data = Default, income)
qplot(data = Default, student)
Default.logit=glm(default~balance + income + student,family=binomial(link="logit"),data=Default)
summary(Default.logit)
##
## Call:
## glm(formula = default ~ balance + income + student, family = binomial(link = "logit"),
## data = Default)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -2.4691 -0.1418 -0.0557 -0.0203 3.7383
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -1.087e+01 4.923e-01 -22.080 < 2e-16 ***
## balance 5.737e-03 2.319e-04 24.738 < 2e-16 ***
## income 3.033e-06 8.203e-06 0.370 0.71152
## studentYes -6.468e-01 2.363e-01 -2.738 0.00619 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 2920.6 on 9999 degrees of freedom
## Residual deviance: 1571.5 on 9996 degrees of freedom
## AIC: 1579.5
##
## Number of Fisher Scoring iterations: 8
# Sélection par AIC et backward
step(Default.logit,direction="backward")
## Start: AIC=1579.54
## default ~ balance + income + student
##
## Df Deviance AIC
## - income 1 1571.7 1577.7
## <none> 1571.5 1579.5
## - student 1 1579.0 1585.0
## - balance 1 2907.5 2913.5
##
## Step: AIC=1577.68
## default ~ balance + student
##
## Df Deviance AIC
## <none> 1571.7 1577.7
## - student 1 1596.5 1600.5
## - balance 1 2908.7 2912.7
##
## Call: glm(formula = default ~ balance + student, family = binomial(link = "logit"),
## data = Default)
##
## Coefficients:
## (Intercept) balance studentYes
## -10.749496 0.005738 -0.714878
##
## Degrees of Freedom: 9999 Total (i.e. Null); 9997 Residual
## Null Deviance: 2921
## Residual Deviance: 1572 AIC: 1578
Default.logit.choisi=glm(default~balance + student,family=binomial(link="logit"),data=Default)
summary(Default.logit.choisi)
##
## Call:
## glm(formula = default ~ balance + student, family = binomial(link = "logit"),
## data = Default)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -2.4578 -0.1422 -0.0559 -0.0203 3.7435
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -1.075e+01 3.692e-01 -29.116 < 2e-16 ***
## balance 5.738e-03 2.318e-04 24.750 < 2e-16 ***
## studentYes -7.149e-01 1.475e-01 -4.846 1.26e-06 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 2920.6 on 9999 degrees of freedom
## Residual deviance: 1571.7 on 9997 degrees of freedom
## AIC: 1577.7
##
## Number of Fisher Scoring iterations: 8
odds.ratio(Default.logit.choisi)
## OR 2.5 % 97.5 % p
## (Intercept) 0.000 0.000 0.000 < 2.2e-16 ***
## balance 1.006 1.005 1.006 < 2.2e-16 ***
## studentYes 0.489 0.365 0.651 1.26e-06 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#score
score.glm = predict.glm(Default.logit.choisi, data=Default, type="response")
#Matrice de confusion (au seuil fixé 0.5)
pred.glm = as.numeric(score.glm >=0.5)
pred.glm = factor(pred.glm, levels = c(0,1), labels = c("No","Yes"))
table(Default$default,pred.glm)
## pred.glm
## No Yes
## No 9628 39
## Yes 228 105
mean(Default$default!=pred.glm)
## [1] 0.0267
#Estimation de l'erreurr par validation croisée
glm_KFold_CV <- function (D,name,K) {
formula=formula(paste(name,"~ ."))
n=nrow(D)
Error_glm=dim(K)
ind_Fold=sample(rep(1:K,ceiling(n/K)),n)
for (i in 1:K){
Dtrain=D[which(ind_Fold!=i),]; Dtest=D[which(ind_Fold==i),]
fit.glm=glm(formula,data=Dtrain,family=binomial)
pred.glm = as.numeric( predict(fit.glm, Dtest, type="response") >= 0.5 )
Error_glm[i]=sum((as.numeric(Dtest[,name])-1)!=pred.glm)/nrow(Dtest)
}
mean(Error_glm)
}
VC.glm=glm_KFold_CV(Default,"default",5)
VC.glm
## [1] 0.0269
# Motivation pour la prediction et courbe du ROC
n = nrow(Default);
p=0.75; ntrain=floor(p*n) ; ntest = n-ntrain
ind=sample(n); ind_train=ind[1:ntrain] ; ind_test=ind[(ntrain+1):n]
Default.train=Default[ind_train,] ; Default.test=Default[ind_test,]
fit.glm=glm(default~.,data=Default.train,family=binomial)
#score
score.glm = predict.glm(fit.glm, Default.test, type="response")
#Matrice de confusion (au seuil fixé 0.5)
pred.glm = as.numeric(score.glm >=0.5)
pred.glm = factor(pred.glm, levels = c(0,1), labels = c("No","Yes"))
table(Default.test[,1],pred.glm)
## pred.glm
## No Yes
## No 2390 13
## Yes 73 24
mean(Default.test[,1]!=pred.glm)
## [1] 0.0344
#Proportion de vrais positifs (au seuil fixé 0.5)
sum( score.glm >= 0.5 & Default.test[,1]=="Yes")/sum(Default.test[,1]=="Yes")
## [1] 0.2474227
#Proportion de vrais negatifs
sum( score.glm < 0.5 & Default.test[,1]=="No")/sum(Default.test[,1]=="No")
## [1] 0.9945901
#Proportion de faux poistifs
sum( score.glm >= 0.5 & Default.test[,1]=="No")/sum(Default.test[,1]=="No")
## [1] 0.005409904
#Taux de vrais positifs (TPR) et taux faux positifs (FPR) pour difeferents valeurs de s
#seuil s
s.glm=seq(0,1,.01)
#des fois c'est mieux avec les quantiles car plus des precision dans les rangs des scores
#s.glm=quantile(score.glm,probs=seq(0,1,.01))
#Initialisation :
absc.glm=numeric(length(s.glm));ordo.glm=numeric(length(s.glm))
for (i in 1:length(s.glm)){
ordo.glm[i]=sum( score.glm>=s.glm[i] & Default.test[,1]=="Yes")/sum(Default.test[,1]=="Yes")
absc.glm[i]=sum( score.glm>=s.glm[i] & Default.test[,1]=="No")/sum(Default.test[,1]=="No")
}
ROC = data.frame(FPR=absc.glm, TPR=ordo.glm)
#Courbe Roc : taux de vrais positifs (TPR) en fonction du taux de faux positifs (FPR)
ggplot(ROC,aes(x=FPR,y=TPR)) + geom_path(aes(),color="red") +
geom_segment(aes(x = 0, y = 0, xend = 1, yend = 1), linetype = 2, color = "black")
Nous disposons de données recuilles à Hewlett-Packards Labs, qui classe 4601 e-mails comme spam ou non spam. Il y a 57 variables indiquant la fréquence de certains mots et de caractères dans l’e-mail. Ces données sont disponnibles sous la librarie kernlab du logiciel R. Le donneur des e-mails c’est George Forman de HP Labs.
library(kernlab)
data(spam);attach(spam)
names(spam)
## [1] "make" "address" "all"
## [4] "num3d" "our" "over"
## [7] "remove" "internet" "order"
## [10] "mail" "receive" "will"
## [13] "people" "report" "addresses"
## [16] "free" "business" "email"
## [19] "you" "credit" "your"
## [22] "font" "num000" "money"
## [25] "hp" "hpl" "george"
## [28] "num650" "lab" "labs"
## [31] "telnet" "num857" "data"
## [34] "num415" "num85" "technology"
## [37] "num1999" "parts" "pm"
## [40] "direct" "cs" "meeting"
## [43] "original" "project" "re"
## [46] "edu" "table" "conference"
## [49] "charSemicolon" "charRoundbracket" "charSquarebracket"
## [52] "charExclamation" "charDollar" "charHash"
## [55] "capitalAve" "capitalLong" "capitalTotal"
## [58] "type"
fit.glm=glm(type~.,data=spam,family=binomial)
#summary(fit.glm)
# Decoupage (2 sous échantillons)
n = nrow(spam); d= ncol(spam)
p=0.75; ntrain=floor(p*n) ; ntest = n-ntrain
ind=sample(n); ind_train=ind[1:ntrain] ; ind_test=ind[(ntrain+1):n]
spam.train=spam[ind_train,] ; spam.test=spam[ind_test,]
# Ajustement du modèle logistique
fit.glm=glm(type~.,data=spam.train,family=binomial)
#score : estimation de p(x) = P(Y=spam|X=x) à l'aidele modèle logistique
score.glm = predict.glm(fit.glm, spam.test, type="response")
#Matrice de confusion (au seuil fixé 0.5)
pred.glm = as.numeric(score.glm >=0.5)
pred.glm = factor(pred.glm, levels = c(0,1), labels = c("nonspam","spam"))
table(spam.test[,d],pred.glm)
## pred.glm
## nonspam spam
## nonspam 670 32
## spam 46 403
mean(spam.test[,d]!=pred.glm)
## [1] 0.06776716
# Courbe du ROC
#Proportion de vrais positifs (au seuil fixé 0.5)
sum( score.glm >= 0.5 & spam.test[,d]=="spam")/sum(spam.test[,d]=="spam")
## [1] 0.8975501
#Proportion de vrais negatifs
sum( score.glm < 0.5 & spam.test[,d]=="nonspam")/sum(spam.test[,d]=="nonspam")
## [1] 0.954416
#Proportion de faux poistifs
sum( score.glm >= 0.5 & spam.test[,d]=="nonspam")/sum(spam.test[,d]=="nonspam")
## [1] 0.04558405
#Taux de vrais positifs (TPR) et taux faux positifs (FPR) pour difeferents valeurs de s
#seuil s
s.glm=seq(0,1,.01)
#des fois c'est mieux avec les quantiles car plus des precision dans les rangs des scores
#s.glm=quantile(score.glm,probs=seq(0,1,.01))
#Initialisation :
absc.glm=numeric(length(s.glm));ordo.glm=numeric(length(s.glm))
for (i in 1:length(s.glm)){
ordo.glm[i]=sum( score.glm>=s.glm[i] & spam.test[,d]=="spam")/sum(spam.test[,d]=="spam")
absc.glm[i]=sum( score.glm>=s.glm[i] & spam.test[,d]=="nonspam")/sum(spam.test[,d]=="nonspam")
}
ROC = data.frame(FPR=absc.glm, TPR=ordo.glm)
#Courbe Roc : Taux de vrais positifs (TPR) en fonction de taux de faux positifs (FPR)
ggplot(ROC,aes(x=FPR,y=TPR)) + geom_path(aes(),color="red") +
geom_segment(aes(x = 0, y = 0, xend = 1, yend = 1), linetype = 2, color = "black")