尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

从订单到推荐位:Apriori/FP-Growth关联规则商品推荐系统

发布时间:2026/9/18 16:57:14

资讯中心
01
ARTICLE

从订单到推荐位:Apriori/FP-Growth关联规则商品推荐系统

从订单到推荐位:Apriori/FP-Growth关联规则商品推荐系统
简介这份面向电子商务与数据挖掘方向学习者的 PDF 文档围绕基于关联规则的商品推荐系统模型展开适合计算机、电商专业学生及算法入门者理解推荐系统的建模思路。文档共 1 个 PDF 文件压缩包约 118KB篇幅紧凑便于随时查阅与打印。内容从电子商务推荐系统的定义与作用讲起梳理简单关联、时序关联与因果关联的区别并逐一介绍 Apriori 算法、基于划分的算法以及 FP-树频集算法的原理与适用场景随后给出完整的推荐模型说明从数据库、网站记录、客户文档采集原始数据经预处理形成有效数据集再借关联规则挖掘建立规则库由模型引擎匹配用户购买清单输出推荐列表的过程并附算法伪代码与流程示意。目前已有 102 人学习可作为课程设计、论文写作或推荐系统入门时参考的轻量资料。1. 从购物车到推荐位关联规则商品推荐系统到底在算什么做电商推荐的人常遇到一个尴尬协同过滤在冷启动和新品上拿不出结果而运营只想回答“用户加了 A下一步推什么”。这份 PDF 给出的模型不走评分矩阵而是把订单事务当作数据源用关联规则挖“啤酒与尿布”式购买组合再把规则库接到推荐引擎上。关联规则、商品推荐系统在这里不是概念词而是可落地的两步先找频繁项集再生成带置信度的强规则。适合谁做数据挖掘、推荐后端、电商中台的工程师以及需要给运营解释推荐依据的人。模型的核心组件是规则库和模型引擎原始数据来自数据库、网站记录与客户文档预处理后进入 Apriori 或 FP 树挖掘最终输出推荐列表。2. 订单流水到事务矩阵Apriori 前的数据预处理与格式校验2.1 原始字段与事务化目标关联规则算法不认宽表它吃的是“事务-项”结构。每个订单是一个事务订单里的商品是项。订单表、订单明细表、商品表、用户行为日志都可能作为原始数据源但直接丢给 Apriori 会因状态、退款、测试账号、拆单导致支持度被污染。常见做法是先用 SQL 把已完成、有效、时间窗口内的订单筛选出来再用 pandas 聚合成一行一个事务。目标格式可以是一行一个订单商品编码用逗号分隔例如SKU1001,SKU2033,SKU7788。来源关键字段处理要求订单主表order_id, user_id, order_time, status只取 completed过滤测试用户限定 90 天订单明细order_id, sku_id, qty, priceqty 0sku_id 非空去重商品表sku_id, category, brand统一编码补品类用于后续打散行为日志user_id, sku_id, event_time可选加权点击/收藏弱于购买下面这段代码把订单明细聚合成事务文件并顺手做了商品编码统一和无效订单过滤。min_items2表示只保留至少两件商品的订单单商品订单对组合规则没有贡献。时间窗口在 SQL 层做掉pandas 层只负责格式转换。import pandas as pd # 读取订单明细与主表 detail pd.read_csv(order_detail.csv) orders pd.read_csv(orders.csv) # 只保留已完成、非测试订单 orders orders[orders[status] completed] orders orders[~orders[user_id].astype(str).str.startswith(test_)] # 关联明细过滤无效商品 df detail.merge(orders[[order_id, order_time]], onorder_id, howinner) df df[(df[qty] 0) (df[sku_id].notna())] # 统一商品编码为大写去掉空白 df[sku_id] df[sku_id].astype(str).str.strip().str.upper() # 按订单聚合去重商品生成事务 basket df.groupby(order_id)[sku_id].apply(lambda x: sorted(set(x))).reset_index() basket basket[basket[sku_id].apply(len) 2] # 至少两件商品才有组合意义 # 保存为 CSV每行一个事务商品用逗号分隔 basket[items] basket[sku_id].apply(lambda x: ,.join(x)) basket[[order_id, items]].to_csv(transactions.csv, indexFalse, headerFalse)代码跑完后要检查transactions.csv的行数、平均事务长度和商品总数。行数太少说明时间窗口太窄或状态过滤太狠平均事务长度如果接近 1关联规则基本挖不出东西。商品总数突然变大往往是因为商品编码没统一同一个 SKU 出现了大小写或空格差异。2.2 数据质量检查与常见坑预处理阶段最容易踩的坑是单商品订单占比过高。用一条 SQL 能快速量化统计已完成订单中商品种类小于 2 的订单比例。如果这个比例超过 70%Apriori 产出的频繁项集会非常稀疏推荐位几乎空转。另一个坑是热门商品霸榜某个爆款出现在 80% 的订单里任何规则都会带上它业务上却没有推荐意义。SELECT COUNT(*) AS single_item_orders, (SELECT COUNT(*) FROM orders WHERE status completed) AS total_orders FROM ( SELECT order_id FROM order_detail WHERE order_id IN (SELECT order_id FROM orders WHERE status completed) GROUP BY order_id HAVING COUNT(DISTINCT sku_id) 2 ) t;拆单和合并订单也要处理。用户一次买五件商品系统拆成三个订单事务就被切碎了。常见做法是按用户和时间窗口合并比如同一用户 30 分钟内多个订单视为一个事务。赠品、运费、测试商品、下架商品在事务化前就要剔除否则规则库会推出一堆无法下单的 SKU。提示先跑一版不做爆款过滤的规则观察前 50 条规则里是否反复出现同一个爆款再决定是否把它从频繁项集里拉黑。2.3 时间窗口与业务过滤规则时间窗口不是越久越好。快消品 30 到 60 天的购买关联更贴近当下耐用品可以放到 180 天。可以按周或按月生成多个批次每个批次单独挖掘线上按权重融合。业务过滤规则包括排除赠品 SKU、排除运费 SKU、排除测试品类、排除客单价异常订单。过滤条件写进 SQL 的 WHERE 子句不要等到代码里再删否则每次重跑都要重复劳动。事务文件建议保留order_time列方便后续做时间衰减。如果只存商品列表后面想按新老规则加权就得重新跑一遍预处理。落盘格式用 CSV 足够字段少、易调试如果事务量到千万级换成 Parquet 能省不少 I/O。3. 频繁项集与强规则挖掘Apriori 支持度、置信度参数落地3.1 mlxtend 跑 Apriori 的最小代码Python 生态里mlxtend是跑 Apriori 最省事的库之一。先把事务文件读成列表再用TransactionEncoder转成布尔矩阵。min_support控制频繁项集的门槛min_threshold控制规则置信度门槛提升度过滤放在规则生成之后。下面的代码把挖掘、过滤、打印串在一起适合在 notebook 里先摸参数。import pandas as pd from mlxtend.preprocessing import TransactionEncoder from mlxtend.frequent_patterns import apriori, association_rules # 读取事务文件每行商品用逗号分隔 with open(transactions.csv, encodingutf-8) as f: dataset [line.strip().split(,) for line in f if line.strip()] te TransactionEncoder() te_ary te.fit(dataset).transform(dataset) df pd.DataFrame(te_ary, columnste.columns_) # 频繁项集支持度阈值先设 0.005 freq apriori(df, min_support0.005, use_colnamesTrue) print(freq.sort_values(support, ascendingFalse).head(10)) # 生成规则置信度 0.25提升度至少 1.2 rules association_rules(freq, metricconfidence, min_threshold0.25) rules rules[rules[lift] 1.2] print(rules[[antecedents, consequents, support, confidence, lift]].head())min_support0.005表示一个商品组合至少出现在 0.5% 的订单里。min_threshold0.25表示前件出现时后件出现的条件概率至少 25%。lift 1.2表示这个组合比随机出现强 20%。use_colnamesTrue让输出直接显示商品编码而不是列索引调试时更直观。参数含义起步建议调整方向min_support频繁项集最低支持度0.005规则太少就降到 0.002规则爆炸就升到 0.01min_confidence规则最低置信度0.25推荐不准就升到 0.4召回不够就降到 0.15min_lift最低提升度1.2低于 1 的规则直接丢弃max_len项集最大长度3组合太长解释成本高线上匹配也慢3.2 Apriori 剪枝与 apriori_gen 逻辑Apriori 的核心是两条先验性质频繁项集的子集必定频繁非频繁项集的超集必定非频繁。第一轮扫描得到频繁 1 项集 L1然后用 L1 连接生成候选 2 项集 C2扫描数据库计算支持度剪掉低于min_support的候选得到 L2。之后用 L2 连接生成 C3再剪枝、再扫描直到没有新的频繁项集。这个递推过程就是 PDF 里apriori_gen(Lk-1, min_sup)做的事。连接操作把两个只有最后一项不同的频繁项集拼起来。剪枝操作检查候选项集的所有 k-1 子集是否都在 Lk-1 中只要有一个不在这个候选就不可能频繁直接删掉。实际写代码时不用手写apriori_genmlxtend已经封装好了。但理解剪枝逻辑能帮你判断参数是否合理如果 L2 数量很少L3 基本出不来如果 L2 数量巨大说明支持度设得太低候选集会膨胀。注意置信度高不代表规则有价值。前件和后件本身都是爆款时置信度天然高但提升度可能接近 1。规则入库前一定要看 lift。3.3 规则落库与版本管理规则挖出来后要落库不能每次推荐都重新跑 Apriori。建一张规则库表保存前件、后件、支持度、置信度、提升度和批次号。前件和后件用逗号分隔的商品编码存储查询时用LIKE或倒排表匹配。批次号用于区分不同时间窗口的规则线上可以按批次加权。CREATE TABLE rule_library ( id BIGINT PRIMARY KEY AUTO_INCREMENT, antecedent VARCHAR(512) NOT NULL, consequent VARCHAR(512) NOT NULL, support DECIMAL(8,6), confidence DECIMAL(8,6), lift DECIMAL(8,6), batch_id VARCHAR(32), create_time DATETIME DEFAULT CURRENT_TIMESTAMP, INDEX idx_antecedent (antecedent(191)), INDEX idx_batch (batch_id) ); INSERT INTO rule_library (antecedent, consequent, support, confidence, lift, batch_id) VALUES (SKU1001,SKU2033, SKU7788, 0.0062, 0.31, 1.45, 20250101_week);规则数量要控制。一个中等电商站点跑min_support0.005可能产出几万条规则全量加载到内存会拖慢接口。常见做法是按lift * confidence排序每个后件保留 Top 20 前件或者按品类做规则分片。批次号配合定时任务每天凌晨重新挖掘新批次上线后观察点击率再决定是否保留旧批次。4. 推荐引擎召回与排序规则库匹配、打分和接口封装4.1 规则匹配召回线上推荐引擎拿到用户购物车或当前商品列表后要快速找出前件被包含的规则再把后件作为候选商品。匹配逻辑不复杂遍历规则库检查前件集合是否是购物车集合的子集同时后件不能已经在购物车里。下面的函数做了召回和去重同一商品被多条规则命中时取最高分。def recommend(cart_items, rules_df, top_k10): cart set(cart_items) candidates [] for _, row in rules_df.iterrows(): ante set(row[antecedents]) cons set(row[consequents]) # 前件必须被购物车包含后件不能已购 if ante.issubset(cart) and not cons cart: score row[confidence] * row[lift] * row.get(decay, 1.0) for item in cons: candidates.append((item, score)) # 同一 SKU 取最高分 best {} for item, score in candidates: if item not in best or score best[item]: best[item] score ranked sorted(best.items(), keylambda x: x[1], reverseTrue) return ranked[:top_k]cart_items是当前购物车 SKU 列表rules_df是从规则库加载到内存的 DataFrametop_k控制返回数量。decay是时间衰减因子越新的规则权重越高。ante.issubset(cart)判断前件是否全部命中not cons cart防止推荐已购商品。实际线上不会每请求遍历全量规则通常先把规则按前件长度分桶或者用商品倒排索引缩小候选集。4.2 打分排序与业务规则召回只保证“有可能相关”排序决定最终展示顺序。打分公式可以简单写成confidence * lift * 时间衰减 * 业务权重。业务权重用来做品类打散、库存过滤、价格区间控制。比如用户购物车里已经有手机规则推手机壳是合理的但连续推五个手机壳就需要打散。库存为 0 的 SKU 在排序前直接过滤避免推荐位出现无法下单的商品。因子含义建议confidence规则条件概率直接相乘lift提升度低于 1 的规则不进入召回decay时间衰减按天衰减半衰期 7 到 30 天category_penalty品类重复惩罚同一品类最多展示 2 个stock库存小于等于 0 直接过滤排序后还可以加一个“解释文案”字段把命中的规则前件展示给运营。比如“买了 A 和 B 的用户也买了 C”这个文案在后台排查推荐效果时很有用。C 端不一定展示但内部工具需要。4.3 接口封装与缓存推荐接口延迟要压到 50ms 以内规则库不能每次查数据库。常见做法是启动时把规则加载到内存或者写入 Redis 哈希按前件商品编码建索引。下面用 FastAPI 写一个最小接口load_rules_from_redis返回规则 DataFrame实际项目里可以换成进程内缓存加定时刷新。from fastapi import FastAPI from pydantic import BaseModel app FastAPI() class CartReq(BaseModel): cart_items: list[str] top_k: int 10 app.post(/recommend) def recommend_api(req: CartReq): rules load_rules_from_redis() # 规则库缓存到 Redis按批次刷新 result recommend(req.cart_items, rules, req.top_k) return {items: [{sku: i, score: s} for i, s in result]}接口层要做参数校验cart_items不能为空top_k限制最大值防止一次拉取过多。规则版本号放在响应头里方便线上对比不同批次的效果。如果 Redis 不可用降级到本地缓存或返回空列表不要阻塞主流程。提示规则库更新后先推送到灰度实例观察接口 P99 和推荐点击率再全量刷新。5. FP-Growth 替换与线上排错增量更新、规则衰减和效果验证5.1 FP-Growth 替换 Apriori 的时机Apriori 要反复扫描数据库事务量上千万后候选集生成会成为瓶颈。FP-Growth 只扫两遍数据库把频繁项压缩进 FP 树再递归挖掘条件模式基。mlxtend里换成fpgrowth只需改一行参数含义和 Apriori 类似。当订单事务超过百万级或者 Apriori 跑一次超过 10 分钟就可以切到 FP-Growth 做全量挖掘。from mlxtend.frequent_patterns import fpgrowth # 支持度可以比 Apriori 稍低FP-Growth 对稀疏数据更稳 freq fpgrowth(df, min_support0.003, use_colnamesTrue)支持度阈值下调后频繁项集数量会上升后续规则生成要更严格地过滤lift。FP 树构建需要把事务按商品频次排序mlxtend内部已经处理。如果内存不够可以按品类分片挖掘再把各分片的规则合并去重。5.2 增量更新与规则衰减全量重跑适合每天一次但大促期间规则变化快可以按小时增量更新。增量更新的做法是只取最近一小时订单和旧事务合并后重新挖掘产出新批次规则。旧规则按时间衰减比如 7 天前的规则权重乘以 0.530 天前的规则权重乘以 0.1。规则表里的batch_id和create_time就是为衰减服务的。现象可能原因处理推荐位为空支持度太高、单商品订单太多降低 min_support合并拆单推荐全是爆款爆款霸榜、lift 过滤不严拉黑爆款或提高 lift 门槛接口变慢规则全量加载、匹配遍历按前件分桶Redis 缓存点击率下降规则过期、季节变化缩短时间窗口提高新批次权重5.3 排错清单与验证指标排错先从数据链路查事务文件行数、频繁项集数量、规则数量、线上召回数量。四个数字断崖式下跌问题一定在预处理或阈值。再看规则质量随机抽 20 条规则人工判断后件是否合理不合理就调lift和品类过滤。最后看线上指标推荐位点击率、人均曝光商品数、加购转化率。规则推荐通常曝光商品数少但转化高如果曝光数极低说明召回不够。线上先切 5% 流量对比 CTR 和人均曝光商品数再决定是否全量。本文还有配套的精品资源点击获取
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。