Spark MLlib 基础统计模块相关性、卡方检验与向量汇总

一、相关性分析(Correlation):快速算出特征之间的"关系矩阵"

1. 场景:为什么要算相关系数?

在特征工程阶段,我们经常会问:

  • 哪些特征之间高度相关,可能存在冗余?
  • 某个特征和目标变量之间相关性强不强?
  • 是否有一些线性关系比较明显的特征,可以重点关注?

这时最常用的工具就是 相关系数,比如:

  • Pearson 相关系数:衡量线性相关性
  • Spearman 相关系数:基于排序的相关性,更适合非线性、单调关系

在 Spark MLlib 中,Correlation 可以直接对 向量列(Vector column) 计算相关性矩阵

2. API 介绍:Correlation.corr

在 PySpark 中:

python 复制代码
from pyspark.ml.linalg import Vectors
from pyspark.ml.stat import Correlation

data = [
    (Vectors.sparse(4, [(0, 1.0), (3, -2.0)]),),
    (Vectors.dense([4.0, 5.0, 0.0, 3.0]),),
    (Vectors.dense([6.0, 7.0, 0.0, 8.0]),),
    (Vectors.sparse(4, [(0, 9.0), (3, 1.0)]),)
]
df = spark.createDataFrame(data, ["features"])

# 默认方法是 Pearson
r1 = Correlation.corr(df, "features").head()
print("Pearson correlation matrix:\n" + str(r1[0]))

# Spearman 相关系数
r2 = Correlation.corr(df, "features", "spearman").head()
print("Spearman correlation matrix:\n" + str(r2[0]))

几个要点:

  • 输入 DataFrame 中有一列向量列,比如 "features"
  • Correlation.corr(df, "features", method) 会返回一个只有一行一列的 DataFrame,这一列就是相关性矩阵
  • head()[0] 拿到的是一个 DenseMatrix,可以转成字符串打印

3. Pearson vs Spearman:怎么选?

  • Pearson

    • 假设变量之间是 线性 关系
    • 对异常值较为敏感
    • 是最常用、最经典的相关系数
  • Spearman

    • 把数值转成 秩(rank),再算 Pearson
    • 不要求线性,只要是单调关系就能体现
    • 对异常值更鲁棒

实践建议:

  • 连续特征线性关系分析:优先用 Pearson
  • 数据有明显非线性趋势、或者有很多异常点:可以尝试 Spearman

4. 典型用法:特征筛选 & 多重共线性检查

  • 你可以对特征列构建一个大的 features 向量,然后用 Correlation.corr 算出相关系数矩阵:

    • 高度相关(例如 |ρ| > 0.9)的特征可以考虑做降维或只保留一个
  • 某些特征与标签的相关性太弱:可以考虑剔除或降低权重(当然不能只看相关系数,还是要配合业务理解)

二、假设检验与卡方检验(ChiSquareTest):离散特征和标签到底有没有关系?

1. 核心问题:这个特征和标签真有关系吗?

在分类问题中,我们经常有离散特征 / 类别型特征,例如:

  • 用户职业(学生 / 上班族 / 自由职业)
  • 设备类型(iOS / Android / Web)
  • 地区(省份 / 城市)

我们想知道的问题通常是:

这个离散特征和 "是否点击 / 是否购买 / 是否违约" 等标签,

是否存在统计意义上的相关性?

这时就轮到 卡方检验(Chi-square test) 出场了。

2. MLlib 中的 ChiSquareTest:特征 vs 标签 独立性检验

spark.ml.stat.ChiSquareTest 提供了对每一维特征与标签之间做 Pearson 卡方独立性检验 的功能:

  • 对每个特征维度,构造一个 列联表(contingency table)
  • 计算卡方统计量(χ²)、自由度和 p-value
  • 判断是否拒绝 "特征和标签相互独立" 这个零假设

👉 前提:特征和标签都必须是离散 / 类别值。

3. Python 示例

python 复制代码
from pyspark.ml.linalg import Vectors
from pyspark.ml.stat import ChiSquareTest

data = [
    (0.0, Vectors.dense(0.5, 10.0)),
    (0.0, Vectors.dense(1.5, 20.0)),
    (1.0, Vectors.dense(1.5, 30.0)),
    (0.0, Vectors.dense(3.5, 30.0)),
    (0.0, Vectors.dense(3.5, 40.0)),
    (1.0, Vectors.dense(3.5, 40.0))
]
df = spark.createDataFrame(data, ["label", "features"])

r = ChiSquareTest.test(df, "features", "label").head()

print("pValues: " + str(r.pValues))
print("degreesOfFreedom: " + str(r.degreesOfFreedom))
print("statistics: " + str(r.statistics))
  • ChiSquareTest.test(df, "features", "label") 返回一个 DataFrame,每一行对应一次测试结果
  • .head() 拿到第一行结果
  • r.pValues:每一个特征维度对应一个 p-value
  • r.degreesOfFreedom:每个特征对应的自由度
  • r.statistics:对应的卡方统计量

4. 怎么解读结果?

  • 原假设 H₀:特征和标签相互独立
  • 备择假设 H₁:特征和标签不独立(存在相关性)

通常我们会设定一个显著性水平,比如 α = 0.05:

  • 如果 pValue < 0.05

    • 拒绝独立性假设
    • 说明该特征与标签之间有显著的统计相关性,可以认为是"有用"的
  • 如果 pValue ≥ 0.05

    • 不能拒绝独立性假设
    • 说明没观察到足够强的统计证据证明它和标签有关

5. 实战中的典型用途

  • 离散特征的筛选

    • 对每个类别型特征做卡方检验
    • 剔除与标签"几乎无关"的特征,减轻模型负担
  • 对特征工程结果做验证

    • 比如你做了某些桶化 / 分箱操作,可以用卡方检验看看新特征是否和标签有更强的统计相关性
  • 模型解释

    • 给业务方输出"哪些类别特征和目标最相关"的证据时,卡方检验是一个很好的工具

三、Summarizer:一行代码搞定向量列的均值、方差、非零比例......

1. 问题:如何快速看一列向量特征的整体分布?

假设你的 DataFrame 里有一列是向量特征 "features"

  • 每一行是一个样本的特征向量

  • 你想知道每一维特征的:

    • 均值(mean)
    • 方差(variance)
    • 最大值 / 最小值(max/min)
    • 非零元素个数(numNonZeros)
    • 总计数(count)等

这时就可以用 Summarizer

2. API 介绍:Summarizer.metrics

示例代码:

python 复制代码
from pyspark.ml.stat import Summarizer
from pyspark.sql import Row
from pyspark.ml.linalg import Vectors

df = sc.parallelize([
    Row(weight=1.0, features=Vectors.dense(1.0, 1.0, 1.0)),
    Row(weight=0.0, features=Vectors.dense(1.0, 2.0, 3.0))
]).toDF()

# 1. 创建一个 summarizer,指定要计算的指标
summarizer = Summarizer.metrics("mean", "count")

# 2. 计算带权重的统计指标
df.select(summarizer.summary(df.features, df.weight)).show(truncate=False)

# 3. 计算不带权重的统计指标
df.select(summarizer.summary(df.features)).show(truncate=False)

# 4. 单独计算 "mean" 带权重
df.select(Summarizer.mean(df.features, df.weight)).show(truncate=False)

# 5. 单独计算 "mean" 不带权重
df.select(Summarizer.mean(df.features)).show(truncate=False)

几个关键点:

  • Summarizer.metrics("mean", "count", "variance", ...) 用来指定要计算的指标

  • summarizer.summary(df.features, df.weight)

    • 第一个参数是向量列
    • 第二个参数是权重列(可选)
  • 如果不传权重列,则表示所有样本权重相同

  • 也可以直接用 Summarizer.mean(...)Summarizer.variance(...) 这种"快捷方法"

3. 权重的意义

权重在很多场景下会很有用,比如:

  • 你的数据是预聚合结果(比如某个样本出现了 n 次)
  • 某些样本在建模中更重要(例如高价值用户)
  • 用采样的数据估计总体统计量时,需要做加权修正

有了 weight 列,可以很方便地得到加权均值加权方差等。

4. Summarizer 支持的指标

官方支持的指标包括:

  • mean:均值
  • variance:方差
  • std:标准差
  • min / max:按列最小值 / 最大值
  • sum:按列求和
  • numNonZeros:按列非零元素个数
  • count:总样本数

这些统计量基本覆盖了 EDA(探索性数据分析)中最常用的一批指标。

四、把基础统计能力融入你的 ML Pipeline

虽然 CorrelationChiSquareTestSummarizer 看起来"只是统计工具",

但在实际的 ML 项目中,它们可以自然地融入到你的整体流程中:

  1. 数据理解阶段

    • 用 Summarizer 看每一维特征的均值/方差/非零比例,识别:

      • 常量特征(variance=0)
      • 极端稀疏或极端密集的特征
    • 用 Correlation 看特征之间的线性相关性,初步感知特征结构

  2. 特征筛选阶段

    • 对离散特征用 ChiSquareTest 筛掉"和标签没有关系"的变量
    • 对连续特征,用相关系数 + 业务理解做初步筛选和降维
  3. 模型调试与解释阶段

    • 用 Summarizer 跟踪不同阶段特征处理后的数据分布是否合理
    • 用 Correlation 和 ChiSquareTest 为"为什么选这些特征"提供统计证据

从工程实践角度看,这些基础统计模块是 MLlib 中非常值得熟练掌握的一块 ------

它们不是"锦上添花",而是很多实战问题的"起手式"。

五、总结

Spark MLlib 提供的基础统计工具大致可以归纳为三类:

  1. Correlation(相关性分析)

    • 支持 Pearson / Spearman
    • 面向向量列,计算相关性矩阵
    • 适用于特征筛选、多重共线性检查、数据理解等场景
  2. ChiSquareTest(卡方独立性检验)

    • 针对离散特征与标签的独立性检验
    • 输出 p-value、自由度、统计量
    • 常用于类别特征的筛选和假设验证
  3. Summarizer(向量列汇总统计)

    • 提供均值、方差、标准差、max/min、sum、非零数、count 等指标
    • 支持权重,适合加权统计场景
    • 是 EDA 与特征监控的基础工具

如果你已经在用 Spark 做机器学习,不妨把 spark.ml.stat 这几个组件视为自己的"统计瑞士军刀",

在建模前后多用一用,很多肉眼看不出的数据问题,都能靠这些基本统计手段提前暴露出来。

相关推荐
Yuyang_Leo22 天前
Spark Core vs Spark MLlib:从数据处理到机器学习的完整指南
人工智能·机器学习·spark-ml
GG向前冲1 个月前
【大数据】Spark MLlib 机器学习流水线搭建
大数据·机器学习·spark-ml
Thomas21433 个月前
sparkml pipeline 使用案例
spark-ml
Thomas21433 个月前
sparkml 多列共享labelEncoder pipeline方案
spark-ml
Thomas21433 个月前
sparkml 多列共享labelEncoder
javascript·ajax·spark-ml
悟乙己3 个月前
在 PySpark ML 中LightGBM比XGBoost更好(二)
spark-ml
Lenskit3 个月前
使用pyspark对上百亿行的hive表生成稀疏向量
python·spark-ml·spark
程序猿阿伟6 个月前
《深度探秘:Java构建Spark MLlib与TensorFlow Serving混合推理流水线》
java·spark-ml·tensorflow
武子康6 个月前
大数据-276 Spark MLib - 基础介绍 机器学习算法 Bagging和Boosting区别 GBDT梯度提升树
大数据·人工智能·算法·机器学习·语言模型·spark-ml·boosting