AFD<-function(X,y){
n<-nrow(X)
p <- ncol(X)
K<-length(levels(factor(y)))
nk<-as.vector(table(y))
names(nk) <- levels(y)
pk<-nk/n
Xk <-list()
Xk <- split(X,y)
V<-var(X)*(n-1)/n
R<-cor(X)
g<-matrix(apply(X,2,mean),ncol=1)
rownames(g) <- colnames(X)
Vk<-list()
Rk<-list()
gk<-list()
for (k in 1:K){
gk[[k]]<-matrix(apply(Xk[[k]],2,mean),ncol=1)
rownames(gk[[k]]) <- colnames(X)
Vk[[k]]<-var(Xk[[k]])*(nk[k]-1)/nk[k]
Rk[[k]]<-cor(Xk[[k]])
}
names(Vk) <- levels(y)
names(Rk) <- levels(y)
names(gk) <- levels(y)
Xcent<-X-matrix(rep(1,n),ncol=1)%*%t(g)
W<-matrix(0,nrow=p,ncol=p)
B<-matrix(0,nrow=p,ncol=p)
for (k in 1:K){
W<-W+pk[k]*Vk[[k]]
B<-B+pk[k]*(gk[[k]]-g)%*%t(gk[[k]]-g)
}
# Calcul des FD :
res<-eigen(solve(V)%*%B)
eig <- Re(res$values[1:(K-1)])
UU<-Re(res$vectors[,1:(K-1)])
normes <- sqrt(diag(t(UU)%*%V%*%UU))
if (K>2) {
U <- sweep(UU,2,normes,"/")
} else {
U <- UU/normes
}
if (K>2) {
rownames(U) <- colnames(X)
colnames(U)<-paste("u",1:ncol(U),sep="")
} else
{
names(U) <- colnames(X)
}
# Calcul des VD :
S<-as.matrix(Xcent)%*%U
if (K>2) {
colnames(S) <-paste("s",1:ncol(S),sep="")
rownames(S)<-rownames(X)
} else names(S)<-rownames(X)
list(eig=eig,U=U,S=S,nk=nk,K=K,y=y,X=X,Xk=Xk,W=W,B=B,g=data.frame(g=g),gk=data.frame(gk),V=V,R=R,Vk=Vk,Rk=Rk)
}
plotAFD<-function(res)
{
dim = c(1)
nbaxes <- length(res$eig)
if ((length(dim) > 1) && (nbaxes >1)) {
min.x<-min(res$S[,dim[1]])
max.x<-max(res$S[,dim[1]])
min.y<-min(res$S[,dim[2]])
max.y<-max(res$S[,dim[2]])
dim1 <- dim[1]
dim2 <- dim[2]
quali <- as.factor(res$y)
plot(res$S[,dim],xlab=paste("Dim",dim1),ylab=paste("Dim",dim2), xlim=c(min.x,max.x),ylim=c(min.y,max.y),pch=" ",main="Individus")
abline(h = 0, lty = 2,)
abline(v = 0, lty = 2)
legend("topleft",legend = levels(quali), text.col = c(1:length(levels(quali))),cex=0.8)
text(res$S[,dim],labels=rownames(res$S),col=as.numeric(quali))
mat.corr <- res$mat.corr
xlim <- c(-1, 1)*1.3
ylim <- c(-1, 1)*1.3
plot(0, 0, type="n",xlab=paste("Dim",dim1),ylab=paste("Dim",dim2), xlim = xlim, ylim = ylim, main="Variables")
x.cercle <- seq(-1, 1, by = 0.01)
y.cercle <- sqrt(1 - x.cercle^2)
lines(x.cercle, y = y.cercle)
lines(x.cercle, y = -y.cercle)
abline(v = 0, lty = 2)
abline(h = 0, lty = 2)
for (j in 1:nrow(mat.corr)) {
arrows(0, 0, mat.corr[j,dim1], mat.corr[j,dim2], length = 0.1, angle = 15, code = 2)
if (abs(mat.corr[j,dim1]) > abs(mat.corr[j,dim2])) {
if (mat.corr[j,dim1] >= 0) pos <- 4
else pos <- 2
} else {
if (mat.corr[j,dim2] >= 0) pos <- 3
else pos <- 1
}
text(mat.corr[j,dim1],mat.corr[j,dim2],labels = rownames(mat.corr)[j], pos = pos)
}
} else {
if (nbaxes==1) {
quali <- as.factor(res$y)
plot(res$S,rep(0,length(res$S)),xlab="Axe 1",ylab="",col=as.numeric(quali))
legend("topleft",legend = levels(quali), text.col = c(1:length(levels(quali))),cex=0.8)
} else {
quali <- as.factor(res$y)
plot(res$S[,dim],rep(0,length(res$S[,dim])),xlab=paste("Axe",dim),ylab="",col=as.numeric(quali))
legend("topleft",legend = levels(quali), text.col = c(1:length(levels(quali))),cex=0.8)
}
}
}
acp_from_scratch <- function(X, nombre_composants=NULL, reduire = FALSE) {
n <- nrow(X)
X <- as.matrix(X)
# Data centree
data <- centrage(X)
# Data normee
if (reduire) {
data <- centrer_reduire(X)
}
#calculer la matrice de covariance matriciellement
matrice_covariance <- (1/n) * t(data) %*% data
# Calcul des valeurs propres et vecteurs propres
eig_result <- eigen(matrice_covariance)
valeurs_propres <- eig_result$values
vecteurs_propres <- eig_result$vectors
# Sélectionner le nombre spécifié de composants principaux
if (!is.null(nombre_composants)) {
vecteurs_propres <- vecteurs_propres[, 1:nombre_composants, drop = FALSE]
}
# Projection des données sur les composants principaux
nouvelles_coordonnees <- data %*% vecteurs_propres
return(list(matrice_covariance=matrice_covariance,
nouvelles_coordonnees=nouvelles_coordonnees,
valeurs_propres=valeurs_propres,
vecteurs_propres=vecteurs_propres))
}
centrage <- function(data) {
n <- nrow(data)
# Centrage des données
# Définir la matrice des poids
matrice_de_poids <- (1/n) * diag(n)
# Calculer la moyenne pondérée matriciellement
mat1_n <- matrix(rep(1, n), nrow=1)
moyenne_ponderee <- mat1_n %*% data / n
#calculer data_centree
data_centree <- sweep(data, 2, moyenne_ponderee)
return (data_centree)
}
centrer_reduire <- function(donnees) {
n <- nrow(donnees) # Nombre d'observations
p <- ncol(donnees) # Nombre de variables
# Centrage des données
donnees_centrees = centrage(donnees)
# Réduction des données (calcul de l'écart-type de façon matricielle avec biais)
# Calculer la matrice de covariance avec biais (diviser par n!)
matrice_covariance <- (1 / n) * (t(donnees_centrees) %*% donnees_centrees)
# Extraire l'écart-type à partir de la diagonale de la matrice de covariance
ecarts_types <- sqrt(diag(matrice_covariance))
# Réduire les données : diviser par l'écart-type
donnees_reduites <- sweep(donnees_centrees, 2, ecarts_types, FUN = "/")
return(donnees_reduites)
}
library(readr)
# Importer les données de l'énoncé
data <- read.csv("chienloup.csv", sep=";")
# Il y a t il des NA ? NON
#print(sum(is.na(data)))
head(data)
## SPE LCB LSM LBM LP LM LAM GENRE
## 1 BULL-DOG 1 1290 640 950 175 112 138 CHIEN
## 2 BULL-DOG 2 1540 740 760 200 142 165 CHIEN
## 3 BOXER 1580 710 710 167 125 133 CHIEN
## 4 SAINT-BERNARD 2200 1110 880 225 154 180 CHIEN
## 5 BULL-MASSIF 1900 930 780 197 132 140 CHIEN
## 6 DOGUE ALLEMAND 1 2410 1190 870 210 147 183 CHIEN
#print(dim(data))
data <- as.data.frame(data)
data_numeric <- data[,2:7]
y <- data[,8]
data_numeric <- as.data.frame(centrer_reduire(as.matrix(data_numeric)))
res <- AFD(data_numeric, y)
##############################################################8
2 groupes donc au plus 1 axes discriminant !
##############################################################8
res$nk #nombre d'individus dans chaque classe
## [1] 30 12
##############################################################8
Il y a 30 individus chien contre 12 individus loup pour les data.
##############################################################8
head(res$V)
## LCB LSM LBM LP LM LAM
## LCB 1.0000000 0.9608048 0.3486069 0.6145106 0.7196386 0.5877091
## LSM 0.9608048 1.0000000 0.2001415 0.6605947 0.7356318 0.5948046
## LBM 0.3486069 0.2001415 1.0000000 0.3698780 0.3501861 0.3547371
## LP 0.6145106 0.6605947 0.3698780 1.0000000 0.8933906 0.7628560
## LM 0.7196386 0.7356318 0.3501861 0.8933906 1.0000000 0.7894591
## LAM 0.5877091 0.5948046 0.3547371 0.7628560 0.7894591 1.0000000
head(res$W)
## LCB LSM LBM LP LM LAM
## LCB 0.9399806 0.8820546 0.2998707 0.4101504 0.5486463 0.4321908
## LSM 0.8820546 0.8966734 0.1361957 0.3924578 0.5112761 0.3907520
## LBM 0.2998707 0.1361957 0.9604259 0.2039360 0.2113390 0.2284550
## LP 0.4101504 0.3924578 0.2039360 0.3041730 0.3111779 0.2333309
## LM 0.5486463 0.5112761 0.2113390 0.3111779 0.5128508 0.3463946
## LAM 0.4321908 0.3907520 0.2284550 0.2333309 0.3463946 0.5970308
head(res$B)
## LCB LSM LBM LP LM LAM
## LCB 0.06001935 0.07875020 0.04873617 0.2043602 0.1709923 0.1555183
## LSM 0.07875020 0.10332658 0.06394577 0.2681370 0.2243557 0.2040525
## LBM 0.04873617 0.06394577 0.03957415 0.1659420 0.1388471 0.1262821
## LP 0.20436019 0.26813696 0.16594205 0.6958270 0.5822127 0.5295251
## LM 0.17099234 0.22435566 0.13884710 0.5822127 0.4871492 0.4430645
## LAM 0.15551833 0.20405252 0.12628208 0.5295251 0.4430645 0.4029692
library(FactoMineR)
data2 <- data_numeric
data2$GENRE <- data$GENRE
pca<-PCA(data2,quali.sup=7,graph=FALSE)
plot(pca,habillage=7)
plot(pca,choix="var")
plot(pca,invisible="ind")
##############################################################8
On voit bien que nos 2 classes sont sur quasi la même dimension et de signe contraire, on a 1 seul axe discriminant en AFD d’ailleurs. On peut en déduire que pour notre AFD on aura les classes chien d’un côté et celles loup de l’autre sur une droite 1D car 1 seul axe car 2 classes.
##############################################################8
res$eig # valeur propre
## [1] 0.8235635
res$U # vecteur propre
## LCB LSM LBM LP LM LAM
## 0.520342622 -0.006455009 0.079745247 -1.062982533 -0.117579660 -0.126031773
plotAFD(res)
u1<-res$U #1er facteurs discriminants
print(u1)
## LCB LSM LBM LP LM LAM
## 0.520342622 -0.006455009 0.079745247 -1.062982533 -0.117579660 -0.126031773
gLOUP <- res$gk[,1]
gCHIEN <- res$gk[,2]
t(gLOUP)%*%u1
## [,1]
## [1,] 0.5739559
t(gCHIEN)%*%u1
## [,1]
## [1,] -1.43489
S1 <- res$S[,1] # VD
#print(S1)
Sk <- split(S1,y)
lapply(Sk,mean)
## $CHIEN
## [1] 0.5739559
##
## $LOUP
## [1] -1.43489
S1 <- res$S
#print(dim(S1))
#print(S1)
Sk <- split(S1,y)
#print(dim(Sk))
#print(Sk)
smoy <- lapply(Sk,mean)
#print(smoy)
seuil1 <- (as.numeric(smoy$CHIEN)+as.numeric(smoy$LOUP))/2 #seuil entre L et H
print(seuil1)
## [1] -0.4304669
predict <- cut(S1,breaks=c(-10,seuil1,10),labels=c("LOUP","CHIEN"))
y <- factor(y, levels = c("LOUP", "CHIEN"))
conf_matrix <- table(y,predict)
pander(conf_matrix)
| LOUP | CHIEN | |
|---|---|---|
| LOUP | 12 | 0 |
| CHIEN | 1 | 29 |
accuracy <- sum(diag(conf_matrix)) / sum(conf_matrix)
sensitivity <- diag(conf_matrix) / rowSums(conf_matrix)
specificity <- diag(conf_matrix) / colSums(conf_matrix)
precision <- diag(conf_matrix) / colSums(conf_matrix)
recall <- sensitivity
F1 <- 2 * (precision * recall) / (precision + recall)
# Data frame pour stocker les métriques avec descriptions
performance_metrics <- data.frame(
Metric = c("Accuracy", "Sensitivity", "Specificity", "Precision", "Recall", "F1 Score"),
Value = c(accuracy, mean(sensitivity), mean(specificity), mean(precision), mean(recall), mean(F1)),
Description = c(
"Proportion de toutes les prédictions correctes",
"Proportion de positifs réels correctement identifiés",
"Proportion de négatifs réels correctement identifiés",
"Proportion de prédictions positives correctes",
"Identique à la sensibilité",
"Moyenne harmonique de la précision et du rappel"
)
)
pander(performance_metrics)
| Metric | Value | Description |
|---|---|---|
| Accuracy | 0.9762 | Proportion de toutes les prédictions correctes |
| Sensitivity | 0.9833 | Proportion de positifs réels correctement identifiés |
| Specificity | 0.9615 | Proportion de négatifs réels correctement identifiés |
| Precision | 0.9615 | Proportion de prédictions positives correctes |
| Recall | 0.9833 | Identique à la sensibilité |
| F1 Score | 0.9715 | Moyenne harmonique de la précision et du rappel |
data_numeric_centree <- as.data.frame(centrage(as.matrix(data_numeric)))
res_centree <- AFD(data_numeric_centree, y)
V_centree <- res_centree$V
B_centree <- res_centree$B
mat_centree <- solve(V_centree) %*% B_centree
print(dim(mat_centree))
## [1] 6 6
head(mat_centree)
## LCB LSM LBM LP LM
## LCB -0.115686741 -0.151790283 -0.093938524 -0.393902367 -0.329586148
## LSM 0.001435129 0.001883005 0.001165336 0.004886479 0.004088616
## LBM -0.017729602 -0.023262660 -0.014396573 -0.060367612 -0.050510813
## LP 0.236330793 0.310084957 0.191902424 0.804683910 0.673295447
## LM 0.026141252 0.034299420 0.021226898 0.089008481 0.074475212
## LAM 0.028020394 0.036765004 0.022752775 0.095406779 0.079828799
## LAM
## LCB -0.299760138
## LSM 0.003718616
## LBM -0.045939820
## LP 0.612365348
## LM 0.067735553
## LAM 0.072604665
eig_centree <- eigen(mat_centree)
values_centree <- eig_centree$values
print(values_centree)
## [1] 8.235635e-01 6.208968e-16 -4.689864e-16 5.808309e-17 -5.743591e-17
## [6] 3.608047e-17
vectors_centree <- eig_centree$vectors
print(vectors_centree)
## [,1] [,2] [,3] [,4] [,5] [,6]
## [1,] 0.434101717 0.216034035 -0.17298133 0.81516105 0.64287325 -0.84146247
## [2,] -0.005385164 -0.011968038 0.89970000 0.29790972 0.05658188 -0.23581918
## [3,] 0.066528374 -0.008443295 0.26103446 0.27676360 -0.72804174 -0.34693484
## [4,] -0.886805199 -0.643959906 -0.12701437 -0.40691682 -0.17756615 0.33109279
## [5,] -0.098092161 0.732972781 -0.02605426 -0.05355258 0.03774964 0.06390074
## [6,] -0.105143432 -0.034370263 -0.27507620 0.04141244 0.14322333 0.04754677
data_numeric_normee <- as.data.frame(centrer_reduire(as.matrix(data_numeric)))
res_normee <- AFD(data_numeric_normee, y)
V_normee <- res_normee$V
B_normee <- res_normee$B
mat_normee <- solve(V_normee) %*% B_normee
print(dim(mat_normee))
## [1] 6 6
head(mat_normee)
## LCB LSM LBM LP LM
## LCB -0.115686741 -0.151790283 -0.093938524 -0.393902367 -0.329586148
## LSM 0.001435129 0.001883005 0.001165336 0.004886479 0.004088616
## LBM -0.017729602 -0.023262660 -0.014396573 -0.060367612 -0.050510813
## LP 0.236330793 0.310084957 0.191902424 0.804683910 0.673295447
## LM 0.026141252 0.034299420 0.021226898 0.089008481 0.074475212
## LAM 0.028020394 0.036765004 0.022752775 0.095406779 0.079828799
## LAM
## LCB -0.299760138
## LSM 0.003718616
## LBM -0.045939820
## LP 0.612365348
## LM 0.067735553
## LAM 0.072604665
eig_normee <- eigen(mat_normee)
values_normee <- eig_normee$values
print(values_normee)
## [1] 8.235635e-01+0.000000e+00i 1.099870e-15+0.000000e+00i
## [3] -2.256959e-16+0.000000e+00i 1.172102e-16+0.000000e+00i
## [5] -6.190151e-17+4.202055e-17i -6.190151e-17-4.202055e-17i
vectors_normee <- eig_normee$vectors
print(vectors_normee)
## [,1] [,2] [,3] [,4]
## [1,] 0.434101717+0i 0.83375525+0i 0.2572331+0i 0.03544473+0i
## [2,] -0.005385164+0i -0.46906070+0i 0.6605637+0i 0.58304723+0i
## [3,] 0.066528374+0i -0.07755971+0i 0.4492316+0i -0.34350402+0i
## [4,] -0.886805199+0i 0.18685364+0i 0.1126469+0i -0.01935804+0i
## [5,] -0.098092161+0i -0.17944646+0i -0.5049477+0i -0.57570692+0i
## [6,] -0.105143432+0i -0.10818233+0i -0.1673801+0i 0.45715576+0i
## [,5] [,6]
## [1,] 0.6983440+0.0000000i 0.6983440+0.0000000i
## [2,] 0.1951932+0.1867490i 0.1951932-0.1867490i
## [3,] -0.2665175+0.3243885i -0.2665175-0.3243885i
## [4,] -0.1349408+0.0073919i -0.1349408-0.0073919i
## [5,] -0.3363387-0.2431549i -0.3363387+0.2431549i
## [6,] 0.2622923+0.0614142i 0.2622923-0.0614142i
lambda <- 0.01
V_reg <- V_centree + lambda * diag(nrow(V_centree))
# Calcul de V_invB avec la matrice régularisée
V_invB <- solve(V_reg) %*% B_centree
# Diagonalisation
eigen_values <- eigen(V_invB)$values
print(eigen_values)
## [1] 8.122405e-01 7.289952e-16 -3.184714e-16 -2.220446e-16 1.364854e-16
## [6] 1.635272e-18
eigen_vectors <- eigen(V_invB)$vectors
print(eigen_vectors)
## [,1] [,2] [,3] [,4] [,5] [,6]
## [1,] -0.40783995 -0.27561641 0.971039653 -0.969112366 -0.24648478 0.256097640
## [2,] -0.03451261 -0.01041745 -0.144404982 -0.009322001 -0.33896899 -0.128107398
## [3,] -0.07401006 -0.07866551 -0.002410983 -0.019990431 -0.16922100 0.924840948
## [4,] 0.89355202 0.66771167 -0.186181952 0.241352177 0.65705961 -0.006743752
## [5,] 0.12454878 -0.68680650 -0.020352935 0.033641153 0.05223306 -0.067178843
## [6,] 0.11423813 0.01402739 -0.033844054 0.030856203 -0.60104402 -0.241066879
projected_data <- as.matrix(data_numeric_centree) %*% Re(eigen_vectors)
print(projected_data)
## [,1] [,2] [,3] [,4] [,5] [,6]
## [1,] -0.60724005 1.24432068 -1.94701941 2.22007251 0.941110502 2.38786707
## [2,] 0.41369716 0.28089711 -1.41152240 1.70986803 0.931997287 0.19011652
## [3,] -1.04020267 0.28358958 -0.93275260 1.19140931 0.936255367 0.15277700
## [4,] 0.28712275 -0.47300692 0.35651561 -0.39926506 -0.409385866 1.49619157
## [5,] -0.49523755 0.30477783 -0.24463114 0.33257285 0.636070619 0.86329267
## [6,] -0.60384505 -0.70978721 1.14013171 -1.30012893 -1.241307492 1.53264878
## [7,] -0.96071739 -1.29570410 1.24606183 -1.42796022 -1.320267140 1.37221440
## [8,] -0.66932663 -0.89872233 1.54144065 -1.75795559 -1.321218746 1.51606171
## [9,] -0.40086783 -0.58161252 0.94503543 -1.02523402 -0.571118791 1.23425595
## [10,] -0.39805000 -0.26880078 -0.01703977 0.01299948 0.018017588 -0.18832043
## [11,] -0.98477703 0.32781266 -0.06130957 0.01171482 0.116175381 -0.29347095
## [12,] -0.72321526 -0.47051790 0.54676853 -0.67216162 -0.351505026 -0.08340316
## [13,] -0.95497684 0.44627117 0.22492152 -0.26318304 -0.050072033 0.04373731
## [14,] -0.75200279 -0.36403837 0.45932520 -0.55418302 -0.552650210 0.36592490
## [15,] 0.10348900 0.13446461 0.55837213 -0.70037377 -0.542394417 0.54256932
## [16,] -0.38226984 0.07965061 0.26452643 -0.32856236 -0.289397363 0.12720682
## [17,] -0.32283149 -0.30345025 0.36201257 -0.43826204 -0.593569467 -0.09632245
## [18,] -0.07257447 0.14074714 -0.05558529 0.03803469 -0.001130554 -0.78623558
## [19,] -0.10396827 0.06656273 0.00188606 -0.03332203 0.029388132 -0.43793420
## [20,] -0.54667095 0.30136254 -0.37362435 0.44443470 0.652481936 -0.84842271
## [21,] -0.57682053 -0.31577820 0.31511122 -0.38111133 -0.200342776 -0.65654685
## [22,] -0.44107605 -0.06354563 0.47608932 -0.53307751 -0.358260736 -0.68483434
## [23,] -1.00433039 0.19190665 -0.53000412 0.57232741 0.347080042 -1.41583221
## [24,] -0.31992477 -0.16506405 0.24381260 -0.31172269 0.082914574 -0.63174390
## [25,] -0.05696004 -0.50561247 0.39336550 -0.52364183 -0.300200906 -1.12194710
## [26,] -0.37761319 0.64375176 -0.48498225 0.58441359 1.100284972 -1.80777987
## [27,] -0.74079622 0.57678239 -0.77920256 0.89501756 0.127653763 -0.11918353
## [28,] -0.44963781 0.26958317 -0.32217932 0.40776665 0.482214102 0.24625787
## [29,] -0.89128597 0.68915048 -0.93677184 1.13731667 1.138933626 -1.47859392
## [30,] -0.70914964 0.43400962 -0.97875168 1.09219679 0.562243631 -1.42055069
## [31,] 1.06013866 0.31378560 -0.40174232 0.46973952 0.137911310 -0.26038103
## [32,] 1.13751716 0.24465337 0.36430840 -0.38963983 0.078540162 0.33495501
## [33,] 0.93488146 0.26288664 0.37778617 -0.47581115 -0.199463105 0.83406533
## [34,] 1.09829796 -0.56556306 0.48109284 -0.55742589 0.677170865 1.16695089
## [35,] 0.70112619 -0.79808019 0.54345320 -0.63326511 -0.644000098 0.28591729
## [36,] 1.63519435 0.36970709 -0.13277708 0.12204757 0.314927834 -0.15114122
## [37,] 1.39525246 0.07361899 -0.89877373 1.03183353 0.319687671 -0.86212908
## [38,] 0.91462996 0.34459239 -1.03078915 1.18496239 0.804181964 -0.17266981
## [39,] 1.47042663 -0.59680547 0.58529117 -0.67698227 -2.180366849 -0.50943816
## [40,] 0.96257041 0.26851795 -0.28464426 0.31763169 0.139352896 -0.52182620
## [41,] 1.63676728 0.20278135 0.22715666 -0.22335171 0.242727336 -0.30569289
## [42,] 1.83525726 -0.12009465 0.16963811 -0.16973873 0.309330012 0.16138987
###################################################################8
On voit bien que nos résultats entre notre fonction AFD quo prend la partie réel et la technique de régularisation est identique presque car en effet on a 1 seul axe qui capte totue la variance, les autres sont négligeables !
Donc les 2 approches sont similaires et donnent les mêmes résulats.
###################################################################8
# Préparation pour l'inertie expliquée et cumulée
eigen_values <- Re(eigen_values)
inertie_expliquee <- eigen_values / sum(eigen_values)
cumul_inertie <- cumsum(inertie_expliquee)
ylim_max <- max(as.data.frame(cumul_inertie)) + .1
# Barplot de l'inertie expliquée
midpoints <- barplot(inertie_expliquee, main="AFD - Inertie expliquée et cumulée CENTREE", xlab="Composantes", ylab="Inertie", ylim=c(0, ylim_max), col = "blue")
lines(midpoints, cumul_inertie, type="b", col="red")
abline(h = 1, col="grey", lty=2) # Ligne pointillée pour l'asymptote
############################################################8
Il est évident que nous allons garder qu’une seul composante.
############################################################8
library(plotly)
##
## Attaching package: 'plotly'
## The following object is masked from 'package:MASS':
##
## select
## The following object is masked from 'package:ggplot2':
##
## last_plot
## The following object is masked from 'package:stats':
##
## filter
## The following object is masked from 'package:graphics':
##
## layout
library(FactoMineR)
library(dplyr)
library(stringr)
options(digits=10)
# Assurez-vous que 'data' est défini correctement et contient les colonnes nécessaires
data_numeric_centree <- data[, 2:7]
data_numeric_centree <- as.data.frame(centrage(as.matrix(data_numeric_centree)))
# Supposons que projected_data est déjà calculé et structuré correctement
ind_coords <- projected_data
# S'assurer que la colonne GENRE existe et contient les bonnes catégories
data_numeric_centree$GENRE <- data$GENRE # Remplacer 'data$GENRE' par la colonne appropriée de votre dataset
# Créer une fonction pour générer un graphique Plotly
generate_plot <- function(x, y, title) {
data_LOUP <- ind_coords[data_numeric_centree$GENRE == "LOUP", ]
data_CHIEN <- ind_coords[data_numeric_centree$GENRE == "CHIEN", ]
plot_ly() %>%
add_trace(x = ~data_LOUP[, x], y = ~data_LOUP[, y],
type = 'scatter', mode = 'markers',
marker = list(size = 6, color = 'red'), name = "L") %>%
add_trace(x = ~data_CHIEN[, x], y = ~data_CHIEN[, y],
type = 'scatter', mode = 'markers',
marker = list(size = 6, color = 'green'), name = "H") %>%
layout(title = title,
xaxis = list(title = paste("PC", x)),
yaxis = list(title = paste("PC", y)))
}
# Créer et afficher les graphiques pour chaque paire de composantes
generate_plot(1, 2, "ACP: PC1 vs PC2")
generate_plot(1, 3, "ACP: PC1 vs PC3")
generate_plot(1, 4, "ACP: PC1 vs PC4")
generate_plot(1, 5, "ACP: PC1 vs PC5")
generate_plot(2, 3, "ACP: PC2 vs PC3")
data_numeric_centree <- data[,2:7]
data_numeric_centree <- as.data.frame(centrage(as.matrix(data_numeric)))
###########################################################################8
On voit que en augmentant les composantes, la qualité des 2 classes distinctes diminue TRES LARGEMENT sans la PC1 !!!!!! (prenons pour voir PC2 VS PC3) Cela rejoint notre constat précédent : il nous faut PC1 et les autres n’apportent pas grand chose; PC1 VS PC2 est trés similaire à PC1 VS PC3.
###########################################################################8
V_centree <- res_centree$V
B_centree <- res_centree$B
W_centree <- res_centree$W
mat_centree1 <- solve(V_centree) %*% B_centree
mat_centree2 <- solve(W_centree) %*% B_centree
head(mat_centree1)
## LCB LSM LBM LP
## LCB -0.115686740613 -0.151790282852 -0.093938524317 -0.393902366785
## LSM 0.001435129224 0.001883004653 0.001165335982 0.004886478735
## LBM -0.017729602151 -0.023262660103 -0.014396573488 -0.060367611814
## LP 0.236330793098 0.310084956504 0.191902424051 0.804683909774
## LM 0.026141252134 0.034299419575 0.021226898055 0.089008481281
## LAM 0.028020393583 0.036765003881 0.022752775383 0.095406779481
## LM LAM
## LCB -0.329586147786 -0.299760137970
## LSM 0.004088616465 0.003718615736
## LBM -0.050510812594 -0.045939819540
## LP 0.673295446719 0.612365347752
## LM 0.074475212488 0.067735552967
## LAM 0.079828799148 0.072604664993
head(mat_centree2)
## LCB LSM LBM LP
## LCB -0.655684770789 -0.86031101138 -0.532421083510 -2.23254438417
## LSM 0.008133969124 0.01067241991 0.006604845571 0.02769539251
## LBM -0.100487143651 -0.13184719249 -0.081596334527 -0.34214918240
## LP 1.339466399363 1.75748735381 1.087657031923 4.56075590118
## LM 0.148162363490 0.19440090492 0.120308980197 0.50447877897
## LAM 0.158812887686 0.20837524694 0.128957287868 0.54074280254
## LM LAM
## LCB -1.86801544085 -1.69896875230
## LSM 0.02317330003 0.02107622441
## LBM -0.28628320240 -0.26037590726
## LP 3.81607752381 3.47074029878
## LM 0.42210768815 0.38390891027
## LAM 0.45245053663 0.41150587243
###########################################################################8
On voit que les signes sont les mêmes pour les 2 matrices mais les coefficient sont diffénrents pour les 2 matrices Etudions alors les VP des deux matrices :
###########################################################################8
eig1 <- eigen(mat_centree1)
eig2 <- eigen(mat_centree2)
values1 <- eig1$values
values2 <- eig2$values
print(Re(values1))
## [1] 8.235634778e-01 6.208968084e-16 -4.689863849e-16 5.808308622e-17
## [5] -5.743590597e-17 3.608046607e-17
print(Re(values2))
## [1] 4.667760776e+00 -2.526839801e-16 -2.526839801e-16 5.224724950e-16
## [5] 2.306287068e-17 0.000000000e+00
###########################################################################8
Pour comparer les VP on néglige les parties imaginaires, on peut le faire comme on a vu que dans notre cas ils sont négligeables. On voit bien ici aussi que le premier axe qui capte toute les inerties à la fois inertie totale (premiere matrice avec V) et aussi intraclasse (deuxieme matrice avec W).
###########################################################################8
vectors1 <- eig1$vectors
vectors2 <- eig2$vectors
print(Re(vectors1))
## [,1] [,2] [,3] [,4]
## [1,] 0.434101716963 0.21603403487 -0.17298132833 0.81516105371
## [2,] -0.005385163907 -0.01196803776 0.89969999614 0.29790971846
## [3,] 0.066528373900 -0.00844329546 0.26103445941 0.27676359534
## [4,] -0.886805199209 -0.64395990609 -0.12701436713 -0.40691682199
## [5,] -0.098092161425 0.73297278051 -0.02605426337 -0.05355257773
## [6,] -0.105143432167 -0.03437026321 -0.27507619652 0.04141243599
## [,5] [,6]
## [1,] 0.64287325012 -0.84146247353
## [2,] 0.05658188359 -0.23581917646
## [3,] -0.72804174144 -0.34693484428
## [4,] -0.17756615493 0.33109279052
## [5,] 0.03774964140 0.06390074047
## [6,] 0.14322333140 0.04754676558
print(Re(vectors2))
## [,1] [,2] [,3] [,4]
## [1,] 0.434101716963 0.67901817548 0.67901817548 -0.585657694569
## [2,] -0.005385163907 -0.17959846911 -0.17959846911 0.044280329964
## [3,] 0.066528373900 -0.03645136367 -0.03645136367 -0.009781040899
## [4,] -0.886805199209 -0.29634142369 -0.29634142369 -0.329452376044
## [5,] -0.098092161425 -0.03927776457 -0.03927776457 0.722746219723
## [6,] -0.105143432167 0.27290848623 0.27290848623 -0.155073151141
## [,5] [,6]
## [1,] -0.967074192470 -0.968851211342
## [2,] 0.001323680352 0.001480358119
## [3,] -0.052926322276 -0.018288360422
## [4,] 0.244669940628 0.243778889459
## [5,] 0.037385277320 0.026965108231
## [6,] 0.026523946373 0.028903471868
###########################################################################8
Pour comparer les VP on néglige les parties imaginaires, on peut le faire comme on a vu que dans notre cas ils sont négligeables. On voit ici que les coordonnées sur le premier axe est le même pour les 2 vecteurs propres des deux premiers valeurs propres des 2 matrices, ensuite ce n’est plus le cas. Cela souligne encore le rôle primordiale de ce premiere axe par rapport aux autres axes suivant qu’on peut négliger.
###########################################################################8
library(MASS)
variance_axes <- apply(projected_data, 2, var)
variance_total <- sum(apply(data_numeric_centree, 2, var))
mu_s <- variance_axes / variance_total
print(mu_s)
## [1] 0.12287982548 0.04028841455 0.08388998164 0.11344328055 0.08069067030
## [6] 0.13805197292
print(eigen_values)
## [1] 8.122405320e-01 7.289952361e-16 -3.184714044e-16 -2.220446049e-16
## [5] 1.364853982e-16 1.635271555e-18
###########################################################################8
Alors qu’une valeur propre écrase les autres, donc qu’un seul axe capte presque toute la variance, on pouvait s’attendre à avoir mu_s avec des valeurs qui écrasent aussi les autres (le premier axe qui écrase les autres), mais ce n’est pas le cas.
###########################################################################8
u1 <- res_centree$U
print(u1)
## LCB LSM LBM LP LM
## 0.520342621939 -0.006455008579 0.079745246692 -1.062982532604 -0.117579660418
## LAM
## -0.126031773282
###########################################################################8
###########################################################################8
library(MASS)
library(pander)
# Inverse de la matrice V
V_inv <- ginv(V_centree)
# Préparation du tableau pour les résultats
results <- data.frame(
Axe = integer(),
Quality_of_Projection = numeric(),
Absolute_Contribution_LOUP = numeric(),
Relative_Contribution_LOUP = numeric(),
Absolute_Contribution_CHIEN = numeric(),
Relative_Contribution_CHIEN = numeric()
)
# Calcul des indicateurs pour chaque axe (s) et chaque groupe (k)
for (s in 1:length(eigen_values)) {
# Qualité de la projection pour l'axe s
quality_projection <- eigen_values[s] / sum(eigen_values)
# Contribution absolue et relative du centre de gravité pour le groupe "Loup"
absolute_contribution_LOUP <- (t(eigen_vectors[,s]) %*% V_inv %*% gLOUP)^2
relative_contribution_LOUP <- absolute_contribution_LOUP / eigen_values[s]
# Contribution absolue et relative du centre de gravité pour le groupe "Chien"
absolute_contribution_CHIEN <- (t(eigen_vectors[,s]) %*% V_inv %*% gCHIEN)^2
relative_contribution_CHIEN <- absolute_contribution_CHIEN / eigen_values[s]
# Ajouter les résultats dans le tableau
results <- rbind(results, c(s, quality_projection, absolute_contribution_LOUP,
relative_contribution_LOUP, absolute_contribution_CHIEN,
relative_contribution_CHIEN))
}
# Nommer les colonnes du tableau
colnames(results) <- c("Axe", "Qualité de Projection", "Contribution Absolue (Loup)",
"Contribution Relative (Loup)", "Contribution Absolue (Chien)",
"Contribution Relative (Chien)")
# Afficher le tableau avec pander
pander(results)
| Axe | Qualité de Projection | Contribution Absolue (Loup) |
|---|---|---|
| 1 | 1 | 0.4718 |
| 2 | 8.975e-16 | 0.2006 |
| 3 | -3.921e-16 | 0.1663 |
| 4 | -2.734e-16 | 0.1954 |
| 5 | 1.68e-16 | 0.1945 |
| 6 | 2.013e-18 | 0.02113 |
| Contribution Relative (Loup) | Contribution Absolue (Chien) |
|---|---|
| 0.5809 | 2.949 |
| 2.752e+14 | 1.254 |
| -5.223e+14 | 1.04 |
| -8.801e+14 | 1.221 |
| 1.425e+15 | 1.216 |
| 1.292e+16 | 0.1321 |
| Contribution Relative (Chien) |
|---|
| 3.631 |
| 1.72e+15 |
| -3.264e+15 |
| -5.501e+15 |
| 8.907e+15 |
| 8.077e+16 |
###########################################################################8
La qualité de projection par nuage voit celui numéro 1 écraser les autres, car on a une VP qui écrase les autres.
###########################################################################8
X <- data_numeric
y <- data$GENRE
# Fonction pour calculer l'écart-type intra-classe et standardiser les données
standardize_intra_class <- function(X, y) {
X_standardized <- as.data.frame(matrix(nrow = nrow(X), ncol = ncol(X)))
colnames(X_standardized) <- colnames(X)
# Calculer l'écart-type pour chaque groupe et standardiser les variables
for (group in unique(y)) {
indices <- which(y == group)
X_group <- X[indices, ]
mean_group <- colMeans(X_group)
sd_group <- apply(X_group, 2, sd)
X_group_centered <- sweep(X_group, 2, mean_group, FUN = "-")
X_group_scaled <- sweep(X_group_centered, 2, sd_group, FUN = "/")
X_standardized[indices, ] <- X_group_scaled
}
return(X_standardized)
}
X_standardized <- standardize_intra_class(X, y)
head(X_standardized)
## LCB LSM LBM LP LM
## 1 -2.4466857377 -2.4724995592 2.2661406875 -1.4497678760 -2.3671687543
## 2 -1.5923960248 -1.8465503037 0.4417053882 0.1976956195 0.4658789570
## 3 -1.4557096708 -2.0343350803 -0.0384091642 -1.9769561945 -1.1395147461
## 4 0.6629288172 0.4694619416 1.5939803141 1.8451591149 1.5990980415
## 5 -0.3622188383 -0.6572467183 0.6337512092 0.0000000000 -0.4784702801
## 6 1.3805321760 0.9702213460 1.4979574036 0.8566810176 0.9380535755
## LAM
## 1 -1.2918998195
## 2 0.4320521637
## 3 -1.6111501868
## 4 1.3898032655
## 5 -1.1641996726
## 6 1.5813534858
library(dplyr)
AFD2<-function(X,y, centrerReduire = False){
if (centrerReduire) {
# Fonction pour calculer l'écart-type intra-classe et standardiser les données
standardize_intra_class(X, y)
}
n<-nrow(X)
p <- ncol(X)
K<-length(levels(factor(y)))
nk<-as.vector(table(y))
names(nk) <- levels(y)
pk<-nk/n
Xk <-list()
Xk <- split(X,y)
V<-var(X)*(n-1)/n
R<-cor(X)
g<-matrix(apply(X,2,mean),ncol=1)
rownames(g) <- colnames(X)
Vk<-list()
Rk<-list()
gk<-list()
for (k in 1:K){
gk[[k]]<-matrix(apply(Xk[[k]],2,mean),ncol=1)
rownames(gk[[k]]) <- colnames(X)
Vk[[k]]<-var(Xk[[k]])*(nk[k]-1)/nk[k]
Rk[[k]]<-cor(Xk[[k]])
}
names(Vk) <- levels(y)
names(Rk) <- levels(y)
names(gk) <- levels(y)
Xcent<-X-matrix(rep(1,n),ncol=1)%*%t(g)
W<-matrix(0,nrow=p,ncol=p)
B<-matrix(0,nrow=p,ncol=p)
for (k in 1:K){
W<-W+pk[k]*Vk[[k]]
B<-B+pk[k]*(gk[[k]]-g)%*%t(gk[[k]]-g)
}
# Calcul des FD :
res<-eigen(solve(V)%*%B)
eig <- Re(res$values[1:(K-1)])
UU<-Re(res$vectors[,1:(K-1)])
normes <- sqrt(diag(t(UU)%*%V%*%UU))
if (K>2) {
U <- sweep(UU,2,normes,"/")
} else {
U <- UU/normes
}
if (K>2) {
rownames(U) <- colnames(X)
colnames(U)<-paste("u",1:ncol(U),sep="")
} else
{
names(U) <- colnames(X)
}
# Calcul des VD :
S<-as.matrix(Xcent)%*%U
if (K>2) {
colnames(S) <-paste("s",1:ncol(S),sep="")
rownames(S)<-rownames(X)
} else names(S)<-rownames(X)
lambda <- 0.05
V_reg <- V + lambda * diag(nrow(V))
V_invB <- solve(V_reg) %*% B
eigen_values <- eigen(V_invB)$values
eigen_vectors <- eigen(V_invB)$vectors
gLOUP <- data.frame(gk)[,1]
gCHIEN <- data.frame(gk)[,2]
V_inv <- ginv(V)
results <- data.frame(
Axe = integer(),
Quality_of_Projection = numeric(),
Absolute_Contribution_LOUP = numeric(),
Relative_Contribution_LOUP = numeric(),
Absolute_Contribution_CHIEN = numeric(),
Relative_Contribution_CHIEN = numeric()
)
# Calcul des indicateurs pour chaque axe (s) et chaque groupe (k)
for (s in 1:length(eigen_values)) {
# Qualité de la projection pour l'axe s
quality_projection <- eigen_values[s] / sum(eigen_values)
# Contribution absolue et relative du centre de gravité pour le groupe "Loup"
absolute_contribution_LOUP <- (t(eigen_vectors[,s]) %*% V_inv %*% gLOUP)^2
relative_contribution_LOUP <- absolute_contribution_LOUP / eigen_values[s]
# Contribution absolue et relative du centre de gravité pour le groupe "Chien"
absolute_contribution_CHIEN <- (t(eigen_vectors[,s]) %*% V_inv %*% gCHIEN)^2
relative_contribution_CHIEN <- absolute_contribution_CHIEN / eigen_values[s]
# Ajouter les résultats dans le tableau
results <- rbind(results, c(s, quality_projection, absolute_contribution_LOUP,
relative_contribution_LOUP, absolute_contribution_CHIEN,
relative_contribution_CHIEN))
}
colnames(results) <- c("Axe", "Qualité de Projection", "Contribution Absolue (Loup)",
"Contribution Relative (Loup)", "Contribution Absolue (Chien)",
"Contribution Relative (Chien)")
list(eig=eig,U=U,S=S,nk=nk,K=K,y=y,X=X,Xk=Xk,W=W,B=B,g=data.frame(g=g),gk=data.frame(gk),V=V,R=R,Vk=Vk,Rk=Rk,results=results)
}
data <- as.data.frame(data)
data_numeric <- data[,2:7]
y <- data[,8]
res3 = AFD2(X,y,centrerReduire = TRUE)
head(res3$results)
## Axe Qualité de Projection Contribution Absolue (Loup)
## 1 1 1.000000000e+00 0.46080241880
## 2 2 3.524455466e-16 0.03128179755
## 3 3 -3.111227065e-16 0.06090065317
## 4 4 1.434705176e-16 0.18964205618
## 5 5 -3.817216460e-17 0.09683025685
## 6 6 1.788391896e-17 0.04328993358
## Contribution Relative (Loup) Contribution Absolue (Chien)
## 1 5.954800078e-01 2.8800151175
## 2 1.146970133e+14 0.1955112347
## 3 -2.529546560e+14 0.3806290823
## 4 1.708143787e+15 1.1852628511
## 5 -3.278058738e+15 0.6051891053
## 6 3.128071428e+15 0.2705620849
## Contribution Relative (Chien)
## 1 3.721750049e+00
## 2 7.168563330e+14
## 3 -1.580966600e+15
## 4 1.067589867e+16
## 5 -2.048786712e+16
## 6 1.955044643e+16
head(results)
## Axe Qualité de Projection Contribution Absolue (Loup)
## 1 1 1.000000000e+00 0.47182064600
## 2 2 8.975115220e-16 0.20062811863
## 3 3 -3.920900175e-16 0.16633470430
## 4 4 -2.733729680e-16 0.19541878698
## 5 5 1.680356900e-16 0.19450385772
## 6 6 2.013284846e-18 0.02113398396
## Contribution Relative (Loup) Contribution Absolue (Chien)
## 1 5.808878373e-01 2.9488790375
## 2 2.752118377e+14 1.2539257414
## 3 -5.222908619e+14 1.0395919019
## 4 -8.800879762e+14 1.2213674186
## 5 1.425089132e+15 1.2156491107
## 6 1.292383757e+16 0.1320873998
## Contribution Relative (Chien)
## 1 3.630548983e+00
## 2 1.720073986e+15
## 3 -3.264317887e+15
## 4 -5.500549851e+15
## 5 8.906807075e+15
## 6 8.077398483e+16
print(res3$eig)
## [1] 0.8235634778
print(res_centree$eig)
## [1] 0.8235634778
print(res3$U)
## LCB LSM LBM LP LM
## 0.520342621939 -0.006455008579 0.079745246692 -1.062982532604 -0.117579660418
## LAM
## -0.126031773282
print(res_centree$U)
## LCB LSM LBM LP LM
## 0.520342621939 -0.006455008579 0.079745246692 -1.062982532604 -0.117579660418
## LAM
## -0.126031773282
###########################################################################8
On observe que pour l’axe 1, les résultat entre CENTREE ET CENTREE REDUITS sont les mêmes : car on a la même valeur propres entre les 2 et le même LD1.
En effet, on divise les donnees selon les classes et non selon la méthode classique comme en ACP.
###########################################################################8
calculate_correlations <- function(eigen_vectors, eigen_values) {
eigen_vectors <- eigen_vectors[,1:2]
eigen_values <- eigen_values[1:2]
correlations <- sweep(eigen_vectors, 2, sqrt(eigen_values), FUN = "*")
return(correlations)
}
correlations <- calculate_correlations(eigen_vectors, eigen_values)
variable_names <- c('Var1', 'Var2', 'Var3', 'Var4', 'Var5', 'Var6')
correlation_df <- data.frame(Variable = variable_names, correlations)
pander(correlation_df)
| Variable | X1 | X2 |
|---|---|---|
| Var1 | -0.3676 | -7.442e-09 |
| Var2 | -0.0311 | -2.813e-10 |
| Var3 | -0.0667 | -2.124e-09 |
| Var4 | 0.8053 | 1.803e-08 |
| Var5 | 0.1122 | -1.854e-08 |
| Var6 | 0.103 | 3.787e-10 |
###########################################################################8
On voit que les coefficients de corrélation avec les différentes variables sont non négligeable seulement dans le cas du premier axe factorielle. Ceci est en cohérence avec nos résultats précédents sur les différents axes factorielles et que le premier écrase les autres.
###########################################################################8
project_on_factors <- function(variables, correlations) {
projection <- variables %*% correlations[, 1:2]
return(projection)
}
projection <- project_on_factors(as.matrix(X_standardized), correlations)
# Cercle de corrélation
plot_correlation_circle <- function(correlations) {
plot(correlations[,1], correlations[,2], type = 'n')
text(correlations[,1], correlations[,2], labels = colnames(X_standardized), cex = 0.7)
abline(h = 0, v = 0, col = "gray")
circle_radius <- sqrt(max(correlations[,1]^2 + correlations[,2]^2))
symbols(0, 0, circles = circle_radius, add = TRUE, inches = FALSE, lty = 2) # fait un circle
}
plot_correlation_circle(correlations)
###########################################################################8
On voit ici que c’est la variable LP qui est la plus discriminante, les variables LBM et LSM sont celles qui le sont le moins. (On raisonne uniquement en 1D selon le premiere axe)
###########################################################################8