該例子援引的是http://files.grouplens.org/datasets/movielens/ 中ml-100k.zip的數據,可以直接下載下來保存到本地,修改代碼中的路徑即可。
package spark;
import org.apache.spark.SparkConf;
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.mllib.recommendation.ALS;
import org.apache.spark.mllib.recommendation.MatrixFactorizationModel;
import org.apache.spark.mllib.recommendation.Rating;
import scala.Tuple2;
public class JavaASLM100K {
public static void main(String ... args) {
SparkConf sparkConf = new SparkConf().setAppName("JavaALS");
sparkConf.setMaster("local[2]");
JavaSparkContext jsc = new JavaSparkContext(sparkConf);
String path = "F:/ml-100k/u.data";
JavaRDD<String> data = jsc.textFile(path);
JavaRDD<Rating> ratings = data.map(s -> {
String[] sarray = s.split("\t");
return new Rating(Integer.parseInt(sarray[0]), Integer.parseInt(sarray[1]), Double.parseDouble(sarray[2]));
});
/**
* 1) ratings : 評分矩陣對應的RDD。需要我們輸入。如果是隱式反饋,則是評分矩陣對應的隱式反饋矩陣。
*
* 2) rank : 矩陣分解時對應的低維的維數。即PTm×kQk×nPm×kTQk×n中的維度k。這個值會影響矩陣分解的性能,越大則算法運行的時間和佔用的內存可能會越多。通常需要進行調參,一般可以取10-200之間的數。
*
* 3) iterations :在矩陣分解用交替最小二乘法求解時,進行迭代的最大次數。這個值取決於評分矩陣的維度,以及評分矩陣的係數程度。一般來說,不需要太大,比如5-20次即可。默認值是5。
*
* 4) lambda: 在
* python接口中使用的是lambda_,原因是lambda是Python的保留字。這個值即爲FunkSVD分解時對應的正則化係數。主要用於控制模型的擬合程度,增強模型泛化能力。取值越大,則正則化懲罰越強
* 。大型推薦系統一般需要調參得到合適的值。
*
* 5) alpha : 這個參數僅僅在使用隱式反饋trainImplicit時有用。指定了隱式反饋信心閾值,這個值越大則越認爲用戶和他沒有評分的物品之間沒有關聯。一般需要調參得到合適值。
*/
int rank = 10;
int numIterations = 10;
MatrixFactorizationModel model = ALS.train(JavaRDD.toRDD(ratings), rank, numIterations, 0.01);
Rating[] ts = model.recommendProducts(1, 10);
System.out.println("用戶1最喜歡的10個商品爲:");
for(int i =0 ;i < ts.length;i++){
System.out.println("商品:"+ts[i].product()+"、評分:"+ts[i].rating());
}
System.out.println("用戶18對商品177的預測評分爲:"+model.predict(18, 177));
//對數據文件u1.base中的數據進行評估
String pathTest = "F:/ml-100k/u1.base";
JavaRDD<String> data1 = jsc.textFile(pathTest);
JavaRDD<Tuple2<Integer,Integer>> ratings1 = data1.map(s -> {
String[] sarray = s.split("\t");
return new Tuple2<Integer,Integer>(Integer.parseInt(sarray[0]), Integer.parseInt(sarray[1]));
});
JavaRDD<Rating> rste = model.predict(JavaPairRDD.fromJavaRDD(ratings1));
rste.sortBy(s->s.rating(), true, 3).foreach(s->System.out.println(s.user()+"-"+s.product()+"-"+s.rating()));
}
}