【发布时间】:2014-02-01 07:02:52
【问题描述】:
这个问题是同一线程here 的延续。以下是本书中的一个最小工作示例:
Wehrens R. Chemometrics 与 R 中的多变量数据分析 自然科学和生命科学。第 1 版。海德堡;纽约: 施普林格。 2011 年。(第 250 页)。
示例取自本书及其包ChemometricsWithR。它突出了使用交叉验证技术建模时的一些缺陷。
目标:
一种交叉验证的方法,使用相同的重复 CV 集来执行 PLS 的已知策略,然后通常是 LDA 或类似逻辑回归、SVM、C5.0、CART 的表亲,具有 caret 包的精神。因此,每次调用等待分类器之前都需要 PLS,以便对 PLS score 空间进行分类,而不是对观察本身进行分类。 caret 包中最接近的方法是在使用任何分类器建模之前将PCA 作为预处理步骤。下面是一个 PLS-LDA 程序,只有一个交叉验证来测试分类器的性能,没有 10 倍 CV 或任何重复。下面的代码取自上述书中,但进行了一些更正,否则会引发错误:
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
输出:
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
但是,混淆矩阵与书中的不匹配,反正书中的代码确实坏了,但是这里的这个对我有用!
注意事项:
虽然这只是一份 CV,但意图是首先就这个方法达成一致,将训练集的sd 和mean 应用于测试集,根据特定数量的 PC 将 PLUS 转换为 PLS 分数ncomp .我希望这发生在插入符号中的每一轮简历中。如果这里作为代码的方法是正确的,那么它可以作为一个最小工作示例的良好开端,同时修改 caret 包的代码。
旁注:
缩放和居中可能会非常混乱,我认为 R 中的一些 PLS 函数在内部进行缩放,有或没有居中,我不确定,因此在插入符号中构建自定义模型时应小心处理以避免缺少或多次缩放或居中(我对这些东西很警惕)。
多重居中/缩放的风险
下面的代码只是为了展示多重居中/缩放如何改变数据,这里只显示了居中,但同样的问题也适用于缩放。
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)
输出:
xNotCentered xCentered1 xCentered2 xCentered3
2.035540e+00 1.897798e-16 -5.603699e-18 -5.332377e-18
如果我在本课程的某个地方遗漏了什么,请发表评论。谢谢。
【问题讨论】:
-
我认为插入符号还不支持预处理的客户方法。但是,您可以构建一个包含预处理的自定义模型流:caret.r-forge.r-project.org/custom_models.html
-
谢谢。我查看了自定义模型,我没有找到附近的复杂情况是在代码中告诉
train需要训练 CV 折叠的分数。通常,我会先尝试 PLS-LDA,如果有效,然后对其他分类器执行相同的操作。它就像一个原型模型。那么能否先提供如何自定义PLS-LDA的代码? -
我投票把它移到stackoverflow,我认为它更合适。
-
@doctorate 您将定义一个自定义模型,该模型将在给定数据集的情况下拟合 pls-lda 模型。然后,您将为您的模型编写一个预测函数,该函数将在给定模型拟合和测试集的情况下进行预测。然后,您将这些函数作为自定义方法提供给 caret,并且 caret 将为您的数据集的每个重新采样处理将正确的数据传递给每个函数。
-
@Zach:我在旧线程中提到的包具有适合
plslda和predict.plslda的模型(以及更多功能,如coef和一些后处理)。不过,目前不支持caret。
标签: r classification cross-validation r-caret