Como personalizar um modelo no CARET para executar o modelo de classificação em duas etapas PLS- [Classifer]?
Esta pergunta é uma continuação do mesmo threadaqui. Abaixo está um exemplo de trabalho mínimo retirado deste livro:
Wehrens R. Chemometrics com análise de dados multivariada R nas ciências naturais e ciências da vida. 1ª edição. Heidelberg; Nova York: Springer. 2011. (página 250).
O exemplo foi retirado deste livro e seu pacoteChemometricsWithR
. Ele destacou algumas armadilhas ao modelar usando técnicas de validação cruzada.
O objetivo:
Uma metodologia validada cruzada usando o mesmo conjunto de CV repetido para executar uma estratégia conhecida dePLS
seguido tipicamente porLDA
primos como regressão logística, SVM, C5.0, CART, com o espírito decaret
pacote. Portanto, o PLS seria necessário todas as vezes antes de chamar o classificador em espera para classificar o PLSPonto espaço em vez das próprias observações. A abordagem mais próxima no pacote de intercalação está fazendoPCA
como uma etapa de pré-processamento antes da modelagem com qualquer classificador. Abaixo está um procedimento PLS-LDA com apenas uma validação cruzada para testar o desempenho do classificador, não houve CV 10 vezes ou qualquer repetição. O código abaixo foi retirado do livro mencionado, mas com algumas correções gera erro:
library(ChemometricsWithR)
data(prostate)
prostate.clmat <- classvec2classmat(prostate.type) # convert Y to a dummy var
odd <- seq(1, length(prostate.type), by = 2) # training
even <- seq(2, length(prostate.type), by = 2) # holdout test
prostate.pls <- plsr(prostate.clmat ~ prostate, ncomp = 16, validation = "CV", subset=odd)
Xtst <- scale(prostate[even,], center = colMeans(prostate[odd,]), scale = apply(prostate[odd,],2,sd))
tst.scores <- Xtst %*% prostate.pls$projection # scores for the waiting trained LDA to test
prostate.ldapls <- lda(scores(prostate.pls)[,1:16],prostate.type[odd]) # LDA for scores
table(predict(prostate.ldapls, new = tst.scores[,1:16])$class, prostate.type[even])
predictionTest <- predict(prostate.ldapls, new = tst.scores[,1:16])$class)
library(caret)
confusionMatrix(data = predictionTest, reference= prostate.type[even]) # from caret
Resultado:
Confusion Matrix and Statistics
Reference
Prediction bph control pca
bph 4 1 9
control 1 35 7
pca 34 4 68
Overall Statistics
Accuracy : 0.6564
95% CI : (0.5781, 0.7289)
No Information Rate : 0.5153
P-Value [Acc > NIR] : 0.0001874
Kappa : 0.4072
Mcnemar's Test P-Value : 0.0015385
Statistics by Class:
Class: bph Class: control Class: pca
Sensitivity 0.10256 0.8750 0.8095
Specificity 0.91935 0.9350 0.5190
Pos Pred Value 0.28571 0.8140 0.6415
Neg Pred Value 0.76510 0.9583 0.7193
Prevalence 0.23926 0.2454 0.5153
Detection Rate 0.02454 0.2147 0.4172
Detection Prevalence 0.08589 0.2638 0.6503
Balanced Accuracy 0.51096 0.9050 0.6643
No entanto, a matriz de confusão não coincidiu com a do livro, de qualquer maneira o código do livro quebrou, mas este aqui funcionou comigo!
Notas:
Embora este fosse apenas um CV, mas a intenção é concordar com essa metodologia primeiro,sd
emean
do conjunto de trens foram aplicados no conjunto de testes, PLUS transformado em escores PLS com base em um número específico de PCncomp
. Eu quero que isso ocorra a cada rodada do CV no cursor. Se a metodologia como código estiver correta aqui, ela poderá servir, como um bom começo para um exemplo de trabalho mínimo, enquanto modifica o código do pacote de interpolação.
Notas laterais:
Pode ser muito complicado com a escala e a centralização, acho que algumas das funções do PLS no R fazem a escala internamente, com ou sem centralização, não tenho certeza, portanto, a construção de um modelo personalizado em caret deve ser manuseada com cuidado para evitar a falta ou várias escalas ou centralizações (estou de guarda com essas coisas).
Perigos de várias centralizações / redimensionamentos
O código abaixo é apenas para mostrar como a centralização / escalonamento múltiplo pode alterar os dados, apenas a centralização é mostrada aqui, mas o mesmo problema com a escalabilidade também se aplica.
set.seed(1)
x <- rnorm(200, 2, 1)
xCentered1 <- scale(x, center=TRUE, scale=FALSE)
xCentered2 <- scale(xCentered1, center=TRUE, scale=FALSE)
xCentered3 <- scale(xCentered2, center=TRUE, scale=FALSE)
sapply (list(xNotCentered= x, xCentered1 = xCentered1, xCentered2 = xCentered2, xCentered3 = xCentered3), mean)
Resultado:
xNotCentered xCentered1 xCentered2 xCentered3
2.035540e+00 1.897798e-16 -5.603699e-18 -5.332377e-18
Deixe um comentário se estiver faltando algo em algum lugar deste curso. Obrigado.