特征对数变换和指数变换是数据预处理中的两种常用技术,它们可以帮助改善数据的分布特性,从而提高某些模型的性能。
对数变换通常用于减少数据的偏斜性(skewness),它将原始数据的每个值转换为该值的自然对数或以10为底的对数。对于具有重尾分布的数据,对数变换时很好的处理方式。公式为:
下面代码的目的是通过生成具有重尾分布的数据,并对其进行对数变换,来展示对数变换对数据分布的影响。
import numpy as np
import matplotlib.pyplot as plt
# 设置随机种子以获得可复现的结果
np.random.seed(0)
# 生成具有重尾分布的数据(例如,使用帕累托分布)
data = np.random.pareto(a=1, size=2000)
# 对数变换,这里使用10为底对数
# 为了避免对数变换中的问题,添加一个小的常数(例如1)
log_data = np.log10(data + 1)
# 绘制原始数据的直方图
plt.figure(figsize=(14, 5)) # 调整图形大小以便更清晰的展示
plt.subplot(1, 2, 1) # 1行2列的第一个图
plt.hist(data, bins=50, color='blue', alpha=0.7, log=True) # 使用对数刻度
plt.title('Original Data (Log Scale)')
plt.xlabel('Value') # 添加x轴标签
plt.ylabel('Frequency (log scale)') # 添加y轴标签,说明y轴是频率的对数刻度
# 绘制对数变换后数据的直方图
plt.subplot(1, 2, 2) # 1行2列的第二个图
plt.hist(log_data, bins=30, color='green', alpha=0.7) # 正常刻度
plt.title('Log-transformed Data')
plt.xlabel('Value') # 添加x轴标签
plt.ylabel('Frequency') # 添加y轴标签
# 显示图形
plt.tight_layout() # 调整布局以避免标签重叠
plt.show()
下面是对代码的分析和对数变换前后作用的解释:
np.random.pareto(a=2.0, size=2000)
生成了2000个服从帕累托分布的数据点。帕累托分布是一种典型的重尾分布,其特点是大部分数据点集中在较小的值附近,而少数数据点是极端大的值。np.log10(data + 1)
。这里添加了1来避免对数函数在0处未定义的问题。运行结果如下:
在原始数据的直方图上使用对数刻度,可以清晰地看到数据的重尾特性,即直方图的右侧有一个长尾,对数变换后的数据直方图可能看起来更加紧凑,极端大值的影响被减少
指数变换通常用于处理具有极端值或非常不均匀分布的数据,它将原始数据的每个值转换为该值的指数函数,指数变换可以放大较小的值而压缩较大的值,有助于减少极端值的影响。公式为:
指数变换主要应用与图像处理领域,可参考如下的文章:
这段代码演示了如何对一组非正态分布的正值数据进行指数变换,并可视化变换前后的数据分布。
import numpy as np
import matplotlib.pyplot as plt
# 生成数据:使用gamma分布生成非正态分布的正值数据
data = np.random.gamma(shape=1.0, scale=1.0, size=1000)
# 归一化数据到[0, 1]区间
data_normalized = data / np.max(data)
# 应用指数变换
exp_data_normalized = np.exp(data_normalized - 1) # 减1保证变换后数据不会全为0
# 反归一化到原始数据的范围
exp_data = exp_data_normalized * np.max(data)
# 绘制原始数据的直方图
plt.figure(figsize=(10, 6))
plt.subplot(1, 2, 1)
plt.hist(data, bins=30, color='blue', alpha=0.7)
plt.title("Original Data")
# 绘制指数变换后数据的直方图
# 截断数据以避免过大的值
threshold = np.percentile(exp_data, 99) # 取99百分位数作为阈值
exp_data[exp_data > threshold] = threshold
plt.subplot(1, 2, 2)
plt.hist(exp_data, bins=30, color='green', alpha=0.7)
plt.title("Exponential Transformed Data")
# 添加坐标轴标签
plt.xlabel('Value')
plt.ylabel('Frequency')
# 显示图形
plt.tight_layout()
plt.show()
下面是对代码的分析:
numpy
的random.gamma
函数生成一组非正态分布的正值数据,这种分布通常产生偏斜的数据,具有重尾特性。直方图显示了变换前后数据分布的对比,指数变换后的数据可能更加均匀或具有更小的偏斜度。
两种变换对数据要求:在应用这些变换之前,需要考虑数据的特性和模型的需求。例如,对数变换不适用于零或负值,因为对数函数在这些值上是未定义的。而指数变换则可以处理负值。
平方根变换和对数变换可以简单推广为Box-Cox变换。Box-Cox变换是一种在统计建模中常用的数据变换方法,由George E.P. Box和David Cox在19年提出,用于处理连续的、正值的、偏斜分布的数据,以便它们更符合正态分布的要求。这种变换特别适用于线性回归模型中,当响应变量不满足正态分布时,通过变换可以使模型满足线性、正态性、性以及方差齐性的假设条件。
Box-Cox变换的一般形式为:
其中,y是原始数据,λ 是变换参数 。
box-cox变换的主要作用:是将数据进行归一化,使得数据更加符合统计假设。在实际应用中,box-cox变换常用于解决回归分析和方差分析中的数据不满足正态分布的问题,从而提高模型的准确度和可靠性。
box-cox变换优点:
box-cox变换缺点:
下面代码演示了如何使用Box-Cox变换对一组非正态分布的正值数据进行处理,并可视化原始数据和变换后数据的分布情况。
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
# 假设有一组非正态分布的正值数据
# 这里我们使用一个偏态分布的示例数据集
data = np.random.gamma(shape=2.0, scale=2.0, size=1000)
# 应用Box-Cox变换,并找到最优的lambda值
transformed_data, optimal_lambda = stats.boxcox(data)
# 打印最优的lambda值
print(f"Optimal lambda value: {optimal_lambda}")
# 绘制原始数据的直方图
plt.figure(figsize=(14, 6))
plt.subplot(1, 2, 1)
plt.hist(data, bins=30, color='blue', alpha=0.7)
plt.title("Original Data")
# 添加坐标轴标签
plt.xlabel('Value')
plt.ylabel('Frequency')
# 绘制变换后数据的直方图
plt.subplot(1, 2, 2)
plt.hist(transformed_data, bins=30, color='green', alpha=0.7)
plt.title(f"Box-Cox Transformed Data \n(lambda = {optimal_lambda})")
# 添加坐标轴标签
plt.xlabel('Value')
plt.ylabel('Frequency')
# 显示图形
plt.tight_layout()
plt.show()
scipy.stats.boxcox
函数对数据进行Box-Cox变换。该函数返回变换后的数据transformed_data
和最优的lambda值optimal_lambda
。最优的lambda值是通过极大似然估计得到的,用于确定最佳的Box-Cox变换形式。matplotlib
库绘制原始数据和变换后数据的直方图。原始数据(伽马分布)具有偏态分布,Box-Cox变换旨在通过非线性变换减少数据的偏态,使数据更接近正态分布。
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- igbc.cn 版权所有 湘ICP备2023023988号-5
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务