特征工程9大方法
特征工程是机器学习和数据分析中至关重要的一步,它涉及对原始数据进行转换、提取和选择,以便更好地表示数据并改善机器学习算法的性能。特征工程的目标是将原始数据转化为机器学习算法可以理解和处理的形式,同时最大程度地保留有关数据的有用信息。通过精心设计的特征工程流程,我们可以提取数据中蕴含的关键信息,能够更好地描述数据、发现数据的潜在模式,并构建出更准确、稳健的机器学习模型。🚀🚀🚀
大家好,给大家介绍一下特征工程的方法🌟
特征工程是机器学习和数据分析中不可或缺的环节。它能够提高模型性能、降低过拟合风险、处理数据质量问题,同时改善数据表示和计算效率。正确应用特征工程可以使机器学习模型更加准确。
以下是特征几个方面的重要性:
-
提高模型性能:良好的特征工程可以显著提高机器学习模型的性能。通过选择、转换和创建适当的特征,可以使模型更好地捕捉数据中的模式和关系,从而提高预测准确性。
-
降低过拟合风险:特征工程有助于减少过拟合的风险。通过移除冗余特征、进行特征选择和降维等技术,可以减少模型对噪声和不相关信息的敏感性,提高模型的泛化能力。
-
处理缺失值和异常值:特征工程可以处理数据中的缺失值和异常值。通过选择合适的方法来处理缺失值(如填充或删除)和异常值(如截断或替换),可以提高数据的完整性和质量,从而改善模型的性能。
-
改善数据表示:特征工程可以改善数据的表示形式,使其更适合机器学习算法的处理。例如,将文本数据转换为数值特征或使用特征缩放技术将不同尺度的特征统一到相似的范围内,有助于提高模型的稳定性和效果。
-
揭示隐藏信息:通过特征工程,可以从原始数据中提取隐藏的信息和关系。例如,通过时间序列特征提取可以捕捉到时间的趋势和周期性,通过特征组合可以发现特征之间的交互作用,从而提供更丰富的特征表示。
-
改善计算效率:特征工程可以减少数据维度和特征数量,从而提高计算效率。通过特征选择和降维技术,可以减少模型训练和推理的计算负担,加快模型的训练和预测速度。
文章总结了九种常用的特征工程方法
1.数据清洗:对原始数据进行处理和修复,以去除或纠正数据中的错误、不一致性和缺失值,以确保数据的准确性、完整性和一致性。
2.特征缩放:将特征数据按比例缩放,使其在相同的数值范围内。
3.特征编码:将非数值型的特征转化为数值型的特征,以便机器学习算法能够处理。
4.特征选择:从原始特征集合中选择出最具有代表性或最能够区分不同类别的特征。
5.特征变换:对原始特征进行变换,以便更好地满足模型的需求或提取更有用的特征。
6.文本处理:将文本数据转化为数值型的特征,以便机器学习算法能够处理。
7.时间序列特征提取:从时间序列数据中提取有用的特征,以便进行预测或分析。
8.组合特征:将多个特征进行组合,生成新的特征,以提供更丰富的信息。
9.特征降维:高维特征空间转化为低维特征空间,以减少特征维度和数据复杂度,提高模型的训练效率和泛化能力。
一、数据清洗🌈
数据清洗是特征工程中的一个重要步骤,它涉及检测和处理数据中的缺失值、异常值和重复值,以确保数据的准确性和完整性。下面是数据清洗的一些常见操作:
1.缺失值处理
-
检测缺失值:通过查看数据中的空值、NaN(Not a Number)或特定的占位符来检测缺失值。
-
处理缺失值:根据缺失值的情况,可以选择删除包含缺失值的行或列,填充缺失值(如使用均值、中位数或众数进行填充)或使用插值方法进行填充。
举例:
import pandas as pd
#创建包含缺失值的示例数据集
data={'A':[1,2,None,4],'B':[6,None,8,9]}
df=pd.DataFrame(data)
#删除包含缺失值的行
df.dropna(inplace=True)
#使用均值填充缺失值
df.fillna(df.mean(),inplace=True)
#使用插值方法填充缺失值
df.interpolate(method='linear',inplace=True)
print(df)
#删除包含缺失值的行
df.dropna(inplace=True)
print(df)
#输出删除包含缺失值的行的结果:
```
A B
0 1.0 6.0
3 4.0 9.0
```
df.dropna() 是 Pandas 中用于删除包含缺失值的行或列的方法。它可以根据不同的参数来删除 DataFrame 中的缺失值所在的行或列,
inplace=True
是一个可选参数,表示对原始数据框进行就地修改,即直接在原始数据框上删除行,而不返回一个新的数据框。
#使用均值填充缺失值
df.fillna(df.mean(),inplace=True)
print(df)
#输出使用均值填充缺失值的结果:
```
A B
0 1.000000 6.000000
1 2.000000 7.666667
2 2.333333 8.000000
3 4.000000 9.000000
```
df.fillna() 是 Pandas 中用于填充缺失值的方法。它可以使用指定的值或方法来填充 DataFrame 中的缺失值,df.mean()是调用DataFrame对象的mean()方法,用于计算每列的均值。
#使用插值方法填充缺失值
df.interpolate(method='linear',inplace=True)
print(df)
#输出使用插值方法填充缺失值的结果:
```
A B
0 1.0 6.0
1 2.0 7.0
2 3.0 8.0
3 4.0 9.0
```
df.interpolate()是pandas库中的一个函数,用于在数据中进行插值操作。它可以根据已知的数据点的位置和值来预测缺失值的值,并将插值后的值填充到缺失值的位置,method='linear’是一个可选参数,指定了插值方法。在此示例中,选择了线性插值方法。
2.异常值处理
异常值处理是数据清洗的一个重要步骤,它旨在识别和处理数据中的异常、离群值或错误值。常见的异常值处理方法包括删除异常值、替换异常值、截断处理、缩放/标准化处理、使用插值方法、使用统计模型。
当使用标准差处理异常值时,通常会将超出均值加减阈值乘以标准差的范围的数据点视为异常值,并进行处理。以下是一个示例:
import pandas as pd
# 创建包含异常值的示例数据
data = {'A': [10, 15, 12, 17, 9, 30, 8, 14, 16, 20, 5]}
df = pd.DataFrame(data)
# 识别异常值的一种常见方法是使用标准差
mean = df['A'].mean() #计算列'A'的均值(mean)
std_dev = df['A'].std() #计算列'A'的标准差(std_dev)
threshold = 2 #指定阈值(threshold),通常选择2作为标准差的倍数
'''使用布尔条件筛选出位于均值加减阈值乘以标准差范围内的数据点,这些数据点被认为是非异常值。
将筛选后的数据赋值给DataFrame df,即保留了非异常值的数据。'''
df = df[(df['A'] > mean - threshold * std_dev) & (df['A'] < mean + threshold * std_dev)]
print(df)
#输出结果:
```
A
0 10
1 15
2 12
3 17
4 9
6 8
7 14
8 16
9 20
10 5
```
在上述示例中,我们创建了一个DataFrame df 包含列’A’的示例数据,其中包含异常值30,然后,我们计算了列’A’的均值和标准差,并指定了阈值为2倍标准差。最后,我们使用布尔条件筛选出位于均值加减阈值乘以标准差范围内的数据点,并将结果赋值回DataFrame df,从而过滤掉了异常值。
3.重复值处理
重复值处理是数据清洗的一个重要步骤,它旨在识别和处理数据中的重复观测值。以下是一些常见的重复值处理方法:
1. 删除重复值:最简单的方法是直接删除包含重复值的观测值或变量。可以使用 df.drop_duplicates() 方法删除重复的行或列。
2. 替换重复值:将重复值替换为其他值,例如使用缺失值(NaN)或特定的数值来替换。可以使用 df.replace() 方法将重复值替换为指定的值。
3. 标记重复值:可以通过在数据中添加一个额外的列来标记重复值。可以使用 df.duplicated() 方法检测重复值,并将结果赋值给新的列,例如将重复值标记为True,非重复值标记为False。
4. 合并重复值:有时候重复值可能是由于数据的不完整或重复记录而产生的。在这种情况下,可以根据某些条件将重复记录进行合并,以获得更准确的数据。可以使用 df.groupby() 方法结合合适的聚合函数(如求和、平均值等)来合并重复记录。
举例:
import pandas as pd
# 创建包含重复行的示例数据
data = {'A': [1, 2, 3, 4, 2, 3, 1],
'B': ['a', 'b', 'c', 'd', 'b', 'c', 'a']}
df = pd.DataFrame(data)
# 打印原始数据
print("原始数据:")
print(df)
# 删除重复行
df = df.drop_duplicates()
# 打印删除重复行后的数据
print("\n删除重复行后的数据:")
print(df)
#输出结果:
```
原始数据:
A B
0 1 a
1 2 b
2 3 c
3 4 d
4 2 b
5 3 c
6 1 a
删除重复行后的数据:
A B
0 1 a
1 2 b
2 3 c
3 4 d
```
在上述示例中,我们创建了一个DataFrame df 包含两列’A’和’B’的示例数据,其中包含了重复的行。然后,我们使用****drop_duplicates()****方法删除了重复行,并将结果赋值回DataFrame df。
df = df.drop_duplicates()是pandas库中的一个函数调用,用于删除数据框中的重复行。
二、特征缩放
特征缩放是数据预处理的一项重要步骤,它用于将特征值转换到相似的尺度范围,以消除不同特征之间的量纲差异。常见的特征缩放方法包括最小-最大缩放、标准化和正规化。
1.最小-最大缩放(Min-Max Scaling)
最小-最大缩放是一种常见的特征缩放方法,它将特征值线性地映射到指定的最小值和最大值之间。
举例:
假设我们有一个特征向量 X = [10, 20, 30, 40, 50],我们希望将其缩放到范围 [0, 1],首先,找到特征向量的最小值和最大值,即 X_min = 10 和 X_max = 50,然后,使用最小-最大缩放公式将特征向量进行缩放:
import numpy as np
# 原始特征向量
X = np.array([10, 20, 30, 40, 50])
# 最小值和最大值
X_min = X.min()
X_max = X.max()
# 最小-最大缩放
X_scaled = (X - X_min) / (X_max - X_min)
# 打印缩放后的特征向量
print("缩放后的特征向量:")
print(X_scaled)
#输出结果:
```
缩放后的特征向量:
[0. 0.25 0.5 0.75 1. ]
```
在这个示例中,我们首先定义了原始特征向量 X。然后,使用X.min()
和X.max()
分别计算特征向量的最小值和最大值。接下来,使用最小-最大缩放公式 (X - X_min) / (X_max - X_min)
对特征向量进行缩放。
2.标准化(Standardization)
标准化(Standardization)是一种常见的特征缩放方法,它将特征值转换为均值为0、标准差为1的标准正态分布。
举例:
假设我们有一个特征向量 X = [10, 20, 30, 40, 50],我们希望将其标准化。
import numpy as np
# 原始特征向量
X = np.array([10, 20, 30, 40, 50])
# 计算均值和标准差
mean = np.mean(X)
std_dev = np.std(X)
# 标准化
X_scaled = (X - mean) / std_dev
# 打印标准化后的特征向量
print("标准化后的特征向量:")
print(X_scaled)
#输出结果:
```
标准化后的特征向量:
[-1.41421356 -0.70710678 0. 0.70710678 1.41421356]
```
在这个示例中,我们首先定义了原始特征向量 X。然后,使用np.mean(X)计算特征向量的均值,使用np.std(X)计算特征向量的标准差。接下来,使用标准化公式 (X - mean) / std_dev 对特征向量进行标准化。
3.归一化(Normalization)
正规化(Normalization)是一种常见的特征缩放方法,它通过将每个样本的特征向量转换成单位长度来进行缩放。
举例:
假设我们有一个特征向量 X = [3, 4],我们希望将其进行正规化。
from sklearn.preprocessing import Normalizer
import numpy as np
# 原始特征向量
X = np.array([[3, 4]])
# 创建Normalizer对象
normalizer = Normalizer(norm='l2')
# 使用transform进行正规化
X_normalized = normalizer.transform(X)
# 打印正规化后的特征向量
print("正规化后的特征向量:")
print(X_normalized)
#输出结果:
```
正规化后的特征向量:
[[0.6 0.8]]
```
Normalizer是Scikit-learn库中的一个预处理类,用于对数据进行归一化处理。在给定的数据集上,
Normalizer
可以应用不同的归一化方法。
在这个示例中,我们使用了scikit-learn库中的Normalizer类来进行正规化。首先,我们定义了原始特征向量 X,这里使用了一个2维的特征向量 [3, 4]。然后,我们创建了一个Normalizer对象(normalizer),并指定了正规化的方式为L2范数(欧几里德范数)。接下来,我们使用transform方法对特征向量 X 进行正规化。
三、特征编码
1.独热编码(One-Hot Encoding)
独热编码(One-Hot Encoding)是一种常用的特征编码方法,用于将分类变量表示为二进制向量的形式。每个分类变量的取值将被编码为一个长度等于分类变量不同取值数量的二进制向量,其中只有一个元素为1,表示该分类的取值。
举例:
from sklearn.preprocessing import OneHotEncoder
import numpy as np
# 原始分类变量
categories = np.array(["red", "blue", "green", "red", "yellow"])
# 创建OneHotEncoder对象
encoder = OneHotEncoder()
# 使用fit_transform进行独热编码
encoded_categories = encoder.fit_transform(categories.reshape(-1, 1))
# 打印独热编码后的结果
print("独热编码后的结果:")
print(encoded_categories.toarray())
#输出结果:
```
独热编码后的结果:
[[0. 0. 1. 0.]
[1. 0. 0. 0.]
[0. 1. 0. 0.]
[0. 0. 1. 0.]
[0. 0. 0. 1.]]
```
fit_transform是scikit-learn中一种常用的方法,它结合了
fit
和transform
两个步骤,用于对数据进行训练拟合和转换。
在这个示例中,我们使用了scikit-learn库中的OneHotEncoder
类来进行独热编码。首先,我们定义了原始的分类变量categories,这里使用了一个包含5个颜色的数组。然后,我们创建了一个OneHotEncoder
对象(encoder
)。接下来,我们使用fit_transform
方法对分类变量进行独热编码,注意需要将categories数组转换为列向量,即reshape为(-1, 1)的形状。最后,我们打印出独热编码后的结果。
2.标签编码(Label Encoding)
标签编码(Label Encoding)是一种将分类变量表示为整数形式的常见编码方法。每个不同的分类取值被赋予一个唯一的整数标签。
举例:
原始的分类变量是一个包含水果名称的数组,其中包括了苹果、香蕉、橙子、苹果和葡萄这几种水果。我们的目标是将这些水果名称编码为整数标签。
from sklearn.preprocessing import LabelEncoder
import numpy as np
# 原始分类变量
categories = np.array(["苹果", "香蕉", "橙子", "苹果", "葡萄"])
# 创建LabelEncoder对象
encoder = LabelEncoder()
# 使用fit_transform进行标签编码
encoded_categories = encoder.fit_transform(categories)
# 打印标签编码后的结果
print("标签编码后的结果:")
print(encoded_categories)
#输出结果:
```
标签编码后的结果:
[1 3 0 1 2]
```
我们使用了scikit-learn
库中的LabelEncoder
类来进行标签编码。首先,我们定义了原始的分类变量categories
,这里使用了一个包含5个水果的数组。然后,我们创建了一个LabelEncoder
对象(encoder
)。接下来,我们使用fit_transform
方法对分类变量进行标签编码。
3.特征哈希(Feature Hashing)
特征哈希(Feature Hashing)是一种常用的特征向量编码方法,用于将高维特征向量映射到固定长度的特征空间。它通过哈希函数将原始特征映射到一个指定的特征维度上。
特征哈希的过程如下:
-
定义目标特征维度。选择一个固定的特征维度,通常使用一个较小的值。
-
初始化特征哈希空间。创建一个长度为目标特征维度的零向量或稀疏向量。
-
对于每个原始特征,应用哈希函数。哈希函数将原始特征映射到特征哈希空间的索引位置。
-
对于哈希函数生成的索引位置,更新特征哈希空间。可以根据需要进行简单更新,例如将对应位置的值加1。
-
最终得到的特征哈希空间即为编码后的特征向量。
举例:
假设我们有一个文本分类任务,要根据电影评论的文本内容将其分类为正面评价或负面评价。我们可以使用特征哈希来对文本进行编码。
from sklearn.feature_extraction.text import HashingVectorizer
# 原始文本数据
documents = [
"这部电影太好看了,情节紧凑、演员表现出色!",
"我觉得这部电影很无聊,剧情一点都不吸引人。"
]
# 创建HashingVectorizer对象
vectorizer = HashingVectorizer(n_features=10)
# 使用transform进行特征哈希编码
hashed_features = vectorizer.transform(documents)
# 打印特征哈希编码后的结果
print("特征哈希编码后的结果:")
print(hashed_features.toarray())
#输出结果:
```
特征哈希编码后的结果:
[[-0.57735027 0. 0. 0. 0.57735027 0.
0.57735027 0. 0. 0. ]
[ 0. 0. 0. 0. -0.70710678 0.
0. 0. 0. -0.70710678]]
```
transform方法是scikit-learn中Transformer类的一个重要方法,用于对数据进行转换。它用于将已拟合(训练)的模型应用于新的数据,从而将其转换为模型所期望的表示形式。
请注意,由于特征哈希是通过哈希函数进行映射的,因此每次运行代码时,生成的特征哈希空间可能会有所不同。
首先,我们定义了两个电影评论的文本内容。然后,我们创建了一个HashingVectorizer对象(vectorizer),并指定了目标特征维度为10。
接下来,我们使用transform方法对原始文本进行特征哈希编码。这将生成一个特征哈希空间,其中每个文本对应一个长度为10的特征向量。
fit_transform,fit,transform区别和作用详解
四、特征选择
特征选择(Feature Selection)是从原始特征集合中选择最具有预测能力的特征子集的过程。它的目的是降低维度、减少特征数量,并提高机器学习模型的性能和解释性。
1.过滤法(Filtering Method)
过滤法(Filtering Method)是一种常用的特征选择方法,用于从原始特征中选择最相关或最具有区分度的特征子集。它通过对每个特征进行评估和排序,然后根据预定义的评估指标选择重要的特征。
过滤法的主要步骤如下:
-
特征评估:对每个特征进行评估,计算其与目标变量之间的相关性或区分度。常见的评估方法包括皮尔逊相关系数、卡方检验、互信息等。
-
特征排序:根据评估指标对特征进行排序,将最相关或最具有区分度的特征排在前面。
-
特征选择:根据预定义的选择策略,选择排名靠前的特征作为最终的特征子集。可以根据预设的特征数量或设定一个阈值来确定选择的特征数目。
过滤法的优点是简单、高效,不依赖具体的机器学习算法。它可以在特征预处理阶段独立于具体的学习算法使用,帮助减少特征维度,提高模型的效率和泛化能力。然而,过滤法忽略了特征之间的相互关系,可能会导致丢失一些重要的关联特征。
举例:
假设我们有一个二分类问题,要根据一组特征预测某个客户是否会购买某个产品。我们可以使用方差选择作为过滤法的评估指标,选择方差较大的特征作为最终的特征子集。
from sklearn.feature_selection import VarianceThreshold
import numpy as np
# 原始特征数据
X = np.array([
[1, 1, 1, 0],
[0, 1, 1, 0],
[1, 0, 0, 0],
[0, 1, 0, 0],
[1, 1, 1, 1]
])
# 创建VarianceThreshold对象
selector = VarianceThreshold(threshold=0.2)
# 使用fit_transform进行特征选择
selected_features = selector.fit_transform(X)
# 打印经过方差选择后的特征子集
print("方差选择后的特征子集:")
print(selected_features)
#输出结果:
```
方差选择后的特征子集:
[[1 1]
[0 1]
[1 0]
[0 0]
[1 1]]
```
VarianceThreshold
是scikit-learn中的一个特征选择方法,它可以根据特征的方差来进行选择,在代码中,threshold=0.2表示设置方差的阈值为0.2。这意味着如果某个特征的方差小于0.2,它将被认为是低方差特征,会被选择性地删除。
2.包装法(Wrapper Method)
包装法(Wrapper Method)是一种特征选择方法,它通过使用一个特定的学习算法来评估不同特征子集的性能,并选择对于特定学习任务最佳的特征子集。与过滤法不同,包装法将特征选择过程视为一个搜索问题,通过尝试不同的特征子集来找到最佳子集。
包装法的主要步骤如下:
-
特征子集搜索:包装法从初始特征集合开始,通过不断迭代地搜索特征子集的组合。它可以使用不同的搜索策略,如逐步向前选择、逐步向后删除、逐步向前向后选择等。
-
子集评估:对于每个特征子集,使用一个预定的学习算法进行训练和评估。常见的评估指标包括准确率、F1分数、召回率等,根据具体问题选择合适的指标。
-
特征子集更新:根据评估结果更新当前的特征子集。可能增加或删除某些特征,以寻找更好的特征组合。
-
终止条件:根据预设的终止条件(如达到特定特征数目、达到最佳性能等),决定是否停止迭代搜索过程。
举例:
假设我们有一个二分类问题,要根据一组特征预测某个客户是否会购买某个产品。我们可以使用包装法来选择最佳的特征子集,以提高分类器的性能。
from sklearn.feature_selection import RFE
from sklearn.ensemble import RandomForestClassifier
import numpy as np
# 原始特征数据
X = np.array([
[0.5, 0.2, 0.1, 0.8],
[0.3, 0.6, 0.4, 0.5],
[0.9, 0.1, 0.6, 0.3],
[0.2, 0.8, 0.9, 0.1],
[0.7, 0.4, 0.2, 0.6]
])
# 目标变量
y = np.array([0, 1, 1, 0, 1])
# 创建随机森林分类器作为评估器
estimator = RandomForestClassifier()
# 创建RFE对象,选择两个特征
selector = RFE(estimator, n_features_to_select=2)
# 使用fit_transform进行特征选择
selected_features = selector.fit_transform(X, y)
# 打印经过特征选择后的特征子集
print("特征选择后的特征子集:")
print(selected_features)
#输出结果:
```
特征选择后的特征子集:
[[0.1 0.8]
[0.4 0.5]
[0.6 0.3]
[0.9 0.1]
[0.2 0.6]]
```
RFE(Recursive Feature Elimination),是一种特征选择方法,用于从给定的特征集中递归地选择最重要的特征子集。它通过反复训练模型并消除最不重要的特征来进行特征选择。
在实际应用中,可以根据具体的问题和数据集,选择适合的评估器和特征数目,以及进行交叉验证等其他技术来更好地评估特征子集的性能。
3.嵌入法(Embedded Method)
嵌入法它在特征选择过程中直接与学习算法结合,通过学习算法自身的特性来选择最佳的特征子集。嵌入法将特征选择视为学习算法的一部分,通过优化学习算法的性能来选择最佳特征。
嵌入法的主要步骤如下:
-
学习算法训练:使用特征子集训练学习算法。不同的学习算法有不同的特征选择方式,例如决策树可以直接通过特征重要性进行特征选择,线性模型可以通过正则化项来约束特征权重。
-
特征权重计算:学习算法根据训练过程中的特征权重或参数,评估每个特征的重要性。这些权重可以表示特征对于学习算法的贡献程度。
-
特征子集更新:根据特征权重,选择重要性较高的特征作为最佳特征子集。可以根据权重的阈值进行特征选择,也可以设定要选择的特征数目。
-
终止条件:根据预设的终止条件(如达到特定特征数目、达到最佳性能等),决定是否停止特征选择过程。
常见的嵌入法算法包括决策树、线性模型(如逻辑回归和线性支持向量机)、正则化方法(如L1正则化和L2正则化)等。
以下是使用决策树进行特征选择的示例:
from sklearn.feature_selection import SelectFromModel
from sklearn.tree import DecisionTreeClassifier
import numpy as np
# 原始特征数据
X = np.array([
[1, 1, 1, 0],
[0, 1, 1, 0],
[1, 0, 0, 0],
[0, 1, 0, 0],
[1, 1, 1, 1]
])
# 目标变量
y = np.array([1, 0, 0, 1, 1])
# 创建决策树分类器作为评估器
estimator = DecisionTreeClassifier()
# 创建SelectFromModel对象,基于特征重要性选择特征
selector = SelectFromModel(estimator)
# 使用fit_transform进行特征选择
selected_features = selector.fit_transform(X, y)
# 打印经过特征选择后的特征子集
print("特征选择后的特征子集:")
print(selected_features)
#输出结果:
```
特征选择后的特征子集:
[[1 1]
[1 1]
[0 0]
[1 0]
[1 1]]
```
嵌入法通常是在模型训练的过程中进行特征选择,因此可能会增加训练时间。
决策树分类器(DecisionTreeClassifier)
五、特征变换
特征变换(Feature Transformation)是将原始特征进行数学变换,以改变其表示形式或提取更有用的信息。特征变换的目的是使数据更适合机器学习算法的处理,改善模型的性能或提取更具代表性的特征。常见特征变换方法包括多项式特征、对数变换、指数变换。
1.多项式特征
多项式特征通过将原始特征进行多项式组合来生成新的特征。这种方法可以捕捉特征之间的非线性关系,并提供更丰富的特征表示,从而提高机器学习模型的拟合能力。
举例:
假设你是一个房地产公司的数据科学家,你需要建立一个模型来预测房屋的销售价格。你已经收集到了一些房屋的数据,包括房屋的面积(以平方英尺为单位)和房龄(以年为单位),以及对应的销售价格(以万美元为单位),你决定使用多项式特征来扩展原始特征,以便更好地捕捉特征之间的非线性关系。你打算使用二次多项式特征(即度数为2)进行特征转换,请使用Python编写代码,使用多项式特征进行房屋销售价格的预测。
-
导入所需的库,包括
sklearn.preprocessing
中的PolynomialFeatures
类和sklearn.linear_model
中的LinearRegression
类。 -
定义原始的特征矩阵
X
和目标变量y
,分别表示房屋的面积和房龄以及对应的销售价格。 -
创建一个
PolynomialFeatures
对象,设置度数为2。 -
使用
fit_transform
方法对原始特征进行多项式特征变换,得到扩展后的特征矩阵X_poly
。 -
创建一个线性回归模型。
-
使用多项式特征变换后的特征矩阵进行模型训练,通过调用
fit
方法。 -
使用新的房屋数据
[1800, 8]
进行预测。首先对新数据进行多项式特征变换,然后调用模型的predict
方法进行预测。 -
打印预测的销售价格。
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
# 原始特征数据
X = [[1500, 10], [2000, 5], [1200, 15]]
y = [250, 350, 200]
# 创建PolynomialFeatures对象,设置度数为2
poly = PolynomialFeatures(degree=2)
# 使用fit_transform进行多项式特征变换
X_poly = poly.fit_transform(X)
# 创建线性回归模型
model = LinearRegression()
# 使用多项式特征变换后的特征矩阵进行模型训练
model.fit(X_poly, y)
# 进行预测
new_data = [[1800, 8]]
new_data_poly = poly.transform(new_data)
predicted_price = model.predict(new_data_poly)
# 打印预测结果
print("预测的销售价格:", predicted_price)
#输出结果:
```
预测的销售价格: [294.82593559]
```
2.对数变换
对数变换是一种常见的数据转换方法,用于改变数据的分布或减小数据的尺度。它通过取某个数值的对数来转换原始数据,从而改变数据的相对大小关系,一般具有以下特点。
-
数据具有指数增长趋势:当数据随着自变量的增加呈指数增长时,对数变换可以使数据变得更加线性,从而便于建模和分析。
-
数据具有右偏或左偏分布:当数据的分布呈现右偏(正偏)或左偏(负偏)时,对数变换可以将数据拉伸或压缩,使其更接近正态分布,从而符合许多统计模型的假设。
-
数据的尺度跨度较大:当数据的尺度跨度较大时,使用对数变换可以将数据缩放到更小的范围,减少不同变量之间的尺度差异。
举例:
假设我们有以下数据:
房屋面积(平方英尺):[1000, 1500, 2000, 2500, 3000]
销售价格(万美元):[50, 75, 100, 125, 150]
我们可以使用对数变换来转换销售价格
import numpy as np
# 原始数据
area = np.array([1000, 1500, 2000, 2500, 3000])
price = np.array([50, 75, 100, 125, 150])
# 对数变换
log_price = np.log10(price)
print("原始价格:", price)
print("对数变换后的价格:", log_price)
#输出结果:
```
原始价格: [ 50 75 100 125 150]
对数变换后的价格: [1.69897 1.87506 2. 2.09691 2.17609]
```
我们可以看到,变换后的数值更接近线性关系,更适合用于建模和分析。
3.指数变换
指数变换是一种常见的数据转换方法,用于改变数据的分布或减小数据的尺度。它通过取数据的指数来转换原始数据,从而改变数据的相对大小关系。
举例:
假设我们有以下数据:
时间(小时):[1, 2, 3, 4, 5]
货物存储量(单位):[10, 6, 3, 2, 1]
我们可以使用指数变换来转换货物存储量。
import numpy as np
# 原始数据
time = np.array([1, 2, 3, 4, 5])
storage = np.array([10, 6, 3, 2, 1])
# 指数变换
exp_storage = np.exp(storage)
print("原始货物存储量:", storage)
print("指数变换后的货物存储量:", exp_storage)
#输出结果:
```
原始货物存储量: [10 6 3 2 1]
指数变换后的货物存储量: [22026.46579481 403.42879349 20.08553692 7.3890561 2.71828183]
```
转换后的货物存储量呈现指数衰减趋势,更容易用于建模和分析。
六、文本处理
文本处理是指对文本数据进行预处理、清理、转换和分析的过程。它是自然语言处理(NLP)领域的一个重要组成部分,用于处理和理解文本数据。
1.分词
在分词过程中,文本被分解成单个的词语或标记,这些词语可以是单词、短语、符号或其他语言单位。分词有助于将连续的文本转换为离散的标记,为后续的文本处理和分析提供基础。
举例:
import nltk
text = "Hello, how are you today?"
# 使用nltk进行分词
tokens = nltk.word_tokenize(text)
print(tokens)
#输出结果:
```
['Hello', ',', 'how', 'are', 'you', 'today', '?']
```
分词的方法和效果取决于具体的文本和语言。不同的语言和文本类型可能需要使用不同的分词工具或技术来获得更好的结果。此外,还可以使用其他库和工具,如jieba(用于中文分词)和spaCy等,来进行分词处理。
2.停用词移除
其含义是在文本处理中常见的无实际含义的词语,例如英语中的"a"、“an”、"the"等。这些词语在文本中频繁出现,但通常不携带重要的语义信息,因此在某些文本分析任务中可以被移除,以减少噪音和提高处理效果。
举例:
使用python中的nltk移除停用词
import nltk
from nltk.corpus import stopwords
text = "This is an example sentence, demonstrating the removal of stop words."
# 下载停用词
nltk.download('stopwords')
# 获取英语停用词列表
stop_words = set(stopwords.words('english'))
# 分词
tokens = nltk.word_tokenize(text)
# 移除停用词
filtered_tokens = [word for word in tokens if word.lower() not in stop_words]
print(filtered_tokens)
#输出结果:
```
['This', 'example', 'sentence', ',', 'demonstrating', 'removal', 'stop', 'words', '.']
```
除了nltk库,还有其他许多用于停用词移除的工具和库可供选择,如spaCy和scikit-learn等。这些工具通常提供了多种语言的停用词列表,并具有更高效和灵活的停用词移除功能。
3.词袋表示
词袋表示用于将文本转换为数值特征向量。它基于假设,即文本中的词语顺序和语法结构对于表达文本含义不是必要的,只考虑词语的出现频率或存在与否。
举例:
from sklearn.feature_extraction.text import CountVectorizer
# 原始文本数据
documents = [
"This is the first document.",
"This document is the second document.",
"And this is the third one.",
"Is this the first document?"
]
# 创建词袋模型
vectorizer = CountVectorizer()
# 将文本转换为词袋表示
bag_of_words = vectorizer.fit_transform(documents)
# 获取词袋中的词语
feature_names = vectorizer.get_feature_names()
# 打印词袋表示的特征向量
print(bag_of_words.toarray())
# 打印词袋中的词语
print(feature_names)
#输出结果:
```
[[0 1 1 1 0 0 1 0 1]
[0 2 0 1 0 1 1 0 1]
[1 0 0 1 1 0 1 1 1]
[0 1 1 1 0 0 1 0 1]]
['and', 'document', 'first', 'is', 'one', 'second', 'the', 'third', 'this']
```
词袋表示是一种简单而常用的文本表示方法,但它忽略了词语顺序和语义信息。在实际应用中,可以结合其他技术,如TF-IDF(词频-逆文档频率)权重计算,来改进词袋表示的效果。
4.TF-IDF表示(Term Frequency-Inverse Document Frequency)
TF(词频)指的是某个词语在文本中出现的频率,计算方式为词语在文本中出现的次数除以文本中总词语数。
IDF(逆文档频率)指的是词语的普遍重要性,计算方式为总文档数除以包含该词语的文档数的对数。
TF-IDF表示将TF和IDF相乘,以得到词语在文本中的重要性程度。
举例:
from sklearn.feature_extraction.text import TfidfVectorizer
# 原始文本数据
documents = [
"This is the first document.",
"This document is the second document.",
"And this is the third one.",
"Is this the first document?"
]
# 创建TF-IDF向量化器
vectorizer = TfidfVectorizer()
# 将文本转换为TF-IDF表示
tfidf_matrix = vectorizer.fit_transform(documents)
# 获取TF-IDF表示的特征向量
feature_names = vectorizer.get_feature_names()
# 打印TF-IDF表示的特征向量
print(tfidf_matrix.toarray())
# 打印特征向量对应的词语
print(feature_names)
#输出结果:
```
[[0. 0. 0.52547275 0. 0. 0. 0.52547275 0. 0.52547275]
[0. 0.81940995 0. 0. 0. 0.57320793 0.33670292 0. 0.33670292]
[0.65249088 0. 0. 0.38537163 0.65249088 0. 0.30259008 0.65249088 0.30259008]
[0. 0. 0.52547275 0. 0. 0. 0.52547275 0. 0.52547275]]
['and', 'document', 'first', 'is', 'one', 'second', 'the', 'third', 'this']
```
TF-IDF表示考虑了词语在文本中的频率和在整个文本集合中的普遍重要性,因此可以更好地反映词语在文本中的重要程度。它在信息检索、文本分类和文本相似度等任务中广泛应用。
七、时间序列特征提取
时间序列特征提取是指从时间序列数据中提取有意义的特征,以用于分析、建模和预测。时间序列数据是按时间顺序排列的数据点,如股票价格、气温、交通流量等。
常见的时间序列特征包括:滞后特征、移动平均特征、时序特征
1.滞后特征
滞后特征基于时间序列数据中当前时刻与过去时刻之间的关系,将过去时刻的观测值作为特征。
举例:
假设我们有一个每日销售额的时间序列数据,我们想要使用滞后特征来预测未来的销售额。
import pandas as pd
# 创建示例时间序列数据
data = pd.DataFrame({
'日期': ['2022-01-01', '2022-01-02', '2022-01-03', '2022-01-04', '2022-01-05'],
'销售额': [100, 120, 90, 110, 130]
})
# 将日期列转换为日期时间类型
data['日期'] = pd.to_datetime(data['日期'])
# 添加一阶滞后特征
data['lag_1'] = data['销售额'].shift(1)
# 打印结果
print(data)
#输出结果:
```
日期 销售额 lag_1
0 2022-01-01 100 NaN
1 2022-01-02 120 100.0
2 2022-01-03 90 120.0
3 2022-01-04 110 90.0
4 2022-01-05 130 110.0
```
我们使用pandas库创建了一个DataFrame对象来表示时间序列数据。然后,我们将日期列转换为日期时间类型,以便后续处理。接下来,我们使用shift()
函数将销售额列向下移动一个位置,得到一阶滞后特征列"lag_1"。
在第一行中,由于没有前一个时刻的销售额,所以滞后特征值为NaN。
2.移动平均特征
移动平均特征基于时间序列数据中一定窗口内观测值的平均值,用于捕捉时间序列的趋势和平滑数据。其基本思想是使用一组连续观测值的平均值来代表当前时刻的特征。通过滑动窗口的方式,移动平均特征可以在不同的时间尺度上捕捉时间序列的趋势和周期性。
举例:
假设我们有一个每日销售额的时间序列数据,我们想要使用移动平均特征来平滑数据并捕捉销售额的趋势。
import pandas as pd
# 创建示例时间序列数据
data = pd.DataFrame({
'日期': ['2022-01-01', '2022-01-02', '2022-01-03', '2022-01-04', '2022-01-05'],
'销售额': [100, 120, 90, 110, 130]
})
# 将日期列转换为日期时间类型
data['日期'] = pd.to_datetime(data['日期'])
# 计算简单移动平均特征
window_size = 7 # 窗口大小为7天
data['moving_avg'] = data['销售额'].rolling(window=window_size).mean()
# 打印结果
print(data)
#输出结果:
```
日期 销售额 moving_avg
0 2022-01-01 100 NaN
1 2022-01-02 120 NaN
2 2022-01-03 90 NaN
3 2022-01-04 110 NaN
4 2022-01-05 130 110.0
```
data.rolling(window, …).<aggregation_function>()其中,data是一个Pandas数据框或时间序列数据,window是指定的滚动窗口大小,<aggregation_function>是滚动窗口内的聚合函数,例如mean表示计算滚动平均值,sum表示计算滚动总和等。
在前6行中,由于没有足够的过去观测值来计算移动平均值,所以特征值为NaN。从第7行开始,我们计算过去7天(包括当前时刻)的销售额的平均值,并将结果作为移动平均特征。
3.时序特性
时序特征是指从时间序列数据中提取的用于描述、表示和分析数据的特征。时序特征可以包括多个方面,例如趋势、周期性、季节性、周期长度、时间延迟等.
常见时序特征代码:
import pandas as pd
import statsmodels.api as sm
# 创建示例时间序列数据
data = pd.DataFrame({
'日期': ['2022-01-01', '2022-01-02', '2022-01-03', '2022-01-04', '2022-01-05'],
'气温': [15, 18, 20, 16, 22]
})
# 将日期列转换为日期时间类型
data['日期'] = pd.to_datetime(data['日期'])
# 提取趋势特征
X_trend = sm.add_constant(range(len(data)))
model_trend = sm.OLS(data['气温'], X_trend)
results_trend = model_trend.fit()
trend_slope = results_trend.params[1] # 趋势斜率
# 提取周期性特征
X_period = sm.add_constant(range(len(data)))
model_period = sm.OLS(data['气温'], X_period)
results_period = model_period.fit()
period_frequency = 1 / results_period.params[2] # 周期频率
# 提取季节性特征
seasonal_decomposition = sm.tsa.seasonal_decompose(data['气温'], period=1)
seasonal_index = seasonal_decomposition.seasonal
# 提取自回归特征
lag_values = [1, 2, 3] # 指定滞后观测值的数量
lag_features = []
for lag in lag_values:
lag_feature = data['气温'].shift(lag)
lag_features.append(lag_feature)
data['lag_1'] = lag_features[0]
data['lag_2'] = lag_features[1]
data['lag_3'] = lag_features[2]
# 提取统计特征
mean_temperature = data['气温'].mean()
var_temperature = data['气温'].var()
max_temperature = data['气温'].max()
min_temperature = data['气温'].min()
# 打印结果
print("趋势斜率:", trend_slope)
print("周期频率:", period_frequency)
print("季节性指数:", seasonal_index)
print("滞后观测值:", lag_features)
print("均值:", mean_temperature)
print("方差:", var_temperature)
print("最大值:", max_temperature)
print("最小值:", min_temperature)
#输出结果:
```
趋势斜率: 1.2
周期频率: 1.0
季节性指数: [0.0, 0.0, 0.0, 0.0, 0.0]
滞后观测值: [NaN, 15.0, 18.0, 20.0, 16.0]
均值: 18.2
方差: 7.3
最大值: 22
最小值: 15
```
八、组合特征
组合特征指通过将多个原始特征进行组合、衍生或转换,创建新的特征。这样做的目的是为了增加模型对数据的表达能力,捕捉更多的信息和非线性关系。
1.特征交叉:✨
特征交叉是通过将两个或多个特征进行组合、衍生或转换,创建新的特征。特征交叉的目的是为了捕捉特征之间的相互影响或交互关系,从而提高模型的表达能力。
举例:
import pandas as pd
# 示例数据集
data = {'feature1': [3, 4, 5, 6],
'feature2': [6, 7, 8, 9]}
df = pd.DataFrame(data)
# 特征交叉
df['feature_cross'] = df['feature1'] * df['feature2']
print(df)
#输出结果:
```
feature1 feature2 feature_cross
0 3 6 18
1 4 7 28
2 5 8 40
3 6 9 54
```
在这个示例中,新特征feature_cross是通过feature1和feature2相乘得到的。例如,在第一行中,feature_cross的值是3乘以6,得到18。
2.特征合并⭐️
特征合并是将不同特征组合在一起形成一个新的特征向量或特征矩阵的过程。特征合并的目的是将不同来源或不同类型的特征结合起来,以提供更全面和丰富的信息供机器学习模型使用。
举例:
假设我们有一个包含两个数值特征的DataFrame,现在,我们想要将feature1和feature2进行特征合并,创建一个新的特征feature_merge,它是两个特征的和。
import pandas as pd
df = pd.DataFrame({'feature1': [3, 4, 5, 6],
'feature2': [6, 7, 8, 9]})
df['feature_merge'] = df['feature1'] + df['feature2']
print(df)
#输出结果:
```
feature1 feature2 feature_merge
0 3 6 9
1 4 7 11
2 5 8 13
3 6 9 15
```
我们使用了加法运算符(+)将feature1和feature2进行了特征合并,并创建了一个新的特征feature_merge,该特征表示了两个特征的和。
九、特征降维
特征降维是将高维特征空间中的特征表示转换为低维表示的过程,同时保留原始数据中最重要的信息。特征降维的目的是减少特征的数量,消除冗余和噪音,简化模型的复杂度,并提高模型的训练效率和泛化能力。
常见的特征降维方法包括主成分分析(PCA)、线性判别分析(LDA)、特征选择和特征提取。
1.主成分分析(PCA)
主成分分析是一种无监督的线性降维方法,通过找到数据中的主成分,将高维数据映射到低维空间。它将原始特征转换为一组互不相关的主成分,这些主成分按照方差的大小排列。选择保留的主成分数量可以控制降维后的维度。
举例:
加载鸢尾花数据集,并使用PCA将数据降低到2维。
from sklearn.decomposition import PCA
from sklearn.datasets import load_iris
# 加载鸢尾花数据集
data = load_iris()
X, y = data.data, data.target
# 创建PCA对象
pca = PCA(n_components=2)
# 对数据进行降维
X_pca = pca.fit_transform(X)
print(X_pca.shape)
#输出结果:
```
(150, 2)
```
鸢尾花数据集(Iris - UCI Machine Learning Repository)
2.线性判别分析(LDA)
线性判别分析是一种有监督的线性降维方法,常用于分类问题。与PCA不同,LDA不仅仅关注数据的方差信息,还考虑了类别之间的区分度。LDA的基本思想是将原始特征投影到一个低维空间,以最大化类别之间的差异度(类间散布矩阵)并最小化类别内部的差异度(类内散布矩阵)。通过这种方式,LDA能够在降维的同时保留最具判别性的信息。
举例:
加载鸢尾花数据集,并使用LDA将数据降低到2维。
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.datasets import load_iris
# 加载鸢尾花数据集
data = load_iris()
X, y = data.data, data.target
# 创建LDA对象
lda = LinearDiscriminantAnalysis(n_components=2)
# 对数据进行降维
X_lda = lda.fit_transform(X, y)
print(X_lda.shape)
#输出结果:
```
(150, 2)
```
LDA是一种有监督的降维方法,通过考虑类别之间的差异度来选择最具判别性的特征。它在分类问题中经常用于特征工程和数据可视化,可以帮助提高分类模型的性能。
3.特征选择
特征选择(Feature Selection)是从原始特征集合中选择最相关或最具信息量的特征子集的过程。它是特征工程的一部分,旨在减少特征维度、提高模型性能、降低过拟合风险或简化模型解释性。
举例:
加载鸢尾花数据集,并使用特征选择将数据降低到2维。
from sklearn.feature_selection import SelectKBest, f_classif
from sklearn.datasets import load_iris
# 加载鸢尾花数据集
data = load_iris()
X, y = data.data, data.target
# 创建SelectKBest对象
selector = SelectKBest(score_func=f_classif, k=2)
# 对数据进行特征选择
X_selected = selector.fit_transform(X, y)
print(X_selected.shape)
#输出结果:
```
(150, 2)
```
SelectKBest是一种常用的特征选择方法,在特征选择过程中使用了一种指定的评估指标来计算特征的重要性。你可以根据问题的需求选择不同的评估指标。
4.特征提取
特征提取(Feature Extraction)是从原始数据中创建新的特征表示的过程,以捕捉数据的重要信息。与特征选择不同,特征提取不仅是从现有特征中选择最相关的特征,而是通过转换、组合或创建新的特征来表示数据。
举例:
加载鸢尾花数据集,并使用特征提取将数据降低到2维。
from sklearn.decomposition import KernelPCA
from sklearn.datasets import load_iris
# 加载鸢尾花数据集
data = load_iris()
X, y = data.data, data.target
# 创建KernelPCA对象
kpca = KernelPCA(n_components=2, kernel='rbf')
# 对数据进行特征提取
X_kpca = kpca.fit_transform(X)
print(X_kpca.shape)
#输出结果:
```
(150, 2)
```
KernelPCA是一种非线性的降维方法,通过使用核函数(如RBF核函数)将数据映射到高维特征空间,并在该空间中进行主成分分析。这使得KernelPCA能够有效地捕捉非线性的数据结构。
十、本文相关链接::🔥🔥🔥
fit_transform,fit,transform区别和作用详解
决策树分类器(DecisionTreeClassifier)
鸢尾花数据集(Iris - UCI Machine Learning Repository)
文章的全部代码放在这里https://github.com/2214018128zcy/Machine-learning
结束:😊
喜欢本文的朋友可以收藏点赞起来!!!🎉🎉🎉
以后会继续更新相关领域的博客内容,大家可以点点关注!🌟