1. 玻璃识别数据集的多类别不平衡分类实战
作为一名数据科学家,我最近接手了一个有趣的分类项目——通过玻璃的化学成分来识别其类型。这个看似简单的任务实际上隐藏着不少挑战,特别是当遇到类别分布严重不均衡的情况时。今天我就来分享一下我的实战经验,希望能帮助遇到类似问题的同行。
玻璃识别数据集是一个经典的多元分类问题,包含214个样本和9个化学特征。每个样本代表一种玻璃,需要被分类到6种类型之一(注意:原始数据有7类,但第4类没有样本)。最让人头疼的是各类样本数量差异巨大——从最多的76个样本到最少的只有9个样本。
在实际项目中,我经常遇到这种"长尾分布"的数据。处理这类问题时,单纯的准确率往往具有误导性,需要更细致的评估方法和建模策略。
2. 数据集探索与理解
2.1 数据加载与基本统计
首先我们加载数据并查看基本情况:
from pandas import read_csv from collections import Counter # 加载数据集 filename = 'glass.csv' dataframe = read_csv(filename, header=None) # 查看数据维度 print(dataframe.shape) # (214, 10) # 统计类别分布 target = dataframe.values[:,-1] counter = Counter(target) for k,v in counter.items(): per = v / len(target) * 100 print(f'Class={k}, Count={v}, Percentage={per:.1f}%')输出结果显示:
Class=1, Count=70, Percentage=32.7% Class=2, Count=76, Percentage=35.5% Class=3, Count=17, Percentage=7.9% Class=5, Count=13, Percentage=6.1% Class=6, Count=9, Percentage=4.2% Class=7, Count=29, Percentage=13.6%2.2 特征分析与可视化
数据集包含以下化学特征:
- RI:折射率
- Na:钠含量
- Mg:镁含量
- Al:铝含量
- Si:硅含量
- K:钾含量
- Ca:钙含量
- Ba:钡含量
- Fe:铁含量
通过绘制各特征的分布直方图,我发现:
- 折射率(RI)呈近似正态分布
- 镁(Mg)含量呈现明显的双峰分布
- 钡(Ba)和铁(Fe)含量大多为零,只有少数样本有值
这种特征分布差异意味着我们在建模前需要进行标准化处理。
3. 评估框架建立
3.1 分层交叉验证
对于不平衡数据,我推荐使用分层重复K折交叉验证:
from sklearn.model_selection import RepeatedStratifiedKFold cv = RepeatedStratifiedKFold(n_splits=5, n_repeats=3, random_state=1)这种验证方式能确保:
- 每个折的类别分布与整体一致
- 通过多次重复减少随机性影响
- 提供更可靠的性能估计
3.2 基线模型
建立一个预测多数类的基线模型:
from sklearn.dummy import DummyClassifier baseline = DummyClassifier(strategy='most_frequent') scores = cross_val_score(baseline, X, y, cv=cv, scoring='accuracy') print(f'Baseline Accuracy: {scores.mean():.3f} (±{scores.std():.3f})')基线准确率为35.5%,这是我们必须要超越的门槛。
4. 模型比较与选择
4.1 候选模型测试
我测试了以下五种常见算法:
from sklearn.svm import SVC from sklearn.neighbors import KNeighborsClassifier from sklearn.ensemble import (RandomForestClassifier, ExtraTreesClassifier, BaggingClassifier) models = { 'SVM': SVC(gamma='auto'), 'KNN': KNeighborsClassifier(), 'BAG': BaggingClassifier(n_estimators=1000), 'RF': RandomForestClassifier(n_estimators=1000), 'ET': ExtraTreesClassifier(n_estimators=1000) }4.2 性能比较结果
经过交叉验证,各模型表现如下:
| 模型 | 平均准确率 | 标准差 |
|---|---|---|
| SVM | 0.669 | 0.057 |
| KNN | 0.647 | 0.055 |
| BAG | 0.767 | 0.070 |
| RF | 0.796 | 0.062 |
| ET | 0.776 | 0.057 |
随机森林表现最佳,接下来我将重点优化这个模型。
5. 模型优化策略
5.1 类别权重调整
针对不平衡问题,我为随机森林设置了自定义类别权重:
class_weights = { 0: 1.0, # Class 1 1: 1.0, # Class 2 2: 2.0, # Class 3 3: 2.0, # Class 5 4: 2.0, # Class 6 5: 2.0 # Class 7 } model = RandomForestClassifier(n_estimators=1000, class_weight=class_weights, random_state=42)这种设置给予少数类更大的权重,使模型更关注这些类别的正确分类。
5.2 特征工程尝试
我尝试了以下特征变换方法:
- 标准化:对折射率单独处理
- 对数变换:对右偏特征进行转换
- 交互特征:创建元素含量比值特征
其中,简单的标准化配合原始特征就取得了不错的效果。
6. 最终模型评估
经过优化后的随机森林模型性能:
Mean Accuracy: 0.808 (±0.059)相比基线35.5%和初始RF的79.6%,我们的优化带来了显著提升。
6.1 混淆矩阵分析
通过混淆矩阵发现:
- 大类(1,2,7)分类效果很好
- 小类(3,5,6)仍有误判,但相比之前改善明显
- 类别6(餐具玻璃)仍然最具挑战性
6.2 特征重要性
查看模型学到的特征重要性:
- 镁(Mg)含量是最具判别力的特征
- 折射率(RI)和铝(Al)含量也很重要
- 铁(Fe)含量的判别力最低
这与我们之前的探索性分析结果一致。
7. 实际应用建议
基于这个项目经验,我总结出以下实用建议:
数据层面:
- 对小类样本进行智能过采样(SMOTE)
- 尝试聚类方法生成合成样本
模型层面:
- 使用代价敏感学习
- 尝试梯度提升树(XGBoost, LightGBM)
- 集成不同算法的预测结果
评估层面:
- 不要只看准确率,要关注召回率、F1分数
- 对每个类别单独评估性能
- 使用马修斯相关系数(MCC)等平衡指标
部署注意:
- 对新数据持续监控模型表现
- 设置置信度阈值,低置信度预测转人工审核
- 定期用新数据重新训练模型
这个项目让我深刻体会到,处理不平衡分类问题时,单纯的模型调优是不够的,需要从数据、模型、评估三个层面系统性地思考和设计解决方案。希望我的这些经验对你有帮助!