scala> spark.version
res8: String = 2.2.0
我正在使用包含列locationID
的spark Dataframe。我已经创建了一个MLlib管道来构建一个线性回归模型,当我为一个locationID
提供数据时它就可以工作。我现在想为每个'locationID'创建许多模型(生产中可能有几千个locationID)。我想保存每个模型的模型系数。
我不确定在Scala中如何做到这一点。
我的管道定义如下:
import org.apache.spark.ml.feature.{OneHotEncoder, StringIndexer}
import org.apache.spark.ml.regression.LinearRegression
import org.apache.spark.ml.regression.LinearRegressionModel
import org.apache.spark.ml.feature.VectorAssembler
import org.apache.spark.ml.{Pipeline, PipelineModel}
import org.apache.spark.sql
// Load the regression input data
val mydata = spark.read.format("csv")
.option("header", "true")
.option("inferSchema", "true")
.load("./inputdata.csv")
// Crate month one hot encoding
val monthIndexer = new StringIndexer()
.setInputCol("month")
.setOutputCol("monthIndex").fit(mydata)
val monthEncoder = new OneHotEncoder()
.setInputCol(monthIndexer.getOutputCol)
.setOutputCol("monthVec")
val assembler = new VectorAssembler()
.setInputCols(Array("monthVec","tran_adr"))
.setOutputCol("features")
val lr = new LinearRegression()
.setMaxIter(10)
.setRegParam(0.3)
.setElasticNetParam(0.8)
val pipeline = new Pipeline()
.setStages(Array(monthIndexer, monthEncoder, assembler, lr))
// Fit using the model pipeline
val myPipelineModel = pipeline.fit(mydata)
然后我能够像这样拉出模型细节:
val modelExtract = myPipelineModel.stages(3).asInstanceOf[LinearRegressionModel]
println(s"Coefficients: ${modelExtract.coefficients} Intercept: ${modelExtract.intercept}")
// Summarize the model over the training set and print out some metrics
val trainingSummary = modelExtract.summary
println(s"numIterations: ${trainingSummary.totalIterations}")
println(s"objectiveHistory: [${trainingSummary.objectiveHistory.mkString(",")}]")
trainingSummary.residuals.show()
println(s"RMSE: ${trainingSummary.rootMeanSquaredError}")
println(s"r2: ${trainingSummary.r2}")
现在,我想对locationID
中找到的列mydata
进行分组,并在数据的每个分区上运行管道。
我尝试过使用groupby,但我只能聚合。
val grouped = mydata.groupBy("locationID")
我还试图将唯一的locationID
作为一个列表并循环遍历它:
val locationList = mydata.select(mydata("prop_code")).distinct
locationList.foreach { printLn }
我知道spark不是创建许多小型模型的理想选择,最适合在大量数据上创建一个模型,但我的任务是将其作为概念验证。
在spark中做这样的事情的正确方法是什么?
答案 0 :(得分:1)
在spark中做这样的事情的正确方法是什么?
我冒险声称没有好的方法。有许多高级工具可以处理核心内数据处理和许多任务调度库,可用于协调独立的学习任务。 Spark根本没有提供任何东西。
它的调度功能是平庸的,ML / MLlib工具也是如此,当每个任务都是独立的时,缩放和容错是没有用的。
你可以使用Spark进行通用目的的调度(如果你不介意使用Python,这个想法是用sklearn keyed models实现的),但那就是它。
答案 1 :(得分:0)
我遇到了同样的问题。我的数据在$“ description_pretty”上分区,这就是我的处理方式。我在分区上拆分数据框,将其输入管道,选择相关列,然后将其合并回去。
val pipe = new Pipeline().setStages(Array(encoder, assembler,
multivariate_linear_model))
val descriptions_pretty = training_df.select("description_pretty").
distinct.
as[String].
rdd.
collect
val model_predictions_df = descriptions_pretty.par.
map(x => pipe.fit(training_df.filter($"description_pretty" === x)).
transform(prediction_df.filter($"description_pretty" === x)).
select($"description", $"description_pretty",
$"standard_event_date".cast("String"),
$"prediction".as("daily_peak_bps"))).
reduce( _ union _)
您可以在.transform之前停下来,而是获取系数