数据特征处理:从独热编码到多项式特征与特征选择
1. 独热编码基础
在数据处理中,我们常常会遇到包含多个类别值的特征。为了让这些特征适用于模型和统计技术,通常需要将它们编码为数字。常见的做法是将类别值映射为数字序号,例如在调查数据中,将编程语言特征进行编码,如 Python=1,R=2,JavaScript=3 等。然而,不同的编程语言之间并没有内在或明显的顺序,强加这种人为的顺序可能会影响模型的质量。
为了避免这种人为排序,我们可以使用独热编码(One-Hot Encoding)。独热编码的核心思想是将一个具有多个值的特征转换为多个特征,每个类别值对应一个新特征。在这些新特征中,只有一个特征的值为 1,其余特征的值为 0(或者根据编程语言和库的不同,表现为 True/False)。
例如,在调查数据集中,“最喜欢的编程语言”列就是一个适合进行独热编码的候选特征。在 Pandas 中,可以使用
get_dummies()
函数实现独热编码;在 scikit-learn 中,
OneHotEncoder
类可以完成相同的任务,并且它不仅适用于 Pandas 数据框,还可以处理类似矩阵的数据。
以下是使用 Pandas 进行独热编码的示例代码:
survey6 = pd.get_dummies(survey5, prefix="Lang")
survey6.sample(10, random_state=3).T.tail(8)
结果如下:
| | 83 | 5 | 6 | 42 | 100 | 97 | 40 | 25 | 115 | 103 |
| — | — | — | — | — | — | — | — | — | — | — |
| Lang_C++ | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| Lang_JavaScript | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| Lang_MATLAB | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
| Lang_Python | 0 | 1 | 1 | 0 | 1 | 1 | 1 | 0 | 1 | 0 |
| Lang_R | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 |
| Lang_Scala | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| Lang_VB | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| Lang_Whitespace | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
使用 scikit-learn 进行独热编码的示例代码如下:
from sklearn.preprocessing import OneHotEncoder
lang = survey5[['Language']]
enc = OneHotEncoder(sparse=False).fit(lang)
one_hot = enc.transform(lang)
print(enc.get_feature_names())
print("\nA few encoded rows:")
print(one_hot[80:90])
输出结果为:
['x0_C++' 'x0_JavaScript' 'x0_MATLAB' 'x0_Python' 'x0_R' 'x0_Sc' 'x0_VB' 'x0_Whitespace']
A few encoded rows:
[[0. 0. 0. 1. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 1.]
[0. 0. 0. 1. 0. 0. 0. 0.]
[0. 0. 1. 0. 0. 0. 0. 0.]
[0. 0. 0. 1. 0. 0. 0. 0.]
[0. 0. 0. 1. 0. 0. 0. 0.]
[0. 0. 0. 1. 0. 0. 0. 0.]
[0. 0. 0. 1. 0. 0. 0. 0.]
[0. 0. 0. 0. 1. 0. 0. 0.]
[0. 0. 0. 1. 0. 0. 0. 0.]]
2. 多项式特征生成
多项式特征生成是一种可以创建大量新合成特征的方法。其基本思想是添加新特征,这些新特征是现有特征最多 N 个的乘积。在 scikit-learn 中,
PolynomialFeatures
类可以完成这个任务,它会对所有参数组合(直到指定的阶数)进行乘法运算。
例如,对于原始特征数量为 30 的数据,在阶数为 2 时,会生成 496 个多项式特征;当原始特征数量为 100 时,阶数为 2 会生成 5151 个多项式特征。
以下是使用 Wisconsin 乳腺癌数据集生成多项式特征的示例代码:
from sklearn.datasets import load_breast_cancer
from sklearn.preprocessing import MinMaxScaler
from sklearn.preprocessing import PolynomialFeatures
import pandas as pd
cancer = load_breast_cancer()
X_raw = MinMaxScaler().fit_transform(cancer.data)
y = cancer.target
poly = dict()
X_poly = dict()
print(f"Raw data set shape: {cancer.data.shape}")
for n in [2, 3, 4, 5]:
poly[n] = PolynomialFeatures(n)
X_poly[n] = poly[n].fit_transform(X_raw)
print(f"Degree {n} polynomial: {X_poly[n].shape}")
输出结果为:
Raw data set shape: (569, 30)
Degree 2 polynomial: (569, 496)
Degree 3 polynomial: (569, 5456)
Degree 4 polynomial: (569, 46376)
Degree 5 polynomial: (569, 324632)
从输出结果可以看出,随着多项式阶数的增加,特征数量会急剧增加。过多的特征可能会导致“维度灾难”,使模型的效果和统计意义变差。因此,在生成多项式特征后,通常需要进行特征选择。
3. 特征选择的必要性
当特征数量过多时,模型的效果和统计意义可能会受到影响。一个粗略的经验法则是,列数不应超过行数的十分之一。不同的模型对特征数量有不同的要求,但总体来说,即使对于拥有数百万观测值的数据集,特征维度的上限也应该控制在几百个左右。
在深度学习中,虽然有时输入层的维度可能会超过这个经验法则,但网络的初始层通常会进行降维操作,实际上是在进行特征选择。
4. 特征选择方法
有多种方法可以进行特征选择,其中最简单的方法是对每个特征的预测强度进行单变量建模,例如在 scikit-learn 中可以使用
SelectKBest
类。然而,更强大的技术是基于特定的模型对象(即一个类和一组超参数)递归地消除特征。
在 scikit-learn 中,
RFE
和
RFECV
类可以进行递归特征消除。
RFECV
类更加精确,但速度较慢,它通过多次训练模型并结合交叉验证来选择特征。
以下是使用
RFECV
对乳腺癌数据集的二阶多项式特征进行特征选择的示例代码:
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.feature_selection import RFECV
model = RandomForestClassifier(n_estimators=100, max_depth=5, n_jobs=4, random_state=2)
rfecv = RFECV(estimator=model, n_jobs=-1)
best_feat = rfecv.fit(X_poly[2], y)
X_support = X_poly[2][:, best_feat.support_]
print(X_support.shape)
for X in (X_raw, X_poly[2], X_support):
X_train, X_test, y_train, y_test = (
train_test_split(X, y, random_state=42))
model.fit(X_train, y_train)
accuracy = model.score(X_test, y_test)
error_rate = 100*(1-accuracy)
print(f"Features | {X.shape=}\t| {error_rate=:.2f}%")
输出结果为:
(569, 337)
Features | X.shape=(569, 30) | error_rate=2.80%
Features | X.shape=(569, 496) | error_rate=1.40%
Features | X.shape=(569, 337) | error_rate=0.70%
从结果可以看出,使用多项式特征可以显著降低错误率,而经过特征选择后,错误率进一步降低。这表明特征选择在提高模型准确性方面起着重要作用。
5. 总结
在数据处理和建模过程中,独热编码、多项式特征生成和特征选择是非常重要的步骤。独热编码可以避免人为排序对模型的影响;多项式特征生成可以创建更多的合成特征,但可能会导致维度灾难;特征选择则可以帮助我们筛选出真正对模型有帮助的特征,提高模型的效果和性能。通过合理运用这些技术,我们可以更好地处理数据,构建更强大的模型。
以下是整个数据处理流程的 mermaid 流程图:
graph LR
A[原始数据] --> B[独热编码]
B --> C[多项式特征生成]
C --> D[特征选择]
D --> E[模型训练与评估]
综上所述,在实际应用中,我们需要根据数据的特点和模型的需求,灵活运用这些方法,以达到最佳的建模效果。
数据特征处理:从独热编码到多项式特征与特征选择
6. 不同特征处理方法的对比分析
为了更直观地了解不同特征处理方法对模型性能的影响,我们将上述使用的几种方法进行对比。以下是一个总结表格:
| 特征处理方法 | 特征数量 | 错误率 | 说明 |
| — | — | — | — |
| 原始特征 | 30 | 2.80% | 未经过任何特征处理的原始数据 |
| 二阶多项式特征(未筛选) | 496 | 1.40% | 通过
PolynomialFeatures
生成的二阶多项式特征 |
| 二阶多项式特征(筛选后) | 337 | 0.70% | 使用
RFECV
进行特征选择后的特征 |
从表格中可以清晰地看到,使用多项式特征能够显著降低错误率,而经过特征选择后,模型的错误率进一步降低。这充分说明了特征处理的重要性,以及特征选择在提高模型性能方面的关键作用。
7. 特征选择的具体操作步骤
对于特征选择,尤其是使用
RFECV
进行递归特征消除,具体的操作步骤如下:
1.
定义模型
:选择一个合适的模型,并设置好相应的超参数。例如,在上述示例中,我们使用了
RandomForestClassifier
作为模型,并设置了
n_estimators=100
,
max_depth=5
等超参数。
from sklearn.ensemble import RandomForestClassifier
model = RandomForestClassifier(n_estimators=100, max_depth=5, n_jobs=4, random_state=2)
-
创建
RFECV实例 :将定义好的模型作为参数传递给RFECV类,并可以设置其他参数,如n_jobs=-1表示使用所有可用的 CPU 核心。
from sklearn.feature_selection import RFECV
rfecv = RFECV(estimator=model, n_jobs=-1)
-
拟合数据
:使用
fit方法对数据进行拟合,该方法会自动进行递归特征消除和交叉验证。
best_feat = rfecv.fit(X_poly[2], y)
-
筛选特征
:根据
RFECV实例的support_属性,筛选出对模型有帮助的特征。
X_support = X_poly[2][:, best_feat.support_]
- 评估模型 :使用筛选后的特征对模型进行训练和评估,比较不同特征处理方法下模型的性能。
from sklearn.model_selection import train_test_split
for X in (X_raw, X_poly[2], X_support):
X_train, X_test, y_train, y_test = (
train_test_split(X, y, random_state=42))
model.fit(X_train, y_train)
accuracy = model.score(X_test, y_test)
error_rate = 100*(1-accuracy)
print(f"Features | {X.shape=}\t| {error_rate=:.2f}%")
8. 不同编程语言中的实现
除了 Python 中的 scikit-learn,R 语言也提供了相应的功能来进行特征处理和特征选择。
在 R 中,可以使用
caret
包中的
rfe()
和
rfeControl()
函数进行递归特征消除。以下是一个简单的示例,展示了如何在 R 中生成多项式特征:
library(tibble)
library(caret)
X <- tibble(A = c(0.2, 0.3, 0.4),
B = c(0.1, -0.3, 0.5),
C = c(-0.2, 0.3, 0.1))
formula = ~ .^3
poly2 <- as.tibble(model.matrix(formula, data=X))
print(poly2)
输出结果如下:
# A tibble: 3 x 8
'(Intercept)' A B C 'A:B' 'A:C' 'B:C' 'A:B:C'
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 1 0.2 0.1 -0.2 0.02 -0.04 -0.02 -0.004
2 1 0.3 -0.3 0.3 -0.09 0.09 -0.09 -0.027
3 1 0.4 0.5 0.1 0.2 0.04 0.05 0.02
从输出结果可以看到,R 语言通过
model.matrix
函数生成了包含原始特征、两两特征乘积以及三个特征乘积的多项式特征。
9. 注意事项和适用场景
在进行特征处理和特征选择时,有一些注意事项和适用场景需要我们关注:
-
独热编码
:
-
注意事项
:独热编码会增加特征的维度,可能导致数据稀疏。在处理大规模数据时,需要考虑内存和计算资源的问题。
-
适用场景
:适用于处理具有多个类别值的特征,尤其是类别之间没有明显顺序关系的情况。
-
多项式特征生成
:
-
注意事项
:随着多项式阶数的增加,特征数量会急剧增加,容易导致“维度灾难”。因此,在使用时需要谨慎选择多项式的阶数。
-
适用场景
:当原始特征之间可能存在非线性关系时,多项式特征生成可以帮助模型捕捉这些关系,提高模型的性能。
-
特征选择
:
-
注意事项
:不同的特征选择方法适用于不同的模型和数据。在选择特征选择方法时,需要考虑模型的类型和数据的特点。
-
适用场景
:当特征数量过多时,特征选择可以帮助我们筛选出对模型有帮助的特征,减少噪声,提高模型的性能和计算效率。
10. 总结与展望
通过本文的介绍,我们了解了独热编码、多项式特征生成和特征选择等特征处理方法的原理、实现和应用。这些方法在数据处理和建模过程中起着至关重要的作用,可以帮助我们提高模型的性能和效率。
在实际应用中,我们需要根据数据的特点和模型的需求,灵活运用这些方法。同时,我们也可以尝试不同的组合和参数,以找到最佳的特征处理方案。
未来,随着数据量的不断增加和模型复杂度的不断提高,特征处理和特征选择的重要性将更加凸显。我们需要不断探索和创新,开发出更加高效和智能的特征处理方法,以应对日益复杂的数据挑战。
以下是整个特征处理流程的 mermaid 流程图,包含了不同的处理步骤和选择方法:
graph LR
A[原始数据] --> B{是否为类别特征}
B -- 是 --> C[独热编码]
B -- 否 --> D[原始特征]
C --> E[多项式特征生成]
D --> E
E --> F{是否需要特征选择}
F -- 是 --> G[特征选择(如 RFECV)]
F -- 否 --> H[直接使用特征]
G --> I[模型训练与评估]
H --> I
通过这个流程图,我们可以更清晰地看到整个特征处理的流程,以及不同步骤之间的关系。在实际应用中,我们可以根据具体情况选择合适的处理方法,以达到最佳的建模效果。
超级会员免费看
17万+

被折叠的 条评论
为什么被折叠?



