改善糖尿病的SVM分类


10

我正在使用SVM来预测糖尿病。我为此使用BRFSS数据集。数据集的维度为并且存在偏斜。s在目标变量中的百分比为而s构成其余的。11 89 432607×136Y11%N89%

我只使用了数据集中15136独立变量。减少数据集的原因之一是当NA省略包含s的行时具有更多的训练样本。

15在运行统计方法(例如随机树,逻辑回归)并从结果模型中找出哪些变量很重要之后,才选择这些变量。例如,在运行逻辑回归之后,我们通常p-value对最重要的变量进行排序。

我进行变量选择的方法正确吗?任何建议都非常欢迎。

以下是我的R实现。

library(e1071) # Support Vector Machines

#--------------------------------------------------------------------
# read brfss file (huge 135 MB file)
#--------------------------------------------------------------------
y <- read.csv("http://www.hofroe.net/stat579/brfss%2009/brfss-2009-clean.csv")
indicator <- c("DIABETE2", "GENHLTH", "PERSDOC2", "SEX", "FLUSHOT3", "PNEUVAC3", 
    "X_RFHYPE5", "X_RFCHOL", "RACE2", "X_SMOKER3", "X_AGE_G", "X_BMI4CAT", 
    "X_INCOMG", "X_RFDRHV3", "X_RFDRHV3", "X_STATE");
target <- "DIABETE2";
diabetes <- y[, indicator];

#--------------------------------------------------------------------
# recode DIABETE2
#--------------------------------------------------------------------
x <- diabetes$DIABETE2;
x[x > 1]  <- 'N';
x[x != 'N']  <- 'Y';
diabetes$DIABETE2 <- x; 
rm(x);

#--------------------------------------------------------------------
# remove NA
#--------------------------------------------------------------------
x <- na.omit(diabetes);
diabetes <- x;
rm(x);

#--------------------------------------------------------------------
# reproducible research 
#--------------------------------------------------------------------
set.seed(1612);
nsamples <- 1000; 
sample.diabetes <- diabetes[sample(nrow(diabetes), nsamples), ]; 

#--------------------------------------------------------------------
# split the dataset into training and test
#--------------------------------------------------------------------
ratio <- 0.7;
train.samples <- ratio*nsamples;
train.rows <- c(sample(nrow(sample.diabetes), trunc(train.samples)));

train.set  <- sample.diabetes[train.rows, ];
test.set   <- sample.diabetes[-train.rows, ];

train.result <- train.set[ , which(names(train.set) == target)];
test.result  <- test.set[ , which(names(test.set) == target)];

#--------------------------------------------------------------------
# SVM 
#--------------------------------------------------------------------
formula <- as.formula(factor(DIABETE2) ~ . );
svm.tune <- tune.svm(formula, data = train.set, 
    gamma = 10^(-3:0), cost = 10^(-1:1));
svm.model <- svm(formula, data = train.set, 
    kernel = "linear", 
    gamma = svm.tune$best.parameters$gamma, 
    cost  = svm.tune$best.parameters$cost);

#--------------------------------------------------------------------
# Confusion matrix
#--------------------------------------------------------------------
train.pred <- predict(svm.model, train.set);
test.pred  <- predict(svm.model, test.set);
svm.table <- table(pred = test.pred, true = test.result);
print(svm.table);

我运行了(训练=,测试=)样本,因为它在笔记本电脑中速度更快。我得到的测试数据(样本)的混淆矩阵非常糟糕。700 300 3001000700300300

    true
pred   N   Y
   N 262  38
   Y   0   0

我需要提高对Y班级的预测。实际上,Y即使我的表现不佳,我也需要尽可能地准确N。任何提高分类准确性的建议将不胜感激。


我猜您的SVM根本不起作用,但是不知道为什么!规范化您的数据也可能更好...
user4581 2011年

是的,它基本上可以预测Y任何输入。这意味着的时间是正确的。 90%
阿南德

标准化数据是最好的开始。从那开始。您也可以尝试搜索非线性内核,它可能会显示更好的结果。(这取决于您的国界,可能进行标准化就足够了)
404Dreamer_ML 2011年

你也可以尝试kernlab,而不是e1071-它会自动执行规范化,有一些技巧使得更容易引导的第一款车型。

Answers:


9

我有4条建议:

  1. 您如何选择要包含在模型中的变量?也许您缺少了较大数据集中的一些关键指标。
  2. 您正在使用的几乎所有指标(例如性别,吸烟者等)都应视为因素。将这些变量视为数字是错误的,并且可能导致模型中的错误。
  3. 为什么要使用SVM?您是否尝试过任何更简单的方法,例如线性判别分析甚至线性回归?在较大的数据集上使用简单方法可能会产生更好的结果。
  4. 尝试插入符号。它可以帮助您交叉验证模型的准确性,它可以并行化,从而使您可以更快地工作,并且可以轻松地探索不同类型的模型。

这是插入符号的一些示例代码:

library(caret)

#Parallize
library(doSMP)
w <- startWorkers()
registerDoSMP(w)

#Build model
X <- train.set[,-1]
Y <- factor(train.set[,1],levels=c('N','Y'))
model <- train(X,Y,method='lda')

#Evaluate model on test set
print(model)
predY <- predict(model,test.set[,-1])
confusionMatrix(predY,test.set[,1])
stopWorkers(w)

这个LDA模型击败了您的SVM,我什至没有解决您的问题。我敢肯定,如果您将性,吸烟者等因素重新编码,将会获得更好的结果。


我收到以下错误task 1 failed - "could not find function "predictionFunction""。我知道这不是论坛,但是如果您有任何意见,请告诉我。
阿南德(Anand

1
@Anand:以管理员身份打开一个新的R会话(或在Mac / Linux上运行sudo R)。运行update.packages.完成后,关闭R并重新打开普通(非管理员)会话。运行“ SVM”和“混淆矩阵”部分以外的代码。然后运行我的代码。如果仍然出现错误,请张贴返回错误的行以及确切的错误。
Zach

1
@Anand:另外,请确保您正在运行最新版本的R(2.14),并使用最新版本的插入符号。您可以通过install.packages('caret')再次运行来更新插入符号。
Zach

@Anand:太好了!您可以为train函数添加不同的方法,例如nb(朴素贝叶斯),glm(逻辑回归)svmLinearsvmRadial。svm需要很长时间才能适应。
Zach

3

如果您使用的是线性核,则特征选择可能不是一个好主意,并且正则化可以比特征选择更有效地防止过度拟合。请注意,SVM大致实现的性能范围与功能空间的大小无关,而功能空间的大小是SVM的卖点之一。


2

我最近遇到了这个问题,发现了一些有用的方法。首先,尝试一个朴素贝叶斯模型(软件包klaR),当分类问题中的少数类很小时,有时可以为您提供更好的结果。另外,如果您确实选择使用SVM,则可能要尝试对少数类进行过度采样。从本质上讲,您将希望包含少数派类别的更多示例或为少数派类别综合创建案例

这篇论文:http://www.it.iitb.ac.in/~kamlesh/Page/Reports/highlySkewed.pdf

在Weka中实现了有关这些技术的一些讨论和示例,但您也可以在R中自己实现它们。


感谢您的有用评论。让我尝试一下您的建议。
阿南德

1

除了已经提到的内容之外,您还正在修复最佳模型以使用线性核。您应该预测将使用已调整的最佳模型,包括在调整阶段使用/找到的相同内核(由于您正在调整伽马,因此我假设是RBF)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.