2021-02-12 關于以ALS為基礎的匹配算法學習

好久不寫技術文章了,以前寫了好多,發現都找不到了,不知道是不是某次ITeye的更新導致的,還是我自己喝多了刪除了。ALS(Alternating Least Squares)交替的最小二乘法,網絡上太多的文章去介紹了,同時,在電商領域也有非常多的實踐,根本不算是什么新鮮的玩意兒。本身就是利用和用戶的有效互動,然后通過內容(太喜歡內容這個詞了,包含了一切的含義,內容可以是具體的商品,可以是一篇討論性的文章,可以是一則廣告,可以是一段視頻;我們在商業環境下,把一切可以用來探知用戶興趣及與用戶產生互動的一切載體都稱之為內容,內容是我們了解用戶的開始,也是構建用戶體系完成用戶運營的根本。)ALS只是我們CF算法中的一種方式而已,沒有什么特別的。


image.png

上面這個公式,就是要找到用戶對隱藏特征的偏好與產品包含隱藏特征的程度的最優匹配結果。目標函數中U和V相互作用,先假設U的初始值U(0),這樣就將問題轉化成了一個最小二乘問題,可以根據U(0)可以計算出V(0),再根據V(0)計算出U(1),反復進行迭代,直到該函數收斂,

關于函數f(x)在點x0處的收斂定義。對于任意實數b>0,存在c>0,對任意x1,x2滿足0<|x1-x0|<c,0<|x2-x0|<c,有|f(x1)-f(x2)|<b。

其實就是是指會聚于一點,向某一值靠近。本身還是最小二乘法,一個利用線性方式解決問題的模式。
image.png

這張圖是我能找到的說的最明白的,也是為啥要求解函數E = |y1-y’1|+|y2-y’2|+...+|yn-y’n|的最小值的原因。
image.png
理解了最小二乘法,邏輯回歸一樣好理解了。畢竟不討論數學,可以在跟大家的面談分享中細聊。當然在我們正在開發的系統中,使用ALS,也是因為:
  • 簡單,算法簡單,實現簡單,團隊接受度高,學習曲線平緩(給團隊選技術的第一要務)
  • 因為與用戶之間可能是正反饋,可能負反饋,可能沒有反饋,所以會選
  • 前期開發時,對樣本量的要求沒有這么苛刻,當然需要架構師有對領域的深度認知,冷啟動過程幾乎沒有
    當然這需要感謝Spark MLlib的作用。我們要實現的場景非常簡單,就是給用戶發內容,看用戶點選路徑,收集用戶使用行為信息,并根據過往的同類型用戶的使用情況進行內容推薦。
    為了讓團隊能夠更有目標感,選用了以下基本的技術:
    HBase(存儲用戶的行為信息,商品標簽,用戶標簽), Kafka(消息隊列),Zookeeper做了HBase/Kafka的集群,Spark(計算引擎),Redis(匹配結果),Mysql(基本數據存儲,比如商品/用戶)

大概的模式就是這么簡單:


image.png

貼段代碼看看評分是如何工作的:

import org.apache.spark.ml.evaluation.RegressionEvaluator
import org.apache.spark.ml.recommendation.ALS

case class Rating(userId: Int, movieId: Int, rating: Float, timestamp: Long)
def parseRating(str: String): Rating = {
  val fields = str.split("::")
  assert(fields.size == 4)
  Rating(fields(0).toInt, fields(1).toInt, fields(2).toFloat, fields(3).toLong)
}

val ratings = spark.read.textFile("data/mllib/als/prd_sample.txt")
  .map(parseRating)
  .toDF()
val Array(training, test) = ratings.randomSplit(Array(0.9, 0.2))

// Build the recommendation model using ALS on the training data
val als = new ALS()
  .setMaxIter(5)
  .setRegParam(0.01)
  .setUserCol("userId")
  .setItemCol("prdId")
  .setRatingCol("rating")
val model = als.fit(training)

// Evaluate the model by computing the RMSE on the test data
// Note we set cold start strategy to 'drop' to ensure we don't get NaN evaluation metrics
model.setColdStartStrategy("drop")
val predictions = model.transform(test)

val evaluator = new RegressionEvaluator()
  .setMetricName("rmse")
  .setLabelCol("rating")
  .setPredictionCol("prediction")
val rmse = evaluator.evaluate(predictions)
println(s"Root-mean-square error = $rmse")

// Generate top 10 prd(whatever it is) for each user
val userRecs = model.recommendForAllUsers(10)
// Generate top 10 user recommendations for each prd
val prdRecs = model.recommendForAllItems(10)

// Generate top 10 prd recommendations for a specified set of users
val users = ratings.select(als.getUserCol).distinct().limit(3)
val userSubsetRecs = model.recommendForUserSubset(users, 10)
// Generate top 10 user recommendations for a specified set of prd
val prdlist = ratings.select(als.getItemCol).distinct().limit(3)
val prdSubSetRecs = model.recommendForItemSubset(prdlist, 10)

上文提到的關于隱式反饋的設置,只需要“setImplicitPrefs(true)”即可。如果針對具體的預測,可以按照如下去做:

val user_product = trainingRDD.map {
      case Rating(user, product, rate) =>
        (user, product)
    }
val predictions =
      alsModel.predict(user_product).map {
        case Rating(user, product, rate) =>
          ((user, product), rate)
      }

其中,ComputeService就是記錄了用戶的正負反饋(沒有反饋的相應的行為權重比負反饋還要低,因為被認為是根本不關注)。實際使用過程中,Redis中的所有匹配結果,都會記錄到我們的Hive中,因為很多的關鍵性指標都需要在Hive中進行存儲和計算,還是那句話,推薦算法早就已經有了,所有的數字化媒體或電商都在用,一點不新鮮,但是每周的針對推薦結果的復盤才讓這些工具更有價值。HBase二級索引支持不好我們有Phoenix,Spark對實時事件處理不了我們還有Flink,其實重點的工作落在了用戶的屬性,內容的屬性標簽的拆分上,內容可能標準化程度更高一些,但是人的個性化就太多了。由于涉及商業項目的具體設計和實現,在這里不寫這么多了;實際過程中以下兩個過程極為重要:

  • 召回階段:用些成本低、易實現、速度快的模型進行初步篩選;
  • 排序階段:用更全面的數據、更精細的特征、更復雜的模型進行精挑細選
    特別注意人工規則的植入,我們的ComputeService里面會放入人工規則的排序幫助作出更好的推薦判斷。

小結一下,ALS的使用過程,對訓練集合,特征值,迭代的參數設定及防過擬合參數都有要求(我們需要假設,假設是一切數據期望的前提,但是別使假設變得過度嚴格)。大年初一,還是祝大家新春快樂,萬事可期!

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,546評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,570評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,505評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,017評論 1 313
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,786評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,219評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,287評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,438評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,971評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,796評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,995評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,540評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,230評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,662評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,918評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,697評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,991評論 2 374

推薦閱讀更多精彩內容