基于 Apache PredictionIO 构建 Tapster 漫画推荐应用:Tinder 式“点赞/点踩“实时推荐的完整实战 人工智能机器学习后端模型推理服务大数据【免费下载链接】predictionioPredictionIO, a machine learning server for developers and ML engineers.项目地址https://gitcode.com/gh_mirrors/pre/predictionio点击查看免费下载本教程完整复现 PredictionIO 官方归档的 Tapster 漫画推荐 Demo一个基于 Ruby on Rails 构建、模仿 Tinder 交互的 Web 应用它根据用户对漫画剧集Episode的实时点赞/点踩行为通过 Apache PredictionIO 的 Similar Product相似物品引擎模板实时推荐下一部漫画。读完本文你将掌握从数据整理、PredictionIO 安装、引擎模板改造将默认 view 事件切换为 like 事件、批量导入 19 万条互动数据到训练部署、前后端联调jQuery Rails PredictionIO EngineClient的端到端实战方案并深入理解底层 ALS 协同过滤与共现推荐Co-occurrence的实现原理。应用背景与推荐思路Tapster 的目标是打造一个Tinder 式的漫画推荐应用用户在界面上逐张浏览漫画剧集向左/向右滑动或点击表达喜欢或不喜欢系统根据本会话内的所有点赞与点踩记录实时推荐下一条漫画。推荐引擎选用 Apache PredictionIO 的Similar Product Template相似产品模板它在仓库中的快速上手文档见 docs/manual/source/templates/similarproduct/quickstart.html.md.erb。该模板非常适合基于用户即时行为做推荐尤其适合新用户或历史行为很少的用户——推荐依据不是用户画像而是用户最近喜欢的物品的相似物。模板底层使用 Spark MLlib 的Alternating Least SquaresALS隐式反馈推荐算法这是一种经典的协同过滤Collaborative FilteringCF算法。协同过滤的核心思想是把用户-物品的互动关系建模为一个矩阵通过少量潜在因子latent factor来描述用户与物品从而填补矩阵中的缺失项即预测用户可能喜欢的物品。通俗地说它的逻辑就是喜欢这部漫画的人也喜欢这些漫画。数据集说明Tapster 的数据源自 Tapastic漫画连载平台仓库中未附带原始数据文件但数据文件的格式与规模如下剧集列表episode_list.csv1000 行字段episodeId | episodeTitle | episodeCategories | episodeUrl | episodeImageUrls每一行代表一部漫画剧集Episode即一条连环漫画 strip其中episodeCategories将被导入 PredictionIO 作为物品的categories属性供引擎在查询时做分类过滤。用户点赞列表user_list.csv192,587 行字段userId | episodeId | likedTimestamp每一行代表一个用户对某个剧集的赞事件这是训练推荐模型的核心反馈数据。整个教程分为四大步骤Demo 应用搭建Rails 应用 本地数据库Apache PredictionIO 安装与初始化将数据导入数据库与 PredictionIO Event Server将 Demo 应用与 PredictionIO 集成记录实时事件 查询推荐第一步搭建 Tapster Demo 应用Demo 应用本身是一个 Rails 项目克隆后通过 Bundler 安装依赖$ git clone https://github.com/PredictionIO/Demo-Tapster.git $ cd Demo-Tapster $ bundle install随后编辑config/database.yml以匹配本地数据库设置模板已为 PostgreSQL、MySQL、SQLite 提供合理的默认配置然后创建并迁移数据库$ rake db:create $ rake db:migrate此时应用已就绪但数据库为空。接下来导入剧集数据$ rake import:episodes该任务脚本非常简单逐行遍历 CSV 文件为每行在本地数据库创建一个 Episode 记录。执行rails server后浏览器访问 http://localhost:3000 即可看到应用界面第二步安装 Apache PredictionIO 并创建应用安装 PredictionIO按照官方安装指南安装 Apache PredictionIO或者直接运行官方一键安装脚本。安装完成后可通过pio status随时检查服务状态。创建新 App在 PredictionIO 中为 Tapster 创建一个新应用$ pio app new tapster命令执行后会输出该应用的App ID和Access Key务必记录这两个值——App ID 将写入引擎配置文件Access Key 用于向 Event Server 写入事件提示如果忘记 Access Key随时可以运行$ pio app list重新查看。第三步基于 Similar Product 模板搭建引擎克隆引擎模板进入 PredictionIO 安装目录克隆 Similar Product 模板作为引擎工程$ cd PredictionIO $ git clone https://github.com/apache/predictionio-template-similar-product.git tapster-episode-similar修改 engine.json进入引擎目录编辑engine.json将datasource.params.appName或其中的 App ID 相关字段改为刚才创建的 tapster 应用 ID$ cd tapster-episode-similar $ nano engine.json $ cd ..该文件是 PredictionIO 引擎的装配清单声明了引擎工厂类、数据源、预处理器、算法列表与 Serving 组件。仓库中 examples/scala-parallel-similarproduct/multi-events-multi-algos/engine.json 是同类引擎配置的真实示例。改造模板将 view 事件改为 like 事件默认情况下Similar Product 模板读取的是view浏览事件。Tapster 需要根据用户的点赞行为做推荐因此要修改DataSource.scala中的readTraining()将事件名从view改为likeoverride def readTraining(sc: SparkContext): TrainingData { ... val viewEventsRDD: RDD[ViewEvent] eventsDb.find( appId dsp.appId, entityType Some(user), eventNames Some(List(like)), // MODIFIED // targetEntityType is optional field of an event. targetEntityType Some(Some(item)))(sc) // eventsDb.find() returns RDD[Event] .map { event val viewEvent try { event.event match { case like ViewEvent( // MODIFIED user event.entityId, item event.targetEntityId.get, t event.eventTime.getMillis) case _ throw new Exception(sUnexpected event ${event} is read.) } } catch { case e: Exception { logger.error(sCannot convert ${event} to ViewEvent. s Exception: ${e}.) throw e } } viewEvent } ... }从源码看这个改动的作用PEventStore.find()按entityType Some(user)、eventNames Some(List(like))、targetEntityType Some(Some(item))过滤事件只取用户 → 物品方向的 like 事件并将其转换为ViewEvent(user, item, t)结构。仓库中的 multi-events-multi-algos 版 DataSource 更进一步同时读取like与dislike两类事件并封装成带布尔标记的LikeEvent(user, item, t, like)展示了在单个推荐器里融合赞/踩事件的更进阶做法。编译引擎$ cd tapster-episode-similar $ pio build $ cd ..编译成功后引擎即完成注册可用于后续训练。第四步导入数据到 PredictionIO启动 Event Server一切就绪后启动事件服务器$ pio eventserver两点注意事项随时可用$ pio status检查 PredictionIO 各组件状态如果笔记本休眠可能需要手动重启内置 HBase本教程基于 hbase-0.98.6$ cd PredictionIO/venders/hbase-0.98.6/bin $ ./stop-hbase.sh $ ./start-hbase.sh执行导入脚本要导入的核心事件是Like 事件例如用户 X 喜欢剧集 Y。执行$ rake import:predictionio这个 Rake 脚本比 episodes 导入复杂它分为三个层次1. 连接 Event Serverclient PredictionIO::EventClient.new(ENV[PIO_ACCESS_KEY], ENV[PIO_EVENT_SERVER_URL], THREADS)需要设置环境变量PIO_ACCESS_KEY与PIO_EVENT_SERVER_URLEvent Server 默认地址为http://localhost:7070。这两个值可以写入应用根目录的.env文件Rails 每次运行时会自动加载。2. 注册用户与剧集脚本先遍历data/user_list.csv取出唯一的用户 ID 与剧集 ID 集合。先注册用户user_ids.each_with_index do |id, i| # Send unique user IDs to PredictionIO. client.aset_user(id) puts Sent user ID #{id} to PredictionIO. Action #{i 1} of #{user_count} end再为每个剧集发送$set事件把categories属性写入物品实体引擎做分类过滤时依赖该属性episode_ids.each_with_index do |id, i| # Load episode from database - we will need this to include the categories! episode Episode.where(episode_id: id).take if episode # Send unique episode IDs to PredictionIO. client.acreate_event( $set, item, id, properties: { categories: episode.categories } ) puts Sent episode ID #{id} to PredictionIO. Action #{i 1} of #{episode_count} else puts Episode ID #{id} not found in database! Skipping!.color(:red) end end3. 发送 like 事件最后再次遍历user_list.csv逐行发送 like 事件CSV.foreach(USER_LIST, headers: true) do |row| user_id row[0] # userId episode_id row[1] # episodeId # Send like to PredictionIO. client.acreate_event( like, user, user_id, { targetEntityType item, targetEntityId episode_id } ) puts Sent user ID #{user_id} liked episode ID #{episode_id} to PredictionIO. Action #{$INPUT_LINE_NUMBER} of #{line_count}. end注意acreate_event(like, user, user_id, { targetEntityType item, targetEntityId episode_id })生成的事件正是DataSource.readTraining()中PEventStore.find所要读取的user → item 方向的 like 事件两端字段一一对应。按教程所述整个脚本在普通笔记本上运行约需 4 分钟。导入完成后全部数据1000 个剧集、约 19.2 万条用户点赞记录即进入 PredictionIO 的存储层可供引擎训练使用第五步训练与部署引擎训练模型进入引擎目录执行训练$ cd tapster-episode-similar $ pio train -- --driver-memory 4g使用--driver-memory参数限制 PredictionIO 驱动端内存避免内存占用过高导致崩溃4g可根据机器配置上下调整。生产环境中还可以设置定时任务周期性重训引擎让模型持续吸收最新数据。训练背后发生了什么仓库中 multi-events-multi-algos 的 ALSAlgorithm 展示了模板算法实现——它先把用户/物品的字符串 ID 通过BiMap映射成整数索引将事件聚合成MLlibRating(userIndex, itemIndex, value)再调用ALS.trainImplicit(ratings, rank, iterations, lambda, blocks, alpha, seed)训练隐式反馈模型最终产出每个物品的潜在因子向量productFeatures。而 LikeAlgorithm 展示了 Tapster 这类赞/踩场景的更完整做法用reduceByKey保留每个用户-物品对的最新态度赞/踩并把 like 编码为1、dislike 编码为-1直接喂给ALS.trainImplicit作为隐式负反馈信号// keep the latest value if (t1 t2) v1 else v2 ... // With ALS.trainImplicit(), we can use negative value to indicate // nagative siginal (ie. dislike) val r if (like) 1 else -1 MLlibRating(u, i, r)部署模型训练完成后在tapster-episode-similar目录下部署$ pio deploy默认情况下引擎服务监听在 http://localhost:8000。此时环境已就绪Demo 应用有数据PredictionIO 有训练好的模型。接下来要做的是把两者连起来让应用实时记录点赞事件、并向引擎查询推荐。第六步Demo 应用与 PredictionIO 集成数据流总览应用端保持对每次赞/踩的记录每次点击后前端通过 jQuery 把当前的赞与踩数组一并 POST 给 Rails 服务器服务器再查询 PredictionIO得到一个相似剧集并回传给 jQuery 展示。完整数据流用户喜欢某个剧集Tapster 把 Like 事件发送到 PredictionIO Event Serverhttp://localhost:7070Tapster 以本会话内用户评价过的全部剧集赞 踩作为 Query 查询 PredictionIO 引擎http://localhost:8000PredictionIO 返回 1 个推荐剧集并展示给用户。JavaScript 侧核心代码位于app/assets/javascripts/application.js。文件大部分是点击事件处理、加载弹窗展示等 UI 逻辑最关键的是查询函数queryPIO——它把赞/踩数组序列化后 POST 给 Rails 的/episodes/query接口// Query the server for a comic based on previous likes. See episodes#query. queryPIO: function() { var _this this; // For closure. $.ajax({ url: /episodes/query, type: POST, data: { likes: JSON.stringify(_this.likes), dislikes: JSON.stringify(_this.dislikes), } }).done(function(data) { _this.setComic(data); }); }Rails 侧服务端逻辑集中在app/controllers/episodes_controller.rb的query动作def query # Create PredictionIO client. client PredictionIO::EngineClient.new(ENV[PIO_ENGINE_URL]) # Get posted likes and dislikes. likes ActiveSupport::JSON.decode(params[:likes]) dislikes ActiveSupport::JSON.decode(params[:dislikes]) if likes.empty? # We cant query PredictionIO with no likes so # we will return a random comic instead. episode random_episode render json: episode return end # Query PredictionIO. # Here we black list the disliked items so they are not shown again! response client.send_query(items: likes, blackList: dislikes, num: 1) # With a real application you would want to do some # better sanity checking of the response here! # Get ID of response. id response[itemScores][0][item] # Find episode in database. episode Episode.where(episode_id: id).take render json: episode end逐步拆解这段逻辑首行通过PredictionIO::EngineClient连接引擎需要设置PIO_ENGINE_URL同样写入.env文件默认值为http://localhost:8000解析浏览器 POST 上来的 JSON赞与踩数组边界处理如果用户还没有任何点赞无法向 PredictionIO 发起有效查询直接返回一个随机剧集有赞数据时构造查询{ items: likes, blackList: dislikes, num: 1 }——把喜欢的剧集作为相似性种子把点踩的剧集放进黑名单确保不再出现从响应的response[itemScores][0][item]取出推荐剧集 ID回数据库查出完整记录并以 JSON 渲染。Query 字段的源码依据send_query(items: ..., blackList: ..., num: 1)中的字段对应引擎Query数据结构。仓库 Engine.scala 定义了完整的Query(items, num, categories, categoryBlackList, whiteList, blackList)ALSAlgorithm.predict 中isCandidateItem的实现印证了 blackList 的过滤逻辑候选物品必须blackList.map(!_.contains(i)).getOrElse(true)同时自动丢弃查询中已有的物品!queryList.contains(i)。浏览器收到 JSON 响应后jQuery 会用新剧集替换当前漫画并隐藏加载提示——至此一个完整的实时点赞 → 实时推荐闭环就完成了。原理纵深相似推荐是如何算出来的ALS 隐式反馈与物品向量Similar Product 模板默认使用ALS.trainImplicit训练出物品 × 潜在因子矩阵productFeatures。查询时取查询物品的特征向量与全部候选物品的特征向量逐一计算余弦相似度并求和得分越高表示越相似最后取 Top-N。仓库 ALSAlgorithm.scala 中的cosine()正是这一相似度度量的实现private def cosine(v1: Array[Double], v2: Array[Double]): Double { ... d / (math.sqrt(n1) * math.sqrt(n2)) }共现推荐Co-occurrence模板还内置了一个更轻量的共现算法CooccurrenceAlgorithm.scala 直接统计同一用户互动过的物品对的出现次数——userItem.join(userItem)后过滤item1 item2去除重复对reduceByKey计数再对每个物品取共现次数最高的 Top-N。其推荐逻辑与喜欢 A 的人大多也喜欢 B的直觉完全一致非常适合 Tapster 这类行为数据量大、需要快速上手的场景。Serving多算法结果融合当引擎配置了多个算法时Serving 组件负责融合各算法结果。仓库 Serving.scala 展示了一种典型做法对每个算法返回的分数做z-score 标准化(score - mean) / stdDev再按物品 ID 分组求和排序取 Top-N。当query.num 1时则跳过标准化直接使用原始分数。这与 Tapster 单算法、单结果的场景相比展示了面向多算法生产环境的扩展路径。总结Tapster 教程演示了一条完整的交互式推荐应用落地路径Rails 应用负责交互与本地数据Apache PredictionIO 负责事件存储、模型训练与在线服务两者通过 REST/SDK 解耦。其核心设计值得复用用相似物品而非用户画像做推荐天然适配新用户与冷启动场景事件模型即数据模型$set写物品属性、like写互动信号DataSource 端用PEventStore.find精确取数改动一个事件名即可切换行为语义赞/踩双信号可进一步升级为隐式正负反馈1/-1仓库中 multi-events-multi-algos 的完整示例DataSource LikeAlgorithm Serving就是这一思路的现成参考。如果你不熟悉 RubyPredictionIO 官方还提供 Python、Java、PHP 等多语言 SDK且 Event Server 原生支持 JSON REST API完全可以用你擅长的语言复刻同样的架构。相关模板细节可继续阅读仓库内 Similar Product 快速上手文档 及其 DASE 组件详解。赞分享人工智能机器学习后端模型推理服务大数据【免费下载链接】predictionioPredictionIO, a machine learning server for developers and ML engineers.项目地址https://gitcode.com/gh_mirrors/pre/predictionio点击查看免费下载相关推荐用 Apache PredictionIO 构建 Tapster 漫画推荐应用Similar Product 模板完整实战用 Apache PredictionIO 构建 Tapster 漫画推荐应用Similar Product 模板完整实战 本文档 tapster.html机器学习后端大数据基于 Apache PredictionIO Similar Product 模板构建 Tapster 漫画推荐 Demo 实战指南基于 Apache PredictionIO Similar Product 模板构建 Tapster 漫画推荐 Demo 实战指南 本文是 Apache Pr机器学习后端推荐系统如何用res-downloader一键获取全网无水印视频3分钟快速上手指南如何用res downloader一键获取全网无水印视频3分钟快速上手指南 还在为下载视频时出现的水印烦恼吗想快速收集教学素材却苦于平台限制res dow桌面应用网络音视频上一篇跨平台视觉对比工具MegSpot专业图片视频分析的高效解决方案下一篇如何优雅地获取B站评论数据5个实用技巧告别403烦恼创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考