样本分布不平衡,机器学习准确率高又有什么用?
前面無論是用全部變量還是篩選出的特征變量、無論如何十折交叉驗證調參,獲得的模型應用于測試集時雖然預測準確率能在90%以上,但與不基于任何信息的隨機猜測相比,這個模型都是統計不顯著的 (這一點可能意義也不大,樣本不平衡時看模型整體準確性無意義)。一個原因應該是樣本不平衡導致的。DLBCL組的樣品數目約為FL組的3倍。不通過建模而只是盲猜結果為DLBCL即可獲得75%的正確率。而FL組的預測準確率卻很低。
而通常我們關注的是占少數的樣本,如是否患病,我們更希望能盡量發現可能存在的疾病,提前采取措施。
因此如何處理非平衡樣品是每一個算法應用于分類問題時都需要考慮的。
不平衡樣本的模型構建中的影響主要體現在2個地方:
隨機采樣構建決策樹時會有較大概率只拿到了樣品多的分類,這些樹將沒有能力預測樣品少的分類,從而構成無意義的決策樹。
在決策樹的每個分子節點所做的決策會傾向于整體分類純度,因此樣品少的分類對結果的貢獻和影響少。
一般處理方式有下面4種:
Class weights: 樣品少的類分類錯誤給予更高的罰分 (impose a heavier cost when errors are made in the minority class)
Down-sampling: 從樣品多的類隨機移除樣品
Up-sampling: 在樣品少的類隨機復制樣品 (randomly replicate instances in the minority class)
Synthetic minority sampling technique (SMOTE): 通過插值在樣品少的類中合成填充樣本
這些權重加權或采樣技術對閾值依賴的評估指標如準確性等影響較大,它們相當于把決策閾值推向了ROC曲線中的”最優位置” (這在Boruta特征變量篩選部分有講)。但這些權重加權或采樣技術對ROC曲線通常影響不會太大。
基于模擬數據的樣本不平衡處理
這里先通過一套模擬數據熟悉下處理流程,再應用于真實數據。采用caret包的twoClassSim函數生成包含20個有意義變量和10個噪音變量的數據集。該數據集包含5000個觀察樣品,分為兩組,多數組和少數組的樣品數目比例為50:1 (通過intercept參數控制)。
library(dplyr) # for data manipulation library(caret) # for model-building # install.packages("xts") # install.packages("quantmod") # wget https://cran.r-project.org/src/contrib/Archive/DMwR/DMwR_0.4.1.tar.gz # R CMD INSTALL DMwR_0.4.1.tar.gz library(DMwR) # for smote implementation # 或使用smotefamily代替 # library(smotefamily) # for smote implementation library(purrr) # for functional programming (map) library(pROC) # for AUC calculationsset.seed(2969)imbal_train <- twoClassSim(5000,intercept = -25,linearVars = 20,noiseVars = 10)imbal_train$Class = ifelse(imbal_train$Class == "Class1", "Normal", "Disease") imbal_train$Class <- factor(imbal_train$Class, levels=c("Disease", "Normal"))imbal_test <- twoClassSim(5000,intercept = -25,linearVars = 20,noiseVars = 10) imbal_test$Class = ifelse(imbal_test$Class == "Class1", "Normal", "Disease") imbal_test$Class <- factor(imbal_test$Class, levels=c("Disease", "Normal"))prop.table(table(imbal_train$Class))prop.table(table(imbal_test$Class))樣品構成
Disease Normal 0.0204 0.9796 Disease Normal 0.0252 0.9748構建原始GBM模型
這里應用另外一種集成學習算法 (GBM, Gradient Boosting Machine)進行模型構建。GBM也是效果很好的集成學習算法,可以處理變量的互作和非線性關系。機器學習中常用的GBDT、XGBoost和LightGBM算法(或工具)都是基于梯度提升機(GBM)的算法思想。
先構建一個原始模型,重復5次10-折交叉驗證尋找最優的模型超參數,采用AUC作為評估標準。這些概念如果不熟悉翻一下往期推文。
# Set up control function for training ctrl <- trainControl(method = "repeatedcv",number = 10,repeats = 5,summaryFunction = twoClassSummary,classProbs = TRUE)# Build a standard classifier using a gradient boosted machineset.seed(5627) orig_fit <- train(Class ~ .,data = imbal_train,method = "gbm",verbose = FALSE,metric = "ROC",trControl = ctrl)# Build custom AUC function to extract AUC # from the caret model objecttest_roc <- function(model, data) {roc(data$Class,predict(model, data, type = "prob")[, "Disease"])}orig_fit %>%test_roc(data = imbal_test) %>%auc()AUC值為0.95,還是很不錯的。
Setting levels: control = Disease, case = Normal Setting direction: controls > cases Area under the curve: 0.9538從confusion matrix (預測結果采用默認閾值)來看,Disease的分類效果一般,準確率(敏感性)只有30.6%。不管是Normal還是Disease都傾向于預測為Normal,特異性低,這是因為樣品不平衡導致的。而我們通常更希望盡早發現疾病的存在。
predictions_train <- predict(orig_fit, newdata=imbal_test) confusionMatrix(predictions_train, imbal_test$Class)Confusion Matrix and StatisticsReference Prediction Disease NormalDisease 38 17Normal 88 4857Accuracy : 0.979 95% CI : (0.9746, 0.9828)No Information Rate : 0.9748 P-Value [Acc > NIR] : 0.02954 Kappa : 0.4109 Mcnemar's Test P-Value : 8.415e-12 Sensitivity : 0.3016 Specificity : 0.9965 Pos Pred Value : 0.6909 Neg Pred Value : 0.9822 Prevalence : 0.0252 Detection Rate : 0.0076 Detection Prevalence : 0.0110 Balanced Accuracy : 0.6490 'Positive' Class : Disease采用權重分配或抽樣方式處理樣品不平衡問題
這里應用的GBM模型自身有一個參數weights可以用于設置樣品的權重;caret在trainControl函數中提供了sampling參數可以進行up-sample和down-sample,或其它任何算法的采樣方式(這里用的是smotefamily::SMOTE函數進行采樣)。
# Create model weights (they sum to one) # 給每一個觀察一個權重 class1_weight = (1/table(imbal_train$Class)[['Normal']]) * 0.5 class2_weight = (1/table(imbal_train$Class)[["Disease"]]) * 0.5 model_weights <- ifelse(imbal_train$Class == "Normal",class1_weight, class2_weight)# Use the same seed to ensure same cross-validation splits ctrl$seeds <- orig_fit$control$seeds# Build weighted modelweighted_fit <- train(Class ~ .,data = imbal_train,method = "gbm",verbose = FALSE,weights = model_weights,metric = "ROC",trControl = ctrl)# Build down-sampled modelctrl$sampling <- "down"down_fit <- train(Class ~ .,data = imbal_train,method = "gbm",verbose = FALSE,metric = "ROC",trControl = ctrl)# Build up-sampled modelctrl$sampling <- "up"up_fit <- train(Class ~ .,data = imbal_train,method = "gbm",verbose = FALSE,metric = "ROC",trControl = ctrl)# Build smote model ctrl$sampling <- "smote"smote_fit <- train(Class ~ .,data = imbal_train,method = "gbm",verbose = FALSE,metric = "ROC",trControl = ctrl)計算下每個模型的AUC值
# Examine results for test setmodel_list <- list(original = orig_fit,weighted = weighted_fit,down = down_fit,up = up_fit,SMOTE = smote_fit)model_list_roc <- model_list %>%map(test_roc, data = imbal_test)model_list_roc %>%map(auc)樣品加權模型獲得的AUC值最高,其次是up-sample, SMOTE, down-sample,結果都比original有提高。
Setting levels: control = Disease, case = Normal Setting direction: controls > cases Setting levels: control = Disease, case = Normal Setting direction: controls > cases Setting levels: control = Disease, case = Normal Setting direction: controls > cases Setting levels: control = Disease, case = Normal Setting direction: controls > cases Setting levels: control = Disease, case = Normal Setting direction: controls > cases $original Area under the curve: 0.9538$weighted Area under the curve: 0.9793$down Area under the curve: 0.9667$up Area under the curve: 0.9778$SMOTE Area under the curve: 0.9744繪制下ROC曲線,查看下模型的具體效果展示。樣品加權的模型優于其它所有模型,原始模型在假陽性率0-25%時效果差于其它模型。好的模型是在較低假陽性率時具有較高的真陽性率。
results_list_roc <- list(NA) num_mod <- 1for(the_roc in model_list_roc){results_list_roc[[num_mod]] <- data_frame(TPR = the_roc$sensitivities,FPR = 1 - the_roc$specificities,model = names(model_list)[num_mod])num_mod <- num_mod + 1}results_df_roc <- bind_rows(results_list_roc)results_df_roc$model <- factor(results_df_roc$model, levels=c("original", "down","SMOTE","up","weighted"))# Plot ROC curve for all 5 modelscustom_col <- c("#000000", "#009E73", "#0072B2", "#D55E00", "#CC79A7")ggplot(aes(x = FPR, y = TPR, group = model), data = results_df_roc) +geom_line(aes(color = model), size = 1) +scale_color_manual(values = custom_col) +geom_abline(intercept = 0, slope = 1, color = "gray", size = 1) +theme_bw(base_size = 18) + coord_fixed(1)ggplot(aes(x = FPR, y = TPR, group = model), data = results_df_roc) +geom_line(aes(color = model), size = 1) +facet_wrap(vars(model)) +scale_color_manual(values = custom_col) +geom_abline(intercept = 0, slope = 1, color = "gray", size = 1) +theme_bw(base_size = 18) + coord_fixed(1)加權后的模型,總預測準確率降低了一點,但Disease的預測準確性升高了2.47倍,70.63%。
predictions_train <- predict(weighted_fit, newdata=imbal_test) confusionMatrix(predictions_train, imbal_test$Class)結果如下
Confusion Matrix and StatisticsReference Prediction Disease NormalDisease 89 83Normal 37 4791Accuracy : 0.976 95% CI : (0.9714, 0.9801)No Information Rate : 0.9748 P-Value [Acc > NIR] : 0.3137 Kappa : 0.5853 Mcnemar's Test P-Value : 3.992e-05 Sensitivity : 0.7063 Specificity : 0.9830 Pos Pred Value : 0.5174 Neg Pred Value : 0.9923 Prevalence : 0.0252 Detection Rate : 0.0178 Detection Prevalence : 0.0344 Balanced Accuracy : 0.8447 'Positive' Class : Disease從這套測試數據來看,設置權重獲得的模型效果是最好的。但這不是絕對的,應用于自己的數據時,需要都嘗試一下,看看自己的數據更適合哪種方式。
未完待續......
機器學習系列教程
從隨機森林開始,一步步理解決策樹、隨機森林、ROC/AUC、數據集、交叉驗證的概念和實踐。
文字能說清的用文字、圖片能展示的用、描述不清的用公式、公式還不清楚的寫個簡單代碼,一步步理清各個環節和概念。
再到成熟代碼應用、模型調參、模型比較、模型評估,學習整個機器學習需要用到的知識和技能。
一圖感受各種機器學習算法
機器學習算法 - 隨機森林之決策樹初探(1)
機器學習算法-隨機森林之決策樹R 代碼從頭暴力實現(2)
機器學習算法-隨機森林之決策樹R 代碼從頭暴力實現(3)
機器學習算法-隨機森林之理論概述
機器學習算法-隨機森林初探(1)
機器學習 - 隨機森林手動10 折交叉驗證
機器學習 模型評估指標 - ROC曲線和AUC值
機器學習 - 訓練集、驗證集、測試集
一個函數統一238個機器學習R包,這也太贊了吧
基于Caret和RandomForest包進行隨機森林分析的一般步驟 (1)
Caret模型訓練和調參更多參數解讀(2)
基于Caret進行隨機森林隨機調參的4種方式
機器學習第17篇 - 特征變量篩選(1)
機器學習第18篇 - Boruta特征變量篩選(2)
機器學習第19篇 - 機器學習系列補充:數據集準備和更正YSX包
機器學習第20篇 - 基于Boruta選擇的特征變量構建隨機森林
機器學習第21篇 - 特征遞歸消除RFE算法 理論
機器學習第22篇 - RFE篩選出的特征變量竟然是Boruta的4倍之多
機器學習第23篇 - 更多特征變量卻未能帶來隨機森林分類效果的提升
機器學習相關書籍分享
UCI機器學習數據集
送你一個在線機器學習網站,真香!
多套用于機器學習的多種癌癥表達數據集
這個統一了238個機器學習模型R包的參考手冊推薦給你
莫煩Python機器學習
機器學習與人工智能、深度學習有什么關系?終于有人講明白了
一套完整的基于隨機森林的機器學習流程(特征選擇、交叉驗證、模型評估))
隨機森林預測發現這幾個指標對公眾號文章吸粉最重要
往期精品(點擊圖片直達文字對應教程)
機器學習
后臺回復“生信寶典福利第一波”或點擊閱讀原文獲取教程合集
總結
以上是生活随笔為你收集整理的样本分布不平衡,机器学习准确率高又有什么用?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: NBT:你想成为计算生物学家?
- 下一篇: 图片压缩但质量不减,这个工具很不错