在機器學習中采樣主要分為兩種,過采樣(Oversample)和欠采樣(Undersample)。過采樣就是通過增加少數類樣本的數量來平衡數據集。而欠采樣就是通過減少多數類樣本的數量來平衡數據集。
通常在進行采樣中以下是幾種常用的方法:
1. 隨機采樣
隨機采樣適用于過采樣和欠采樣。其操作方法就是隨機復制增加少數類樣本或者隨機增加刪除減少多數類樣本。
下面是一個代碼例子:
import numpy as np
import pandas as pd
from sklearn.datasets import make_classification
from imblearn.over_sampling import RandomOverSampler
from imblearn.under_sampling import RandomUnderSampler#創建一個不平衡的分類數據集
X, y = make_classification(n_classes=2, class_sep=2,weights=[0.1, 0.9], n_informative=3, n_redundant=1,flip_y=0,n_features=20, n_clusters_per_class=1, n_samples=1000, random_state=10)df = pd.DataFrame(X)
df['target'] = y
# 查看類別分布
print("Original dataset shape:", df['target'].value_counts())# 隨機過采樣
ros = RandomOverSampler(random_state=42)
X_resampled_ros, y_resampled_ros = ros.fit_resample(X, y)
df_ros = pd.DataFrame(X_resampled_ros)
df_ros['target'] = y_resampled_ros
# 查看過采樣后的類別分布
print("Resampled dataset shape (Oversampling):", df_ros['target'].value_counts())#隨機負采樣
rus = RandomUnderSampler(random_state=42)
X_resampled_rus, y_resampled_rus = rus.fit_resample(X, y)
df_rus = pd.DataFrame(X_resampled_rus)
df_rus['target'] = y_resampled_rus
print("Resampled dataset shape (Undersampling):", df_rus['target'].value_counts())
2.SMOTE
通過在少數類樣本之間插值生成合成樣本,通常用于過采樣。
import numpy as np
import pandas as pd
from sklearn.datasets import make_classification
from imblearn.over_sampling import SMOTE# 省略df
#......
# 過采樣
smote = SMOTE(random_state=42)X_resampled_smote, y_resampled_smote = smote.fit_resample(X, y)
df_smote = pd.DataFrame(X_resampled_smote)
df_smote['target'] = y_resampled_smote
print("Resampled dataset shape (SMOTE):", df_smote['target'].value_counts())
3.Tomek Links
這種方法是通過刪除多數類中靠近少數類的邊界樣本來實現欠采樣。工作原理如下:
計算最近鄰:對于每個樣本,計算其最近鄰樣本。
識別 Tomek Links:如果一個多數類樣本的最近鄰是一個少數類樣本,那么這兩個樣本構成一個 Tomek Link。
移除多數類樣本:從數據集中移除那些構成 Tomek Link 的多數類樣本。
重復上述步驟:直到沒有更多的 Tomek Links?
Tomek Links通過移除邊界上的多數類樣本,可以減少多數類樣本的數量,同時盡量保留數據集的結構信息。適用于處理那些多數類樣本與少數類樣本緊密相連的情況。但是同時Tomek Links不能完全平衡數據集,因為移除的樣本數量有限。
import numpy as np
import pandas as pd
from sklearn.datasets import make_classification
from imblearn.under_sampling import TomekLinks# 初始化 TomekLinks
tomek = TomekLinks()# 欠采樣
X_resampled_tomek, y_resampled_tomek = tomek.fit_resample(X, y)df_tomek = pd.DataFrame(X_resampled_tomek)
df_tomek['target'] = y_resampled_tomek
print("Resampled dataset shape (Tomek Links):", df_tomek['target'].value_counts())
4.NearMiss
NearMiss 是一種基于最近鄰的欠采樣方法,用于處理不平衡數據集。它的核心思想是通過移除多數類中與少數類樣本距離較近的樣本,或者移除多數類中距離最遠的樣本,從而減少多數類的樣本數量。NearMiss 提供了多種策略來選擇需要移除的樣本。
import numpy as np
import pandas as pd
from sklearn.datasets import make_classification
from imblearn.under_sampling import NearMiss# df#NearMiss 提供了三種策略:
#版本 1:移除多數類中與少數類樣本距離最近的樣本。
#版本 2:移除多數類中與少數類樣本距離最遠的樣本。
#版本 3:移除多數類中距離最遠的樣本,但不考慮少數類樣本。# 初始化 NearMiss,選擇版本 1
nearmiss = NearMiss(version=1, random_state=42)X_resampled_nearmiss, y_resampled_nearmiss = nearmiss.fit_resample(X, y)df_nearmiss = pd.DataFrame(X_resampled_nearmiss)
df_nearmiss['target'] = y_resampled_nearmiss
print("Resampled dataset shape (NearMiss Version 1):", df_nearmiss['target'].value_counts())