2016-08-30 5 views
0

私はSpark MLib ALSを使用しており、trainImplicit()インターフェイスを使用して、暗黙の設定としてユーザが購入したアイテムの番号を入力しようとしています。私は私のモデルを検証する方法を知らない。私の入力はドメイン[1、inf]にありますが、出力予測は(0,1)の浮動小数点のようです。Spark MLib ALSの入出力ドメイン

コードの通常の種類:

from pyspark.mllib.recommendation import ALS, MatrixFactorizationModel, Rating 
from pyspark.sql import HiveContext 
from pyspark import SparkContext 

sc = SparkContext(appName="Quantity Prediction Model") 
hive = HiveContext(sc) 

d = hive.sql("select o.user_id as user, l.product_id as product, sum(l.quantity) as qty from order_line l join order_order o ON l.order_id = o.id group by o.user_id, l.product_id") 
d.write.save('user_product_qty') 

ratings = d.rdd.map(tuple) 
testdata = ratings.map(lambda t: (t[0], t[1])) 

for rank in (4, 8, 12): 
    model = ALS.trainImplicit(ratings, rank, 10, alpha=0.01) 

    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) 

    # Error is pretty bad because output raitings aren't in the same domain as quantity 
    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("Rank: {} MSE: {}".format(rank, MSE)) 

エクストラクレジット:train()を使用する場合は、入力/出力ドメインは何ですか? 「格付け」は5ポイントスケールになると予想されますか?これはどこにも書かれていません。

答えて

0

RMSEは、暗黙的なALSの理想的な基準ではありません(元の論文は、より精巧な評価手法を提案しています)。ただし、入力評価を(-1; 1)にマッピングすると、RMSEを適用して暗黙のALSトレーニング結果を評価することもできます。

詳しくは、https://github.com/apache/spark/pull/597を参照してください。

// RMSE 
logger.info(s"Calculating RMSE on ${testingSet.count()} ratings") 
def groupRatings(rs: RDD[MLlibRating]): RDD[((Int, Int), Double)] = 
    rs.map { r => ((r.user, r.product), r.rating) } 

// When using implicit ALS we should treat actual and predicted 
// ratings as confidence levels. See also apache/spark#597. 
// 
// Predicted ratings are clamped to [0;1] 
def clampPredicted(r: Double): Double = 
    math.max(math.min(r, 1.0), 0.0) 

def clampActual(r: Double): Double = if (r > 0.0) 1.0 else 0.0 

def sqr(x: Double): Double = x * x 

val ratingSquaredErrors = 
    groupRatings(alsModel.predict(testingSet.map { r => (r.user, r.product) })) 
    .join(groupRatings(testingSet)) 
    .map { case (_, (predictedRating, actualRating)) => 
     sqr(clampPredicted(predictedRating) - clampActual(actualRating)) } 
val rmse = sqrt(ratingSquaredErrors.mean()) 
logger.info(s"RMSE: ${rmse}") 

最後に、いくつかのコードは、あなたが始めるために(スパークからALSのためMovieLens例でinpsired)