【发布时间】:2016-05-31 07:17:52
【问题描述】:
我正在一个相当大的 RDD rdd 上训练一个 org.apache.spark.mllib.recommendation.ALS 模型。我想选择一个像样的正则化超参数,这样我的模型就不会过度(或不足)拟合。为此,我将rdd(使用randomSplit)拆分为一个训练集和一个测试集,并使用一组定义的超参数对它们执行交叉验证。
由于我在交叉验证中多次使用训练和测试 RDD,因此在某些时候cache() 数据似乎很自然,以加快计算速度。但是,我的 Spark 知识非常有限,我想知道这两个选项中哪个更好(以及为什么):
-
在拆分前缓存初始RDD
rdd,即:val train_proportion = 0.75 val seed = 42 rdd.cache() val split = rdd.randomSplit(Array(train_proportion, 1 - train_proportion), seed) val train_set = split(0) val test_set = split(1) -
在拆分初始RDD后缓存
train和testRDD:val train_proportion = 0.75 val seed = 42 val split = rdd.randomSplit(Array(train_proportion, 1 - train_proportion), seed) val train_set = split(0).cache() val test_set = split(1).cache()
我的猜测是选项 1 更好,因为 randomSplit 也将受益于 rdd 被缓存的事实,但我不确定它是否会对(多次)未来对 train_set 的访问产生负面影响和 test_set 关于选项 2。
This answer 似乎证实了我的直觉,但它没有收到任何反馈,所以我想在这里询问一下。
你怎么看?更重要的是:为什么?
请注意,我在 Spark 集群上进行了实验,但是这几天经常很忙,所以我的结论可能是错误的。我还检查了 Spark 文档,但没有找到我的问题的答案。
【问题讨论】:
-
如果
rdd的创建成本不是很高,那么拆分后的缓存似乎是一个更好的选择。但是,如果我们没有看到您的代码或执行统计信息,您就不能真正孤立地判断。例如,ALS 无论如何都在使用密集的缓存和检查点。 -
重要的不是以后会不会做更多的计算。您想知道从给定点执行沿袭的次数。如果您从训练集中执行单个线性沿袭,应用大量转换序列并且从不从原始训练集中执行新沿袭,那么 cache() 将没有用。由于我们不确切知道您在训练和测试集之后做了什么,因此我们无法回答这个问题。由于交叉验证的问题,在我看来,您可以按照 mark91 cache 之前和之后的建议
-
感谢您的回答。 @psoucy:之后我要做的就是,对于一组正则化参数,在
train_set上训练 ALS,然后在test_set上预测评级。我还计算了 MSE 和 MAE 来评估我的结果并选择最佳正则化参数,所以我想每个超参数在test_set上执行了至少一个沿袭,这证明缓存它是合理的。但是,由于我不太了解 ALS 是如何实现的,所以我仍然不确定缓存train_set是否是个好主意。 -
@AlexisZubiolo 是的,我很高兴在这种情况下 cache() 会很有用。如果您查看此示例ampcamp.berkeley.edu/big-data-mini-course/…,他们会在发送到 train() 之前将所有集合都保留()
标签: scala caching apache-spark split