This is an automated email from the ASF dual-hosted git repository.

zhengruifeng pushed a commit to branch branch-4.x
in repository https://gitbox.apache.org/repos/asf/spark.git


The following commit(s) were added to refs/heads/branch-4.x by this push:
     new 27aebe769827 [SPARK-58250][ML][CONNECT] Add OneVsRest size estimate
27aebe769827 is described below

commit 27aebe769827715e9dec4af006e6a4f498cec988
Author: Ruifeng Zheng <[email protected]>
AuthorDate: Wed Jul 22 19:46:35 2026 +0800

    [SPARK-58250][ML][CONNECT] Add OneVsRest size estimate
    
    ### What changes were proposed in this pull request?
    
    This patch adds a model-owned `estimatedSize` implementation for 
`OneVsRestModel`. The estimate includes the model's parameter metadata, label 
metadata, and the estimates of its binary classification submodels.
    
    ### Why are the changes needed?
    
    Spark Connect uses `Model.estimatedSize` to enforce ML model-cache limits. 
`OneVsRestModel` was the only concrete classification model that inherited the 
default graph traversal. Its copied submodels retain their parent estimators, 
so that traversal can include shared Spark session/context state rather than 
only the cached model's data. The explicit estimate follows the established 
classifier-model pattern and accounts only for state owned by the One-vs-Rest 
model.
    
    ### Does this PR introduce _any_ user-facing change?
    
    Yes. Spark Connect cache accounting for One-vs-Rest models becomes more 
accurate, preventing shared runtime state from inflating the estimated model 
size. There is no public API change.
    
    ### How was this patch tested?
    
    Added a regression test that verifies the estimate is the sum of 
One-vs-Rest parameter metadata, label metadata, and its contained models' 
estimates.
    
    Ran:
    
    ```
    JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64 build/sbt 'mllib/testOnly 
*OneVsRestSuite'
    ```
    
    All 17 tests passed.
    
    ### Was this patch authored or co-authored using generative AI tooling?
    
    Generated-by: Codex (GPT-5)
    
    Closes #57420 from zhengruifeng/SPARK-58181-one-vs-rest-estimated-size-dev3.
    
    Authored-by: Ruifeng Zheng <[email protected]>
    Signed-off-by: Ruifeng Zheng <[email protected]>
    (cherry picked from commit c1d87077e6e3f6d5b90d16d7e07a17b5e81f7a3a)
    Signed-off-by: Ruifeng Zheng <[email protected]>
---
 .../org/apache/spark/ml/classification/OneVsRest.scala |  6 ++++++
 .../spark/ml/classification/OneVsRestSuite.scala       | 18 ++++++++++++++++++
 2 files changed, 24 insertions(+)

diff --git 
a/mllib/src/main/scala/org/apache/spark/ml/classification/OneVsRest.scala 
b/mllib/src/main/scala/org/apache/spark/ml/classification/OneVsRest.scala
index f62b951fd650..38c68fd7000c 100644
--- a/mllib/src/main/scala/org/apache/spark/ml/classification/OneVsRest.scala
+++ b/mllib/src/main/scala/org/apache/spark/ml/classification/OneVsRest.scala
@@ -42,6 +42,7 @@ import org.apache.spark.sql.functions._
 import org.apache.spark.sql.types._
 import org.apache.spark.storage.StorageLevel
 import org.apache.spark.util.ArrayImplicits._
+import org.apache.spark.util.SizeEstimator
 import org.apache.spark.util.ThreadUtils
 
 private[ml] trait ClassifierTypeTrait {
@@ -148,6 +149,11 @@ final class OneVsRestModel private[ml] (
   @Since("2.4.0")
   val numFeatures: Int = models.head.numFeatures
 
+  private[spark] override def estimatedSize: Long = {
+    estimateMatadataSize + SizeEstimator.estimate(labelMetadata) +
+      models.iterator.map(_.estimatedSize).sum
+  }
+
   /** @group setParam */
   @Since("2.1.0")
   def setFeaturesCol(value: String): this.type = set(featuresCol, value)
diff --git 
a/mllib/src/test/scala/org/apache/spark/ml/classification/OneVsRestSuite.scala 
b/mllib/src/test/scala/org/apache/spark/ml/classification/OneVsRestSuite.scala
index 61b5a50fea69..70408731a20f 100644
--- 
a/mllib/src/test/scala/org/apache/spark/ml/classification/OneVsRestSuite.scala
+++ 
b/mllib/src/test/scala/org/apache/spark/ml/classification/OneVsRestSuite.scala
@@ -68,6 +68,24 @@ class OneVsRestSuite extends MLTest with 
DefaultReadWriteTest {
     ParamsSuite.checkParams(model)
   }
 
+  test("SPARK-58250: OneVsRestModel estimated size") {
+    val trainingData = Seq(
+      (0.0, Vectors.dense(0.0, 0.0)),
+      (0.0, Vectors.dense(0.0, 1.0)),
+      (1.0, Vectors.dense(1.0, 0.0)),
+      (1.0, Vectors.dense(1.0, 1.0)),
+      (2.0, Vectors.dense(2.0, 0.0)),
+      (2.0, Vectors.dense(2.0, 1.0))).toDF("label", "features")
+
+    val model = new OneVsRest()
+      .setClassifier(new LogisticRegression().setMaxIter(1))
+      .fit(trainingData)
+
+    val maxSize = 32 * 1024
+    assert(model.estimatedSize < maxSize,
+      s"Estimation (${model.estimatedSize}) should be less than $maxSize")
+  }
+
   test("one-vs-rest: default params") {
     val numClasses = 3
     val ova = new OneVsRest()


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to