【机器学习【7】】数据预处理:数据准备、数据转换、数据输出
文章目录
- 一、 数据准备
- 1、加载数据并初步检查
- 2、处理缺失值
- 3、剔除无效数据
- 4、去除冗余维度(特征选择)
- 4.1、构建监督学习数据
- 4.2、删除方差为0的特征
- 4.3、删除与目标变量相关性低的特征
- 4.4、使用SelectKBest选择最相关的特征
- 二、 数据转换
- 1、概述
- 1.1、 什么是“量纲影响”?
- 1.2、统一的数据转换入口:fit_transform
- 2、 常用数据预处理方法
- 2.1. Min-Max Scaling(最小-最大缩放)
- 2.2. Z-Score标准化
- 2.3. 正态化(Normalizer)
- 2.4. 二值化
- 三. 数据输出
本文学习目标
掌握机器学习项目中 “数据预处理” 三大步骤(数据准备、数据转换、数据输出),学会处理缺失值、无效数据与冗余维度,并能够利用 scikit-learn 对数据进行尺度调整、正态化、标准化及二值化,从而为后续模型训练奠定高质量数据基础。
一、 数据准备
本章通过加载数据、处理缺失值、剔除无效数据、删除方差为0特征、基于相关性筛选和SelectKBest自动选择,最终从原始7个特征筛选出2个最相关特征(id、age),完成了从数据清洗到特征选择的完整数据准备流程。
1、加载数据并初步检查
import pandas as pd
df = pd.read_csv('data.csv')
print("原始数据:")
print(df)
print(df.info())
原始数据:id age gender score height weight status
0 1 23.0 M 85.0 175 70 已完成
1 2 21.0 F 90.0 160 55 已完成
2 3 22.0 M 78.0 180 80 进行中
3 4 20.0 F 95.0 158 50 已完成
4 5 NaN M 120.0 170 68 已取消
5 6 25.0 F NaN 165 60 已完成
6 7 19.0 M 70.0 172 65 已完成
7 8 24.0 F 105.0 162 54 进行中
8 9 130.0 M 82.0 178 75 已完成
9 10 23.0 F 85.0 160 55 已完成
10 11 22.0 M 88.0 300 75 已完成
11 12 -5.0 F 92.0 150 45 已完成
12 13 28.0 M 110.0 180 200 已完成
13 14 30.0 F 99.0 165 60 已完成
14 15 27.0 M 101.0 170 68 已完成
15 16 26.0 F NaN 165 60 已完成
16 17 23.0 M 85.0 175 70 已完成
17 18 21.0 F NaN 160 55 已完成
18 19 22.0 M 78.0 180 80 进行中
19 20 20.0 F 95.0 158 50 已完成
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 20 entries, 0 to 19
Data columns (total 7 columns):# Column Non-Null Count Dtype
--- ------ -------------- ----- 0 id 20 non-null int64 1 age 19 non-null float642 gender 20 non-null object 3 score 17 non-null float644 height 20 non-null int64 5 weight 20 non-null int64 6 status 20 non-null object
dtypes: float64(2), int64(3), object(2)
memory usage: 1.2+ KB
None
age和score有些空值。
2、处理缺失值
常见做法:
- 删除含缺失值的行
- 用均值/中位数/众数/指定值填充
代码示例:
# 删除含缺失值的行
df_clean = df.dropna()# # 用0填充所有缺失值
# df_filled = df.fillna(0)
#
# # 用每列均值填充
# df_mean = df.fillna(df.mean(numeric_only=True))
#
# # 针对某一列用中位数填充
# df['age'] = df['age'].fillna(df['age'].median())# 查看前几行,确认格式和字段
print(df_clean.head())
# 查看字段类型和缺失情况
print(df_clean.info())
去掉了含有空值的行
id age gender score height weight status
0 1 23.0 M 85.0 175 70 已完成
1 2 21.0 F 90.0 160 55 已完成
2 3 22.0 M 78.0 180 80 进行中
3 4 20.0 F 95.0 158 50 已完成
6 7 19.0 M 70.0 172 65 已完成
<class 'pandas.core.frame.DataFrame'>
Index: 16 entries, 0 to 19
Data columns (total 7 columns):# Column Non-Null Count Dtype
--- ------ -------------- ----- 0 id 16 non-null int64 1 age 16 non-null float642 gender 16 non-null object 3 score 16 non-null float644 height 16 non-null int64 5 weight 16 non-null int64 6 status 16 non-null object
dtypes: float64(2), int64(3), object(2)
memory usage: 1.0+ KB
None
3、剔除无效数据
常见做法:
- 过滤掉不合理的数值(如年龄为负、成绩大于100等)
- 只保留业务需要的记录
代码示例:
# 只保留年龄在0~120之间的记录
df_valid = df[(df['age'] >= 0) & (df['age'] <= 120)]# 只保留成绩在0~100之间的记录
df_valid = df_valid[(df_valid['score'] >= 0) & (df_valid['score'] <= 100)]# 只保留状态为“已完成”的订单
df_valid = df_valid[df_valid['status'] == '已完成']# 查看前几行,确认格式和字段
print(df_valid.head())
筛选符合要求的数据
id age gender score height weight status
0 1 23.0 M 85.0 175 70 已完成
1 2 21.0 F 90.0 160 55 已完成
3 4 20.0 F 95.0 158 50 已完成
6 7 19.0 M 70.0 172 65 已完成
9 10 23.0 F 85.0 160 55 已完成
4、去除冗余维度(特征选择)
常见做法:
- 删除方差为0的特征(即所有值都一样)
- 删除与目标变量无关或高度相关的特征
- 用特征选择算法自动筛选
4.1、构建监督学习数据
准备机器学习模型的输入特征(X)和目标变量(y)
# 作用:从数据集中分离出输入特征(X)。axis=1:按列删除(axis=0是按行删除)
X = df_valid.drop(['score', 'gender', 'status'], axis=1)
# 作用:提取目标变量(y)。选择 'score' 列作为预测目标
# 这是监督学习中的标签(label)
y = df_valid['score']
print("\n数值型特征X:")
print(X)
print("\n目标变量y:")
print(y)
数值型特征X:id age height weight
0 1 23.0 175 70
1 2 21.0 160 55
3 4 20.0 158 50
6 7 19.0 172 65
9 10 23.0 160 55
10 11 22.0 300 75
13 14 30.0 165 60
16 17 23.0 175 70
19 20 20.0 158 50目标变量y:
0 85.0
1 90.0
3 95.0
6 70.0
9 85.0
10 88.0
13 99.0
16 85.0
19 95.0
Name: score, dtype: float64
4.2、删除方差为0的特征
删除方差为0特征的作用:
提升计算效率:移除无变化特征,减少模型训练的计算开销
避免特征干扰:防止无信息特征对模型学习造成负面影响
保证特征质量:确保每个保留的特征都具有区分样本的能力
from sklearn.feature_selection import VarianceThreshold
# 创建方差阈值选择器,设置阈值为0.0。
# threshold=0.0:删除方差为0的特征(即所有值都相同的列)
# 也可以设置其他阈值,如 threshold=0.1 删除方差小于0.1的特征
selector = VarianceThreshold(threshold=0.0)# 对特征矩阵X进行方差阈值选择。
# fit_transform():先拟合(计算每列方差),再转换(删除低方差列)
# 返回的是NumPy数组,列名信息丢失
X_var = selector.fit_transform(X)
# 获取被保留的列名。
# selector.get_support():返回布尔数组,True表示保留的列
# indices=True:返回索引而不是布尔值
# X.columns[...]:根据索引获取对应的列名
selected_columns = X.columns[selector.get_support(indices=True)]
# 将NumPy数组转换回pandas DataFrame,并恢复列名。
X_var = pd.DataFrame(X_var, columns=selected_columns)
print("\n删除方差为0特征后的X:")
print(X_var)
删除方差为0特征后的X:id age height weight
0 1.0 23.0 175.0 70.0
1 2.0 21.0 160.0 55.0
2 4.0 20.0 158.0 50.0
3 7.0 19.0 172.0 65.0
4 10.0 23.0 160.0 55.0
5 11.0 22.0 300.0 75.0
6 14.0 30.0 165.0 60.0
7 17.0 23.0 175.0 70.0
8 20.0 20.0 158.0 50.0
4.3、删除与目标变量相关性低的特征
删除与目标变量相关性低的特征能够:
- 提升模型性能:移除对预测目标贡献很小的特征,让模型专注于真正重要的变量
- 降低过拟合风险:减少噪声特征,避免模型学习到无关的虚假模式
- 提高训练效率:减少特征维度,加快模型训练和预测速度
- 增强可解释性:只保留有意义的特征,使模型结果更容易理解和解释
# 作用:计算特征与目标变量的相关性矩阵。
# pd.concat([X_var, y], axis=1):将特征矩阵X和目标变量y合并
# .corr():计算皮尔逊相关系数矩阵
cor_matrix = pd.concat([X_var, y], axis=1).corr()
print("\n相关性矩阵:")
print(cor_matrix)# 作用:找出与目标变量'score'相关性很低的特征。
# 获取目标变量'score'与其他特征的相关性,并筛选出小于0.3的特征
low_corr = cor_matrix['score'].abs() < 0.3
print("===========")
print(low_corr)
# 作用:获取需要删除的列名。
# 这是布尔索引,只保留值为 True 的行:
drop_cols = low_corr[low_corr].index
X_corr = X_var.drop(columns=drop_cols)print("\n删除相关性低特征后的X:")
print(X_corr)
相关性矩阵:id age height weight score
id 1.000000 0.233823 0.069203 -0.031490 -0.674926
age 0.233823 1.000000 -0.016136 0.173211 -0.999220
height 0.069203 -0.016136 1.000000 0.681087 0.204757
weight -0.031490 0.173211 0.681087 1.000000 0.119523
score -0.674926 -0.999220 0.204757 0.119523 1.000000
===========
id False
age False
height True
weight True
score False
Name: score, dtype: bool删除相关性低特征后的X:id age
0 1.0 23.0
1 2.0 21.0
2 4.0 20.0
3 7.0 19.0
4 10.0 23.0
5 11.0 22.0
6 14.0 30.0
7 17.0 23.0
8 20.0 20.0
4.4、使用SelectKBest选择最相关的特征
SelectKBest的作用:基于统计检验 自动选择与目标变量最相关的k个特征,通过F统计量评估特征重要性并保留得分最高的特征,实现自动化的特征筛选。
from sklearn.feature_selection import SelectKBest, f_regression
# 创建特征选择器
# score_func=f_regression:使用F统计量作为评分函数
# k=min(3, X_corr.shape[1]):选择前k个特征,最多选3个,不超过现有特征数
# X_corr.shape[1]:当前特征矩阵的列数
selector = SelectKBest(score_func=f_regression, k=min(3, X_corr.shape[1]))
# 执行特征选择
# fit_transform():先拟合(计算F统计量),再转换(选择特征)
# X_corr:输入特征矩阵、y:目标变量、 返回NumPy数组,只包含选中的特征
X_best = selector.fit_transform(X_corr, y)
# 获取被选中特征的列名
# selector.get_support():返回布尔数组,True表示被选中的特征
# indices=True:返回索引而不是布尔值
# X_corr.columns[...]:根据索引获取对应的列名
best_columns = X_corr.columns[selector.get_support(indices=True)]
print("\nSelectKBest筛选后的特征:", list(best_columns))
print(pd.DataFrame(X_best, columns=best_columns))
SelectKBest筛选后的特征: ['id', 'age']id age
0 1.0 23.0
1 2.0 21.0
2 4.0 20.0
3 7.0 19.0
4 10.0 23.0
5 11.0 22.0
6 14.0 30.0
7 17.0 23.0
8 20.0 20.0
二、 数据转换
1、概述
在机器学习项目中,原始数据往往存在不同的取值范围、单位(量纲)、分布形态或异常点。如果不加处理,模型容易受到“量纲影响”——即某些数值范围大的特征主导模型训练,导致结果失真。因此,科学的数据预处理是提升模型效果的关键第一步。
1.1、 什么是“量纲影响”?
量纲,也叫“单位”或“尺度”,指的是特征的取值范围和单位。例如,身高(cm)和体重(kg)在同一个数据集中,数值大小和单位完全不同。
量纲影响指的是:如果不同特征的数值范围差异很大,模型在计算距离或权重时,数值大的特征会主导结果,导致模型偏向这些特征,影响学习效果。
1.2、统一的数据转换入口:fit_transform
scikit-learn 为各种数据转换器(如缩放、标准化、正态化、二值化等)提供了统一的 fit_transform
接口。它将“拟合参数”和“数据转换”合二为一,极大简化了数据预处理流程。
fit(X)
:计算并存储转换所需的统计量(如最大/最小值、均值、方差等)transform(X)
:用已存储的统计量对数据进行转换fit_transform(X)
:一步完成拟合和转换,推荐常用
拟合参数,指的是通过对训练数据进行分析、计算得到的、用于后续数据转换或建模的统计量或系数。
以数据预处理为例:
- MinMaxScaler 的拟合参数:每一列的最小值和最大值(fit时计算,transform时用来缩放数据)。
- StandardScaler 的拟合参数:每一列的均值和标准差(fit时计算,transform时用来标准化数据)。
2、 常用数据预处理方法
2.1. Min-Max Scaling(最小-最大缩放)
- 公式:Xscaled=(X−Xmin)/(Xmax−Xmin)X_{scaled} = (X - X_{min}) / (X_{max} - X_{min})Xscaled=(X−Xmin)/(Xmax−Xmin)
- 作用:将特征缩放到指定区间(如0~1),消除不同量纲带来的影响。
- 适用场景:需要将数据限制在特定范围,如神经网络输入
# 1. Min-Max Scaling(调整数据尺度)
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler(feature_range=(0, 1))
X_scaled = scaler.fit_transform(X_best)
print("1. Min-Max Scaling(0-1缩放):")
print("作用:将特征缩放到指定区间(0~1),消除不同量纲带来的影响")
print("适用场景:需要将数据限制在特定范围,如神经网络输入")
print("结果:")
print(pd.DataFrame(X_scaled, columns=best_columns))
print("\n" + "="*50)
1. Min-Max Scaling(0-1缩放):
作用:将特征缩放到指定区间(0~1),消除不同量纲带来的影响
适用场景:需要将数据限制在特定范围,如神经网络输入
结果:id age
0 0.000000 0.363636
1 0.052632 0.181818
2 0.157895 0.090909
3 0.315789 0.000000
4 0.473684 0.363636
5 0.526316 0.272727
6 0.684211 1.000000
7 0.842105 0.363636
8 1.000000 0.090909==================================================
2.2. Z-Score标准化
- 公式:Xstandardized=(X−μ)/σX_{standardized} = (X - μ) / σXstandardized=(X−μ)/σ
- 作用:将特征转换为均值为0、方差为1的分布,适合大多数机器学习算法。
- 适用场景:线性回归、SVM、神经网络等需要标准化特征的算法
# 2. Z-Score标准化
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_standardized = scaler.fit_transform(X_best)
print("2. Z-Score标准化:")
print("作用:将特征转换为均值为0、方差为1的分布,适合大多数机器学习算法")
print("适用场景:线性回归、SVM、神经网络等需要标准化特征的算法")
print("结果:")
print(pd.DataFrame(X_standardized, columns=best_columns))
print("\n" + "="*50)
2. Z-Score标准化:结果:id age
0 -1.363740 0.218218
1 -1.204342 -0.436436
2 -0.885545 -0.763763
3 -0.407351 -1.091089
4 0.070844 0.218218
5 0.230242 -0.109109
6 0.708436 2.509506
7 1.186631 0.218218
8 1.664825 -0.763763==================================================
2.3. 正态化(Normalizer)
- 公式:Xnormalized=X/∣∣X∣∣X_{normalized} = X / ||X||Xnormalized=X/∣∣X∣∣
- 作用:将每个样本缩放为单位范数,常用于文本特征或距离计算场景。
- 适用场景:文本分类、聚类算法、需要计算样本间距离的场景,但注意可能丢失原始数据的比例信息。
# 3. 正态化(Normalizer)
from sklearn.preprocessing import Normalizer
normalizer = Normalizer(norm='l2')
X_normalized = normalizer.fit_transform(X_best)
print("3. 正态化(L2范数):")
print("作用:将每个样本缩放为单位范数,常用于文本特征或距离计算场景")
print("适用场景:文本分类、聚类算法、需要计算样本间距离的场景")
print("结果:")
print(pd.DataFrame(X_normalized, columns=best_columns))
print("\n" + "="*50)
3. 正态化(L2范数):
作用:将每个样本缩放为单位范数,常用于文本特征或距离计算场景
适用场景:文本分类、聚类算法、需要计算样本间距离的场景
结果:id age
0 0.043437 0.999056
1 0.094809 0.995495
2 0.196116 0.980581
3 0.345705 0.938343
4 0.398726 0.917070
5 0.447214 0.894427
6 0.422885 0.906183
7 0.594391 0.804176
8 0.707107 0.707107==================================================
2.4. 二值化
- 公式:XbinaryX_{binary}Xbinary = 1 if X > threshold else 0
- 作用:按阈值将特征转换为0或1,适合需要离散特征的模型。
- 特点:简化数据,适合某些算法,但会丢失大量信息
- 适用场景:朴素贝叶斯、决策树等需要离散特征的算法
# 4. 二值化
from sklearn.preprocessing import Binarizer
# 创建一个二值化转换器,设置阈值为0.5。
# 含义:对于每个特征值,如果大于0.5则转换为1,否则为0。
binarizer = Binarizer(threshold=0.5)
X_binary = binarizer.fit_transform(X_normalized)
print("4. 二值化:")
print("作用:按阈值将特征转换为0或1,适合需要离散特征的模型")
print("适用场景:朴素贝叶斯、决策树等需要离散特征的算法")
print("结果:")
print(pd.DataFrame(X_binary, columns=best_columns))
print("\n" + "="*50)
4. 二值化:
作用:按阈值将特征转换为0或1,适合需要离散特征的模型
适用场景:朴素贝叶斯、决策树等需要离散特征的算法
结果:id age
0 0.0 1.0
1 0.0 1.0
2 0.0 1.0
3 0.0 1.0
4 0.0 1.0
5 0.0 1.0
6 0.0 1.0
7 1.0 1.0
8 1.0 1.0==================================================
三. 数据输出
将处理后的数据保存为NumPy数组或pandas DataFrame,供下游模型使用。可通过pd.to_csv('processed.csv', index=False)
导出到文件系统。
df_out.to_csv('processed.csv', index=False)
# index=False 表示不保存行索引到文件df_loaded = pd.read_csv('processed.csv')
print(df_loaded.head())
id age score
0 1.0 23.0 85.0
1 2.0 21.0 90.0
2 4.0 20.0 95.0
3 7.0 19.0 70.0
4 10.0 23.0 85.0
合理的数据预处理能够显著提升多数机器学习算法的准确度与收敛速度。实验表明,在相同算法下,经过标准化或正态化的数据往往获得更稳定、更优的评估指标(如准确率、AUC)。