Spark ALS多次训练模型对象不同但推荐结果相同问题排查
问题解答
你遇到的这个情况其实是PySpark随机数生成机制导致的典型问题,下面给你拆解原因和解决办法:
1. 核心原因:同一会话下全局随机种子被复用
PySpark的ALS算法在初始化用户/物品因子矩阵时,会依赖随机数。但如果没有显式指定seed参数,Spark会默认使用SparkContext的全局随机种子。在同一个脚本运行的生命周期(也就是同一个SparkSession内),多次创建ALS实例并训练时,底层的随机数生成器并不会重新初始化,而是延续上一次的随机序列生成数值。
换句话说:第一次训练用了全局随机序列的前N个值初始化因子矩阵,第二次训练还是从这个序列的同一个起始位置取数,导致两次的初始因子矩阵完全一致。哪怕模型对象的ID不同(比如你看到的ALS_444a9e62eb6938248b4c和ALS_465c95728272696c6c67),但模型的核心初始参数是一样的,最终训练出的推荐结果自然没有差别。
2. 重启脚本后结果变化的原因
当你重启脚本时,新的SparkSession会被创建,此时全局随机种子会重新生成(通常基于当前系统时间),ALS训练的初始随机值就会和上一次脚本运行时不同,推荐结果也就随之变化了。
3. 解决方案:显式指定不同的随机种子
要让两次训练得到不同的模型和推荐结果,只需要在创建ALS实例时,手动指定seed参数,并且每次训练使用不同的种子值即可:
修改后的训练函数:
def __train_model(ratings, seed): """Train the ALS model with the current dataset """ logger.info("Training the ALS model...") als = ALS( rank=rank, maxIter=iterations, implicitPrefs=True, regParam=regularization_parameter, userCol="order_id", itemCol="product_id", ratingCol="count", seed=seed # 显式传入随机种子 ) model = als.fit(ratings) logger.info("ALS model built!") return model # 两次训练使用不同的固定种子 model1 = __train_model(ratings_DF, 123) sim_table_1 = model1.recommendForAllUsers(100).toPandas() model2 = __train_model(ratings_DF, 456) sim_table_2 = model2.recommendForAllUsers(100).toPandas()
如果想要动态生成随机种子,也可以用Python的随机数模块:
import random # 每次生成0到100000之间的随机整数作为种子 model1 = __train_model(ratings_DF, random.randint(0, 100000)) model2 = __train_model(ratings_DF, random.randint(0, 100000))
验证方法
你可以打印两个模型的用户因子矩阵来确认差异:
print("Model1 user factor sample:", model1.userFactors.select("features").first()) print("Model2 user factor sample:", model2.userFactors.select("features").first())
设置不同种子后,这两个输出会明显不同,说明初始随机值已经被正确区分开了。
内容的提问来源于stack exchange,提问作者Ivan Shelonik
相关产品推荐
相关产品推荐

