python抽樣方法解讀及實現(xiàn)過程
抽樣方法概覽
隨機抽樣—總體個數(shù)較少
每個抽樣單元被抽中的概率相同,并且可以重現(xiàn)。
隨機抽樣常常用于總體個數(shù)較少時,它的主要特征是從總體中逐個抽取。
1、抽簽法
2、隨機數(shù)法:隨機數(shù)表、隨機數(shù)骰子或計算機產(chǎn)生的隨機數(shù)。
分層抽樣——總體存在差異且對結(jié)果有影響
分層抽樣是指在抽樣時,將總體分成互不相交的層,然后按照一定的比例,從各層獨立地抽取一定數(shù)量的個體,將各層取出的個體合在一起作為樣本的方法。層內(nèi)變異越小越好,層間變異越大越好。
分層以后,在每一層進行簡單隨機抽樣,不同群體所抽取的個體個數(shù),一般有三種方法:
(1)等數(shù)分配法,即對每一層都分配同樣的個體數(shù);
(2)等比分配法,即讓每一層抽得的個體數(shù)與該類總體的個體數(shù)之比都相同;
(3)最優(yōu)分配法,即各層抽得的樣本數(shù)與所抽得的總樣本數(shù)之比等于該層方差與各類方差之和的比。
import pandas as pd import random as rd import numpy as np import math as ma def typeicalSampling(group, typeicalFracDict): name = group.name frac = typeicalFracDict[name] return group.sample(frac=frac) def group_sample(data_set,lable,typeicalFracDict): #分層抽樣 #data_set數(shù)據(jù)集 #lable分層變量名 #typeicalFracDict:分類抽樣比例 gbr=data_set.groupby(by=[lable]) result=data_set.groupby(lable,group_keys=False).apply(typeicalSampling,typeicalFracDict) return result data = pd.DataFrame({'id': [3566841, 6541227, 3512441, 3512441, 3512441,3512441, 3512441, 3512441, 3512441, 3512441], 'sex': ['male', 'Female', 'Female','male', 'Female', 'Female','male', 'Female','male', 'Female'], 'level': ['high', 'low', 'middle','high', 'low', 'middle','high', 'low', 'middle','middle']}) data_set=data label='sex' typicalFracDict = { 'male': 0.8, 'Female': 0.2 } result=group_sample(data_set,label,typicalFracDict) print(result)
整體抽樣
整群抽樣又稱聚類抽樣,是將總體中各單位歸并成若干個互不交叉、互不重復(fù)的集合,稱之為群;然后以群為抽樣單位抽取樣本的一種抽樣方式。
應(yīng)用整群抽樣時,要求各群有較好的代表性,即群內(nèi)各單位的差異要大,群間差異要小。
實施步驟
先將總體分為i個群,然后從i個群中隨即抽取若干個群,對這些群內(nèi)所有個體或單元均進行調(diào)查。抽樣過程可分為以下幾個步驟:
(1)確定分群的標(biāo)注
(2)總體(N)分成若干個互不重疊的部分,每個部分為一群。
(3)據(jù)各樣本量,確定應(yīng)該抽取的群數(shù)。
(4)采用簡單隨機抽樣或系統(tǒng)抽樣方法,從i群中抽取確定的群數(shù)。
系統(tǒng)抽樣——總體多
系統(tǒng)抽樣亦稱為機械抽樣、等距抽樣。 [4] 當(dāng)總體中的個體數(shù)較多時,采用簡單隨機抽樣顯得較為費事。這時,可將總體分成均衡的幾個部分,然后按照預(yù)先定出的規(guī)則,從每一部分抽取一個個體,得到所需要的樣本,這種抽樣叫做系統(tǒng)抽樣。 [1]
def SystematicSampling(dataMat,number): length=len(dataMat) k=int(length/number) sample=[] i=0 if k>0 : while len(sample)!=number: sample.append(dataMat[0+i*k]) i+=1 return sample else : return RandomSampling(dataMat,number)
過采樣
1、RandomOverSampler
原理:從樣本少的類別中隨機抽樣,再將抽樣得來的樣本添加到數(shù)據(jù)集中。
缺點:重復(fù)采樣往往會導(dǎo)致嚴(yán)重的過擬合
主流過采樣方法是通過某種方式人工合成一些少數(shù)類樣本,從而達到類別平衡的目的,而這其中的鼻祖就是SMOTE。
from imblearn.over_sampling import RandomOverSampler ros = RandomOverSampler(sampling_strategy={0: 700,1:200,2:150 },random_state=0) X_resampled, y_resampled = ros.fit_sample(X, y) print(Counter(y_resampled))
2、SMOTE
原理:在少數(shù)類樣本之間進行插值來產(chǎn)生額外的樣本。對于少數(shù)類樣本a, 隨機選擇一個最近鄰的樣本b, 從a與b的連線上隨機選取一個點c作為新的少數(shù)類樣本;
具體地,對于一個少數(shù)類樣本xi使用K近鄰法(k值需要提前指定),求出離xi距離最近的k個少數(shù)類樣本,其中距離定義為樣本之間n維特征空間的歐氏距離。
然后從k個近鄰點中隨機選取一個,使用下列公式生成新樣本:
from imblearn.over_sampling import SMOTE smo = SMOTE(sampling_strategy={0: 700,1:200,2:150 },random_state=42) X_smo, y_smo = smo.fit_sample(X, y) print(Counter(y_smo))
SMOTE會隨機選取少數(shù)類樣本用以合成新樣本,而不考慮周邊樣本的情況,這樣容易帶來兩個問題:
1)如果選取的少數(shù)類樣本周圍也都是少數(shù)類樣本,則新合成的樣本不會提供太多有用信息。
2)如果選取的少數(shù)類樣本周圍都是多數(shù)類樣本,這類的樣本可能是噪音,則新合成的樣本會與周圍的多數(shù)類樣本產(chǎn)生大部分重疊,致使分類困難。
總的來說我們希望新合成的少數(shù)類樣本能處于兩個類別的邊界附近,這樣往往能提供足夠的信息用以分類。而這就是下面的 Border-line SMOTE 算法要做的事情。
3、BorderlineSMOTE
這個算法會先將所有的少數(shù)類樣本分成三類,如下圖所示:
noise
:所有的k近鄰個樣本都屬于多數(shù)類danger
: 超過一半的k近鄰樣本屬于多數(shù)類safe
:超過一半的k近鄰樣本屬于少數(shù)類
Border-line SMOTE算法只會從處于”danger“狀態(tài)的樣本中隨機選擇,然后用SMOTE算法產(chǎn)生新的樣本。處于”danger“狀態(tài)的樣本代表靠近”邊界“附近的少數(shù)類樣本,而處于邊界附近的樣本往往更容易被誤分類。因而 Border-line SMOTE 只對那些靠近”邊界“的少數(shù)類樣本進行人工合成樣本,而 SMOTE 則對所有少數(shù)類樣本一視同仁。
Border-line SMOTE 分為兩種:Borderline-1 SMOTE 和 Borderline-2 SMOTE。 Borderline-1 SMOTE 在合成樣本時式中的x^
是一個少數(shù)類樣本,而 Borderline-2 SMOTE 中的x^則是k近鄰中的任意一個樣本。
from imblearn.over_sampling import BorderlineSMOTE smo = BorderlineSMOTE(kind='borderline-1',sampling_strategy={0: 700,1:200,2:150 },random_state=42) #kind='borderline-2' X_smo, y_smo = smo.fit_sample(X, y) print(Counter(y_smo))
4、ADASYN
原理:采用某種機制自動決定每個少數(shù)類樣本需要產(chǎn)生多少合成樣本,而不是像SMOTE那樣對每個少數(shù)類樣本合成同數(shù)量的樣本。先確定少數(shù)樣本需要合成的樣本數(shù)量(與少數(shù)樣本周圍的多數(shù)類樣本數(shù)呈正相關(guān)),然后利用SMOTE合成樣本。
缺點:ADASYN的缺點是易受離群點的影響,如果一個少數(shù)類樣本的K近鄰都是多數(shù)類樣本,則其權(quán)重會變得相當(dāng)大,進而會在其周圍生成較多的樣本。
from imblearn.over_sampling import ADASYN ana = ADASYN(sampling_strategy={0: 800,2:300,1:400 },random_state=0) X_ana, y_ana = ana.fit_sample(X, y)
用 SMOTE 合成的樣本分布比較平均,而Border-line SMOTE合成的樣本則集中在類別邊界處。ADASYN的特性是一個少數(shù)類樣本周圍多數(shù)類樣本越多,則算法會為其生成越多的樣本,從圖中也可以看到生成的樣本大都來自于原來與多數(shù)類比較靠近的那些少數(shù)類樣本。
5、KMeansSMOTE
原理:在使用SMOTE進行過采樣之前應(yīng)用KMeans聚類。
KMeansSMOTE包括三個步驟:聚類、過濾和過采樣。在聚類步驟中,使用k均值聚類為k個組。過濾選擇用于過采樣的簇,保留具有高比例的少數(shù)類樣本的簇。然后,它分配合成樣本的數(shù)量,將更多樣本分配給少數(shù)樣本稀疏分布的群集。最后,過采樣步驟,在每個選定的簇中應(yīng)用SMOTE以實現(xiàn)少數(shù)和多數(shù)實例的目標(biāo)比率。
from imblearn.over_sampling import KMeansSMOTE kms = KMeansSMOTE(sampling_strategy={0: 800,2:300,1:400 },random_state=42) X_kms, y_kms = kms.fit_sample(X, y) print(Counter(y_kms))
6、SMOTENC
可處理分類特征的SMOTE
from imblearn.over_sampling import SMOTENC sm = SMOTENC(random_state=42, categorical_features=[18, 19])
7、SVMSMOTE
使用支持向量機分類器產(chǎn)生支持向量然后再生成新的少數(shù)類樣本,然后使用SMOTE合成樣本
from imblearn.over_sampling import SVMSMOTE svmm = SVMSMOTE(sampling_strategy={0: 800,2:300,1:400 },random_state=42) X_svmm, y_svmm = svmm.fit_sample(X, y) print(Counter(y_kms))
下采樣
1、RandomUnderSampler(可控制欠采樣數(shù)量)
原理:從多數(shù)類樣本中隨機選取一些剔除掉。
缺點:被剔除的樣本可能包含著一些重要信息,致使學(xué)習(xí)出來的模型效果不好。
from imblearn.under_sampling import RandomUnderSampler cc = RandomUnderSampler(sampling_strategy={0: 50,2:100,1:100 },random_state=0) X_resampled, y_resampled = cc.fit_sample(X, y) print(sorted(Counter(y_resampled).items()))
2、NearMiss(可控制欠采樣數(shù)量)
原理:從多數(shù)類樣本中選取最具代表性的樣本用于訓(xùn)練,主要是為了緩解隨機欠采樣中的信息丟失問題。
NearMiss采用一些啟發(fā)式的規(guī)則來選擇樣本,根據(jù)規(guī)則的不同可分為3類,通過設(shè)定version參數(shù)來確定:
NearMiss-1
:選擇到最近的K個少數(shù)類樣本平均距離最近的多數(shù)類樣本NearMiss-2
:選擇到最遠(yuǎn)的K個少數(shù)類樣本平均距離最近的多數(shù)類樣本NearMiss-3
:對于每個少數(shù)類樣本選擇K個最近的多數(shù)類樣本,目的是保證每個少數(shù)類樣本都被多數(shù)類樣本包圍
NearMiss-1和NearMiss-2的計算開銷很大,因為需要計算每個多類別樣本的K近鄰點。另外,NearMiss-1易受離群點的影響,
from imblearn.under_sampling import NearMiss nm1 = NearMiss(sampling_strategy={0: 50,2:100,1:100 },random_state=0, version=1) X_resampled_nm1, y_resampled = nm1.fit_sample(X, y) print(sorted(Counter(y_resampled).items()))
3、ClusterCentroids(可控制欠采樣數(shù)量)
原理:利用kmeans將對各類樣本分別聚類,利用質(zhì)心替換整個簇的樣本。
from imblearn.under_sampling import ClusterCentroids cc = ClusterCentroids(sampling_strategy={0: 700,1:100,2:90 },random_state=0) X_resampled, y_resampled = cc.fit_sample(X, y) print(sorted(Counter(y_resampled).items()))
4、TomekLinks(數(shù)據(jù)清洗方法,無法控制欠采樣數(shù)量)
原理:Tomek Link表示不同類別之間距離最近的一對樣本,即這兩個樣本互為最近鄰且分屬不同類別。這樣如果兩個樣本形成了一個Tomek Link,則要么其中一個是噪音,要么兩個樣本都在邊界附近。這樣通過移除Tomek Link就能“清洗掉”類間重疊樣本,使得互為最近鄰的樣本皆屬于同一類別,從而能更好地進行分類。
from imblearn.under_sampling import TomekLinks nm1 = TomekLinks(sampling_strategy='all',random_state=0) X_resampled_nm1, y_resampled = nm1.fit_sample(X, y) print(sorted(Counter(y_resampled).items()))
TomekLinks函數(shù)中的auto參數(shù)控制Tomek’s links中的哪些樣本被剔除. 默認(rèn)的ratio=‘auto’ 移除多數(shù)類的樣本, 當(dāng)ratio='all’時, 兩個樣本均被移除.
5、EditedNearestNeighbours(數(shù)據(jù)清洗方法,無法控制欠采樣數(shù)量)
原理:對于屬于多數(shù)類的一個樣本,如果其K個近鄰點有超過一半(kind_sel=‘mode’)或全部(kind_sel=‘all’)都不屬于多數(shù)類,則這個樣本會被剔除。
from imblearn.under_sampling import EditedNearestNeighbours renn = EditedNearestNeighbours(kind_sel='all') X_res, y_res = renn.fit_resample(X, y) print(sorted(Counter(y_res).items()))
6、RepeatedEditedNearestNeighbours (數(shù)據(jù)清洗方法,無法控制欠采樣數(shù)量)
原理:重復(fù)EditedNearestNeighbours多次(參數(shù)max_iter控制迭代次數(shù))
#下采樣RepeatedEditedNearestNeighbours接口 from imblearn.under_sampling import RepeatedEditedNearestNeighbours renn = RepeatedEditedNearestNeighbours(kind_sel='all',max_iter=101) X_res, y_res = renn.fit_resample(X, y) print(sorted(Counter(y_res).items()))
7、ALLKNN(數(shù)據(jù)清洗方法,無法控制欠采樣數(shù)量)
from imblearn.under_sampling import AllKNN renn = AllKNN(kind_sel='all') X_res, y_res = renn.fit_resample(X, y) print(sorted(Counter(y_res).items()))
8、CondensedNearestNeighbour (數(shù)據(jù)清洗方法,無法控制欠采樣數(shù)量)
使用近鄰的方法來進行迭代, 來判斷一個樣本是應(yīng)該保留還是剔除, 具體的實現(xiàn)步驟如下:
1)集合C: 所有的少數(shù)類樣本;
2)選擇一個多數(shù)類樣本(需要下采樣)加入集合C, 其他的這類樣本放入集合S;
3)使用集合S訓(xùn)練一個1-NN的分類器, 對集合S中的樣本進行分類;
4)將集合S中錯分的樣本加入集合C;
5)重復(fù)上述過程, 直到?jīng)]有樣本再加入到集合C.
from imblearn.under_sampling import CondensedNearestNeighbour renn = CondensedNearestNeighbour(random_state=0) X_res, y_res = renn.fit_resample(X, y) print(sorted(Counter(y_res).items()))
CondensedNearestNeighbour方法對噪音數(shù)據(jù)是很敏感的, 也容易加入噪音數(shù)據(jù)到集合C中.
9、OneSidedSelection (數(shù)據(jù)清洗方法,無法控制欠采樣數(shù)量)
原理:在CondensedNearestNeighbour的基礎(chǔ)上使用 TomekLinks 方法來剔除噪聲數(shù)據(jù)(多數(shù)類樣本).
from imblearn.under_sampling import OneSidedSelection oss = OneSidedSelection(random_state=0) X_resampled, y_resampled = oss.fit_sample(X, y) print(sorted(Counter(y_resampled).items()))
10、NeighbourhoodCleaningRule (數(shù)據(jù)清洗方法,無法控制欠采樣數(shù)量)
from sklearn.linear_model import LogisticRegression from imblearn.under_sampling import InstanceHardnessThreshold iht = InstanceHardnessThreshold(random_state=0, estimator=LogisticRegression()) X_resampled, y_resampled = iht.fit_sample(X, y) print(sorted(Counter(y_resampled).items()))
11、InstanceHardnessThreshold(數(shù)據(jù)清洗方法,無法控制欠采樣數(shù)量)
在數(shù)據(jù)上運用一種分類器, 然后將概率低于閾值的樣本剔除掉.
from sklearn.linear_model import LogisticRegression from imblearn.under_sampling import InstanceHardnessThreshold iht = InstanceHardnessThreshold(random_state=0, estimator=LogisticRegression()) X_resampled, y_resampled = iht.fit_sample(X, y) print(sorted(Counter(y_resampled).items()))
12、EasyEnsemble(可控制數(shù)量)
從多數(shù)類樣本中隨機抽樣成子集,該子集的數(shù)量等于少數(shù)類樣本的數(shù)量。接著將該子集與少數(shù)類樣本結(jié)合起來訓(xùn)練一個模型,迭代n次。這樣雖然每個子集的樣本少于總體樣本,但集成后總信息量并不減少。
from imblearn.ensemble import EasyEnsemble ee = EasyEnsemble(sampling_strategy={0: 500,1:199,2:89 },random_state=0, n_subsets=10) X_resampled, y_resampled = ee.fit_sample(X, y) print(X_resampled.shape) print(y_resampled.shape) print(sorted(Counter(y_resampled[0]).items()))
有兩個很重要的參數(shù):
(i) n_subsets 控制的是子集的個數(shù)
(ii) replacement 決定是有放回還是無放回的隨機采樣.
13、BalanceCascade(可控制數(shù)量)
在第n輪訓(xùn)練中,將從多數(shù)類樣本中抽樣得來的子集與少數(shù)類樣本結(jié)合起來訓(xùn)練一個基學(xué)習(xí)器H,訓(xùn)練完后多數(shù)類中能被H正確分類的樣本會被剔除。在接下來的第n+1輪中,從被剔除后的多數(shù)類樣本中產(chǎn)生子集用于與少數(shù)類樣本結(jié)合起來訓(xùn)練。
同樣, n_max_subset 參數(shù)控制子集的個數(shù), 以及可以通過設(shè)置bootstrap=True來使用bootstraping(自助法).
from imblearn.ensemble import BalanceCascade from sklearn.linear_model import LogisticRegression bc = BalanceCascade(random_state=0, estimator=LogisticRegression(random_state=0), n_max_subset=4) X_resampled, y_resampled = bc.fit_sample(X, y) print(X_resampled.shape) print(sorted(Counter(y_resampled[0]).items()))
過采樣與下采樣結(jié)合
SMOTE算法的缺點是生成的少數(shù)類樣本容易與周圍的多數(shù)類樣本產(chǎn)生重疊難以分類,而數(shù)據(jù)清洗技術(shù)恰好可以處理掉重疊樣本,所以可以將二者結(jié)合起來形成一個pipeline,先過采樣再進行數(shù)據(jù)清洗。主要的方法是 SMOTE + ENN 和 SMOTE + Tomek ,其中 SMOTE + ENN 通常能清除更多的重疊樣本.
1、SMOTEENN
from imblearn.combine import SMOTEENN smote_enn = SMOTEENN(random_state=0) X_resampled, y_resampled = smote_enn.fit_sample(X, y) print(sorted(Counter(y_resampled).items()))
2、 SMOTETomek
from imblearn.combine import SMOTETomek smote_tomek = SMOTETomek(sampling_strategy={0: 700,1:300,2:200 },random_state=0) X_resampled, y_resampled = smote_tomek.fit_sample(X, y) print(sorted(Counter(y_resampled).items()))
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
selenium+python實現(xiàn)文件上傳操作的方法實例
文件上傳功能是我們在日常開發(fā)中經(jīng)常會遇到的一個需求,下面這篇文章主要給大家介紹了關(guān)于selenium+python實現(xiàn)文件上傳操作的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2021-08-08python實現(xiàn)猜數(shù)游戲(保存游戲記錄)
這篇文章主要為大家詳細(xì)介紹了python實現(xiàn)猜數(shù)游戲,保存游戲記錄,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2020-06-06