#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")