【Scala统计学系列】scala spark ChiSqTest Statistics卡方统计用法示例源码详解

spark ChiSqTest Statistics卡方统计用法示例源码详解

ChiSqTest

用法

源码分析

org.apache.spark.mllib.stat.test.ChiSqTest是Spark中用于执行卡方检验的类。它提供了计算卡方检验的方法,包括拟合度检验(goodness-of-fit test)和独立性检验(test of independence),以及计算每个特征与标签之间卡方统计量的方法。

关键点总结如下:

  • 类定义:private[spark] object ChiSqTest extends Logging
  • 方法:
    • chiSquaredFeatures方法:对输入的RDD的每个特征与标签进行Pearson独立性检验,返回一个包含每个特征与标签之间的ChiSquaredTestResult的数组。
    • chiSquared方法:对输入的观察值和期望值进行Pearson的拟合度检验,返回一个ChiSquaredTestResult对象。
    • chiSquaredMatrix方法:对输入的列联表进行Pearson的独立性检验,返回一个ChiSquaredTestResult对象。
  • 常量:
    • maxCategories:索引标签和特征时的最大类别数,默认为10000。
  • 内部类:
    • Method:表示卡方检验的方法,包括方法名称和计算统计量的函数。
    • NullHypothesis:枚举类型,表示不同类型卡方检验的零假设。

该类还包含一些辅助方法,如解析方法名称、验证输入参数等。

中文源码

package org.apache.spark.mllib.stat.test

import scala.collection.mutable

import breeze.linalg.{DenseMatrix => BDM}
import org.apache.commons.math3.distribution.ChiSquaredDistribution

import org.apache.spark.SparkException
import org.apache.spark.internal.Logging
import org.apache.spark.mllib.linalg.{Matrices, Matrix, Vector, Vectors}
import org.apache.spark.mllib.regression.LabeledPoint
import org.apache.spark.rdd.RDD

/**
 * 使用指定的方法对输入的RDD进行卡方检验。
 * 对于两个向量,进行拟合度检验(goodness-of-fit test);
 * 对于矩阵,进行独立性检验(test of independence),评估列之间是否独立。
 * 还提供了一种方法,用于计算输入RDD中每个特征与标签之间的卡方统计量,
 * 返回一个大小为特征数量的`Array[ChiSquaredTestResult]`。
 *
 * 支持的拟合度检验方法:`pearson`(默认)
 * 支持的独立性检验方法:`pearson`(默认)
 *
 * 更多关于卡方检验的信息:http://en.wikipedia.org/wiki/Chi-squared_test
 */
private[spark] object ChiSqTest extends Logging {

  /**
   * @param name 方法的名称。
   * @param chiSqFunc 计算统计量的函数,给定观察值和期望值。
   */
  case class Method(name: String, chiSqFunc: (Double, Double) => Double)

  // Pearson's chi-squared test: http://en.wikipedia.org/wiki/Pearson%27s_chi-squared_test
  val PEARSON = new Method("pearson", (observed: Double, expected: Double) => {
    val dev = observed - expected
    dev * dev / expected
  })

  // 不同类型的卡方检验的零假设,将包含在结果中。
  object NullHypothesis extends Enumeration {
    type NullHypothesis = Value
    val goodnessOfFit = Value("观察值遵循与期望值相同的分布。")
    val independence = Value("结果的出现是统计独立的。")
  }

  // 根据输入的方法名称返回对应的方法
  private def methodFromString(methodName: String): Method = {
    methodName match {
      case PEARSON.name => PEARSON
      case _ => throw new IllegalArgumentException("未知的卡方检验方法。")
    }
  }

  /**
   * 索引标签和特征时的最大类别数
   */
  private[spark] val maxCategories: Int = 10000

  /**
   * 对输入RDD的每个特征与标签进行Pearson独立性检验。
   * 构建由原始(特征,标签)对构成的列联表,并用其进行独立性检验。
   * 返回一个包含每个特征与标签之间的ChiSquaredTestResult的数组。
   */
  def chiSquaredFeatures(data: RDD[LabeledPoint],
      methodName: String = PEARSON.name): Array[ChiSqTestResult] = {
    val numCols = data.first().features.size
    val results = new Array[ChiSqTestResult](numCols)
    var labels: Map[Double, Int] = null
    // 每次最多处理1000列
    val batchSize = 1000
    var batch = 0
    while (batch * batchSize < numCols) {
      // 下面的代码块可以整理并公开为 chiSquared(data: RDD[(V1, V2)]) 方法
      val startCol = batch * batchSize
      val endCol = startCol + math.min(batchSize, numCols - startCol)
      val pairCounts = data.mapPartitions { iter =>
        val distinctLabels = mutable.HashSet.empty[Double]
        val allDistinctFeatures: Map[Int, mutable.HashSet[Double]] =
          Map((startCol until endCol).map(col => (col, mutable.HashSet.empty[Double])): _*)
        var i = 1
        iter.flatMap { case LabeledPoint(label, features) =>
          if (i % 1000 == 0) {
            if (distinctLabels.size > maxCategories) {
              throw new SparkException(s"卡方检验期望因子(分类值),但发现了超过$maxCategories个不同的标签值。")
            }
            allDistinctFeatures.foreach { case (col, distinctFeatures) =>
              if (distinctFeatures.size > maxCategories) {
                throw new SparkException(s"卡方检验期望因子(分类值),但在第$col列中发现了超过$maxCategories个不同的值。")
              }
            }
          }
          i += 1
          distinctLabels += label
          val brzFeatures = features.asBreeze
          (startCol until endCol).map { col =>
            val feature = brzFeatures(col)
            allDistinctFeatures(col) += feature
            (col, feature, label)
          }
        }
      }.countByValue()

      if (labels == null) {
        // 仅对第一列进行此操作,因为标签在特征之间是不变的。
        labels =
          pairCounts.keys.filter(_._1 == startCol).map(_._3).toArray.distinct.zipWithIndex.toMap
      }
      val numLabels = labels.size
      pairCounts.keys.groupBy(_._1).foreach { case (col, keys) =>
        val features = keys.map(_._2).toArray.distinct.zipWithIndex.toMap
        val numRows = features.size
        val contingency = new BDM(numRows, numLabels, new Array[Double](numRows * numLabels))
        keys.foreach { case (_, feature, label) =>
          val i = features(feature)
          val j = labels(label)
          contingency(i, j) += pairCounts((col, feature, label))
        }
        results(col) = chiSquaredMatrix(Matrices.fromBreeze(contingency), methodName)
      }
      batch += 1
    }
    results
  }

  /*
   * 对输入的观察值和期望值进行Pearson的拟合度检验。
   * 当没有传入`expected`时,假设服从均匀分布。
   */
  def chiSquared(observed: Vector,
      expected: Vector = Vectors.dense(Array.empty[Double]),
      methodName: String = PEARSON.name): ChiSqTestResult = {

    // 验证输入参数
    val method = methodFromString(methodName)
    if (expected.size != 0 && observed.size != expected.size) {
      throw new IllegalArgumentException("观察值和期望值必须具有相同的大小。")
    }
    val size = observed.size
    if (size > 1000) {
      logWarning("由于期望频率较低,卡方近似可能不准确,这是由于类别数较多导致的: $size.")
    }
    val obsArr = observed.toArray
    val expArr = if (expected.size == 0) Array.tabulate(size)(_ => 1.0 / size) else expected.toArray
    if (!obsArr.forall(_ >= 0.0)) {
      throw new IllegalArgumentException("观察向量中不允许出现负值。")
    }
    if (expected.size != 0 && !expArr.forall(_ >= 0.0)) {
      throw new IllegalArgumentException("期望向量中不允许出现负值。")
    }

    // 确定期望的缩放因子
    val obsSum = obsArr.sum
    val expSum = if (expected.size == 0.0) 1.0 else expArr.sum
    val scale = if (math.abs(obsSum - expSum) < 1e-7) 1.0 else obsSum / expSum

    // 计算卡方统计量
    val statistic = obsArr.zip(expArr).foldLeft(0.0) { case (stat, (obs, exp)) =>
      if (exp == 0.0) {
        if (obs == 0.0) {
          throw new IllegalArgumentException("由于观察值和期望值都为0,无法计算卡方统计量。")
        } else {
          return new ChiSqTestResult(0.0, size - 1, Double.PositiveInfinity, PEARSON.name,
            NullHypothesis.goodnessOfFit.toString)
        }
      }
      if (scale == 1.0) {
        stat + method.chiSqFunc(obs, exp)
      } else {
        stat + method.chiSqFunc(obs, exp * scale)
      }
    }
    val df = size - 1
    val pValue = 1.0 - new ChiSquaredDistribution(df).cumulativeProbability(statistic)
    new ChiSqTestResult(pValue, df, statistic, PEARSON.name, NullHypothesis.goodnessOfFit.toString)
  }

  /*
   * 对输入的列联表进行Pearson的独立性检验。
   * TODO: 在支持稀疏矩阵时进行优化。
   */
  def chiSquaredMatrix(counts: Matrix, methodName: String = PEARSON.name): ChiSqTestResult = {
    val method = methodFromString(methodName)
    val numRows = counts.numRows
    val numCols = counts.numCols

    // 获取行和列的和
    val colSums = new Array[Double](numCols)
    val rowSums = new Array[Double](numRows)
    val colMajorArr = counts.toArray
    val colMajorArrLen = colMajorArr.length

    var i = 0
    while (i < colMajorArrLen) {
      val elem = colMajorArr(i)
      if (elem < 0.0) {
        throw new IllegalArgumentException("列联表不能包含负值。")
      }
      colSums(i / numRows) += elem
      rowSums(i % numRows) += elem
      i += 1
    }
    val total = colSums.sum

    // 第二次遍历计算统计量
    var statistic = 0.0
    var j = 0
    while (j < colMajorArrLen) {
      val col = j / numRows
      val colSum = colSums(col)
      if (colSum == 0.0) {
        throw new IllegalArgumentException("由于第 [$col] 列的和为0,无法计算输入矩阵的卡方统计量。")
      }
      val row = j % numRows
      val rowSum = rowSums(row)
      if (rowSum == 0.0) {
        throw new IllegalArgumentException("由于第 [$row] 行的和为0,无法计算输入矩阵的卡方统计量。")
      }
      val expected = colSum * rowSum / total
      statistic += method.chiSqFunc(colMajorArr(j), expected)
      j += 1
    }
    val df = (numCols - 1) * (numRows - 1)
    if (df == 0) {
      // 只有1列或1行。常数分布与任何内容都是独立的。
      // 在这种情况下,pValue = 1.0 和 statistic = 0.0。
      new ChiSqTestResult(1.0, 0, 0.0, methodName, NullHypothesis.independence.toString)
    } else {
      val pValue = 1.0 - new ChiSquaredDistribution(df).cumulativeProbability(statistic)
      new ChiSqTestResult(pValue, df, statistic, methodName, NullHypothesis.independence.toString)
    }
  }
}

Statistics

用法

Spark MLlib的Statistics类提供了一组用于统计分析的方法。以下是对每个方法的总结和用法:

  • colStats(X: RDD[Vector]): MultivariateStatisticalSummary

    • 计算输入RDD[Vector]的列统计摘要。
    • 返回包含列统计摘要的MultivariateStatisticalSummary对象。
    • 示例:
      val X: RDD[Vector] = ???
      val summary: MultivariateStatisticalSummary = Statistics.colStats(X)
      
  • corr(X: RDD[Vector]): Matrix

    • 计算输入RDD[Vector]的Pearson相关矩阵。
    • 返回比较X中列的Pearson相关矩阵。
    • 示例:
      val X: RDD[Vector] = ???
      val corrMatrix: Matrix = Statistics.corr(X)
      
  • corr(X: RDD[Vector], method: String): Matrix

    • 使用指定的方法计算输入RDD[Vector]的相关矩阵。
    • 目前支持的方法有pearson(默认)和spearman
    • 示例:
      val X: RDD[Vector] = ???
      val corrMatrix: Matrix = Statistics.corr(X, "spearman")
      
  • corr(x: RDD[Double], y: RDD[Double]): Double

    • 计算两个输入RDD[Double]的Pearson相关系数。
    • 返回两个输入RDD[Double]之间的Pearson相关系数。
    • 示例:
      val x: RDD[Double] = ???
      val y: RDD[Double] = ???
      val correlation: Double = Statistics.corr(x, y)
      
  • corr(x: RDD[Double], y: RDD[Double], method: String): Double

    • 使用指定的方法计算两个输入RDD[Double]的相关系数。
    • 目前支持的方法有pearson(默认)和spearman
    • 返回使用指定方法计算的两个输入RDD[Double]之间的相关系数。
    • 示例:
      val x: RDD[Double] = ???
      val y: RDD[Double] = ???
      val correlation: Double = Statistics.corr(x, y, "spearman")
      
  • chiSqTest(observed: Vector, expected: Vector): ChiSqTestResult

    • 对观测数据进行Pearson卡方拟合度检验,验证其是否符合期望的分布。
    • 返回包含检验统计量、自由度、p-value、使用的方法和零假设的ChiSqTestResult对象。
    • 示例:
      val observed: Vector = ???
      val expected: Vector = ???
      val result: ChiSqTestResult = Statistics.chiSqTest(observed, expected)
      
  • chiSqTest(observed: Vector): ChiSqTestResult

    • 对观测数据进行Pearson卡方拟合度检验,验证其是否符合均匀分布。
    • 返回包含检验统计量、自由度、p-value、使用的方法和零假设的ChiSqTestResult对象。
    • 示例:
      val observed: Vector = ???
      val result: ChiSqTestResult = Statistics.chiSqTest(observed)
      
  • chiSqTest(observed: Matrix): ChiSqTestResult

    • 对输入的列联表进行Pearson独立性检验。
    • 返回包含检验统计量、自由度、p-value、使用的方法和零假设的ChiSqTestResult对象。
    • 示例:
      val observed: Matrix = ???
      val result: ChiSqTestResult = Statistics.chiSqTest(observed)
      
  • chiSqTest(data: RDD[LabeledPoint]): Array[ChiSqTestResult]

    • 在输入RDD上对每个特征相对于标签进行Pearson独立性检验。
    • 返回包含每个特征相对于标签的ChiSqTestResult的数组。
    • 示例:
      val data: RDD[LabeledPoint] = ???
      val results: Array[ChiSqTestResult] = Statistics.chiSqTest(data)
      
  • kolmogorovSmirnovTest(data: RDD[Double], cdf: Double => Double): KolmogorovSmirnovTestResult

    • 对从连续分布中采样的数据进行双边Kolmogorov-Smirnov(KS)检验。
    • 返回包含测试统计量、p-value和零假设的KolmogorovSmirnovTestResult对象。
    • 示例:
      val data: RDD[Double] = ???
      val cdf: Double => Double = ???
      val result: KolmogorovSmirnovTestResult = Statistics.kolmogorovSmirnovTest(data, cdf)
      
  • kolmogorovSmirnovTest(data: RDD[Double], distName: String, params: Double*): KolmogorovSmirnovTestResult

    • 进行一样本、双边Kolmogorov-Smirnov(KS)概率分布相等性检验的便捷函数。
    • 支持的理论分布有正态分布(distName = "norm")。
    • 返回包含测试统计量、p-value和零假设的KolmogorovSmirnovTestResult对象。
    • 示例:
      val data: RDD[Double] = ???
      val distName: String = ???
      val params: Double* = ???
      val result: KolmogorovSmirnovTestResult = Statistics.kolmogorovSmirnovTest(data, distName, params: _*)
      

这些方法可以帮助您进行统计分析,例如计算列统计摘要、相关矩阵、相关系数,以及进行卡方拟合度检验和KS检验。根据您的需求,选择适当的方法并提供所需的输入数据即可。

示例

package org.example.spark
import org.apache.spark.mllib.linalg._
import org.apache.spark.mllib.regression.LabeledPoint
import org.apache.spark.mllib.stat.{MultivariateStatisticalSummary, Statistics}
import org.apache.spark.mllib.stat.test.ChiSqTestResult
import org.apache.spark.rdd.RDD
import org.apache.spark.sql.SparkSession

object StatisticsExample {
  def main(args: Array[String]): Unit = {
    val spark = SparkSession.builder()
      .appName("StatisticsExample")
      .master("local[*]")
      .getOrCreate()

    val sc = spark.sparkContext
    sc.setLogLevel("error")

    // 示例数据
    val vec: Vector = Vectors.dense(0.1, 0.15, 0.2, 0.3, 0.25)
    val mat: Matrix = Matrices.dense(3, 3, Array(1.0, 3.0, 5.0, 2.0, 4.0, 6.0,7.0,8.0,9.0))
    val obs: RDD[LabeledPoint] = sc.parallelize(Seq(
      LabeledPoint(1.0, Vectors.dense(1.0, 0.0, 3.0)),
      LabeledPoint(1.0, Vectors.dense(1.0, 2.0, 0.0)),
      LabeledPoint(-1.0, Vectors.dense(-1.0, 0.0, -0.5))
    ))
    val v1 = Vectors.dense(176, 406)
    val v2 = Vectors.dense(210, 372)

    // 计算列统计摘要
    val summary: MultivariateStatisticalSummary = Statistics.colStats(obs.map(_.features))
    println("Column Summary Statistics:")
    println(s"Mean: ${summary.mean}")
    println(s"Variance: ${summary.variance}")

    // 计算Pearson相关矩阵
    val corrMatrix: Matrix = Statistics.corr(obs.map(_.features), "pearson")
    println("\nPearson Correlation Matrix:")
    println(corrMatrix)

    // 进行卡方拟合度检验
    val observed: Vector = Vectors.dense(10, 20, 30)
    val expected: Vector = Vectors.dense(15, 15, 30)
    val chiSqTestResult: ChiSqTestResult = Statistics.chiSqTest(observed, expected)
    println("\nChi-Square Goodness of Fit Test:")
    println(chiSqTestResult)

    // 进行独立性检验
    val independenceTestResult: ChiSqTestResult = Statistics.chiSqTest(mat)
    println("\nChi-Square Independence Test:")
    println(independenceTestResult)

    // 对每个特征相对于标签进行独立性检验
    val featureTestResults: Array[ChiSqTestResult] = Statistics.chiSqTest(obs)
    println("\nFeature Independence Tests:")
    featureTestResults.zipWithIndex.foreach { case (result, index) =>
      println(s"Feature ${index + 1}:")
      println(result)
    }

    // chi test
    val chiTestResult = Statistics.chiSqTest(v1, v2)
    println(chiTestResult)

    spark.stop()
  }
}

//Column Summary Statistics:
//Mean: [0.3333333333333333,0.6666666666666666,0.8333333333333333]
//Variance: [1.3333333333333333,1.3333333333333333,3.5833333333333335]
//
//Pearson Correlation Matrix:
//1.0                 0.5                  0.6099942813304188
//0.5                 1.0                  -0.3812464258315116
//0.6099942813304188  -0.3812464258315116  1.0
//
//Chi-Square Goodness of Fit Test:
//Chi squared test summary:
//method: pearson
//degrees of freedom = 2
//statistic = 3.3333333333333335
//pValue = 0.1888756028375621
//No presumption against null hypothesis: observed follows the same distribution as expected..
//
//Chi-Square Independence Test:
//Chi squared test summary:
//method: pearson
//degrees of freedom = 4
//statistic = 1.78125
//pValue = 0.7759109366353244
//No presumption against null hypothesis: the occurrence of the outcomes is statistically independent..
//
//Feature Independence Tests:
//Feature 1:
//Chi squared test summary:
//method: pearson
//degrees of freedom = 1
//statistic = 3.0000000000000004
//pValue = 0.08326451666354884
//Low presumption against null hypothesis: the occurrence of the outcomes is statistically independent..
//Feature 2:
//Chi squared test summary:
//method: pearson
//degrees of freedom = 1
//statistic = 0.75
//pValue = 0.3864762307712326
//No presumption against null hypothesis: the occurrence of the outcomes is statistically independent..
//Feature 3:
//Chi squared test summary:
//method: pearson
//degrees of freedom = 2
//statistic = 3.0
//pValue = 0.22313016014843035
//No presumption against null hypothesis: the occurrence of the outcomes is statistically independent..
//Chi squared test summary:
//method: pearson
//degrees of freedom = 1
//statistic = 8.612288786482335
//pValue = 0.003339024479776409
//Very strong presumption against null hypothesis: observed follows the same distribution as expected..
//
// 

中文源码

/**
 * MLlib中统计函数的API。
 */
@Since("1.1.0")
object Statistics {

  /**
   * 计算输入RDD[Vector]的列统计摘要。
      *
   * @param X 要计算列统计摘要的RDD[Vector]。
   * @return 包含列统计摘要的[[MultivariateStatisticalSummary]]对象。
      */
    @Since("1.1.0")
    def colStats(X: RDD[Vector]): MultivariateStatisticalSummary = {

    new RowMatrix(X).computeColumnSummaryStatistics()
  }

  /**
   * 计算输入RDD[Vector]的Pearson相关矩阵。
   * 协方差为0的列在相关矩阵中产生NaN条目。
      *
   * @param X 要计算相关矩阵的RDD[Vector]。
   * @return 比较X中列的Pearson相关矩阵。
      */
    @Since("1.1.0")
    def corr(X: RDD[Vector]): Matrix = Correlations.corrMatrix(X)

  /**
   * 使用指定的方法计算输入RDD[Vector]的相关矩阵。
   * 目前支持的方法:`pearson`(默认)、`spearman`。
      *
   * @param X 要计算相关矩阵的RDD[Vector]。
   * @param method 指定用于计算相关性的方法的字符串。
   *               支持:`pearson`(默认)、`spearman`
   * @return 比较X中列的相关矩阵。
      *
   * @note 对于Spearman相关性(一种等级相关性),我们需要为每列创建一个RDD[Double],
   * 并对其进行排序以获取排名,然后将列重新连接成一个RDD[Vector],这是非常耗时的操作。
   * 在调用`method = "spearman"`的corr之前,先缓存输入RDD,以避免重新计算公共血统。
      */
    @Since("1.1.0")
    def corr(X: RDD[Vector], method: String): Matrix = Correlations.corrMatrix(X, method)

  /**
   * 计算两个输入RDD[Double]的Pearson相关系数。
   * 如果任一向量方差为0,则返回NaN。
      *
   * @param x 与y具有相同基数的RDD[Double]。
   * @param y 与x具有相同基数的RDD[Double]。
   * @return 包含两个输入RDD[Double]之间的Pearson相关系数的Double。
      *
   * @note 两个输入RDD需要具有相同数量的分区和每个分区中的相同数量的元素。
      */
    @Since("1.1.0")
    def corr(x: RDD[Double], y: RDD[Double]): Double = Correlations.corr(x, y)

  /**
   * `corr()`的Java友好版本
      */
    @Since("1.4.1")
    def corr(x: JavaRDD[java.lang.Double], y: JavaRDD[java.lang.Double]): Double =

    corr(x.rdd.asInstanceOf[RDD[Double]], y.rdd.asInstanceOf[RDD[Double]])

  /**
   * 使用指定的方法计算两个输入RDD[Double]的相关系数。
   * 目前支持的方法:`pearson`(默认)、`spearman`。
      *
   * @param x 与y具有相同基数的RDD[Double]。
   * @param y 与x具有相同基数的RDD[Double]。
   * @param method 指定用于计算相关性的方法的字符串。
   *               支持:`pearson`(默认)、`spearman`
   * @return 包含使用指定方法计算的两个输入RDD[Double]之间的相关系数的Double。
      *
   * @note 两个输入RDD需要具有相同数量的分区和每个分区中的相同数量的元素。
      */
    @Since("1.1.0")
    def corr(x: RDD[Double], y: RDD[Double], method: String): Double = Correlations.corr(x, y, method)

  /**
   * `corr()`的Java友好版本
      */
    @Since("1.4.1")
    def corr(x: JavaRDD[java.lang.Double], y: JavaRDD[java.lang.Double], method: String): Double =

    corr(x.rdd.asInstanceOf[RDD[Double]], y.rdd.asInstanceOf[RDD[Double]], method)

  /**
   * 对观测数据进行Pearson卡方拟合度检验,以验证其是否符合期望的分布。
      *
   * @param observed 包含观测分类计数/相对频率的向量。
   * @param expected 包含期望分类计数/相对频率的向量。
   *                 如果`expected`总和与`observed`总和不同,则会重新调整`expected`。
   * @return 包含检验统计量、自由度、p-value、使用的方法和零假设的ChiSquaredTestResult对象。
      *
   * @note 两个输入向量需要具有相同的大小。
   * `observed`不能包含负值。
   * `expected`不能包含非正值。
      */
    @Since("1.1.0")
    def chiSqTest(observed: Vector, expected: Vector): ChiSqTestResult = {

    ChiSqTest.chiSquared(observed, expected)
  }

  /**
   * 对观测数据进行Pearson卡方拟合度检验,以验证其是否符合均匀分布,
   * 其中每个类别的期望频率为`1 / observed.size`。
      *
   * @param observed 包含观测分类计数/相对频率的向量。
   * @return 包含检验统计量、自由度、p-value、使用的方法和零假设的ChiSquaredTestResult对象。
      *
   * @note `observed`不能包含负值。
      */
    @Since("1.1.0")
    def chiSqTest(observed: Vector): ChiSqTestResult = ChiSqTest.chiSquared(observed)

  /**
   * 对输入的列联表进行Pearson独立性检验,其中不能包含负条目或列或行总和为0。
      *
   * @param observed 列联表(包含计数或相对频率)。
   * @return 包含检验统计量、自由度、p-value、使用的方法和零假设的ChiSquaredTestResult对象。
      */
    @Since("1.1.0")
    def chiSqTest(observed: Matrix): ChiSqTestResult = ChiSqTest.chiSquaredMatrix(observed)

  /**
   * 在输入RDD上对每个特征相对于标签进行Pearson独立性检验。
   * 对于每个特征,(特征,标签)对被转换为列联表,并计算卡方统计量。
   * 所有标签和特征值必须是分类的。
      *
   * @param data 包含具有分类特征的标记数据集的`RDD[LabeledPoint]`。
   *             实数特征将被视为每个不同值都是分类的。
   * @return 包含每个特征相对于标签的ChiSquaredTestResult的数组。
   *         返回的数组中元素的顺序反映了输入特征的顺序。
      */
    @Since("1.1.0")
    def chiSqTest(data: RDD[LabeledPoint]): Array[ChiSqTestResult] = {

    ChiSqTest.chiSquaredFeatures(data)
  }

  /**
   * `chiSqTest()`的Java友好版本
      */
    @Since("1.5.0")
    def chiSqTest(data: JavaRDD[LabeledPoint]): Array[ChiSqTestResult] = chiSqTest(data.rdd)

  /**
   * 对从连续分布中采样的数据进行双边Kolmogorov-Smirnov(KS)检验。
   * 通过比较样本数据的经验累积分布与理论分布之间的最大差异,
   * 我们可以提供一个测试,用于验证样本数据是否来自该理论分布的零假设。
   * 有关KS检验的更多信息:
   * @see <a href="https://en.wikipedia.org/wiki/Kolmogorov%E2%80%93Smirnov_test">
   * Kolmogorov-Smirnov test (Wikipedia)</a>
      *
   * @param data 要测试的样本数据的`RDD[Double]`。
   * @param cdf 计算给定值处的理论CDF的`Double => Double`函数。
   * @return 包含测试统计量、p-value和零假设的[[org.apache.spark.mllib.stat.test.KolmogorovSmirnovTestResult]]对象。
      */
    @Since("1.5.0")
    def kolmogorovSmirnovTest(data: RDD[Double], cdf: Double => Double)

    : KolmogorovSmirnovTestResult = {
    KolmogorovSmirnovTest.testOneSample(data, cdf)
  }

  /**
   * 进行一样本、双边Kolmogorov-Smirnov(KS)概率分布相等性检验的便捷函数。
   * 当前支持正态分布,参数为均值和标准差。
   * (distName = "norm")
   * @param data 要测试的样本数据的`RDD[Double]`。
   * @param distName 理论分布的名称的字符串。
   * @param params 用于理论分布的参数的`Double*`。
   * @return 包含测试统计量、p-value和零假设的[[org.apache.spark.mllib.stat.test.KolmogorovSmirnovTestResult]]对象。
      */
    @Since("1.5.0")
    @varargs
    def kolmogorovSmirnovTest(data: RDD[Double], distName: String, params: Double*)

    : KolmogorovSmirnovTestResult = {
    KolmogorovSmirnovTest.testOneSample(data, distName, params: _*)
  }

  /**
   * `kolmogorovSmirnovTest()`的Java友好版本
      */
    @Since("1.5.0")
    @varargs
    def kolmogorovSmirnovTest(
      data: JavaDoubleRDD,
      distName: String,
      params: Double*): KolmogorovSmirnovTestResult = {

    kolmogorovSmirnovTest(data.rdd.asInstanceOf[RDD[Double]], distName, params: _*)
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BigDataMLApplication

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值