数据处理方式 之 对数变换 和Box-Cox变换以及对应逆变换【深度学习】
对数变换 和Box-Cox变换
变换的目的
- 就是让数据分布更适合建模,减少偏态和异常值带来的负面影响,从而提升模型的表现和稳定性。
准备工作
- 确保要处理的数据的值都大于 0 。
- 在这之前,可以统计对应列的最值
print(df.min(), df.max())
,观察是否有< 0 的值,有的话,就必须先处理,再做后续变换 - 示例代码如下:
def reset_zero(x): return max(x,0)
# 先给这两列的值,确保大于0,再进行对数转换或者Box-Cox转换
features['Garage spaces']=features['Garage spaces'].apply(lambda x: reset_zero(x))
features['Total spaces']=features['Total spaces'].apply(lambda x: reset_zero(x))
对数变换log和boxcox变换的联系
log1p(x)
实际上是 Box-Cox 变换的特殊情况(λ=0),- 即
log1p(x) == boxcox1p(x, λ=0)
- 即
- Box-Cox 变换通过调节 λ,可以在 log1p 和其他幂次变换之间自适应选择,使数据分布更接近正态分布。
- 所以 Box-Cox 更灵活,能自动适应不同特征的分布;而 log1p 只是 λ=0 的情况。
对数变换 – np.log / np.log1p
- 🧨🧨🧨注意内容:
- log1p 对应 +1,如果需要,求逆的时候还要 -1;
- 观察法:直观的方式:
数值比较大,且不同样本之间的数据变化也比较大【下面给出个具体例子】
print(train_features.min(), train_features.max()) # 应在一个合理范围内
print(train_labels.min(), train_labels.max())# 调整前
# tensor(0) tensor(72993.2)
# tensor(0) tensor(18100053)# 调整后
# tensor(-15.2072) tensor(72.9932)
# tensor(11.5179) tensor(18.3153)
"""
- 更科学一点的方法:一般是要结合数据的特性来使用,比如这里使用偏度(skewness)
- |skewness| < 0.5:分布近似对称(无需处理)
- 0.5 ≤ |skewness| < 1:中等偏斜(可考虑处理)
- |skewness| ≥ 1:高度偏斜(建议处理)
- 综上,对于>0.5 就可以使用这个了
- 举例子:根据下面的输出的head(20) 来查看数据的偏度,决定是否使用
# 选取 features 数据集中所有数值型(int64 和 float64)列的列名
numerical_columns = features.select_dtypes(include=['int64','float64']).columns # 对每个数值型特征计算偏度(skewness),即分布的不对称程度。
# stats.skew(x) 计算偏度,偏度越大,分布越偏斜。
# 结果按偏度从大到小排序。
skewed_features = features[numerical_columns].apply(lambda x: stats.skew(x)).sort_values(ascending=False)
skewness = pd.DataFrame({'Skew value' :skewed_features})
# 展示偏度最大的前20个特征。
skewness.head(20)
使用方法
y = np.log1p(y)
等价于 y =np.log(1 + y)
import numpy as np
import pandas as pdtrain_data = pd.read_csv("train.csv")
# train_data["Sold Price"] = np.log(train_data["Sold Price"]+1)
train_data["Sold Price"] = np.log1p(train_data["Sold Price"]) # 求原数值
train_data["Sold Price"] = np.exp(train_data["Sold Price"]) - 1
逆变换
import numpy as np# 生成示例数据
np.random.seed(0)
original_data = [0.5, 1.0