在研一上学期学习了《大数据分析D》课程,3.3节让我彻底改变了以往对"相关性"的认知,是最让我感到"原来如此"的一章内容。之前本科学统计时,Pearson相关系数几乎成了"万能钥匙"------只要两个变量,就先算个r看看强不强。因此,以往不论是参加比赛还是写本科毕业论文时,习惯性只看Pearson相关系数,一旦接近0就认为"没关系"。经过这一节的学习才对"线性相关为0,不代表无相关"的理解更加深刻------变量间可能存在复杂的非线性依赖。线性相关只是冰山一角,现实世界里变量之间的关系往往弯弯曲曲、非单调,甚至隐藏在噪声背后。非线性相关分析就像给Pearson系上了"透视眼",让我能看到更真实的变量关联。
这一节主要介绍了三种非线性相关度量方法:
- 互信息(Mutual Information) 与熵的联系
- 最大信息系数(Maximal Information Coefficient, MIC)
- 距离相关(Distance Correlation)
下面结合教材内容、我自己的思考、书外案例与代码实践,系统梳理这一节。
3.3.1 为什么需要非线性相关分析?
教材开篇就点明:线性相关指标(如Pearson)对非线性关系不敏感 。
我印象最深的是教材里那句话:"在狭义上,非线性关系指的是不成比例、不能用直线表示的数量关系,通常以曲线表示。"
举个最经典的反例:
变量X均匀分布在[-1,1],Y = X²(抛物线关系)。
Pearson相关系数r ≈ 0,完全捕捉不到明显的二次关系!
这让我想起本科上课老师们会经常举出的例子:性别和学好英语的关系,相关性几乎为0,我就天真地得出"这二者没有关系"。现在回头看,可能两者之间存在复杂的非线性关系(如倒U型),被Pearson彻底忽略了。、
教材强调:Pearson、Spearman等对非线性关系敏感度低。Pearson假设线性关系,Spearman捕捉单调但忽略复杂非单调。
案例:Y = X²(抛物线)
python
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import pearsonr, spearmanr, kendalltau
from sklearn.feature_selection import mutual_info_regression
np.random.seed(42)
n = 1500
x = np.random.uniform(-3, 3, n)
y_quad = x**2 + np.random.normal(0, 1, n) # 加噪声
# 计算指标
pearson_quad = pearsonr(x, y_quad)[0]
spearman_quad = spearmanr(x, y_quad)[0]
kendall_quad = kendalltau(x, y_quad)[0]
mi_quad = mutual_info_regression(x.reshape(-1,1), y_quad)[0]
print(f"二次关系 (Y=X² + 噪声):")
print(f"Pearson: {pearson_quad:.3f}")
print(f"Spearman: {spearman_quad:.3f}")
print(f"Kendall: {kendall_quad:.3f}")
print(f"互信息: {mi_quad:.3f}")
# 可视化
plt.figure(figsize=(8,6))
plt.scatter(x, y_quad, alpha=0.4, s=10)
plt.title('二次关系示例:Pearson失效 (r≈0,但明显强非线性)')
plt.xlabel('X')
plt.ylabel('Y = X² + 噪声')
plt.grid(True)
plt.show()
Pearson失效的经典案例
python
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import pearsonr
# 抛物线关系:Y = X²
np.random.seed(42)
x = np.random.uniform(-2, 2, 1000)
y = x**2 + np.random.normal(0, 0.5, 1000)
pearson_corr, p_value = pearsonr(x, y)
print(f"Pearson相关系数: {pearson_corr:.3f} (接近0,但明显有强非线性关系!)")
# 可视化
plt.scatter(x, y, alpha=0.5)
plt.title('Y = X² + 噪声 (Pearson ≈ 0)')
plt.xlabel('X')
plt.ylabel('Y')
plt.show()
在大数据时代,变量维度动辄成百上千,线性假设往往过于简化。非线性相关分析能帮助我们在特征选择阶段发现更多潜在关联,避免遗漏重要信号。Reshef et al. (2011, Science)指出,传统相关在探索性数据分析中遗漏大量关联。
3.3.2 互信息(Mutual Information)
互信息是信息论中的核心概念,用来衡量两个随机变量共享的信息量。
教材给出的公式:
I(X;Y)=∑x∈X∑y∈Yp(x,y)log(p(x,y)p(x)p(y)) I(X;Y) = \sum_{x\in X}\sum_{y\in Y} p(x,y)\log\left(\frac{p(x,y)}{p(x)p(y)}\right) I(X;Y)=x∈X∑y∈Y∑p(x,y)log(p(x)p(y)p(x,y))
连续变量形式:
I(X;Y)=∬p(x,y)log(p(x,y)p(x)p(y))dxdy I(X;Y) = \iint p(x,y)\log\left(\frac{p(x,y)}{p(x)p(y)}\right) dxdy I(X;Y)=∬p(x,y)log(p(x)p(y)p(x,y))dxdy
性质:
- I(X;Y) ≥ 0,等于0当且仅当X与Y独立
- I(X;Y) = H(X) - H(X|Y) = H(Y) - H(Y|X) = H(X) + H(Y) - H(X,Y)
教材中有一个简单例子:两个二值变量X和Y,计算得到互信息≈0.02(弱相关),而Pearson≈-0.096。
代码示例2:多种经典关系的互信息计算
python
import numpy as np
from sklearn.feature_selection import mutual_info_regression
from scipy.stats import pearsonr, spearmanr
np.random.seed(0)
n = 2000
x = np.linspace(-1, 1, n)
relations = {
'线性': 2 * x + np.random.normal(0, 0.2, n),
'二次': x**2 + np.random.normal(0, 0.1, n),
'正弦': np.sin(6 * np.pi * x) + np.random.normal(0, 0.3, n),
'绝对值': np.abs(x) + np.random.normal(0, 0.1, n),
'独立噪声': np.random.normal(0, 1, n)
}
for name, y in relations.items():
pearson = pearsonr(x, y)[0]
spearman = spearmanr(x, y)[0]
mi = mutual_info_regression(x.reshape(-1, 1), y)[0]
print(f"{name:5} | Pearson: {pearson:.3f} | Spearman: {spearman:.3f} | 互信息: {mi:.3f}")
计算了《活着》小说中主要人物出现频率与章节序号的互信息。结果显示"家珍""凤霞"与章节序号的互信息明显高于随机水平,说明人物出场并非均匀分布,而是随剧情推进有聚集现象。
python
import numpy as np
from sklearn.metrics import mutual_info_score
import pandas as pd
# 假设df中有'chapter'和'count_jiazhen'列
mi = mutual_info_score(df['chapter_bin'], pd.cut(df['count_jiazhen'], bins=5, labels=False))
print(f"家珍出现频率与章节的互信息: {mi:.4f}")
互信息对任意函数关系都敏感,但数值大小难以直观解释(不像Pearson在[-1,1]),且对离散化方式敏感。
3.3.3 最大信息系数(MIC)
MIC是2011年Science上提出的指标,旨在捕捉广泛的函数关系(线性、非线性、周期性等),并将相关强度归一化到[0,1]。
核心思想:
对(X,Y)散点图进行网格划分,寻找使归一化互信息最大的划分方式。
公式:
MIC(X,Y)=maxa×b<BI(D,a,b)log2min(a,b) MIC(X,Y) = \max_{a\times b < B} \frac{I(D,a,b)}{\log_2 \min(a,b)} MIC(X,Y)=a×b<Bmaxlog2min(a,b)I(D,a,b)
其中B通常取n^{0.6}(n为样本量)。
优点:
- 归一化,便于比较
- 对多种函数关系具有"公平性"(equitability)
- 当无关系时≈0,有函数关系时趋近1
缺点: - 计算复杂度较高(O(n^2)左右)
- 对噪声敏感
教材图3-8直观展示了MIC在不同关系下的表现:线性、二次、 sinusoidal、正弦波等都能接近1,而噪声点接近0。
代码示例3:使用minepy批量计算MIC
python
from minepy import MINE
import numpy as np
import matplotlib.pyplot as plt
def test_mic(func, n=1000):
x = np.linspace(-1, 1, n)
y = func(x) + np.random.normal(0, 0.1, n) # 加噪声
mine = MINE(alpha=0.6, c=15)
mine.compute_score(x, y)
return mine.mic()
funcs = [lambda x: x, lambda x: x**2, lambda x: np.sin(5*np.pi*x), lambda x: np.abs(x)]
names = ['线性', '二次', '正弦', '绝对值']
for name, func in zip(names, funcs):
mic = test_mic(func)
print(f"{name}关系的MIC ≈ {mic:.3f}")
MIC的归一化特性让不同类型关系的强度可直接比较。
3.3.4 距离相关(Distance Correlation)
距离相关(dCor)是2007年提出的另一类非线性相关指标,基于距离协方差。
核心优势:当且仅当X与Y独立时dCor=0 ,这比Pearson和Spearman更严格。
教材提到它能检测复杂非线性甚至非函数关系(如圆形、星形等),可见距离相关是非常强大的。
dCor的计算涉及中心化距离矩阵,Python的dcor包实现很方便。
代码示例4:圆形关系的距离相关
python
import numpy as np
import scipy.stats as stats
# 手动实现简化版距离相关(因环境无dcor包)
def distance_correlation(x, y):
x = np.atleast_1d(x)
y = np.atleast_1d(y)
a = np.sqrt(((x[:, None] - x[None, :])**2).sum(-1))
b = np.sqrt(((y[:, None] - y[None, :])**2).sum(-1))
A = a - a.mean(axis=0) - a.mean(axis=1)[:, None] + a.mean()
B = b - b.mean(axis=0) - b.mean(axis=1)[:, None] + b.mean()
cov = np.sqrt((A * B).mean())
var_x = np.sqrt((A * A).mean())
var_y = np.sqrt((B * B).mean())
if var_x * var_y == 0:
return 0
return cov / np.sqrt(var_x * var_y)
# 圆形数据
t = np.random.uniform(0, 2*np.pi, 1000)
x_circle = np.cos(t)
y_circle = np.sin(t) + np.random.normal(0, 0.1, 1000)
dcor_val = distance_correlation(x_circle, y_circle)
pearson_val = pearsonr(x_circle, y_circle)[0]
print(f"圆形关系 | Pearson: {pearson_val:.3f} | 距离相关: {dcor_val:.3f}")
说明:虽然Pearson几乎为0,但距离相关显著捕捉到依赖。Kinney & Atwal (2014)批评MIC的"公平性",推荐距离相关作为更鲁棒选择。
教材中给出了桥梁振动数据(timestamp, amplitude, frequency),计算了互信息、MIC、Pearson、Spearman、Kendall。虽然传统线性/秩相关几乎为0,而互信息和MIC显示出中等强度非线性关系。通过绘制振幅随时间的变化散点图,发现振幅呈现明显的衰减趋势(指数衰减),这解释了为什么线性相关很弱,而MIC能捕捉到这种单调下降的非线性模式。
3.3.5 教材案例复现:桥梁振动数据
代码示例5:生成模拟数据并全面计算
python
import numpy as np
import pandas as pd
from scipy.stats import pearsonr, spearmanr
from sklearn.feature_selection import mutual_info_regression
from minepy import MINE
# 生成模拟桥梁振动数据
np.random.seed(1)
n = 1000
timestamp = np.arange(n)
amplitude = 15 * np.exp(-timestamp / 300) + np.random.normal(0, 0.8, n)
frequency = 12 + 3 * np.cos(2 * np.pi * timestamp / 200) + np.random.normal(0, 0.4, n)
df = pd.DataFrame({'timestamp': timestamp, 'amplitude': amplitude, 'frequency': frequency})
# 计算函数
def analyze_pair(x, y, name):
p = pearsonr(x, y)[0]
s = spearmanr(x, y)[0]
mi = mutual_info_regression(x.reshape(-1,1), y)[0]
mine = MINE(alpha=0.6, c=15)
mine.compute_score(x, y)
m = mine.mic()
print(f"{name}: Pearson={p:.3f}, Spearman={s:.3f}, MI={mi:.3f}, MIC={m:.3f}")
analyze_pair(df['timestamp'], df['amplitude'], "时间 vs 振幅")
analyze_pair(df['amplitude'], df['frequency'], "振幅 vs 频率")
时间与振幅有强非线性衰减,传统线性指标可能低估。
| 方法 | 捕捉线性 | 捕捉非线性 | 归一化 | 对噪声鲁棒性 | 计算复杂度 |
|---|---|---|---|---|---|
| Pearson | ✓ | ✗ | ✓ | 中 | 低 |
| Spearman | ✓(单调) | △ | ✓ | 中 | 中 |
| 互信息 | ✓ | ✓ | ✗ | 低 | 中 |
| MIC | ✓ | ✓ | ✓ | 中 | 高 |
| 距离相关 | ✓ | ✓ | ✓ | 高 | 高 |
个人思考:
- 在特征工程中,没有万能指标,实际项目中建议同时计算多种相关性,形成"指标组合拳"。我现在会优先用MIC或距离相关做初步筛选,再综合判断。
- 非线性相关分析让我意识到:负相关并不等于无相关,弱线性相关也可能隐藏强非线性信号。
- 未来想尝试把MIC融入随机森林的特征重要性评估中,看能否提升模型对非线性特征的敏感度。
- 可视化不可或缺------再高的MIC也可能只是噪声,散点图是最终判断依据。
这一节让我从"只看Pearson"的舒适区走了出来,开始用更开放的视角看待变量关系。数据挖掘的魅力就在于此------永远有更深的规律等待我们去发现。这一节让我从"线性思维"转向"非线性探索"。通过大量代码实践,我不仅理解了理论,还能应用于未来的科研项目。感谢学院提供学习《大数据分析D》的资源和机会,通过课上和课后亲手实操,验证一个又一个"原来如此"!真正理解一个概念,最好的方式就是亲手实现它!
笔记来源:杜同学