趋近智
许多机器学习 (machine learning)算法,尤其是线性模型和那些假设误差呈正态分布的算法,在处理高度偏斜的数值特征时,表现可能不理想。偏斜度指的是数据分布的不对称性。一种常见类型是右偏(或正偏),其分布的右侧尾部比左侧长或厚。这常出现在表示计数、频率或货币数值的特征中,大多数观测值集中在较低值,但少数极高值使分布拉伸。
以“收入”特征为例。大多数人的收入可能在一个特定范围,但少数人的收入可能明显更高,从而形成一个长长的右尾。这些极端值可能不成比例地影响模型参数 (parameter)或距离计算。
处理右偏数据最常用且有效的方法之一是对数变换。应用自然对数(底数为 ,常表示为 )或以10为底的对数()会压缩数据范围,尤其是在高端。
变换定义如下: 这里 是原始特征值, 是变换后的值。
对数的作用是,大值比小值被更显著地缩小。例如,,,。虽然100和1000之间的绝对差是900,但它们自然对数之间的差异只有大约2.3。这种压缩有助于使分布更对称,常更接近正态分布。
标准对数变换的一个明显限制是它只对正值()定义。零的对数未定义,负数的对数会得到复数,这些复数通常不能直接用于标准机器学习 (machine learning)模型。
如果您的数据包含零但没有负值,一个常用的变通方法是在应用对数之前,将一个小的常数(通常是1)加到所有值上。这被称为 log(1+x) 变换或 log1p:
这种变换有一个方便的属性,即 ,它在允许对非负数据进行变换的同时,保留了零的含义。许多数值计算库,包括NumPy,都提供一个专用函数 np.log1p(),即使对于非常小的 值,它也能准确计算 。
如果您的数据包含负值,对数变换(即使是 log1p)也不能直接应用。在这种情况下,您可能需要考虑其他变换,例如Yeo-Johnson变换(本章稍后会提到),或者如果这在您的应用背景下合理,可以根据特征的符号来拆分特征。
在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())
对数变换的影响通常通过可视化能更好地理解。让我们比较原始偏斜特征及其对数变换后的版本分布。
原始正偏斜数据(蓝色)和应用
log1p变换后的数据(绿色)的概率密度直方图比较。变换后的数据显示出更对称的钟形。
如图所示,原始分布在零附近高度集中,并有一个长尾延伸向更高的值。在 log1p 变换后,分布变得更加对称和分散,更接近正态分布。这种变换后的特征通常更适合对尺度和分布形状敏感的算法。
对数变换是特征工程工具包中一个简单但有效的工具,对于处理真实数据集中常见的具有指数增长模式或乘性影响的特征特别有用。
这部分内容有帮助吗?
log1p 函数的官方文档,详细说明其数学定义、用法以及为何适用于包含零值的非负数据。© 2026 ApX Machine Learning用心打造