关于"小数据"的Spark性能

par*_*iso 5 java apache-spark apache-spark-sql

我希望熟悉Spark的人可以给我一个"直觉检查",看看我是否可能滥用SparkML框架,或者考虑到上下文(#rows,#feature),我所看到的性能是可以理解的.

简而言之,我有一个相当宽的小数据集(~150行)(~180个特征).我已经在Spark和Scikit-learn中编写了类似的Lasso训练代码,这导致相同的模型(相同的模型系数和LOOCVE).但是,Spark代码需要大约100倍的时间(sklearn需要大约5秒,接近600秒.

据我所知,Spark针对大型分布式数据集进行了优化,并且这种差异可以合理地归因于数据并行性隐藏的开销延迟,但这仍然感觉非常缓慢.

火花代码基本上是:

//... code to add a number of PipelineStages to a List<PipelineStage> (~90 UnaryTransformer stages), ending in a StandardScaler

// Add Lasso model
LinearRegression lasso = new LinearRegression()
                .setLabelCol(response)
                .setFeaturesCol("normed_features")
                .setMaxIter(100000)
                .setPredictionCol(response+"_prediction")
                .setElasticNetParam(1.0)
                .setFitIntercept(true)
                .setRegParam(0.2);

// stages is the List<PipelineStage> loaded with 90 or so UnaryTransformer steps
stages.add(lasso);

Pipeline pipeline = new Pipeline(stages);
DataFrame df = getTrainingData(trainingData, response);
RegressionEvaluator evaluator = new RegressionEvaluator()
                .setLabelCol(response)
                .setMetricName("mae")
                .setPredictionCol(response+"_prediction")
);

df.cache();

ParamMap[] paramGrid = new ParamGridBuilder().build();

CrossValidator cv = new CrossValidator()
            .setEstimator(pipeline)
            .setEvaluator(evaluator)
            .setEstimatorParamMaps(paramGrid)
            .setNumFolds(20);

double cve = cv.fit(df).avgMetrics()[0];
Run Code Online (Sandbox Code Playgroud)

Python代码使用与#folds(20)相同的Lasso和GridSearchCV.

不幸的是,我无法真正提供MWE,因为我们使用自定义的变换器,我必须粘贴,但我想知道是否有人愿意权衡sklearn和spark之间的运行时差异是否意味着用户错误.我有意应用的唯一好方法是在安装CrossValidator之前缓存训练DataFrame.