数据预处理方法合集(特征工程、数据降维、数据划分、数据平衡)
本文继续介绍数据预处理中的特征工程、数据降维、数据划分、数据平衡的内容,接下来我们将详细地介绍具体的方法,文末可获得预处理方法合集PDF!
目录
成本敏感学习(Cost-Sensitive Learning)
特征工程
特征选择(Feature Selection)
特征选择是从数据集中选择对目标变量最有影响的特征,同时剔除不相关或冗余的特征。通过特征选择,可以减少模型的复杂度,提高模型的性能和可解释性。
-
过滤法(Filter Methods):依据统计特性(如方差、相关系数、卡方检验、互信息)选择特征。
-
包裹法(Wrapper Methods): 使用模型性能指标(如精度、AUC)评估特征组合。
-
嵌入法(Embedded Methods): 在模型训练过程中内置特征选择(如Lasso回归、决策树)。
1)过滤法(Filter Method)
-
方差选择法(Variance Threshold)
低方差特征可能对模型贡献较小,因此可以删除方差低于某个阈值的特征。
适用场景:在数据中存在常数特征或几乎不变的特征时,可以通过方差选择法来去除它们。
from sklearn.feature_selection import VarianceThreshold
# 示例数据
X = [[0, 2, 0, 3],
[0, 1, 4, 3],
[0, 1, 1, 3]]
# 去除低方差特征
selector = VarianceThreshold(threshold=0.1)
X_high_variance = selector.fit_transform(X)
print("去除低方差特征后的数据:")
print(X_high_variance)
-
卡方检验(Chi-Square Test)
卡方检验用于检查类别变量之间的独立性。通过计算特征与目标变量之间的卡方统计量来判断其相关性。
适用场景:用于分类问题中的特征选择,特别是类别变量的处理。
from sklearn.datasets import load_iris
from sklearn.feature_selection import SelectKBest, chi2
# 加载数据
data = load_iris()
X, y = data.data, data.target
# 使用卡方检验选择前2个最相关特征
selector = SelectKBest(score_func=chi2, k=2)
X_kbest = selector.fit_transform(X, y)
print("卡方检验选择的特征:")
print(X_kbest)
-
皮尔逊相关系数(Pearson Correlation Coefficient)
计算每个特征与目标变量之间的线性相关性,选择相关性较高的特征。
适用场景:用于连续型特征和目标变量之间的线性关系分析。
import numpy as np
from scipy.stats import pearsonr
# 示例数据
X = np.array([1, 2, 3, 4, 5])
y = np.array([1, 2, 3, 4, 5])
# 计算相关系数
corr, _ = pearsonr(X, y)
print("皮尔逊相关系数:", corr)
-
互信息(Mutual Information)
互信息衡量两个变量之间的依赖性,捕捉线性和非线性关系。它是信息论中的一个概念,表示通过一个变量可以获得多少关于另一个变量的信息。
适用场景:用于处理分类问题中的非线性关系特征选择。
from sklearn.feature_selection import mutual_info_classif
# 示例数据
X = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
y = [0, 1, 0]
# 计算互信息
mi = mutual_info_classif(X, y)
print("互信息得分:", mi)
2)包裹法(Wrapper Method)
包裹法使用一个预测模型来评估特征子集的性能,通过训练模型来找到最优的特征组合。包裹法比过滤法更能捕捉特征之间的相互作用,但计算成本较高,特别是当特征数量很多时。
-
递归特征消除(Recursive Feature Elimination, RFE)
RFE通过递归地构建模型,逐步消除最不重要的特征,最终得到最优特征子集。
适用场景:适用于需要选择少量最重要特征的场景,尤其是在特征数量较多时。
from sklearn.feature_selection import RFE
from sklearn.linear_model import LogisticRegression
# 加载数据
data = load_iris()
X, y = data.data, data.target
# 使用RFE选择特征
model = LogisticRegression(max_iter=200)
selector = RFE(model, n_features_to_select=2)
X_rfe = selector.fit_transform(X, y)
print("RFE选择的特征:")
print(X_rfe)
-
前向选择(Forward Selection)
从空特征集开始,每次加入一个最能提高模型性能的特征,直到达到某个停止条件。适用场景:适用于逐步构建特征集,尤其在计算资源有限的情况下。
-
后向选择(Backward Elimination)
从完整特征集开始,每次去除一个对模型影响最小的特征,直到达到某个停止条件。适用场景:适用于逐步减少特征,尤其在已经有一个比较好的特征集的情况下。
3)嵌入法(Embedded Method)
嵌入法在模型训练过程中自动进行特征选择,特征选择过程与模型的训练过程是同步进行的。嵌入法结合了过滤法和包裹法的优点,既考虑了特征与目标变量之间的关系,也考虑了特征之间的相互作用。
-
Lasso回归(L1正则化)
Lasso回归通过在损失函数中加入L1正则化项,使得某些特征的系数缩小为零,从而起到特征选择的作用。
适用场景:适用于线性模型,尤其是当特征数量多于样本数量时。
from sklearn.linear_model import Lasso
from sklearn.datasets import load_boston
# 加载数据
X, y = load_boston(return_X_y=True)
# 使用Lasso进行特征选择
model = Lasso(alpha=0.1)
model.fit(X, y)
importance = model.coef_
print("Lasso回归选择的特征:")
print(importance)
-
决策树模型(Decision Tree)
决策树模型通过选择信息增益最大的特征来进行分裂,天然地进行特征选择。
适用场景:适用于处理分类和回归问题,尤其是当特征之间存在非线性关系时。
from sklearn.tree import DecisionTreeClassifier
# 加载数据
X, y = load_iris(return_X_y=True)
# 使用决策树进行特征选择
model = DecisionTreeClassifier()
model.fit(X, y)
importance = model.feature_importances_
print("决策树模型选择的特征:")
print(importance)
-
基于正则化的随机森林(Random Forest with Regularization)
随机森林通过构建多个决策树,计算每个特征的重要性得分,选择最重要的特征。
适用场景:适用于处理高维数据和非线性问题,特别是在特征之间存在复杂交互时。
from sklearn.ensemble import RandomForestClassifier
# 加载数据
X, y = load_iris(return_X_y=True)
# 使用随机森林进行特征选择
model = RandomForestClassifier(n_estimators=100)
model.fit(X, y)
importance = model.feature_importances_
print("随机森林模型选择的特征:")
print(importance)
总结
过滤法: 简单且计算效率高,适合初步筛选特征,但无法考虑特征之间的交互作用。
包裹法: 更能捕捉特征之间的交互作用,但计算成本较高,适用于特征数量较少的情况。
嵌入法: 在模型训练过程中自动选择特征,结合了模型的性能和特征的重要性,适用于大多数机器学习问题。
特征提取
特征提取是将高维数据转换为低维特征空间的过程,目的是提取出对模型预测有用的特征,同时去除噪声和冗余信息。
1)主成分分析(PCA)
主成分分析(PCA)是一种线性降维技术,通过将数据投影到方差最大的方向上,从而减少数据的维度。PCA的目标是找到数据中一组新的正交坐标轴(称为主成分),这些轴上的投影能最大程度地保留数据的方差信息。
Step1 计算数据的协方差矩阵。
Step2 求解协方差矩阵的特征值和特征向量。
Step3 根据特征值的大小选择对应的特征向量作为主成分。
Step4 将原始数据投影到选择的主成分上。
适用场景: PCA适用于需要降维和去除噪声的场景,尤其是在数据集中包含大量相关特征的情况下。常用于图像处理、数据可视化和压缩等领域。
from sklearn.decomposition import PCA
import numpy as np
# 示例数据
X = np.array([[2.5, 2.4], [0.5, 0.7], [2.2, 2.9], [1.9, 2.2], [3.1, 3.0], [2.3, 2.7]])
# 使用PCA进行特征提取
pca = PCA(n_components=1)
X_pca = pca.fit_transform(X)
print("PCA提取的主成分:")
print(X_pca)
2)独立成分分析(ICA)
独立成分分析(ICA)是一种统计和计算方法,旨在将观察到的混合信号分解为具有统计独立性的源信号。ICA常用于盲源分离(如音频信号的分离)和数据降维中。
Step1 寻找一个解混合矩阵,使得分离后的信号相互独立。
Step2 通过最大化信号的非高斯性来实现信号的独立性。
适用场景: ICA适用于信号处理领域,尤其是在音频、图像处理和神经科学中,用于从混合信号中提取独立成分。
from sklearn.decomposition import FastICA
# 示例数据
X = np.array([[2, 4], [1, 3], [2, 2], [3, 5], [4, 6], [2, 3]])
# 使用ICA进行特征提取
ica = FastICA(n_components=2)
X_ica = ica.fit_transform(X)
print("ICA提取的独立成分:")
print(X_ica)
3)线性判别分析(LDA)
线性判别分析(LDA)是一种监督式降维方法,旨在通过最大化类间方差与类内方差的比率,找到能最好区分不同类别的数据投影方向。与PCA不同,LDA考虑了类别标签的信息。
Step1 计算类内散布矩阵(SW)和类间散布矩阵(SB)。
Step2 求解矩阵SW−1SB的特征值和特征向量。
Step3 将数据投影到选定的特征向量方向上。
适用场景: LDA适用于分类问题中的降维,特别是在特征数量多于样本数量的情况下,如人脸识别、文本分类等。
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDA
# 示例数据
X = np.array([[2, 3], [3, 4], [4, 5], [5, 6], [6, 7]])
y = np.array([0, 0, 1, 1, 1])
# 使用LDA进行特征提取
lda = LDA(n_components=1)
X_lda = lda.fit_transform(X, y)
print("LDA提取的判别分量:")
print(X_lda)
4)奇异值分解(SVD)
奇异值分解(SVD)是一种矩阵分解方法,用于将一个矩阵分解为三个矩阵的乘积:左奇异矩阵、对角奇异值矩阵和右奇异矩阵。SVD广泛应用于降维、数据压缩、图像处理和推荐系统中。
SVD分解公式为:X=U⋅Σ⋅VT其中,X是原始数据矩阵,𝑈是左奇异矩阵,Σ是对角奇异值矩阵,VT是右奇异矩阵的转置。
适用场景: SVD适用于数据降维、矩阵补全、图像压缩等场景,特别是在处理大规模稀疏矩阵时非常有效。
from sklearn.decomposition import TruncatedSVD
import numpy as np
# 示例数据
X = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# 使用SVD进行特征提取
svd = TruncatedSVD(n_components=2)
X_svd = svd.fit_transform(X)
print("SVD提取的特征:")
print(X_svd)
5)核PCA(Kernel PCA)
核PCA是PCA的非线性扩展,通过使用核技巧(Kernel Trick),将数据映射到一个高维特征空间,然后在高维空间中进行PCA。这使得核PCA能够捕捉数据中的非线性结构。K(X,X′)=ϕ(X)⋅ϕ(X′)其中,𝐾(𝑋,𝑋′)是核函数,𝜙(𝑋)是将数据映射到高维空间的映射函数。
适用场景: 核PCA适用于非线性数据结构的降维,常用于图像处理、非线性分类问题中。
from sklearn.decomposition import KernelPCA
# 示例数据
X = np.array([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]])
# 使用核PCA进行特征提取
kpca = KernelPCA(n_components=2, kernel='rbf')
X_kpca = kpca.fit_transform(X)
print("核PCA提取的特征:")
print(X_kpca)
6)非负矩阵分解(NMF)
非负矩阵分解(NMF)是一种矩阵分解方法,用于将一个非负矩阵分解为两个非负矩阵的乘积。NMF常用于数据降维、特征提取和信号处理等领域。与PCA不同,NMF要求分解后的矩阵元素都为非负数,这使得NMF在解释性上有优势。
适用场景: NMF适用于处理非负数据(如图像数据、文档-词矩阵)和需要解释性结果的场景,如主题建模、信号分解等。
from sklearn.decomposition import NMF
import numpy as np
# 示例数据
X = np.array([[1, 2], [3, 4], [5, 6]])
# 使用NMF进行特征提取
nmf = NMF(n_components=2)
X_nmf = nmf.fit_transform(X)
print("NMF提取的特征:")
print(X_nmf)
数据降维
线性降维方法
线性降维方法假设数据的结构可以通过线性变换来捕捉,这些方法在处理具有线性特征的数据时非常有效。常见方法有:
-
主成分分析(PCA): 基于线性变换,将数据投影到方差最大的方向上。
-
线性判别分析(LDA): 寻找能够最好分离不同类别的线性投影方向。
-
奇异值分解(SVD): 通过线性分解将矩阵分解为低维子空间。
-
独立成分分析(ICA): 通过线性变换分离出独立的成分。
非线性降维方法
非线性降维方法用于处理具有复杂非线性结构的数据,这些方法能够捕捉到数据中更复杂的模式。
1)t-SNE
t-SNE是一种非线性降维方法,通过最小化高维空间中相似点在低维空间中的分布差异来实现降维。t-SNE特别擅长保留数据的局部结构,适用于高维数据的可视化。
适用场景: 常用于高维数据的可视化,特别是当需要展示数据的簇结构时。
from sklearn.manifold import TSNE
# 示例数据
X = [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]
# 使用t-SNE进行降维
tsne = TSNE(n_components=2)
X_tsne = tsne.fit_transform(X)
print("t-SNE降维后的数据:")
print(X_tsne)
2)局部线性嵌入(LLE)
LLE是一种非线性降维方法,通过保留数据的局部结构,将高维数据嵌入到低维空间中。LLE假设每个数据点及其邻居可以通过线性组合表示,并通过保留这些线性组合关系来实现降维。
适用场景: 适用于处理复杂的非线性数据,特别是当数据位于流形上时。
from sklearn.manifold import LocallyLinearEmbedding
# 示例数据
X = [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]
# 使用LLE进行降维
lle = LocallyLinearEmbedding(n_components=2)
X_lle = lle.fit_transform(X)
print("LLE降维后的数据:")
print(X_lle)
3)Isomap
Isomap是一种基于流形学习的非线性降维方法,通过保留数据的全局几何结构,将高维数据嵌入到低维空间中。Isomap通过计算数据点之间的最短路径距离来捕捉数据的流形结构。
适用场景: 适用于数据位于复杂的非线性流形上的情况,常用于图像分析和数据可视化。
from sklearn.manifold import Isomap
# 示例数据
X = [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]
# 使用Isomap进行降维
isomap = Isomap(n_components=2)
X_isomap = isomap.fit_transform(X)
print("Isomap降维后的数据:")
print(X_isomap)
4)UMAP
UMAP通过构建高维空间中的近邻图,并将其投影到低维空间中,以保留数据的拓扑结构。
-
数据可视化: UMAP常用于将高维数据嵌入到二维或三维空间中,以便于可视化和理解数据的内在结构。
-
聚类分析: UMAP可以在低维空间中保留聚类结构,帮助识别数据中的群体和模式。
-
降维预处理: UMAP可作为降维预处理步骤,减少数据维度,从而提高后续机器学习模型的效率和性能。
import umap
import numpy as np
# 示例数据
X = np.array([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]])
# 使用UMAP进行降维
reducer = umap.UMAP(n_components=2)
X_umap = reducer.fit_transform(X)
print("UMAP降维后的数据:")
print(X_umap)
数据划分
训练集、验证集和测试集划分
数据集通常被划分为训练集、验证集和测试集,以便对模型进行训练、调优和最终评估。这种划分方式确保模型在训练过程中不会看到测试集数据,从而能够更准确地评估模型的泛化能力。
-
训练集(Training Set): 用于训练模型的部分数据,模型通过这个数据学习特征和规律。
-
验证集(Validation Set): 用于调优模型参数的部分数据,帮助选择最佳模型超参数,防止过拟合。
-
测试集(Test Set): 最终用于评估模型性能的数据,模型在训练和调优过程中未曾见过这些数据。
from sklearn.model_selection import train_test_split
# 示例数据
X = [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]
y = [0, 1, 0, 1, 0]
# 将数据划分为训练集和测试集(80%训练,20%测试)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
print("训练集数据:", X_train)
print("测试集数据:", X_test)
交叉验证(Cross-Validation)
交叉验证是一种常用的模型评估方法,尤其在数据量较少时非常有效。交叉验证通过将数据集划分为多个互斥的子集,每次使用其中一个子集作为验证集,其他子集作为训练集,反复进行训练和验证,从而更全面地评估模型的性能。
-
k折交叉验证(k-Fold Cross-Validation): 将数据集划分为k个子集,每次使用k-1个子集进行训练,剩下的一个子集进行验证,重复k次,最终计算平均性能。
-
留一法(LOO, Leave-One-Out): 每次只留出一个数据点作为验证集,其余数据用于训练,适合小数据集。
from sklearn.model_selection import cross_val_score
from sklearn.ensemble import RandomForestClassifier
import numpy as np
# 示例数据
X = np.array([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]])
y = np.array([0, 1, 0, 1, 0])
# 使用k折交叉验证评估模型(5折交叉验证)
model = RandomForestClassifier(random_state=42)
scores = cross_val_score(model, X, y, cv=5)
print("交叉验证得分:", scores)
分层抽样(Stratified Sampling)
分层抽样是一种用于处理类别不平衡数据集的划分方法。通过在每个类别中按比例抽取样本,分层抽样确保训练集和测试集中各类别的比例与原始数据集一致。分层交叉验证(Stratified Cross-Validation)是其在交叉验证中的应用。在处理类别不平衡问题时,能够确保各类别的代表性,防止模型在某些类别上表现过差。提高了模型评估的公平性和稳定性。
from sklearn.model_selection import train_test_split
# 示例数据
X = [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12]]
y = [0, 0, 1, 1, 1, 0]
# 分层抽样划分数据集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, stratify=y, random_state=42)
print("分层抽样后的训练集:", y_train)
print("分层抽样后的测试集:", y_test)
时间序列数据划分(Time Series Split)
时间序列数据的划分不同于静态数据,因为时间序列数据具有时间依赖性。传统的随机划分可能会破坏数据的时间结构,因此需要使用特定的方法来处理时间序列数据。
-
滚动窗口法(Rolling Window Method): 在时间序列数据上应用滚动窗口,每次使用一段时间的数据作为训练集,接下来的数据作为测试集。
-
时间序列交叉验证(Time Series Cross-Validation): 在时间序列数据中,通过递增的时间窗口进行交叉验证,保证训练集数据总是早于测试集数据。
from sklearn.model_selection import TimeSeriesSplit
import numpy as np
# 示例时间序列数据
X = np.array([[1], [2], [3], [4], [5], [6], [7]])
y = np.array([1, 2, 3, 4, 5, 6, 7])
# 时间序列交叉验证(3次分割)
tscv = TimeSeriesSplit(n_splits=3)
for train_index, test_index in tscv.split(X):
print("训练集索引:", train_index, "测试集索引:", test_index)
留出法(Hold-Out Method)
留出法是最简单的数据划分方法,将数据随机划分为两部分,一部分用于训练模型,另一部分用于测试模型。通常按比例划分,比如70%用于训练,30%用于测试。
from sklearn.model_selection import train_test_split
# 示例数据
X = [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]
y = [0, 1, 0, 1, 0]
# 留出法划分数据集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
print("留出法训练集:", X_train)
print("留出法测试集:", X_test)
自助法(Bootstrap Method)
自助法是一种基于重采样的数据划分方法,通过从原始数据集中有放回地抽样生成多个训练集,未被抽到的样本作为测试集。自助法常用于模型评估、集成学习(如Bagging)等。
from sklearn.utils import resample
import numpy as np
# 示例数据
X = np.array([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]])
y = np.array([0, 1, 0, 1, 0])
# 使用自助法生成训练集
X_resampled, y_resampled = resample(X, y, n_samples=4, random_state=42)
print("自助法生成的训练集:")
print(X_resampled)
数据平衡
数据平衡方法主要用于处理类别不平衡问题,特别是在分类任务中,类别不平衡可能导致模型对少数类别的预测性能较差。
欠采样(Undersampling)
1)随机欠采样
随机欠采样是一种直接减少多数类样本数量的策略,通过随机删除多数类中的一些样本,使其数量与少数类接近,从而达到平衡数据集的目的。
适用场景: 适用于多数类样本数量非常多的情况,尤其是在数据量大到处理时间和存储资源成为瓶颈时。随机欠采样能够有效地减少数据量,降低计算资源的消耗。
from imblearn.under_sampling import RandomUnderSampler
import numpy as np
# 示例数据
X = np.array([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12]])
y = np.array([0, 0, 0, 0, 1, 1])
# 随机欠采样
rus = RandomUnderSampler(random_state=42)
X_res, y_res = rus.fit_resample(X, y)
print("欠采样后的数据:", X_res)
print("欠采样后的标签:", y_res)
2)聚类欠采样
聚类欠采样通过使用聚类算法将多数类样本分为多个簇,然后从每个簇中选择代表性样本进行训练。这种方法在保持多数类样本多样性的同时减少样本数量,避免了随机欠采样可能带来的信息丢失。
适用场景: 适用于多数类样本数量多但样本分布复杂的情况,通过聚类保持多数类样本的代表性和多样性。
from imblearn.under_sampling import ClusterCentroids
# 示例数据
X = np.array([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12]])
y = np.array([0, 0, 0, 0, 1, 1])
# 使用聚类欠采样
cc = ClusterCentroids(random_state=42)
X_res, y_res = cc.fit_resample(X, y)
print("聚类欠采样后的数据:", X_res)
print("聚类欠采样后的标签:", y_res)
过采样(Oversampling)
1) 随机过采样
随机过采样通过复制少数类样本来增加少数类的数量,使其数量与多数类接近。这种方法简单直接,可以有效平衡数据集,但也容易导致过拟合。
适用场景: 适用于少数类样本数量非常少的场景,尤其是在少数类样本对模型性能影响较大时。随机过采样能够增加少数类的数量,提高模型对少数类的识别能力。
from imblearn.over_sampling import RandomOverSampler
# 示例数据
X = np.array([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12]])
y = np.array([0, 0, 0, 0, 1, 1])
# 随机过采样
ros = RandomOverSampler(random_state=42)
X_res, y_res = ros.fit_resample(X, y)
print("随机过采样后的数据:", X_res)
print("随机过采样后的标签:", y_res)
2)SMOTE
SMOTE通过在少数类样本之间插值来合成新的少数类样本。这种方法通过生成新的样本来避免简单复制带来的过拟合问题,从而更好地平衡数据集。
适用场景: 适用于少数类样本较少且模型容易过拟合的场景。SMOTE能够在增加少数类样本数量的同时保持数据的多样性。
from imblearn.over_sampling import SMOTE
# 示例数据
X = np.array([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12]])
y = np.array([0, 0, 0, 0, 1, 1])
# 使用SMOTE进行过采样
smote = SMOTE(random_state=42)
X_res, y_res = smote.fit_resample(X, y)
print("SMOTE过采样后的数据:", X_res)
print("SMOTE过采样后的标签:", y_res)
混合采样(Hybrid Sampling)
1)SMOTE + ENN(Edited Nearest Neighbors)
SMOTE + ENN结合了SMOTE和ENN两种方法。首先通过SMOTE合成新的少数类样本,接着使用ENN算法删除数据集中可能包含噪声的多数类样本,从而在增加少数类样本的同时清理数据。
适用场景: 适用于数据集复杂、含噪声较多的场景,通过这种方法可以提高数据的质量和模型的性能。
from imblearn.combine import SMOTEENN
# 示例数据
X = np.array([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12]])
y = np.array([0, 0, 0, 0, 1, 1])
# 使用SMOTE + ENN进行混合采样
smote_enn = SMOTEENN(random_state=42)
X_res, y_res = smote_enn.fit_resample(X, y)
print("SMOTE + ENN混合采样后的数据:", X_res)
print("SMOTE + ENN混合采样后的标签:", y_res)
2)SMOTE + Tomek Links
SMOTE + Tomek Links通过结合SMOTE和Tomek Links两种技术,先使用SMOTE生成少数类样本,然后使用Tomek Links去除数据中容易混淆的多数类样本,从而进一步平衡数据集。
适用场景: 适用于希望通过去除冗余多数类样本来提高数据集质量的场景。
from imblearn.combine import SMOTETomek
# 示例数据
X = np.array([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12]])
y = np.array([0, 0, 0, 0, 1, 1])
# 使用SMOTE + Tomek Links进行混合采样
smote_tomek = SMOTETomek(random_state=42)
X_res, y_res = smote_tomek.fit_resample(X, y)
print("SMOTE + Tomek Links混合采样后的数据:", X_res)
print("SMOTE + Tomek Links混合采样后的标签:", y_res)
集成方法(Ensemble Methods)
1)EasyEnsemble
EasyEnsemble是一种集成方法,它通过对多数类进行多次随机欠采样,生成多个平衡的子集,并训练多个分类器,将这些分类器的结果集成。这种方法能够有效减少多数类样本的数量,同时保留数据的多样性。
适用场景: 适用于数据量大且需要构建稳健模型的场景,尤其在少数类样本非常重要的任务中。
from imblearn.ensemble import EasyEnsembleClassifier
# 示例数据
X = np.array([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12]])
y = np.array([0, 0, 0, 0, 1, 1])
# 使用EasyEnsemble进行数据平衡
model = EasyEnsembleClassifier(random_state=42)
model.fit(X, y)
y_pred = model.predict(X)
print("EasyEnsemble预测结果:", y_pred)
2)BalanceCascade
BalanceCascade是一种逐步欠采样方法,每次对多数类进行欠采样,去除当前分类器可以正确分类的多数类样本,直至达到数据集的平衡。然后集成所有分类器的预测结果。
适用场景: 适用于数据集中多数类样本明显多于少数类的情况,通过这种方法可以逐步优化模型对少数类的识别能力。
import numpy as np
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import VotingClassifier
from sklearn.model_selection import train_test_split
from collections import Counter
# 示例数据
X = np.array([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12], [13, 14], [15, 16], [17, 18], [19, 20]])
y = np.array([0, 0, 0, 0, 0, 0, 1, 1, 1, 1])
# 自定义 BalanceCascade 方法
def balance_cascade(X, y, n_classifiers=3):
classifiers = []
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
for i in range(n_classifiers):
clf = DecisionTreeClassifier(random_state=42)
clf.fit(X_train, y_train)
y_pred = clf.predict(X_train)
correct_classified_indices = np.where((y_pred == y_train) & (y_train == 0))[0]
# 剔除当前分类器能够正确分类的多数类样本
X_train = np.delete(X_train, correct_classified_indices, axis=0)
y_train = np.delete(y_train, correct_classified_indices, axis=0)
classifiers.append(clf)
print(f"Classifier {i+1} trained with {len(y_train)} samples remaining.")
# 使用VotingClassifier集成多个分类器
voting_clf = VotingClassifier(estimators=[(f'clf{i}', clf) for i, clf in enumerate(classifiers)], voting='hard')
voting_clf.fit(X, y)
return voting_clf
# 运行 BalanceCascade
voting_clf = balance_cascade(X, y, n_classifiers=3)
# 预测测试集
X_test = np.array([[2, 3], [6, 7], [10, 11]])
y_pred = voting_clf.predict(X_test)
print("预测结果:", y_pred)
成本敏感学习(Cost-Sensitive Learning)
1)加权随机森林
加权随机森林通过为少数类样本分配较高的权重,使模型在训练时更加关注少数类。这种方法通过调整权重来解决类别不平衡问题,而无需对数据进行采样处理。
适用场景: 适用于不希望改变数据集结构但希望模型更加关注少数类的场景,如医疗诊断、欺诈检测等任务。
from sklearn.ensemble import RandomForestClassifier
# 示例数据
X = np.array([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12]])
y = np.array([0, 0, 0, 0, 1, 1])
# 使用加权随机森林进行数据平衡
model = RandomForestClassifier(class_weight={0: 1, 1: 10}, random_state=42)
model.fit(X, y)
y_pred = model.predict(X)
print("加权随机森林预测结果:", y_pred)
2)代价敏感决策树
代价敏感决策树在决策树模型中为不同类别设定不同的代价权重,使得模型在分类错误时对少数类的惩罚更大,从而更倾向于正确分类少数类样本。
适用场景: 适用于希望在决策树模型中显式控制分类错误代价的场景,如不对称损失函数的问题。
from sklearn.tree import DecisionTreeClassifier
# 示例数据
X = np.array([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12]])
y = np.array([0, 0, 0, 0, 1, 1])
# 使用代价敏感决策树
model = DecisionTreeClassifier(class_weight={0: 1, 1: 10}, random_state=42)
model.fit(X, y)
y_pred = model.predict(X)
print("代价敏感决策树预测结果:", y_pred)
生成对抗网络(GAN)
生成对抗网络通过生成模型和判别模型的对抗训练,生成逼真的少数类样本。生成模型负责生成新的样本,判别模型则用于区分生成的样本与真实样本,二者在对抗中不断改进。
适用场景: 适用于复杂数据类型的少数类样本扩展,如图像分类、文本生成等任务。
自适应采样
ADASYN
ADASYN是一种自适应采样方法,通过在少数类样本之间合成新的样本,特别关注那些难以分类的样本,生成更多类似这些样本的新数据。
适用场景: 适用于希望通过关注难以分类的少数类样本来提高模型性能的场景,如数据复杂度较高的分类任务。
from imblearn.over_sampling import ADASYN
# 示例数据
X = np.array([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12]])
y = np.array([0, 0, 0, 0, 1, 1])
# 使用ADASYN进行自适应过采样
adasyn = ADASYN(random_state=42)
X_res, y_res = adasyn.fit_resample(X, y)
print("ADASYN采样后的数据:", X_res)
print("ADASYN采样后的标签:", y_res)
Easy数模,让数学建模变得轻松易懂。我们提供从基础到高级的建模教程、个性化竞赛助攻、丰富的建模资源分享,旨在帮助您快速提升数学建模能力,无论是学术竞赛还是实际应用,都能轻松应对。
关注公众号,后台回复“数据预处理”即可获得数据预处理方法合集PDF!