我正在使用Spark来构建推荐系统原型。在完成一些教程后,我能够从我的数据中训练MatrixFactorizationModel
。
但是,Spark mllib训练的模型只是Serializable
。如何使用此模型为真实用户推荐?我的意思是,如果用户数据增加,我怎样才能将模型保存到某种数据库中或更新它?
例如,由Mahout推荐库训练的模型可以存储到像Redis这样的数据库中,然后我们可以稍后查询推荐的项目列表。但是我们如何在Spark中做类似的事情?有什么建议吗?
答案 0 :(得分:9)
首先,您从Mahout引用的“模型”不是模型,而是预先计算的推荐列表。您也可以使用Spark执行此操作,并为用户计算批量建议,并将其保留在您喜欢的任何位置。这与序列化模型无关。如果您不想进行实时更新或评分,您可以在那里停止使用Spark,就像使用Mahout一样。
但我同意在很多情况下你确实希望将模型运送到其他地方并提供服务。如您所见,Spark中的其他模型为Serializable
,但不是MatrixFactorizationModel
。 (是的,即使它被标记为这样,它也不会序列化。)同样,有一个名为PMML的预测模型的标准序列化,但它不包含因式矩阵模型的词汇表。
原因实际上是一样的。尽管许多预测模型(如SVM或逻辑回归模型)只是一小组系数,但是因式矩阵模型非常庞大,包含两个可能具有数十亿个元素的矩阵。这就是为什么我认为PMML没有任何合理的编码。
同样,在Spark中,这意味着实际的矩阵是RDD
,无法直接序列化。您可以将这些RDD保存到存储中,使用Spark在其他地方重新读取它们,然后手动重新创建MatrixFactorizationModel
。
但您无法使用Spark提供或更新模型。为此,您正在考虑编写一些代码来执行更新并动态计算建议。
我不介意在这里建议Oryx项目,因为它的目的是管理这方面,特别是对于ALS建议。实际上,Oryx 2项目基于Spark,虽然在alpha中,已经包含了序列化和提供MatrixFactorizationModel
输出的完整管道。我不知道它是否符合您的需求,但至少可能是一个有趣的参考点。
答案 1 :(得分:2)
使用Spark创建recs的另一种方法是搜索引擎方法。这基本上是Solr或Elasticsearch提供的共同推荐人。将因子分解与同时发生的比较超出了这个问题,因此我将仅描述后者。
您将互动(user-id,item-id)提供给Mahout的spark-itemsimilarity
。这将为交互数据中显示的每个项目生成类似项目的列表。默认情况下它将作为csv出现,因此可以存储在任何地方。但它需要由搜索引擎索引。
在任何情况下,当您想要获取recs时,您使用用户的历史记录作为查询,您将获得一个有序的项目列表作为recs。
此方法的一个好处是可以根据需要为多个用户操作计算指标。可以使用用户采取的与您要推荐的内容相关的任何操作。例如,如果您想推荐购买,但也记录产品视图。如果您将产品视图视为与购买相同,那么您可能会得到更糟糕的回复(我已经尝试过了)。但是,如果您计算购买指标和产品视图的另一个(实际上是交叉共生)指标,则它们同样可以预测购买。这具有增加用于recs的数据的效果。可以使用用户位置完成相同类型的操作,以将位置信息混合到购买记录中。
您还可以根据上下文偏向您的rec。如果您在目录的“电子”部分,您可能希望recs偏向于电子产品。根据项目的“类别”元数据字段向查询添加电子设备,并在查询中提升它,并且您有偏见的记录。
由于所有指标的偏向和混合都发生在查询中,因此recs引擎可以轻松调整到多个上下文,同时只保留一个通过搜索引擎进行的多字段查询。我们从Solr或Elasticsearch获得可扩展性。
分解或搜索方法的另一个好处是,全新的用户和新的历史记录可用于创建记录,其中旧的Mahout推荐人只能向用户推荐并且在作业运行时已知的交互。
这里的描述:
答案 2 :(得分:0)
你应该在一个简化的RDD(一组用户,产品)对上运行model.predictAll(),就像在Mahout Hadoop Job中一样,并存储结果以供在线使用......
答案 3 :(得分:0)
您可以使用 .save( sparkContext,outputFolder )功能将模型保存到您选择的文件夹中。在实时提供建议时,您只需使用 MatrixFactorizationModel.load( sparkContext,modelFolder )函数将其作为MatrixFactorizationModel对象加载。
@Sean Owen 的问题:MatrixFactorizationObject不包含分解矩阵:用户特征和项目特征矩阵,而不是建议/预测评级。< / p>