想象一下丙笋,假如今天是你作為數(shù)據(jù)分析師入職的第一天捐凭,老板交給你一個數(shù)據(jù)分析任務:通過公司已經(jīng)有的信用卡用戶和交易信息淑廊,預測用戶未來是否會逾期還款。
這個問題看似簡單旧烧,實則隱藏了一個非常大的坑:據(jù)粗略估計影钉,全國的信用卡平均不良率只有不到1%,也就是說掘剪,銀行貸出100萬平委,可能只有1萬沒有辦法正常收回,這樣夺谁,如果你拿到一個信用卡還款數(shù)據(jù)集廉赔,很大可能是這個數(shù)據(jù)集里有99%的正樣本,1%的負樣本匾鸥,在預測的時候可能模型對于負樣本的特征表現(xiàn)并不敏感蜡塌。
同樣的,這樣的場景還有:檢測某平臺所有交易訂單中的欺詐訂單(畢竟大多數(shù)用戶都是正常交易的老實人)勿负、檢測銀行中的洗錢交易馏艾、預測大型企業(yè)客戶的流失等等。
我們常說的類別不平衡問題奴愉,就是數(shù)據(jù)集中存在某一類樣本琅摩,其數(shù)量遠多于或遠少于其他類樣本,從而導致一些機器學習模型失效的問題躁劣。
對于這種情況迫吐,在機器學習界,只要祭出三板斧账忘,就可以解決絕大部分的數(shù)據(jù)不平衡問題志膀,讓你的模型所向披靡,預測能力取得一個質(zhì)的飛躍鳖擒。這三板斧分別是:過采樣(欠采樣)溉浙、對不同類樣本設置不同的懲罰權重、集成學習中的bagging方法蒋荚。下面戳稽,我們首先學習第一大絕招:過采樣(欠采樣)的原理和實現(xiàn)。
無論是過采樣還是欠采樣期升,無非就是兩種思路:一是補惊奇,給樣本量少的那個類別增加樣本量;二是刪播赁,刪掉一部分樣本量多的類別颂郎。最終達到每個類別的樣本數(shù)量平衡的目的。
一容为、過采樣(over-sampling)
又稱上采樣乓序。過采樣繼承了“補”的思路寺酪,通過增加分類中少數(shù)類樣本的數(shù)量來實現(xiàn)樣本均衡。過采樣最直接的方法就是將少數(shù)類的樣本多復制幾份替劈。但是這種方法的缺點是:如果樣本特征太少寄雀,這些重復的樣本就可能導致過擬合的問題。一般情況下陨献,我們不是簡單復制幾份盒犹,而是在復制的同時加一些隨機噪聲、干擾數(shù)據(jù)等眨业,防止模型過擬合阿趁。
另一種解決方法就是通過特定的算法合成新的樣本。
其實這些算法執(zhí)行流程并沒有那么難理解坛猪,算法實現(xiàn)起來也并不是很難。以典型的過采樣算法smote算法為例皂股,算法流程如下:
假設有兩個class:class1 和 class2 墅茉,其中class1樣本數(shù)少。
步驟1:從class1中隨機選擇一個點C呜呐,找到該點的K個鄰居
步驟2:從K個鄰居中隨機選擇一個點C_ne
步驟3:連接C與C1就斤,在C與C_ne的連線上生成新的點C_new
步驟4:重復1-4 M步驟,可構造M個點
在Python中蘑辑,處理樣本不均衡問題我們需要用到一個包:imbalanced-learn洋机。
首先,安裝這個包:pip install imbalanced-learn
我們先用 https://zhuanlan.zhihu.com/p/95412564 中講的生成數(shù)據(jù)集的方法生成一個正負樣本量不均衡的數(shù)據(jù)集洋魂。
from sklearn import datasets
# 生成
X,Y = datasets.make_classification(n_samples = 20,
n_features = 4,
n_classes = 2,
weights = [0.3,0.7])
print(X)
print(Y)
輸出結(jié)果如下:
[[ 1.21706083 1.12986 1.2998324 1.15376352] [ 1.17533636 -1.29561194 -0.28954016 1.00276647] [ 1.50145008 -0.06476093 0.65946499 1.35525496] [-0.69105133 -1.72583842 -1.4398602 -0.70573952] [ 0.52003318 -0.53992062 -0.10653626 0.44523502] [-1.2449438 1.44815687 0.35575841 -1.05861377] [-0.69626765 0.51388754 0.00736094 -0.60588014] [ 0.28817084 2.14562256 1.52336461 0.36087658] [-0.60796446 -0.04013406 -0.30997876 -0.55186576] [-1.50124558 2.42594496 0.86890189 -1.24482048] [ 0.4807009 -0.150123 0.12738589 0.42785389] [ 1.61349955 -1.76329405 -0.38756462 1.37731124] [ 1.52055699 1.23124411 1.50722703 1.43305357] [ 0.18461106 -0.67446852 -0.35030985 0.13551482] [ 1.10954433 1.00010374 1.16562311 1.05044065] [ 0.96242505 2.41142144 2.01037078 0.98324786] [-0.93460516 -1.2828331 -1.2668987 -0.90538419] [ 0.74531935 1.24987676 1.15714557 0.73260898] [ 0.65228896 -0.50904671 -0.02477175 0.56632109] [-0.06905236 -0.20338623 -0.16389815 -0.07196445]]
[1 1 1 0 1 0 1 1 0 0 1 1 1 0 1 1 0 1 1 1]
可以看到生成的標簽中绷旗,0標簽和1標簽的比例是3:7。
我們以SMOTE算法作為過采樣算法對不均衡樣本進行處理:
from imblearn.over_sampling import SMOTE # 導入過采樣處理庫SMOTE
# 使用SMOTE方法進行過采樣處理
smote = SMOTE() # 建立SMOTE模型對象
X_new, Y_new = smote.fit_sample(X, Y) # 輸入數(shù)據(jù)并作過采樣處理
print('Y_new:',Y_new)
print('Y_new長度:',len(Y_new))
輸出如下:
Y_new: [1 1 1 0 1 0 1 1 0 0 1 1 1 0 1 1 0 1 1 1 0 0 0 0 0 0 0 0]
Y_new長度: 28
可以看到副砍,算法補充了8個0樣本衔肢,使得0、1類別的比例變成了1:1
除此之外豁翎,還有這些過采樣函數(shù)可以調(diào)用:
- over_sampling.ADASYN()
- over_sampling.KMeansSMOTE()
- over_sampling.RandomOverSampler()
- over_sampling.SMOTE()
- over_sampling.SMOTENC()
- over_sampling.SVMSMOTE()
二角骤、欠采樣
又稱下采樣(under-sampling),這是繼承了“刪”的思路心剥,通過刪掉一部分多類樣本的數(shù)量來實現(xiàn)樣本均衡邦尊,最直接的方法是隨機去掉一些多數(shù)類樣本來減小多數(shù)類的規(guī)模。這樣做的缺點也很明顯优烧,可能刪得太過分蝉揍,把數(shù)量多的類別的樣本中一些重要的信息也刪除掉。
當然匙隔,為了避免這種情況疑苫,我們也可以采用一些成熟的欠采樣算法熏版,我們以RandomUnderSampler為例。
from imblearn.under_sampling import RandomUnderSampler # 導入欠采樣處理庫Random UnderSampler
# 使用RandomUnderSampler方法進行欠采樣處理
RandomUnderSampler = RandomUnderSampler() # 建立RandomUnderSampler模型對象
X_new, Y_new = RandomUnderSampler.fit_sample(X,Y) # 輸入數(shù)據(jù)并進行欠采樣處理
print('Y_new:',Y_new)
print('Y_new長度:',len(Y_new))
輸出如下:
Y_new: [0 0 0 0 0 0 1 1 1 1 1 1]
Y_new長度: 12
可以看到捍掺,算法舍棄了8個1樣本撼短,使得0、1類別得比例變成1:1挺勿。
不管是欠采樣還是過采樣曲横,如果想自己決定采樣數(shù)量,可以添加這個參數(shù):sampling_strategy = {類別:個數(shù)}:每個類別得采樣個數(shù)(在0.6版本以前是ratio參數(shù))不瓶。
還有這些欠采樣函數(shù)可以調(diào)用:
- under_sampling.CondensedNearestNeighbour()
- under_sampling.EditedNearestNeighbours()
- under_sampling.RepeatedEditedNearestNeighbours()
- under_sampling.AllKNN()
- under_sampling.InstanceHardnessThreshold()
- under_sampling.NearMiss()
- under_sampling.NeighbourhoodCleaningRule()
- under_sampling.OneSidedSelection()
- under_sampling.RandomUnderSampler()
- under_sampling.TomekLinks()
總體上禾嫉,過采樣和欠采樣更適合大數(shù)據(jù)分布不均衡的情況,尤其是過采樣方法蚊丐,應用極為廣泛熙参。
三、擴展閱讀
imbalanced-learn文檔鏈接:https://imbalanced-learn.readthedocs.io/en/stable/api.html