From 05422a8fe9e5911d8e496c2dcc80a819118c893e Mon Sep 17 00:00:00 2001 From: Xiangrui Meng Date: Fri, 30 Jan 2015 11:51:06 -0800 Subject: [PATCH] add unit test for model construction --- .../mllib/regression/IsotonicRegression.scala | 4 +- .../regression/IsotonicRegressionSuite.scala | 45 +++++++++++++------ 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/mllib/src/main/scala/org/apache/spark/mllib/regression/IsotonicRegression.scala b/mllib/src/main/scala/org/apache/spark/mllib/regression/IsotonicRegression.scala index 779fa8d4c1453..d63732366f940 100644 --- a/mllib/src/main/scala/org/apache/spark/mllib/regression/IsotonicRegression.scala +++ b/mllib/src/main/scala/org/apache/spark/mllib/regression/IsotonicRegression.scala @@ -40,7 +40,7 @@ class IsotonicRegressionModel ( private val predictionOrd = if (isotonic) Ordering[Double] else Ordering[Double].reverse - assert(boundaries.length == predictions.length) + require(boundaries.length == predictions.length) assertOrdered(boundaries) assertOrdered(predictions)(predictionOrd) @@ -48,7 +48,7 @@ class IsotonicRegressionModel ( private def assertOrdered(xs: Array[Double])(implicit ord: Ordering[Double]): Unit = { var i = 1 while (i < xs.length) { - assert(ord.compare(xs(i - 1), xs(i)) <= 0, + require(ord.compare(xs(i - 1), xs(i)) <= 0, s"Elements (${xs(i - 1)}, ${xs(i)}) are not ordered.") i += 1 } diff --git a/mllib/src/test/scala/org/apache/spark/mllib/regression/IsotonicRegressionSuite.scala b/mllib/src/test/scala/org/apache/spark/mllib/regression/IsotonicRegressionSuite.scala index 962e52536da66..0e8025c1e0e2e 100644 --- a/mllib/src/test/scala/org/apache/spark/mllib/regression/IsotonicRegressionSuite.scala +++ b/mllib/src/test/scala/org/apache/spark/mllib/regression/IsotonicRegressionSuite.scala @@ -20,6 +20,7 @@ package org.apache.spark.mllib.regression import org.scalatest.{Matchers, FunSuite} import org.apache.spark.mllib.util.MLlibTestSparkContext +import org.apache.spark.mllib.util.TestingUtils._ class IsotonicRegressionSuite extends FunSuite with MLlibTestSparkContext with Matchers { @@ -55,80 +56,67 @@ class IsotonicRegressionSuite extends FunSuite with MLlibTestSparkContext with M test("increasing isotonic regression") { val model = runIsotonicRegression(Seq(1, 2, 3, 3, 1, 6, 17, 16, 17, 18), true) - assert(model.predictions === Array(1, 2, 7d/3, 7d/3, 7d/3, 6, 16.5, 16.5, 17, 18)) } test("isotonic regression with size 0") { val model = runIsotonicRegression(Seq(), true) - assert(model.predictions === Array()) } test("isotonic regression with size 1") { val model = runIsotonicRegression(Seq(1), true) - assert(model.predictions === Array(1.0)) } test("isotonic regression strictly increasing sequence") { val model = runIsotonicRegression(Seq(1, 2, 3, 4, 5), true) - assert(model.predictions === Array(1, 2, 3, 4, 5)) } test("isotonic regression strictly decreasing sequence") { val model = runIsotonicRegression(Seq(5, 4, 3, 2, 1), true) - assert(model.predictions === Array(3, 3, 3, 3, 3)) } test("isotonic regression with last element violating monotonicity") { val model = runIsotonicRegression(Seq(1, 2, 3, 4, 2), true) - assert(model.predictions === Array(1, 2, 3, 3, 3)) } test("isotonic regression with first element violating monotonicity") { val model = runIsotonicRegression(Seq(4, 2, 3, 4, 5), true) - assert(model.predictions === Array(3, 3, 3, 4, 5)) } test("isotonic regression with negative labels") { val model = runIsotonicRegression(Seq(-1, -2, 0, 1, -1), true) - assert(model.predictions === Array(-1.5, -1.5, 0, 0, 0)) } test("isotonic regression with unordered input") { val trainRDD = sc.parallelize(generateIsotonicInput(Seq(1, 2, 3, 4, 5)).reverse).cache() val model = new IsotonicRegression().run(trainRDD) - assert(model.predictions === Array(1, 2, 3, 4, 5)) } test("weighted isotonic regression") { val model = runIsotonicRegression(Seq(1, 2, 3, 4, 2), Seq(1, 1, 1, 1, 2), true) - assert(model.predictions === Array(1, 2, 2.75, 2.75,2.75)) } test("weighted isotonic regression with weights lower than 1") { val model = runIsotonicRegression(Seq(1, 2, 3, 2, 1), Seq(1, 1, 1, 0.1, 0.1), true) - assert(model.predictions.map(round) === Array(1, 2, 3.3/1.2, 3.3/1.2, 3.3/1.2)) } test("weighted isotonic regression with negative weights") { val model = runIsotonicRegression(Seq(1, 2, 3, 2, 1), Seq(-1, 1, -3, 1, -5), true) - assert(model.predictions === Array(1.0, 10.0/6, 10.0/6, 10.0/6, 10.0/6)) } test("weighted isotonic regression with zero weights") { val model = runIsotonicRegression(Seq[Double](1, 2, 3, 2, 1), Seq[Double](0, 0, 0, 1, 0), true) - assert(model.predictions === Array(1, 2, 2, 2, 2)) } @@ -186,4 +174,33 @@ class IsotonicRegressionSuite extends FunSuite with MLlibTestSparkContext with M assert(model.predict(3) === 4) assert(model.predict(10) === 1) } -} \ No newline at end of file + + test("model construction") { + val model = new IsotonicRegressionModel(Array(0.0, 1.0), Array(1.0, 2.0), isotonic = true) + assert(model.predict(-0.5) === 1.0) + assert(model.predict(0.0) === 1.0) + assert(model.predict(0.5) ~== 1.5 absTol 1e-14) + assert(model.predict(1.0) === 2.0) + assert(model.predict(1.5) === 2.0) + + intercept[IllegalArgumentException] { + // different array sizes. + new IsotonicRegressionModel(Array(0.0, 1.0), Array(1.0), isotonic = true) + } + + intercept[IllegalArgumentException] { + // unordered boundaries + new IsotonicRegressionModel(Array(1.0, 0.0), Array(1.0, 2.0), isotonic = true) + } + + intercept[IllegalArgumentException] { + // unordered predictions (isotonic) + new IsotonicRegressionModel(Array(0.0, 1.0), Array(2.0, 1.0), isotonic = true) + } + + intercept[IllegalArgumentException] { + // unordered predictions (antitonic) + new IsotonicRegressionModel(Array(0.0, 1.0), Array(1.0, 2.0), isotonic = false) + } + } +}