2016-06-21 3 views
2

Я пытаюсь расширить или проксировать класс org.apache.spark.ml.clustering.KMeans, такой, что разрешено K = 1.Как расширить (или прокси) класс scala с помощью частного конструктора

class K1Means extends Estimator{ 

    final val kmeans = new KMeans() 
    val k = 1 

    override def setK(value:Int) { 
     if(value >1){ 
      this.kmeans.setK(value) 
     } 
    } 

    override def fit(dataset: DataFrame): KMeansModel = { 
     if(this.k == 1){ 
      /* super specific to my case */ 
      val avg_sample = Vectors.zeros(
       dataset 
       .select("scaledFeatures") 
       .take(1)(0)(0) // first row 
       .asInstanceOf[DenseVector] // was of type Any 
       .size 
      ) // with the scaling the average value of each column is 0 
      var centers_local = Array(avg_sample) 
      return new KMeansModel(centers_local) 
     } 
     else{ 
      return this.kmeans.fit(dataset) 
     } 
    } 
// every method then calls this.kmeans.method() 
} 

Я попытался это, но new KMeansModel(centers_local) не разрешается, так как KMeansModel имеет закрытый конструктор. Вот сообщение об ошибке:

constructor KMeansModel in class KMeansModel cannot be accessed in class K1Means

Я также попытался расширить KMeansModel, так что я могу создать свой собственный и вернуть его:

class K1MeansModel(centers: Array[DenseVector]) extends KMeansModel{} 

Но это также не: constructor KMeansModel in class KMeansModel cannot be accessed in class K1MeansModel

+0

Документы, кажется, не согласен с вами: https://spark.apache.org/docs/1.6.0/api/java/org/apache/spark/ml/clustering/KMeansModel.html смотрит публику мне –

+0

Можете ли вы изменить свой вопрос и предоставить фактическое сообщение об ошибке? –

+0

Хорошо, мне придется перефразировать. Конструктор является частным, возможно, это правильный способ сказать это.Это может быть вызвано только KMeans. – Borbag

ответ

2

Здесь несколько проблем, начиная с KMeansModel, являющегося приватным: https://github.com/apache/spark/blob/4f83ca1059a3b580fca3f006974ff5ac4d5212a1/mllib/src/main/scala/org/apache/spark/ml/clustering/KMeans.scala#L102

Почему это проблема? Вы можете полностью написать свой собственный прокси-сервер так, как вы его предлагали, но для того, чтобы переопределить метод «fit», тип данных, возвращаемый этой функцией, должен быть KMeansModel или совместимым (скажем, «K1MeansModel»), например:

class K1MeansModel extends KMeansModel{ 
    // ... 
} 

class K1Means extends KMeans{ 

    final val kmeans = new KMeans() 
    // ... 

    override def fit(dataset: DataFrame): KMeansModel = { 
     if(this.k == 1){ 
      // ... 
      return new K1MeansModel(centers_local) 
     } 
     else{ 
      return this.kmeans.fit(dataset) 
     } 
    } 
} 

Но да, потому что KMeansModel является частным, это невозможно. Поэтому вы можете подумать «почему бы не переопределить его?». Действительно, вы можете просто скопировать & вставить код KMeansModel, от GitHub.

Определение KMeansModel выглядит следующим образом:

class KMeansModel (
     override val uid: String, 
     private val parentModel: MLlibKMeansModel) 
    extends Model[KMeansModel] with KMeansParams { } 

Но да, потому что KMeansParams является частным, это невозможно. Поэтому вы можете подумать «почему бы не переопределить его?». Действительно, вы могли бы просто скопировать & вставить код KMeansParams, от GitHub.

Определение KMeansParams выглядит следующим образом:

trait K1MeansParams 
    extends Params 
     with HasMaxIter 
     with HasFeaturesCol 
     with HasSeed 
     with HasPredictionCol 
     with HasTol { } 

Но да, потому что HasMaxIter, HasFeaturesCol, HasSeed, HasPredictionCol, HasTol все частные, это не представляется возможным. ... У тебя идея.


TL; DR да, вы могли бы пойти и переопределение (копировать & клейстер) тонну искровых классов в свой проект, просто переопределить KMeans. Я считаю как минимум 7 классов, для которых потребуется скопировать &. Для меня это дерьмо. Вместо этого я бы рекомендовал добавить код непосредственно в Apache Spark. Вставьте Spark GitHub repo, добавьте свой код для K = 1 непосредственно в класс ml.KMeans и сделайте с ним.

 Смежные вопросы

  • Нет связанных вопросов^_^