Skip to content

Commit 05422a8

Browse files
committed
add unit test for model construction
1 parent 5925113 commit 05422a8

File tree

2 files changed

+33
-16
lines changed

2 files changed

+33
-16
lines changed

mllib/src/main/scala/org/apache/spark/mllib/regression/IsotonicRegression.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,15 @@ class IsotonicRegressionModel (
4040

4141
private val predictionOrd = if (isotonic) Ordering[Double] else Ordering[Double].reverse
4242

43-
assert(boundaries.length == predictions.length)
43+
require(boundaries.length == predictions.length)
4444
assertOrdered(boundaries)
4545
assertOrdered(predictions)(predictionOrd)
4646

4747
/** Asserts the input array is monotone with the given ordering. */
4848
private def assertOrdered(xs: Array[Double])(implicit ord: Ordering[Double]): Unit = {
4949
var i = 1
5050
while (i < xs.length) {
51-
assert(ord.compare(xs(i - 1), xs(i)) <= 0,
51+
require(ord.compare(xs(i - 1), xs(i)) <= 0,
5252
s"Elements (${xs(i - 1)}, ${xs(i)}) are not ordered.")
5353
i += 1
5454
}

mllib/src/test/scala/org/apache/spark/mllib/regression/IsotonicRegressionSuite.scala

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ package org.apache.spark.mllib.regression
2020
import org.scalatest.{Matchers, FunSuite}
2121

2222
import org.apache.spark.mllib.util.MLlibTestSparkContext
23+
import org.apache.spark.mllib.util.TestingUtils._
2324

2425
class IsotonicRegressionSuite extends FunSuite with MLlibTestSparkContext with Matchers {
2526

@@ -55,80 +56,67 @@ class IsotonicRegressionSuite extends FunSuite with MLlibTestSparkContext with M
5556

5657
test("increasing isotonic regression") {
5758
val model = runIsotonicRegression(Seq(1, 2, 3, 3, 1, 6, 17, 16, 17, 18), true)
58-
5959
assert(model.predictions === Array(1, 2, 7d/3, 7d/3, 7d/3, 6, 16.5, 16.5, 17, 18))
6060
}
6161

6262
test("isotonic regression with size 0") {
6363
val model = runIsotonicRegression(Seq(), true)
64-
6564
assert(model.predictions === Array())
6665
}
6766

6867
test("isotonic regression with size 1") {
6968
val model = runIsotonicRegression(Seq(1), true)
70-
7169
assert(model.predictions === Array(1.0))
7270
}
7371

7472
test("isotonic regression strictly increasing sequence") {
7573
val model = runIsotonicRegression(Seq(1, 2, 3, 4, 5), true)
76-
7774
assert(model.predictions === Array(1, 2, 3, 4, 5))
7875
}
7976

8077
test("isotonic regression strictly decreasing sequence") {
8178
val model = runIsotonicRegression(Seq(5, 4, 3, 2, 1), true)
82-
8379
assert(model.predictions === Array(3, 3, 3, 3, 3))
8480
}
8581

8682
test("isotonic regression with last element violating monotonicity") {
8783
val model = runIsotonicRegression(Seq(1, 2, 3, 4, 2), true)
88-
8984
assert(model.predictions === Array(1, 2, 3, 3, 3))
9085
}
9186

9287
test("isotonic regression with first element violating monotonicity") {
9388
val model = runIsotonicRegression(Seq(4, 2, 3, 4, 5), true)
94-
9589
assert(model.predictions === Array(3, 3, 3, 4, 5))
9690
}
9791

9892
test("isotonic regression with negative labels") {
9993
val model = runIsotonicRegression(Seq(-1, -2, 0, 1, -1), true)
100-
10194
assert(model.predictions === Array(-1.5, -1.5, 0, 0, 0))
10295
}
10396

10497
test("isotonic regression with unordered input") {
10598
val trainRDD = sc.parallelize(generateIsotonicInput(Seq(1, 2, 3, 4, 5)).reverse).cache()
10699
val model = new IsotonicRegression().run(trainRDD)
107-
108100
assert(model.predictions === Array(1, 2, 3, 4, 5))
109101
}
110102

111103
test("weighted isotonic regression") {
112104
val model = runIsotonicRegression(Seq(1, 2, 3, 4, 2), Seq(1, 1, 1, 1, 2), true)
113-
114105
assert(model.predictions === Array(1, 2, 2.75, 2.75,2.75))
115106
}
116107

117108
test("weighted isotonic regression with weights lower than 1") {
118109
val model = runIsotonicRegression(Seq(1, 2, 3, 2, 1), Seq(1, 1, 1, 0.1, 0.1), true)
119-
120110
assert(model.predictions.map(round) === Array(1, 2, 3.3/1.2, 3.3/1.2, 3.3/1.2))
121111
}
122112

123113
test("weighted isotonic regression with negative weights") {
124114
val model = runIsotonicRegression(Seq(1, 2, 3, 2, 1), Seq(-1, 1, -3, 1, -5), true)
125-
126115
assert(model.predictions === Array(1.0, 10.0/6, 10.0/6, 10.0/6, 10.0/6))
127116
}
128117

129118
test("weighted isotonic regression with zero weights") {
130119
val model = runIsotonicRegression(Seq[Double](1, 2, 3, 2, 1), Seq[Double](0, 0, 0, 1, 0), true)
131-
132120
assert(model.predictions === Array(1, 2, 2, 2, 2))
133121
}
134122

@@ -186,4 +174,33 @@ class IsotonicRegressionSuite extends FunSuite with MLlibTestSparkContext with M
186174
assert(model.predict(3) === 4)
187175
assert(model.predict(10) === 1)
188176
}
189-
}
177+
178+
test("model construction") {
179+
val model = new IsotonicRegressionModel(Array(0.0, 1.0), Array(1.0, 2.0), isotonic = true)
180+
assert(model.predict(-0.5) === 1.0)
181+
assert(model.predict(0.0) === 1.0)
182+
assert(model.predict(0.5) ~== 1.5 absTol 1e-14)
183+
assert(model.predict(1.0) === 2.0)
184+
assert(model.predict(1.5) === 2.0)
185+
186+
intercept[IllegalArgumentException] {
187+
// different array sizes.
188+
new IsotonicRegressionModel(Array(0.0, 1.0), Array(1.0), isotonic = true)
189+
}
190+
191+
intercept[IllegalArgumentException] {
192+
// unordered boundaries
193+
new IsotonicRegressionModel(Array(1.0, 0.0), Array(1.0, 2.0), isotonic = true)
194+
}
195+
196+
intercept[IllegalArgumentException] {
197+
// unordered predictions (isotonic)
198+
new IsotonicRegressionModel(Array(0.0, 1.0), Array(2.0, 1.0), isotonic = true)
199+
}
200+
201+
intercept[IllegalArgumentException] {
202+
// unordered predictions (antitonic)
203+
new IsotonicRegressionModel(Array(0.0, 1.0), Array(1.0, 2.0), isotonic = false)
204+
}
205+
}
206+
}

0 commit comments

Comments
 (0)