Spark IllegalArgumentException: объекты столбца должны иметь тип struct<тип:tinyint,размер:int,индексы:array,значения:array>

#scala #apache-spark #linear-regression

#scala #apache-spark #линейная регрессия

Вопрос:

Я пытаюсь использовать org.apache.spark.ml.regression.LinearRegression подходящие мои данные. Итак, я преобразовал исходный RDD в dataframe и попытался передать его в модель линейной регрессии.

 val spark: SparkSession = SparkSession.builder.master("local").getOrCreate
val parsedData = dataRDD.map{
  item =>
    val doubleArray = Array(item._1.toDouble, item._2.toDouble, item._3.toDouble)
    val features = Vectors.dense(doubleArray)
    Row(item._4.toDouble, features)
}

val schema = List(
  StructField("label", DoubleType, true),
  StructField("features", new org.apache.spark.mllib.linalg.VectorUDT, true)
)

val df = spark.createDataFrame(
  parsedData,
  StructType(schema)
)
val lr = new LinearRegression()
  .setMaxIter(10)
  .setRegParam(0.3)
  .setElasticNetParam(0.8)

val lr_model = lr.fit(df)
  

И вот как выглядит фрейм данных:

  --------- ------------- 
|    label|     features|
 --------- ------------- 
|      5.0|[0.0,1.0,0.0]|
|     20.0|[0.0,1.0,0.0]|
|    689.0|[0.0,1.0,0.0]|
|    627.0|[0.0,1.0,0.0]|
|    127.0|[0.0,1.0,0.0]|
|      0.0|[0.0,1.0,0.0]|
|      0.0|[0.0,1.0,0.0]|
|      0.0|[0.0,1.0,0.0]|
|     76.0|[0.0,1.0,0.0]|
|      5.0|[0.0,1.0,0.0]|
|      0.0|[0.0,1.0,0.0]|
|      0.0|[0.0,1.0,0.0]|
|      0.0|[0.0,1.0,0.0]|
|      0.0|[0.0,1.0,0.0]|
|      0.0|[0.0,1.0,0.0]|
|      2.0|[0.0,1.0,0.0]|
|    329.0|[0.0,1.0,0.0]|
|2354115.0|[0.0,1.0,0.0]|
|      5.0|[0.0,1.0,0.0]|
|   4303.0|[0.0,1.0,0.0]|
 --------- ------------- 
  

Но он представил ошибку ниже.

 java.lang.IllegalArgumentException: requirement failed: Column features must be of type struct<type:tinyint,size:int,indices:array<int>,values:array<double>> but was actually struct<type:tinyint,size:int,indices:array<int>,values:array<double>>.
  

Более поздний тип данных, похоже, не отличается от требуемого. Кто-нибудь может помочь?

Ответ №1:

Вы используете org.apache.spark.ml.regression.LinearRegression (SparkML) со старой версией VectorUDT (mllib, которая устарела), и они, похоже, не работают вместе.

Замените new org.apache.spark.mllib.linalg.VectorUDT на new org.apache.spark.ml.linalg.VectorUDT , и это должно сработать.

Обратите внимание, что, чтобы избежать объявления схемы, вы можете создать фрейм данных с toDF помощью (после импорта импликаций spark), чтобы позволить Spark определить правильный тип ( org.apache.spark.ml.linalg.VectorUDT ) для вас:

 import org.apache.spark.ml.linalg.Vectors
import spark.implicits._
val df = dataRDD.map{ item =>
    val doubleArray = Array(item._1.toDouble, item._2.toDouble, item._3.toDouble)
    val features = Vectors.dense(doubleArray)
    (item._4.toDouble, features)
}.toDF("label", "features")