#6278·spinnaker

如何克服 MannWhitney 判别法的缺陷

作者: moertel创建于 2020年8月11日更新于 2026年8月11日
标签enhancementcomponent/kayentano-lifecycle
点击此处展开单元测试

scala
  test("Mann-Whitney 判别器测试: 变量性增加") {
    val experimentData = Array(
      10.0, 10.1, 10.2, 10.3, 10.4, 10.5, 10.6, 17.0, 17.1, 17.2, 17.3, 17.4, 17.5, 17.6, 17.7
    )
    val controlData = Array(
       1.0, 100.0,  4.0, 101.0,  5.0, 102.0,  6.0, 103.0,  7.0, 104.0,  8.0, 105.0,  9.0, 106.0, 17.0
    )
    val experimentMetric = Metric("pass-metric", experimentData, "canary")
    val controlMetric = Metric("pass-metric", controlData, "baseline")
    val classifier = new MannWhitneyClassifier(tolerance = 0.10, confLevel = 0.95)
    val result = classifier.classify(controlMetric, experimentMetric, MetricDirection.Either)
    assert(result.classification == Pass) // 从逻辑上来看,它不应该通过!
  }

我们的推断是: 如果一个工程师看到此结果,他们肯定会停止部署并调查发生了什么。这个问题源于 MannWhitney 的工作方式。但是: 如何防止这种类型的假阴性呢? acd6e780-bf77-11ea-83a8-f91ee307927a

Case 2: 最初的波动随着时间的推移而消失

结果是 FAIL,但它应该是 PASS

点击此处展开单元测试

scala
  test("Mann-Whitney 判别器测试: 最初的波动随着时间的推移而消失") {
    val experimentData = Array(
      10.99, 10.991, 10.992, 10.993, 10.994, 10.995, 10.996, 11, 11.01, 11.02, 11.021, 11.023, 11.024, 11.025, 11.026
    )
    val controlData = Array(
      2.1, 15.05, 2.2, 15.01, 2.3, 10.982, 11.011, 11, 10.989, 10.988, 10.987, 10.986, 10.985, 10.984, 10.983
    )
    val experimentMetric = Metric("pass-metric", experimentData, "canary")
    val controlMetric = Metric("pass-metric", controlData, "baseline")
    val classifier = new MannWhitneyClassifier(tolerance = 0.10, confLevel = 0.95)
    val result =
…

内容来源: spinnaker/spinnaker