三 机器学习之特征工程
机器学习特征工程是将原始数据转化为更能代表预测目标的特征,以提高机器学习模型性能的一系列技术和方法。
1 特征工程是什么?

机器学习特征工程是将原始数据转化为更能代表预测目标的特征,以提高机器学习模型性能的一系列技术和方法。有句话在业界广泛流传:数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限而已。特征工程本质是一项工程活动,目的是最大限度地从原始数据中提取特征以供算法和模型使用。特征处理是特征工程的核心部分,sklearn 提供了较为完整的特征处理方法,包括数据预处理,特征选择,降维等。
本文使用 sklearn 中的 IRIS(鸢尾花)数据集进行说明,该数据集由 Fisher 在 1936 年整理,包含 4 个特征(Sepal.Length、Sepal.Width、Petal.Length、Petal.Width ,单位为厘米),目标值为鸢尾花的分类(Iris Setosa、Iris Versicolour、Iris Virginica)。导入代码如下:
from sklearn.datasets import load_iris
#导入IRIS数据集
iris = load_iris()
#特征矩阵
iris.data
#目标向量
iris.target
2 数据预处理
通过特征提取得到的特征可能存在以下问题:
- 不属于同一量纲。
- 信息冗余。
- 定性特征不能直接使用。
- 存在缺失值。
- 信息利用率低。
- 数据偏态问题
- 数据噪声问题
- 数据不一致问题
- 数据增强问题
一般使用 sklearn 中的 preproccessing 库来进行数据预处理。
2.1 无量纲化
使不同规格的数据转换到同一规格,常见方法有标准化和区间缩放法。
- 标准化:前提是特征值服从正态分布,标准化后转换成标准正态分布。使用 StandardScaler 类,代码如下:
from sklearn.preprocessing import StandardScaler
#标准化,返回值为标准化后的数据
StandardScaler().fit_transform(iris.data)
- 区间缩放法:利用边界值信息,将特征取值区间缩放到特定范围,如[0, 1]。使用 MinMaxScaler 类,代码如下:
from sklearn.preprocessing import MinMaxScaler
#区间缩放,返回值为缩放到[0, 1]区间的数据
MinMaxScaler().fit_transform(iris.data)
- 标准化与归一化的区别:标准化依照特征矩阵的列处理数据,通过求 z-score 的方法将样本特征值转换到同一量纲下;归一化依照特征矩阵的行处理数据,目的是使样本向量在点乘运算或其他核函数计算相似性时拥有统一标准,转化为“单位向量”。使用 Normalizer 类归一化代码如下:
from sklearn.preprocessing import Normalizer
#归一化,返回值为归一化后的数据
Normalizer().fit_transform(iris.data)
2.2 对定量特征二值化
核心在于设定阈值,大于阈值赋值为 1,小于等于阈值赋值为 0 。使用 Binarizer 类,代码如下:
from sklearn.preprocessing import Binarizer
#二值化,阈值设置为3,返回值为二值化后的数据
Binarizer(threshold=3).fit_transform(iris.data)
2.3 对定性特征哑编码
使用 OneHotEncoder 类,由于 IRIS 数据集特征皆为定量特征,用其目标值演示,代码如下:
from sklearn.preprocessing import OneHotEncoder
#哑编码,对IRIS数据集的目标值,返回值为哑编码后的数据
OneHotEncoder().fit_transform(iris.target.reshape((-1,1)))
2.4 缺失值计算
使用 Imputer 类,对新增含缺失值样本处理,代码如下:
from numpy import vstack, array, nan
from sklearn.preprocessing import Imputer
#缺失值计算,返回值为计算缺失值后的数据
#参数missing_value为缺失值的表示形式,默认为NaN
#参数strategy为缺失值填充方式,默认为mean(均值)
Imputer().fit_transform(vstack((array([nan, nan, nan, nan]), iris.data)))
2.5 数据变换
- 多项式转换:使用 PolynomialFeatures 类,代码如下:
from sklearn.preprocessing import PolynomialFeatures
#多项式转换
#参数degree为度,默认值为2
PolynomialFeatures().fit_transform(iris.data)
- 基于单变元函数的数据变换:使用 FunctionTransformer 类,以对数函数转换为例,代码如下:
from numpy import log1p
from sklearn.preprocessing import FunctionTransformer
#自定义转换函数为对数函数的数据变换
#第一个参数是单变元函数
FunctionTransformer(log1p).fit_transform(iris.data)
2.6 处理数据偏态
数据集中某些特征的分布呈现出明显的偏态,即大部分数据集中在某一区域,而另一区域的数据很少。这种情况可能会影响模型的训练效果,因为模型可能会过度拟合数据较多的部分,而忽略数据较少的部分。
- 解决方法:可以使用对数变换、Box - Cox变换等方法对数据进行变换,使数据分布更接近正态分布。对于严重偏态的数据,也可以考虑采用分箱的方法,将数据划分到不同的区间,以减少偏态对模型的影响。
from scipy import stats
# 生成一些偏态数据
data = np.random.exponential(scale=1, size=1000)
df = pd.DataFrame(data, columns=['skewed_feature'])
# 对数变换
df['log_transformed'] = np.log(df['skewed_feature'])
# Box-Cox变换
transformed, _ = stats.boxcox(df['skewed_feature'])
df['boxcox_transformed'] = transformed
# 分箱
df['binned'] = pd.cut(df['skewed_feature'], bins=10)
2.7 处理数据噪声
数据中可能存在一些随机的、不相关的干扰信息,即噪声。噪声可能会干扰模型的学习过程,降低模型的准确性和泛化能力。
- 解决方法:可以使用平滑技术,如移动平均、中值滤波等,对数据进行去噪处理。对于一些异常值(可能是噪声点),可以根据一定的规则进行识别和处理,如设定阈值,将超出阈值的数据点视为异常值并进行修正或删除。
from scipy.signal import medfilt, convolve
# 生成带噪声的数据
np.random.seed(0)
t = np.linspace(0, 10, 1000)
y = np.sin(t) + 0.5 * np.random.normal(size=len(t))
df = pd.DataFrame({'time': t, 'noisy_signal': y})
# 移动平均
window_size = 10
df['moving_average'] = df['noisy_signal'].rolling(window=window_size).mean()
# 中值滤波
df['median_filtered'] = medfilt(df['noisy_signal'], kernel_size=5)
2.8 处理数据不一致性
在数据收集和整合过程中,可能会出现数据不一致的情况,例如不同数据源对同一实体的描述存在差异,或者数据在不同时间点的记录存在矛盾。
- 解决方法:需要进行数据清洗和一致性检查,通过制定数据一致性规则,对数据进行比对和修正。可以使用数据融合技术,将来自不同数据源的数据进行融合,以消除不一致性。同时,建立数据质量管理机制,在数据录入和更新过程中,进行实时的一致性检查和验证,确保数据的准确性和一致性。
# 模拟不一致数据
data1 = {
'id': [1, 2, 3],
'name': ['Alice', 'Bob', 'Charlie'],
'age': [25, 30, 35]
}
data2 = {
'id': [1, 2, 3],
'name': ['Alice', 'Robert', 'Charlie'],
'age': [25, 31, 35]
}
df1 = pd.DataFrame(data1)
df2 = pd.DataFrame(data2)
# 数据融合和一致性检查
merged = pd.merge(df1, df2, on='id', suffixes=('_df1', '_df2'))
merged['name'] = merged.apply(lambda row: row['name_df1'] if row['name_df1'] == row['name_df2'] else 'Inconsistent', axis=1)
merged['age'] = merged.apply(lambda row: row['age_df1'] if row['age_df1'] == row['age_df2'] else np.nan, axis=1)
merged = merged[['id', 'name', 'age']]
2.9 数据增强
在一些机器学习任务中,尤其是深度学习中,数据量不足可能导致模型过拟合,无法学习到足够的特征和规律。
- 解决方法:数据增强是通过对原始数据进行一系列的变换,如旋转、翻转、缩放、平移、添加噪声等,生成更多的样本,以扩充数据集的规模和多样性。这样可以让模型学习到更多的数据特征,提高模型的泛化能力。数据增强在图像、语音等领域应用较为广泛。
# 读取图像
image = cv2.imread('your_image.jpg')
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
# 数据增强操作
# 旋转
rotated = cv2.rotate(image, cv2.ROTATE_90_CLOCKWISE)
# 翻转
flipped = cv2.flip(image, 1)
# 缩放
scaled = cv2.resize(image, None, fx=0.5, fy=0.5)
# 平移
M = np.float32([[1, 0, 50], [0, 1, 50]])
translated = cv2.warpAffine(image, M, (image.shape[1], image.shape[0]))
# 添加噪声
noisy = image + np.random.normal(0, 20, image.shape).astype(np.uint8)
2.10
| 类 | 功能 | 说明 |
|---|---|---|
| StandardScaler | 无量纲化 | 标准化,基于特征矩阵的列,将特征值转换至服从标准正态分布 |
| MinMaxScaler | 无量纲化 | 区间缩放,基于最大最小值,将特征值转换到[0, 1]区间上 |
| Normalizer | 归一化 | 基于特征矩阵的行,将样本向量转换为“单位向量” |
| Binarizer | 二值化 | 基于给定阈值,将定量特征按阈值划分 |
| OneHotEncoder | 哑编码 | 将定性数据编码为定量数据 |
| Imputer | 缺失值计算 | 计算缺失值,缺失值可填充为均值等 |
| PolynomialFeatures | 多项式数据转换 | 多项式数据转换 |
| FunctionTransformer | 自定义单元数据转换 | 使用单变元的函数来转换数据 |
3 特征选择
数据预处理后,选择有意义的特征输入模型训练,从特征是否发散和与目标的相关性两方面考虑。特征选择方法分为 3 种:
3.1 Filter
按照发散性或者相关性对各个特征进行评分,设定阈值或者待选择阈值的个数选择特征。
- 方差选择法:计算各个特征的方差,根据阈值选择方差大于阈值的特征。
方差阈值法在特征选择中是一种简单且快速的方法,在以下几种情况下可以使用:
数据探索初期:在拿到一个新的数据集,对数据的特征分布和重要性还没有清晰认识时,方差阈值法可以作为一种初步的探索性方法,快速找出那些取值相对稳定(方差小)的特征,将其初步排除,从而聚焦于更有可能包含有效信息的特征。例如,在分析用户消费数据时,可能存在一些特征如用户注册时间的某一固定字段,其值基本不变,通过方差阈值法能迅速发现并排除这类特征。
对计算资源要求高的场景:当计算资源有限,无法承受复杂的特征选择方法带来的计算负担时,方差阈值法因其计算简单、复杂度低的特点,能够在不消耗过多资源的情况下对特征进行筛选。比如在一些嵌入式系统或移动设备上进行数据处理时,这种方法就比较适用。
作为预处理步骤:可以将方差阈值法作为特征选择的预处理步骤,先去除一部分明显不相关的特征,降低数据维度,然后再使用其他更复杂的特征选择方法进行进一步筛选,这样可以提高后续方法的效率。
使用 VarianceThreshold 类,代码如下:
from sklearn.feature_selection import VarianceThreshold
#方差选择法,返回值为特征选择后的数据
#参数threshold为方差的阈值
VarianceThreshold(threshold=3).fit_transform(iris.data)
- 相关系数法:计算各个特征对目标值的相关系数以及相关系数的 P 值。
线性关系明显时:当特征与目标值之间存在线性关系时,相关系数法能准确量化这种关系的强弱和方向。比如在研究身高与体重的关系时,二者通常呈现出较强的线性关系,相关系数法可以很好地反映它们之间的紧密程度。
需要考虑统计显著性时:相关系数的 P 值可以帮助判断相关系数是否具有统计显著性,从而确定特征与目标值之间的关系是真实存在还是偶然出现的。这在需要严谨判断特征有效性的场景中非常重要,例如在医学研究中,判断某种药物剂量与治疗效果之间的关系时,通过 P 值可以排除一些因随机因素导致的虚假相关性。
用 SelectKBest 类结合相关系数,代码如下:
from sklearn.feature_selection import SelectKBest
from scipy.stats import pearsonr
#选择K个最好的特征,返回选择特征后的数据
#第一个参数为计算评估特征是否好的函数,该函数输入特征矩阵和目标向量,输出二元组(评分,P值)的数组,数组第i项为第i个特征的评分和P值。在此定义为计算相关系数
#参数k为选择的特征个数
SelectKBest(lambda X, Y: array(map(lambda x:pearsonr(x, Y), X.T)).T, k=2).fit_transform(iris.data, iris.target)
- 卡方检验:检验定性自变量对定性因变量的相关性。
模型构建前筛选:在构建分类模型(如决策树、逻辑回归等)之前,如果有大量的定性特征,使用卡方检验可以对这些特征进行筛选,去除与因变量相关性不显著的特征,从而降低数据维度,减少模型的复杂度,提高模型的训练效率和泛化能力。例如在构建一个判断患者是否患有某种疾病(患病、未患病)的模型时,有患者的性别、民族、职业等多个定性特征,通过卡方检验可以筛选出对疾病判断有重要影响的特征,避免模型过拟合。
缺点
只能检测线性相关性:卡方检验只能判断两个定性变量之间是否存在关联,但无法准确描述这种关联的具体形式和方向,也不能检测变量之间的非线性关系。如果特征与目标变量之间存在复杂的非线性关系,卡方检验可能无法有效识别,从而导致重要特征的遗漏。
受样本量影响大:卡方检验的结果对样本量较为敏感。在样本量较小时,卡方检验的统计效力可能不足,容易出现假阴性结果,即实际上特征与目标变量有关联,但由于样本量不够而未能检测出来;而在样本量过大时,即使特征与目标变量之间的关联非常微弱,也可能被判定为显著相关,出现假阳性结果。
无法处理多分类变量的复杂关系:当定性自变量或因变量是多分类变量时,卡方检验只能给出总体的关联性判断,无法深入分析各个类别之间的具体关系。例如,对于一个有多个取值的特征变量,卡方检验不能明确指出每个取值与目标变量的不同类别之间的具体关联程度和差异。
局限性
仅考虑变量间的独立性:卡方检验的原假设是两个变量相互独立,它只能判断变量是否不独立,即是否存在某种关联,但对于变量之间的因果关系等更深入的问题无法给出答案。在实际的特征筛选中,我们可能不仅关心特征与目标变量是否相关,还希望了解它们之间的因果关系或潜在的作用机制,卡方检验在这方面存在局限性。
不能直接用于特征排序:卡方检验只能给出特征与目标变量是否相关的二元判断,不能直接对特征的重要性进行量化排序。如果需要根据特征的重要程度进行筛选和排序,卡方检验需要结合其他方法来实现,这增加了特征筛选过程的复杂性和工作量。
用 SelectKBest 类结合卡方检验,代码如下:
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2
#选择K个最好的特征,返回选择特征后的数据
SelectKBest(chi2, k=2).fit_transform(iris.data, iris.target)
- 互信息法:经典互信息评价定性自变量对定性因变量的相关性,处理定量数据用最大信息系数法。
经典互信息
探索变量关系:当研究需要深入了解定性自变量和定性因变量之间的依赖关系,尤其是在存在复杂的非线性关系时,经典互信息可以发挥作用。例如,在分析用户的性别、职业等定性特征与用户对不同类型产品的偏好这种定性因变量之间的关系时,互信息能够捕捉到它们之间的潜在联系,即使这种联系不是简单的线性关系。
特征筛选初筛:在数据挖掘和机器学习的特征工程中,作为初步的特征筛选方法,能快速从大量定性特征中找出与因变量有较高关联的特征。比如在构建一个文本分类模型时,对于文档的各种分类标签(定性自变量)和文档所属的主题类别(定性因变量),可以用经典互信息来筛选出对主题分类有重要作用的标签特征。
最大信息系数法
处理复杂关系:当面对定量数据,且变量之间可能存在复杂的非线性关系时,最大信息系数法能够有效度量变量间的相关性。例如,在研究城市的经济发展指标(如 GDP、人口密度等定量特征)与环境污染程度(如空气质量指数等定量因变量)之间的关系时,即使这些关系不是简单的直线关系,最大信息系数法也能捕捉到它们之间的内在联系。
数据探索分析:在对定量数据集进行探索性分析时,最大信息系数法可以帮助发现变量之间的潜在关联,为后续的建模和分析提供方向。比如在分析气象数据中的温度、湿度、风速等定量特征与农作物产量这一定量因变量的关系时,通过最大信息系数法可以找出对产量影响较大的气象因素。
用 SelectKBest 类结合最大信息系数法,代码如下:
from sklearn.feature_selection import SelectKBest
from minepy import MINE
#由于MINE的设计不是函数式的,定义mic方法将其为函数式的,返回一个二元组,二元组的第2项设置成固定的P值0.5
def mic(x, y):
m = MINE()
m.compute_score(x, y)
return (m.mic(), 0.5)
#选择K个最好的特征,返回特征选择后的数据
SelectKBest(lambda X, Y: array(map(lambda x:mic(x, Y), X.T)).T, k=2).fit_transform(iris.data, iris.target)
3.2 Wrapper
根据目标函数(通常是预测效果评分),每次选择若干特征,或者排除若干特征。
效果
较好的预测性能:Wrapper 方法通过直接优化目标函数来选择特征,能够找到与目标变量具有高度相关性的特征子集,从而提高模型的预测准确性和泛化能力。
考虑特征间的相互作用:该方法在评估特征子集时,会考虑特征之间的相互影响。它可以识别出那些单独作用不明显,但与其他特征组合后能显著提升模型性能的特征,有助于挖掘数据中的复杂关系。
优点
针对性强:针对具体的学习算法和目标函数进行特征选择,能够最大程度地满足特定模型的需求,使选择出的特征子集在该模型上表现最佳。
无需领域知识:不需要对数据的领域知识有深入了解,完全基于数据驱动的方式进行特征选择,减少了人为因素的干扰,尤其适用于对数据内在结构和关系不太清楚的情况。
自动化程度高:整个特征选择过程可以自动进行,无需手动干预,节省了大量的时间和精力,提高了数据分析的效率。
缺点
计算成本高:Wrapper 方法需要对大量的特征子集进行评估,这涉及到多次训练和测试模型,计算量非常大。特别是当特征数量较多时,计算成本会显著增加,导致算法运行时间长,对于大规模数据处理较为困难。
容易过拟合:由于 Wrapper 方法是基于特定数据集和模型进行特征选择的,过于依赖训练数据,容易选择出一些仅在训练数据上表现良好,但在测试数据或新数据上泛化能力较差的特征,从而导致模型过拟合。
局限性
模型依赖性:选择出的特征子集是针对特定的模型和目标函数而言的,不同的模型或目标函数可能会得到不同的特征子集。因此,Wrapper 方法缺乏通用性,在更换模型或任务时,可能需要重新进行特征选择。
特征空间探索不全面:尽管 Wrapper 方法会尝试不同的特征组合,但在高维特征空间中,它可能无法穷举所有可能的子集,有可能错过一些潜在的最优特征组合。
优化提升方式
采用启发式搜索策略:为了降低计算成本,可以采用启发式搜索算法,如贪婪搜索、模拟退火、遗传算法等,来减少需要评估的特征子集数量。这些算法能够在较短的时间内找到近似最优的特征子集,提高特征选择的效率。
结合交叉验证:为了缓解过拟合问题,可以在特征选择过程中结合交叉验证技术。通过将数据集划分为多个子集,在不同的子集上进行训练和验证,更全面地评估特征子集的性能,选择出具有较好泛化能力的特征。
与其他特征选择方法结合:可以将 Wrapper 方法与 Filter 方法或 Embedded 方法相结合。先使用 Filter 方法进行初步的特征筛选,去除一些明显不相关的特征,缩小特征空间,然后再使用 Wrapper 方法进行精细的特征选择,这样可以在一定程度上平衡计算成本和特征选择效果。
使用并行计算和分布式计算:利用并行计算框架或分布式计算平台,如多线程编程、GPU 加速、Hadoop 等,将特征选择任务并行化或分布到多个计算节点上进行处理,从而加快计算速度,提高算法的可扩展性,以应对大规模数据和高维特征空间的挑战。
递归特征消除法使用 RFE 类,代码如下:
from sklearn.feature_selection import RFE
from sklearn.linear_model import LogisticRegression
#递归特征消除法,返回特征选择后的数据
#参数estimator为基模型
#参数n_features_to_select为选择的特征个数
RFE(estimator=LogisticRegression(), n_features_to_select=2).fit_transform(iris.data, iris.target)
3.3 Embedded
先使用某些机器学习的算法和模型进行训练,得到各个特征的权值系数,根据系数从大到小选择特征。
优点
计算效率高:与 Wrapper 方法相比,Embedded 方法不需要对大量的特征子集进行单独的训练和评估,而是在模型训练的过程中同时完成特征选择,大大减少了计算量,提高了特征筛选的效率,尤其适用于大规模数据集和高维特征空间。
模型性能较好:因为选择的特征是基于模型的优化目标来确定的,所以可以直接提升模型的性能,避免了选择出的特征与模型不匹配导致的性能下降问题。
无需额外的特征评估指标:不需要像 Filter 方法那样依赖于一些事先定义好的、与模型无关的特征评估指标,而是直接根据模型训练得到的特征权值系数来进行特征选择,更加符合实际的模型应用场景。
缺点
模型依赖性强:Embedded 方法选择的特征是针对特定的模型和算法而言的,不同的模型或同一模型的不同参数设置可能会导致不同的特征选择结果。因此,其通用性较差,当需要更换模型或调整模型参数时,可能需要重新进行特征选择。
难以解释特征重要性:虽然可以得到特征的权值系数,但这些系数的含义可能并不直观,尤其是对于一些复杂的模型,如深度学习模型,很难直接从系数中解释每个特征对模型输出的具体贡献和重要性,缺乏可解释性。
局限性
局部最优解问题:在模型训练过程中,特征选择可能会陷入局部最优解,即找到的特征子集只是在当前的训练过程和参数设置下是最优的,但不一定是全局最优的特征组合。这可能导致错过一些更优的特征选择方案,影响模型的最终性能。
对数据噪声敏感:如果数据中存在噪声或异常值,可能会影响模型训练得到的特征权值系数,进而影响特征选择的结果。噪声数据可能会使一些不重要的特征获得较高的权值,而真正重要的特征权值被低估,导致特征选择出现偏差。
优化提升方式
使用集成学习方法:可以将多个不同的 Embedded 模型进行集成,例如通过 Bagging 或 Boosting 等技术,综合多个模型的特征选择结果,以减少模型依赖性和局部最优解问题的影响。这样可以提高特征选择的稳定性和准确性,得到更具代表性的特征子集。
结合模型解释技术:为了提高特征重要性的可解释性,可以结合一些模型解释技术,如 LIME(Local Interpretable Model - Agnostic Explanations)、SHAP(SHapley Additive exPlanations)等。这些技术可以帮助解释每个特征对模型预测结果的贡献程度,使特征选择结果更易于理解和解释。
数据预处理和清洗:在使用 Embedded 方法之前,对数据进行充分的预处理和清洗,去除噪声和异常值,以减少它们对特征权值系数的影响。同时,可以对数据进行标准化或归一化处理,使不同特征具有相同的尺度,避免因特征尺度差异导致的权值偏差。
采用交叉验证和模型选择:通过交叉验证来评估不同模型和参数设置下的特征选择效果,选择出在验证集上表现最佳的模型和对应的特征子集。这样可以在一定程度上避免模型过拟合和局部最优解问题,提高特征选择的泛化能力。此外,还可以尝试不同类型的模型和算法,比较它们的特征选择结果,选择最适合数据和任务的模型及特征子集。
- 基于惩罚项的特征选择法:使用带惩罚项的基模型,可筛选特征和降维。结合 SelectFromModel 类与带 L1 惩罚项的逻辑回归模型,代码如下:
from sklearn.feature_selection import SelectFromModel
from sklearn.linear_model import LogisticRegression
#带L1惩罚项的逻辑回归作为基模型的特征选择
SelectFromModel(LogisticRegression(penalty="l1", C=0.1)).fit_transform(iris.data, iris.target)
结合 L1 以及 L2 惩罚项的逻辑回归模型,代码如下:
from sklearn.feature_selection import SelectFromModel
#带L1和L2惩罚项的逻辑回归作为基模型的特征选择
#参数threshold为权值系数之差的阈值
SelectFromModel(LR(threshold=0.5, C=0.1)).fit_transform(iris.data, iris.target)
- 基于树模型的特征选择法:结合 SelectFromModel 类与 GBDT 模型,代码如下:
from sklearn.feature_selection import SelectFromModel
from sklearn.ensemble import GradientBoostingClassifier
#GBDT作为基模型的特征选择
SelectFromModel(GradientBoostingClassifier()).fit_transform(iris.data, iris.target)
3.4 回顾
| 类 | 所属方式 | 说明 |
|---|---|---|
| VarianceThreshold | Filter | 方差选择法 |
| SelectKBest | Filter | 可选关联系数、卡方校验、最大信息系数作为得分计算的方法 |
| RFE | Wrapper | 递归地训练基模型,将权值系数较小的特征从特征集合中消除 |
| SelectFromModel | Embedded | 训练基模型,选择权值系数较高的特征 |
4 降维
特征选择后可能因特征矩阵过大导致计算量大等问题,常见降维方法有主成分分析法(PCA)和线性判别分析(LDA)。PCA 是无监督降维方法,让映射后的样本具有最大的发散性;LDA 是有监督降维方法,让映射后的样本有最好的分类性能。
4.1 主成分分析法(PCA)
使用 decomposition 库的 PCA 类,
优点
无监督学习:不需要使用标签信息,仅基于数据本身的结构进行特征提取和降维,适用于各种类型的数据,包括没有类别标签的数据集。
能够去除噪声和冗余:通过将数据投影到主成分空间,可以去除数据中的噪声和冗余信息,使得数据更加紧凑和易于处理,同时保留了数据的主要特征。
可解释性强:主成分是原始特征的线性组合,通过分析主成分与原始特征之间的系数关系,可以一定程度上解释每个主成分所代表的含义,帮助理解数据的内在结构。
缺点
可能丢失重要信息:在降维过程中,由于只保留了部分主成分,可能会丢失一些对特定任务或模型来说重要的信息,尤其是当数据中的一些重要特征与主成分方向不一致时。
对数据分布敏感:PCA 假设数据是服从高斯分布的,如果数据分布不符合这一假设,其降维效果可能会受到影响,甚至可能导致错误的结果。
不考虑类别信息:由于是无监督学习方法,PCA 在特征提取过程中没有考虑数据的类别信息,可能无法很好地捕捉到与分类任务相关的特征。
局限性
难以确定主成分个数:确定保留多少个主成分是一个相对主观的过程,通常需要根据经验或一些指标(如累计方差贡献率)来判断,但这些方法并不一定能准确地确定最适合特定任务的主成分个数。
线性变换的局限性:PCA 只能捕捉到数据中的线性关系,对于非线性关系的处理能力有限。如果数据中存在复杂的非线性结构,PCA 可能无法很好地提取特征。
优化提升方式
结合其他方法确定主成分个数:除了常用的累计方差贡献率等指标外,可以结合交叉验证、信息准则(如 AIC、BIC)等方法来更准确地确定主成分个数,以平衡模型的复杂度和性能。
核主成分分析(KPCA):为了处理非线性数据,可以采用核主成分分析方法。KPCA 通过将数据映射到高维特征空间,然后在高维空间中进行主成分分析,从而能够捕捉到数据中的非线性关系。
与监督学习结合:将 PCA 与监督学习算法结合使用,例如在分类任务中,先使用 PCA 进行降维,然后将降维后的数据作为输入,训练分类模型。通过这种方式,可以在一定程度上弥补 PCA 不考虑类别信息的不足。
代码如下:
from sklearn.decomposition import PCA
#主成分分析法,返回降维后的数据
#参数n_components为主成分数目
PCA(n_components=2).fit_transform(iris.data)
4.2 线性判别分析法(LDA)
优点
利用类别信息:作为有监督的方法,LDA 充分利用了数据的类别信息,能够找到与分类任务最相关的特征,因此在分类问题中通常能够取得较好的特征筛选效果,有助于提高分类模型的准确性。
对线性可分数据效果好:对于线性可分的数据,LDA 能够找到最优的线性投影方向,将不同类别的数据完全分开,从而实现很好的降维和特征筛选效果。
降维效果明确:LDA 的降维目标明确,即最大化类间差异和最小化类内差异,其降维后的特征空间具有明确的物理意义,即最有利于分类的方向。
缺点
对数据分布要求严格:LDA 假设各个类别的数据都服从高斯分布,并且各个类别的协方差矩阵相同。如果数据不满足这些假设,LDA 的性能可能会受到影响。
易过拟合:在小样本情况下,LDA 计算类内和类间协方差矩阵时可能会出现估计不准确的情况,导致过拟合现象。此时,降维后的特征可能在训练集上表现很好,但在测试集上泛化能力较差。
只适用于分类任务:LDA 是专门为分类任务设计的降维方法,对于其他非分类任务,如回归、聚类等,LDA 并不适用。
局限性
特征空间维度限制:LDA 降维后的特征空间维度最多为类别数减 1。如果类别数较少,可能无法实现较大程度的降维,限制了其在一些高维数据场景下的应用。
对非线性分类问题效果有限:LDA 是基于线性投影的方法,对于非线性分类问题,它可能无法找到合适的投影方向来实现有效的类别分离。在这种情况下,需要结合其他非线性处理方法或使用非线性版本的 LDA(如核 LDA)。
优化提升方式
采用正则化方法:为了克服小样本情况下的过拟合问题,可以采用正则化的 LDA,如在协方差矩阵估计中加入正则化项,或者采用收缩估计方法来改进协方差矩阵的估计,提高模型的泛化能力。
核线性判别分析(KLDA):对于非线性分类问题,可以使用核线性判别分析方法。KLDA 通过将数据映射到高维核空间,然后在核空间中进行线性判别分析,从而能够处理非线性分类问题,提高特征筛选的效果。
结合其他特征工程方法:可以将 LDA 与其他特征工程方法结合使用,如特征选择、特征提取等。例如,先使用一些无监督的特征选择方法去除一些明显无关的特征,然后再使用 LDA 进行降维和特征筛选,以进一步提高特征的质量和分类性能。
使用 lda 库的 LDA 类,代码如下:
from sklearn.lda import LDA
#线性判别分析法,返回降维后的数据
#参数n_components为降维后的维数
LDA(n_components=2).fit_transform(iris.data, iris.target)
4.3 回顾
| 库 | 类 | 说明 |
|---|---|---|
| decomposition | PCA | 主成分分析法 |
| lda | LDA | 线性判别分析法 |
更多推荐



所有评论(0)