在机器学习的世界里,非平衡分类问题就像是一颗难啃的硬骨头。啥是非平衡分类问题呢?简单来说,就是在分类任务中,各个类别的样本数量差距特别大。比如说,在医疗诊断中,患某种罕见病的患者数量肯定远远少于健康人群。这种数据的不平衡会让模型更倾向于预测数量多的类别,从而导致对数量少的类别预测效果很差。为了解决这个问题,我们可以把代价敏感学习和采样技术深度结合起来,下面就来详细说说。
一、非平衡分类问题的现状
在生活中,非平衡分类问题到处都是。就拿信用卡欺诈检测来说吧,正常交易的数量那是海量的,而欺诈交易的数量就少得可怜。如果直接用这些数据训练模型,模型大概率会把所有交易都判断为正常交易,因为它从大量正常交易的数据中学到的信息更多。再比如,在动植物物种识别中,一些珍稀物种的样本数量很少,模型就很难准确识别这些珍稀物种。这就是非平衡分类问题带来的麻烦,会让模型的准确性大打折扣。
二、代价敏感学习
1. 基本概念
代价敏感学习就是在训练模型的时候,考虑不同分类错误所带来的代价。比如说,在医疗诊断中,把一个患病的人误诊为健康人(假阴性)和把一个健康人误诊为患病的人(假阳性),这两种错误带来的代价是不一样的。假阴性可能会让患者错过最佳治疗时间,后果很严重;而假阳性可能只是让患者多做一些检查。所以,在训练模型的时候,我们要给假阴性更高的代价,这样模型就会更努力地去避免假阴性错误。
2. 示例(Python 技术栈)
# 导入必要的库
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
import numpy as np
# 生成非平衡的分类数据
X, y = make_classification(n_samples=1000, n_features=10, n_informative=5, n_redundant=0,
weights=[0.9, 0.1], random_state=42)
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 创建代价敏感的逻辑回归模型
# class_weight='balanced' 会根据类别比例自动调整权重
model = LogisticRegression(class_weight='balanced')
# 训练模型
model.fit(X_train, y_train)
# 预测
y_pred = model.predict(X_test)
# 输出模型的准确率
print("模型准确率:", model.score(X_test, y_test))
注释:
make_classification函数用于生成非平衡的分类数据,weights=[0.9, 0.1]表示类别 0 的样本占 90%,类别 1 的样本占 10%。LogisticRegression是逻辑回归模型,class_weight='balanced'会根据类别比例自动调整权重,让模型更关注数量少的类别。fit方法用于训练模型,predict方法用于预测,score方法用于计算模型的准确率。
3. 优缺点
优点:
- 能让模型更关注那些容易被忽略的少数类样本,提高少数类的分类准确率。
- 不需要对数据进行复杂的处理,直接在模型训练阶段考虑代价。
缺点:
- 确定合适的代价比较困难,需要大量的经验和实验。
- 如果代价设置不合理,可能会导致模型过拟合。
4. 注意事项
- 在确定代价时,要结合具体的业务场景。比如在医疗诊断中,要考虑误诊带来的实际后果。
- 可以通过交叉验证等方法来选择合适的代价。
三、采样技术
1. 过采样
过采样就是增加少数类样本的数量,让各个类别的样本数量更平衡。常见的过采样方法有随机过采样和 SMOTE(Synthetic Minority Over - sampling Technique)。
随机过采样示例(Python 技术栈)
from imblearn.over_sampling import RandomOverSampler
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
# 生成非平衡的分类数据
X, y = make_classification(n_samples=1000, n_features=10, n_informative=5, n_redundant=0,
weights=[0.9, 0.1], random_state=42)
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 创建随机过采样对象
ros = RandomOverSampler(random_state=42)
X_resampled, y_resampled = ros.fit_resample(X_train, y_train)
# 创建逻辑回归模型
model = LogisticRegression()
# 训练模型
model.fit(X_resampled, y_resampled)
# 预测
y_pred = model.predict(X_test)
# 输出模型的准确率
print("模型准确率:", model.score(X_test, y_test))
注释:
RandomOverSampler是随机过采样类,fit_resample方法用于对训练数据进行过采样。- 过采样后,再用新的数据训练模型。
SMOTE 示例(Python 技术栈)
from imblearn.over_sampling import SMOTE
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
# 生成非平衡的分类数据
X, y = make_classification(n_samples=1000, n_features=10, n_informative=5, n_redundant=0,
weights=[0.9, 0.1], random_state=42)
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 创建 SMOTE 对象
smote = SMOTE(random_state=42)
X_resampled, y_resampled = smote.fit_resample(X_train, y_train)
# 创建逻辑回归模型
model = LogisticRegression()
# 训练模型
model.fit(X_resampled, y_resampled)
# 预测
y_pred = model.predict(X_test)
# 输出模型的准确率
print("模型准确率:", model.score(X_test, y_test))
注释:
SMOTE是一种合成少数类过采样技术,它会在少数类样本之间进行插值,生成新的少数类样本。- 同样,过采样后再训练模型。
2. 欠采样
欠采样就是减少多数类样本的数量,让各个类别的样本数量更平衡。常见的欠采样方法有随机欠采样。
随机欠采样示例(Python 技术栈)
from imblearn.under_sampling import RandomUnderSampler
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
# 生成非平衡的分类数据
X, y = make_classification(n_samples=1000, n_features=10, n_informative=5, n_redundant=0,
weights=[0.9, 0.1], random_state=42)
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 创建随机欠采样对象
rus = RandomUnderSampler(random_state=42)
X_resampled, y_resampled = rus.fit_resample(X_train, y_train)
# 创建逻辑回归模型
model = LogisticRegression()
# 训练模型
model.fit(X_resampled, y_resampled)
# 预测
y_pred = model.predict(X_test)
# 输出模型的准确率
print("模型准确率:", model.score(X_test, y_test))
注释:
RandomUnderSampler是随机欠采样类,fit_resample方法用于对训练数据进行欠采样。- 欠采样后,再用新的数据训练模型。
3. 采样技术的优缺点
优点:
- 过采样可以增加少数类样本的数量,让模型有更多的信息来学习少数类的特征。
- 欠采样可以减少多数类样本的数量,避免模型过度关注多数类。
缺点:
- 过采样可能会导致过拟合,因为新生成的样本可能只是原始样本的简单复制或插值。
- 欠采样会丢失一些多数类的信息,可能会影响模型的整体性能。
4. 注意事项
- 过采样时要注意控制样本数量,避免过拟合。
- 欠采样时要确保保留了足够的多数类信息。
四、代价敏感学习与采样技术的深度结合
1. 结合方式
我们可以先使用采样技术对数据进行预处理,让数据变得更平衡,然后再使用代价敏感学习来训练模型。这样既能解决数据不平衡的问题,又能让模型更关注不同分类错误的代价。
2. 示例(Python 技术栈)
from imblearn.over_sampling import SMOTE
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
# 生成非平衡的分类数据
X, y = make_classification(n_samples=1000, n_features=10, n_informative=5, n_redundant=0,
weights=[0.9, 0.1], random_state=42)
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 使用 SMOTE 进行过采样
smote = SMOTE(random_state=42)
X_resampled, y_resampled = smote.fit_resample(X_train, y_train)
# 创建代价敏感的逻辑回归模型
model = LogisticRegression(class_weight='balanced')
# 训练模型
model.fit(X_resampled, y_resampled)
# 预测
y_pred = model.predict(X_test)
# 输出模型的准确率
print("模型准确率:", model.score(X_test, y_test))
注释:
- 先使用
SMOTE对训练数据进行过采样,让数据更平衡。 - 然后创建代价敏感的逻辑回归模型,使用过采样后的数据进行训练。
3. 结合的优势
- 综合了采样技术和代价敏感学习的优点,既能解决数据不平衡问题,又能让模型更关注不同分类错误的代价。
- 可以提高模型对少数类的分类准确率,同时保证模型的整体性能。
4. 注意事项
- 在结合时,要根据具体的业务场景和数据特点选择合适的采样方法和代价设置。
- 可以通过交叉验证等方法来评估结合的效果。
五、应用场景
1. 医疗诊断
在医疗诊断中,很多疾病的患者数量相对健康人群来说是少数。通过结合代价敏感学习和采样技术,可以提高对疾病的诊断准确率,避免漏诊。
2. 金融欺诈检测
在金融领域,欺诈交易的数量远远少于正常交易。使用这种结合方法可以让模型更准确地识别欺诈交易,保护金融机构和用户的利益。
3. 动植物物种识别
对于珍稀物种的识别,样本数量往往很少。结合这两种技术可以提高对珍稀物种的识别准确率,有助于保护生物多样性。
六、总结
处理非平衡分类问题是机器学习中的一个重要挑战。代价敏感学习和采样技术都有各自的优缺点,将它们深度结合可以充分发挥两者的优势,提高模型对少数类的分类准确率。在实际应用中,要根据具体的业务场景和数据特点选择合适的方法和参数,通过不断的实验和优化,找到最适合的解决方案。
评论