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) | 时间序列数据 | 特征冗余,需筛选 | | 词袋模型 | 文本分类等任务 | 忽略单词顺序和语义 | 通过这个表格,可以更直观地了解不同特征工程方法的适用范围和局限性,在实际应用中做出更合理的选择。
corwn 最低0.47元/天 解锁专栏
买1年送3月
点击查看下一篇
profit 400次 会员资源下载次数
profit 300万+ 优质博客文章
profit 1000万+ 优质下载资源
profit 1000万+ 优质文库回答
复制全文

相关推荐

张_伟_杰

人工智能专家
人工智能和大数据领域有超过10年的工作经验,拥有深厚的技术功底,曾先后就职于多家知名科技公司。职业生涯中,曾担任人工智能工程师和数据科学家,负责开发和优化各种人工智能和大数据应用。在人工智能算法和技术,包括机器学习、深度学习、自然语言处理等领域有一定的研究
最低0.47元/天 解锁专栏
买1年送3月
百万级 高质量VIP文章无限畅学
千万级 优质资源任意下载
千万级 优质文库回答免费看

最新推荐

容器部署与管理实战指南

# 容器部署与管理实战指南 ## 1. 容器部署指导练习 ### 1.1 练习目标 在本次练习中,我们将使用容器管理工具来构建镜像、运行容器并查询正在运行的容器环境。具体目标如下: - 配置容器镜像注册表,并从现有镜像创建容器。 - 使用容器文件创建容器。 - 将脚本从主机复制到容器中并运行脚本。 - 删除容器和镜像。 ### 1.2 准备工作 作为工作站机器上的学生用户,使用 `lab` 命令为本次练习准备系统: ```bash [student@workstation ~]$ lab start containers-deploy ``` 此命令将准备环境并确保所有所需资源可用。 #

基于属性测试的深入解析与策略探讨

### 基于属性测试的深入解析与策略探讨 #### 1. 基于属性测试中的收缩机制 在基于属性的测试中,当测试失败时,像 `stream_data` 这样的框架会执行收缩(Shrinking)操作。收缩的目的是简化导致测试失败的输入,同时确保简化后的输入仍然会使测试失败,这样能更方便地定位问题。 为了说明这一点,我们来看一个简单的排序函数测试示例。我们实现了一个糟糕的排序函数,实际上就是恒等函数,它只是原封不动地返回输入列表: ```elixir defmodule BadSortTest do use ExUnit.Case use ExUnitProperties pro

开源安全工具:Vuls与CrowdSec的深入剖析

### 开源安全工具:Vuls与CrowdSec的深入剖析 #### 1. Vuls项目简介 Vuls是一个开源安全项目,具备漏洞扫描能力。通过查看代码并在本地机器上执行扫描操作,能深入了解其工作原理。在学习Vuls的过程中,还能接触到端口扫描、从Go执行外部命令行应用程序以及使用SQLite执行数据库操作等知识。 #### 2. CrowdSec项目概述 CrowdSec是一款开源安全工具(https://github.com/crowdsecurity/crowdsec ),值得研究的原因如下: - 利用众包数据收集全球IP信息,并与社区共享。 - 提供了值得学习的代码设计。 - Ge

信息系统集成与测试实战

### 信息系统集成与测试实战 #### 信息系统缓存与集成 在实际的信息系统开发中,性能优化是至关重要的一环。通过使用 `:timer.tc` 函数,我们可以精确测量执行时间,从而直观地看到缓存机制带来的显著性能提升。例如: ```elixir iex> :timer.tc(InfoSys, :compute, ["how old is the universe?"]) {53, [ %InfoSys.Result{ backend: InfoSys.Wolfram, score: 95, text: "1.4×10^10 a (Julian years)\n(time elapsed s

实时资源管理:Elixir中的CPU与内存优化

### 实时资源管理:Elixir 中的 CPU 与内存优化 在应用程序的运行过程中,CPU 和内存是两个至关重要的系统资源。合理管理这些资源,对于应用程序的性能和可扩展性至关重要。本文将深入探讨 Elixir 语言中如何管理实时资源,包括 CPU 调度和内存管理。 #### 1. Elixir 调度器的工作原理 在 Elixir 中,调度器负责将工作分配给 CPU 执行。理解调度器的工作原理,有助于我们更好地利用系统资源。 ##### 1.1 调度器设计 - **调度器(Scheduler)**:选择一个进程并执行该进程的代码。 - **运行队列(Run Queue)**:包含待执行工

构建交互式番茄钟应用的界面与功能

### 构建交互式番茄钟应用的界面与功能 #### 界面布局组织 当我们拥有了界面所需的所有小部件后,就需要对它们进行逻辑组织和布局,以构建用户界面。在相关开发中,我们使用 `container.Container` 类型的容器来定义仪表盘布局,启动应用程序至少需要一个容器,也可以使用多个容器来分割屏幕和组织小部件。 创建容器有两种方式: - 使用 `container` 包分割容器,形成二叉树布局。 - 使用 `grid` 包定义行和列的网格。可在相关文档中找到更多关于 `Container API` 的信息。 对于本次开发的应用,我们将使用网格方法来组织布局,因为这样更易于编写代码以

RHEL9系统存储、交换空间管理与进程监控指南

# RHEL 9 系统存储、交换空间管理与进程监控指南 ## 1. LVM 存储管理 ### 1.1 查看物理卷信息 通过 `pvdisplay` 命令可以查看物理卷的详细信息,示例如下: ```bash # pvdisplay --- Physical volume --- PV Name /dev/sda2 VG Name rhel PV Size <297.09 GiB / not usable 4.00 MiB Allocatable yes (but full) PE Size 4.00 MiB Total PE 76054 Free PE 0 Allocated PE 76054

轻量级HTTP服务器与容器化部署实践

### 轻量级 HTTP 服务器与容器化部署实践 #### 1. 小需求下的 HTTP 服务器选择 在某些场景中,我们不需要像 Apache 或 NGINX 这样的完整 Web 服务器,仅需一个小型 HTTP 服务器来测试功能,比如在工作站、容器或仅临时需要 Web 服务的服务器上。Python 和 PHP CLI 提供了便捷的选择。 ##### 1.1 Python 3 http.server 大多数现代 Linux 系统都预装了 Python 3,它自带 HTTP 服务。若未安装,可使用包管理器进行安装: ```bash $ sudo apt install python3 ``` 以

Ansible高级技术与最佳实践

### Ansible高级技术与最佳实践 #### 1. Ansible回调插件的使用 Ansible提供了多个回调插件,可在响应事件时为Ansible添加新行为。其中,timer插件是最有用的回调插件之一,它能测量Ansible剧本中任务和角色的执行时间。我们可以通过在`ansible.cfg`文件中对这些插件进行白名单设置来启用此功能: - **Timer**:提供剧本执行时间的摘要。 - **Profile_tasks**:提供剧本中每个任务执行时间的摘要。 - **Profile_roles**:提供剧本中每个角色执行时间的摘要。 我们可以使用`--list-tasks`选项列出剧

PowerShell7在Linux、macOS和树莓派上的应用指南

### PowerShell 7 在 Linux、macOS 和树莓派上的应用指南 #### 1. PowerShell 7 在 Windows 上支持 OpenSSH 的配置 在 Windows 上使用非微软开源软件(如 OpenSSH)时,可能会遇到路径问题。OpenSSH 不识别包含空格的路径,即使路径被单引号或双引号括起来也不行,因此需要使用 8.3 格式(旧版微软操作系统使用的短文件名格式)。但有些 OpenSSH 版本也不支持这种格式,当在 `sshd_config` 文件中添加 PowerShell 子系统时,`sshd` 服务可能无法启动。 解决方法是将另一个 PowerS