O presente trabalho tem como finalidade apresentar e discutir aplicações de alguns métodos de classificação, no caso: Regressão Logística, Discriminante Linear e Quadrático de Fisher e extensões.
Pacotes utilizados:
require(MASS)
require(xtable)
require(lattice)
require(hmeasure)
require(klaR)
require(ggplot2)
require(gridExtra)
require(pROC)
O objetivo é encontrar uma regressão para a chance de ser aprovado em uma universidade dados suas notas em exames anteriores. Os dados referem-se a históricos de candidatos as vagas com suas notas anteriores e o resultado deles na universidade.
Visualização do comportamento das notas nos dois exames.
plot(exemplo[,1], exemplo[,2], las = 1,
col = ifelse(exemplo$status==0,"red","blue"),
pch = 20, xlab="Exame 1",ylab="Exame 2")
legend(x=85, y = 104 ,c("Aprovado","Reprovado"),
pch = 20, col=c("blue","red"), bty ="n")
A função logística é dada por:
\[g(z) = \frac{1}{1+e^{-z}}\]
Com isso teremos valores entre 0 e 1.
sigmoid<- function(z) {
return(1/(1 + exp(-z)))
}
A função custo para um grupo de paramêtros será
\[J(\theta)= \frac{1}{m} \sum\limits_{i=1}^m [-y^{(i)}log(h_\theta(x^{(i)}))-(1-y^{(i)})log(1-h_{\theta}(x^{(i)}))]\]
e o gradiente do custo será um vetor de tamanho igual a \(\theta\) onde o \(j\) é o ésimo elemento (j=0,1, . , n):
\[\frac{\partial J(\theta)}{\partial \theta_J} = \frac{1}{m} \sum\limits_{i=1}^m (h_{\theta}(x^{(i)})-y^{(i)})x^{(i)}_{j}\]
Com isso geramos a função costFunction
. Essa função retornará o custo de usar esse conjunto de parâmetros.
#Parâmetros de entrada
X <- as.matrix( cbind(1, exemplo[, 1:2])) # Matriz das variáveis
theta <- matrix(0, nrow = ncol(exemplo[, 1:2]) + 1, ncol = 1)
y <- exemplo[, 3] # Resposta
#Função de custo
costFunction<- function(theta, X, y) {
m <- length(y)
J <- 0
grad <- matrix(0,nrow=length(theta)+1,ncol=1)
h <- sigmoid(X %*% theta)
costPos <- t(-y) %*% log(h)
costNeg <- (1 - t(y)) %*% log(1 - h)
J = (1/m) * (costPos - costNeg)
grad = (1/m) * (t(X) %*% (h - y))
return(c(J))
}
costFunction(theta, X, y)
## [1] 0.6931472
O objetivo é escolher o grupo de parâmetros, que vai gerar o menor custo, e o maior verossimil. Utilizando optim
, que é uma função de otimização de uso geral baseado em algoritmos de gradiente.
#Ajuste da regressão
ajuste<-optim(c(0,0,0),function(theta)
{costFunction(theta,X,y)},method="Nelder-Mead")
ajuste
## $par
## [1] -25.1647048 0.2062524 0.2015046
##
## $value
## [1] 0.2034977
##
## $counts
## function gradient
## 156 NA
##
## $convergence
## [1] 0
##
## $message
## NULL
#Custo
costFunction(matrix(ajuste$par,
nrow = ncol(exemplo [, 1:2])+ 1, ncol = 1), X, y)
## [1] 0.2034977
Na saída da função, temos os valores finais de parâmetros no par, o J no value e o total de iterações em counts. Em convergence, 0 indica se a conclusão foi bem sucedida.
Verificando ajuste gerado pela função com o ajuste gerado pela função glm.
ajuste$par #Ajuste pela função
## [1] -25.1647048 0.2062524 0.2015046
glm(status ~ exame1 + exame2,
data = exemplo ,family = "binomial") #Ajuste glm
##
## Call: glm(formula = status ~ exame1 + exame2, family = "binomial",
## data = exemplo)
##
## Coefficients:
## (Intercept) exame1 exame2
## -25.1613 0.2062 0.2015
##
## Degrees of Freedom: 99 Total (i.e. Null); 97 Residual
## Null Deviance: 134.6
## Residual Deviance: 40.7 AIC: 46.7
Observa-se que os valores ajustados pela função coincidem com os valores gerados pelo glm.
No gráfico, temos de um lado temos os indivíduos que esperamos que serão aprovados, e do outro o que esperamos que não serão.
x1 <- c(min(X[,2])-2,max(X[,2])+2)
y1 <- (-1/ajuste$par[3] ) * (ajuste$par[2] * x1 + ajuste$par[1] )
plot(exemplo[,1], exemplo[,2],
col = ifelse(exemplo$status==0, "red", "blue"),
pch=19, xlab = "Exame 1", ylab = "Exame 2",
ylim=c(30,110))
lines(x1, y1, lty = 2, lwd=2 ,col="black")
legend(x = 83, y = 115,c("Aprovado","Reprovado","Margem"),
pch = c(19,19,NA), lty = c(0,0,2), lwd=2,
col = c("blue","red","black"), bty = "n")
Com a função encontrada, podemos prever alguns resultados. Se um indivíduo tem suas notas anteriores a 80, ele terá 99% de chance de ser aprovado nessa universidade. E assim por diante para os demais casos.
# Indivíduo com nota 80 e nota 80
sigmoid(ajuste$par[1] + ajuste$par[2] * 80 + ajuste$par[3] * 80)
## [1] 0.9994223
Algumas outras previsões. Para um indivíduo com nota 90 na primeira prova, e 40 na segunda, tem 81% de chance de ser aprovado.
# Indivíduo com nota 90 e nota 40
sigmoid(ajuste$par[1] + ajuste$par[2] * 90 + ajuste$par[3] * 40)
## [1] 0.8112565
Já para o indivíduo com nota 70 na primeira prova, e 30 na segunda, terá 34% de chance de ser aprovado.
# Indivíduo com nota 70 e nota 50
sigmoid(ajuste$par[1] + ajuste$par[2] * 70 + ajuste$par[3] * 50)
## [1] 0.3425826
E aquele com notas anteriores igual a 50, terá 8% de chance de ser aprovado.
# Indivíduo com nota 50 e nota 50
sigmoid(ajuste$par[1] + ajuste$par[2] * 50 + ajuste$par[3] * 50)
## [1] 0.008352106
Retirado Recologia
A análise descriminante basea-se na idéia bayesiana, de que temos como informação \(f(\textbf{X}=\textbf{x}|Y=k)\), com \(\textbf{X}\) um vetor de variáveis aleatórias e \(Y\) uma variável nominal com k
níveis. A ideia é obter um classificador a partir de dados de treino, e predizer a classificação de um objeto ou indivíduo a partir de um conjunto de variáveis \(\textbf{X}\). Ou seja, queremos \(f(Y=k|\textbf{X}=x)\), então utiliza-se a regra de Bayes
de forma: \(f(Y=k|\textbf{X}=x) \propto f(\textbf{X} \textbf{x}|Y) \pi(Y)\). A análise discriminante de Fisher, tradicionalmente pressupõe que \(\textbf{X}|Y=k \sim NM(\boldsymbol{\mu}_k, \boldsymbol{\Sigma}_k)\).
\(\pi(Y)\) é uma probabilidade à priori de classificação. Quando não se tem conhecimento desta probabilidade, utiliza-se a proporção de observações contidas em cada classe, que seria equivalente uma priori do tipo flat
.
Depois de obtido um classificador com os dados de treino, nós queremos saber, a partir de novos objetos mensurados \(\textbf{x_1, x_2, ..., x_n}\), quais as suas classificações. Deste modo, a ideia é identificar a classe k
da variável \(Y\) que maximiza \(f(\textbf{X} \textbf{x}|Y) \pi(Y)\), parecida com a idéia de TRV
.
Quando a \(f(\textbf{X} \textbf{x}|Y) \) é assumido distribuição normal, chamamos de discriminante de Fisher. Queremos o \(k\) que maximize,então:
\[\delta_k(k) \propto \text{ argmax } \pi_k(k) f_k(x)\].
Passando o logarítimo tem-se:
\[=\text{ argmax } \left \{ \log{\pi_k} - \frac{1}{2}\log{\mid \boldsymbol{\Sigma}_k \mid} - \frac{1}{2} (\textbf{x} - \boldsymbol{\mu}_k){}' \boldsymbol{\Sigma}_k^{-1} (\textbf{x} - \boldsymbol{\mu}_k)\right \}\]
Um exemplo seria um estudo para saber se o indivíduo tem ou não determinado tipo de câncer, realizado com n indivíduos, na qual estes foram submetidos ao exame padrão ouro
. Neste mesmo estudo, foram registradas diversas variáveis a respeito do paciente, como idade, sexo, taxa colesterol, entre outras. A partir desta classificação à priori
, com os dados de novos indivíduos na qual não foram submetidos ao exame padrão ouro
, utiliza-se as variáveis de mais fácil mensuração para predizer se tem ou não o câncer.
Alguns outros exemplos como:
Classificar vasos de porcelana chinenses conforme o período histórico ou dinastia, a partir de variáveis de medidas como, altura, largura, tipos de desenhos e etc.
Classificar um indivíduo tendo ou não x patologia a partir de medidas de um desenho feito em sessão.
Classificar o indivíduo em bom ou mau pagador a partir de informações socioeconômicas do mesmo.
Ocorre quando \(\boldsymbol{\Sigma}_i = \boldsymbol{\Sigma}_j \text{, } \forall i \neq j\), com \(i \text{, }j \in k\)
Utilizando a função lda()
do pacote MASS
para realizar a análise discriminante linear de Fisher. A planilha de dados foi dividida em duas partes, a primeira contendo 50 observações para treino
e outras 50 para teste
.
set.seed(56567567)
k<- sample(100,50)
treino<- exemplo[k,]
teste<- exemplo[-k,]
fit1<- lda(status~.,data=exemplo,subset = k)
PredVC<- predict(fit1,teste)
A função lda()
permite incluir fórmula da variável resposta \(\sim\) as variáveis explanatórias, funciona da mesma maneira que no lm()
ou glm()
. Existe a opção de mudar as proporções à priori
, se não declaradas, são usadas as proporções de observações em cada classe.
Na predição, existem três alternativas: declar por fora dividindo a base de dados de treino
e teste
e ajustando pela primeira;usando o argumento subset
que serve para declarar as linhas da base de dados que serão utilizadas para o ajuste; e uma terceira opção é utilizar o argumento CV=T
que realiza validação cruzada pelo método Leave-one-out
.
Tabela de contingência dos preditos versus observados:
tc <- table(teste$status, PredVC$class)
dimnames(tc) <- list(Observados = c("Reprovado", "Aprovado"), "Predictos (cv)" = c("Reprovado", "Aprovado"))
print(round(tc))
## Predictos (cv)
## Observados Reprovado Aprovado
## Reprovado 13 4
## Aprovado 4 29
A tabela de contingência é construída por meio do cruzamento das classes dos valores observados e preditos. Como no exemplo existem duas classes (Aprovado
ou Reprovado
), então, existem 4 cenários possíveis:
Predito como Reprovado
sendo que defato o indivíduo Reprovou
,
Classificar como Aprovado
dado que o indivíduo foi Aprovado
(as duas anteriores consistem os acertos, sempre na diagonal),
Classificar como Reprovado
sendo que na verdade o indivíduo foi Aprovado
Classificar como Aprovado
sendo que na realidade o indivíduo veio a Reprovar
.
A partir desta configuração, são dispostas as contagens em uma tabela conforme cada um dos cenários anteriores.
Tabela de proporções de acertos e erros
round(prop.table(tc, 1),3)
## Predictos (cv)
## Observados Reprovado Aprovado
## Reprovado 0.765 0.235
## Aprovado 0.121 0.879
Disposta na forma de proporção por linha (observados), ou seja, a proporção de classificação correta como Reprovado
foi de aproximadamente \(95 \%\), enquanto a porporção de classificação correta de Aprovado
foi de \(85 \%\).
Proporção geral de acertos:
sum(diag(prop.table(tc)))
## [1] 0.84
Essa é a proporção geral de acertos, que basicamente é a proporção de elementos na diagonal em relação ao total.
Gráfico dos preditos:
###############################################
densityplot(~PredVC$x, groups=teste$status,bw=1,xlab="Discriminante",ylab="Densidade")
ldahist(PredVC$x[,1],g=teste$status)
title("Discriminante 1")
O primeiro gráfico mostra a densidade estimada dos valores preditos em cada classe, já o segundo, é o gráfico de cima, porém, em abcissas diferentes, e serve para visualizar a intersecção e a forma de divisão feita por cada discriminante.
Estudando a sensibilidade da priori
. Foi usada uma sequência de 9 proporções diferentes para declarar como priori, do resultado da predição foram extraídas as proporções de acertos por classe e a proporção geral.
Priori no primeiro exemplo
fit1$prior
## 0 1
## 0.46 0.54
priorVals<- matrix(rbind(seq(0.1,0.9,by=0.1),1-seq(0.1,0.9,by=0.1)),ncol=2,byrow = T)
results<-list()
tcpriori2<- list()
for(i in 1:9){
fit1priori2<- lda(status~.,data=treino,prior=priorVals[i,])
PredVCpriori2<- predict(fit1priori2,teste)
tcpriori2[[i]] <- table(teste$status, PredVCpriori2$class)
dimnames(tcpriori2[[i]]) <- list(Observados = c("Reprovado", "Aprovado"), "Predictos (cv)" = c("Reprovado", "Aprovado"))
results[[i]]<- data.frame(priori=priorVals[i,],propClass=round(diag(prop.table(tcpriori2[[i]],1)),2),propGeral=sum(diag(prop.table(tcpriori2[[i]]))))
}; results
## [[1]]
## priori propClass propGeral
## Reprovado 0.1 0.65 0.88
## Aprovado 0.9 1.00 0.88
##
## [[2]]
## priori propClass propGeral
## Reprovado 0.2 0.76 0.9
## Aprovado 0.8 0.97 0.9
##
## [[3]]
## priori propClass propGeral
## Reprovado 0.3 0.76 0.88
## Aprovado 0.7 0.94 0.88
##
## [[4]]
## priori propClass propGeral
## Reprovado 0.4 0.76 0.86
## Aprovado 0.6 0.91 0.86
##
## [[5]]
## priori propClass propGeral
## Reprovado 0.5 0.76 0.82
## Aprovado 0.5 0.85 0.82
##
## [[6]]
## priori propClass propGeral
## Reprovado 0.6 0.88 0.86
## Aprovado 0.4 0.85 0.86
##
## [[7]]
## priori propClass propGeral
## Reprovado 0.7 0.94 0.88
## Aprovado 0.3 0.85 0.88
##
## [[8]]
## priori propClass propGeral
## Reprovado 0.8 0.94 0.78
## Aprovado 0.2 0.70 0.78
##
## [[9]]
## priori propClass propGeral
## Reprovado 0.9 0.94 0.78
## Aprovado 0.1 0.70 0.78
Pelas tabelas acima, nota-se que conforme muda a informação à priori
, as proporções de acertos mudam bastante, devido, também ao conjunto de dados pequeno. Na função qda()
, essa mudança das proporções ocorre em uma magnitude muito menor, por estar incluindo mais informações da amostra através do termo quadrático.
A função quadrática ocorre quando \(\boldsymbol{\Sigma}_i \neq \boldsymbol{\Sigma}_j\), ou seja, terá o termo quadrático \(\textbf{x}{}' \boldsymbol{\Sigma_k}^{-1} \textbf{x}\), com \(k\) a classe.
fit1Q<- qda(status~.,data=exemplo,subset = k)
PredQVC<-predict(fit1Q,teste)
Tabela de contingência dos preditos versus observados:
tcQ <- table(teste$status, PredQVC$class)
dimnames(tcQ) <- list(Observados = c("Reprovado", "Aprovado"), "Predictos (cv)" = c("Reprovado", "Aprovado"))
print(round(tcQ))
## Predictos (cv)
## Observados Reprovado Aprovado
## Reprovado 14 3
## Aprovado 5 28
Proporção de acertos em cada grupo
round(prop.table(tcQ, 1),3)
## Predictos (cv)
## Observados Reprovado Aprovado
## Reprovado 0.824 0.176
## Aprovado 0.152 0.848
Proporção geral de acertos:
sum(diag(prop.table(tcQ)))
## [1] 0.84
Comparando com o resultado obtido pela discriminante linear (lda()
), obtivemos um pequeno ganho na proporção de Aprovados
ao considerar o termo quadrático, ou seja, matrizes de covariâncias das variáveis diferentes entre os grupos.
Pode-se dizer que a análise discriminante quadrática é mais geral, no sentido de considerar matrizes de covariâncias das variáveis explanatórias diferentes, tendo assim, o termo quadrático. A análise discriminante linear é um caso particular, onde é pressuposto que estas matrizes de covariâncias sejam iguais para todas as classes. Porém, podemos flexibilizar isto incluindo um parâmetro ponderador:
\[\boldsymbol{\hat{\Sigma}}_k(\lambda) = (1- \lambda)\boldsymbol{\hat{\Sigma}}_k + \lambda \boldsymbol{\hat{\Sigma}} \]
Além disso, se assumisse independência entre as variáveis, ou seja, matrizes de covariâncias apenas com valores nas diagonais, teríamos um caso particular da análise discriminante de Fisher, conhecido como Naive Bayes
. Usando também esta idéia, a análise discriminante regularizada também flexibiliza neste sentido, adicionando um parâmetro \(\gamma\), ou seja:
\[\boldsymbol{\hat{\Sigma}}_k(\lambda, \gamma) = (1- \gamma)\boldsymbol{\hat{\Sigma}}_k (\lambda) + \gamma \frac{1}{d} tr \left [\boldsymbol{\hat{\Sigma}}_k (\lambda)\right ]\textbf{I} \].
Os parâmetros \(\lambda\) e \(\gamma\) variam de 0 a 1, o primeiro flexibiliza quanto matrizes de covariâncias diferentes entre as classes, o segundo flexibiliza quanto a dependência entre as variáveis explicativas. No caso, se \(\lambda=0\) e \(\gamma=0\), temos o caso da análise discriminante quadrática, se \(\lambda=0\) e \(\gamma=1\) temos a análise discriminante linear. Na função rda()
do pacote klaR
, temos os argumentos das funções anteriores, mais a opção de fixar o valor dos parâmetros \(\lambda\) e \(\gamma\), assim como podemos estimá-los, afim de que os dados decidam a melhor ponderação.
Foram considerados três casos, primeiro a análogas da discriminante lineare posteriormente a quadrática, e o terceiro é estimando os parâmetros de ponderação.
fitRLDA<- rda(status~.,data = treino,gamma = 0,lambda = 1)
PredRLDA<- predict(fitRLDA,teste[,1:2])
fitRQDA<- rda(status~.,data = treino,gamma = 0,lambda = 0)
PredRQDA<- predict(fitRQDA,teste[,1:2])
fitREst<- rda(status~.,data = treino)
PredREst<- predict(fitREst,teste[,1:2])
Tabela de contingência dos preditos versus observados:
tcRLDA <- table(teste$status, PredRLDA$class)
dimnames(tcRLDA) <- list(Observados = c("Reprovado", "Aprovado"), "Predictos (cv)" = c("Reprovado", "Aprovado"))
print(round(tcRLDA))
## Predictos (cv)
## Observados Reprovado Aprovado
## Reprovado 13 4
## Aprovado 4 29
tcRQDA <- table(teste$status, PredRQDA$class)
dimnames(tcRQDA) <- list(Observados = c("Reprovado", "Aprovado"), "Predictos (cv)" = c("Reprovado", "Aprovado"))
print(round(tcRQDA))
## Predictos (cv)
## Observados Reprovado Aprovado
## Reprovado 14 3
## Aprovado 5 28
tcREst <- table(teste$status, PredREst$class)
dimnames(tcREst) <- list(Observados = c("Reprovado", "Aprovado"), "Predictos (cv)" = c("Reprovado", "Aprovado"))
print(round(tcREst))
## Predictos (cv)
## Observados Reprovado Aprovado
## Reprovado 14 3
## Aprovado 4 29
Proporção de acertos em cada grupo
round(prop.table(tcRLDA, 1),3)
## Predictos (cv)
## Observados Reprovado Aprovado
## Reprovado 0.765 0.235
## Aprovado 0.121 0.879
round(prop.table(tcRQDA, 1),3)
## Predictos (cv)
## Observados Reprovado Aprovado
## Reprovado 0.824 0.176
## Aprovado 0.152 0.848
round(prop.table(tcREst, 1),3)
## Predictos (cv)
## Observados Reprovado Aprovado
## Reprovado 0.824 0.176
## Aprovado 0.121 0.879
Proporção geral de acertos:
sum(diag(prop.table(tcRLDA)))
## [1] 0.84
sum(diag(prop.table(tcRQDA)))
## [1] 0.84
sum(diag(prop.table(tcREst)))
## [1] 0.86
Nota-se que os resultados dos modelos análogos ao discriminante linear (lda()
) e quadrático (qda()
) foram os mesmos, e estimando os parâmetros obtem-se o mesmo resultado da quadrática (neste exemplo).
fit<- glm(status ~ exame1 + exame2,
data = treino ,family = "binomial")
predGLM<- predict(fit,teste,type="response")
contour_data <- expand.grid(exame1 = seq(0, 100, length = 200),
exame2 = seq(0, 100, length = 200))
logistic_predict<- data.frame(contour_data,
status = as.numeric(ifelse(predict(fit, contour_data,type="response")>0.5,1,0)))
lda_predict <- data.frame(contour_data,
status = as.numeric(predict(fit1, contour_data)$class))
qda_predict <- data.frame(contour_data,
status = as.numeric(predict(fit1Q, contour_data)$class))
rda_predict <- data.frame(contour_data,
status = as.numeric(predict(fitREst, contour_data)$class))
p <- ggplot(teste, aes(x = exame1, y = exame2, color = status)) + geom_point()
v1<- p + stat_contour(aes(x = exame1, y = exame2, z = status), data = logistic_predict)+ggtitle("Reg. Logistica")
v2<- p + stat_contour(aes(x = exame1, y = exame2, z = status), data = lda_predict)+ggtitle("LDA")
v3<- p + stat_contour(aes(x = exame1, y = exame2, z = status), data = qda_predict)+ggtitle("QDA")
v4<- p + stat_contour(aes(x = exame1, y = exame2, z = status), data = rda_predict)+ggtitle("RDA")
grid.arrange(v1,v2,v3,v4,ncol=2)
HRL<- roc(teste$status,predGLM)
HLDL<- roc(teste$status,PredVC$posterior[,2])
HLDQ<- roc(teste$status,PredQVC$posterior[,2])
HRD<- roc(teste$status,PredREst$posterior[,2])
par(mfrow=c(2,2))
plot.roc(HRL,print.auc = T,auc.polygon.col = "blue",max.auc.polygon = T,print.thres = T,main="Reg. Logística")
##
## Call:
## roc.default(response = teste$status, predictor = predGLM)
##
## Data: predGLM in 17 controls (teste$status 0) < 33 cases (teste$status 1).
## Area under the curve: 0.9572
plot.roc(HLDL,print.auc = T,auc.polygon.col = "blue",max.auc.polygon = T,print.thres = T,main="LDA")
##
## Call:
## roc.default(response = teste$status, predictor = PredVC$posterior[, 2])
##
## Data: PredVC$posterior[, 2] in 17 controls (teste$status 0) < 33 cases (teste$status 1).
## Area under the curve: 0.9519
plot.roc(HLDQ,print.auc = T,auc.polygon.col = "blue",max.auc.polygon = T,print.thres = T,main="QDA")
##
## Call:
## roc.default(response = teste$status, predictor = PredQVC$posterior[, 2])
##
## Data: PredQVC$posterior[, 2] in 17 controls (teste$status 0) < 33 cases (teste$status 1).
## Area under the curve: 0.959
plot.roc(HRD,print.auc = T,auc.polygon.col = "blue",max.auc.polygon = T,print.thres = T,main="RDA")
##
## Call:
## roc.default(response = teste$status, predictor = PredREst$posterior[, 2])
##
## Data: PredREst$posterior[, 2] in 17 controls (teste$status 0) < 33 cases (teste$status 1).
## Area under the curve: 0.959
Aplicando a LDA para o conjunto de dados wine
do R
. O Conjunto de dados wine
do pacote rattle
, possui 13 variáveis de características de 178 observações de 3 tipos de cultivos de vinho diferentes. A ideia é achar um classificador em um dos três tipos segundo as características das variáveis apresentadas.
data(wine, package='rattle')
t1<- xtable(head(wine))
print(t1,type = "html")
Type | Alcohol | Malic | Ash | Alcalinity | Magnesium | Phenols | Flavanoids | Nonflavanoids | Proanthocyanins | Color | Hue | Dilution | Proline | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | 1 | 14.23 | 1.71 | 2.43 | 15.60 | 127 | 2.80 | 3.06 | 0.28 | 2.29 | 5.64 | 1.04 | 3.92 | 1065 |
2 | 1 | 13.20 | 1.78 | 2.14 | 11.20 | 100 | 2.65 | 2.76 | 0.26 | 1.28 | 4.38 | 1.05 | 3.40 | 1050 |
3 | 1 | 13.16 | 2.36 | 2.67 | 18.60 | 101 | 2.80 | 3.24 | 0.30 | 2.81 | 5.68 | 1.03 | 3.17 | 1185 |
4 | 1 | 14.37 | 1.95 | 2.50 | 16.80 | 113 | 3.85 | 3.49 | 0.24 | 2.18 | 7.80 | 0.86 | 3.45 | 1480 |
5 | 1 | 13.24 | 2.59 | 2.87 | 21.00 | 118 | 2.80 | 2.69 | 0.39 | 1.82 | 4.32 | 1.04 | 2.93 | 735 |
6 | 1 | 14.20 | 1.76 | 2.45 | 15.20 | 112 | 3.27 | 3.39 | 0.34 | 1.97 | 6.75 | 1.05 | 2.85 | 1450 |
Dividiu-se o conjunto de dados em dois, uma parte contendo 60 observações para treino
e as outras 118 observações para teste
.
kv<- sample(178,60)
testeWine<- wine[-kv,]
fit2<- lda(Type ~.,data=wine,subset = kv)
PredCV2<- predict(fit2,testeWine)
A partir da predição, serão extraídas informações sobre a qualidade da predição da discriminação obtida.
Tabela de contingência dos preditos versus observados:
tc2 <- table(testeWine$Type, PredCV2$class)
dimnames(tc2) <- list(Observados = as.character(unique(wine$Type)), "Predictos (cv)" = as.character(unique(wine$Type)))
print(round(tc2))
## Predictos (cv)
## Observados 1 2 3
## 1 39 0 0
## 2 1 44 3
## 3 0 0 31
Proporção de acertos em cada grupo
round(prop.table(tc2, 1),3)
## Predictos (cv)
## Observados 1 2 3
## 1 1.000 0.000 0.000
## 2 0.021 0.917 0.062
## 3 0.000 0.000 1.000
Proporção geral de acertos:
sum(diag(prop.table(tc2)))
## [1] 0.9661017
Gráfico dos preditos:
###############################################
#Primeira discriminante
ldahist(PredCV2$x[,1],g=testeWine$Type)
title("Discriminante 1")
#Segunda discriminante
ldahist(PredCV2$x[,2],g=testeWine$Type)
title("Discriminante 2")
####################
# Ou de forma sememlhante
densityplot(~PredCV2$x[,1], groups=testeWine$Type,bw=0.4,auto.key = T,xlab="Discriminante 1",ylab="Densidade")
densityplot(~PredCV2$x[,2], groups=testeWine$Type,bw=0.4,auto.key = T,xlab="Discriminante 2",ylab="Densidade")
Pelos gráficos acima, pode-se concluir que a primeira discriminante
conseguiu separar muito bem a primeira classe de cultivo das demais e de forma razoável a segunda da terceira, já, a segunda discriminante
separa os cultivos das classes 1 e 3 da segunda, conforme os gráficos mostrados acima.
Para a base de dados wine
, temos:
fitQda<- qda(Type ~.,data=wine,subset=kv)
PredQda<- predict(fitQda,testeWine)
Tabela de contingência dos preditos versus observados:
tcQda <- table(testeWine$Type, PredQda$class)
dimnames(tcQda) <- list(Observados = as.character(unique(wine$Type)), "Predictos (cv)" = as.character(unique(wine$Type)))
print(round(tcQda))
## Predictos (cv)
## Observados 1 2 3
## 1 19 20 0
## 2 1 47 0
## 3 0 7 24
Proporção de acertos em cada grupo
prop.table(tcQda, 1)
## Predictos (cv)
## Observados 1 2 3
## 1 0.48717949 0.51282051 0.00000000
## 2 0.02083333 0.97916667 0.00000000
## 3 0.00000000 0.22580645 0.77419355
Proporção geral de acertos:
sum(diag(prop.table(tcQda)))
## [1] 0.7627119
No primeiro exemplo, tivemos um pequeno ganho na predição considerando as matrizes de covariâncias das variáveis explicativas diferentes entre os grupos, porém, para este segundo exemplo, observou-se uma perda ao considerar o termo quadrático, significando que seu acréscimo acaba correndo
muito atrás dos dados.
Para o segundo conjunto de dados teremos:
fitRLDA2<- rda(Type~.,data = wine[kv,],gamma = 0,lambda = 1)
PredRLDA2<- predict(fitRLDA2,testeWine)
fitRQDA2<- rda(Type~.,data = wine[kv,],gamma = 0,lambda = 0)
PredRQDA2<- predict(fitRQDA2,testeWine)
fitREst2<- rda(Type~.,data = wine[kv,])
PredREst2<- predict(fitREst2,testeWine)
Tabela de contingência dos preditos versus observados:
tcRLDA2 <- table(testeWine$Type, PredRLDA2$class)
dimnames(tcRLDA2) <- list(Observados = as.character(unique(wine$Type)), "Predictos (cv)" = as.character(unique(wine$Type)))
print(round(tcRLDA2))
## Predictos (cv)
## Observados 1 2 3
## 1 39 0 0
## 2 1 44 3
## 3 0 0 31
tcRQDA2 <- table(testeWine$Type, PredRQDA2$class)
dimnames(tcRQDA2) <- list(Observados = as.character(unique(wine$Type)), "Predictos (cv)" = as.character(unique(wine$Type)))
print(round(tcRQDA2))
## Predictos (cv)
## Observados 1 2 3
## 1 19 20 0
## 2 1 47 0
## 3 0 7 24
tcREst2 <- table(testeWine$Type, PredREst2$class)
dimnames(tcREst2) <- list(Observados = as.character(unique(wine$Type)), "Predictos (cv)" = as.character(unique(wine$Type)))
print(round(tcREst2))
## Predictos (cv)
## Observados 1 2 3
## 1 33 0 6
## 2 1 35 12
## 3 0 17 14
Proporção de acertos em cada grupo
round(prop.table(tcRLDA2, 1),3)
## Predictos (cv)
## Observados 1 2 3
## 1 1.000 0.000 0.000
## 2 0.021 0.917 0.062
## 3 0.000 0.000 1.000
round(prop.table(tcRQDA2, 1),3)
## Predictos (cv)
## Observados 1 2 3
## 1 0.487 0.513 0.000
## 2 0.021 0.979 0.000
## 3 0.000 0.226 0.774
round(prop.table(tcREst2, 1),3)
## Predictos (cv)
## Observados 1 2 3
## 1 0.846 0.000 0.154
## 2 0.021 0.729 0.250
## 3 0.000 0.548 0.452
Proporção geral de acertos:
sum(diag(prop.table(tcRLDA2)))
## [1] 0.9661017
sum(diag(prop.table(tcRQDA2)))
## [1] 0.7627119
sum(diag(prop.table(tcREst2)))
## [1] 0.6949153
No segundo conjunto de dados conclui-se que quanto mais complexo o modelo, maior o erro de predição.
Utilizar o banco de dados Pima.tr do pacote MASS
com treino
e a base de dados Pima.te como teste
. A com a resposta type e variáveis explicativas bmi e ped.
Ajustar o modelo pela função de optim
e comparar com ajuste do glm
.
Ajustar pelo método discriminante linear, e quadrático de Fisher
Ajustar pelo método discriminante regularizado
Obter as curvas ROC pelos métodos acima
Interpretar os resultados