机器学习中的特征工程与分类模型

1. 异常值对特征缩放的影响

在进行特征缩放时,异常值可能会对结果产生显著影响。即使大部分数据都围绕值 20 波动,一个异常值的存在也会导致感兴趣范围的“压缩”。例如,没有异常值时,归一化序列可能如下:

0, 0.8, 0.84, 0.88, 0.92, 0.96, 1

这个序列具有更高的扩散因子。因此,在应用最小 - 最大归一化之前,要警惕异常值。

1.1 如何识别异常值

识别异常值可以通过查看表格摘要来实现。观察每列从最小值到最大值的数值变化情况:
- 如果每两个连续行之间的差值大致相同,那么数据是均匀分布的。
- 如果最小值与 25% 分位数或 75% 分位数与最大值之间的差值远大于平均值,那么该列可能包含异常值。

以下是一个包含异常值的列的示例:

column_with_outliers
count            106.000000
mean              -0.249395
std                1.782681
min               -8.000000
25%               -0.972149  # 25% - min = 7 ← 异常值的迹象
50%               -0.364116  # 50% - 25% = 0.6
75%                0.637160  # 75% - 50% = 1
max                7.000000  # max – 75% = 6.4 ← 异常值的迹象

当存在异常值时,为了进行最佳的特征缩放,可以参考鲁棒缩放方法。

2. 特征选择

特征选择的目标包括:
- 防止维度灾难
- 去除高度相关(冗余)的特征
- 去除不能表征类别的特征(无关特征)
- 用最少的特征实现尽可能高的指标(如准确率、F1 分数、均方根误差)

2.1 特征选择的方法

2.1.1 顺序特征选择

这是一种穷举方法,它尝试所有列的组合以最终获得最优结果。根据想要保留的特征比例,可以选择一次删除一个特征,或者从空列表开始一次添加一个特征(选择最能改善指标的特征),这由方向参数指定。可以手动选择要保留的特征数量,也可以依靠自动选择机制来找到最佳数量。示例代码如下:

from tinyml4all.tabular.features import Select
# direction = forward 会从 0 个特征增长到 n 个特征
# direction = backward 会从 N 个特征缩减到 n 个特征
select = Select(sequential="auto", direction="forward")
table2 = select(table)
print(table2.head())
    r
0  38
1  40
2  49
3  65
4  54

使用自动选择机制发现,仅红色列就足以实现良好的分类结果。

2.1.2 基于分数的选择

这是一种更快、无需分类器的方法,基于单变量统计测试来决定删除哪些特征。这些测试为每列生成一个分数,该分数表示该特征在分类任务中的重要程度。在这种情况下,必须手动选择要保留的列数,没有自动设置。示例代码如下:

# 1 是要选择的列数
select = Select(univariate=1)
table2 = select(table)
print(table2.head())
    r
0  38
1  40
2  49
3  65
4  54

单变量测试也选择了红色列,但并非所有数据集都是如此。

2.1.3 递归特征消除(RFE)

RFE 可以看作是顺序特征选择的更快版本。它需要一个分类器来递归地决定删除哪些特征,该分类器必须能够产生特征重要性分数。这个分数用于选择对分类结果贡献最小的列,然后递归地重复这个过程,直到达到所需的特征数量。示例代码如下:

# 1 是要选择的列数
select = Select(rfe=1)
table2 = select(table)
print(table2.head())
    r
0  38
1  40
2  49
3  65
4  54

2.2 选择最佳特征选择方法的指南

方法 优点 缺点
单变量 快速;建议在开发的早期阶段使用 不能保证得到最优选择
递归 比顺序特征选择快;可能收敛到最优解;在中等数据集上优于单变量方法 在大型数据集上,某些分类器可能会变慢
顺序 可能收敛到最优解 在大型数据集上,某些分类器可能会变慢

此外,还可以手动选择要保留或丢弃的列,例如:

Select(include=["r", "b"])  # 保留 r 和 b 列
Select(exclude=["g"])  # 丢弃 g 列

3. 水果分类项目的特征工程

对于水果分类项目,考虑以下特征工程方法:
- 由于只有三个特征,特征选择带来的价值不大。
- 所有特征都是连续的,离散化没有太大意义(可以选择应用分箱,但在这种情况下价值不大)。
- 特征缩放可以使一些分类器受益(且数据中没有异常值)。

基于以上情况,目前仅实现最小 - 最大归一化。示例代码如下:

from tinyml4all.tabular.classification import Table, Chain
from tinyml4all.tabular.features import Scale
table = Table.read_csv("fruits.csv")
# 使用 Chain 来适应更多步骤的情况
optimal_chain = Chain(Scale(method="minmax"))
table2 = optimal_chain(table)

4. 分类模型

分类模型是机器学习工作流程的下一步,它训练算法来识别每种水果的独特特征。如果在特征工程阶段做得很好,这部分应该会顺利进行。目标是优化所选模型的参数,以将准确率/F1 分数提高到最大值。

4.1 分类器的主要特征

不同类型的分类器具有以下主要特征:
- 对特征缩放的鲁棒性/不变性 :一些分类器(如决策树)无论输入规模如何都能对数据进行分类(因此可以跳过归一化);而另一些分类器(如逻辑回归)在特征具有共同规模时效果更好。
- 线性/非线性 :一些分类器仅适用于线性可分的数据(如线性支持向量机),而另一些允许多项式或径向边界(如带有高斯核的支持向量机);还有一些是基于规则的(如决策树)。
- 内存需求 :由于最终目标是将训练好的模型部署到资源受限的设备上,因此希望模型尽可能小且运行速度尽可能快。基于决策树的分类器运行速度非常快,几乎不需要 RAM(它们可以编译成 if - then - else 块);而其他分类器需要进行矩阵乘法来计算结果,这意味着它们需要在内存中存储一些权重,其内存需求会随着输入特征的数量线性(甚至更多)增加。

所有 tinyml4all 包中的分类器都共享相同的接口,因此可以在不更改其他代码的情况下交换不同的分类器。

4.2 常见分类器介绍

4.2.1 决策树

决策树是一种直观的分类器,它创建一个树状数据结构,通过逐步对数据集特征进行分割来做出决策。在每一步,算法根据信息增益原则选择要分割的特征和分割值,即选择能使不同类之间的分离得到最大改善的分割点。

优点
- 易于理解和解释:可以直观地看到决策树做出分类的原因。
- 数据准备要求低:不需要归一化,并且可以直接处理非数值(分类)数据,只需评估分箱是否能改善结果。
- 自带特征选择:不重要的特征会自动被忽略,因为它们不会产生显著的信息增益。
- 推理速度快:在微控制器上,决策树可以转换为简单的 if - then - else 列表,无需进行数学计算。

缺点
- 容易过拟合:学习到的模型可能过于复杂,过度拟合训练数据,但可以通过参数调整(如限制树的深度)来缓解。
- 不稳定:数据的微小变化可能导致生成完全不同的树。
- 不能保证最优性:由于实际实现通常基于一些启发式方法来加速学习过程,因此得到的树可能不是最优的。
- 难以学习某些概念:例如 XOR、奇偶性或多路复用器问题。
- 在不平衡数据集上有偏差:如果某些类别占主导地位,决策树学习器会创建有偏差的树,建议在拟合决策树之前平衡数据集。

4.2.2 随机森林

随机森林是决策树的集成。它训练多个不同的决策树,每个树在训练集的不同子样本上进行训练,这大大降低了过拟合的可能性,并通常提高了集成的准确率。此外,随机森林还应用了特征装袋技术,为每个树提供仅随机子集的特征,进一步防止过拟合。

在推理时,每个树预测自己的输出类别,得票最多的类别获胜并被选为集成的预测结果。

优点
- 与决策树的优点相同
- 开箱即用的准确率很高:随机森林是最容易使用的分类器之一,几乎不需要调整就能表现良好。设置合理的树的数量(10 - 20)通常就足够了,也可以调整内部决策树的参数以获得更高的准确率。

缺点
- 与决策树的缺点相同
- 黑盒模型:与决策树不同,随机森林失去了可解释性,因为由于组合了多个树,很难理解它为什么做出某个预测。

建议将随机森林作为默认分类器,因为它开箱即用的准确率较高,并且对许多特征工程预处理不敏感。

4.2.3 极端梯度提升(XGBoost)

XGBoost 自 2014 年推出以来广受欢迎,因为它在许多在线机器学习竞赛中获胜。它是一种梯度提升技术,与随机森林类似,它也组合多个决策树。不同的是,随机森林并行训练树,每个树相互独立,而梯度提升是串行训练树,每个树基于前一个树的结果进行训练,在每次迭代中,算法尝试减少损失函数。

XGBoost 的核心思想是级联建模残差误差,最终纠正这些误差。“极端”强调了一些软件优化,这些优化大大提高了训练时间和预测准确率。

优点
- 与随机森林的优点相同
- 对过拟合非常鲁棒

缺点
- 与随机森林的缺点相同
- 比随机森林慢

4.2.4 逻辑回归

尽管名称中包含“回归”,但逻辑回归实际上是一种二元分类算法。它从线性回归借用了名称,线性回归产生的线性模型形式如下:
[y = w^T x_i]
其中 (x_i) 是输入样本,(w) 是权重向量。这意味着输入样本中的每个值都乘以一个权重,然后将结果累加,产生一个连续输出。

为了从回归转换为分类,逻辑回归将逻辑函数应用于输出,使其定义域变为 [0, 1]。在二元分类中,这个值表示当前样本属于正类的概率。

训练逻辑回归的目标是最小化分类误差,或者等价地,最大化似然。样本 (i) 属于正类的概率计算公式为:
[p_i = logit(w^T x_i)]
整个数据集的似然计算公式为:
[L(w) = \sum_{i=1}^{N} [y_i \ln(p_i) + (1 - y_i) \ln(1 - p_i)]]
其中 (y_i) 是样本的真实标签(由于是二元分类器,(y_i) 为 0 或 1)。

优点
- 推理速度快(与特征数量呈线性关系)
- 预测类成员的概率
- 权重系数可以表示特征对于类成员的“重要性”

缺点
- 对噪声和异常值敏感
- 权重数量随输入数量线性增长
- 线性模型,因此最好对输入数据进行转换以提高准确率(如应用幂、对数、平方根运算)
- 对相关输入敏感
- 可能无法收敛到 (w) 的最优值

4.2.5 支持向量机(SVM)

支持向量机是一种二元分类算法,可通过一对一投票方案应用于多类问题。SVM 的核心思想是找到两个类之间的分离边界,并使边界的间隔尽可能大,以提供鲁棒的分类。

间隔仅由训练集中的一些有意义的点(支持向量)计算得出,这些点位于两个类的边界上,是最难分类的点。

在现实世界的数据中,通常很难找到两个类之间的清晰分离,甚至这种分离可能不存在。为了解决这个问题,SVM 的主要思路是将原始数据投影到更高维的空间中,在这个新的高维空间中,两个类更容易分离。

优点
- 在高维数据中有效
- 推理时仅使用支持向量
- 对异常值鲁棒

缺点
- 训练时间随训练样本数量的增加而增加得不好
- 在存在许多重叠类的情况下表现不佳
- 需要调整多个参数才能表现良好
- 仅适用于数值输入
- 黑盒模型
- 对于 (n) 个特征和 (k) 个支持向量,需要在 RAM 中存储的权重数量为 (n * k)(类的可分离性越差,(k) 越大,每个类至少有一个支持向量,通常更多)

4.3 分类器的比较

分类器 优点 缺点
决策树 训练和执行速度快;对特征规模不敏感;部署后内存效率高 容易过拟合,在不平衡设置中有偏差;可能表现出次优的准确率
随机森林 与决策树的优点相同;开箱即用的准确率更高 不可解释
XGBoost 与随机森林的优点相同;可以提高几个百分点的准确率 比随机森林训练慢
逻辑回归 推理时间和内存与特征数量呈线性关系 推理时间和内存与特征数量呈线性关系;线性模型;对异常值敏感
SVM 在高维数据中有效;对异常值鲁棒 在大型数据集上训练慢;需要参数调整才能工作良好;推理时间和内存与特征数量的关系大于线性

4.4 水果项目的分类器应用

现在已经列举了可用的分类器,下面看看如何将它们应用到水果项目中。分类器的 API 与特征工程步骤类似。

from tinyml4all.tabular.classification.models import DecisionTree, RandomForest, LogisticRegression, SVM
# 打印给定分类器可以设置的参数描述
print(help(RandomForest))
# 训练分类器并进行预测
rf = RandomForest(n_estimators=20)
table2 = rf(table)
# table.full() 打印数据 + 真实标签 + 预测标签
print(table2.full())

输出示例:

r  g  b  truth  __prediction__
0  38  23  18  orange  orange
1  40  22  18  orange  orange
2  49  25  19  orange  orange
3  65  31  22  orange  orange
4  54  25  18  orange  orange

为了快速检查分类器的整体性能,可以生成分类报告。示例代码如下:

print(table2.classification_report())

输出示例:

              precision    recall  f1-score   support
      orange       1.00      0.90      0.95        50
      tomato       0.89      1.00      0.94        50
    zucchini       1.00      0.98      0.99        50
    accuracy                           0.96       150
   macro avg       0.96      0.96      0.96       150
weighted avg       0.96      0.96      0.96       150
+-------------------+--------+-------+---------- +
| True vs. Predicted | orange | tomato | zucchini  |
+-------------------+--------+------ -+----------+
|       orange       |   45   |   5    |    0     |
|       tomato       |   0    |   50   |    0     |
|      zucchini      |   0    |   1    |    49     |
+-------------------+--------+--------+----------+

综上所述,在机器学习项目中,特征工程和分类模型的选择与应用是非常重要的环节。通过合理处理异常值、选择合适的特征和分类器,可以提高模型的性能和准确性。

5. 总结与建议

5.1 特征工程总结

  • 异常值处理 :异常值会影响特征缩放效果,最小 - 最大归一化对异常值敏感,识别异常值可查看表格摘要中各分位数差值。存在异常值时可考虑鲁棒缩放。
  • 特征选择 :目标是防止维度灾难、去除冗余和无关特征、用最少特征实现高指标。方法有顺序特征选择、基于分数的选择、递归特征消除,各有优缺点,可根据数据集大小和分类器选择合适方法,也可手动选择列。
  • 水果项目特征工程 :水果项目特征少,特征选择价值不大,特征连续离散化意义小,特征缩放可使部分分类器受益,可采用最小 - 最大归一化。

5.2 分类模型总结

分类器 优点 缺点 适用场景
决策树 易理解、数据准备要求低、自带特征选择、推理快 易过拟合、不稳定、不保证最优、难学某些概念、不平衡数据有偏差 数据简单、对解释性要求高
随机森林 继承决策树优点、准确率高、少调参 不可解释 对解释性要求不高、追求高准确率
XGBoost 继承随机森林优点、抗过拟合强 训练慢 对准确率要求极高、数据量大
逻辑回归 推理快、预测概率、体现特征重要性 对噪声和异常值敏感、线性模型有局限 数据线性可分、对推理速度要求高
SVM 高维数据有效、对异常值鲁棒 训练慢、多参数调整、仅适用于数值输入 高维数据、异常值多

5.3 整体流程建议

graph LR
    A[数据获取] --> B[异常值检测]
    B --> C{是否有异常值}
    C -- 是 --> D[鲁棒缩放]
    C -- 否 --> E[特征选择]
    D --> E
    E --> F{特征选择方法}
    F -- 数据少 --> G[顺序特征选择]
    F -- 快速初步筛选 --> H[基于分数的选择]
    F -- 中等数据 --> I[递归特征消除]
    G --> J[特征缩放]
    H --> J
    I --> J
    J --> K{分类器选择}
    K -- 解释性高 --> L[决策树]
    K -- 高准确率少调参 --> M[随机森林]
    K -- 极高准确率 --> N[XGBoost]
    K -- 线性可分推理快 --> O[逻辑回归]
    K -- 高维数据异常值多 --> P[SVM]
    L --> Q[模型训练与评估]
    M --> Q
    N --> Q
    O --> Q
    P --> Q

在实际项目中,可按照上述流程进行操作。首先获取数据,检测异常值,根据情况进行缩放。然后进行特征选择,选择合适的方法。接着根据数据特点和项目需求选择分类器,最后进行模型训练和评估。在每个步骤中,都要根据实际情况进行调整和优化,以达到最佳的模型性能。

例如,对于水果分类项目,由于数据简单、特征少且无异常值,可先进行最小 - 最大归一化,再根据对解释性和准确率的要求选择决策树或随机森林进行分类。在训练过程中,不断调整模型参数,通过分类报告等评估指标来优化模型。

Logo

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

更多推荐