31、数据特征处理:从独热编码到多项式特征与特征选择

数据特征处理:从独热编码到多项式特征与特征选择

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)
  1. 创建 RFECV 实例 :将定义好的模型作为参数传递给 RFECV 类,并可以设置其他参数,如 n_jobs=-1 表示使用所有可用的 CPU 核心。
from sklearn.feature_selection import RFECV
rfecv = RFECV(estimator=model, n_jobs=-1) 
  1. 拟合数据 :使用 fit 方法对数据进行拟合,该方法会自动进行递归特征消除和交叉验证。
best_feat = rfecv.fit(X_poly[2], y) 
  1. 筛选特征 :根据 RFECV 实例的 support_ 属性,筛选出对模型有帮助的特征。
X_support = X_poly[2][:, best_feat.support_] 
  1. 评估模型 :使用筛选后的特征对模型进行训练和评估,比较不同特征处理方法下模型的性能。
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

通过这个流程图,我们可以更清晰地看到整个特征处理的流程,以及不同步骤之间的关系。在实际应用中,我们可以根据具体情况选择合适的处理方法,以达到最佳的建模效果。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值