Skewness and Kurtosis: From Moments to Machine Learning
TL;DR · AI 摘要
Skewness and Kurtosis: From Moments to Machine Learning Towards Data Science Data Science Skewness and Kurtosis: From Mo...
核心要点
- 主题聚焦:Skewness and Kurtosis: From Moments to Machine L
- 来源:Towards Data Science,建议结合原文判断细节。
- AI 分析暂不可用,本条为保底评分与摘要。
偏度和峰度:从矩到机器学习 | Towards Data Science
数据科学
偏度和峰度:从矩到机器学习
高阶矩的数学原理、直觉理解、解释方法及实际应用。
Mansi Bramta
2026年10月23日
23分钟阅读时间
在Google上关注我们
分享
封面图片由AI生成
1. 为什么需要样本:总体与样本
如果我说“我想了解印度全国非医学专业12年级学生的平均分数”,这在实践中是否可行?
我的意思是,谁会去访问印度的每所学校,每个州、每个区、每个村庄?这几乎是不可能的。即使我们设法收集了所有这些数据,也需要耗费大量时间、金钱和人力,而且过程中存在大量出错和不一致的可能。
那么,这个问题真的无法解决吗?
绝对不是!
我们可以使用统计学中最重要的概念之一:总体与样本来解决这个问题。
请看这张图:
作者使用Lucidchart制作的图表。
如上图所示,总体的一个子集称为样本。
当数据量太大无法收集或计算时,我们通常使用样本数据代替。但有一个重要条件:样本必须具有代表性,且不应引入系统性偏差。这意味着我们不应以可能轻易改变结果的方式选择特定群体。
例如,如果我只考虑得分90%或以上的学生成绩,平均分会自然很高。但如果考虑所有分数段的学生,从低分到高分,样本更可能代表实际总体,因此结果更可能接近真实总体值。
总体的大小用N表示,样本的大小用n表示。
2. 为什么除以n−1?自由度解析
这里可能会产生疑问——为什么在样本计算中,我们要除以(n-1)而不是(n)?
要澄清这个困惑,我们需要了解一个重要的概念。
你知道吗?偏差的总和始终为0?
这里有一个简单的证明。
这是我们的样本均值,对吗?
x̄ = (x₁ + x₂ + ⋯ + xₙ) / n
如果我们两边同时乘以n,
n·x̄ = x₁ + x₂ + ⋯ + xₙ
展开后我们会得到类似这样的结果,这意味着每个样本点与均值的偏差总和:
(x₁ − x̄) + (x₂ − x̄) + ⋯ + (xₙ − x̄) = 0
它始终为0。
Σᵢ₌₁ⁿ (xᵢ − x̄) = 0
现在,根据这一点,我们注意到一个关键点。
假设我们有三个偏差:
-2, 0, ?
我们真的需要所有三个偏差吗?
根据前两个,我可以轻易推断出第三个必须是+2。这是唯一能使总和等于0的值。
因此,在这三个偏差中,我们只能独立选择其中两个。第三个会自动由前两个决定。
因此,一般来说,如果我们有n个样本均值的偏差,其中只有(n-1)个可以独立变化,因为它们的总和必须为0。
这就是我们对自由度的第一个直觉理解。
但还有一个更重要的点需要说明。
在计算样本方差时,我们使用的是样本均值而不是真实的总体均值。由于这个原因,除以n会使我们对方差的估计系统性地偏小。
通过除以(n-1)可以纠正这种偏差,从而得到总体方差的无偏估计。
这就是你不知不觉中已经熟悉了自由度概念的原因。
现在你可能会疑惑:为什么在讨论偏度之前,我们要绕这么远的路,先了解总体、样本和自由度?
因为偏度和峰度是统计量,要正确理解它们的公式,必须了解总体和样本公式的来源。
3. 矩:形状的构建模块
在进入主题之前,我们先学习另一个重要概念——矩。
我们有四个中心矩:
- 一阶中心矩 → 0
- 二阶中心矩 → 方差
- 三阶中心矩 → 与偏度相关
- 四阶中心矩 → 与峰度相关
我们已经学习过均值和方差,它们分别对应原始矩中的第一矩和中心矩中的第二矩。
在本文中,我们将深入探讨三阶和四阶中心矩,了解在标准化后它们如何导出偏度和峰度的度量。
— 一阶中心矩 → 0 → μ₁ = E[(X − μ)]
— 二阶中心矩 → 方差 → μ₂ = E[(X − μ)²]
— 三阶中心矩 → 与偏度相关 → μ₃ = E[(X − μ)³]
— 四阶中心矩 → 与峰度相关 → μ₄ = E[(X − μ)⁴]
这些总体矩是通过总体分布定义的。
如果我们想计算对应的样本矩,只需将总体期望替换为相应的样本均值。
mᵣ = (1/n) Σᵢ₌₁ⁿ (xᵢ − x̄)ʳ
4. 偏度:衡量不对称性
#### 4.1 对称分布与偏态分布
现在我们已经具备了理解主要话题的所有知识,让我们先从理解分布开始。
→ 分布描述了变量值的分布方式以及不同值或值范围出现的频率。我们可以简单地将其视为数据的"地图"。
这张地图可以是对称的或非对称的。
对称性如图所示(作者使用Python创建)。
非对称分布进一步分为两种类型——右偏分布和左偏分布:
人们常常混淆这一点,因为他们认为分布较多的一侧对应其名称。但有一个关键点需要记住:始终观察尾部。
如果长尾向右延伸,则为右偏(正偏)。
如果长尾向左延伸,则为左偏(负偏)。
以下是生成1000个随机数据点的Python代码,展示了右偏、正态和左偏分布。
python
# 示例代码(此处应保留原文代码块内容)import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import gaussian_kde
# 生成数据
np.random.seed(42)
# 正偏态(右偏)
positive = np.random.exponential(scale=2, size=1000)
# 正态分布
normal = np.random.normal(loc=5, scale=1, size=1000)
# 负偏态(左偏)
negative = -np.random.exponential(scale=2, size=1000)
# 绘制分布的函数
def plot_distribution(data, title):
# 均值
mean = np.mean(data)
# 中位数
median = np.median(data)
# 核密度估计
kde = gaussian_kde(data)
x = np.linspace(min(data), max(data), 1000)
y = kde(x)
# 众数 = KDE 最大值对应的 x 值
mode = x[np.argmax(y)]
# 绘制直方图
plt.hist(
data,
bins=30,
density=True,
alpha=0.5
)
# KDE 曲线
plt.plot(
x,
y,
linewidth=2,
label="KDE"
)
# 均值
plt.axvline(
mean,
linewidth=2,
color = 'red',
label=f"均值 = {mean:.2f}"
)
# 中位数
plt.axvline(
median,
linewidth=2,
color = 'green',
label=f"中位数 = {median:.2f}"
)
# 众数
plt.axvline(
mode,
linewidth=2,
color = 'black',
label=f"众数 ≈ {mode:.2f}"
)
plt.title(title)
plt.xlabel("数值")
plt.ylabel("密度")
plt.legend()
plt.show()
# 绘制所有三个分布
plot_distribution(positive, "正偏态(右偏)")
plot_distribution(normal, "正态分布")
plot_distribution(negative, "负偏态(左偏)")#### 4.2 偏态数据中的均值、中位数和众数
我们还需要观察在这些分布中,均值、中位数和众数的位置关系。
对于左偏(负偏)分布 -> 均值 < 中位数 < 众数。
对于对称的正态分布,我们通常观察到 -> 均值 ≈ 中位数 ≈ 众数。
对于右偏(正偏)分布,我们通常观察到 -> 均值 > 中位数 > 众数。
偏态分布的尾部延伸有时可能由分布一侧的极端值或异常值引起。但偏度并不总是意味着存在异常值;分布本身可能自然地在某一侧具有更长的尾部。
#### 4.3 从三阶中心矩到偏度
接下来,我们已经看到偏度的数学概念,这与我之前解释的矩(Moments)概念相关。
如上所述,我将其描述为与偏度相关,而非偏度本身。这自然引出了一个重要问题:为什么我们需要在这里进行标准化?
我们只需要进行轻微的标准化,使最终的度量值独立于数据的尺度。
γ₁ = E[(X − μ)³] / σ³
在这里,我们将三阶中心矩除以标准差的立方。
三阶中心矩具有立方单位,如(cm³)、(km³)等。但我们不希望偏度值依赖于数据的测量单位。
通过除以标准差的立方,我们消除了单位,得到了一个无单位(无量纲)的值。
另一个重要问题是:为什么需要使用三次方?为什么不使用平方?
(X − μ)
表示数据点与均值的距离。
如果我们平方这个距离,正负偏差都会变为正数。这样我们会丢失偏差方向的信息。
但当我们使用三次方时,会出现有趣的现象:
(+2)³ = +8
而
(-2)³ = -8
符号被保留!
这使得三阶中心矩能够捕捉到均值周围不对称性的方向。
还有另一个重要的点需要说明。立方运算对数据中的较大偏差赋予了更高的权重。例如:
2³ = 8 5³ = 125
因此,极端值对三阶中心矩的影响更为显著。这也是偏度对极端值和异常值特别敏感的原因之一。
#### 4.4 样本偏度:费舍尔-皮尔逊系数与偏差校正
现在,我们还需要补充一个重要信息:上述公式适用于总体数据。
但在大多数现实问题中,我们很少能获取完整的总体数据。通常我们处理的是样本数据。
因此,在从样本数据计算偏度时,需要对总体公式进行调整。
这种调整引导我们得到了费舍尔-皮尔逊样本偏度系数:
g₁ = [(1/n) Σᵢ₌₁ⁿ (xᵢ − x̄)³] / [(1/n) Σᵢ₌₁ⁿ (xᵢ − x̄)²]^(3/2)
初次看到这个公式时,可能会觉得有些复杂,但实际上它非常直观。
本质上,它是三阶样本中心矩除以二阶样本中心矩的(3/2)次方。
其背后的逻辑是:
- 三阶样本中心矩告诉我们数据的不对称性特征
- 二阶样本中心矩告诉我们数据的分布范围或尺度
通过将三阶矩除以二阶矩的(3/2)次方,我们实际上是在问:
数据的不对称性相对于其尺度有多大?
这种标准化非常重要,因为我们不希望偏度值受数据单位或尺度的影响。
但即使如此,这个估计量仍然存在局限性:它可能产生偏差,尤其是在小样本情况下。
可以这样理解:如果我们从同一总体中反复抽取不同样本并计算每个样本的偏度,这些偏度值会有所波动。如果我们对多次重复抽样得到的样本偏度估计值取平均,这个平均值可能会系统性地偏离总体真实偏度。
我们不会简单地将这种差异称为错误。当估计量系统性地高估或低估我们试图估计的量时,这种系统性差异被称为偏差(Bias)。
因此,我们需要一个校正因子,我们称之为C(n):
G₁ = C(n) * g₁
这个校正因子是基于样本偏度估计量在重复抽样下的期望行为推导出来的。
这引导我们得到了调整后的费舍尔-皮尔逊偏度系数:
G₁ = [√(n(n − 1)) / (n − 2)] · g₁
这种调整略微改变了估计值,以补偿未调整样本偏度中存在的系统性偏差。
当样本量变得非常大时,校正因子会趋近于1,因此:
G₁ → g₁
换句话说,对于大样本,调整后与未调整的偏度之间的差异会变得非常小。
在这里,我们可以看到校正因子仅依赖于样本量n。但为什么不是其他因素?
→ 我们不希望根据数据的单位(如100卢比、10,000卢比、身高、薪资等)来计算不同的校正因子。
我们正在修正的问题本质上是一个有限样本问题。
因此,校正应取决于样本量,而不是数据的实际值或单位。
没有一个普遍适用的数学规则来解释这一点,因为偏度的解释在很大程度上取决于上下文和数据。
作为一个粗略的经验法则:
- 如果偏度 ≈ 0 → 数据近似对称。
- 如果偏度为正 → 分布为右偏。
- 如果偏度为负 → 分布为左偏。
- 如果 |偏度| 较大 → 分布表现出更强的不对称性。
但上下文非常重要。
在某些情况下,偏度值为 1 可能完全可接受,而在其他情况下可能存在问题。没有一个单一的阈值可以告诉我们偏度是“好”还是“坏”的。
让我们通过 Python 代码来验证这一点,使用我上面展示的相同随机数据集。
from scipy.stats import skew
print("Positive skewness:", skew(positive))
print("Normal skewness:", skew(normal))
print("Negative skewness:", skew(negative))正偏度: 1.865034222864843 正态偏度: -0.036662811518565 负偏度: -1.6510942321423066
从上述结果可以看出,正负符号清楚地表明了偏度的方向。
我们还可以看到,正态偏度略微为负。我们可以将其视为近似对称。然而,仅凭接近零的偏度值并不能证明分布是正态分布的。因此,仅根据偏度值,我们不会认为该分布具有显著的左偏性。
我们还可以清楚地看到,正偏度的绝对值大于负偏度的绝对值。
但请记住,我们不能仅仅因为正数大于负数就进行比较。相反,当我们比较偏度的强度或绝对值时,需要查看它们的绝对值。
例如:
|1.865034222864843| > |-1.651094232142306|
因此,右偏分布的偏度略强于左偏分布。
需要记住的重要一点是:
符号 → 偏度方向 绝对值 → 偏度的强度或程度
5. 峰度:它与尾部有关,而非峰顶
#### 5.1 峰度真正衡量的是什么
在查阅许多网站并研究峰度后,我了解到人们通常将其描述为分布的“峰度”或“尖锐程度”。
但事实真的如此吗?
并非完全如此。
峰度是一个标准化的四阶中心矩,对极端观测值和尾部行为特别敏感。
简单来说,它帮助我们理解极端观测值和尾部行为的相对重要性。
在上面的图像中,你能关注到尾部的不同模式吗?
是的,这些尾部行为的差异与峰度有关。
正如我们在理解偏度公式时所学到的,峰度也遵循类似的模式。
β₂ = E[(X − μ)⁴] / σ⁴
展开后将得到:
β₂ = E[(X − μ)⁴] / (E[(X − μ)²])²
在这里,我们只需取四阶中心矩,并通过标准差的四次方进行标准化。
以下是一个简单的流程图,帮助我们有效记忆这一概念。
但正如我们所知,这个公式适用于总体数据,而我们通常无法获取整个总体的数据。因此,我们需要一个样本公式来应用。
但在继续之前,我想让我们先学习一个重要的概念:超额峰度。
#### 5.2 为什么使用四次方?
在继续之前,这里可能又会有一个问题:
为什么使用四次方?
为了确定偏度的方向,我们使用了三次方,因为三次方能够保留偏差的符号。
但在这里,我们希望均值两侧的偏差都能以正向方式贡献,同时对较大的偏差赋予更大的权重。四次方正好可以做到这一点。
(-2)⁴ = 16
(2)⁴ = 16
因此,正负偏差都会以正向方式贡献。
但这并不是我们使用四次方的唯一原因。
四次方还会使极端值获得不成比例的高权重。
10⁴ = 10,000
这意味着当观测值离均值越远时,其对四阶中心矩的贡献会迅速增加。
因此,峰度不仅关注观测值是否远离均值,四次方的特性会让峰度对远离均值的观测值产生更强的敏感性。
#### 5.3 峰度超额:这个“3”从何而来?
现在,让我们转向峰度超额的概念。
要理解峰度超额,我们首先需要了解峰度的不同取值:
使用Overleaf中通过LaTeX格式化的数学公式。
要理解这个“3”的来源,我们需要对正态分布有更深入的了解。
Z = (X − μ) / σ
这是标准正态随机变量,当我们从正态分布中取任意一点(X),减去均值,再除以标准差时,就会得到这个变量:
这种转换称为标准化。
当均值为0且标准差为1时,它成为正态分布的一个特例,即:
Z ~ N(0,1)
因此,在标准正态分布中,均值为0,标准差为1。
对于峰度,我们关注的是四阶中心矩:
E[(X − μ)⁴] = E[(σZ)⁴] = σ⁴ E[Z⁴]
对于标准正态随机变量,偶数阶矩遵循一个非常有趣的规律:
E[Z²ᵏ] = (2k − 1)!!
当k=2时,我们处理的是四阶矩。
这里!!表示双阶乘,意味着我们向下乘以每隔一个数:
3!! = 3 × 1 = 3
这就是我们著名的“3”的来源!
K = E[(X − μ)⁴] / σ⁴ = 3σ⁴ / σ⁴ = 3
因此,我们可以得出结论:正态分布的峰度为3。
这就是我们在解释峰度时使用3作为基准的原因。
然而,原始的峰度值并不总是很容易解释。例如,说一个分布的峰度为5,并不能立即告诉我们太多信息。
因此,我们通过减去正态分布的峰度(即3)来简化解释。
因此:
现在解释变得简单明了:
- 峰度超额(>0)→ 通常表示尾部更重,对极端观测值的敏感性比正态分布更高
- 峰度超额(=0)→ 与正态分布具有相同的峰度
- 峰度超额(<0)→ 通常表示尾部更轻,对极端观测值的敏感性比正态分布更低
#### 5.4 尖峰态、中峰态和低峰态分布
让我们通过图表来观察:
从上面的图表中可以明显看出,峰度超额值为20.52,这与0相比非常高。
这表明该分布具有更高的峰度和更重的尾部,对极端观测值的敏感性比正态分布更强。这种分布通常被称为尖峰态分布。
在这里,峰度超额值为-0.01,这非常接近0。
这表明该分布的峰度与正态分布大致相同,因此我们可以认为它近似为中峰度分布(Mesokurtic)。然而,这并不意味着该分布一定是正态分布。
此处的超额峰度(Excess Kurtosis)为 -1.18。
由于超额峰度为负值,该分布的峰度低于正态分布,通常极端观测值的影响也较小。这种分布通常被称为低峰度分布(Platykurtic)。
正如你所看到的,这些尾部差异从图表本身也可以明显看出。
以下是用于生成上述图表的 Python 代码:
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import kurtosis, gaussian_kde
np.random.seed(42)
# 1. 重尾分布
heavy = np.random.standard_t(df=3, size=10000)
# 2. 正态分布
normal = np.random.normal(loc=0, scale=1, size=10000)
# 3. 轻尾分布
light = np.random.uniform(-2, 2, size=10000)
# 计算超额峰度
print("重尾分布峰度:", kurtosis(heavy))
print("正态分布峰度:", kurtosis(normal))
print("轻尾分布峰度:", kurtosis(light))
# -------------------------
# 重尾分布
# -------------------------
plt.figure(figsize=(8, 5))
plt.hist(heavy, bins=100, density=True, alpha=0.6)
# KDE
x = np.linspace(-10, 10, 1000)
kde = gaussian_kde(heavy)
plt.plot(x, kde(x), linewidth=2)
plt.title(f"重尾分布\n超额峰度 = {kurtosis(heavy):.2f}")
plt.xlabel("值")
plt.ylabel("密度")
plt.show()
# -------------------------
# 正态分布
# -------------------------
plt.figure(figsize=(8, 5))
plt.hist(normal, bins=50, density=True, alpha=0.6)
# KDE
x = np.linspace(-4, 4, 1000)
kde = gaussian_kde(normal)
plt.plot(x, kde(x), linewidth=2)
plt.title(f"正态分布\n超额峰度 = {kurtosis(normal):.2f}")
plt.xlabel("值")
plt.ylabel("密度")
plt.show()
# -------------------------
# 轻尾分布
# -------------------------
plt.figure(figsize=(8, 5))
plt.hist(light, bins=50, density=True, alpha=0.6)
# KDE
x = np.linspace(-2.5, 2.5, 1000)
kde = gaussian_kde(light)
plt.plot(x, kde(x), linewidth=2)
plt.title(f"轻尾分布\n超额峰度 = {kurtosis(light):.2f}")
plt.xlabel("值")
plt.ylabel("密度")
plt.show()默认情况下,SciPy 的 kurtosis() 函数返回的是 Fisher 的超额峰度,其中正态分布的值为 0。
#### 5.5 样本峰度与 Fisher 校正
现在,我们对超额峰度有了清晰的理解,实际上我们已经更接近样本数据的峰度公式。
g₂ = m₄ / m₂² − 3
m₂ = (1/n) Σᵢ₌₁ⁿ (xᵢ − x̄)²
m₄ = (1/n) Σᵢ₌₁ⁿ (xᵢ − x̄)⁴
此处,g₂ 表示样本超额峰度。
正如我们之前所学,我们通过将四阶中心矩除以二阶中心矩的平方,然后减去 3(正态分布的峰度)来获得超额峰度。
但正如我们在偏度中看到的那样,这个估计量存在小样本偏差。
因此,我们需要应用校正以获得偏差校正后的样本超额峰度,也称为 Fisher 校正。
G₂ = [(n − 1) / ((n − 2)(n − 3))] · [(n + 1)(m₄/m₂² − 3) + 6]
这就是偏差校正后的样本超额峰度(Fisher 校正)。
在继续之前,还有一个重要的事情需要记住。
正如我之前提到的,人们常常将峰度与尖锐程度联系在一起。但这一观点并不总是正确,也不应成为峰度定义的核心。
两个分布可能具有相似的峰值,但尾部行为却存在显著差异。
峰度与尾部行为及极端观测值的影响密切相关,而不仅仅是对峰值高度的度量。
#### 5.6 偏度与峰度:记忆图
至此,我将用一张记忆图来结束本节内容。
一个微妙但非常重要的一点
一个分布可能具有高偏度但低峰度,或低偏度但高峰度。
为什么?
因为偏度和峰度衡量的是分布的两个不同方面:
- 偏度 → 告诉我们分布的对称性及方向。
- 峰度 → 告诉我们极端值和尾部的行为。
因此,一个分布可以几乎完全对称,但仍具有非常重或非常轻的尾部。
需要记住的关键点是:对称性本身并不能告诉我们极端值的行为。
6. 在 Python 中计算偏度和峰度
我已在上方提供了 Python 代码,但再次向您介绍可用于计算偏度和峰度的函数。
import pandas as pd
df["variable"].skew()
df["variable"].kurt()pandas 的 kurt() 函数默认返回带有偏差校正的费舍尔样本超额峰度。
from scipy.stats import skew, kurtosis
skew(df["variable"])
kurtosis(df["variable"])默认情况下,SciPy 的 skew() 计算有偏样本偏度,而 kurtosis() 返回有偏的费舍尔超额峰度,除非更改相应的偏差校正选项。
7. 缓解偏度:数据变换
我们能否仅通过观察偏度值来判断数据是好还是坏?
在得出任何结论之前,我们必须首先问:
偏度是否真实?它是由极端值或异常值引起的吗?它是否真的影响我们的分析或即将使用的机器学习算法?或者变换是否能有所帮助?
偏度本身并不一定是问题。其重要性取决于数据的性质、分析的目的以及所使用的机器学习算法。
正如我之前提到的,我们可以通过不同的变换来减少偏度。现在,让我们逐一讨论这些方法。
#### 7.1 对数变换
从名称本身可以看出,我们对数值取对数。
对数变换会更强烈地压缩大值,而对小值压缩较弱,这可以显著减少强烈的右偏。
为什么不常用于左偏?
标准对数仅定义在正数上,因此我们不能直接将其应用于包含零或负值的数据。
对于左偏数据,根据数据的性质,可能需要考虑其他变换。
#### 7.2 平方根变换
同样,从名称可以看出,我们对数值取平方根。
平方根变换会压缩较大的值,但不如对数变换激进,因此对于中等程度的右偏可能有用。
然而,它需要非负值。
#### 7.3 立方根变换
在这里,我们对数值取立方根。
立方根的一个有用特性是,它既可以应用于正数,也可以应用于负数。
因此,根据数据的不同,它可用于减少右偏或左偏。
#### 7.4 Box-Cox 变换
Box-Cox变换以两位引入该方法的统计学家George Box和David Cox命名。
这是一种统计技术,旨在寻找一个合适的λ值对数据进行变换,通常目标是使分布更加对称或改善统计模型的假设。
变换公式为:
X^(λ) = (X^λ − 1)/λ,当λ ≠ 0 X^(λ) = ln(X),当λ = 0
当:
λ = 0
Box-Cox变换对应对数变换。
当:
λ ≠ 0
则应用相应的幂变换。
需要记住的一个重要限制是,标准的Box-Cox变换要求数据必须严格为正。
以下是一个展示这些变换如何工作的Python示例:
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import boxcox
import seaborn as sns
# 偏态正态数据
X = np.array([
10, 12, 15, 18, 20, 25,
30, 40, 60, 100, 150, 300
])
# 应用Box-Cox变换
X_boxcox, lambda_boxcox = boxcox(X)
print("Box-Cox lambda:", lambda_boxcox)
# 创建图表
plt.figure(figsize=(12, 5))
# 原始数据
plt.subplot(1, 2, 1)
sns.histplot(X, kde=True, bins=8, stat="density")
plt.title("Original Data")
plt.xlabel("Value")
plt.ylabel("Density")
# Box-Cox变换后的数据
plt.subplot(1, 2, 2)
sns.histplot(X_boxcox, kde=True, bins=8, stat="density")
plt.title(f"Box-Cox Transformed (λ = {lambda_boxcox:.2f})")
plt.xlabel("Transformed Value")
plt.ylabel("Density")
plt.tight_layout()
plt.show()Box-Cox λ : -0.3978727501273978
#### 7.5 Yeo-Johnson变换
Yeo-Johnson变换以2000年引入该方法的两位研究人员In-Kwon Yeo和Richard A. Johnson命名。
Yeo-Johnson变换与Box-Cox变换的目标类似,但可以处理零值和负值,即:
X > 0,X = 0,X < 0
因此,与Box-Cox不同,Yeo-Johnson变换可以应用于包含正数、零和负数的数据。
目标仍然相似,即寻找一种合适的变换以减少偏度并使分布更加对称。
以下是你可用的Python代码示例:
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import yeojohnson
import seaborn as sns
# 包含负值、零和正值的数据
X = np.array([
-100, -50, -30, -20, -10,
-5, 0, 2, 5, 10, 20, 50, 100, 200
])
# 应用Yeo-Johnson变换
X_yeojohnson, lambda_yeojohnson = yeojohnson(X)
print("Yeo-Johnson lambda:", lambda_yeojohnson)
# 创建图表
plt.figure(figsize=(12, 5))
# 原始数据
plt.subplot(1, 2, 1)
sns.histplot(X, kde=True, bins=8)
plt.title("Original Data")
plt.xlabel("Value")
plt.ylabel("Density")
# Yeo-Johnson变换后的数据
plt.subplot(1, 2, 2)
sns.histplot(X_yeojohnson, kde=True, bins=8)
plt.title(f"Yeo-Johnson Transformed (λ = {lambda_yeojohnson:.2f})")
plt.xlabel("Transformed Value")
plt.ylabel("Density")
plt.tight_layout()
plt.show()Yeo-Johnson λ : 0.9090980955368206
8. 标准化与变换
在此必须对两件事有明确的理解:
标准化与偏度、标准化与变换
#### 标准化
标准化将数据转换为均值为0、标准差为1的分布。
由于标准化改变了数据的位置和尺度,但不会改变与偏度和峰度等指标相关的分布形状。
另一方面,
转换可以改变分布的形状,并可能减少偏度。
所以,请记住:
标准化改变尺度。转换可以改变形状。
9. 机器学习中的峰度
现在我们已经理解了峰度背后的数学原理,一个重要问题仍然存在:它在机器学习中如何有用?
峰度可以帮助我们调查极端观测值和尾部行为相对于正态分布的影响。
如果我们观察到高峰度,这给了我们进一步调查的理由。
我们可以寻找:
- 离群值
- 数据质量问题
- 真实的极端观测值
但请记住:
高峰度并不自动意味着我们应该移除极端值。
极端观测值可能是数据中真实且重要的部分。在不了解其来源的情况下移除它,实际上可能会损害我们的分析。
10. 实践中的 EDA 工作流程
对于一个数值特征,我们可以检查 ->
- 均值
- 中位数
- 标准差
- 偏度
- 峰度
然后,通过以下可视化方法 ->
- 直方图
- 箱线图
- 核密度图(KDE Plot)
- Q-Q 图
我们可以更好地理解数据的分布。
这些统计摘要和可视化方法共同构成了探索性数据分析(EDA)的重要部分。
至此,我将用一张 EDA 流程图结束这篇博客。
11. 支持材料
本文中使用的可视化和相关资源可在 GitHub 上找到。
GitHub 仓库
12. 资源
- SciPy 文档 — 用于实现和行为的统计函数,如 skew()、kurtosis()、boxcox() 和 yeojohnson()。
- SciPy 文档 — scipy.stats.skew 的参考,用于计算样本偏度并理解偏倚参数。
- SciPy 文档 — scipy.stats.kurtosis 的参考,用于 Fisher 的超额峰度和偏倚校正选项。
- SciPy 文档 — scipy.stats.boxcox 的参考,用于 Box–Cox 变换及其实现。
- SciPy 文档 — scipy.stats.yeojohnson 的参考,用于 Yeo–Johnson 变换及其实现。
- Pandas 文档 — 描述性统计参考,用于实际示例中的 .skew() 和 .kurt()。
- NIST/SEMATECH 统计方法电子手册 — 统计概念参考,包括矩、偏度、峰度、分布和探索性数据分析。
- George E. P. Box & David R. Cox (1964) 变换分析。《皇家统计学会杂志:B系列》,26(2),211–252。— 引入 Box–Cox 变换的原始论文。
- In-Kwon Yeo & Richard A. Johnson (2000) 一种新的幂变换族以改善正态性或对称性。《生物统计学》,87(4),954–959。— 引入 Yeo–Johnson 变换的原始论文。
- Joanes, D. N. & Gill, C. A. (1998) 比较样本偏度和峰度的度量。《皇家统计学会杂志:D系列(统计学家)》,47(1),183–189。