2(1).数据预处理方法
(一)数值特征
数值特征(numerical feature),可以是连续的(continuous),也可以是离散的(discrete),一般表示为一个实数值。
例:年龄、价格、身高、体重、测量数据。
不同算法对于数值特征的处理要求不同。下文中的一些数据处理方法,因为是针对某一特征列的单调变换,所以不会对基于决策树的算法(随机森林、gbdt)产生任何影响。一般而言,决策树类算法不需要预处理数值特征。
一、数值特征缩放
适用场景:
- 基于距离的算法
- 算法用到了梯度下降
1.Rescaling(最小最大标准化/归一化,不免疫outlier)
(1)将训练集中某一列数值特征(假设是第i列)的值缩放到0和1之间
适用场景:
- 如果对输出结果范围有要求,用归一化
- 如果数据较为稳定,不存在极端的最大最小值,用归一化
缺点:这种方法有个缺陷就是当有新数据加入时,可能导致max和min的变化,需要重新定义。
参考:
1 2 3 4 5 6 7 | from sklearn.preprocessing import MinMaxScaler #初始化一个scaler对象 scaler = MinMaxScaler() #调用scaler的fit_transform方法,把我们要处理的列作为参数传进去 data[ '标准化后的A列数据' ] = scaler.fit_transform(data[ 'A列数据' ]) |
(2)要重新缩放任意值集[a,b]之间的范围,公式将变为:
a,b是最小-最大值
2.Mean normalization(均值归一化,不免疫outlier)
将训练集中某一列数值特征(假设是第i列)的值缩放到[-1,1]零均值之间
适用场景:
- 矩阵分解
参考:
3.Standardization(标准化/z-score标准化,不免疫outlier)
将训练集中某一列数值特征(假设是第i列)的值缩放成均值为0,方差为1的状态。
适用场景:
- SVM、LR、神经网络
- 如果数据存在异常值和较多噪音,用标准化,可以间接通过中心化避免异常值和极端值的影响
参考:
- sklearn.preprocessing.scale
- sklearn.preprocessing.StandardScaler(两个基本一样,但一般用这个就ok了,比较高级、方法比较齐全)
1 2 3 4 5 6 7 8 9 10 | # 方法1 from sklearn.proprocessing import scale df_train[ 'feature' ] = scale(df_train[ 'feature' ]) # 方法2 # 一般会把train和test集放在一起做标准化,或者在train集上做标准化后,用同样的标准化器去标准化test集,此时可以用scaler from sklearn.proprocessing import StandardScaler scaler = StandardScaler().fit(df_train) scaler.transform(df_train) scaler.transform(df_test) |
4.scaling to unit length(缩放到单位长度,不免疫outlier)
在机器学习中广泛使用的另一种选择是缩放特征向量的分量,使得完整向量具有长度1。这通常意味着将每个组件除以向量的欧几里德长度:
使用场景:
- 在一些应用中(例如直方图特征),使用特征向量的L1范数(即曼哈顿距离,城市块长度或出租车几何)可能更实际。如果在以下学习步骤中将标量度量用作距离度量,则这尤其重要。
参考:
- sklearn.preprocessing.normalize(X, norm=’l2’, axis=1, copy=True, return_norm=False)
- sklearn.preprocessing.Normalizer(norm=’l2’, copy=True)
1 | sklearn.preprocessing.Normalizer(norm = ’l2’, copy = True ) |
参数:
- norm:'l1','l2',或'max',可选,默认='l2'
- copy:boolean,可选,默认=True
5.绝对值标准化(不免疫outlier)
专为稀疏数据而生。将每个要素缩放到[-1,1]范围,它不会移动/居中数据,因此不会破坏任何稀疏性。该估计器单独地缩放每个特征,使得训练集中的每个特征的最大绝对值将是1.0。该缩放器也可以应用于稀疏CSR或CSC矩阵
参考:
- sklearn.preprocessing.maxabs_scale(X, axis=0, copy=True)
- sklearn.preprocessing.MaxAbsScaler(copy=True)(这两者的关系同上)
6.鲁棒性标准化(免疫outlier)
专为异常值而生。标准差标准化(第一种,最常用的那种)对数据中出现的异常值处理能力不佳,因此诞生了robust_scale,这种不怕异常值扰动的数据缩放法。此Scaler根据分位数范围(默认为IQR:Interquartile Range)删除中位数并缩放数据。 IQR是第1四分位数(第25个分位数)和第3个四分位数(第75个分位数)之间的范围。
参考:
- sklearn.preprocessing.robust_scale(X, axis=0, with_centering=True, with_scaling=True, quantile_range=(25.0, 75.0), copy=True)
- sklearn.preprocessing.RobustScaler(with_centering=True, with_scaling=True, quantile_range=(25.0, 75.0), copy=True)
7.对数/平方根缩放:
适用场景:对数缩放对于处理长尾分布且取值为正数的数值变量非常有效,它将大端长尾压缩为短尾,并将小端进行延伸,平方根或者对数变换是幂变换的特例,在统计学中都称为方差稳定的变换
举例:对数缩放
1 2 | import numpy as np data[ "log_feature1" ] = np.log10(data[ "feature1" ]) |
8.box-cox变换
适用场景:基于极大似然法的幂转换,其作用是让分布在不丢失信息的前提下,具有更好的性质(独立性、方差齐性、正态性等),以便得到更好的模型。
要求:
Box-Cox变换的要求是数据要大于0,否则无法变换,解决的办法是加一个常数,把数据变成正数;
变换后,必须再做正态性检验,确认变换的有效性;
求:假设经过转换后的因变量就是服从正态分布的,然后画出关于的似然函数,似然函数值最大的时候的取值就是这里需要确定的值。
9.上下界截断:
- clipping:可以用pandas dataframe的.clip(low, upper)方法,把特征值的取值限制在一定范围内
-
12
data.ix[data[
'feature1'
]>
10
,
'feature1'
]
=
10
data.ix[data[
'feature2'
]<
-
20
,
'feature2'
]
=
-
20
三、数值特征离散化
这对于决策树类型的模型没太多意义
1.二值化
设定一个阈值,大于阈值的赋值为1,小于等于阈值的赋值为0;默认阈值为0时,只有正值映射到1。
1 | class sklearn.preprocessing.Binarizer(threshold = 0.0 , copy = True ) |
参数:
- threshold:float,可选,默认=0.0,对于稀疏矩阵上的操作,阈值可能不小于0。
- copy:boolean,可选,默认=True
举例:
1 2 3 4 5 6 7 8 | from sklearn.datasets import load_iris import pandas as pd from sklearn.preprocessing import Binarizer X,y = load_iris(return_X_y = True ) df_X = pd.DataFrame(X,columns = list ( "ABCD" )) bn = Binarizer(threshold = 5.843333 ) df_X[ "A" ] = bn.transform(df_X[ "A" ].values.reshape( - 1 , 1 )) |
2.分桶
(1)等宽/非等宽分桶
如商品的评论次数、年龄
参考:
pandas.
cut
(x, bins, right=True, labels=None, retbins=False, precision=3, include_lowest=False, duplicates='raise')- 当bins为int型数字时,会生成等宽的bin;当bins=标量序列时,为用户自定义bin的区间
(2)等频率分桶
如果数值变量的取值存在很大间隔时,有些桶里没有数据,可以基于数据的分布进行分桶,.
将相同数据的记录放进每个区间,先求分位数,再用cut函数
①dataframe结构
dataframe.describe(percentiles=w)来计算分位数
1 2 3 | w = [ i / k for i in range (k + 1 )] w = data.describe (percentiles = w) [ 4 : 4 + k + 1 ] #取几个分位数的值作为不等长列表,用于cut函数 d2 = pd.cut(data,w,labels = range (k)) |
②列表、数组结构
1 2 3 4 5 6 | #用np.percentile(data,百分比)来求 temp = [ i / k * 100 for i in range (k + 1 )] w = [] for item in temp: w.append(np.percentile(data,item)) d3 = pd.cut(data,w,labels = range (k)) |
参考:
(3)一维聚类离散化
先聚类(如k-means),然后对每一类的连续值进行标记
①k-means求聚类中心,并排序,将相邻两项的中点作为边界点,把首末边界点加上,整合成w列表
②cut函数
1 2 3 4 5 6 7 8 | from sklearn.cluster import KMeans kmodel = KMeans(n_clusters = k) #k为聚成几类 kmodel.fit(data.reshape( len (data), 1 ))) #训练模型 c = pd.DataFrame(kmodel.cluster_centers_) #求聚类中心 c = c.sort_values(by = ’列索引') #排序 w = pd.rolling_mean(c, 2 ).iloc[ 1 :] #用滑动窗口求均值的方法求相邻两项求中点,作为边界点 w = [ 0 ] + list (w[ 0 ] + [ data. max () ] #把首末边界点加上 d3 = pd.cut(data,w,labels = range (k)) #cut函数 |
四、缺失值处理
五、特征交叉
1. 数值特征的简单变换
- 单独特征列乘以一个常数(constant multiplication)或者加减一个常数:对于创造新的有用特征毫无用处;只能作为对已有特征的处理。
- 任何针对单独特征列的单调变换(如对数):不适用于决策树类算法。对于决策树而言,之间没有差异, 之间没有差异,除非发生了舍入误差。
- 线性组合(linear combination):仅适用于决策树以及基于决策树的ensemble(如gradient boosting, random forest),因为常见的axis-aligned split function不擅长捕获不同特征之间的相关性;不适用于SVM、线性回归、神经网络等。
- 多项式特征(polynomial feature):
- sklearn.preprocessing.PolynomialFeatures - scikit-learn 0.18.1 documentation。
-
捕获特征之间的相关性, 使用sklearn.preprocessing.PolynomialFeatures来进行特征的构造。它是使用多项式的方法来进行的,如果有a,b两个特征,那么它的2次多项式为(1,a,b,a^2,ab, b^2),这个多项式的形式是使用poly的效果。
- PolynomialFeatures有三个参数
- degree:控制多项式的度
- interaction_only: 默认为False,如果指定为True,那么就不会有特征自己和自己结合的项,上面的二次项中没有a^2和b^2。
1234567891011from
sklearn.datasets
import
load_iris
import
pandas as pd
X,y
=
load_iris(return_X_y
=
True
)
df_X
=
pd.DataFrame(X,columns
=
list
(
"ABCD"
))
from
sklearn.preprocessing
import
PolynomialFeatures
pnf
=
PolynomialFeatures(degree
=
2
,interaction_only
=
True
)
temp
=
pnf.fit_transform(df_X[[
"A"
,
"B"
]].values)
for
i,column
in
enumerate
(
list
(
"EFGH"
)):
df_X[column]
=
temp[:,i]
- 比例特征(ratio feature):
- 绝对值(absolute value)
2. 类别特征与数值特征的组合
用N1和N2表示数值特征,用C1和C2表示类别特征,利用pandas的groupby操作,可以创造出以下几种有意义的新特征:(其中,C2还可以是离散化了的N1)

median(N1)_by(C1) \\ 中位数
mean(N1)_by(C1) \\ 算术平均数
mode(N1)_by(C1) \\ 众数
min(N1)_by(C1) \\ 最小值
max(N1)_by(C1) \\ 最大值
std(N1)_by(C1) \\ 标准差
var(N1)_by(C1) \\ 方差
freq(C2)_by(C1) \\ 频数
freq(C1) \\这个不需要groupby也有意义
仅仅将已有的类别和数值特征进行以上的有效组合,就能够大量增加优秀的可用特征。
将这种方法和线性组合等基础特征工程方法结合(仅用于决策树),可以得到更多有意义的特征,如:

N1 - median(N1)_by(C1)
N1 - mean(N1)_by(C1)
3.用基因编程创造新特征
Welcome to gplearn’s documentation!
基于genetic programming的symbolic regression,具体的原理和实现参见文档。目前,python环境下最好用的基因编程库为gplearn。基因编程的两大用法:
- 转换(transformation):把已有的特征进行组合转换,组合的方式(一元、二元、多元算子)可以由用户自行定义,也可以使用库中自带的函数(如加减乘除、min、max、三角函数、指数、对数)。组合的目的,是创造出和目标y值最“相关”的新特征。这种相关程度可以用spearman或者pearson的相关系数进行测量。spearman多用于决策树(免疫单特征单调变换),pearson多用于线性回归等其他算法。
- 回归(regression):原理同上,只不过直接用于回归而已。
4. 用决策树创造新特征
在决策树系列的算法中(单棵决策树、gbdt、随机森林),每一个样本都会被映射到决策树的一片叶子上。因此,我们可以把样本经过每一棵决策树映射后的index(自然数)或one-hot-vector(哑编码得到的稀疏矢量)作为一项新的特征,加入到模型中。
具体实现:apply()以及decision_path()方法,在scikit-learn和xgboost里都可以用。
六、非线性编码
七、行统计量
DataFrame.nunique(),DataFrame.count
(二)类别特征
一、编码
1.one-hot
如果类别特征本身有顺序(例:优秀、良好、合格、不合格),那么可以保留单列自然数编码。如果类别特征没有明显的顺序(例:红、黄、蓝),则可以使用one-hot编码:
- 作用:将类别变量转换为机器学习算法容易处理的形式
- 为什么one-hot编码可以用来处理非连续(离散)特征?
- 在使用one-hot编码中,我们可以将离散特征的取值扩展到欧式空间,在机器学习中,我们的研究范围就是在欧式空间中,首先这一步,保证了能够适用于机器学习中;另外对于one-hot处理的离散的特征的某个取值也就对应了欧式空间的某个点.
- 怎么用?
- sklearn.preprocessing.OneHotEncoder(n_values=None, categorical_features=None, categories=None, drop=None, sparse=True, dtype=<class ‘numpy.float64’>, handle_unknown=’error’)
View Code
- 如果需要修改编码后的列名
-
categorical_features =['cardIndex','is_abnormal'] dummies = pd.get_dummies(data,columns=categorical_features) dummies = dummies.add_prefix("{}_".format('cardIndex')) data.drop('animal',axis=1,inplace=True) data = data .join(dummies) data
运行结果与LabelBinarizer相似,不过在参数以及输入输出的格式上有细微的差别,参见文档。输出的矩阵是稀疏的,含有大量的0。
2.自然数编码(LabelEncoder)
默认的编码方式,消耗内存小,训练时间快,但是特征的质量不高。用于label encoding,生成一个(n_examples)大小的0~(n_classes-1)矢量,每个样本仅对应一个label。
sklearn.preprocessing.LabelEncoder
3.LabelBinarizer
用于one vs all的label encoding,类似于独热编码,生成一个(n_examples * n_classes)大小的0~1矩阵,每个样本仅对应一个label。
sklearn.preprocessing.LabelBinarizer
4.MultiLabelBinarizer
用于label encoding,生成一个(n_examples * n_classes)大小的0~1矩阵,每个样本可能对应多个label。
sklearn.preprocessing.MultiLabelBinarizer
5.聚类编码
和独热编码相比,聚类编码试图充分利用每一列0与1的信息表达能力。聚类编码时一般需要特定的专业知识(domain knowledge),例如ZIP码可以根据精确度分层为ZIP3、ZIP4、ZIP5、ZIP6,然后按层次进行编码。
6.平均数编码
平均数编码(mean encoding),针对高基数类别特征的有监督编码。当一个类别特征列包括了极多不同类别时(如家庭地址,动辄上万)时,可以采用。优点:和独热编码相比,节省内存、减少算法计算时间、有效增强模型表现。
平均数编码:针对高基数类别特征(类别特征)的数据预处理/特征工程 - 知乎专栏
7.只出现一次的类别
在类别特征列里,有时会有一些类别,在训练集和测试集中总共只出现一次,例如特别偏僻的郊区地址。此时,保留其原有的自然数编码意义不大,不如将所有频数为1的类别合并到同一个新的类别下。
注意:如果特征列的频数需要被当做一个新的特征加入数据集,请在上述合并之前提取出频数特征。
(三)标签
一、标签二值化
二、标签编码
参考文献:
【3】数据规范化——sklearn.preprocessing
【4】Python数据分析4------------数据变换
【7】Python下的机器学习工具sklearn--数据预处理(标签)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现