已遷移到我新博客,閱讀體驗更佳基於sklearn的分類器實戰
完整代碼實現見github:click mepython
一共有十個數據集,數據集中的數據屬性有所有是離散型的,有所有是連續型的,也有離散與連續混合型的。經過對各個數據集的瀏覽,總結出各個數據集的一些基本信息以下:git
連續型數據集: 1. diabets(4:8d-2c) 2. mozilla4(6:5d-2c) 3. pc1(7:21d-2c) 4. pc5(8:38d-2c) 5. waveform-5000(9:40d-3c) 離散型數據集: 1. breast-w(0:9d-2c-?) 離散-連續混合型數據集: 1. colic(1:22d-2c-?) 2. credit-a(2:15d-2c-?) 3. credit-g(3:20d-2c) 4. hepatitis(少許離散屬性)(5:19d-2c-?)
舉一個例子說明,colic(1:22d-2c-?)對應colic這個數據集,冒號前面的1表示人工標註的數據集序號(在代碼實現時我是用序號來映射數據集的),22d表示數據集中包含22個屬性,2c表示數據集共有3種類別,'?'表示該數據集中含有缺失值,在對數據處理前須要注意。github
因爲提供的數據集文件格式是weka的.arff文件,能夠直接導入到weka中選擇各種算法模型進行分析,很是簡便。可是我沒有藉助weka而是使用sklearn來對數據集進行分析的,這樣靈活性更大一點。因此首先須要瞭解.arff的數據組織形式與結構,而後使用numpy讀取到二維數組中。算法
具體作法是過濾掉.arff中'%'開頭的註釋,對於'@'開頭的標籤,只關心'@attribute'後面跟着的屬性名與屬性類型,若是屬性類型是以'{}'圍起來的離散型屬性,就將這些離散型屬性映射到0,1,2......,後面讀取到這一列屬性的數據時直接用建好的映射將字符串映射到數字。除此以外就是數據內容了,讀完一個數據集的內容以後還須要檢測該數據集中是否包含缺失值,這個使用numpy的布爾型索引很容易作到。若是包含缺失值,則統計缺失值這一行所屬類別中全部非缺失數據在缺失屬性上各個值的頻次,而後用出現頻次最高的值來替換缺失值,這就完成對缺失值的填補。具體實現能夠參見preprocess.py模塊中fill_miss函數。數組
實驗環境:網絡
python 3.6.7app
configparser 3.7.4dom
scikit-learn 0.20.2函數
numpy 1.15.4工具
matplotlib 3.0.3
各個分類器都要用到的幾個模塊在這裏作一個簡要說明。
因爲大部分數據集中都包含連續型屬性,因此選擇sklearn.naive_bayes.GaussianNB來對各個數據集進行處理
clf = GaussianNB() skf = StratifiedKFold(n_splits=10) skf_accuracy1 = [] skf_accuracy2 = [] n_classes = np.arange(np.unique(y).size) for train, test in skf.split(X, y): clf.fit(X[train], y[train]) skf_accuracy1.append(clf.score(X[test], y[test])) if n_classes.size < 3: skf_accuracy2.append(roc_auc_score(y[test], clf.predict_proba(X[test])[:, 1], average='micro')) else: ytest_one_hot = label_binarize(y[test], n_classes) skf_accuracy2.append(roc_auc_score(ytest_one_hot, clf.predict_proba(X[test]), average='micro')) accuracy1 = np.mean(skf_accuracy1) accuracy2 = np.mean(skf_accuracy2)
在各個數據集上進行交叉驗證後的accuracy和AUC性能指標以下
能夠看到大部分數據集上的auc指標都比acc高,說明控制好機率閾值(這裏默認0.5)acc可能還有提高空間,由於樣本分佈跟整體分佈還有必定的差距,樣本數布可能很不平衡,而且權衡一個合適的閾值點還須要結合分類問題的背景和關注重點。因爲auc指標考慮到了全部可能閾值劃分狀況,auc越高能說明模型越理想,整體上能表現得更好。
使用sklearn.tree.DecisionTreeClassifier做決策樹分析,而且採用gini係數選擇效益最大的屬性進行劃分,下面給出接口調用方式,交叉驗證方式與前面的naive bayes同樣
clf = DecisionTreeClassifier(random_state=0, criterion='gini')
在各個數據集上進行交叉驗證後的accuracy和AUC性能指標以下
使用sklearn.neighbors.KNeighborsClassifier實現KNN,鄰居數設置爲3即根據最近的3個鄰居來投票抉擇樣本所屬分類,由於數據集最多不超過3類,鄰居數選擇3~6較爲合適,設得更高效果增益不明顯而且時間開銷大,下面給出接口調用方式
clf = KNeighborsClassifier(n_neighbors=3)
在各個數據集上進行交叉驗證後的accuracy和AUC性能指標以下
使用sklearn.neural_network.MLPClassifier實現MLP,設置一層隱藏層100個節點,激活函數relu,優化器Adam,學習率1e-3而且自適應下降,l2正則項懲罰係數,下面給出具體的接口調用方式以及參數配置
clf = MLPClassifier(hidden_layer_sizes=(100), activation='relu', solver='adam', batch_size=128, alpha=1e-4, learning_rate_init=1e-3, learning_rate='adaptive', tol=1e-4, max_iter=200)
在各個數據集上進行交叉驗證後的accuracy和AUC性能指標以下
使用sklean.svm.LinearSVC實現線性SVM分類器,接口調用方式以下
clf = LinearSVC(penalty='l2', random_state=0, tol=1e-4)
在各個數據集上進行交叉驗證後的accuracy和AUC性能指標以下
breast-w數據集上,各分類模型的效果都很好,其中linear svm的準確率最高,mlp的auc值最高
colic數據集上,knn效果不佳,其它分類模型的效果都很好,其中decision tree的準確率最高,mlp的auc值最高
credit-a數據集上,各分類模型的效果都不是很好,其中decision tree的準確率最高,naive bayes的auc值最高
credit-a數據集上,各分類模型的效果都不是很好,其中naive bayes的準確率和auc值都是最高的
diabetes數據集上,各分類模型的效果都不是很好,其中naive bayes的準確率和auc值都是最高的
hepatitis數據集上,各分類模型的準確率都沒達到90%,decision tree的準確率最高,mlp的auc值最高,可是各分類模型的auc值基本都比acc高除了decision tree,說明hepatitis數據集的數據分佈可能不太平衡
經過weka對hepatitis數據集上的正負類進行統計獲得下面的直方圖
從上面的直方圖能夠驗證以前的猜想是對的,hepatitis數據集正負類1:4,數據分佈不平衡,正類遠少於負類樣本數
mozilla4數據集上,各分類模型的表現差別很大,其中knn的acc和auc都是最高的,naivie bayes的acc和auc相差甚大
pc1數據集上,各分類模型的準確率基本都挺高的,可是auc值廣泛都很低,使用weka對數據進行統計分析後發現pc1數據集的正負類比達到13:1,根據auc計算原理可知正類太多可能會致使TPR相比FPR會低不少,從而壓低了auc值
pc5數據集上,各分類模型的準確率都達到了90%以上,可是auc都比acc要低,其中mlp和linear svm的acc與auc相差甚大,緣由估計和pc1差很少,正類樣本太多拉低了AUC,使用weka分析後發現pc5正負類樣本比值達到了32:1,而且數據中夾雜着些許異常的噪聲點
waveform-5000數據集上,各分類模型的準確率基本都是在80%左右,各分類模型的auc基本都有90%除了decision tree之外。waveform-5000是一個三類別的數據集,相比前面的2分類數據集預測難度也會更大,機率閾值的選擇尤其關鍵,一個好的閾值劃分會帶來更高的準確率。
準確率對比
AUC對比
準確率對比
AUC對比
準確率對比
AUC對比
準確率對比
AUC對比
準確率對比
AUC對比
準確率對比
AUC對比
準確率對比
AUC對比
準確率對比
AUC對比
準確率對比
AUC對比
準確率對比
AUC對比
pc1,pc5,waveform-5000,colic,credit-g這幾個數據集的屬性維度都在20維及以上,而對分辨樣本類別有關鍵做用的就只有幾個屬性,因此想到經過降維來擯除干擾屬性以使分類模型更好得學習到數據的特徵。用主成分分析(PCA)降維以後的數據分類效果不佳,考慮到都是帶標籤的數據,就嘗試使用線性判別分析(LDA)利用數據類別信息來降維。可是LDA最多降維到類別數-1,對於二類數據集效果很差。waveform-5000包含三種類別,因而就嘗試用LDA對waveform-5000降維以後再使用各分類模型對其進行學習。
使用sklearn.discriminant_analysis.LinearDiscriminantAnalysis對waveform-5000降維以後的數據樣本分佈散點圖以下,能夠明顯看到數據被聚爲三類,降維以後的數據特徵信息更爲明顯,干擾信息更少,對分類更有利
各分類模型在原數據集和LDA降維數據集上準確率對好比下圖
各分類模型在原數據集和LDA降維數據集上AUC值對好比下圖
能夠看到降維以後的分類效果很理想,不管是acc仍是auc,各個分類模型都獲得了不一樣程度的性能提高
因爲KNN是基於樣本空間的歐氏距離來計算的,而多屬性樣本的各屬性一般有不一樣的量綱和量綱單位,這無疑會給計算樣本之間的真實距離帶來干擾,影響KNN分類效果。爲了消除各屬性之間的量綱差別,須要進行數據標準化處理,計算屬性的z分數來替換原屬性值。在具體的程序設計時使用sklearn.preprocessing.StandardScaler來對數據進行標準化。
bagging with KNN在原數據集和標準化數據集上準確率對好比下圖
bagging with KNN在原數據集和標準化數據集上AUC對好比下圖
能夠看到標準化以後效果仍是不錯的,不管是acc仍是auc,基本在各數據集上都獲得了性能提高
這次實驗讓我對各個分類器的具體用法有了初步的瞭解,不一樣的數據集上應用不一樣分類模型的效果大相徑庭。數據挖掘任務70%時間消耗在數據清洗上,不管什麼分類模型,其在高質量數據上的表現確定是要優於其在低質量數據上的表現。因此拿到一個數據集後不能貿然往上面套分類模型,而是應該先對數據集進行觀察分析,而後利用工具對數據進行清洗、約簡、集成以及轉換,提高數據質量,讓分類更好得學習到數據的特徵,從而有更好的分類效果。本次實驗我也對各數據集進行了預處理,包括數據缺失值填補、數據類型轉換、數據降維、數據標準化等等,這些工做都在各分類模型的分類效果上獲得了必定的反饋。實驗過程當中也遇到了一些問題,好比使用sklearn.metrics.roc_auc_score計算多類別數據的AUC時須要提早將數據標籤轉換爲one hot編碼,LDA最多隻能將數據維度降維到類別數-1等等,這些都爲我之後進行數據挖掘工做積累了寶貴經驗。