Spark ALSアルゴリズムの推奨結果は同じですか?

7034 ワード

Spark ALSアルゴリズムの実験を行ったところ,モデルはすべてのユーザに対して推奨結果が同じであること,すなわち,すべてのユーザに対してモデリングしたモデルは推奨項目が同じであり,スコアに比較的小さな差があることが分かった.以下は3つの部分に分けて分析を行い、それぞれ実験過程と結果の説明、ALSアルゴリズムの原理、問題の分析と解決である.

実験過程及び結果


このセクションの参照先:https://databricks-training.s3.amazonaws.com/movie-recommendation-with-mllib.html(中には2つの部分に問題がありますが、以下に説明しますが、私の理解が間違っているかもしれません).1. 
HDFSにデータをアップロードするにはratingsをアップロードする必要があります.datファイルおよびmovies.Dataファイル、アップロード後のデータは下図の通りです.
2.Spark shellを開いてSpark ALSアルゴリズム呼び出しを行う;
3.映画情報データ及び採点データをロードし、そのコードは以下の通りである.
//       
sc.setLogLevel(“WARN”)
//       
import org.apache.spark.mllib.recommendation._

//   movies    map
val movies = sc.textFile("/user/root/als/movies.dat").map{line => val fields = line.split("::") ; (fields(0).toInt,fields(1))}.collect.toMap

//       
val ratings = sc.textFile("/user/root/als/ratings.dat").map{line => val fields = line.split("::");val rating = Rating(fields(0).toInt,fields(1).toInt,fields(2).toDouble);val timestamp = fields(3).toLong %10; (timestamp,rating)}

//       
println(ratings.count)
println(ratings.map(_._2.user).distinct.count)
println(ratings.map(_._2.product).distinct.count)

4.トレーニングセットとテストセットにデータを分割し、そのコードは以下の通りである.
//     
val training = ratings.filter(x=>x._1<6).values.cache()

//     
val test = ratings.filter(x=>x._1>=6).values.cache()

training.count
test.count

5.パラメータを設定し、モデリングを行います.そのコードは以下の通りです.
val rank = 10
 val lambda = 10.0
 val iter = 20
val model = ALS.train(training,rank,iter,lambda)

6.平均二乗誤差関数を作成し、テストデータセットに対して平均二乗誤差根を求め、そのコードは以下の通りである.
//          
import org.apache.spark.rdd.RDD

def computeRMSE(model:MatrixFactorizationModel, data:RDD[Rating]): Double = {
val usersProducts = data.map(x=>(x.user,x.product))
val ratingsAndPredictions = data.map{case Rating(user,product,rating)=>((user,product),rating)}.join(model.predict(usersProducts).map{case Rating(user,product,rating)=>((user,product),rating)}).values ; math.sqrt(ratingsAndPredictions.map(x=>(x._1-x._2)*(x._1-x._2)).mean())}

//      ,       
 val testRMSE = computeRMSE(model,test)
で得られた平均二乗誤差は、
7.あるユーザーの推薦映画を予測し、出力をフォーマットする.そのコードは以下の通りである.
val userid = 1
//   userid            
 val user1RatedMovieIds = ratings.filter(_._2.user==userid).map(_._2.product).collect.toSeq
//       userid          
val cands = sc.parallelize(movies.keys.filter(!user1RatedMovieIds.contains(_)).toSeq)
//                 ,           ,  10
val recommendations = model.predict(cands.map((userid,_))).collect.sortBy(- _.rating).take(10)
 var i =1
println(“  ”+userid+”      :”)
 recommendations.foreach{rec => println("%2d".format(i)+": "+movies(rec.product)+", predictRating: "+rec.rating);i+=1}

8.上記のコード呼び出しにより、推奨結果は以下の通りである.
9.7ステップ目のuseridを2,3に修正し、その推奨結果が同じであることを見たが、予測スコアが異なるだけで、これは問題のような問題である.
最後に、Spark alsの2つの参照エラー:
パラメータは、ウェブサイトの値(iter=20、lambda=10.0、rank=10)のように設定され、そのテストデータセットで得られる平均二乗誤差は0.8程度ではないため、そのパラメータ値はこのように設定されていないに違いない.
推薦を行う場合、設定したユーザIDは0となります.一つは、元のデータにはこのidのデータがありません.二つ目は、原文では、そのユーザ(すなわち、ユーザidが0のユーザ)が見た映画のスコアを設定してから推奨することができると述べているが、これは新しいユーザ推奨に等しいが、Spark alsアルゴリズムであれば、そのユーザ特徴ベクトルを計算して推奨する必要があり、これは原文では体現されていない.したがって,ユーザ0に対する推薦には問題がある.
また、Spark ALSの新しいユーザーに対する推奨構想は以下の通りである.
新しいユーザ0スコアベクトルが得られる.
平均二乗誤差関数を設定します.
ランダムな新しいユーザ0特徴ベクトル(rank*1のベクトル);
勾配降下法を用いて特徴ベクトルを更新し、最適特徴ベクトルを得る.
最適特徴ベクトルおよびすべての映画の特徴ベクトルを用いて、各映画の予測スコアを得、スコアの最高に基づいてtop推奨を行う.

ALSアルゴリズムの原理


上の問題を分析する前に、まずALSアルゴリズムの原理を理解して、ここは大体分析して、もしこのアルゴリズムを深く理解したいならば、自分で関連資料を探して、理解してください.
注意:映画の採点は最高5点、最低1点です.
上記の表に示すように、データセットは全部で5つの映画、4人のユーザーがあり、この4人のユーザーは5つの映画の中のいくつかの映画を見たことがあり、採点したことがあります.例えば、トムは「釜山行」を5点、「潜伏3」を1点、しかし「招魂2」を見たことがないので、採点を表示していません.
今、もし私たちが映画に2つのラベルを定義して、例えば「動作」、「恐怖」を定義して、すでに映画評論家などの人が私たちに各映画にこの2つのラベルに基づいて打ちすぎたとしたら、次のようなデータがあります.
上記のスコアに基づいて、このようなカラムベクトルを構築できればΘ,次の式を満たします.
では、上記のスペース部分の数値を予測できます(4,5,4,1の間にスペースがあることに注意してください).もちろん、上はトムユーザーにとって、Kate、John、Fansyに対してこのような列ベクトルを得ることができれば、すべてのユーザーに対して次の2次元マトリクスを得ることができます.
ここで、ユーザTomを表す特徴値は、他のユーザがこれに類推する.だから、ここでは、ユーザートムを完全に代表することができ、ユーザーFansyを完全に代表することができると理解することができます.
注意:ここで説明する必要があるのは、不完全なユーザーの映画採点リストや映画のラベル採点に基づいて、一定の誤差範囲内で推定できることです.Θマトリックス.
では、実は私たちはすでにこのアルゴリズムを完成しました.でも、何か違うところがあるみたい?映画評論家のこれらの映画に対する評価は完全に一致していますか?映画評論家はすべての映画を見終わって、これらの映画にラベルを描いて、採点することができますか?これは難しい任務だと想像できます(もちろん、時間があれば完成できます).どうすればいいの?
1つの自然な考え方は,ランダムな映画ラベルスコア(映画の特徴行列として理解できる)を求め,次いで求めることである.Θ行列(ユーザ特徴行列として理解できる).もちろん、この時は大きな誤差があるので、私たちが導いたものに基づいてΘマトリクスを返し、映画の特徴マトリクスを反転します.これを繰り返すことで,我々が予測した映画スコアと実際の映画スコア(ユーザが評価した映画スコア)のグローバル平均二乗誤差が一定の閾値内にあることを保証できる.このとき,アルゴリズムモデリングが完了し,アルゴリズムモデルのパラメータ:映画的特徴行列とユーザ特徴行列(本例では2次元であり,これもこのアルゴリズムのパラメータの1つであるrank)が得られたと言える.次に、この2つのマトリクスに基づいて、ユーザがまだ採点されていない映画について採点予測を行い、ユーザに推奨できる映画を得ることができる(予測採点の大きさに応じて採点top 10を取り出すことができる).

問題の分析と解決


問題の分析:


この問題は次の2つの側面から見ることができます.
テストセットに対して平均平方根誤差を求めると,得られた値は3.7程度であり,この値は実は比較的大きい(もちろん,この「大きい」も一定の経験が必要である),これは我々が構築したモデルに問題があることを一方的に説明することができる(見えない場合は,以下の観点から考えることもできる).
最も直感的な結果,モデルを用いてすべてのユーザを推薦したところ,基本的にすべてのユーザが推薦結果(すなわち映画)は同じであるが,映画の予測スコアが異なるだけであることが分かった.また、すべての予測の採点は比較的小さいので、よく見ると、基本的には0に近いことがわかります.
もちろん、この問題も別の角度から分析することができます.予測スコアが基本的に0に近い場合、ユーザ特徴ベクトル、プロジェクト特徴ベクトルも0に近いのではないでしょうか.どう思う?
モデルを取得した後、次の方法でユーザーまたは映画のフィーチャーベクトルを表示できます.コードは次のとおりです.
見た結果も,確かにユーザ特徴ベクトルやプロジェクト特徴ベクトルにかかわらず,その値は非常に0に近いことは間違いなく問題があり,一般に−1〜1の間にある小数であるが,0に近い数ではないに違いない.したがって、Spark ALSアルゴリズムを使用すると、このアルゴリズムの優劣をどのように評価するかは、このいくつかの面から分析することができます(もちろん、精度やリコール率を使用して評価することもできます).

問題解決:


問題の解決は簡単で、1行のコードで解決できます.
val model = ALS.train(trainging,10,20,0.01);
すなわちlambdaの値を0.01に変更すればよい.修正が完了したら、上で分析した2つの問題を見てみましょう.
1.テストデータセット平均二乗誤差:
2.モデルのユーザ特徴ベクトル及びプロジェクト特徴ベクトル及び最後の推奨結果
ユーザ1,2,3に対して、その推奨結果は以下の通りである.
以上の結果から,各ユーザが推奨する映画が異なるだけでなく,その予測スコアも0に近いわけではないことが分かる.また,そのテストデータセットの誤差は0.9にすぎず,以前の3.8と何倍も異なる.
それはどのようにしてこのように設定すると思いますか?アルゴリズムを理解した上でこのパラメータを設定することができます.
サイクル数iterは、この設定が大きいほど正確であるに違いないが、設定が大きいほど時間がかかることを意味する.
rank、特徴ベクトル緯度、この設定は見なければなりません.小さすぎるとフィットが足りなくなり、誤差が大きくなります.設定が大きいと、モデルの大汎化能力が低下します.だから自分で1度把握する必要があります.一般的には10~100でもいいです.
Lambdaもrankと同じで、設定が大きければオーバーフィットの問題を防止することができ、設定が小さければ、実際には直接0に設定すると理解でき、オーバーフィットを防止する機能はありません.どのように設定しますか?0.0001、0.0003、0.001、0.003、0.01、0.03、0.1、0.3、1、3、10のように毎回約3倍の設定で、どの値が効果的かを大まかに見てから、その比較的良い値(例えば0.01)の前後にもう一つの範囲を設定することができます.例えば(0.003、0.3)の間に、間隔設定の小さな点、すなわち0.003、0.005、0.007、0.009、0.011、、、、.もちろん、機械性がよく、時間が十分であれば、0から100まで直接設定することができ、間隔が小さく、パラメータのセットを試してみることもできます.

まとめ


Spark MLlibのアルゴリズム学習では、まず、その実行結果が自分の予想と同じかどうかを確認するために、インスタンスを使用することができます.
このアルゴリズムのアルゴリズムの原理を大体理解して、どのようにパラメータを調節するかを知って、1つのパラメータの大体の範囲を求めて、それからプログラミングして最適な1組のパラメータ値を求めることを実現します;
実践に着手する
分かち合う
着実に
転載はblogアドレスを明記してください:http://blog.csdn.net/fansy1990