许多机器学习算法,尤其是线性模型和那些假设误差呈正态分布的算法,在处理高度偏斜的数值特征时,表现可能不理想。偏斜度指的是数据分布的不对称性。一种常见类型是右偏(或正偏),其分布的右侧尾部比左侧长或厚。这常出现在表示计数、频率或货币数值的特征中,大多数观测值集中在较低值,但少数极高值使分布拉伸。以“收入”特征为例。大多数人的收入可能在一个特定范围,但少数人的收入可能明显更高,从而形成一个长长的右尾。这些极端值可能不成比例地影响模型参数或距离计算。使用对数变换处理偏斜处理右偏数据最常用且有效的方法之一是对数变换。应用自然对数(底数为 $e$,常表示为 $\ln$)或以10为底的对数($\log_{10}$)会压缩数据范围,尤其是在高端。变换定义如下: $$ y = \log(x) $$ 这里 $x$ 是原始特征值,$y$ 是变换后的值。对数的作用是,大值比小值被更显著地缩小。例如,$\log(10) \approx 2.3$,$\log(100) \approx 4.6$,$\log(1000) \approx 6.9$。虽然100和1000之间的绝对差是900,但它们自然对数之间的差异只有大约2.3。这种压缩有助于使分布更对称,常更接近正态分布。处理零值和负值标准对数变换的一个明显限制是它只对正值($x > 0$)定义。零的对数未定义,负数的对数会得到复数,这些复数通常不能直接用于标准机器学习模型。如果您的数据包含零但没有负值,一个常用的变通方法是在应用对数之前,将一个小的常数(通常是1)加到所有值上。这被称为 log(1+x) 变换或 log1p:$$ y = \log(1 + x) $$这种变换有一个方便的属性,即 $\log(1+0) = \log(1) = 0$,它在允许对非负数据进行变换的同时,保留了零的含义。许多数值计算库,包括NumPy,都提供一个专用函数 np.log1p(),即使对于非常小的 $x$ 值,它也能准确计算 $\log(1+x)$。如果您的数据包含负值,对数变换(即使是 log1p)也不能直接应用。在这种情况下,您可能需要考虑其他变换,例如Yeo-Johnson变换(本章稍后会提到),或者如果这在您的应用背景下合理,可以根据特征的符号来拆分特征。使用NumPy和Pandas实现在Python中使用NumPy应用对数变换很简单。假设您的数据在Pandas DataFrame df 中,并且您想变换名为 feature_skewed 的列:import numpy as np import pandas as pd # 样本偏斜数据(例如,模拟收入) np.random.seed(42) data_skewed = np.random.exponential(scale=10000, size=1000) # 引入一些零值 data_skewed[::10] = 0 df = pd.DataFrame({'feature_skewed': data_skewed}) # 在应用对数前检查负值 if (df['feature_skewed'] < 0).any(): print("警告:特征包含负值。对数变换不适用。") else: # 应用log1p变换以处理可能存在的零值 df['feature_log_transformed'] = np.log1p(df['feature_skewed']) # 显示原始数据和变换后数据的前几行 print(df[['feature_skewed', 'feature_log_transformed']].head()) # 显示基本统计信息 print("\n原始数据统计信息:") print(df['feature_skewed'].describe()) print("\n变换后数据统计信息:") print(df['feature_log_transformed'].describe())效果可视化对数变换的影响通常通过可视化能更好地理解。让我们比较原始偏斜特征及其对数变换后的版本分布。{"data": [{"histnorm": "probability density", "marker": {"color": "#339af0"}, "name": "原始", "opacity": 0.75, "type": "histogram", "x": [1.0, 1.2, 1.5, 2.0, 2.5, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 12.0, 15.0, 20.0, 25.0, 30.0, 35.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0]}, {"histnorm": "probability density", "marker": {"color": "#20c997"}, "name": "Log1p 变换后", "opacity": 0.75, "xaxis": "x2", "type": "histogram", "x": [0.69, 0.79, 0.92, 1.10, 1.25, 1.39, 1.61, 1.79, 1.95, 2.08, 2.20, 2.30, 2.40, 2.56, 2.77, 3.04, 3.26, 3.43, 3.58, 3.71, 3.93, 4.11, 4.26, 4.39, 4.51, 4.61], "yaxis": "y2"}], "layout": {"barmode": "overlay", "legend": {"x": 0.6, "y": 0.95}, "title": "原始分布与对数变换后的分布比较", "xaxis": {"title": "原始值 (feature_skewed)"}, "xaxis2": {"anchor": "y", "overlaying": "x", "position": 0.15, "side": "bottom", "title": "Log(1+x) 变换后的值"}, "yaxis": {"title": "密度"}, "yaxis2": {"anchor": "x", "overlaying": "y", "side": "right", "title": "密度 (变换后)"}}}原始正偏斜数据(蓝色)和应用 log1p 变换后的数据(绿色)的概率密度直方图比较。变换后的数据显示出更对称的钟形。如图所示,原始分布在零附近高度集中,并有一个长尾延伸向更高的值。在 log1p 变换后,分布变得更加对称和分散,更接近正态分布。这种变换后的特征通常更适合对尺度和分布形状敏感的算法。注意事项可解释性: 应用对数变换会改变特征的解释方式。变换后特征的单位变化对应于原始特征的乘性变化。使用对数变换特征的模型中的系数需要相应地进行解释。并非总是完美: 尽管对数变换对于右偏数据通常有效,但它不能保证数据呈完美正态分布。始终要在变换后检查分布。替代方法: 对于并非严格为正的数据或不同类型的分布问题,Box-Cox或Yeo-Johnson等其他变换可能更适合,我们将在接下来看到。对数变换是特征工程工具包中一个简单但有效的工具,对于处理真实数据集中常见的具有指数增长模式或乘性影响的特征特别有用。