spark 协同过滤
协同过滤是一个常用的推荐算法。这些技术用于填充一个user-item的关联矩阵的缺失项。spark.mllib目前支持基于模型的协同过滤,用户和产品能被一组比较小的潜在因素描述,那样算法就可以来预测缺失的项目。spark.mllib使用最小二乘法(ALS)来学习潜在因素。spark.mllib 主要有以下这些参数:
- numBlocks 用于并行计算的块的数量(自动设置为-1)
- rank 是模型中潜在因素的数量
- iterations 运行时的迭代次数
- lambda 指定ALS中正则化的参数
- implicitPrefs 指定使用一个显式反馈的还是一个隐式反馈的ALS变体
- alpha 是一个参数用于查看隐式反馈的ALS变体控制优先级的基准线
显式或隐式反馈
矩阵分解是协同过滤对待user-item矩阵的一个首选方法。
在现实中往往只能得到隐式的反馈(如:浏览,点击,购买,分享等)。spark-lib中处理隐式反馈信息可以参考协同过滤的隐式反馈的数据集。本质上讲这种方法并没有直接构建评级的矩阵模型,它只是优先使用的是二进制的数据。相关的评级只是用来观察用户的偏好,而不是明确的评级。然后用模型找到潜在的因素,进而预测用户的偏好。
调整正则化参数
从1.1版本,我们就缩放正则化参数lambda来解决最小二乘法的问题(user在更新user因数产生的评级或者product在更新product因数产生的评级)。有一种方法叫做ALS-WR参考资料在Large-Scale Parallel Collaborative Filtering for the Netflix Prize。它让lambda较少的依赖于数据集的规模。那样我们就可以在抽样数据集或者能够完整的数据集都得到好的性能。
实例
Scala
在下面的例子里面我们采用评级数据。每一行包括一个用户,一个产品和一个评级数据。由于评级数据是显式的,我们就可以使用默认的ALS.train()方法计算,使用均方差来评估推荐模型的好坏。
详细的API文档ALS Scala docs
import org.apache.spark.mllib.recommendation.ALS
import org.apache.spark.mllib.recommendation.MatrixFactorizationModel
import org.apache.spark.mllib.recommendation.Rating
// Load and parse the data
val data = sc.textFile("data/mllib/als/test.data")
val ratings = data.map(_.split(',') match { case Array(user, item, rate) =>
Rating(user.toInt, item.toInt, rate.toDouble)
})
// Build the recommendation model using ALS
val rank = 10
val numIterations = 10
val model = ALS.train(ratings, rank, numIterations, 0.01)
// Evaluate the model on rating data
val usersProducts = ratings.map { case Rating(user, product, rate) =>
(user, product)
}
val predictions =
model.predict(usersProducts).map { case Rating(user, product, rate) =>
((user, product), rate)
}
val ratesAndPreds = ratings.map { case Rating(user, product, rate) =>
((user, product), rate)
}.join(predictions)
val MSE = ratesAndPreds.map { case ((user, product), (r1, r2)) =>
val err = (r1 - r2)
err * err
}.mean()
println("Mean Squared Error = " + MSE)
// Save and load model
model.save(sc, "target/tmp/myCollaborativeFilter")
val sameModel = MatrixFactorizationModel.load(sc, "target/tmp/myCollaborativeFilter")
完整的例子在源码中examples/src/main/scala/org/apache/spark/examples/mllib/RecommendationExample.scala。如果评级矩阵来源于其它的信息源。使用trainImplicit方法可以得到更好的结果。
val alpha = 0.01
val lambda = 0.01
val model = ALS.trainImplicit(ratings, rank, numIterations, lambda, alpha)
可以参考spark快速启动指南中的the Self-Contained Applications 来运行上面的程序。保证spark-mlib作为依赖文件加入到你的工程中了。
Java
所有MLlib中的方法都可以被java很好的使用。你可以像scala中那样使用它们。唯一要注意的是,scala中使用的是 Scala RDD 对象,而Spark Java API中使用的是独立的 JavaRDD对象。你可以通过调用 JavaRDD对象的 .rdd() 来转换成 Scala RDD 对象。下面是一个在源码中提供的例子程序。
详细javaAPI文档 ALS Java docs
import scala.Tuple2;
import org.apache.spark.api.java.*;
import org.apache.spark.api.java.function.Function;
import org.apache.spark.mllib.recommendation.ALS;
import org.apache.spark.mllib.recommendation.MatrixFactorizationModel;
import org.apache.spark.mllib.recommendation.Rating;
import org.apache.spark.SparkConf;
SparkConf conf = new SparkConf().setAppName("Java Collaborative Filtering Example");
JavaSparkContext jsc = new JavaSparkContext(conf);
// Load and parse the data
String path = "data/mllib/als/test.data";
JavaRDD<String> data = jsc.textFile(path);
JavaRDD<Rating> ratings = data.map(
new Function<String, Rating>() {
public Rating call(String s) {
String[] sarray = s.split(",");
return new Rating(Integer.parseInt(sarray[0]), Integer.parseInt(sarray[1]),
Double.parseDouble(sarray[2]));
}
}
);
// Build the recommendation model using ALS
int rank = 10;
int numIterations = 10;
MatrixFactorizationModel model = ALS.train(JavaRDD.toRDD(ratings), rank, numIterations, 0.01);
// Evaluate the model on rating data
JavaRDD<Tuple2<Object, Object>> userProducts = ratings.map(
new Function<Rating, Tuple2<Object, Object>>() {
public Tuple2<Object, Object> call(Rating r) {
return new Tuple2<Object, Object>(r.user(), r.product());
}
}
);
JavaPairRDD<Tuple2<Integer, Integer>, Double> predictions = JavaPairRDD.fromJavaRDD(
model.predict(JavaRDD.toRDD(userProducts)).toJavaRDD().map(
new Function<Rating, Tuple2<Tuple2<Integer, Integer>, Double>>() {
public Tuple2<Tuple2<Integer, Integer>, Double> call(Rating r){
return new Tuple2<Tuple2<Integer, Integer>, Double>(
new Tuple2<Integer, Integer>(r.user(), r.product()), r.rating());
}
}
));
JavaRDD<Tuple2<Double, Double>> ratesAndPreds =
JavaPairRDD.fromJavaRDD(ratings.map(
new Function<Rating, Tuple2<Tuple2<Integer, Integer>, Double>>() {
public Tuple2<Tuple2<Integer, Integer>, Double> call(Rating r){
return new Tuple2<Tuple2<Integer, Integer>, Double>(
new Tuple2<Integer, Integer>(r.user(), r.product()), r.rating());
}
}
)).join(predictions).values();
double MSE = JavaDoubleRDD.fromRDD(ratesAndPreds.map(
new Function<Tuple2<Double, Double>, Object>() {
public Object call(Tuple2<Double, Double> pair) {
Double err = pair._1() - pair._2();
return err * err;
}
}
).rdd()).mean();
System.out.println("Mean Squared Error = " + MSE);
// Save and load model
model.save(jsc.sc(), "target/tmp/myCollaborativeFilter");
MatrixFactorizationModel sameModel = MatrixFactorizationModel.load(jsc.sc(),
"target/tmp/myCollaborativeFilter");
完整的例子在源码中examples/src/main/java/org/apache/spark/examples/mllib/JavaRecommendationExample.java。可以参考spark快速启动指南中的the Self-Contained Applications 来运行上面的程序。保证spark-mlib作为依赖文件加入到你的工程中了。
Python
在下面的例子里面我们采用评级数据。每一行包括一个用户,一个产品和一个评级数据。由于评级数据是显式的,我们就可以使用默认的ALS.train()方法计算,使用均方差来评估推荐模型的好坏。
详细的Python APIALS Python docs
from pyspark.mllib.recommendation import ALS, MatrixFactorizationModel, Rating
# Load and parse the data
data = sc.textFile("data/mllib/als/test.data")
ratings = data.map(lambda l: l.split(','))\
.map(lambda l: Rating(int(l[0]), int(l[1]), float(l[2])))
# Build the recommendation model using Alternating Least Squares
rank = 10
numIterations = 10
model = ALS.train(ratings, rank, numIterations)
# Evaluate the model on training data
testdata = ratings.map(lambda p: (p[0], p[1]))
predictions = model.predictAll(testdata).map(lambda r: ((r[0], r[1]), r[2]))
ratesAndPreds = ratings.map(lambda r: ((r[0], r[1]), r[2])).join(predictions)
MSE = ratesAndPreds.map(lambda r: (r[1][0] - r[1][1])**2).mean()
print("Mean Squared Error = " + str(MSE))
# Save and load model
model.save(sc, "target/tmp/myCollaborativeFilter")
sameModel = MatrixFactorizationModel.load(sc, "target/tmp/myCollaborativeFilter")
完整的例子在源码中examples/src/main/python/mllib/recommendation_example.py。如果评级矩阵来源于其它的信息源。使用trainImplicit方法可以得到更好的结果。
# Build the recommendation model using Alternating Least Squares based on implicit ratings
model = ALS.trainImplicit(ratings, rank, numIterations, alpha=0.01)
可以参考spark快速启动指南中的the Self-Contained Applications 来运行上面的程序。保证spark-mlib作为依赖文件加入到你的工程中了。