5步实战:用Python的sklearn轻松搞定Ionosphere数据集分类

当你第一次接触机器学习时,那些复杂的数学公式是否让你望而却步?别担心,今天我们就用最直观的方式——代码实战,带你快速上手朴素贝叶斯分类器。不需要死记硬背公式,跟着这5个步骤,你就能在Ionosphere数据集上完成一个完整的分类任务。

1. 环境准备与数据加载

首先确保你的Python环境已经安装了必要的库。如果你使用Anaconda,可以直接用以下命令安装缺失的包:

pip install pandas scikit-learn category-encoders

加载Ionosphere数据集非常简单。这个经典数据集包含雷达返回信号的特征,目标是区分"好"(能显示电离层中的某些结构)和"坏"(不能)的信号。

import pandas as pd

# 加载数据集
data = pd.read_csv('ionosphere.csv')
print(data.head())

你会看到数据有34个特征列和1个目标列。前33列是雷达返回信号的特征值,最后一列'label'是分类标签('g'表示好,'b'表示坏)。

提示:如果找不到数据集,可以直接从UCI机器学习仓库下载,或者使用sklearn的fetch_openml函数在线获取。

2. 数据预处理:为朴素贝叶斯做准备

朴素贝叶斯分类器对数据格式有特定要求。我们需要做两件事:处理类别型特征和离散化连续特征。

2.1 标签编码

首先将目标列转换为数值:

from sklearn.preprocessing import LabelEncoder

# 将标签转换为数值
le = LabelEncoder()
data['label'] = le.fit_transform(data['label'])

2.2 特征离散化

朴素贝叶斯(特别是CategoricalNB)更适合处理离散特征。我们将连续特征分箱:

# 对前33个特征进行分箱处理
for col in data.columns[:33]:
    data[col] = pd.cut(data[col], bins=10, labels=range(10))

2.3 数据集划分

按7:3比例划分训练集和测试集:

from sklearn.model_selection import train_test_split

X = data.drop('label', axis=1)
y = data['label']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

3. 构建朴素贝叶斯分类器

sklearn提供了几种朴素贝叶斯实现,我们选择专门为类别特征设计的CategoricalNB:

from sklearn.naive_bayes import CategoricalNB

# 创建模型实例,强制使用拉普拉斯平滑
model = CategoricalNB(force_alpha=True)
model.fit(X_train, y_train)

这里force_alpha=True参数很重要,它确保模型使用拉普拉斯平滑处理未见过的特征值,避免零概率问题。

4. 模型评估与结果解读

训练完成后,我们来看看模型表现:

from sklearn.metrics import classification_report

# 训练集和测试集上的准确率
print(f"训练集准确率: {model.score(X_train, y_train):.4f}")
print(f"测试集准确率: {model.score(X_test, y_test):.4f}")

# 更详细的分类报告
y_pred = model.predict(X_test)
print(classification_report(y_test, y_pred))

典型输出可能如下:

训练集准确率: 0.9157
测试集准确率: 0.9091
              precision    recall  f1-score   support

           0       0.89      0.86      0.87        35
           1       0.92      0.94      0.93        70

    accuracy                           0.91       105
   macro avg       0.91      0.90      0.90       105
weighted avg       0.91      0.91      0.91       105

5. 模型优化与实用技巧

虽然我们的基础模型表现不错,但还可以进一步优化:

5.1 调整分箱策略

不同的分箱方式会影响模型性能。可以尝试:

# 尝试不同的分箱数量
for col in data.columns[:33]:
    data[col] = pd.cut(data[col], bins=5, labels=range(5))  # 减少分箱数

5.2 特征选择

不是所有特征都同样重要。我们可以使用互信息评分选择最有用的特征:

from sklearn.feature_selection import mutual_info_classif

# 计算特征重要性
importance = mutual_info_classif(X_train, y_train, discrete_features=True)
important_features = importance > 0.01  # 设置阈值
X_train_reduced = X_train.loc[:, important_features]
X_test_reduced = X_test.loc[:, important_features]

# 用筛选后的特征重新训练
model_reduced = CategoricalNB(force_alpha=True)
model_reduced.fit(X_train_reduced, y_train)
print(f"精简特征后的测试集准确率: {model_reduced.score(X_test_reduced, y_test):.4f}")

5.3 处理类别不平衡

如果数据集中两类样本数量差异很大,可以设置class_prior参数:

# 根据训练集计算类别先验
class_prior = [sum(y_train==0)/len(y_train), sum(y_train==1)/len(y_train)]
model_balanced = CategoricalNB(force_alpha=True, class_prior=class_prior)
model_balanced.fit(X_train, y_train)

在实际项目中,我发现特征离散化的分箱策略对朴素贝叶斯性能影响最大。经过几次尝试,发现对Ionosphere数据集使用等宽分箱(uniform)比等频分箱(quantile)效果更好,这可能与特征的分布特性有关。另外,虽然CategoricalNB设计用于类别特征,但适当调整分箱数量后,它也能很好地处理连续特征的离散化结果。

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐