Python特征工程实用指南
立即解锁
发布时间: 2025-09-04 01:01:46 阅读量: 7 订阅数: 19 AIGC 

# Python 特征工程实用指南
## 1. 特征工程概述
特征工程在机器学习中至关重要,它涵盖了从数据中提取、转换和创建特征的一系列操作,旨在为机器学习模型提供更优质的数据,从而提升模型的性能。特征工程的主要任务包括处理缺失数据、对分类变量进行编码、转换数值变量、离散化变量、处理异常值、从日期和时间变量中提取特征、对特征进行缩放以及创建新特征等。
## 2. 适用人群
特征工程适用于以下人群:
- 机器学习和数据科学的学生和专业人士。
- 从事机器学习模型部署的软件工程师。
这些人群可以通过学习特征工程,掌握如何转换数据和创建新特征,以训练出更优秀的机器学习模型。
## 3. 技术要求
在进行特征工程时,需要满足以下软件和硬件要求:
### 3.1 软件版本
| 库名称 | 版本号 |
| --- | --- |
| category - encoders | 2.4.0 |
| Feature - engine | 1.4.0 |
| featuretools | 1.4.0, 1.5.0 |
| matplotlib | 3.4.2 |
| numpy | 1.22.0 |
| pandas | 1.5.0 |
| scikit - learn | 1.1.0 |
| scipy | 1.7.0 |
| seaborn | 0.11.1 |
| statsmodels | 0.12.2 |
| tsfresh | 0.19.0 |
### 3.2 操作系统要求
- Python 3.3 或更高版本。
- 支持 Windows、macOS 或 Linux 操作系统。
- 可使用 Jupyter Notebook,支持 Windows、macOS 或 Linux 系统。
需要注意的是,使用与上述不同的版本可能会导致代码无法运行。如果使用较新版本,需查看其在线文档,确认参数名称是否有变化。
### 3.3 代码获取
- 可以从 GitHub 下载示例代码文件,链接为:https://github.com/PacktPublishing/Python - Feature - Engineering - Cookbook - Second - Edition 。
- 若代码有更新,GitHub 仓库会同步更新。
- 还可访问 https://github.com/PacktPublishing/ 查看其他代码包。
### 3.4 彩色图像下载
可从 https://packt.link/UXyxc 下载包含书中截图和图表彩色图像的 PDF 文件。
## 4. 缺失数据处理
缺失数据在实际数据集中很常见,处理缺失数据的方法有多种,以下是一些常见的处理方法:
### 4.1 移除含缺失数据的观测值
- **操作步骤**:
1. 识别数据集中包含缺失值的观测。
2. 将这些观测从数据集中移除。
- **适用场景**:当缺失数据占比较小,且移除这些观测不会对数据集的整体结构和信息造成较大影响时适用。
- **局限性**:可能会丢失有价值的信息,尤其是当缺失数据并非随机分布时。
### 4.2 均值或中位数填充
- **操作步骤**:
1. 对于数值型变量,计算其均值或中位数。
2. 使用计算得到的均值或中位数填充缺失值。
```python
import pandas as pd
import numpy as np
# 示例数据
data = {'col1': [1, 2, np.nan, 4, 5], 'col2': [6, np.nan, 8, 9, 10]}
df = pd.DataFrame(data)
# 计算均值
mean_value = df['col1'].mean()
# 填充缺失值
df['col1'].fillna(mean_value, inplace=True)
```
- **适用场景**:数据分布较为对称,没有明显的异常值时,均值填充效果较好;当数据存在异常值时,中位数填充更为稳健。
- **局限性**:会改变数据的分布,可能会低估数据的方差。
### 4.3 分类变量填充
- **操作步骤**:
1. 对于分类变量,找出出现频率最高的类别(众数)。
2. 使用众数填充缺失值。
```python
# 示例数据
data = {'col': ['A', 'B', 'A', np.nan, 'B']}
df = pd.DataFrame(data)
# 计算众数
mode_value = df['col'].mode()[0]
# 填充缺失值
df['col'].fillna(mode_value, inplace=True)
```
- **适用场景**:适用于分类变量的缺失值处理。
- **局限性**:可能会导致类别分布的偏差。
### 4.4 用任意数替换缺失值
- **操作步骤**:
1. 选择一个合适的任意数。
2. 使用该任意数替换缺失值。
```python
# 示例数据
data = {'col': [1, 2, np.nan, 4, 5]}
df = pd.DataFrame(data)
# 选择任意数
arbitrary_number = -999
# 替换缺失值
df['col'].fillna(arbitrary_number, inplace=True)
```
- **适用场景**:当缺失值本身具有特殊含义,或者希望将缺失值与正常数据明显区分开时适用。
- **局限性**:可能会影响模型对数据的理解,尤其是当该任意数与正常数据范围差异较大时。
### 4.5 寻找极端值进行填充
- **操作步骤**:
1. 确定数据的分布特征,如计算上下四分位数。
2. 根据分布特征确定极端值,如使用 IQR(四分位距)方法。
3. 使用极端值填充缺失值。
```python
import numpy as np
# 示例数据
data = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, np.nan])
# 计算四分位数
Q1 = np.percentile(data[~np.isnan(data)], 25)
Q3 = np.percentile(data[~np.isnan(data)], 75)
IQR = Q3 - Q1
# 确定极端值
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
# 填充缺失值
data[np.isnan(data)] = upper_bound
```
- **适用场景**:当缺失值可能与极端情况相关时适用。
- **局限性**:极端值的确定可能存在主观性,且可能会引入噪声。
### 4.6 标记填充值
- **操作步骤**:
1. 创建一个新的二进制变量,用于标记哪些值是填充得到的。
2. 对原始变量进行填充操作。
```python
# 示例数据
data = {'col': [1, 2, np.nan, 4, 5]}
df = pd.DataFrame(data)
# 创建标记变量
df['col_missing'] = df['col'].isnull().astype(int)
# 填充缺失值
df['col'].fillna(df['col'].mean(), inplace=True)
```
- **适用场景**:可以让模型了解哪些值是填充得到的,有助于模型更好地处理数据。
- **局限性**:增加了数据的维度,可能会增加模型的复杂度。
### 4.7 链式方程多元填充
- **操作步骤**:
1. 选择一个合适的多元填充算法,如基于回归模型的链式方程填充。
2. 对数据集进行多次迭代填充,每次迭代根据其他变量的值预测缺失值。
```python
from sklearn.experimental import enable_iterative_imputer
from sklearn.impute import IterativeImputer
import pandas as pd
import numpy as np
# 示例数据
data = {'col1': [1, 2, np.nan, 4, 5], 'col2': [6, np.nan, 8, 9, 10]}
df = pd.DataFrame(data)
# 创建迭代填充器
imputer = IterativeImputer()
# 填充数据
df_filled = pd.DataFrame(imputer.fit_transform(df), columns=df.columns)
```
- **适用场景**:当变量之间存在复杂的关系,且缺失数据并非完全随机时适用。
- **局限性**:计算复杂度较高,需要较长的计算时间。
### 4.8 近邻估计填充
- **操作步骤**:
1. 确定距离度量方法,如欧氏距离。
2. 对于每个缺失值,找到与其最近的 k 个邻居。
3. 使用这 k 个邻居的值来估计缺失值。
```python
from sklearn.impute import KNNImputer
import pandas as pd
import numpy as np
# 示例数据
data = {'col1': [1, 2, np.nan, 4, 5], 'col2': [6, np.nan, 8, 9, 10]}
df = pd.DataFrame(data)
# 创建 KNN 填充器
imputer = KNNImputer(n_neighbors=2)
# 填充数据
df_filled = pd.DataFrame(imputer.fit_transform(df), columns=df.columns)
```
- **适用场景**:当数据具有局部相似性时适用。
- **局限性**:邻居数量 k 的选择较为困难,不同的 k 值可能会导致不同的填充结果。
## 5. 分类变量编码
分类变量在机器学习模型中通常需要转换为数值型变量,以下是一些常见的分类变量编码方法:
### 5.1 独热编码
- **操作步骤**:
1. 对于每个分类变量的每个类别,创建一个新的二进制变量。
2. 如果某个观测属于该类别,则对应的二进制变量值为 1,否则为 0。
```python
import pandas as pd
# 示例数据
data = {'col': ['A', 'B', 'A', 'C']}
df = pd.DataFrame(data)
# 独热编码
encoded_df = pd.get_dummies(df, columns=['col'])
```
- **适用场景**:适用于类别数量较少的分类变量。
- **局限性**:会增加数据的维度,当类别数量较多时,可能会导致维度灾难。
### 5.2 高频类别独热编码
- **操作步骤**:
1. 统计每个类别的出现频率。
2. 选择出现频率较高的类别进行独热编码,将其他类别合并为一个“其他”类别。
```python
import pandas as pd
# 示例数据
data = {'col': ['A', 'B', 'A', 'C', 'D', 'D', 'A']}
df = pd.DataFrame(data)
# 统计频率
category_counts = df['col'].value_counts()
# 选择高频类别
frequent_categories = category_counts[category_counts > 1].index
# 合并低频类别
df['col'] = df['col'].apply(lambda x: x if x in frequent_categories else 'Other')
# 独热编码
encoded_df = pd.get_dummies(df, columns=['col'])
```
- **适用场景**:当分类变量的类别数量较多,且大部分观测集中在少数几个类别时适用。
- **局限性**:合并低频类别可能会丢失一些信息。
### 5.3 计数或频率替换
- **操作步骤**:
1. 统计每个类别的出现次数或频率。
2. 使用统计得到的次数或频率替换原始的类别值。
```python
import pandas as pd
# 示例数据
data = {'col': ['A', 'B', 'A', 'C', 'D', 'D', 'A']}
df = pd.DataFrame(data)
# 计算频率
category_frequency = df['col'].value_counts(normalize=True)
# 替换类别值
df['col'] = df['col'].map(category_frequency)
```
- **适用场景**:可以保留类别之间的相对重要性信息。
- **局限性**:可能会导致不同类别之间的差异被缩小。
### 5.4 序数编码
- **操作步骤**:
1. 为每个类别分配一个唯一的整数。
2. 使用这些整数替换原始的类别值。
```python
from sklearn.preprocessing import OrdinalEncoder
import pandas as pd
# 示例数据
data = {'col': ['A', 'B', 'A', 'C']}
df = pd.DataFrame(data)
# 创建序数编码器
encoder = OrdinalEncoder()
# 编码数据
df['col'] = encoder.fit_transform(df[['col']])
```
- **适用场景**:当类别之间存在天然的顺序关系时适用。
- **局限性**:如果类别之间不存在顺序关系,可能会引入错误的信息。
### 5.5 基于目标值的序数编码
- **操作步骤**:
1. 根据目标变量的值,对每个类别进行排序。
2. 为排序后的类别分配序数。
```python
import pandas as pd
from category_encoders import OrdinalEncoder
# 示例数据
data = {'col': ['A', 'B', 'A', 'C'], 'target': [1, 0, 1, 0]}
df = pd.DataFrame(data)
# 创建编码器
encoder = OrdinalEncoder(cols=['col'], mapping=[{'col': 'A', 'target': 1}, {'col': 'B', 'target': 0}, {'col': 'C', 'target': 0}])
# 编码数据
df_encoded = encoder.fit_transform(df)
```
- **适用场景**:当类别与目标变量之间存在一定的关联时适用。
- **局限性**:需要有目标变量,且可能会导致过拟合。
### 5.6 目标均值编码
- **操作步骤**:
1. 对于每个类别,计算其对应的目标变量的均值。
2. 使用计算得到的均值替换原始的类别值。
```python
import pandas as pd
from category_encoders import TargetEncoder
# 示例数据
data = {'col': ['A', 'B', 'A', 'C'], 'target': [1, 0, 1, 0]}
df = pd.DataFrame(data)
# 创建编码器
encoder = TargetEncoder()
# 编码数据
df['col'] = encoder.fit_transform(df['col'], df['target'])
```
- **适用场景**:可以捕捉类别与目标变量之间的关系。
- **局限性**:可能会导致过拟合,尤其是当数据量较小时。
### 5.7 证据权重编码
- **操作步骤**:
1. 计算每个类别中正例和反例的比例。
2. 根据比例计算证据权重。
3. 使用证据权重替换原始的类别值。
```python
import pandas as pd
from category_encoders import WOEEncoder
# 示例数据
data = {'col': ['A', 'B', 'A', 'C'], 'target': [1, 0, 1, 0]}
df = pd.DataFrame(data)
# 创建编码器
encoder = WOEEncoder()
# 编码数据
df['col'] = encoder.fit_transform(df['col'], df['target'])
```
- **适用场景**:常用于金融领域的信用评分模型。
- **局限性**:需要有明确的正例和反例定义,且计算过程相对复杂。
### 5.8 合并稀有类别
- **操作步骤**:
1. 统计每个类别的出现频率。
2. 将出现频率较低的类别合并为一个新的类别。
```python
import pandas as pd
# 示例数据
data = {'col': ['A', 'B', 'A', 'C', 'D', 'D', 'A']}
df = pd.DataFrame(data)
# 统计频率
category_counts = df['col'].value_counts()
# 合并低频类别
df['col'] = df['col'].apply(lambda x: x if category_counts[x] > 1 else 'Other')
```
- **适用场景**:当分类变量的类别数量较多,且大部分观测集中在少数几个类别时适用。
- **局限性**:合并低频类别可能会丢失一些信息。
### 5.9 二进制编码
- **操作步骤**:
1. 为每个类别分配一个唯一的整数。
2. 将整数转换为二进制表示。
3. 将二进制表示拆分为多个二进制变量。
```python
import pandas as pd
from category_encoders import BinaryEncoder
# 示例数据
data = {'col': ['A', 'B', 'A', 'C']}
df = pd.DataFrame(data)
# 创建编码器
encoder = BinaryEncoder()
# 编码数据
encoded_df = encoder.fit_transform(df)
```
- **适用场景**:可以在一定程度上减少独热编码带来的维度增加问题。
- **局限性**:编码后的变量之间可能存在复杂的关系,解释性较差。
## 6. 数值变量转换
在机器学习中,对数值变量进行转换可以改善数据的分布,提高模型的性能。以下是一些常见的数值变量转换方法:
### 6.1 对数转换
- **操作步骤**:
1. 对原始的数值变量取对数。
```python
import numpy as np
import pandas as pd
# 示例数据
data = {'col': [1, 2, 3, 4, 5]}
df = pd.DataFrame(data)
# 对数转换
df['col_log'] = np.log(df['col'])
```
- **适用场景**:当数据的分布呈右偏态,且数据值均为正数时适用。
- **局限性**:不能处理零值和负值。
### 6.2 倒数转换
- **操作步骤**:
1. 对原始的数值变量取倒数。
```python
import numpy as np
import pandas as pd
# 示例数据
data = {'col': [1, 2, 3, 4, 5]}
df = pd.DataFrame(data)
# 倒数转换
df['col_reciprocal'] = 1 / df['col']
```
- **适用场景**:可以将数据的大值缩小,小值放大,适用于数据分布范围较大的情况。
- **局限性**:不能处理零值。
### 6.3 平方根转换
- **操作步骤**:
1. 对原始的数值变量取平方根。
```python
import numpy as np
import pandas as pd
# 示例数据
data = {'col': [1, 4, 9, 16, 25]}
df = pd.DataFrame(data)
# 平方根转换
df['col_sqrt'] = np.sqrt(df['col'])
```
- **适用场景**:当数据的分布呈右偏态,且数据值均为非负数时适用。
- **局限性**:转换效果相对较弱。
### 6.4 幂转换
- **操作步骤**:
1. 选择一个合适的幂指数。
2. 对原始的数值变量进行幂运算。
```python
import numpy as np
import pandas as pd
# 示例数据
data = {'col': [1, 2, 3, 4, 5]}
df = pd.DataFrame(data)
# 幂转换
power = 2
df['col_power'] = np.power(df['col'], power)
```
- **适用场景**:可以根据数据的特点选择不同的幂指数,以达到不同的转换效果。
- **局限性**:幂指数的选择可能需要进行试验。
### 6.5 Box - Cox 转换
- **操作步骤**:
1. 确定 Box - Cox 转换的参数 λ。
2. 根据参数 λ 对原始的数值变量进行转换。
```python
from scipy.stats import boxcox
import pandas as pd
# 示例数据
data = {'col': [1, 2, 3, 4, 5]}
df = pd.DataFrame(data)
# Box - Cox 转换
df['col_boxcox'], lambda_value = boxcox(df['col'])
```
- **适用场景**:可以自动寻找最优的转换参数,使数据更接近正态分布。
- **局限性**:要求数据值均为正数。
### 6.6 Yeo - Johnson 转换
- **操作步骤**:
1. 确定 Yeo - Johnson 转换的参数 λ。
2. 根据参数 λ 对原始的数值变量进行转换。
```python
from sklearn.preprocessing import PowerTransformer
import pandas as pd
# 示例数据
data = {'col': [1, 2, 3, 4, 5]}
df = pd.DataFrame(data)
# 创建转换对象
transformer = PowerTransformer(method='yeo-johnson')
# 转换数据
df['col_yeojohnson'] = transformer.fit_transform(df[['col']])
```
- **适用场景**:可以处理包含零值和负值的数据,应用范围更广。
- **局限性**:转换结果的解释性相对较差。
## 7. 变量离散化
变量离散化是将连续型变量转换为离散型变量的过程,以下是一些常见的变量离散化方法:
### 7.1 等宽离散化
- **操作步骤**:
1. 确定离散化的区间数量。
2. 根据变量的取值范围,将其划分为等宽的区间。
3. 将每个观测值分配到对应的区间中。
```python
import pandas as pd
# 示例数据
data = {'col': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]}
df = pd.DataFrame(data)
# 等宽离散化
df['col_discretized'] = pd.cut(df['col'], bins=3)
```
- **适用场景**:当数据的分布比较均匀时适用。
- **局限性**:可能会导致某些区间的观测值数量过少或过多。
### 7.2 等频离散化
- **操作步骤**:
1. 确定离散化的区间数量。
2. 根据变量的排序结果,将其划分为等数量观测值的区间。
3. 将每个观测值分配到对应的区间中。
```python
import pandas as pd
# 示例数据
data = {'col': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]}
df = pd.DataFrame(data)
# 等频离散化
df['col_discretized'] = pd.qcut(df['col'], q=3)
```
- **适用场景**:当数据的分布不均匀时适用。
- **局限性**:区间的边界可能不直观,难以解释。
### 7.3 任意区间离散化
- **操作步骤**:
1. 手动指定离散化的区间边界。
2. 将每个观测值分配到对应的区间中。
```python
import pandas as pd
# 示例数据
data = {'col': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]}
df = pd.DataFrame(data)
# 任意区间离散化
bins = [0, 3, 6, 10]
df['col_discretized'] = pd.cut(df['col'], bins=bins)
```
- **适用场景**:当根据业务需求或领域知识可以确定合适的区间边界时适用。
- **局限性**:区间边界的确定需要一定的专业知识和经验。
### 7.4 K - 均值聚类离散化
- **操作步骤**:
1. 确定聚类的簇数。
2. 使用 K - 均值聚类算法对数据进行聚类。
3. 将每个观测值所属的簇作为离散化的结果。
```python
from sklearn.cluster import KMeans
import pandas as pd
# 示例数据
data = {'col': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]}
df = pd.DataFrame(data)
# 创建 KMeans 对象
kmeans = KMeans(n_clusters=3)
# 聚类
df['col_discretized'] = kmeans.fit_predict(df[['col']])
```
- **适用场景**:可以根据数据的内在结构进行离散化。
- **局限性**:聚类结果可能受到初始聚类中心的影响,且簇数的选择需要进行试验。
### 7.5 特征二值化
- **操作步骤**:
1. 确定一个阈值。
2. 将大于阈值的观测值设为 1,小于等于阈值的观测值设为 0。
```python
from sklearn.preprocessing import Binarizer
import pandas as pd
# 示例数据
data = {'col': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]}
df = pd.DataFrame(data)
# 创建二值化器
binarizer = Binarizer(threshold=5)
# 二值化
df['col_binarized'] = binarizer.transform(df[['col']])
```
- **适用场景**:当只需要区分变量的高低水平时适用。
- **局限性**:丢失了变量的具体数值信息。
### 7.6 决策树离散化
- **操作步骤**:
1. 使用决策树算法对数据进行训练。
2. 根据决策树的划分规则,将数据进行离散化。
```python
from sklearn.tree import DecisionTreeClassifier
import pandas as pd
# 示例数据
data = {'col': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 'target': [0, 0, 0, 1, 1, 1, 1, 1, 1, 1]}
df = pd.DataFrame(data)
# 创建决策树分类器
tree = DecisionTreeClassifier(max_depth=2)
# 训练模型
tree.fit(df[['col']], df['target'])
# 离散化
df['col_discretized'] = tree.apply(df[['col']])
```
- **适用场景**:可以根据目标变量的信息进行离散化,有助于提高模型的预测性能。
- **局限性**:决策树的复杂度需要进行控制,否则可能会导致过拟合。
## 8. 异常值处理
异常值是数据集中偏离大多数观测值的数据点,以下是一些常见的异常值处理方法:
### 8.1 箱线图可视化
- **操作步骤**:
1. 使用箱线图展示数据的分布情况。
2. 根据箱线图的上下边界,识别异常值。
```python
import seaborn as sns
import pandas as pd
import matplotlib.pyplot as plt
# 示例数据
data = {'col': [1, 2, 3, 4, 5, 6, 7, 8, 9, 100]}
df = pd.DataFrame(data)
# 绘制箱线图
sns.boxplot(x=df['col'])
plt.show()
```
- **适用场景**:可以直观地观察数据的分布和异常值情况。
- **局限性**:只能提供大致的异常值判断,对于复杂的数据分布可能不准确。
### 8.2 均值和标准差检测
- **操作步骤**:
1. 计算数据的均值和标准差。
2. 确定一个阈值,通常为均值加减若干倍的标准差。
3. 将超出阈值的数据点视为异常值。
```python
import pandas as pd
import numpy as np
# 示例数据
data = {'col': [1, 2, 3, 4, 5, 6, 7, 8, 9, 100]}
df = pd.DataFrame(data)
# 计算均值和标准差
mean_value = df['col'].mean()
std_value = df['col'].std()
# 确定阈值
threshold = 3
lower_bound = mean_value - threshold * std_value
upper_bound = mean_value + threshold * std_value
# 检测异常值
outliers = df[(df['col'] < lower_bound) | (df['col'] > upper_bound)]
```
- **适用场景**:当数据服从正态分布时适用。
- **局限性**:对于非正态分布的数据,均值和标准差可能不能准确反映数据的分布特征。
### 8.3 四分位距检测
- **操作步骤**:
1. 计算数据的第一四分位数(Q1)和第三四分位数(Q3)。
2. 计算四分位距(IQR = Q3 - Q1)。
3. 确定上下边界,通常为 Q1 - 1.5 * IQR 和 Q3 + 1.5 * IQR。
4. 将超出上下边界的数据点视为异常值。
```python
import pandas as pd
import numpy as np
# 示例数据
data = {'col': [1, 2, 3, 4, 5, 6, 7, 8, 9, 100]}
df = pd.DataFrame(data)
# 计算四分位数
Q1 = df['col'].quantile(0.25)
Q3 = df['col'].quantile(0.75)
IQR = Q3 - Q1
# 确定上下边界
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
# 检测异常值
outliers = df[(df['col'] < lower_bound) | (df['col'] > upper_bound)]
```
- **适用场景**:对数据的分布没有严格要求,适用于大多数数据。
- **局限性**:上下边界的确定可能存在一定的主观性。
### 8.4 移除异常值
- **操作步骤**:
1. 识别异常值。
2. 将异常值从数据集中移除。
```python
import pandas as pd
import numpy as np
# 示例数据
data = {'col': [1, 2, 3, 4, 5, 6, 7, 8, 9, 100]}
df = pd.DataFrame(data)
# 计算四分位数
Q1 = df['col'].quantile(0.25)
Q3 = df['col'].quantile(0.75)
IQR = Q3 - Q1
# 确定上下边界
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
# 移除异常值
df = df[(df['col'] >= lower_bound) & (df['col'] <= upper_bound)]
```
- **适用场景**:当异常值是由于数据录入错误或测量误差导致时适用。
- **局限性**:可能会丢失有价值的信息,尤其是当异常值并非真正的错误时。
### 8.5 截断异常值
- **操作步骤**:
1. 确定截断的上下限。
2. 将超出上下限的数据点替换为上下限的值。
```python
import pandas as pd
import numpy as np
# 示例数据
data = {'col': [1, 2, 3, 4, 5, 6, 7, 8, 9, 100]}
df = pd.DataFrame(data)
# 确定截断上下限
lower_bound = 1
upper_bound = 10
# 截断异常值
df['col'] = df['col'].clip(lower=lower_bound, upper=upper_bound)
```
- **适用场景**:当异常值可能包含一定的信息,但又不希望其对模型产生过大影响时适用。
- **局限性**:会改变数据的分布,可能会影响模型的性能。
### 8.6 分位数截断
- **操作步骤**:
1. 确定分位数,如 5% 和 95% 分位数。
2. 将低于 5% 分位数的数据点替换为 5% 分位数的值,高于 95% 分位数的数据点替换为 95% 分位数的值。
```python
import pandas as pd
import numpy as np
# 示例数据
data = {'col': [1, 2, 3, 4, 5, 6, 7, 8, 9, 100]}
df = pd.DataFrame(data)
# 计算分位数
lower_quantile = df['col'].quantile(0.05)
upper_quantile = df['col'].quantile(0.95)
# 分位数截断
df['col'] = df['col'].clip(lower=lower_quantile, upper=upper_quantile)
```
- **适用场景**:可以根据数据的分布自动确定截断的上下限。
- **局限性**:分位数的选择可能需要根据具体情况进行调整。
## 9. 日期和时间特征提取
从日期和时间变量中提取特征可以为机器学习模型提供更多的信息,以下是一些常见的日期和时间特征提取方法:
### 9.1 使用 pandas 提取日期特征
- **操作步骤**:
1. 将日期变量转换为 pandas 的 datetime 类型。
2. 使用 pandas 的日期属性提取年、月、日等特征。
```python
import pandas as pd
# 示例数据
data = {'date': ['2023-01-01', '2023-02-01', '2023-03-01']}
df = pd.DataFrame(data)
# 转换为 datetime 类型
df['date'] = pd.to_datetime(df['date'])
# 提取年、月、日
df['year'] = df['date'].dt.year
df['month'] = df['date'].dt.month
df['day'] = df['date'].dt.day
```
- **适用场景**:可以方便地从日期变量中提取基本的时间信息。
- **局限性**:只能提取一些基本的日期特征,对于更复杂的时间关系可能无法处理。
### 9.2 使用 pandas 提取时间特征
- **操作步骤**:
1. 将时间变量转换为 pandas 的 datetime 类型。
2. 使用 pandas 的时间属性提取小时、分钟、秒等特征。
```python
import pandas as pd
# 示例数据
data = {'time': ['12:00:00', '13:30:00', '14:15:00']}
df = pd.DataFrame(data)
# 转换为 datetime 类型
df['time'] = pd.to_datetime(df['time'], format='%H:%M:%S')
# 提取小时、分钟、秒
df['hour'] = df['time'].dt.hour
df['minute'] = df['time'].dt.minute
df['second'] = df['time'].dt.second
```
- **适用场景**:可以方便地从时间变量中提取基本的时间信息。
- **局限性**:只能提取一些基本的时间特征,对于更复杂的时间关系可能无法处理。
### 9.3 计算时间间隔
- **操作步骤**:
1. 将两个日期或时间变量转换为 pandas 的 datetime 类型。
2. 计算两个变量之间的时间间隔。
```python
import pandas as pd
# 示例数据
data = {'start_date': ['2023-01-01', '2023-02-01'], 'end_date': ['2023-01-10', '2023-02-15']}
df = pd.DataFrame(data)
# 转换为 datetime 类型
df['start_date'] = pd.to_datetime(df['start_date'])
df['end_date'] = pd.to_datetime(df['end_date'])
# 计算时间间隔
df['time_interval'] = df['end_date'] - df['start_date']
```
- **适用场景**:可以分析事件的持续时间等信息。
- **局限性**:时间间隔的表示可能需要进一步处理,以适应模型的输入要求。
### 9.4 处理不同时区的时间
- **操作步骤**:
1. 将时间变量转换为 pandas 的 datetime 类型,并指定时区。
2. 使用 pandas 的时区转换方法进行时区转换。
```python
import pandas as pd
# 示例数据
data = {'time': ['2023-01-01 12:00:00']}
df = pd.DataFrame(data)
# 转换为 datetime 类型并指定时区
df['time'] = pd.to_datetime(df['time']).dt.tz_localize('UTC')
# 时区转换
df['time_pst'] = df['time'].dt.tz_convert('US/Pacific')
```
- **适用场景**:当数据涉及不同时区的时间时适用。
- **局限性**:时区的指定和转换需要准确,否则可能会导致时间信息错误。
### 9.5 使用 Feature - engine 自动提取特征
- **操作步骤**:
1. 安装 Feature - engine 库。
2. 使用 Feature - engine 中的日期和时间特征提取器自动提取特征。
```python
from feature_engine.datetime import DatetimeFeatures
import pandas as pd
# 示例数据
data = {'date': ['2023-01-01', '2023-02-01', '2023-03-01']}
df = pd.DataFrame(data)
# 创建日期特征提取器
datetime_features = DatetimeFeatures(variables=['date'], features_to_extract=['year', 'month', 'day'])
# 提取特征
df = datetime_features.fit_transform(df)
```
- **适用场景**:可以自动提取多种日期和时间特征,提高特征工程的效率。
- **局限性**:可能会提取出一些不必要的特征,需要进行特征选择。
## 10. 特征缩放
特征缩放可以使不同特征在相同的尺度上,有助于提高机器学习模型的性能。以下是一些常见的特征缩放方法:
### 10.1 标准化
- **操作步骤**:
1. 计算特征的均值和标准差。
2. 将特征值减去均值,再除以标准差。
```python
from sklearn.preprocessing import StandardScaler
import pandas as pd
# 示例数据
data = {'col': [1, 2, 3, 4, 5]}
df = pd.DataFrame(data)
# 创建标准化器
scaler = StandardScaler()
# 标准化
df['col_scaled'] = scaler.fit_transform(df[['col']])
```
- **适用场景**:当特征的分布接近正态分布时适用。
- **局限性**:对异常值比较敏感,异常值可能会影响标准化的结果。
### 10.2 最大最小缩放
- **操作步骤**:
1. 计算特征的最大值和最小值。
2. 将特征值减去最小值,再除以最大值与最小值的差。
```python
from sklearn.preprocessing import MinMaxScaler
import pandas as pd
# 示例数据
data = {'col': [1, 2, 3, 4, 5]}
df = pd.DataFrame(data)
# 创建最大最小缩放器
scaler = MinMaxScaler()
# 缩放
df['col_scaled'] = scaler.fit_transform(df[['col']])
```
- **适用场景**:可以将特征值缩放到 [0, 1] 区间,适用于需要将特征值限制在一定范围内的情况。
- **局限性**:同样对异常值比较敏感。
### 10.3 中位数和分位数缩放
- **操作步骤**:
1. 计算特征的中位数和四分位数。
2. 根据中位数和四分位数对特征值进行缩放。
```python
from sklearn.preprocessing import RobustScaler
import pandas as pd
# 示例数据
data = {'col': [1, 2, 3, 4, 5]}
df = pd.DataFrame(data)
# 创建中位数和分位数缩放器
scaler = RobustScaler()
# 缩放
df['col_scaled'] = scaler.fit_transform(df[['col']])
```
- **适用场景**:对异常值具有较强的鲁棒性,适用于数据存在异常值的情况。
- **局限性**:缩放后的特征值范围可能不固定。
### 10.4 均值归一化
- **操作步骤**:
1. 计算特征的均值和最大值与最小值的差。
2. 将特征值减去均值,再除以最大值与最小值的差。
```python
import pandas as pd
import numpy as np
# 示例数据
data = {'col': [1, 2, 3, 4, 5]}
df = pd.DataFrame(data)
# 计算均值
mean_value = df['col'].mean()
# 计算最大值与最小值的差
range_value = df['col'].max() - df['col'].min()
# 均值归一化
df['col_scaled'] = (df['col'] - mean_value) / range_value
```
- **适用场景**:可以使特征值的均值为 0,范围在 [-1, 1] 之间。
- **局限性**:对异常值比较敏感。
### 10.5 最大绝对值缩放
- **操作步骤**:
1. 计算特征的最大绝对值。
2. 将特征值除以最大绝对值。
```python
from sklearn.preprocessing import MaxAbsScaler
import pandas as pd
# 示例数据
data = {'col': [1, 2, 3, 4, 5]}
df = pd.DataFrame(data)
# 创建最大绝对值缩放器
scaler = MaxAbsScaler()
# 缩放
df['col_scaled'] = scaler.fit_transform(df[['col']])
```
- **适用场景**:不会改变数据的符号,适用于稀疏数据。
- **局限性**:对异常值比较敏感。
### 10.6 向量单位长度缩放
- **操作步骤**:
1. 计算特征向量的长度。
2. 将特征向量除以其长度。
```python
from sklearn.preprocessing import Normalizer
import pandas as pd
# 示例数据
data = {'col': [1, 2, 3, 4, 5]}
df = pd.DataFrame(data)
# 创建向量单位长度缩放器
scaler = Normalizer()
# 缩放
df['col_scaled'] = scaler.fit_transform(df[['col']])
```
- **适用场景**:可以将特征向量缩放到单位长度,适用于需要考虑向量方向的情况。
- **局限性**:缩放后的特征值不再具有原始的数值意义。
## 11. 新特征创建
创建新特征可以为机器学习模型提供更多的信息,以下是一些常见的新特征创建方法:
### 11.1 数学函数组合
- **操作步骤**:
1. 选择合适的数学函数,如加法、乘法等。
2. 对原始特征进行组合运算,创建新特征。
```python
import pandas as pd
# 示例数据
data = {'col1': [1, 2, 3, 4, 5], 'col2': [6, 7, 8, 9, 10]}
df = pd.DataFrame(data)
# 创建新特征
df['new_col'] = df['col1'] + df['col2']
```
- **适用场景**:可以根据业务知识或数据特点,通过简单的数学运算创建新特征。
- **局限性**:需要对数据有一定的了解,才能选择合适的数学函数。
### 11.2 与参考变量比较
- **操作步骤**:
1. 选择一个参考变量。
2. 将原始特征与参考变量进行比较,创建新的二进制特征。
```python
import pandas as pd
# 示例数据
data = {'col': [1, 2, 3, 4, 5], 'reference': [3, 3, 3, 3, 3]}
df = pd.DataFrame(data)
# 创建新特征
df['new_col'] = (df['col'] > df['reference']).astype(int)
```
- **适用场景**:可以突出特征与参考变量之间的关系。
- **局限性**:创建的新特征是二进制的,可能会丢失一些信息。
### 11.3 多项式展开
- **操作步骤**:
1. 选择多项式的阶数。
2. 使用多项式展开方法,将原始特征进行展开,创建新特征。
```python
from sklearn.preprocessing import PolynomialFeatures
import pandas as pd
# 示例数据
data = {'col': [1, 2, 3, 4, 5]}
df = pd.DataFrame(data)
# 创建多项式特征生成器
poly = PolynomialFeatures(degree=2)
# 生成多项式特征
poly_features = poly.fit_transform(df[['col']])
# 将多项式特征转换为 DataFrame
poly_df = pd.DataFrame(poly_features, columns=poly.get_feature_names_out(['col']))
# 合并特征
df = pd.concat([df, poly_df], axis=1)
```
- **适用场景**:可以捕捉特征之间的非线性关系。
- **局限性**:会增加特征的维度,可能会导致过拟合。
### 11.4 决策树组合
- **操作步骤**:
1. 使用决策树算法对数据进行训练。
2. 根据决策树的划分规则,创建新的特征。
```python
from sklearn.tree import DecisionTreeClassifier
import pandas as pd
# 示例数据
data = {'col1': [1, 2, 3, 4, 5], 'col2': [6, 7, 8, 9, 10], 'target': [0, 0, 1, 1, 1]}
df = pd.DataFrame(data)
# 创建决策树分类器
tree = DecisionTreeClassifier(max_depth=2)
# 训练模型
tree.fit(df[['col1', 'col2']], df['target'])
# 创建新特征
df['new_col'] = tree.apply(df[['col1', 'col2']])
```
- **适用场景**:可以根据目标变量的信息,自动创建有意义的新特征。
- **局限性**:决策树的复杂度需要进行控制,否则可能会导致过拟合。
### 11.5 周期性特征创建
- **操作步骤**:
1. 确定周期性变量,如时间变量。
2. 使用三角函数(如正弦和余弦)将周期性变量转换为新的特征。
```python
import pandas as pd
import numpy as np
# 示例数据
data = {'time': [0, 1, 2, 3, 4]}
df = pd.DataFrame(data)
# 周期性特征创建
df['sin_time'] = np.sin(2 * np.pi * df['time'] / 5)
df['cos_time'] = np.cos(2 * np.pi * df['time'] / 5)
```
- **适用场景**:可以捕捉周期性变量的周期性变化。
- **局限性**:需要对周期性有准确的认识,否则可能无法正确反映周期性变化。
### 11.6 样条特征创建
- **操作步骤**:
1. 选择样条函数的类型和节点。
2. 使用样条函数对原始特征进行转换,创建新特征。
```python
from sklearn.preprocessing import SplineTransformer
import pandas as pd
# 示例数据
data = {'col': [1, 2, 3, 4, 5]}
df = pd.DataFrame(data)
# 创建样条特征生成器
spline = SplineTransformer(n_knots=3, degree=2)
# 生成样条特征
spline_features = spline.fit_transform(df[['col']])
# 将样条特征转换为 DataFrame
spline_df = pd.DataFrame(spline_features, columns=spline.get_feature_names_out(['col']))
# 合并特征
df = pd.concat([df, spline_df], axis=1)
```
- **适用场景**:可以拟合复杂的非线性关系。
- **局限性**:样条函数的选择和节点的确定可能需要进行试验。
## 12. 关系型数据特征提取
使用 Featuretools 可以从关系型数据中自动提取特征,以下是一些常见的操作:
### 12.1 实体集设置和自动特征创建
- **操作步骤**:
1. 安装 Featuretools 库。
2. 定义实体集和实体之间的关系。
3. 使用 Featuretools 的自动特征生成功能创建特征。
```python
import featuretools as ft
import pandas as pd
# 示例数据
customers = pd.DataFrame({
'customer_id': [1, 2, 3],
'name': ['Alice', 'Bob', 'Charlie']
})
transactions = pd.DataFrame({
'transaction_id': [101, 102, 103, 104],
'customer_id': [1, 2, 1, 3],
'amount': [100, 200, 150, 300]
})
# 创建实体集
es = ft.EntitySet(id='customers')
# 添加实体
es = es.add_dataframe(dataframe_name='customers', dataframe=customers, index='customer_id')
es = es.add_dataframe(dataframe_name='transactions', dataframe=transactions, index='transaction_id')
# 添加关系
relationship = ft.Relationship(es['customers']['customer_id'], es['transactions']['customer_id'])
es = es.add_relationship(relationship)
# 自动生成特征
features, feature_names = ft.dfs(entityset=es, target_dataframe_name='customers')
```
- **适用场景**:可以自动从关系型数据中挖掘出有价值的特征,提高特征工程的效率。
- **局限性**:生成的特征数量可能较多,需要进行特征选择。
### 12.2 通用和累积操作特征创建
- **操作步骤**:
1. 定义通用和累积操作,如求和、计数等。
2. 使用 Featuretools 的聚合和转换操作创建特征。
```python
import featuretools as ft
import pandas as pd
# 示例数据
customers = pd.DataFrame({
'customer_id': [1, 2, 3],
'name': ['Alice', 'Bob', 'Charlie']
})
transactions = pd.DataFrame({
'transaction_id': [101, 102, 103, 104],
'customer_id': [1, 2, 1, 3],
'amount': [100, 200, 150, 300]
})
# 创建实体集
es = ft.EntitySet(id='customers')
# 添加实体
es = es.add_dataframe(dataframe_name='customers', dataframe=customers, index='customer_id')
es = es.add_dataframe(dataframe_name='transactions', dataframe=transactions, index='transaction_id')
# 添加关系
relationship = ft.Relationship(es['customers']['customer_id'], es['transactions']['customer_id'])
es = es.add_relationship(relationship)
# 定义聚合和转换操作
agg_primitives = ['sum', 'count']
trans_primitives = ['month']
# 生成特征
features, feature_names = ft.dfs(entityset=es, target_dataframe_name='customers',
agg_primitives=agg_primitives, trans_primitives=trans_primitives)
```
- **适用场景**:可以根据业务需求,自定义特征的创建方式。
- **局限性**:需要对 Featuretools 的操作有一定的了解,才能选择合适的操作。
### 12.3 数值特征组合
- **操作步骤**:
1. 选择需要组合的数值特征。
2. 使用 Featuretools 的转换操作对数值特征进行组合。
```python
import featuretools as ft
import pandas as pd
# 示例数据
data = pd.DataFrame({
'col1': [1, 2, 3, 4, 5],
'col2': [6, 7, 8, 9, 10]
})
# 创建实体集
es = ft.EntitySet(id='data')
# 添加实体
es = es.add_dataframe(dataframe_name='data', dataframe=data, index='index')
# 定义转换操作
trans_primitives = ['add_numeric']
# 生成特征
features, feature_names = ft.dfs(entityset=es, target_dataframe_name='data',
## 12. 关系型数据特征提取(续)
### 12.3 数值特征组合(续)
```python
import featuretools as ft
import pandas as pd
# 示例数据
data = pd.DataFrame({
'col1': [1, 2, 3, 4, 5],
'col2': [6, 7, 8, 9, 10]
})
# 创建实体集
es = ft.EntitySet(id='data')
# 添加实体
es = es.add_dataframe(dataframe_name='data', dataframe=data, index='index')
# 定义转换操作
trans_primitives = ['add_numeric']
# 生成特征
features, feature_names = ft.dfs(entityset=es, target_dataframe_name='data',
trans_primitives=trans_primitives)
```
- **适用场景**:能够将多个数值特征进行组合,挖掘特征之间的潜在关系,为模型提供更丰富的信息。
- **局限性**:组合后的特征可能会增加数据的维度,需要进行合理的特征选择,避免维度灾难。
### 12.4 日期和时间特征提取
- **操作步骤**:
1. 确保数据集中包含日期和时间类型的变量。
2. 使用 Featuretools 的日期和时间相关操作提取特征。
```python
import featuretools as ft
import pandas as pd
# 示例数据
data = pd.DataFrame({
'date': ['2023-01-01', '2023-02-01', '2023-03-01'],
'value': [10, 20, 30]
})
# 将日期列转换为 datetime 类型
data['date'] = pd.to_datetime(data['date'])
# 创建实体集
es = ft.EntitySet(id='data')
# 添加实体
es = es.add_dataframe(dataframe_name='data', dataframe=data, index='index')
# 定义转换操作
trans_primitives = ['month', 'year']
# 生成特征
features, feature_names = ft.dfs(entityset=es, target_dataframe_name='data',
trans_primitives=trans_primitives)
```
- **适用场景**:可以从日期和时间变量中提取有价值的信息,如月份、年份等,有助于模型捕捉时间相关的模式。
- **局限性**:提取的特征可能存在冗余,需要进行筛选,并且对于复杂的时间序列分析,可能需要更高级的方法。
### 12.5 文本特征提取
- **操作步骤**:
1. 准备包含文本数据的数据集。
2. 使用 Featuretools 的文本相关操作提取特征。
```python
import featuretools as ft
import pandas as pd
# 示例数据
data = pd.DataFrame({
'text': ['This is a sample text', 'Another text for example', 'One more text here']
})
# 创建实体集
es = ft.EntitySet(id='data')
# 添加实体
es = es.add_dataframe(dataframe_name='data', dataframe=data, index='index')
# 定义转换操作
trans_primitives = ['num_words']
# 生成特征
features, feature_names = ft.dfs(entityset=es, target_dataframe_name='data',
trans_primitives=trans_primitives)
```
- **适用场景**:可以从文本数据中提取一些基本的特征,如单词数量等,为文本分析提供基础信息。
- **局限性**:对于复杂的文本语义理解和特征提取能力有限,可能需要结合自然语言处理的其他技术。
### 12.6 聚合原语特征创建
- **操作步骤**:
1. 确定需要进行聚合操作的数据集和目标变量。
2. 选择合适的聚合原语,如求和、均值等。
3. 使用 Featuretools 进行聚合操作,创建特征。
```python
import featuretools as ft
import pandas as pd
# 示例数据
customers = pd.DataFrame({
'customer_id': [1, 2, 3],
'name': ['Alice', 'Bob', 'Charlie']
})
transactions = pd.DataFrame({
'transaction_id': [101, 102, 103, 104],
'customer_id': [1, 2, 1, 3],
'amount': [100, 200, 150, 300]
})
# 创建实体集
es = ft.EntitySet(id='customers')
# 添加实体
es = es.add_dataframe(dataframe_name='customers', dataframe=customers, index='customer_id')
es = es.add_dataframe(dataframe_name='transactions', dataframe=transactions, index='transaction_id')
# 添加关系
relationship = ft.Relationship(es['customers']['customer_id'], es['transactions']['customer_id'])
es = es.add_relationship(relationship)
# 定义聚合原语
agg_primitives = ['sum', 'mean']
# 生成特征
features, feature_names = ft.dfs(entityset=es, target_dataframe_name='customers',
agg_primitives=agg_primitives)
```
- **适用场景**:可以对关系型数据进行聚合操作,从不同的角度总结数据,为模型提供更宏观的信息。
- **局限性**:聚合操作可能会丢失一些细节信息,并且需要根据具体问题选择合适的聚合原语。
## 13. 时间序列特征提取
### 13.1 自动特征提取
- **操作步骤**:
1. 安装 tsfresh 库。
2. 准备时间序列数据集。
3. 使用 tsfresh 的自动特征提取功能。
```python
from tsfresh import extract_features
import pandas as pd
# 示例时间序列数据
data = pd.DataFrame({
'id': [1, 1, 1, 2, 2, 2],
'time': [1, 2, 3, 1, 2, 3],
'value': [10, 20, 30, 40, 50, 60]
})
# 提取特征
extracted_features = extract_features(data, column_id='id', column_sort='time')
```
- **适用场景**:可以快速从时间序列数据中提取大量的特征,节省人工特征工程的时间。
- **局限性**:提取的特征数量可能非常多,存在特征冗余,需要进行特征选择。
### 13.2 特征创建与选择
- **操作步骤**:
1. 确定时间序列数据集和目标变量。
2. 使用 tsfresh 进行特征创建。
3. 根据目标变量,使用 tsfresh 的特征选择功能筛选出有意义的特征。
```python
from tsfresh import extract_features, select_features
import pandas as pd
# 示例时间序列数据
data = pd.DataFrame({
'id': [1, 1, 1, 2, 2, 2],
'time': [1, 2, 3, 1, 2, 3],
'value': [10, 20, 30, 40, 50, 60]
})
target = pd.Series([0, 1])
# 提取特征
extracted_features = extract_features(data, column_id='id', column_sort='time')
# 选择特征
selected_features = select_features(extracted_features, target)
```
- **适用场景**:在自动提取特征的基础上,能够筛选出与目标变量相关的特征,提高模型的效率和性能。
- **局限性**:特征选择的效果依赖于目标变量的质量和特征提取的准确性。
### 13.3 不同时间序列特征定制
- **操作步骤**:
1. 针对不同类型的时间序列,分析其特点。
2. 根据时间序列的特点,选择合适的特征提取方法和参数。
3. 使用 tsfresh 进行定制化的特征提取。
```python
from tsfresh import extract_features
import pandas as pd
# 示例不同类型的时间序列数据
data1 = pd.DataFrame({
'id': [1, 1, 1],
'time': [1, 2, 3],
'value': [10, 20, 30]
})
data2 = pd.DataFrame({
'id': [2, 2, 2],
'time': [1, 2, 3],
'value': [40, 50, 60]
})
# 定制特征提取参数
extraction_settings = {
'feature_extraction': {
'length': None,
'mean': None
}
}
# 提取特征
features1 = extract_features(data1, column_id='id', column_sort='time', default_fc_parameters=extraction_settings)
features2 = extract_features(data2, column_id='id', column_sort='time', default_fc_parameters=extraction_settings)
```
- **适用场景**:可以根据不同时间序列的特性,定制特征提取过程,提高特征的针对性和有效性。
- **局限性**:需要对时间序列有深入的了解,才能准确地选择特征提取方法和参数。
### 13.4 预选择特征创建
- **操作步骤**:
1. 确定需要提取的预选择特征列表。
2. 使用 tsfresh 的预选择特征提取功能。
```python
from tsfresh import extract_features
import pandas as pd
# 示例时间序列数据
data = pd.DataFrame({
'id': [1, 1, 1],
'time': [1, 2, 3],
'value': [10, 20, 30]
})
# 预选择特征列表
pre_selected_features = {
'length': None,
'mean': None
}
# 提取预选择特征
extracted_features = extract_features(data, column_id='id', column_sort='time', default_fc_parameters=pre_selected_features)
```
- **适用场景**:当已知某些特征对模型有重要意义时,可以直接提取这些预选择特征,提高效率。
- **局限性**:如果预选择特征列表不准确,可能会遗漏一些重要的特征。
### 13.5 嵌入特征创建到 scikit - learn 管道
- **操作步骤**:
1. 准备时间序列数据集和目标变量。
2. 创建 scikit - learn 管道。
3. 将 tsfresh 的特征提取器嵌入到管道中。
```python
from tsfresh.utilities.dataframe_functions import impute
from tsfresh import extract_features, select_features
from sklearn.pipeline import Pipeline
from sklearn.ensemble import RandomForestClassifier
import pandas as pd
# 示例时间序列数据
data = pd.DataFrame({
'id': [1, 1, 1, 2, 2, 2],
'time': [1, 2, 3, 1, 2, 3],
'value': [10, 20, 30, 40, 50, 60]
})
target = pd.Series([0, 1])
# 创建管道
pipeline = Pipeline([
('feature_extraction', extract_features(data, column_id='id', column_sort='time')),
('feature_selection', select_features(extracted_features, target)),
('classification', RandomForestClassifier())
])
# 训练模型
pipeline.fit(data, target)
```
- **适用场景**:可以将特征提取、特征选择和模型训练集成到一个管道中,简化机器学习流程。
- **局限性**:管道的配置需要根据具体问题进行调整,否则可能会影响模型的性能。
## 14. 文本变量特征提取
### 14.1 字符、单词和词汇计数
- **操作步骤**:
1. 准备文本数据集。
2. 使用 Python 的字符串操作或相关库进行字符、单词和词汇的计数。
```python
import pandas as pd
# 示例文本数据
data = pd.DataFrame({
'text': ['This is a sample text', 'Another text for example']
})
# 字符计数
data['char_count'] = data['text'].str.len()
# 单词计数
data['word_count'] = data['text'].str.split().str.len()
# 词汇计数
vocabulary = set()
for text in data['text']:
words = text.split()
for word in words:
vocabulary.add(word)
data['vocab_count'] = len(vocabulary)
```
- **适用场景**:可以从文本数据中获取一些基本的统计信息,了解文本的长度和丰富度。
- **局限性**:这些计数信息比较简单,不能反映文本的语义和情感等深层次信息。
### 14.2 句子计数估计文本复杂度
- **操作步骤**:
1. 准备文本数据集。
2. 使用正则表达式或相关库进行句子的分割和计数。
```python
import pandas as pd
import re
# 示例文本数据
data = pd.DataFrame({
'text': ['This is a sentence. Another sentence here.', 'One more sentence for example.']
})
# 句子计数
data['sentence_count'] = data['text'].apply(lambda x: len(re.split(r'[.!?]+', x)))
```
- **适用场景**:可以通过句子的数量来估计文本的复杂度,对于文本分析有一定的参考价值。
- **局限性**:句子的分割可能不准确,尤其是对于一些复杂的文本结构。
### 14.3 词袋和 n - 元语法特征创建
- **操作步骤**:
1. 准备文本数据集。
2. 使用 scikit - learn 的 CountVectorizer 进行词袋和 n - 元语法特征的创建。
```python
from sklearn.feature_extraction.text import CountVectorizer
import pandas as pd
# 示例文本数据
data = pd.DataFrame({
'text': ['This is a sample text', 'Another text for example']
})
# 创建 CountVectorizer 对象
vectorizer = CountVectorizer(ngram_range=(1, 2))
# 拟合和转换数据
X = vectorizer.fit_transform(data['text'])
# 将结果转换为 DataFrame
feature_names = vectorizer.get_feature_names_out()
df = pd.DataFrame(X.toarray(), columns=feature_names)
```
- **适用场景**:可以将文本数据转换为数值特征矩阵,适用于文本分类、聚类等机器学习任务。
- **局限性**:词袋模型忽略了单词的顺序和语义信息,n - 元语法也有一定的局限性。
### 14.4 词频 - 逆文档频率(TF - IDF)
- **操作步骤**:
1. 准备文本数据集。
2. 使用 scikit - learn 的 TfidfVectorizer 进行 TF - IDF 特征的计算。
```python
from sklearn.feature_extraction.text import TfidfVectorizer
import pandas as pd
# 示例文本数据
data = pd.DataFrame({
'text': ['This is a sample text', 'Another text for example']
})
# 创建 TfidfVectorizer 对象
vectorizer = TfidfVectorizer()
# 拟合和转换数据
X = vectorizer.fit_transform(data['text'])
# 将结果转换为 DataFrame
feature_names = vectorizer.get_feature_names_out()
df = pd.DataFrame(X.toarray(), columns=feature_names)
```
- **适用场景**:TF - IDF 可以衡量一个单词在文本中的重要性,适用于文本信息检索和文本挖掘等任务。
- **局限性**:TF - IDF 仍然没有考虑单词的语义和上下文信息。
### 14.5 文本清洗和词干提取
- **操作步骤**:
1. 准备文本数据集。
2. 进行文本清洗,如去除标点符号、转换为小写等。
3. 使用词干提取器进行词干提取。
```python
import pandas as pd
import re
from nltk.stem import PorterStemmer
# 示例文本数据
data = pd.DataFrame({
'text': ['This is a sample text!', 'Another text for example.']
})
# 文本清洗
data['clean_text'] = data['text'].apply(lambda x: re.sub(r'[^\w\s]', '', x).lower())
# 词干提取
stemmer = PorterStemmer()
data['stemmed_text'] = data['clean_text'].apply(lambda x: ' '.join([stemmer.stem(word) for word in x.split()]))
```
- **适用场景**:文本清洗和词干提取可以减少文本数据的噪声,提高文本分析的准确性。
- **局限性**:词干提取可能会导致一些信息的丢失,并且不同的词干提取器效果可能不同。
## 总结
特征工程是机器学习中至关重要的环节,它涵盖了从数据预处理到特征创建和提取的多个方面。通过对缺失数据的处理、分类变量的编码、数值变量的转换、变量的离散化、异常值的处理、日期和时间特征的提取、特征的缩放、新特征的创建、关系型数据和时间序列数据的特征提取以及文本变量的特征提取等一系列操作,可以为机器学习模型提供更优质的输入数据,从而提高模型的性能。在实际应用中,需要根据具体的数据特点和问题需求,选择合适的特征工程方法,并进行合理的特征选择和模型调优。
以下是一个简单的特征工程流程 mermaid 流程图:
```mermaid
graph LR
A[数据收集] --> B[数据预处理]
B --> C{数据类型}
C -->|数值型| D[数值变量转换]
C -->|分类型| E[分类变量编码]
C -->|日期时间型| F[日期和时间特征提取]
C -->|时间序列型| G[时间序列特征提取]
C -->|文本型| H[文本变量特征提取]
D --> I[特征缩放]
E --> I
F --> I
G --> I
H --> I
I --> J[新特征创建]
J --> K[特征选择]
K --> L[模型训练]
L --> M[模型评估]
M -->|不满意| B
M -->|满意| N[模型部署]
```
这个流程图展示了从数据收集到模型部署的整个特征工程流程,其中包含了多个关键步骤,并且在模型评估不满意时可以进行迭代优化。
同时,为了更清晰地对比不同特征工程方法的特点,以下是一个简单的表格:
| 特征工程方法 | 适用场景 | 局限性 |
| --- | --- | --- |
| 移除含缺失数据的观测值 | 缺失数据占比较小 | 可能丢失有价值信息 |
| 均值或中位数填充 | 数据分布对称或有异常值 | 改变数据分布,低估方差 |
| 独热编码 | 类别数量较少 | 增加数据维度,可能导致维度灾难 |
| 对数转换 | 数据右偏且为正数 | 不能处理零值和负值 |
| 等宽离散化 | 数据分布均匀 | 区间观测值数量可能不均衡 |
| 标准化 | 特征分布接近正态 | 对异常值敏感 |
| 自动特征提取(Featuretools) | 关系型数据 | 生成特征多,需特征选择 |
| 自动特征提取(tsfresh) | 时间序列数据 | 特征冗余,需筛选 |
| 词袋模型 | 文本分类等任务 | 忽略单词顺序和语义 |
通过这个表格,可以更直观地了解不同特征工程方法的适用范围和局限性,在实际应用中做出更合理的选择。
0
0
复制全文
相关推荐










