糖尿病のSVM分類の改善


10

私はSVMを使用して糖尿病を予測しています。この目的でBRFSSデータセットを使用してます。データセットの次元はであり、歪んでいます。ターゲット変数のs のパーセンテージはで、sは残りの構成します。11 89 432607×136Y11%N89%

データセットの独立変数の15うち、使用しているのは私だけです136。データセットを減らす理由の1つは、NAs を含む行が省略されたときにトレーニングサンプルを増やすことでした。

これらの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

はい、基本的にYはあらゆる入力を予測します。これは、正しい時間のであることを意味します。 90%
Anand

データを正規化することから始めてください。それから始めましょう。また、非線形カーネルを検索してみると、より良い結果が表示される場合があります。(それはあなたのフロンティアビジョンによって異なりますが、正規化で十分かもしれません)
404Dreamer_ML

kernlab代わりに試すこともできますe1071-これは自動的に正規化を行い、最初のモデルのブートストラップを簡単にするヒューリスティックを備えています。

回答:


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""。これはフォーラムではないことは承知していますが、コメントがありましたらお知らせください。
アナンド

1
@Anand:新しいRセッションを管理者として開きます(またはmac / linuxでsudo Rを実行します)。実行update.packages.それが完了したら、Rを閉じて、通常の(管理者以外の)セッションを再度開きます。「SVM」と「​​混同マトリックス」セクション以外のコードを実行します。次に、コードを実行します。それでもエラーが発生する場合は、エラーを返した行と正確なエラーを投稿してください。
ザック

1
@Anand:また、最新バージョンのR(2.14)を実行し、最新バージョンのキャレットを使用していることを確認してください。install.packages('caret')もう一度実行すると、キャレットを更新できます。
ザック

@アナンド:すごい!あなたはのためのさまざまな方法でドロップすることができるtrainような機能、nb(ナイーブベイズ)、 glm(ロジスティック回帰)を、svmLinearsvmRadial。SVMが適合するまでには長い時間がかかります。
Zach、

3

線形カーネルを使用している場合、特徴選択は悪い考えである可能性があり、正則化は特徴選択よりも効果的に過剰適合を防ぐことができます。SVMがおおよそ実装するパフォーマンスの限界は、SVMのセールスポイントの1つである特徴空間の次元とは無関係であることに注意してください。


2

私は最近この問題を抱えており、役立ついくつかのことを見つけました。まず、分類問題の少数派クラスが小さい場合に、より良い結果が得られるNaive Bayesモデル(パッケージklaR)を試してください。また、SVMを使用することを選択した場合は、マイノリティクラスのオーバーサンプリングを試すことをお勧めします。基本的に、マイノリティクラスの例を追加するか、マイノリティクラスのケースを合成して作成します

このペーパー:http://www.it.iitb.ac.in/~kamlesh/Page/Reports/highlySkewed.pdf

Wekaに実装されたこれらの手法のいくつかの議論と例がありますが、Rで自分でそれらを実装することも可能です。


役立つコメントをありがとう。あなたの提案を試してみましょう。
アナンド

1

すでに述べたことに加えて、線形カーネルを使用するように最適なモデルを修正しています。チューニング段階で使用/発見されたものと同じカーネル(ガンマをチューニングしているため、RBFであると想定)を含め、チューニングされた最良のモデルを使用して予測する必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.