在机器学习中,特指使用最小二乘法的一种协同推荐算法。如下图所示,u表示用户,v表示商品,用户给商品打分,但是并不是每一个用户都会给每一种商品打分。? 表示用户没有打分的情况,所以这个矩阵A很多元素都是空的,我们称其为“缺失值(missing value)”。协同过滤提出了一种支持不完整评分矩阵的矩阵分解方法,不用对评分矩阵进行估值填充。
和协同过滤不一样的是,ALS认为用户的评分矩阵是有用户特征矩阵和物品特征矩阵相乘得到的。
ALS 的核心假设是:打分矩阵A是近似低秩的,即一个m∗n的打分矩阵 A 可以用两个小矩阵U(m∗k)和V(n∗k)的乘积来近似:其中k<
Am×n=Um×k×Vk×n
我们把打分理解成相似度,那么“打分矩阵A(m∗n)”就可以由“用户喜好特征矩阵U(m∗k)”和“产品特征矩阵V(n∗k)”的乘积。
Spark使用的是交叉最小二乘法(ALS)来最优化损失函数。算法的思想就是:我们先随机生成然后固定它求解,再固定求解,这样交替进行下去,直到取得最优解min(C)。因为每步迭代都会降低误差,并且误差是有下界的,所以 ALS 一定会收敛。但由于问题是非凸的,ALS 并不保证会收敛到全局最优解。但在实际应用中,ALS 对初始点不是很敏感,是否全局最优解造成的影响并不大。(也可能是一个局部最优解)
package hhc.mllib.label.learn.recommend;
import hhc.mllib.label.learn.config.AppConfig;
import hhc.mllib.label.learn.ml.CreaterBase;
import org.apache.spark.api.java.JavaPairRDD;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.api.java.function.Function;
import org.apache.spark.mllib.evaluation.RegressionMetrics;
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.rdd.RDD;
import scala.Tuple2;
import java.util.Arrays;
import java.util.List;
/**
* Created by huhuichao on 2017/12/7.
*/
public class ALSModelCreater extends CreaterBase{
private MatrixFactorizationModel model;
private transient JavaSparkContext jsc;
public ALSModelCreater(JavaSparkContext jsc) {
this.jsc = jsc;
}
/**
* 读取样本数据
* @param path
* @return
*/
public static JavaRDD getALSJavaRDD(String path, JavaSparkContext sc,String split) {
JavaRDD data=sc.textFile(path);
JavaRDD ratings = data.map(
new Function() {
public Rating call(String s) {
String[] sarray = s.split(split);
return new Rating(Integer.parseInt(sarray[0]), Integer.parseInt(sarray[1]),
Double.parseDouble(sarray[2]));
}
}
);
return ratings;
}
public MatrixFactorizationModel training (JavaRDD ratings,int rank, int numIterations, double v){
return ALS.train(ratings.rdd(), rank, numIterations, v);
}
/**
*
* 计算方差
* @param ratings 样本数据
* @param model model
* @return
*/
public static double evaluateMSE(JavaRDD ratings,MatrixFactorizationModel model) {
JavaRDD> userProducts = ratings.map(
new Function>() {
private static final long serialVersionUID = 1L;
@Override
public Tuple2