R中支持向量机和朴素贝叶斯分类器的可变重要性

Posted

技术标签:

【中文标题】R中支持向量机和朴素贝叶斯分类器的可变重要性【英文标题】:Variable importance for support vector machine and naive Bayes classifiers in R 【发布时间】:2016-08-19 02:57:33 【问题描述】:

我正在用 R 语言在癌症数据集上构建预测分类器。 我正在使用随机森林、支持向量机和朴素贝叶斯分类器。我无法计算 SVM 和 NB 模型的变量重要性

我最终收到以下错误。

UseMethod("varImp") 中的错误: 没有适用于“c('svm.formula', 'svm')”类对象的“varImp”方法

如果有人可以帮助我,我将不胜感激。

【问题讨论】:

欢迎来到 ***。请阅读 (1) how do I ask a good question, (2) How to create a MCVE 以及 (3) how to provide a minimal reproducible example in R。然后相应地编辑和改进您的问题。即,提供重现错误的代码,例如通过使用内置的示例数据集。 【参考方案1】:

我创建了一个循环,该循环一次迭代地删除一个预测变量,并在数据框中捕获从混淆矩阵派生的各种性能度量。这不应该是一个万能的解决方案,我没有时间,但应用修改应该不难。

确保预测变量位于数据框中的最后。

我主要需要模型中的特异性值,通过一次删除一个预测变量,我可以评估每个预测变量的重要性,即通过删除一个预测变量,模型的最小特异性(小于预测变量编号 i) 表示预测变量最重要。您需要知道您将重视哪些指标。

您还可以在内部添加另一个 for 循环以在内核之间进行更改,即线性、多项式、径向,但您可能必须考虑其他参数,例如伽玛。用你的目标变量改变“label_fake”,用你的数据框改变 df_final。

SVM 版本:

set.seed(1)
varimp_df <- NULL # df with results
ptm1 <- proc.time() # Start the clock!
for(i in 1:(ncol(df_final)-1))  # the last var is the dep var, hence the -1
  smp_size <- floor(0.70 * nrow(df_final)) # 70/30 split
  train_ind <- sample(seq_len(nrow(df_final)), size = smp_size)
  training <- df_final[train_ind, -c(i)] # receives all the df less 1 var
  testing <- df_final[-train_ind, -c(i)]

  tune.out.linear <- tune(svm, label_fake ~ .,
                          data = training,
                          kernel = "linear",
                          ranges = list(cost =10^seq(1, 3, by = 0.5))) # you can choose any range you see fit

  svm.linear <- svm(label_fake ~ .,
                    kernel = "linear",
                    data = training,
                    cost = tune.out.linear[["best.parameters"]][["cost"]])

  train.pred.linear <- predict(svm.linear, testing)
  testing_y <- as.factor(testing$label_fake)
  conf.matrix.svm.linear <- caret::confusionMatrix(train.pred.linear, testing_y)
  varimp_df <- rbind(varimp_df,data.frame(
                     var_no=i,
                     variable=colnames(df_final[,i]), 
                     cost_param=tune.out.linear[["best.parameters"]][["cost"]],
                     accuracy=conf.matrix.svm.linear[["overall"]][["Accuracy"]],
                     kappa=conf.matrix.svm.linear[["overall"]][["Kappa"]],
                     sensitivity=conf.matrix.svm.linear[["byClass"]][["Sensitivity"]],
                     specificity=conf.matrix.svm.linear[["byClass"]][["Specificity"]]))
  runtime1 <- as.data.frame(t(data.matrix(proc.time() - ptm1)))$elapsed # time for running this loop
  runtime1 # divide by 60 and you get minutes, /3600 you get hours
    

朴素贝叶斯版本:

varimp_nb_df <- NULL
ptm1 <- proc.time() # Start the clock!
for(i in 1:(ncol(df_final)-1)) 
  smp_size <- floor(0.70 * nrow(df_final))
  train_ind <- sample(seq_len(nrow(df_final)), size = smp_size)
  training <- df_final[train_ind, -c(i)]
  testing <- df_final[-train_ind, -c(i)]

  x = training[, names(training) != "label_fake"]
  y = training$label_fake

  model_nb_var = train(x,y,'nb', trControl=ctrl)

  predict_nb_var <- predict(model_nb_var, newdata = testing )

  confusion_matrix_nb_1 <- caret::confusionMatrix(predict_nb_var, testing$label_fake)  

  varimp_nb_df <- rbind(varimp_nb_df, data.frame(
    var_no=i,
    variable=colnames(df_final[,i]), 
    accuracy=confusion_matrix_nb_1[["overall"]][["Accuracy"]],
    kappa=confusion_matrix_nb_1[["overall"]][["Kappa"]],
    sensitivity=confusion_matrix_nb_1[["byClass"]][["Sensitivity"]],
    specificity=confusion_matrix_nb_1[["byClass"]][["Specificity"]]))
  runtime1 <- as.data.frame(t(data.matrix(proc.time() - ptm1)))$elapsed # time for running this loop
  runtime1 # divide by 60 and you get minutes, /3600 you get hours

玩得开心!

【讨论】:

【参考方案2】:

如果你使用R,变量重要性可以用rminer包中的Importance方法计算。这是我的示例代码:

library(rminer)
M <- fit(y~., data=train, model="svm", kpar=list(sigma=0.10), C=2)
svm.imp <- Importance(M, data=train)

详细请参考以下链接https://cran.r-project.org/web/packages/rminer/rminer.pdf

【讨论】:

【参考方案3】:

给定

library(e1071)
model <- svm(Species ~ ., data = iris)
class(model)
# [1] "svm.formula" "svm"     

library(caret)
varImp(model)
# Error in UseMethod("varImp") : 
#   no applicable method for 'varImp' applied to an object of class "c('svm.formula', 'svm')"

methods(varImp)
#  [1] varImp.bagEarth      varImp.bagFDA        varImp.C5.0*         varImp.classbagg*   
#  [5] varImp.cubist*       varImp.dsa*          varImp.earth*        varImp.fda*         
#  [9] varImp.gafs*         varImp.gam*          varImp.gbm*          varImp.glm*         
# [13] varImp.glmnet*       varImp.JRip*         varImp.lm*           varImp.multinom*    
# [17] varImp.mvr*          varImp.nnet*         varImp.pamrtrained*  varImp.PART*        
# [21] varImp.plsda         varImp.randomForest* varImp.RandomForest* varImp.regbagg*     
# [25] varImp.rfe*          varImp.rpart*        varImp.RRF*          varImp.safs*        
# [29] varImp.sbf*          varImp.train*  

methods(varImp) 中没有函数varImp.svm,因此报错。您可能也想看看this post on Cross Validated。

【讨论】:

以上是关于R中支持向量机和朴素贝叶斯分类器的可变重要性的主要内容,如果未能解决你的问题,请参考以下文章

Python机器学习及实践——基础篇4(朴素贝叶斯)

如何生成混淆矩阵并找到朴素贝叶斯分类器的错误分类率?

朴素贝叶斯分类器的准确性?

机器学习系列-朴素贝叶斯分类器

朴素贝叶斯分类器的平衡语料库

朴素贝叶斯