Swing算法原理比较简单,是阿里早期使用到的一种召回算法,在阿里多个业务被验证过非常有效的一种召回方式,它认为 user-item-user 的结构比 itemCF 的单边结构更稳定。

Swing指的是秋千,例如用户 u uu 和用户 v vv ,都购买过同一件商品i ii,则三者之间会构成一个类似秋千的关系图。若用户 u 和用户 v 之间除了购买过 i 外,还购买过商品 j ,则认为两件商品是具有某种程度上的相似的。

也就是说,商品与商品之间的相似关系,是通过用户关系来传递的。为了衡量物品 i 和 j j的相似性,考察都购买了物品 i 和 j 的用户 u和用户 v , 如果这两个用户共同购买的物品越少,则物品 i和 j 的相似性越高。

Swing算法的表达式如下:

swing python 实现:

# -*- coding: utf-8 -*-"""Author  : ThinkgamerFile    : Swing.pySoftware: PyCharmDesc    : 基于movie lens数据集实现Swing算法
"""import pandas as pd
from itertools import combinations
import json
import osalpha = 0.5
top_k = 20def load_data(train_path, test_path):train_data = pd.read_csv(train_path, sep="\t", engine="python", names=["userid", "movieid", "rate", "event_timestamp"])test_data = pd.read_csv(test_path, sep="\t", engine="python", names=["userid", "movieid", "rate", "event_timestamp"])print(train_data.head(5))print(test_data.head(5))return train_data, test_datadef get_uitems_iusers(train):u_items = dict()i_users = dict()for index, row in train.iterrows():u_items.setdefault(row["userid"], set())i_users.setdefault(row["movieid"], set())u_items[row["userid"]].add(row["movieid"])i_users[row["movieid"]].add(row["userid"])print("使用的用户个数为:{}".format(len(u_items)))print("使用的item个数为:{}".format(len(i_users)))return u_items, i_usersdef cal_similarity(u_items, i_users):item_pairs = list(combinations(i_users.keys(), 2))print("item pairs length:{}".format(len(item_pairs))) # 1410360item_sim_dict = dict()cnt = 0for (i, j) in item_pairs:cnt += 1print(cnt)user_pairs = list(combinations(i_users[i] & i_users[j], 2))result = 0.0for (u, v) in user_pairs:result += 1 / (alpha + list(u_items[u] & u_items[v]).__len__())item_sim_dict.setdefault(i, dict())item_sim_dict[i][j] = result# print(item_sim_dict[i][j])return item_sim_dictdef save_item_sims(item_sim_dict, path):new_item_sim_dict = dict()for item, sim_items in item_sim_dict.items():new_item_sim_dict.setdefault(item, dict())new_item_sim_dict[item] = dict(sorted(sim_items.items(), key = lambda k:k[1], reverse=True)[:top_k])json.dump(new_item_sim_dict, open(path, "w"))print("item 相似 item({})保存成功!".format(top_k))return new_item_sim_dictdef evaluate(item_sim_dict, test):# 可以参考《推荐系统开发实战》中的cf验证方式passif __name__ == "__main__":train_data_path = "../../data/ml-100k/ua.base"test_data_path = "../../data/ml-100k/ua.test"item_sim_save_path = "../../model/swing/item_sim_dict.json"train, test = load_data(train_data_path, test_data_path)if not os.path.exists(item_sim_save_path):u_items, i_users = get_uitems_iusers(train)item_sim_dict = cal_similarity(u_items, i_users)new_item_sim_dict = save_item_sims(item_sim_dict, item_sim_save_path)else:new_item_sim_dict = json.load(open(item_sim_save_path, "r"))evaluate(new_item_sim_dict, test)

————————————————

.Swing Spark实现
创建Swing类,其中的评估函数和predict函数这里并未提供,感兴趣的可以自己实现

/*** @ClassName: Swing* @Description: 实现Swing算法* @author: Thinkgamer**/class SwingModel(spark: SparkSession) extends Serializable{var alpha: Option[Double] = Option(0.0)var items: Option[ArrayBuffer[String]] = Option(new ArrayBuffer[String]())var userIntersectionMap: Option[Map[String, Map[String, Int]]] = Option(Map[String, Map[String, Int]]())/** @Description 给参数 alpha赋值* @Param double* @return cf.SwingModel**/def setAlpha(alpha: Double): SwingModel = {this.alpha = Option(alpha)this}/** @Description 给所有的item进行赋值* @Param [array]* @return cf.SwingModel**/def setAllItems(array: Array[String]): SwingModel = {this.items = Option(array.toBuffer.asInstanceOf[ArrayBuffer[String]])this}/** @Description 获取两两用户有行为的item交集个数* @Param [spark, data]* @return scala.collection.immutable.Map<java.lang.String,scala.collection.immutable.Map<java.lang.String,java.lang.Object>>**/def calUserRateItemIntersection(data: RDD[(String, String, Double)]): Map[String, Map[String, Int]] = {val rdd = data.map(l => (l._1, l._2)).groupByKey().map(l => (l._1, l._2.toSet))val map = (rdd cartesian rdd).map(l => (l._1._1, (l._2._1, (l._1._2 & l._2._2).toArray.length))).groupByKey().map(l => (l._1, l._2.toMap)).collectAsMap().toMapmap.take(10).foreach(println)map}def fit(data: RDD[(String, String, Double)]): RDD[(String, String, Double)]= {this.userIntersectionMap = Option(this.calUserRateItemIntersection(data))println(this.userIntersectionMap.take(10))val rdd = data.map(l => (l._2, l._1)).groupByKey().map(l => (l._1, l._2.toSet))val result: RDD[(String, String, Double)] = (rdd cartesian rdd).map(l => {val item1 = l._1._1val item2 = l._2._1val intersectionUsers = l._1._2 & l._2._2var score = 0.0for(u1 <- intersectionUsers){for(u2 <- intersectionUsers){score += 1.0 / (this.userIntersectionMap.get.get(u1).get(u2).toDouble + this.alpha.get)}}(item1, item2, score) // (item1, item2, swingsocre)})result}def evalute(test: RDD[(String, String, Double)]) = { }def predict(userid: String) = { }def predict(userids: Array[String]) = { }}

main函数调用

object Swing {def main(args: Array[String]): Unit = {val spark = SparkSession.builder().master("local[10]").appName("Swing").enableHiveSupport().getOrCreate()Logger.getRootLogger.setLevel(Level.WARN)val trainDataPath = "data/ml-100k/ua.base"val testDataPath = "data/ml-100k/ua.test"import spark.sqlContext.implicits._val train: RDD[(String, String, Double)] = spark.sparkContext.textFile(trainDataPath).map(_.split("\t")).map(l => (l(0), l(1), l(2).toDouble))val test: RDD[(String, String, Double)] = spark.sparkContext.textFile(testDataPath).map(_.split("\t")).map(l => (l(0), l(1), l(2).toDouble))val items: Array[String] = train.map(_._2).collect()val swing = new SwingModel(spark).setAlpha(1).setAllItems(items)val itemSims: RDD[(String, String, Double)] = swing.fit(train)swing.evalute(test)swing.predict("")swing.predict(Array("", ""))spark.close()}
}

转载
https://blog.csdn.net/Gamer_gyt/article/details/115678598

阿里手淘猜你喜欢Swing算法介绍相关推荐

  1. Spark推荐实战系列之Swing算法介绍、实现与在阿里飞猪的实战应用(附代码)

    1.Swing算法介绍 Swing算法原理比较简单,是阿里早期使用到的一种召回算法,在阿里多个业务被验证过非常有效的一种召回方式,它认为 user-item-user 的结构比 itemCF 的单边结 ...

  2. Swing算法介绍、实现与在阿里飞猪的实战应用

    本系列主要是基于Spark的推荐算法实战系列,本文为首篇,欢迎关注! 1.Swing算法介绍 Swing算法原理比较简单,是阿里早期使用到的一种召回算法,在阿里多个业务被验证过非常有效的一种召回方式, ...

  3. 【推荐实践】阿里飞猪“猜你喜欢”推荐排序实践

    导读:飞猪猜你喜欢排序模型由线性模型升级到端到端的深度模型,并进行了多个版本的迭代.本文分享模型迭代中的一些技术沉淀. 引言 俗话说有多少米,就下多大锅.在特征体系构建上,我们已经准备了很多米了,并且 ...

  4. 通过反编译的方式分析阿里手淘小蜜的实现方式

    为什么要分析手淘的小蜜 因为可能需要做一款类似的产品. 如何分析 反编译手淘 查看UI布局 分析步骤 1. 反编译手淘查看反编译后的源码分析实现框架 2. 反编译资源文件查看资源信息(没有得逞) 3. ...

  5. MySQL数据库:我的阿里手淘面试经历分享,爱了爱了

    前言 其实前几篇文章已经写了好多有关于Spring源码的文章,事实上,很多同学虽然一直在跟着阅读.学习这些Spring的源码教程,但是一直都很迷茫,这些Spring的源码学习,似乎只是为了面试吹逼用, ...

  6. 阿里手淘可伸缩布局方案amfe-flexible解决vue移动端适配问题

    前言: 由于viewport单位得到众多浏览器的兼容,lib-flexible这个过渡方案已经可以放弃使用,不管是现在的版本还是以前的版本,都存有一定的问题.建议大家开始使用viewport来替代此方 ...

  7. 2023电商运营关于淘宝猜你喜欢玩法

    那么在这个大数据推送内容呈现出"千人千面"的情况下,我们要怎样才能出现在我们的潜在客户手机中的"猜你喜欢"这类免费推荐板块里,成为了作为淘宝卖家最关心的事情. ...

  8. 【艾特淘】如何才能入池淘宝“猜你喜欢”?

    据大数据统计,平均每个月有6.34亿人在淘宝上购物,无数男男女女端着手机一页一页地刷着这个淘宝个性化推荐的板块,希望淘到点好东西.这是一群很难搞定的消费者,心思多变又经常漫无目的.一个刚开启健身生活的 ...

  9. 弘辽科技:猜你喜欢要怎么样入池呢?

    弘辽科技:猜你喜欢要怎么样入池呢 据大数据统计,平均每个月有6.34亿人在淘宝上购物,无数男男女女端着手机一页一页地刷着这个淘宝个性化推荐的板块,希望淘到点好东西. 这是一群很难搞定的消费者--心思多 ...

最新文章

  1. JavaScript 为什么要有 Symbol 类型?
  2. linux下的arm仿真,使用QEMU仿真ARM Linux系统
  3. boost::function模块实现operator()的测试程序
  4. [Swift]最强UIButton解析 | #selector()绑定点击事件
  5. 移除Win10资源管理器中OneDrive图标
  6. 深入V8引擎-写在前面
  7. 小米路由器刷 linux,小米路由器刷入Padavan系统
  8. (转)74系列芯片使用汇总
  9. 如何破解域管理员密码
  10. 在python中安装包出现Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None))
  11. 有一个包含 10 亿个搜索关键词的日志文件,如何快速获取到 Top 10 最热门的搜索关键词呢?
  12. mysql data seek_mysql_data_seek函数详解
  13. Oracle 12C新特性总结
  14. 解决VMware虚拟机字体模糊的办法
  15. wifi 联想小新_WiFi 6锐龙5一个都不能少 小新Pro 13详细配置曝光
  16. el-transfer 用法
  17. 定语从句和同位语重句的区别
  18. Android通话录音流程
  19. 【论文笔记】标准正交基和投影在分布式控制中的应用
  20. 【ZZULIOJ】1012: 求绝对值

热门文章

  1. UGUI Button在点击后停留在Highlighted状态的Bug
  2. C# VS2017运行极光官网V1.1.0Deom
  3. 均衡发展计算机室一机一册,义务教育均衡发展实验室标准.doc
  4. HBuilder X 提示“浏览器运行尚不支持此种类型文件”
  5. 多线程编程 - PHP 实现
  6. 清北复交人浙南,都有哪些CS院校推荐?
  7. 【京东API】京东app获得JD商品详情原数据接口
  8. Linux·C语言高级编程·attribute和section详解
  9. 树莓派python手势识别控制_Raspberry Pi和手势传感器控制LED
  10. 2018俄罗斯世界杯冷门之夜!卫冕冠军德国0-1不敌墨西哥遭开门黑