Melhorando a classificação SVM de diabetes

10

Estou usando o SVM para prever diabetes. Estou usando o conjunto de dados BRFSS para esse fim. O conjunto de dados tem as dimensões de e está inclinado. A porcentagem de s na variável de destino é de 11 %, enquanto os s constituem os 89 % restantes .432607×136Y11%N89%

Eu estou usando apenas 15fora de 136variáveis independentes do conjunto de dados. Um dos motivos para reduzir o conjunto de dados foi ter mais amostras de treinamento quando as linhas que contêm NAs são omitidas.

Essas 15variáveis ​​foram selecionadas após a execução de métodos estatísticos, como árvores aleatórias, regressão logística e descoberta de quais variáveis ​​são significativas nos modelos resultantes. Por exemplo, após executar a regressão logística, costumávamos p-valueordenar as variáveis ​​mais significativas.

Meu método de fazer a seleção de variáveis ​​está correto? Qualquer sugestão para é muito bem-vinda.

A seguir está a minha Rimplementação.

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);

Eu corri com amostras (treinamento = 700 e teste = 300 ), pois é mais rápido no meu laptop. A matriz de confusão para os dados de teste ( 300 amostras) que recebo é bastante ruim.1000700300300

    true
pred   N   Y
   N 262  38
   Y   0   0

Preciso melhorar minha previsão para a Yturma. Na verdade, eu preciso ser o mais preciso possível, Ymesmo que eu tenha um desempenho ruim N. Todas as sugestões para melhorar a precisão da classificação serão muito apreciadas.

Anand
fonte
Eu acho que o seu SVM não funciona, mas não sei por que! Também pode ser o seu melhor para normalizaram seus dados ...
user4581
Y 90%
Normalizar os dados é a melhor coisa para começar. Comece por isso. Você também pode tentar pesquisar também que o kernel não linear pode mostrar um resultado melhor. (Depende da sua previsão de fronteira, pode ser normalização deve ser suficiente)
404Dreamer_ML
Você também pode tentar, em kernlabvez de e1071- ele normaliza automaticamente e possui algumas heurísticas, facilitando a inicialização do primeiro modelo.

Respostas:

9

Tenho 4 sugestões:

  1. Como você está escolhendo as variáveis ​​a serem incluídas no seu modelo? Talvez você esteja perdendo alguns dos principais indicadores do conjunto de dados maior.
  2. Quase todos os indicadores que você está usando (como sexo, fumante, etc.) devem ser tratados como fatores. Tratar essas variáveis ​​como numéricas está errado e provavelmente está contribuindo para o erro no seu modelo.
  3. Por que você está usando um SVM? Você tentou métodos mais simples, como análise discriminante linear ou mesmo regressão linear? Talvez uma abordagem simples em um conjunto de dados maior traga um resultado melhor.
  4. Experimente o pacote de sinal de intercalação . Ele ajudará a validar cruzadamente a precisão do modelo, é paralelo, o que permitirá que você trabalhe mais rápido e facilita a exploração de diferentes tipos de modelos.

Aqui está um exemplo de código para circunflexo:

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)

Esse modelo de LDA supera seu SVM e eu nem consertei seus fatores. Eu tenho certeza que se você recodificar Sexo, Fumante, etc. como fatores, obterá melhores resultados.

Zach
fonte
Eu recebo o seguinte erro task 1 failed - "could not find function "predictionFunction"". Eu sei que este não é um fórum, mas se você tiver algum comentário, por favor me avise.
perfil
11
@Anand: Abra uma nova sessão do R como administrador (ou execute o sudo R no mac / linux). Executar update.packages.Quando terminar, feche o R e abra novamente uma sessão normal (não administrativa). Execute seu código, exceto para as seções "SVM" e "Matriz de confusão". Em seguida, execute o meu código. Se você ainda receber um erro, poste a linha que retornou um erro, juntamente com o erro exato.
Zach
11
@ Anand: Além disso, verifique se você está executando a versão mais recente do R (2.14) e usando a versão mais recente do cursor. Você pode atualizar o sinal de intercalação executando install.packages('caret')novamente.
Zach
@ Anand: Ótimo! Você pode inserir diferentes métodos para a trainfunção, como nb(bayes ingênuos), glm(regressão logística) svmLineare svmRadial. O svm's demorará muito tempo para se encaixar.
Zach
3

Se você estiver usando um kernel linear, é possível que a seleção de recursos seja uma má ideia e que a regularização possa impedir o ajuste excessivo de maneira mais eficaz do que a seleção de recursos. Observe que os limites de desempenho que o SVM implementa aproximadamente são independentes da dimensão do espaço de recurso, que foi um dos pontos de venda do SVM.

Dikran Marsupial
fonte
2

Eu tive esse problema recentemente e encontrei algumas coisas que ajudam. Primeiro, experimente um modelo Naive Bayes (pacote klaR), que às vezes fornece melhores resultados quando a classe minoritária em um problema de classificação é pequena. Além disso, se você optar por permanecer com um SVM, poderá tentar sobreamostrar a classe minoritária. Essencialmente, você deseja incluir mais exemplos da classe minoritária ou criar casos sintéticos para a classe minoritária

Este artigo: http: //www.it.iitb.ac.in/~kamlesh/Page/Reports/highlySkewed.pdf

Tem alguma discussão e exemplos dessas técnicas implementadas em Weka, mas também é possível implementá-las em R.

Dan
fonte
Obrigado pelos comentários úteis. Deixe-me experimentar suas sugestões.
Anand
1

Além do que já foi mencionado, você está corrigindo seu melhor modelo para usar um kernel linear. Você deve prever o uso do melhor modelo que foi ajustado, incluindo o mesmo kernel que foi usado / encontrado em seu estágio de ajuste (que eu assumo ser RBF, pois você está ajustando gama).

benbo
fonte