若是機器學習能像推薦引擎這樣的簡單用例征服,那麼開始使用機器學習能夠像Hello World同樣簡單。算法
在Java中啓動機器學習最流行的工具選擇是Apache Spark,由於它帶有一個特殊的ML庫或模塊,其中包含着許多簡單到高級的算法。apache
產品推薦被業界公認爲是一個協做過濾問題,Apache Spark有一個內置算法來實現它。app
什麼是協同過濾?機器學習
根據Apache Spark網站 上的描述:ide
這些技術旨在補充用戶項目關聯矩陣的缺失條目。 spark.mllib目前支持基於模型的協同過濾,其中用戶和產品由一組可用於預測缺失條目的潛在因素來描述。 spark.mllib使用交替最小二乘法(ALS)來學習這些潛在的因素。工具
spark.mllib之實現具備如下參數:學習
numBlocks是用於並行計算的塊數(設置爲-1以自動配置)。網站
排名是要使用的功能數量(也稱爲潛在因子數量)。spa
迭代是運行ALS的迭代次數。 ALS一般在20次或更少的迭代中收斂到合理的解決方案。orm
lambda指定ALS中的正則化參數。
implicitPrefs指定是使用顯式反饋ALS變體,仍是適用於隱式反饋數據的變體。
alpha是一個適用於ALS的隱式反饋變量的參數,它支配偏好觀察值的基線置信度。
開始Spark之旅
ApacheSpark mllib可使用Maven對中央存儲庫的依賴。 咱們須要設置以下模塊來啓動它。
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.11</artifactId>
<version>${spark.version}</version>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-mllib_2.11</artifactId>
<version>${spark.version}</version>
</dependency>
準備數據集
如今,在準備開發以前,咱們須要構建有效的數據集。在本文的案例中,咱們嘗試創建一個基於銷售訂單歷史的樣本創建銷售線索預測模型。
如下是兩個數據集的樣本記錄。
銷售訂單:
用戶名 |
用戶名 |
產品編號 |
產品名稱 |
購買率 |
數量 |
金額 |
1 |
User 1 |
1 |
產品1 |
10 |
5 |
50 |
1 |
User 1 |
2 |
產品2 |
20 |
10 |
200 |
1 |
User 1 |
3 |
產品3 |
10 |
15 |
150 |
2 |
User 2 |
1 |
產品1 |
10 |
5 |
50 |
2 |
User 2 |
2 |
產品2 |
20 |
20 |
400 |
2 |
User 2 |
4 |
產品4 |
10 |
15 |
150 |
銷售線索記錄:
用戶編號 |
用戶名 |
產品編號 |
產品名稱 |
1 |
User 1 |
4 |
Product 4 |
1 |
User 1 |
5 |
Product 5 |
2 |
User 2 |
3 |
Product 3 |
2 |
User 2 |
6 |
Product 6 |
咱們的目標是根據過去的訂單歷史來預測或推薦相關的產品(商品)。
在上面的表格中,咱們能夠看到用戶1和用戶2都訂購了產品1和產品2; 另外,他們還各自單獨訂購了一件產品。
如今,咱們預測用戶對替代產品和一個新產品的興趣。
技術實現
第一步
調入訓練模型,而後使用JavaRDD API將其轉換爲評價模式。
JavaRDD < String > salesOrdersFile = sc.textFile("target/classes/data/sales_orders.csv");
// Map file to Ratings(user, item, rating) tuples
JavaRDD < Rating > ratings = salesOrdersFile.map(new Function < String, Rating > () {
public Rating call(String order) {
String data[] = order.split(",");
returnnewRating(Integer.parseInt(data[userIdIndex]),Integer.parseInt(data[productIdIndex]),Double.parseDouble(data[ratingIndex]));
}
});
第二步
下一步是使用ALS算法訓練矩陣分解模型。
MatrixFactorizationModel model =ALS.train(JavaRDD.toRDD(ratings), rank, numIterations);
第三步
如今,咱們加載銷售主文件並轉換爲元組格式。
// file format - user, product
JavaRDD < String > salesLeadsFile = sc.textFile("target/classes/data/sales_leads.csv");
// Create user-product tuples from leads
JavaRDD < Tuple2 < Object, Object >> userProducts = salesLeadsFile.map(newFunction < String, Tuple2 < Object, Object>> () {
public Tuple2 < Object, Object > call(String lead) {
String data[] = lead.split(",");
returnnew Tuple2 < Object, Object > (Integer.parseInt(data[userIdIndex]),Integer.parseInt(data[productIdIndex]));
}
});
第四步
最後,咱們能夠用一個簡單的API來預測將來的等級。
// Predict the ratings of the products not rated by user
JavaRDD<Rating> recomondations = model.predict(userProducts.rdd()).toJavaRDD().distinct();
第五步
可使用基本流水線操做對數據輸出進行排序:
// Sort the recommendations by rating in descending order
recomondations = recomondations.sortBy(new Function < Rating, Double > () {
@Override
publicDouble call(Rating v1) throws Exception {
return v1.rating();
}
}, false, 1);
第六步
如今,你可使用基礎JavaRDD API來顯示最終結果。
// Print the recommendations .
recomondations.foreach(new VoidFunction < Rating > () {
@Override
publicvoid call(Rating rating) throws Exception {
String str = "User : " + rating.user() + // " Product : " + rating.product() + // " Rating : " + rating.rating();
System.out.println(str);
}
});
輸出結果以下:
User : 2 Product : 3 Rating : 54.54927015541634
User : 1 Product : 4 Rating : 49.93948224984236
結論
以上Spark輸出的建議爲:User 2想買Product 3,而User 1會購買Product 4。也就是說不建議咱們推薦新產品,由於它們不符合過去任何類似性的標準。
學習愉快!