【火爐煉AI】機器學習015-如何處理樣本數誤差較大的數據集
(本文所使用的Python庫和版本號: Python 3.5, Numpy 1.14, scikit-learn 0.19, matplotlib 2.2 )git
咱們獲得的數據集在絕大多數狀況下,都不是理想的數據集,都須要通過各類各樣的處理,其中的一個處理方式就是,如何處理樣本數誤差較大的數據集。好比對於某種疾病的發生機率是1%,即得到的天然狀態下的數據集中大約99%的樣本都是正常的,那麼此時,經過模型進行訓練,獲得的模型在對新樣本進行預測時,也每每偏向於樣本數較大的類別,此時或極大的下降小樣本類別的召回率。github
<br/>dom
1. 查看數據集的特徵
此處所使用的是書本《Python機器學習經典實例》第三章的非平衡數據集,此處我用pandas讀取到內存中,經過info()來查看該數據集的基本狀況,代碼以下:機器學習
# 準備數據集 data_path='E:\PyProjects\DataSet\FireAI/data_multivar_imbalance.txt' df=pd.read_csv(data_path,header=None) # print(df.head()) # 沒有問題 print(df.info()) # 查看數據信息,確保沒有錯誤 dataset_X,dataset_y=df.iloc[:,:-1],df.iloc[:,-1] # print(dataset_X.head()) # print(dataset_X.info()) # print(dataset_y.head()) # 檢查沒問題 dataset_X=dataset_X.values dataset_y=dataset_y.values
-------------------------------------輸---------出--------------------------------函數
<class 'pandas.core.frame.DataFrame'> RangeIndex: 1200 entries, 0 to 1199 Data columns (total 3 columns): 0 1200 non-null float64 1 1200 non-null float64 2 1200 non-null int64 dtypes: float64(2), int64(1) memory usage: 28.2 KB None性能
--------------------------------------------完-------------------------------------學習
能夠看出,該數據集只有兩個features,一個label,且整個數據集有1200個樣本。能夠經過查看數據集的2D分佈來初步的瞭解該數據集的樣本誤差。以下圖所示:url
########################小**********結###############################spa
1. 數據集中不一樣類別之間樣本數誤差比較大,此時須要作進一步處理。.net
2. 數據集的加載和顯示等,在前面的文章中已經講爛了,此處無需贅言。
#################################################################
<br/>
2. 用線性SVM分類器構建分類模型
從上面的數據集分佈圖中能夠大體看出,這個模型不是簡單的線性模型,固然,爲了對比效果,此處我仍然使用線性SVM分類器來構建分類模型,看一下效果。
代碼以下:
# 將整個數據集劃分爲train set和test set from sklearn.model_selection import train_test_split train_X, test_X, train_y, test_y=train_test_split( dataset_X,dataset_y,test_size=0.25,random_state=42) # 若是用線性SVM分類器來進行分類,看看是什麼結果 # 使用線性核函數初始化一個SVM對象。 from sklearn.svm import SVC classifier=SVC(kernel='linear') # 構建線性分類器 classifier.fit(train_X,train_y)
而後在經過plot_classifier()函數將這個模型的分類效果畫出來。
# 模型在訓練集上的性能報告: from sklearn.metrics import classification_report plot_classifier(classifier,train_X,train_y) # 分類器在訓練集上的分類效果 target_names = ['Class-0', 'Class-1'] y_pred=classifier.predict(train_X) print(classification_report(train_y, y_pred, target_names=target_names))
-------------------------------------輸---------出--------------------------------
precision recall f1-score support
Class-0 0.00 0.00 0.00 151 Class-1 0.83 1.00 0.91 749
avg / total 0.69 0.83 0.76 900
--------------------------------------------完-------------------------------------
能夠看出,線性SVM分類器徹底沒有將class_0區分出來,獲得的各類指標都是0,從分類效果圖中也能夠看到,根本就沒有線性平面。
########################小**********結###############################
1. 因爲本數據集存在樣本數量誤差,故而使用線性SVM分類器沒有任何效果。
#################################################################
<br/>
3. 解決樣本數量誤差的方法
從上面能夠看出,因爲樣本數量誤差的存在,使用線性SVM分類器沒有任何效果,那麼咱們該怎麼處理這種數據集了?
SVM內部存在一個class_weight參數,咱們能夠設置該參數爲"balanced",來調節各類類別樣本數量的權重,使其達到平衡。以下代碼:
# 看來直接使用簡單的線性SVM分類器難以將class_0區分出來,故而咱們要調整數據集中樣本的數量權重 classifier2=SVC(kernel='linear',class_weight='balanced') # 比上面的分類器增長了 class_weight=‘balanced'參數 classifier2.fit(train_X,train_y) # 模型在訓練集上的性能報告: plot_classifier(classifier2,train_X,train_y) # 分類器在訓練集上的分類效果 target_names = ['Class-0', 'Class-1'] y_pred2=classifier2.predict(train_X) print(classification_report(train_y, y_pred2, target_names=target_names))
-------------------------------------輸---------出--------------------------------
precision recall f1-score support
Class-0 0.35 0.86 0.50 151 Class-1 0.96 0.68 0.79 749
avg / total 0.86 0.71 0.74 900
--------------------------------------------完-------------------------------------
從分類效果圖中能夠看出,此時可使用線性SVM來對數據集進行訓練,並能獲得效果還不錯的分類模型,從分類結果報告中能夠看出,各類指標也還不錯,但也存在較大的提高空間。
########################小**********結###############################
1. 在定義SVM分類器時,只須要設置class_weight=balanced便可消除數據集中樣本數量誤差的問題。
2. 若是分類器的效果不理想,那麼須要考慮是不是數據集存在明顯的樣本數量誤差問題。
#################################################################
<br/>
注:本部分代碼已經所有上傳到(個人github)上,歡迎下載。
參考資料:
1, Python機器學習經典實例,Prateek Joshi著,陶俊傑,陳小莉譯