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阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容