资讯动态

Django+协同过滤:从零搭建招聘信息推荐系统实战

发布时间:2026/9/26 18:11:12 来源:尧图企业网站定制
简介基于协同过滤算法的招聘信息推荐系统是一份结合Django与爬虫技术的完整项目源码面向毕业设计、课程设计及工程实训等场景适合希望从零搭建推荐系统前后端的学习者。压缩包内共508个文件以Vue前端组件、Python后端逻辑、JavaScript交互脚本及Py打包缓存文件为主辅以CSS样式、SQL数据库脚本、Word文档和安装运行批处理整体大小23.35MB目录结构清晰便于按模块查阅。目前已有84人学习/下载。内含可运行源码、SQL数据文件和学习文档LW并针对Python3.8DjangoMySQL5.7Vue环境做了适配管理员后台支持用户管理、招聘信息管理、留言板与系统设置同时内置爬虫模块可采集招聘数据配合安装运行脚本能帮助学习者快速启动项目并理解协同过滤推荐在真实系统中的应用逻辑。1. 从一份 zip 到一套能跑的招聘推荐系统先搞清楚它要解决什么做过招聘平台的人都知道简历投递环节的匹配效率低得惊人。候选人面对几十页职位列表翻到第三屏就失去耐心HR 面对成百上千份简历筛完关键词还要靠经验判断。协同过滤算法在电商推荐里已经被验证得很成熟但把它搬到招聘场景有一个非常特殊的问题用户和职位之间的交互数据极其稀疏。一个求职者一天可能只投三五份简历一个职位一周可能只收到几十份投递这种稀疏度远低于电商的“浏览-点击-购买”链路。所以“5p125基于协同过滤算法的招聘信息推荐系统_djangospider.zip”这类项目本质上是在回答一个问题在交互数据这么少的前提下怎么用协同过滤给求职者推靠谱的职位同时让 HR 看到真正匹配的候选人。这套方案的技术栈很清晰Django 负责 Web 框架和业务逻辑spider 负责从招聘网站抓取原始职位数据协同过滤算法在中间做推荐计算。适合谁呢两类人最值得花时间研究一类是正在做毕业设计或者求职作品集的计算机专业学生需要一套完整的、能演示前后端交互和推荐效果的工程项目另一类是中小型招聘平台或者企业内部招聘系统的开发者想用低成本方案先验证推荐效果而不是一上来就上大规模机器学习平台。第一个要建立的心理预期是这类项目的核心价值不在算法有多先进而在“数据获取—数据清洗—推荐计算—结果展示”这条链路是否完整、是否能跑通。2. 协同过滤在招聘场景下的选型为什么不能用电商那套照搬2.1 基于用户的协同过滤 vs 基于物品的协同过滤招聘场景的天然倾向协同过滤分两大类基于用户的UserCF和基于物品的ItemCF。电商里 ItemCF 是绝对主流因为物品数量相对稳定用户行为丰富算物品相似度非常划算。但招聘推荐系统里情况完全反过来。职位物品是动态变化的今天挂出来的 Java 开发岗下周可能就下架了而候选人用户的画像相对稳定——他的技能栈、工作经验、期望薪资在几个月内不会有太大变化。所以很多招聘推荐项目会优先采用基于用户的协同过滤找到与你技能相似、投递行为相近的其他求职者看他们投了什么职位把这些职位推荐给你。但这里有个现实的问题UserCF 需要维护用户相似度矩阵当用户量过万时两两计算的开销非常可观。所以实际项目中常见的做法是折中——先用基于物品的协同过滤算职位相似度再用“你投过的职位”去召回相似职位。具体到这份 zip 里的实现通常会在两者之间做可配置的切换或者直接实现 ItemCF 为主、UserCF 为辅的混合策略。选 ItemCF 还有一个非常实际的理由职位相似度的计算结果可以离线预处理缓存成文件或者数据库表用户在页面上发起请求时直接查相似职位列表就行响应速度快演示效果好。2.2 招聘数据稀疏带来的冷启动问题从 spider 抓回来的数据开始就得处理前面说了招聘场景数据稀疏这会导致协同过滤最经典的冷启动问题。新职位没有任何投递记录无法计算相似度新用户没有任何投递历史无法做个性化推荐。这个 zip 项目的解法通常有两种。一种是基于内容的补充策略职位本身带有分类、技能标签、薪资范围、学历要求这些属性利用这些属性算职位相似度弥补交互数据的不足这种叫基于属性的推荐另一种是热度兜底策略冷启动用户或者冷启动职位直接推热门职位榜等积累了足够的交互行为再切换成个性化推荐。spider 模块在这里的价值不只是抓数据更重要的是抓什么字段、怎么清洗。原始数据里职位描述往往是长文本需要做分词和关键词提取薪资可能是“1.5万-2.5万”这种字符串要解析成数值区间才能参与计算工作地点、学历要求、经验要求这些离散字段要统一编码。这些清洗工作在推荐系统里占了 60% 的工作量却最容易被忽略。很多照着 zip 跑通的人会发现推荐结果不准问题八成不在协同过滤算法本身而在喂给算法的特征太脏。2.3 离线计算 vs 实时推荐Django 项目里推荐结果怎么落库招聘推荐不是电商那种毫秒级响应的场景求职者打开职位详情页、翻到推荐模块等两三秒完全能接受。所以不需要引入实时计算框架离线批处理就够。常见的落地路径是spider 抓完数据后写一个独立的 Python 脚本或者 Django management command执行协同过滤计算把结果写进数据库表比如一张 user_recommendation 表字段包括 user_id、recommended_job_ids用逗号分隔或者 JSON 存储、score、created_at。Django 的视图层只需要查询这张表取出推荐职位 ID再去职位表里关联查询详细信息拼装成 JSON 返回给前端。这种设计的优势非常明显推荐计算和 Web 服务完全解耦。算法改动了只需要重新跑离线任务不影响线上服务稳定性。而且对新手友好不需要理解 Celery 或者消息队列一个 management command 就能搞定。对想加分的人来说可以在这个基础上用 Django 的 signal 或者定时任务把离线计算自动化但那是后话先把主链路跑通更重要。3. 把 zip 里的 Django 项目跑起来环境搭建与数据准备3.1 解压后先看目录结构django app 和 spider 模块是怎么组织的拿到 zip 解压后第一步不是急着跑而是把目录结构摸清楚。一个规范的此类项目根目录下通常有 manage.py、一个主配置目录比如 jobrec/ 或者 config/、一个核心业务 app比如 recommendation/ 或者 jobs/、一个 spider 目录以及 requirements.txt。用 tree 命令或者直接在编辑器里扫一眼重点确认四个东西第一settings.py 里配置了哪些 appINSTALLED_APPS 列表里有没有 recommendation、jobs 这些业务模块第二spider 目录下是独立的爬虫脚本还是基于 Scrapy 框架的完整工程——前者只需要装 requests 和 BeautifulSoup后者要装 Scrapy 且要注意版本兼容第三有没有 SQL 初始化文件或者迁移文件migrations 目录第四requirements.txt 里列了哪些依赖这决定了你能不能在一小时内把环境装完。这里要提醒一句zip 里的代码往往是在作者本地环境跑通的依赖版本写得很随意。常见的情况是 requirements.txt 里只有 Django2.x 或者 Django3.x但推荐计算用到的 pandas、numpy、scikit-learn 并没有列全。所以需要自己补齐。我的习惯是先建一个干净的虚拟环境Python 版本用 3.8 或者 3.9Django 版本按 requirements.txt 来其他缺失的库在跑的时候报错再装哪缺补哪这样最省时间。3.2 建虚拟环境、装依赖、初始化数据库一条命令都别省虚拟环境是这类项目第一个翻车点。很多同学图省事直接用全局 Python 环境结果系统里 Django 版本和项目要求的版本冲突一跑就报错。以下是推荐的操作流程# 创建虚拟环境python3.8 或 3.9 均可不要用 3.12 以上部分老依赖会编译失败 python3 -m venv venv # 激活虚拟环境Windows 用户把 source 换成 venv\Scripts\activate source venv/bin/activate # 先升级 pip避免安装依赖时出现奇怪问题 pip install --upgrade pip # 安装项目依赖如果 requirements.txt 不完整后续缺啥补啥 pip install -r requirements.txt # 初始化数据库Django 默认用的 SQLite不需要额外装数据库服务 python manage.py makemigrations python manage.py migrate # 创建超级用户用于登录 Django admin 后台查看数据 python manage.py createsuperuser这段命令背后的逻辑是makemigrations 会把 models.py 里定义的模型变化生成迁移文件migrate 才会真正建表。如果跑 migrate 报错大概率是 models.py 里某个字段类型写得不兼容或者是外键引用了一个不存在的表。SQLite 不需要额外配置这对新手最友好如果你要换成 MySQL记得在 settings.py 里改 DATABASES 配置并且提前建好数据库、设置好字符集 utf8mb4。初始化完成后用 python manage.py runserver 启动开发服务器浏览器访问 http://127.0.0.1:8000 能看到 Django 默认页面就说明框架本体跑通了。这时候你看到的还是一个空壳因为没有数据推荐模块自然没有输出。下一步是搞定数据。3.3 两条数据路径跑 spider 抓真实数据或者用 fixtures 造测试数据这个 zip 里带 spider 模块所以理想路径是跑爬虫抓真实职位数据。但真实爬虫有几个现实问题目标网站改版导致选择器失效、反爬机制拦截、抓取字段缺失。所以我的建议是双轨并行——既跑 spider也准备一套 fixtures 测试数据兜底。fixtures 是 Django 提供的数据导入机制。如果你在 zip 里看到 fixtures 目录或者 .json 文件直接用以下命令导入# 导入 fixture 数据假设文件名为 job_data.json python manage.py loaddata job_data.json如果没有现成的 fixture可以自己写一个简单的数据生成脚本。用 Django 的 shell 模式快速造 200 个职位和 50 个用户交互记录就足够跑通推荐流程了。以下是一个参考脚本# 在项目根目录创建 seed_data.py然后执行 python seed_data.py import os import django import random os.environ.setdefault(DJANGO_SETTINGS_MODULE, jobrec.settings) # 改为你的项目配置 django.setup() from jobs.models import Job, UserProfile, Application # 按实际模型名导入 # 先清空旧数据避免重复导入 Job.objects.all().delete() UserProfile.objects.all().delete() Application.objects.all().delete() # 生成职位数据覆盖 Java、Python、前端、测试、运维等常见岗位 categories [Java开发, Python开发, 前端开发, 软件测试, 运维工程师] cities [北京, 上海, 深圳, 杭州, 成都] for i in range(200): Job.objects.create( titlef{random.choice(categories)}工程师-{i}, categoryrandom.choice(categories), cityrandom.choice(cities), salary_minrandom.randint(8, 20), salary_maxrandom.randint(15, 40), description职位描述文本用于关键词提取和相似度计算, requirement本科及以上学历相关工作经验, ) # 生成候选人和投递记录构建协同过滤需要的交互矩阵 for u in range(50): user UserProfile.objects.create(usernamefcandidate_{u}) # 每个用户随机投递 3-10 个职位构建交互矩阵 for job in random.sample(list(Job.objects.all()), random.randint(3, 10)): Application.objects.create(useruser, jobjob, statussubmitted)代码里的逻辑说明职位数据要覆盖多个分类和城市这些离散属性会参与相似度计算太单一会导致推荐结果没有区分度交互记录一定要有稀疏性每个用户投递 3 到 10 个职位一共 50 个用户产生的交互记录大约在 300 条左右这个稀疏度贴合真实招聘场景。参数可以按需调整如果你想让推荐效果更明显把用户数增加到 200投递数增加到 10 到 20这样相似用户能更稳定地算出来。4. 推荐引擎核心实现从原始数据到相似度计算到 Top-N 推荐4.1 用户-职位交互矩阵怎么构建内存版 pandas 和 SQL 查询两种姿势协同过滤算法要求输入是一个用户-物品交互矩阵行是用户列是职位单元格值表示交互行为投递1浏览0.5收藏0.8。招聘系统里最重的行为就是投递所以常见的做法是直接用 0/1 矩阵投过为 1没投为 0。第一种写法用 pandas 直接拉数据代码最简洁import pandas as pd from django.core.management.base import BaseCommand from jobs.models import Application, Job, UserProfile class Command(BaseCommand): help 构建用户-职位交互矩阵并计算推荐结果 def handle(self, *args, **options): # 从数据库拉取投递记录只取 user_id 和 job_id 两列 applications Application.objects.all().values(user_id, job_id) df pd.DataFrame(list(applications)) # 构造稀疏矩阵行是用户列是职位投递标记为 1 interaction_matrix df.pivot_table( indexuser_id, columnsjob_id, valuesjob_id, aggfunccount, fill_value0 ) # 将 0/1 矩阵转换为浮点类型方便后续计算 interaction_matrix interaction_matrix.astype(float) print(f交互矩阵形状: {interaction_matrix.shape}) print(f稀疏度: {1 - (interaction_matrix.values 0).sum() / interaction_matrix.size:.4f})这里 pivot_table 的作用是把长表每条投递记录一行转成宽表每个用户一行、每个职位一列。aggfunccount 表示如果有重复投递就计数fill_value0 表示没有投递的格子填 0。print 出矩阵形状和稀疏度很有必要——如果稀疏度超过 0.95你就要警惕推荐效果可能不好需要考虑加一些热门职位兜底。如果你的数据量在十万条交互以上pandas 的 pivot_table 内存开销还能扛住但到百万级别就要换思路了。可以用 scipy.sparse 的 CSR 矩阵来存计算时用矩阵乘法一次搞定相似度。不过这套 zip 项目的定位是中小规模演示pandas 完全够用不建议在第一步就把复杂度抬上去。4.2 ItemCF 相似度计算余弦相似度在职位推荐里的具体实现有了交互矩阵下一步算职位之间的相似度。ItemCF 的核心假设是两个职位被同一批用户投递过它们就是相似的。用余弦相似度来度量公式是cos(θ) A·B / (|A|×|B|)A 和 B 是两个职位列向量。下面给出完整实现import numpy as np from sklearn.metrics.pairwise import cosine_similarity from jobs.models import Job def compute_item_similarity(interaction_matrix): 计算职位之间的余弦相似度矩阵 interaction_matrix: DataFrame行是用户列是职位 返回: 职位相似度矩阵和职位 ID 列表 # 转置矩阵行变成职位列变成用户每一行是一个职位的用户投递向量 item_matrix interaction_matrix.T # 用 sklearn 的余弦相似度计算一行代码搞定 similarity_matrix cosine_similarity(item_matrix) # 把相似度矩阵转成 DataFrame方便按职位 ID 索引 job_ids item_matrix.index.tolist() similarity_df pd.DataFrame( similarity_matrix, indexjob_ids, columnsjob_ids ) return similarity_df逻辑说明item_matrix 的行是职位列是用户同样用 0/1 表示该用户是否投递过该职位。cosine_similarity 会遍历每一对职位向量计算它们的余弦值。如果两个职位经常被同一批用户投递向量方向接近余弦值接近 1如果完全没有重合用户余弦值就是 0。这里有个隐藏的参数点要不要对交互矩阵做加权比如把用户投递次数多的职位加权调低防止热门职位把相似度拉偏。这个可以在后续调优时考虑第一次跑通不用加。4.3 给用户推荐 Top-N 职位过滤已投递和历史下架职位算出职位相似度矩阵之后推荐逻辑就是对用户投递过的职位找出每个的相似职位按相似度加权聚合去掉用户已经投过的取分值最高的 N 个。这就是最经典的 ItemCF 推荐流程实现如下def recommend_for_user(user_id, similarity_df, interaction_matrix, top_n10): 为单个用户生成职位推荐列表 # 从交互矩阵中取出该用户的投递记录 if user_id not in interaction_matrix.index: return [] user_row interaction_matrix.loc[user_id] # 找出该用户投递过的职位 interacted_jobs user_row[user_row 0].index.tolist() # 初始化评分字典维护每个候选职位的累计得分 scores {} for job in interacted_jobs: # 取出与该职位相似的 TOP 20 个职位 similar_jobs similarity_df[job].sort_values(ascendingFalse).head(20) for similar_job, score in similar_jobs.items(): # 过滤掉用户已经投递过的职位 if similar_job in interacted_jobs: continue # 分数累加投递过的职位权重为 1未来可调成投递次数 scores[similar_job] scores.get(similar_job, 0) score # 按分数倒序取前 N 个 ranked_jobs sorted(scores.items(), keylambda x: x[1], reverseTrue)[:top_n] # 返回职位 ID 列表和推荐分数 return [(job_id, score) for job_id, score in ranked_jobs]这段代码有一个必须注意的参数similar_jobs similarity_df[job].sort_values().head(20)。head(20) 这个值决定了每个已投递职位会贡献多少个候选职位调大会让推荐结果更发散调小更集中。我一般建议第一次用 20后面根据推荐效果在 10 到 50 之间调整。还有 scores 累加时用的是原始相似度没有做归一化如果用户投递了 20 个职位和投递 3 个职位前者的分数天然会更高。这让投递多的用户推荐结果更稳定投递少的用户推荐结果更稀疏符合直觉逻辑。4.4 把推荐结果写回 Django 数据库离线计算后怎么让页面能查到计算出来的推荐结果不能每次都现算太慢。正确做法是写一张推荐表在离线任务统一更新from jobs.models import JobRecommendation def generate_all_recommendations(similarity_df, interaction_matrix, top_n10): 批量计算所有用户的推荐结果并写入数据库 # 清空旧的推荐记录保证每次跑出来的结果干净 JobRecommendation.objects.all().delete() # 遍历交互矩阵中的每个用户 for user_id in interaction_matrix.index: recommendations recommend_for_user(user_id, similarity_df, interaction_matrix, top_n) # 批量构造对象一次性写入数据库减少数据库开销 bulk_list [] for rank, (job_id, score) in enumerate(recommendations): bulk_list.append( JobRecommendation( user_iduser_id, job_idjob_id, scorescore, rankrank 1 # 排名从 1 开始方便前端展示序号 ) ) # 使用了 bulk_create效率比逐条 create 高一个数量级 JobRecommendation.objects.bulk_create(bulk_list) print(f推荐生成完毕共 {len(bulk_list)} 条推荐记录)这里有两个细节值得注意第一是 JobRecommendation.objects.all().delete() 放在循环外只清一次如果在循环里清每处理一个用户就把所有记录删光最后只剩最后一个用户的推荐第二是 bulk_create 会绕过 Django 的 save() 方法字段里的 auto_now_add 时间戳可能会有问题如果时间戳很重要手动给每个对象加上 created_at。把推荐结果写库之后Django 视图层只需要一行查询就能拿到用户推荐比如 JobRecommendation.objects.filter(user_idrequest.user.id).order_by(rank)再关联职位表取详情拼 JSON 返回到前端。5. 推荐结果出来了先别高兴三个必踩的性能和准确率坑5.1 旧职位 ID 出现在推荐列表里蜘蛛抓完数据没做状态管理现象推荐结果里出现“已经下架三个月”的职位用户点进去 404。原因spider 抓数据时把职位当成一次性任务抓完入库就不管了没有维护职位的上下架状态。协同过滤只认 ID不管职位还存不存在。解决给 Job 模型加一个 is_active 字段spider 每次抓取时先标记所有旧记录为 inactive再更新活着的职位。推荐查询时强制过滤 is_activeTrue。如果不想改模型也行在 recommend_for_user 里对 candidates 做一次 Job.objects.filter(id__incandidates, is_activeTrue) 的过滤但治标不治本推荐表里还是会积累脏数据。5.2 热门职位霸榜长尾职位永远没有出头之日现象推荐列表演变成“热门职位排行榜”每个人看到的都一样协同过滤的个性化完全失效。原因物品流行度偏差。热门职位投递基数大相似度计算时它们和几乎所有职位都有交点导致推荐分虚高。这在电商里是经典问题在招聘场景更严重因为职位生命周期短热门职位抢走了绝大多数曝光。解决在推荐计算时对热门职位做惩罚。常见的做法是把相似度乘以一个惩罚系数公式是惩罚系数 1 / (1 log(1 职位投递次数))。投递次数越多惩罚越重。调控的弹性很大log 底数和分母常数都可以调。我给个经验值职位投递次数超过全部职位中位数两倍的惩罚系数直接降到 0.5 以下效果立竿见影。5.3 数据库越跑越慢推荐表变成数据泥潭现象runserver 启动越来越慢admin 后台点开用户管理要等好几秒SQLite 文件从几百 KB 长到几百 MB。原因推荐表没有唯一约束每次跑推荐任务都是先全删再全插数据库碎片化严重加上没有建立索引。解决给 JobRecommendation 表加一个唯一约束user_id, job_id这样即使多次跑离线任务也不会产生重复记录。然后给 user_id 加索引这是查询最频繁的字段。具体操作是改 models.py 里的 Meta 类class JobRecommendation(models.Model): user models.ForeignKey(User, on_deletemodels.CASCADE) job models.ForeignKey(Job, on_deletemodels.CASCADE) score models.FloatField() rank models.IntegerField() created_at models.DateTimeField(auto_now_addTrue) class Meta: # 联合唯一约束防止同用户同职位重复推荐 unique_together (user, job) # 按用户和分数查索引加速视图层查询 indexes [ models.Index(fields[user, score]), ]迁移之后跑一次 python manage.py makemigrations 和 migrate 让索引生效。能扛到什么程度SQLite 下十万条推荐记录毫无压力到百万级建议换 MySQL。另外在清空推荐表时不要用 .all().delete()改用原生 SQL 的 TRUNCATE 或者 Django 的 QuerySet.delete() 都行但记得先关掉外键检查否则删除会非常慢。6. 让推荐系统变得“能用”混合策略、离线评估和一个实战验收技巧推荐系统跑通了不等于能上线你还得回答一个问题推荐得准不准评判一个招聘推荐系统的推荐质量不能只看用户点没点还要看职位适配度。这要求在系统里埋一个评估模块。我的做法是写一个离线评估脚本把交互矩阵按 8:2 拆成训练集和测试集用训练集跑一遍推荐然后看看测试集里的真实投递职位有没有出现在推荐列表里。这个指标就是召回率公式很简单命中数除以测试集投递总数。如果召回率低于 5%说明推荐算法基本没起作用需要调参数10% 以上算及格20% 以上说明个性化效果已经肉眼可见。评估脚本不用太复杂以下是核心伪代码思路# 评估脚本逻辑 from sklearn.model_selection import train_test_split # 把交互矩阵按用户划分每个用户的 80% 投递进训练集20% 进测试集 train_matrix, test_matrix train_test_split(interaction_matrix, test_size0.2, random_state42) # 用训练集计算职位相似度和推荐结果 similarity_df compute_item_similarity(train_matrix) # 对每个用户拿到推荐 TOP 10 职位列表 hit_count 0 total_count 0 for user_id in test_matrix.index: # 测试集中该用户的真实投递 true_jobs test_matrix.loc[user_id][test_matrix.loc[user_id] 0].index.tolist() # 推荐结果 recommended_jobs [job_id for job_id, score in recommend_for_user(user_id, similarity_df, train_matrix, top_n10)] # 命中统计 hits set(true_jobs) set(recommended_jobs) hit_count len(hits) total_count len(true_jobs) recall hit_count / total_count if total_count 0 else 0 print(f召回率: {recall:.2f}命中 {hit_count}/{total_count})注意 train_test_split 的行是用户列是职位random_state42 保证可复现。如果你发现召回率一直不理想按照前面的经验优先检查三点职位是否有 is_active 过滤、热门职位惩罚是否开启、交互矩阵是否太稀疏。也可以用同样的评估逻辑对比不同 top_n 和 head(20) 参数组合哪个召回率高就用哪个这是硬道理。最后再讲一个关于混合策略的小技巧能让推荐效果在演示时显得更自然。在最终返回给前端的推荐列表里把纯 ItemCF 的结果和“同类职位热度排行”按 7:3 或 8:2 的比例混合。这个混合逻辑写在视图层不碰算法核心代码# 视图层混合推荐逻辑 from jobs.models import JobRecommendation, Job def mixed_recommendations(user_id, top_n10): # 从推荐表拿个性化结果 personalized list( JobRecommendation.objects.filter(user_iduser_id).order_by(rank)[:int(top_n * 0.8)] ) # 同类别下热门职位兜底 if personalized: first_job Job.objects.get(idpersonalized[0].job_id) hot_jobs Job.objects.filter( categoryfirst_job.category, is_activeTrue ).order_by(-view_count)[:int(top_n * 0.2)] else: hot_jobs Job.objects.filter(is_activeTrue).order_by(-view_count)[:top_n] # 合并并去重保持排序稳定 merged personalized list(hot_jobs) seen set() result [] for item in merged: job_id item.job_id if hasattr(item, job_id) else item.id if job_id not in seen: seen.add(job_id) result.append(job_id) return result混合比例不要写成死代码放到 settings.py 里当配置项PERSONALIZED_RATIO 0.8。这样调整推荐风格不需要改代码改配置就行。我自己的习惯是每次改完推荐算法和参数都会把召回率数字记录下来跑完评估脚本数字涨了就用新参数跌了就回滚。用数据而不是直觉来做决定这大概是这套项目里最值得带走的一个习惯。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑