From f86c5122eadd9b0a595b776d77d6cdf23ad6731a Mon Sep 17 00:00:00 2001 From: Yuhao Yang Date: Fri, 10 Mar 2017 17:18:21 -0800 Subject: [PATCH 1/7] half --- .../scala/org/apache/spark/ml/fpm/FPGrowth.scala | 15 ++++++++++----- .../apache/spark/mllib/fpm/AssociationRules.scala | 2 +- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/mllib/src/main/scala/org/apache/spark/ml/fpm/FPGrowth.scala b/mllib/src/main/scala/org/apache/spark/ml/fpm/FPGrowth.scala index 417968d9b817..6d9303fce70e 100644 --- a/mllib/src/main/scala/org/apache/spark/ml/fpm/FPGrowth.scala +++ b/mllib/src/main/scala/org/apache/spark/ml/fpm/FPGrowth.scala @@ -159,7 +159,7 @@ class FPGrowth @Since("2.2.0") ( StructField("items", dataset.schema($(featuresCol)).dataType, nullable = false), StructField("freq", LongType, nullable = false))) val frequentItems = dataset.sparkSession.createDataFrame(rows, schema) - copyValues(new FPGrowthModel(uid, frequentItems)).setParent(this) + copyValues(new FPGrowthModel(uid, frequentItems, data.count())).setParent(this) } @Since("2.2.0") @@ -189,7 +189,8 @@ object FPGrowth extends DefaultParamsReadable[FPGrowth] { @Experimental class FPGrowthModel private[ml] ( @Since("2.2.0") override val uid: String, - @transient val freqItemsets: DataFrame) + @transient val freqItemsets: DataFrame, + val numTotalRecords: Long) extends Model[FPGrowthModel] with FPGrowthParams with MLWritable { /** @group setParam */ @@ -211,7 +212,7 @@ class FPGrowthModel private[ml] ( */ @Since("2.2.0") @transient lazy val associationRules: DataFrame = { - AssociationRules.getAssociationRulesFromFP(freqItemsets, "items", "freq", $(minConfidence)) + AssociationRules.getAssociationRulesFromFP(freqItemsets, "items", "freq", numTotalRecords, $(minConfidence)) } /** @@ -319,6 +320,7 @@ private[fpm] object AssociationRules { dataset: Dataset[_], itemsCol: String, freqCol: String, + numTotalRecords: Long, minConfidence: Double): DataFrame = { val freqItemSetRdd = dataset.select(itemsCol, freqCol).rdd @@ -326,13 +328,16 @@ private[fpm] object AssociationRules { val rows = new MLlibAssociationRules() .setMinConfidence(minConfidence) .run(freqItemSetRdd) - .map(r => Row(r.antecedent, r.consequent, r.confidence)) + .map(r => Row(r.antecedent, r.consequent, r.confidence, r.freqUnion / numTotalRecords)) + + val dt = dataset.schema(itemsCol).dataType val schema = StructType(Seq( StructField("antecedent", dt, nullable = false), StructField("consequent", dt, nullable = false), - StructField("confidence", DoubleType, nullable = false))) + StructField("confidence", DoubleType, nullable = false), + StructField("support", DoubleType, nullable = false))) val rules = dataset.sparkSession.createDataFrame(rows, schema) rules } diff --git a/mllib/src/main/scala/org/apache/spark/mllib/fpm/AssociationRules.scala b/mllib/src/main/scala/org/apache/spark/mllib/fpm/AssociationRules.scala index acb83ac31aff..337ce50e68cc 100644 --- a/mllib/src/main/scala/org/apache/spark/mllib/fpm/AssociationRules.scala +++ b/mllib/src/main/scala/org/apache/spark/mllib/fpm/AssociationRules.scala @@ -106,7 +106,7 @@ object AssociationRules { class Rule[Item] private[fpm] ( @Since("1.5.0") val antecedent: Array[Item], @Since("1.5.0") val consequent: Array[Item], - freqUnion: Double, + private[spark] val freqUnion: Double, freqAntecedent: Double) extends Serializable { /** From 9580aa910523144aba8e4f5a3d9693fe4387f16f Mon Sep 17 00:00:00 2001 From: Yuhao Yang Date: Sun, 12 Mar 2017 10:50:30 -0700 Subject: [PATCH 2/7] add support to association rules --- .../org/apache/spark/ml/fpm/FPGrowth.scala | 32 +++++++++++-------- .../apache/spark/ml/fpm/FPGrowthSuite.scala | 24 +++++++++++--- 2 files changed, 37 insertions(+), 19 deletions(-) diff --git a/mllib/src/main/scala/org/apache/spark/ml/fpm/FPGrowth.scala b/mllib/src/main/scala/org/apache/spark/ml/fpm/FPGrowth.scala index 6d9303fce70e..6ee9ac009fa8 100644 --- a/mllib/src/main/scala/org/apache/spark/ml/fpm/FPGrowth.scala +++ b/mllib/src/main/scala/org/apache/spark/ml/fpm/FPGrowth.scala @@ -17,10 +17,11 @@ package org.apache.spark.ml.fpm -import scala.collection.mutable.ArrayBuffer import scala.reflect.ClassTag import org.apache.hadoop.fs.Path +import org.json4s.DefaultFormats +import org.json4s.JsonDSL._ import org.apache.spark.annotation.{Experimental, Since} import org.apache.spark.ml.{Estimator, Model} @@ -190,7 +191,7 @@ object FPGrowth extends DefaultParamsReadable[FPGrowth] { class FPGrowthModel private[ml] ( @Since("2.2.0") override val uid: String, @transient val freqItemsets: DataFrame, - val numTotalRecords: Long) + val numTrainingRecords: Long) extends Model[FPGrowthModel] with FPGrowthParams with MLWritable { /** @group setParam */ @@ -212,7 +213,8 @@ class FPGrowthModel private[ml] ( */ @Since("2.2.0") @transient lazy val associationRules: DataFrame = { - AssociationRules.getAssociationRulesFromFP(freqItemsets, "items", "freq", numTotalRecords, $(minConfidence)) + AssociationRules.getAssociationRulesFromFP( + freqItemsets, "items", "freq", numTrainingRecords, $(minConfidence)) } /** @@ -260,7 +262,7 @@ class FPGrowthModel private[ml] ( @Since("2.2.0") override def copy(extra: ParamMap): FPGrowthModel = { - val copied = new FPGrowthModel(uid, freqItemsets) + val copied = new FPGrowthModel(uid, freqItemsets, numTrainingRecords) copyValues(copied, extra).setParent(this.parent) } @@ -282,7 +284,8 @@ object FPGrowthModel extends MLReadable[FPGrowthModel] { class FPGrowthModelWriter(instance: FPGrowthModel) extends MLWriter { override protected def saveImpl(path: String): Unit = { - DefaultParamsWriter.saveMetadata(instance, path, sc) + val extraMetadata = "numTrainingRecords" -> instance.numTrainingRecords + DefaultParamsWriter.saveMetadata(instance, path, sc, Some(extraMetadata)) val dataPath = new Path(path, "data").toString instance.freqItemsets.write.parquet(dataPath) } @@ -295,9 +298,11 @@ object FPGrowthModel extends MLReadable[FPGrowthModel] { override def load(path: String): FPGrowthModel = { val metadata = DefaultParamsReader.loadMetadata(path, sc, className) + implicit val format = DefaultFormats + val numTrainingRecords = (metadata.metadata \ "numTrainingRecords").extract[Long] val dataPath = new Path(path, "data").toString val frequentItems = sparkSession.read.parquet(dataPath) - val model = new FPGrowthModel(metadata.uid, frequentItems) + val model = new FPGrowthModel(metadata.uid, frequentItems, numTrainingRecords) DefaultParamsReader.getAndSetParams(model, metadata) model } @@ -312,25 +317,24 @@ private[fpm] object AssociationRules { * algorithms like [[FPGrowth]]. * @param itemsCol column name for frequent itemsets * @param freqCol column name for frequent itemsets count + * @param numTrainingRecords count of training Dataset * @param minConfidence minimum confidence for the result association rules * @return a DataFrame("antecedent", "consequent", "confidence") containing the association * rules. */ def getAssociationRulesFromFP[T: ClassTag]( - dataset: Dataset[_], - itemsCol: String, - freqCol: String, - numTotalRecords: Long, - minConfidence: Double): DataFrame = { + dataset: Dataset[_], + itemsCol: String, + freqCol: String, + numTrainingRecords: Long, + minConfidence: Double): DataFrame = { val freqItemSetRdd = dataset.select(itemsCol, freqCol).rdd .map(row => new FreqItemset(row.getSeq[T](0).toArray, row.getLong(1))) val rows = new MLlibAssociationRules() .setMinConfidence(minConfidence) .run(freqItemSetRdd) - .map(r => Row(r.antecedent, r.consequent, r.confidence, r.freqUnion / numTotalRecords)) - - + .map(r => Row(r.antecedent, r.consequent, r.confidence, r.freqUnion / numTrainingRecords)) val dt = dataset.schema(itemsCol).dataType val schema = StructType(Seq( diff --git a/mllib/src/test/scala/org/apache/spark/ml/fpm/FPGrowthSuite.scala b/mllib/src/test/scala/org/apache/spark/ml/fpm/FPGrowthSuite.scala index 076d55c18054..66d45d416963 100644 --- a/mllib/src/test/scala/org/apache/spark/ml/fpm/FPGrowthSuite.scala +++ b/mllib/src/test/scala/org/apache/spark/ml/fpm/FPGrowthSuite.scala @@ -38,13 +38,13 @@ class FPGrowthSuite extends SparkFunSuite with MLlibTestSparkContext with Defaul val model = new FPGrowth().setMinSupport(0.5).fit(data) val generatedRules = model.setMinConfidence(0.5).associationRules val expectedRules = spark.createDataFrame(Seq( - (Array("2"), Array("1"), 1.0), - (Array("1"), Array("2"), 0.75) - )).toDF("antecedent", "consequent", "confidence") + (Array("2"), Array("1"), 1.0, 0.75), + (Array("1"), Array("2"), 0.75, 0.75) + )).toDF("antecedent", "consequent", "confidence", "support") .withColumn("antecedent", col("antecedent").cast(ArrayType(dt))) .withColumn("consequent", col("consequent").cast(ArrayType(dt))) - assert(expectedRules.sort("antecedent").rdd.collect().sameElements( - generatedRules.sort("antecedent").rdd.collect())) + assert(expectedRules.collect().toSet.equals( + generatedRules.collect().toSet)) val transformed = model.transform(data) val expectedTransformed = spark.createDataFrame(Seq( @@ -74,6 +74,20 @@ class FPGrowthSuite extends SparkFunSuite with MLlibTestSparkContext with Defaul assert(checkDF.count() == 3 && checkDF.filter(col("freq") === col("expectedFreq")).count() == 3) } + test("FPGrowth associationRules") { + val freqItemsets = spark.createDataFrame(Seq( + (Array("2"), 4L), + (Array("1"), 2L), + (Array("1", "2"), 2L) + )).toDF("items", "freq") + val model = new FPGrowthModel("fpgrowth", freqItemsets, 4L).setMinConfidence(0.1) + val expectedRules = spark.createDataFrame(Seq( + (Array("2"), Array("1"), 0.5, 0.5), + (Array("1"), Array("2"), 1.0, 0.5) + )).toDF("antecedent", "consequent", "confidence", "support") + assert(expectedRules.collect().toSet.equals(model.associationRules.collect().toSet)) + } + test("FPGrowth getFreqItems with Null") { val df = spark.createDataFrame(Seq( (1, Array("1", "2", "3", "5")), From 1225496f3c00146ee45a99dcf19618a38d5d1462 Mon Sep 17 00:00:00 2001 From: Yuhao Yang Date: Tue, 14 Mar 2017 10:04:34 -0700 Subject: [PATCH 3/7] update comment --- .../src/main/scala/org/apache/spark/ml/fpm/FPGrowth.scala | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mllib/src/main/scala/org/apache/spark/ml/fpm/FPGrowth.scala b/mllib/src/main/scala/org/apache/spark/ml/fpm/FPGrowth.scala index e95459c7b3d3..5535578f814e 100644 --- a/mllib/src/main/scala/org/apache/spark/ml/fpm/FPGrowth.scala +++ b/mllib/src/main/scala/org/apache/spark/ml/fpm/FPGrowth.scala @@ -208,8 +208,8 @@ class FPGrowthModel private[ml] ( /** * Get association rules fitted by AssociationRules using the minConfidence. Returns a dataframe - * with three fields, "antecedent", "consequent" and "confidence", where "antecedent" and - * "consequent" are Array[T] and "confidence" is Double. + * with four fields, "antecedent", "consequent", "confidence" and "support", where "antecedent" + * and "consequent" are Array[T], "confidence" and "support" are Double. */ @Since("2.2.0") @transient lazy val associationRules: DataFrame = { @@ -319,8 +319,8 @@ private[fpm] object AssociationRules { * @param freqCol column name for frequent itemsets count * @param numTrainingRecords count of training Dataset * @param minConfidence minimum confidence for the result association rules - * @return a DataFrame("antecedent", "consequent", "confidence") containing the association - * rules. + * @return a DataFrame("antecedent", "consequent", "confidence", "support") containing the + * association rules. */ def getAssociationRulesFromFP[T: ClassTag]( dataset: Dataset[_], From 180b43df0cb1ca71f1bcabcae7dde933c5e301dc Mon Sep 17 00:00:00 2001 From: Yuhao Yang Date: Thu, 8 Jun 2017 16:59:07 -0700 Subject: [PATCH 4/7] merge conflict --- .../org/apache/spark/ml/fpm/FPGrowthSuite.scala | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/mllib/src/test/scala/org/apache/spark/ml/fpm/FPGrowthSuite.scala b/mllib/src/test/scala/org/apache/spark/ml/fpm/FPGrowthSuite.scala index 033b8b7e2ed9..a7a765f93e3b 100644 --- a/mllib/src/test/scala/org/apache/spark/ml/fpm/FPGrowthSuite.scala +++ b/mllib/src/test/scala/org/apache/spark/ml/fpm/FPGrowthSuite.scala @@ -76,15 +76,12 @@ class FPGrowthSuite extends SparkFunSuite with MLlibTestSparkContext with Defaul } test("FPGrowth associationRules") { - val freqItemsets = spark.createDataFrame(Seq( - (Array("2"), 4L), - (Array("1"), 2L), - (Array("1", "2"), 2L) - )).toDF("items", "freq") - val model = new FPGrowthModel("fpgrowth", freqItemsets, 4L).setMinConfidence(0.1) + val model = new FPGrowth().setMinSupport(0.1).setMinConfidence(0.1).fit(dataset) val expectedRules = spark.createDataFrame(Seq( - (Array("2"), Array("1"), 0.5, 0.5), - (Array("1"), Array("2"), 1.0, 0.5) + (Array("2"), Array("1"), 1.0, 0.75), + (Array("3"), Array("1"), 1.0, 0.25), + (Array("1"), Array("3"), 0.25, 0.25), + (Array("1"), Array("2"), 0.75, 0.75) )).toDF("antecedent", "consequent", "confidence", "support") assert(expectedRules.collect().toSet.equals(model.associationRules.collect().toSet)) } From eb25f287393ccffeb1a5905f7752298808945a2c Mon Sep 17 00:00:00 2001 From: Yuhao Yang Date: Tue, 13 Jun 2017 14:09:57 -0700 Subject: [PATCH 5/7] fix python and R test --- R/pkg/tests/fulltests/test_mllib_fpm.R | 3 +- python/pyspark/ml/fpm.py | 38 +++++++++++++------------- python/pyspark/ml/tests.py | 4 +-- 3 files changed, 23 insertions(+), 22 deletions(-) diff --git a/R/pkg/tests/fulltests/test_mllib_fpm.R b/R/pkg/tests/fulltests/test_mllib_fpm.R index 69dda52f0c27..0d13eba4c03b 100644 --- a/R/pkg/tests/fulltests/test_mllib_fpm.R +++ b/R/pkg/tests/fulltests/test_mllib_fpm.R @@ -44,7 +44,8 @@ test_that("spark.fpGrowth", { expected_association_rules <- data.frame( antecedent = I(list(list("2"), list("3"))), consequent = I(list(list("1"), list("1"))), - confidence = c(1, 1) + confidence = c(1, 1), + support = c(0.75, 0.5) ) expect_equivalent(expected_association_rules, collect(spark.associationRules(model))) diff --git a/python/pyspark/ml/fpm.py b/python/pyspark/ml/fpm.py index dd7dda5f0312..d03c31a13f02 100644 --- a/python/pyspark/ml/fpm.py +++ b/python/pyspark/ml/fpm.py @@ -186,29 +186,29 @@ class FPGrowth(JavaEstimator, HasItemsCol, HasPredictionCol, |[z] | |[x, z, y, r, q, t, p] | +------------------------+ - >>> fp = FPGrowth(minSupport=0.2, minConfidence=0.7) + >>> fp = FPGrowth(minSupport=0.4, minConfidence=0.7) >>> fpm = fp.fit(data) >>> fpm.freqItemsets.show(5) - +---------+----+ - | items|freq| - +---------+----+ - | [s]| 3| - | [s, x]| 3| - |[s, x, z]| 2| - | [s, z]| 2| - | [r]| 3| - +---------+----+ + +------+----+ + | items|freq| + +------+----+ + | [s]| 3| + |[s, x]| 3| + | [r]| 3| + | [y]| 3| + |[y, x]| 3| + +------+----+ only showing top 5 rows >>> fpm.associationRules.show(5) - +----------+----------+----------+ - |antecedent|consequent|confidence| - +----------+----------+----------+ - | [t, s]| [y]| 1.0| - | [t, s]| [x]| 1.0| - | [t, s]| [z]| 1.0| - | [p]| [r]| 1.0| - | [p]| [z]| 1.0| - +----------+----------+----------+ + +----------+----------+----------+-------+ + |antecedent|consequent|confidence|support| + +----------+----------+----------+-------+ + | [t]| [y]| 1.0| 0.5| + | [t]| [x]| 1.0| 0.5| + | [t]| [z]| 1.0| 0.5| + | [y, t, x]| [z]| 1.0| 0.5| + | [x]| [s]| 0.75| 0.5| + +----------+----------+----------+-------+ only showing top 5 rows >>> new_data = spark.createDataFrame([(["t", "s"], )], ["items"]) >>> sorted(fpm.transform(new_data).first().prediction) diff --git a/python/pyspark/ml/tests.py b/python/pyspark/ml/tests.py index 17a39472e1fe..d231b6d90f8a 100755 --- a/python/pyspark/ml/tests.py +++ b/python/pyspark/ml/tests.py @@ -1283,8 +1283,8 @@ def test_association_rules(self): fpm = fp.fit(self.data) expected_association_rules = self.spark.createDataFrame( - [([3], [1], 1.0), ([2], [1], 1.0)], - ["antecedent", "consequent", "confidence"] + [([3], [1], 1.0, 0.5), ([2], [1], 1.0, 0.75)], + ["antecedent", "consequent", "confidence", "support"] ) actual_association_rules = fpm.associationRules From 40cf4497432bd4e2cbeec8e6647b52c4c8e74072 Mon Sep 17 00:00:00 2001 From: Yuhao Yang Date: Mon, 30 Jul 2018 16:12:48 -0700 Subject: [PATCH 6/7] mima fix --- .../org/apache/spark/ml/fpm/FPGrowth.scala | 23 ++++++++++++++----- .../apache/spark/ml/fpm/FPGrowthSuite.scala | 1 + project/MimaExcludes.scala | 3 +++ 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/mllib/src/main/scala/org/apache/spark/ml/fpm/FPGrowth.scala b/mllib/src/main/scala/org/apache/spark/ml/fpm/FPGrowth.scala index 0523634743ff..638574c0d980 100644 --- a/mllib/src/main/scala/org/apache/spark/ml/fpm/FPGrowth.scala +++ b/mllib/src/main/scala/org/apache/spark/ml/fpm/FPGrowth.scala @@ -220,7 +220,7 @@ object FPGrowth extends DefaultParamsReadable[FPGrowth] { class FPGrowthModel private[ml] ( @Since("2.2.0") override val uid: String, @Since("2.2.0") @transient val freqItemsets: DataFrame, - @Since("2.4.0") val numTrainingRecords: Long) + @Since("2.4.0") val numTrainingRecords: Long = -1) extends Model[FPGrowthModel] with FPGrowthParams with MLWritable { /** @group setParam */ @@ -359,7 +359,7 @@ private[fpm] object AssociationRules { * from algorithms like [[FPGrowth]]. * @param itemsCol column name for frequent itemsets * @param freqCol column name for frequent itemsets count - * @param numTrainingRecords count of training Dataset + * @param numTrainingRecords count of training Dataset, default -1. * @param minConfidence minimum confidence for the result association rules * @return a DataFrame("antecedent", "consequent", "confidence", "support") containing the * association rules. @@ -376,15 +376,26 @@ private[fpm] object AssociationRules { val rows = new MLlibAssociationRules() .setMinConfidence(minConfidence) .run(freqItemSetRdd) - .map(r => Row(r.antecedent, r.consequent, r.confidence, r.freqUnion / numTrainingRecords)) + .map { r => + if (numTrainingRecords > 0) { + Row(r.antecedent, r.consequent, r.confidence, r.freqUnion / numTrainingRecords) + } else { + Row(r.antecedent, r.consequent, r.confidence) + } + + } val dt = dataset.schema(itemsCol).dataType val schema = StructType(Seq( StructField("antecedent", dt, nullable = false), StructField("consequent", dt, nullable = false), - StructField("confidence", DoubleType, nullable = false), - StructField("support", DoubleType, nullable = false))) - val rules = dataset.sparkSession.createDataFrame(rows, schema) + StructField("confidence", DoubleType, nullable = false))) + val rulesSchema = if (numTrainingRecords > 0) { + schema.add(StructField("support", DoubleType, nullable = false)) + } else { + schema + } + val rules = dataset.sparkSession.createDataFrame(rows, rulesSchema) rules } } diff --git a/mllib/src/test/scala/org/apache/spark/ml/fpm/FPGrowthSuite.scala b/mllib/src/test/scala/org/apache/spark/ml/fpm/FPGrowthSuite.scala index a7a765f93e3b..61ef755649df 100644 --- a/mllib/src/test/scala/org/apache/spark/ml/fpm/FPGrowthSuite.scala +++ b/mllib/src/test/scala/org/apache/spark/ml/fpm/FPGrowthSuite.scala @@ -38,6 +38,7 @@ class FPGrowthSuite extends SparkFunSuite with MLlibTestSparkContext with Defaul val data = dataset.withColumn("items", col("items").cast(ArrayType(dt))) val model = new FPGrowth().setMinSupport(0.5).fit(data) val generatedRules = model.setMinConfidence(0.5).associationRules + generatedRules.show() val expectedRules = spark.createDataFrame(Seq( (Array("2"), Array("1"), 1.0, 0.75), (Array("1"), Array("2"), 0.75, 0.75) diff --git a/project/MimaExcludes.scala b/project/MimaExcludes.scala index eeb097ef153a..1e48b04109ec 100644 --- a/project/MimaExcludes.scala +++ b/project/MimaExcludes.scala @@ -93,6 +93,9 @@ object MimaExcludes { ProblemFilters.exclude[InheritedNewAbstractMethodProblem]("org.apache.spark.ml.param.shared.HasValidationIndicatorCol.getValidationIndicatorCol"), ProblemFilters.exclude[InheritedNewAbstractMethodProblem]("org.apache.spark.ml.param.shared.HasValidationIndicatorCol.org$apache$spark$ml$param$shared$HasValidationIndicatorCol$_setter_$validationIndicatorCol_="), ProblemFilters.exclude[InheritedNewAbstractMethodProblem]("org.apache.spark.ml.param.shared.HasValidationIndicatorCol.validationIndicatorCol") + + // [SPARK-19939][ML] Add support for association rules in ML + ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.spark.ml.fpm.FPGrowthModel.this") ) // Exclude rules for 2.3.x From 733c7ff70c46f0c54cdf520b44645544b810e04e Mon Sep 17 00:00:00 2001 From: Yuhao Yang Date: Mon, 27 Aug 2018 15:13:31 -0700 Subject: [PATCH 7/7] comma --- project/MimaExcludes.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/MimaExcludes.scala b/project/MimaExcludes.scala index ebd390148df2..f7d47091d21d 100644 --- a/project/MimaExcludes.scala +++ b/project/MimaExcludes.scala @@ -101,7 +101,7 @@ object MimaExcludes { ProblemFilters.exclude[InheritedNewAbstractMethodProblem]("org.apache.spark.ml.param.shared.HasValidationIndicatorCol.validationIndicatorCol"), // [SPARK-23042] Use OneHotEncoderModel to encode labels in MultilayerPerceptronClassifier - ProblemFilters.exclude[MissingClassProblem]("org.apache.spark.ml.classification.LabelConverter") + ProblemFilters.exclude[MissingClassProblem]("org.apache.spark.ml.classification.LabelConverter"), // [SPARK-19939][ML] Add support for association rules in ML ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.spark.ml.fpm.FPGrowthModel.this")