Spark ML中randomSplit无固定seed时样本数波动是否为预期行为?
这是预期行为,不是Bug!
你遇到的训练/测试集行数不固定的情况,完全符合Spark ML randomSplit 函数的设计逻辑,并不是软件Bug。下面给你拆解背后的原因:
1. 随机拆分的本质:近似比例而非精确比例
randomSplit 是通过随机抽样实现数据集拆分的:它会为每条数据生成一个0到1之间的随机数,再根据你指定的比例(比如0.7和0.3),判断随机数落在哪个区间,进而将数据分配到训练集或测试集。
这种机制决定了拆分结果是近似符合设定比例,而非严格精确匹配。当数据集规模较小时(比如你的1442行),随机抽样的波动会更明显——1442的70%是1009.4,你几次运行的训练集行数(989-1025)都围绕这个数值波动,完全在合理范围内。
2. Seed参数的作用:固定随机状态
当你指定seed参数时,Spark会固定随机数生成器的初始状态,这样每次运行生成的随机数序列完全一致,自然拆分结果(包括行数)也会完全相同。这就是设置seed后行数不再波动的原因。
3. 如果需要精确行数的拆分怎么办?
如果你的业务场景要求严格按照7:3的行数拆分(比如训练集必须是1009行,测试集433行),可以手动计算行数后进行拆分,示例代码如下:
import org.apache.spark.sql.functions.rand // 先打乱数据集 val shuffledDF = dfForModel.orderBy(rand()) // 计算训练集的精确行数 val totalCount = dfForModel.count() val trainCount = (totalCount * 0.7).toLong // 拆分数据集 val trainData = shuffledDF.limit(trainCount) val testData = shuffledDF.except(trainData)
不过要注意,except操作在大数据集上可能有性能损耗,小数据集(比如你的情况)完全可以放心使用。
内容的提问来源于stack exchange,提问作者Bhagirathi
相关产品推荐
相关产品推荐

