Skip to content
Closed
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ public Vector predictRaw(Vector features) {
*/
@Override
public MyJavaLogisticRegressionModel copy(ParamMap extra) {
return copyValues(new MyJavaLogisticRegressionModel(uid(), weights_), extra);
return copyValues(new MyJavaLogisticRegressionModel(uid(), weights_), extra)
.setParent(parent());

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix indentation

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ private class MyLogisticRegressionModel(
*/
override def copy(extra: ParamMap): MyLogisticRegressionModel = {
copyValues(new MyLogisticRegressionModel(uid, weights), extra)
.setParent(parent)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this can fit on 1 line, please do so. (here and elsewhere)

}
}
// scalastyle:on println
2 changes: 1 addition & 1 deletion mllib/src/main/scala/org/apache/spark/ml/Pipeline.scala
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,6 @@ class PipelineModel private[ml] (
}

override def copy(extra: ParamMap): PipelineModel = {
new PipelineModel(uid, stages.map(_.copy(extra)))
new PipelineModel(uid, stages.map(_.copy(extra))).setParent(parent)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ final class DecisionTreeClassificationModel private[ml] (

override def copy(extra: ParamMap): DecisionTreeClassificationModel = {
copyValues(new DecisionTreeClassificationModel(uid, rootNode, numClasses), extra)
.setParent(parent)
}

override def toString: String = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ final class GBTClassificationModel(

override def copy(extra: ParamMap): GBTClassificationModel = {
copyValues(new GBTClassificationModel(uid, _trees, _treeWeights), extra)
.setParent(parent)
}

override def toString: String = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,7 @@ class LogisticRegressionModel private[ml] (

override def copy(extra: ParamMap): LogisticRegressionModel = {
copyValues(new LogisticRegressionModel(uid, weights, intercept), extra)
.setParent(parent)
}

override protected def raw2prediction(rawPrediction: Vector): Double = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ final class OneVsRestModel private[ml] (
override def copy(extra: ParamMap): OneVsRestModel = {
val copied = new OneVsRestModel(
uid, labelMetadata, models.map(_.copy(extra).asInstanceOf[ClassificationModel[_, _]]))
copyValues(copied, extra)
copyValues(copied, extra).setParent(parent)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ final class RandomForestClassificationModel private[ml] (

override def copy(extra: ParamMap): RandomForestClassificationModel = {
copyValues(new RandomForestClassificationModel(uid, _trees, numFeatures, numClasses), extra)
.setParent(parent)
}

override def toString: String = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,9 @@ final class Bucketizer(override val uid: String)
SchemaUtils.appendColumn(schema, prepOutputField(schema))
}

override def copy(extra: ParamMap): Bucketizer = defaultCopy(extra)
override def copy(extra: ParamMap): Bucketizer = {
defaultCopy[Bucketizer](extra).setParent(parent)
}
}

private[feature] object Bucketizer {
Expand Down
2 changes: 1 addition & 1 deletion mllib/src/main/scala/org/apache/spark/ml/feature/IDF.scala
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,6 @@ class IDFModel private[ml] (

override def copy(extra: ParamMap): IDFModel = {
val copied = new IDFModel(uid, idfModel)
copyValues(copied, extra)
copyValues(copied, extra).setParent(parent)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,6 @@ class MinMaxScalerModel private[ml] (

override def copy(extra: ParamMap): MinMaxScalerModel = {
val copied = new MinMaxScalerModel(uid, originalMin, originalMax)
copyValues(copied, extra)
copyValues(copied, extra).setParent(parent)
}
}
2 changes: 1 addition & 1 deletion mllib/src/main/scala/org/apache/spark/ml/feature/PCA.scala
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,6 @@ class PCAModel private[ml] (

override def copy(extra: ParamMap): PCAModel = {
val copied = new PCAModel(uid, pcaModel)
copyValues(copied, extra)
copyValues(copied, extra).setParent(parent)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,6 @@ class StandardScalerModel private[ml] (

override def copy(extra: ParamMap): StandardScalerModel = {
val copied = new StandardScalerModel(uid, scaler)
copyValues(copied, extra)
copyValues(copied, extra).setParent(parent)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ class StringIndexerModel private[ml] (

override def copy(extra: ParamMap): StringIndexerModel = {
val copied = new StringIndexerModel(uid, labels)
copyValues(copied, extra)
copyValues(copied, extra).setParent(parent)
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,6 @@ class VectorIndexerModel private[ml] (

override def copy(extra: ParamMap): VectorIndexerModel = {
val copied = new VectorIndexerModel(uid, numFeatures, categoryMaps)
copyValues(copied, extra)
copyValues(copied, extra).setParent(parent)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,6 @@ class Word2VecModel private[ml] (

override def copy(extra: ParamMap): Word2VecModel = {
val copied = new Word2VecModel(uid, wordVectors)
copyValues(copied, extra)
copyValues(copied, extra).setParent(parent)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ class ALSModel private[ml] (

override def copy(extra: ParamMap): ALSModel = {
val copied = new ALSModel(uid, rank, userFactors, itemFactors)
copyValues(copied, extra)
copyValues(copied, extra).setParent(parent)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ final class DecisionTreeRegressionModel private[ml] (

override def copy(extra: ParamMap): DecisionTreeRegressionModel = {
copyValues(new DecisionTreeRegressionModel(uid, rootNode), extra)
.setParent(parent)
}

override def toString: String = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ final class GBTRegressionModel(

override def copy(extra: ParamMap): GBTRegressionModel = {
copyValues(new GBTRegressionModel(uid, _trees, _treeWeights), extra)
.setParent(parent)
}

override def toString: String = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ class LinearRegressionModel private[ml] (
override def copy(extra: ParamMap): LinearRegressionModel = {
val newModel = copyValues(new LinearRegressionModel(uid, weights, intercept))
if (trainingSummary.isDefined) newModel.setSummary(trainingSummary.get)
newModel
newModel.setParent(parent)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ final class RandomForestRegressionModel private[ml] (

override def copy(extra: ParamMap): RandomForestRegressionModel = {
copyValues(new RandomForestRegressionModel(uid, _trees, numFeatures), extra)
.setParent(parent)
}

override def toString: String = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,6 @@ class CrossValidatorModel private[ml] (
uid,
bestModel.copy(extra).asInstanceOf[Model[_]],
avgMetrics.clone())
copyValues(copied, extra)
copyValues(copied, extra).setParent(parent)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ class PipelineSuite extends SparkFunSuite {
val copied = model.copy(ParamMap(hashingTF.numFeatures -> 10))
require(copied.stages(0).asInstanceOf[HashingTF].getNumFeatures === 10,
"copy should handle extra stage params")
assert(copied.parent == model.parent)
}

test("pipeline model constructors") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ package org.apache.spark.ml.classification

import org.apache.spark.SparkFunSuite
import org.apache.spark.ml.impl.TreeTests
import org.apache.spark.ml.param.ParamsSuite
import org.apache.spark.ml.param.{ParamMap, ParamsSuite}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no longer any need to import ParamMap. Please check imports in other tests too

import org.apache.spark.ml.tree.LeafNode
import org.apache.spark.mllib.linalg.{Vector, Vectors}
import org.apache.spark.mllib.regression.LabeledPoint
Expand Down Expand Up @@ -232,6 +232,13 @@ class DecisionTreeClassifierSuite extends SparkFunSuite with MLlibTestSparkConte
compareAPIs(rdd, dt, categoricalFeatures = Map.empty[Int, Int], numClasses)
}

test("copied model must have the same parent") {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think you need to write a new unit test for each model. A more efficient way would be to write a generic testing utility like this (maybe inside a new file like test/scala/org/apache/spark/ml/util/MLTestingUtils.scala):

object MLTestingUtils {
  def checkCopy(model: Model[_]): Unit = {
    val copied = model.copy()
    assert(copied.parent === model.parent)
  }
}

Later on, we can add other standard checks here as well.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then each unit test can call that helper in an existing test.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is better to make helper method in order not to make duplicates. But it is better to have one unit test has one assert to make it easy to specify which test fail. How about?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, that's a good point. I'm OK with you leaving them as separate tests.

ParamsSuite.checkParams(new DecisionTreeClassifier)
val model = new DecisionTreeClassificationModel("dtc", new LeafNode(0.0, 0.0, null), 2)
val copied = model.copy(ParamMap.empty)
assert(model.parent == copied.parent)
}

test("predictRaw and predictProbability") {
val rdd = continuousDataPointsForMulticlassRDD
val dt = new DecisionTreeClassifier()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ package org.apache.spark.ml.classification

import org.apache.spark.SparkFunSuite
import org.apache.spark.ml.impl.TreeTests
import org.apache.spark.ml.param.ParamsSuite
import org.apache.spark.ml.param.{ParamMap, ParamsSuite}
import org.apache.spark.ml.regression.DecisionTreeRegressionModel
import org.apache.spark.ml.tree.LeafNode
import org.apache.spark.mllib.regression.LabeledPoint
Expand Down Expand Up @@ -77,6 +77,14 @@ class GBTClassifierSuite extends SparkFunSuite with MLlibTestSparkContext {
}
}

test("copied model must have the same parent") {
val model = new GBTClassificationModel("gbtc",
Array(new DecisionTreeRegressionModel("dtr", new LeafNode(0.0, 0.0, null))),
Array(1.0))
val copied = model.copy(ParamMap.empty)
assert(model.parent == copied.parent)
}

test("Checkpointing") {
val tempDir = Utils.createTempDir()
val path = tempDir.toURI.toString
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
package org.apache.spark.ml.classification

import org.apache.spark.SparkFunSuite
import org.apache.spark.ml.param.ParamsSuite
import org.apache.spark.ml.param.{ParamMap, ParamsSuite}
import org.apache.spark.mllib.classification.LogisticRegressionSuite._
import org.apache.spark.mllib.linalg.{Vectors, Vector}
import org.apache.spark.mllib.util.MLlibTestSparkContext
Expand Down Expand Up @@ -66,7 +66,8 @@ class LogisticRegressionSuite extends SparkFunSuite with MLlibTestSparkContext {
test("params") {
ParamsSuite.checkParams(new LogisticRegression)
val model = new LogisticRegressionModel("logReg", Vectors.dense(0.0), 0.0)
ParamsSuite.checkParams(model)
val copied = model.copy(ParamMap.empty)
assert(model.parent == copied.parent)
}

test("logistic regression: default params") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,16 @@ class OneVsRestSuite extends SparkFunSuite with MLlibTestSparkContext {
require(m.getThreshold === 0.1, "copy should handle extra model params")
}
}

test("copied model must have the same parent") {
ParamsSuite.checkParams(new OneVsRest)
val lrModel = new LogisticRegressionModel("lr", Vectors.dense(0.0), 0.0)
val lrCopied = lrModel.copy(ParamMap.empty)
assert(lrModel.parent == lrCopied.parent)
val model = new OneVsRestModel("ovr", Metadata.empty, Array(lrModel))
val copied = model.copy(ParamMap.empty)
assert(model.parent == copied.parent)
}
}

private class MockLogisticRegression(uid: String) extends LogisticRegression(uid) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ package org.apache.spark.ml.classification

import org.apache.spark.SparkFunSuite
import org.apache.spark.ml.impl.TreeTests
import org.apache.spark.ml.param.ParamsSuite
import org.apache.spark.ml.param.{ParamMap, ParamsSuite}
import org.apache.spark.ml.tree.LeafNode
import org.apache.spark.mllib.linalg.{Vector, Vectors}
import org.apache.spark.mllib.regression.LabeledPoint
Expand Down Expand Up @@ -122,6 +122,14 @@ class RandomForestClassifierSuite extends SparkFunSuite with MLlibTestSparkConte
compareAPIs(rdd, rf2, categoricalFeatures, numClasses)
}

test("copied model must have the same parent") {
ParamsSuite.checkParams(new RandomForestClassifier)
val model = new RandomForestClassificationModel("rfc",
Array(new DecisionTreeClassificationModel("dtc", new LeafNode(0.0, 0.0, null), 2)), 2, 2)
val copied = model.copy(ParamMap.empty)
assert(model.parent == copied.parent)
}

test("predictRaw and predictProbability") {
val rdd = orderedLabeledPoints5_20
val rf = new RandomForestClassifier()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ package org.apache.spark.ml.feature
import scala.util.Random

import org.apache.spark.{SparkException, SparkFunSuite}
import org.apache.spark.ml.param.ParamsSuite
import org.apache.spark.ml.param.{ParamMap, ParamsSuite}
import org.apache.spark.mllib.linalg.Vectors
import org.apache.spark.mllib.util.MLlibTestSparkContext
import org.apache.spark.mllib.util.TestingUtils._
Expand Down Expand Up @@ -111,6 +111,12 @@ class BucketizerSuite extends SparkFunSuite with MLlibTestSparkContext {
val lsResult = Vectors.dense(data.map(x => BucketizerSuite.linearSearchForBuckets(splits, x)))
assert(bsResult ~== lsResult absTol 1e-5)
}

test("copied model must have the same parent") {
val model = new Bucketizer()
val copied = model.copy(ParamMap.empty)
assert(model.parent == copied.parent)
}
}

private object BucketizerSuite extends SparkFunSuite {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
package org.apache.spark.ml.feature

import org.apache.spark.SparkFunSuite
import org.apache.spark.ml.param.ParamMap
import org.apache.spark.mllib.linalg.{Vector, Vectors}
import org.apache.spark.mllib.util.MLlibTestSparkContext
import org.apache.spark.sql.{Row, SQLContext}
Expand Down Expand Up @@ -51,6 +52,10 @@ class MinMaxScalerSuite extends SparkFunSuite with MLlibTestSparkContext {
.foreach { case Row(vector1: Vector, vector2: Vector) =>
assert(vector1.equals(vector2), "Transformed vector is different with expected.")
}

// copied model must have the same parent.
val copied = model.copy(ParamMap.empty)
assert(model.parent == copied.parent)
}

test("MinMaxScaler arguments max must be larger than min") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
package org.apache.spark.ml.feature

import org.apache.spark.SparkFunSuite
import org.apache.spark.ml.param.ParamsSuite
import org.apache.spark.ml.param.{ParamMap, ParamsSuite}
import org.apache.spark.mllib.linalg.distributed.RowMatrix
import org.apache.spark.mllib.linalg.{Vector, Vectors, DenseMatrix, Matrices}
import org.apache.spark.mllib.util.MLlibTestSparkContext
Expand All @@ -35,6 +35,13 @@ class PCASuite extends SparkFunSuite with MLlibTestSparkContext {
ParamsSuite.checkParams(model)
}

test("copied model must have the same parent") {
val mat = Matrices.dense(2, 2, Array(0.0, 1.0, 2.0, 3.0)).asInstanceOf[DenseMatrix]
val model = new PCAModel("pca", new OldPCAModel(2, mat))
val copied = model.copy(ParamMap.empty)
assert(model.parent == copied.parent)
}

test("pca") {
val data = Array(
Vectors.sparse(5, Seq((1, 1.0), (3, 7.0))),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ package org.apache.spark.ml.feature

import org.apache.spark.SparkFunSuite
import org.apache.spark.ml.attribute.{Attribute, NominalAttribute}
import org.apache.spark.ml.param.ParamsSuite
import org.apache.spark.ml.param.{ParamMap, ParamsSuite}
import org.apache.spark.mllib.util.MLlibTestSparkContext

class StringIndexerSuite extends SparkFunSuite with MLlibTestSparkContext {
Expand All @@ -30,6 +30,12 @@ class StringIndexerSuite extends SparkFunSuite with MLlibTestSparkContext {
ParamsSuite.checkParams(model)
}

test("copied model must have the same parent") {
val model = new StringIndexerModel("indexer", Array("a", "b"))
val copied = model.copy(ParamMap.empty)
assert(model.parent == copied.parent)
}

test("StringIndexer") {
val data = sc.parallelize(Seq((0, "a"), (1, "b"), (2, "c"), (3, "a"), (4, "a"), (5, "c")), 2)
val df = sqlContext.createDataFrame(data).toDF("id", "label")
Expand Down
Loading