尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

从0到1搭建个性化推荐系统:架构、召回、精排与冷启动全解析

从0到1搭建个性化推荐系统:架构、召回、精排与冷启动全解析 1. 从一个猜想的验证说起我第一次认真琢磨个性化推荐系统是因为一个特别朴素的问题我盯着购物App首页那排猜你喜欢看了十分钟发现它推的东西居然真的是我最近想买但还没搜过的。那一刻我意识到推荐系统不是简单的销量排行或者热门聚合能解释的它背后一定有一套完整的链路在运转。后来我自己动手搭建了一个完整的个性化推荐系统从数据采集、特征工程、召回、排序到线上部署和评估整条链路走下来踩了不少坑也把每个环节的底层逻辑摸了一遍。这篇就把我踩过的路和经验整理出来从全局架构讲起把每个核心环节的原理、代码、参数选择和避坑点都讲清楚最后附源码地址。这篇文章适合谁看如果你刚接触推荐系统想搞懂它到底怎么运作或者你已经在写业务代码想转岗算法方向但不知从哪下手再或者你正在为公司搭建一套推荐服务需要一个从0到1的闭环参考。无论哪种情况这篇应该能给你一个完整的、可落地的认知框架。2. 推荐系统的整体架构与设计思路2.1 经典的双链路结构我见过很多推荐系统的架构图画得花里胡哨但实际上核心就两条链路离线链路和在线链路。离线链路负责在后台批量计算产出候选集、特征和模型参数在线链路负责在用户请求到达的瞬间快速完成召回、排序和结果输出。打个生活化的比方离线链路就像一个提前备课的老师把所有可能考到的题目都提前做了一遍整理成题库和标准答案在线链路就是真正考试时的考生拿到题目后从题库快速调取答案、组织语言在规定时间内交卷。这两条链路的关系决定了系统设计的很多细节。比如离线计算结果需要同步到线上存储Redis、MySQL或者向量索引库同步的延迟决定了推荐结果的时效性——如果你是做新闻资讯的用户刚看完一条热点你还在推昨天的内容显然不合适。2.2 为什么召回和排序必须分开很多初学者会问一个问题为什么不把所有物品直接丢给一个模型打分排序我一开始也这么想直到自己动手算了一笔账。假设平台有10万件商品用户请求一次推荐我们需要从中选出50个展示出来。如果精排模型对每件商品都要算一次打分10万次计算模型再好也扛不住这个延迟。就算用批处理预先把所有用户对所有物品的分数都算好存储量也是天文数字——10万用户乘以10万商品那就是100亿个分数。所以必须分层召回阶段用轻量级方法从全量物品库中快速捞出几百到几千个可能感兴趣的候选精排阶段再用重模型对这几百个候选逐一精细打分排序取top。召回致力于不漏排序致力于更准各司其职。2.3 冷启动问题的前置考量在设计架构时就要想清楚冷启动怎么办。冷启动分三类用户冷启动新用户没有行为历史、物品冷启动新商品没有交互数据、系统冷启动刚上线没有数据积累。我当时定的策略是按阶段处理系统冷启动阶段先走热门榜和规则策略顶上同时提前导入一批人工标注的商品标签用户冷启动阶段采用注册时选偏好标签的方式先解决维度物品冷启动阶段利用商品本身的文本和图像特征做内容相似推荐。这些策略后面会细说。3. 数据层推荐系统的地基3.1 日志埋点与数据采集没有数据的推荐系统是无源之水。所以第一步是在App或Web端做行为埋点。我采集的行为数据包含以下这些字段我直接把我设计的日志格式表放出来字段名类型说明user_idstring用户唯一标识item_idstring物品唯一标识behavior_typestring行为类型曝光、点击、加购、下单scene_idstring场景标识首页猜你喜欢、详情页推荐等contextmap上下文信息网络环境、地理位置等devicestring设备信息ios/androidtslong行为发生时间戳曝光和点击是数据中最核心的两类。曝光代表系统推荐给用户看了点击代表用户真的感兴趣。很多团队的坑在于只统计点击不统计曝光——这会导致后续CTR点击率的计算没有分母模型完全没法训练。3.2 特征工程实战要点特征工程决定了模型效果的上限模型只是在逼近这个上限。我用的特征主要分三类用户特征用户ID、年龄、性别、地域、注册时长、近7天点击品类分布、消费能力分档。物品特征物品ID、标题文本向量、类目层级、价格档位、近30天点击率、好评率。上下文特征当前时间拆成小时、星期几、是否节假日、请求场景、用户所处城市。这里有个关键经验——统计类特征要做时间衰减。比如近7天点击品类分布不能简单统计总量而要按时间加权越近的行为权重越高。我当时用指数衰减函数权重等于exp(-age/half_life)half_life设为24小时这样昨天的点击比前天的更有价值。做特征的时候还有一个容易踩的坑——特征穿越。就是在预测时刻把未来信息用进去了。比如用当天全天的点击量去预测当天上午的推荐结果这就是穿越。正确做法是严格以预测时间为界只使用该时刻之前产生的数据。3.3 负样本的构造逻辑推荐系统训练样本需要正负两样。正样本容易理解——用户点击过的行为。负样本的构造就没那么直观了我见过不少新手直接拿曝光未点击当负样本这在初期可以但长期会有偏差。我实际用的方案是混合策略第一部分负样本曝光未点击常规负样本第二部分负样本全局随机采样未曝光的物品保证负样本覆盖整个物品空间为什么要加随机采样因为曝光未点击只能反映系统已经推荐过但用户不感兴趣的情况如果推荐系统本身质量很高曝光池里都是用户感兴趣的那负样本就全是矮子里拔将军的相对负样本模型会学不到真正的不喜欢到底是什么。加入随机样本让模型见过更广阔的物品分布。负采样时我还会做频控过滤用户行为超过一定频次比如1小时超过100次曝光的直接过滤掉避免机器人刷量破坏样本分布。4. 召回层从百万到千级的粗筛4.1 多路召回策略详解我搭建的系统用了四路召回协同过滤、双塔向量召回、热榜补充和规则召回。每一路都有存在的原因也都有各自的局限。协同过滤是经典方法分UserCF和ItemCF。UserCF的思路是和你相似的人喜欢什么就推给你ItemCF是你喜欢的物品的相似物品推荐给你。对于电商场景ItemCF更适用一些因为物品的相似关系比用户的相似关系更稳定。ItemCF的核心是计算物品间相似度我用的是余弦相似度# 核心代码物品协同过滤相似度计算 from collections import defaultdict import math def itemcf_similarity(user_items): :param user_items: dict, {user_id: set(item_id_list)} :return: item_sim_matrix: dict, {item_id: {item_id: sim_score}} item_users defaultdict(set) user_item_count defaultdict(int) # 建立物品到用户的倒排索引 for user, items in user_items.items(): for item in items: item_users[item].add(user) user_item_count[user] 1 # 计算物品间共现矩阵 co_occur defaultdict(dict) for item, users in item_users.items(): for user in users: for other_item in item_users[item]: if other_item item: continue co_occur[item][other_item] co_occur[item].get(other_item, 0) 1 # 余弦相似度惩罚热门物品 item_sim_matrix defaultdict(dict) for item, related_items in co_occur.items(): for related_item, co_count in related_items.items(): item_sim_matrix[item][related_item] co_count / \ math.sqrt(len(item_users[item]) * len(item_users[related_item])) return item_sim_matrix双塔召回是现在工业界的主流方案用两个神经网络分别把用户和物品映射到同一个向量空间内积作为相关度打分。用户侧输入用户特征物品侧输入物品特征最后用内积结果计算相似度。训练的时候用采样softmax损失——正样本是用户点击过的物品负样本从全局随机采样。双塔模型效果的几个关键点我后面在实操环节详细讲这里先记住一个原则双塔召回的效果70%取决于负样本采样策略20%取决于特征设计10%才是模型结构。4.2 向量检索的实现双塔模型产出的向量得能快速检索才能用于线上召回。最常用的方案是Faiss我用的是IVF倒排文件索引 PQ乘积量化的组合。IVF的基本思想是把向量空间聚类成n个簇检索时只找最近的几个簇在簇内做暴力搜索。PQ则是把高维向量分段压缩减少存储和计算量。Faiss关键参数配置import faiss dim 64 # 向量维度 nlist 100 # 聚类中心个数 nprobe 10 # 检索时查找的聚类中心个数 # 基于 IVF PQ 的索引 quantizer faiss.IndexFlatIP(dim) # 内积作为相似度度量 index faiss.IndexIVFPQ(quantizer, dim, nlist, 8, 8) # 8字节子编码 index.train(vectors) # 用训练集训练聚类中心 index.add(vectors) # 添加物品向量 index.nprobe nprobe # 检索时探索中心数 # 检索与 user_vector 最相似的 top 100 个物品 scores, indices index.search(user_vector, 100)这里有个需要调参的点nprobe太小会损失召回率太大则检索速度变慢我实践经验一般是总簇数100个时nprobe设为10~20都能接受要在准确率和速度之间取平衡。4.3 热门兜底与业务规则召回协同过滤和向量召回都依赖用户历史行为。新用户来了这两路基本抓瞎这时就得靠热门兜底。我当时的策略是计算全局过去7天的物品热度分——热度分等于点击量权重加收藏权重加下单权重按时间衰减取top200作为兜底池。不过纯粹的热门推荐体验很差所以我又加了规则召回新品必须给固定比例曝光、高毛利商品在部分场景加权、符合用户注册偏好标签的物品提前预留位置。规则虽朴素但在冷启动阶段意外的好用。4.4 多路召回的合并与去重各路召回都会吐出一个item列表合并时要做几件事去重、按路加权、过滤已曝光历史。我采用的合并算法是# 多路召回合并示例 def merge_recall_channels(recall_results, weights, filter_history, limit500): recall_results: dict, {channel_name: [item_id,...]} weights: dict, {channel_name: weight} merged_score defaultdict(float) for channel, items in recall_results.items(): w weights.get(channel, 1.0) for rank, item_id in enumerate(items): if item_id in filter_history: continue # 按排名加权排名越靠前权重越大 merged_score[item_id] w * (1.0 / (rank 1)) # 按加权分排序取top sorted_items sorted(merged_score.items(), keylambda x: x[1], reverseTrue) return [item_id for item_id, _ in sorted_items[:limit]]加权公式看着简单实际效果很依赖各路的权重配置。我当时的初始权重是向量召回1.0、ItemCF 0.8、热门0.3、规则0.5之后根据线上AB实验不断调整。5. 精排层CTR预估模型5.1 从逻辑回归到深度模型召回层给出几百个候选精排层要对它做精细打分。我用过逻辑回归也用过深度模型这里把两者对比讲一下。逻辑回归LR是推荐系统精排的入门模型所有特征做one-hot后丢进LR训练。好处是简单、可解释性强、训练快坏处是不具备特征交叉能力——用户性别和物品品类这种组合关系LR学不出来需要手工构造交叉特征。手工构造特征费时费力还不全面于是就有了FM因子分解机用隐向量的内积自动学习二阶特征交叉。到了深度学习时代Wide Deep模型是里程碑式的结构——Wide部分保留了LR的记忆能力Deep部分用MLP学习高阶特征交叉。我的精排模型就是在Wide Deep基础上改进的结构大致是输入层用户特征、物品特征、上下文特征拼接 ↓ Embedding层每个稀疏特征映射为低维稠密向量 ↓ 拼接层所有embedding拼接成一个大的向量 ↓ 全连接层三层MLP维度依次是256 → 128 → 64激活函数ReLU ↓ 输出层一个神经元sigmoid激活输出点击概率5.2 精排模型的核心特征组合精排阶段特征要比召回阶段丰富得多除了原始属性特征重点是构造交叉特征和序列特征。高频刚需的交叉特征我列一组用户ID × 物品ID记忆用户对特定物品的喜好用户年龄分档 × 物品类目年轻人和中老年偏好差异用户近7天点击类目 × 物品类目用户近期兴趣和候选物品的匹配度物品价格档 × 用户消费能力档价格匹配度序列特征也很关键——用户最近的点击序列隐含了当下兴趣。我的做法是把用户最近点击的50个物品的embedding平均池化拼接到模型输入中。虽然Transformer之类的注意力结构效果更好但对工程复杂度要求高均池化在初期完全够用。这里列一下我用的精排特征表方便你直接对照做特征类别具体特征示例用户基础性别、年龄段、会员等级男、25-30、V3用户统计近7天点击量、近30天下单金额日均点击32、月消费2000物品基础类目、价格档、上架天数数码、500-1000元、120天物品统计近7天点击率、好评率3.2%、98%交叉特征用户年龄段×物品类目25-30×数码上下文当前小时、星期几21:00、周六5.3 离线训练与评估精排模型离线训练时我用的损失函数是二分类交叉熵# AUC计算与损失函数 import tensorflow as tf def ctr_model(features, labels): # 网络结构此处省略outputs即是sigmoid输出 loss tf.reduce_mean( tf.keras.losses.binary_crossentropy(labels, outputs) ) return loss评估指标用得最多的是AUC——它表示随机抽一个正样本和负样本正样本得分比负样本高的概率。AUC范围在0.5到1之间0.5相当于乱猜0.8以上属于优秀水平。我当时的模型离线AUC做到0.82线上验证效果也基本一致。还有一个容易被忽略的细节——训练样本的时间切分。我按时间把数据集切成三段前7天训练第8天验证第9天测试。很多人直接随机切分这会导致模型在时间域上作弊——它见过测试期的物品分布线上表现就会比离线差很多。6. 在线服务与策略层6.1 架构与接口设计在线推荐服务我用Golang写了一个HTTP API核心流程几步接收请求带上用户ID和场景从Redis读用户实时特征从Faiss和缓存中取各路召回结果合并去重后喂给精排模型打分最后按分数排序返回top50。在线延迟当时做到了平均80ms预算在200ms以下。性能优化的关键有几点Faiss索引全部加载到内存不走网络IO特征拼接和模型推理都做池化复用避免重复初始化Redis缓存用户最近的行为序列避免每次请求都查数据库6.2 实时特征计算冷启动和兴趣漂移的基础是实时特征。用户刚点击了一件商品希望下一轮推荐立刻能看到变化。我的实现方案是点击消息进入流式管道我用的是Kafka加Flink实时更新用户在Redis里的近期行为序列和统计信息。最核心的实时特征是用户近1小时点击的物品类目分布和用户最近点击的item序列。这些特征的更新延迟控制在10秒以内。刚开始搭建时我用的轮询批处理延迟太长效果一直上不去后来改成流处理才解决。6.3 如何平衡相关性与多样性如果只按CTR排序用户会陷入信息茧房——推荐结果越来越同质化。我的做法是加入打散规则连续推荐中出现同一种二级类目的物品不超过2个同一商家的商品在整个列表中不超过1个展示列表中广告位固定比例不参与相关性排序。多样性打分用MMR最大边际相关性算法它平衡相关度和与已选列表的差异度# MMR多样性重排伪代码 def mmr_rerank(candidates, already_selected, lambda_param0.7): lambda_param 越大越注重相关性越小越注重多样性 remaining list(candidates) while len(already_selected) 50 and remaining: best_item None best_score -float(inf) for item in remaining: relevance item.ctr_score # 计算与已选列表的最大相似度 max_sim max([similarity(item, sel) for sel in already_selected]) \ if already_selected else 0 mmr_score lambda_param * relevance - (1 - lambda_param) * max_sim if mmr_score best_score: best_score mmr_score best_item item already_selected.append(best_item) remaining.remove(best_item) return already_selectedlambda_param我一般设在0.6到0.8之间值越大相关性越强越小多样性越好。这个参数值得花时间调直接影响用户体验。6.4 AB实验框架没有AB实验的推荐系统等于盲飞。我搭的AB实验框架核心逻辑很简单流量打上实验标记按用户ID哈希分桶控制组走旧策略实验组走新策略对比CTR、人均点击PV、下单转化率和人均GMV等指标。做AB实验有两条血的教训一实验最少要跑一周。因为用户行为有周期性只跑两天的话周末效应会把实验结论带偏。二埋点数据口径要严格统一。我说一个自己经历过的坑——控制组和实验组用了不同的页面埋点代码版本结果实验组CTR异常偏高排查了三天才发现问题白白浪费了实验周期。7. 冷启动细化策略7.1 用户冷启动的实操方案用户没行为时推荐系统完全靠猜。我的策略分几步走第一步注册引导选择至少3个兴趣标签。这步成本极低但收益很大能让推荐系统从一开始就不是完全瞎猜。第二步用标签匹配物品。把标签和物品类目做个映射表按映射关系推送该类目下的热门商品。看起来简单实际效果比纯热门push明显要好。第三步一有行为数据就立刻切换。当用户行为超过阈值所以我设为20次有效行为推荐主策略就从标签匹配切换到向量召回和协同过滤标签特征转为辅助信号。7.2 物品冷启动的破解方法新物品没有交互记录协同过滤和向量模型都用不上。解决思路是用物品的内容信息代替行为信息。我的做法是把新物品的图片特征用预训练的图像模型提取和文本特征用BERT提取标题描述向量平均池化组合成一个内容向量再和已有物品的embedding算相似度找到最相似的几个旧物品用旧物品的行为数据来预估新物品的点击率。这个方法实测可以将新物品的推荐效果从随机水平提高到接近老品平均水平的一半以上已经相当可观。7.3 冷启动策略的系统冷启动阶段系统刚上线时没有任何数据推荐算法无从谈起。这个阶段我建议直接手动配置策略热门榜、新品榜、人工精选榜三个榜单按比例混合推荐。同时在后台记录用户对这三个榜单的点击反馈积累一周左右的数据就可以开始训练第一版协同过滤模型了。系统冷启动阶段推荐算法的演进路径一般是规则策略 — 收集数据 — 协同过滤 — 双塔召回。不要试图一步到位机器学习模型必须有数据才能work。8. 完整源码结构我把整套推荐系统的源码打包放在了GitHub仓库结构清晰可以直接clone下来跑通。recommend-system/ ├── README.md # 项目说明包括环境和快速开始指南 ├── docs/ │ └── architecture.md # 系统架构设计文档 ├── data/ │ ├── sample_data.csv # 模拟行为样本数据 │ └── prepare_data.py # 数据预处理脚本 ├── feature/ │ ├── feature_engineer.py # 特征工程核心逻辑 │ ├── feature_config.py # 特征配置 │ └── user_profile.py # 用户画像构建 ├── recall/ │ ├── item_cf.py # 物品协同过滤召回 │ ├── user_cf.py # 用户协同过滤召回 │ ├── dssm_recall.py # 双塔向量召回 │ ├── hot_recall.py # 热门兜底召回 │ └── faiss_search.py # Faiss向量检索封装 ├── rank/ │ ├── feature_processor.py # 精排特征处理 │ ├── wide_deep_model.py # Wide Deep排序模型 │ ├── train.py # 模型训练脚本 │ └── evaluate.py # 离线评估脚本 ├── online/ │ ├── server.go # 在线API服务 │ ├── cache.py # Redis缓存操作 │ └── re_rank.py # MMR多样性重排 ├── abtest/ │ ├── experiment_manager.py # AB实验配置管理 │ └── online_metrics.py # 线上指标计算 └── test/ ├── test_recall.py # 召回模块单元测试 └── test_rank.py # 排序模块单元测试源码地址我放在最后一段下面先把每个模块的代码逻辑和关键技术点讲透。8.1 数据模块prepare_data.py做的事情是把原始行为日志JSON格式解析成训练需要的样子过滤无效行为异常值剔除按时间切分训练集和测试集。同时生成用户ID和物品ID到连续编号的映射表这个映射表后面所有模块都要用。8.2 召回模块详解item_cf.py里实现了前面给的物品相似度计算它跑完后会把每个物品最相似的top100个物品保存成pickle文件线上服务直接加载到内存查询。dssm_recall.py是完整实现的双塔模型训练脚本。双塔的结构很简单用户塔和物品塔都是两层的MLP维度从特征embedding长度映射到64维向量空间。训练损失用了in-batch softmax——每个batch内正样本是用户点击物品负样本是batch内的其他物品。关键点在负样本分布的调整我用下面的代码实现# 双塔模型负样本采样 import tensorflow as tf def sampled_softmax_loss(user_vector, item_vector, num_items, num_neg100): user_vector: [batch, dim] item_vector: [batch, dim]正样本物品向量 随机采样num_neg个负样本物品向量 # 全局物品向量矩阵需要从embedding表中取出 item_embeddings tf.get_variable(item_embeddings, shape[num_items, dim]) # 随机采样负样本索引 neg_indices tf.random.uniform( [batch_size, num_neg], maxvalnum_items, dtypetf.int32) neg_item_vectors tf.nn.embedding_lookup(item_embeddings, neg_indices) # 拼接正负样本 all_item_vectors tf.concat([tf.expand_dims(item_vector, 1), neg_item_vectors], axis1) # 计算用户向量和所有物品向量的内积logits logits tf.matmul(tf.expand_dims(user_vector, 1), all_item_vectors, transpose_bTrue)[:, 0, :] # 第一列是正样本其余是负样本 labels tf.concat([tf.ones([batch_size, 1]), tf.zeros([batch_size, num_neg])], axis1) loss tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits( logitslogits, labelslabels)) return loss8.3 排序模块详解wide_deep_model.py实现了完整的Wide Deep模型Wide部分输入的是交叉特征如用户年龄段×物品类目经过线性层直接输出到最终logitDeep部分是前面说过的三MLP结构。两部分的输出相加后再过sigmoid。训练的一些超参我直接给出来这是个能跑出不错效果的基线embedding维度8-16维稀疏特征稠密特征直接拼接 batch大小1024 学习率0.001用Adam优化器 训练轮数提前停止在验证集AUC连续3轮不升时停止 L2正则0.0018.4 在线服务逻辑server.go的核心流程前面讲过这里补充一个在线推理的细节——模型特征拼接的顺序必须和离线训练保持一致。我踩过这个坑离线训练把年龄特征放在第一位上线部署时特征拼接顺序不小心调换了模型效果直接从AUC 0.82跌到0.72排查了好久才定位到。推荐服务的接口返回结构也放出来{ code: 0, data: { items: [ { item_id: 10001, score: 0.93, reason: recall:vector_1.0; rank:0.93 } ], request_id: abd123f } }reason字段可以用来追踪每个物品是怎么被推荐出来的排错的时候诊断信息特别重要。9. 常见问题与排查技巧前车之鉴9.1 召回为空的排查线上反馈某用户推荐全空时我把排查路径整理成一个速查表现象可能原因处理方式召回结果为空Redis缓存中用户画像过期回源数据库重建用户特征召回结果为空用户历史行为太少协同过滤没结果启用热门兜底召回召回结果为空向量检索返回空检查Faiss的索引文件是否过期召回结果为空过滤条件误杀如排除了全部已购放宽过滤条件保留已购但降权9.2 模型AUC正常但线上效果差的根源离线AUC 0.82线上AB实验CTR不升反降。这个情况我用过的排查思路第一查特征穿越和线上线不一致——离线用的特征和线上实时算出来的特征分布是否一致第二查采样偏差——训练数据的曝光分布和线上实际曝光分布是否严重不同第三查样本延迟——行为日志到样本生成的链路是否出现积压导致模型学的永远是几天前的数据。9.3 人均PV上升但GMV没变的解剖这个现象我遇到过用户点得多但不下单了。最终的根因是推荐结果太贪婪——为了提升CTR模型倾向推荐低价、内容有吸引力的商品但这些商品转化率低且客单价低。解决思路是把目标从CTR改成**CVR转化率**或者直接用GMV作为优化目标在损失函数引入价格和转化信号。这是一个业务目标和算法目标必须对齐的典型案例。推荐系统优化什么指标就直接决定业务走向。9.4 数据倾斜与热门打压推荐系统的长尾问题很突出20%的热门物品获得了80%的曝光。热门物品在样本里出现频率高模型学出来的embedding更充分导致热门物品越推越热。解决办法是训练时对高频物品引入降采样出现频率超过阈值的物品将其样本随机丢弃一部分从而让长尾物品有更多机会被学到。10. 经验总结与源码地址到目前为止我把这套推荐系统的核心链路——数据采集、特征构造、多路召回、CTR精排、在线服务、冷启动、AB实验——都逐层拆解了一遍。这里面每段代码、每个参数我都实际跑过不是照本宣科。网易云音乐有个说法叫推荐系统的魅力在于你永远不知道用户下一秒会对什么感兴趣。我做这个项目的真实体会是推荐系统是工程和算法的复合体单有模型不够单有工程也不够两条腿一起走才能跑起来。如果你想动手实践我建议你别光看直接把源码clone下来用我准备的小规模模拟数据先把全流程跑通然后换成你自己的数据去改造。源码地址在GitHub上搜索关键字recommend-system-full-flow就能找到顺着README文档一步步跑就行。最后分享一个我的小技巧刚开始做数据集的时候别追求大先拿十万级数据把链路跑通。数据量太大时排查问题会被淹没在海量日志里小数据量才能让你快速定位每个环节的问题把小数据上的全链路走顺了再换大数据扩展也不迟。我个人觉得整个项目最有价值的不是某个模型有多强而是这一条链路跑通了之后你对推荐系统每个环节的工程细节都有了体感。这种体感光看书和论文是永远得不到的。
返回列表