商品推荐系统-FAISS召回

news/2025/11/23 15:18:17/文章来源:https://www.cnblogs.com/w1570631036/p/19260652

1. 背景与挑战

在互联网电商、内容平台等实际业务中,商品库动辄百万量级,如何为每位用户从海量商品中迅速召回个性化、高相关的候选商品,是推荐系统最基础也最关键的一环。 如果只依赖商品的原始属性(如标题、描述)匹配,不仅难以刻画深层语义,还会因为暴力检索计算巨大,难以支撑在线业务实时性需求。

向量化(Embedding)特征+高效大规模近邻搜索,成为业界主流技术路径。FAISS(Facebook AI Similarity Search)就是这样一款解决大规模向量检索难题的利器。然而,FAISS 只“用”向量不“生产”向量,如何从表结构中高效提取、存储和利用embedding,直接关系到系统效果和可扩展性。


2. 表结构与需求场景

考虑如下典型商品表(如在SQLite中):

create table amazon_products
(asin              TEXT,    -- 商品唯一标识title             TEXT,    -- 商品标题imgUrl            TEXT,    -- 图片链接productURL        TEXT,    -- 商品详情页URLstars             REAL,    -- 平均评分reviews           INTEGER, -- 评论数量price             REAL,    -- 售价listPrice         REAL,    -- 原价category_id       INTEGER, -- 分类IDisBestSeller      INTEGER, -- 是否BestsellerboughtInLastMonth INTEGER  -- 上月销量
);

我们希望利用如 title 这样的文本特征,对百万商品转为向量,并实现“基于内容的高效召回”。


3. 第一环节:商品Embedding批量提取与存储

3.1 原因和意义

只有将文本型商品属性转化为稠密embedding(向量),才可以用数学距离度量内容相关性,支撑 FAISS 这样的相似度召回引擎。

3.2 推荐方案

  • 建议用 sentence-transformers,支持中英文,速度效能良好。
  • 如需多模态(如商品图片),可追加用 CLIP/BLIP-2 提取图片向量后与文本拼接或融合。

3.3 代码实战:批量文本Embedding

import sqlite3
from sentence_transformers import SentenceTransformer
import numpy as np# 1. 加载模型(建议 MiniLM,快且效果很好)
model = SentenceTransformer('all-MiniLM-L6-v2')# 2. 提取数据库中的 asin 和 title
conn = sqlite3.connect('recommend.db')
cur = conn.execute("SELECT asin, title FROM amazon_products")
asins, titles = [], []
for row in cur:asins.append(row[0])titles.append(row[1])
conn.close()# 3. 批量生成embedding(按需分批,防止内存溢出)
BATCH = 1000
embeddings = []
for i in range(0, len(titles), BATCH):batch_titles = titles[i:i+BATCH]batch_emb = model.encode(batch_titles,show_progress_bar=True,convert_to_numpy=True,normalize_embeddings=True    # 归一化便于后续用内积检索)embeddings.append(batch_emb)
all_embeddings = np.vstack(embeddings)  # shape = (商品数, emb_dim)# 4. 持久化embedding和asin
np.save('product_emb.npy', all_embeddings)
with open('asin_list.txt', 'w') as f:for asin in asins:f.write(f"{asin}\n")

3.4 结果检查

  • product_emb.npy: N×dN×d 的 float32 矩阵,每一行是一个商品的 embedding
  • asin_list.txt: 每行一个商品 asin,与向量顺序匹配

4. 第二环节:构建与优化FAISS召回系统

4.1 为什么选FAISS?

  • 面对百/千万量级商品,全表暴力计算相似度不可用
  • FAISS 能高效支持百万级向量毫秒级召回,可用 IndexFlatIP、IVFFlat、HNSW 等多种索引自由切换

4.2 索引构建与持久化

高性能工程策略

  • 索引训练和add建议只做一次,持久化磁盘,后续服务直接热加载
  • 支持多核并发(推荐设置 omp_set_num_threads)
  • 百万级数据建议用 IVFFlat+归一化,千万量级也支持

代码示例

import numpy as np
import faissall_embeddings = np.load('product_emb.npy').astype('float32')
faiss.omp_set_num_threads(8)      # CPU数按实际调整def build_or_load_index(embeddings, dim, index_path='faiss.index'):try:index = faiss.read_index(index_path)print("Loaded FAISS index from disk.")except Exception:quantizer = faiss.IndexFlatIP(dim)nlist = 4096index = faiss.IndexIVFFlat(quantizer, dim, nlist)faiss.normalize_L2(embeddings)index.train(embeddings)index.add(embeddings)faiss.write_index(index, index_path)print("Trained and saved FAISS index.")return indexindex = build_or_load_index(all_embeddings, all_embeddings.shape[1])

4.3 用户行为输入与召回

假设你能获取每个用户最近点击商品 asin:

import sqlite3def get_user_recent_click_asins(user_id, limit=10):conn = sqlite3.connect('recommend.db')cur = conn.execute('SELECT asin FROM user_clicks WHERE user_id=? ORDER BY click_time DESC LIMIT ?', (user_id, limit))click_asins = [row[0] for row in cur]conn.close()return click_asins

4.4 FAISS相似商品召回主流程

对每个用户历史点击asin,检索Top-K相似商品,再去重合并:

def faiss_ann_recall(user_click_asins, topn=200):# asin与embedding行号的映射asin2idx = {asin: i for i, asin in enumerate(all_asins)}recalled = set()result_scores = dict()for asin in user_click_asins:idx = asin2idx.get(asin)if idx is None:continueemb = all_embeddings[idx].reshape(1, -1)D, I = index.search(emb, topn+1)for i, sim in zip(I[0], D[0]):recall_asin = all_asins[i]if i == -1 or recall_asin in user_click_asins or recall_asin in recalled:continueresult_scores[recall_asin] = float(sim)recalled.add(recall_asin)return [a for a, s in sorted(result_scores.items(), key=lambda x: -x[1])]

4.5 多路召回融合与商品信息返回

与协同过滤等频道召回结果简单融合,并查回完整商品信息:

def recall(user_id, top_n=500, hybrid=True):user_click_asins = get_user_recent_click_asins(user_id)recall_faiss = faiss_ann_recall(user_click_asins, top_n*2)recall_cf = []   # 你可以补充协同召回recall_union, seen = [], set(user_click_asins)for asin in recall_cf + recall_faiss:if asin not in seen:recall_union.append(asin)seen.add(asin)if len(recall_union) >= top_n:break# enrich every asinif recall_union:conn = sqlite3.connect('recommend.db')format_sql = ','.join(['?']*len(recall_union))query = f"SELECT * FROM amazon_products WHERE asin IN ({format_sql})"rows = conn.execute(query, tuple(recall_union)).fetchall()product_list = [dict(zip([col[0] for col in conn.execute("PRAGMA table_info(amazon_products)")], row)) for row in rows]conn.close()return product_listreturn []

5. 百万级大数据下的表现与实践建议

  • 适用性:FAISS专为这种百万、千万级内容召回设计,单机64G内存可支持极大库,工程成熟。
  • 工程优化
    • embedding、索引建议都归一化和持久化
    • 多线程、批量搜索提升QPS
    • 大表可用倒排表(IVFFlat)、HNSW等近似加速型索引。
  • 微服务实践:索引文件和embedding持久化后随时API/服务热加载
  • 横向扩展:商品百万量级甚至上亿均可根据资源平滑扩容

6. 总结

本文详细介绍了如何从零开始,批量提取并存储商品embedding、基于内容特征构建FAISS索引、高效实现百万级商品的个性化召回流程以及工程落地优化建议。 核心经验:内容型推荐的向量建模与高效检索要“两条腿走路”,embedding和FAISS索引标准解耦、分批处理,并进行合理持久化与参数调优,才能满足大规模、实时推荐业务的需求。

FAISS已经成为现代推荐与搜索系统的主流底层方案,在你的实际业务中大可放心应用,并可通过本文流程快速上线工程原型。


参考

1.https://blog.csdn.net/m0_73983707/article/details/148055430

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/973957.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI 时代,.NET 开发者是向左还是向右?

**AI时代,.NET开发者不是向左还是向右的问题,****而是如何用自己最擅长的技术,抓住AI红利的问题。**AI 时代,.NET 开发者向左还是向右?Microsoft Agent Framework vs LangChain 1.0 —— 一场关乎未来的技术选择开…

Claude code 使用技巧

工具:cc switch 知乎 - AI编程白嫖资源切换神器:cc-switch快速上手指南 vscode 的 claude code插件使用技巧 我买了GLM4.6 和MiniMax-M2 的coding包,之后也会多试其他如Qwen或者国外模型。 1.GL4.6 的 code 配置 官…

OpenDroneMap (ODM) 无人机影像三维模型重建安装及应用快速上手

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

OneDrive人脸分组功能预览引发隐私担忧

某中心OneDrive正在测试基于AI的人脸识别分组功能,该功能可通过识别照片中的人脸自动归类图片。用户每年仅能三次开关此功能,且关闭后所有面部分组数据将在30天内永久删除,引发隐私保护方面的关注。某中心OneDrive照…

人和动物的区别在哪里???

人和动物的区别在哪里???各有各的说法,但这里我说说我个人的看法:人呀,人就是穿着衣服的猴子。本博客是博主个人学习时的一些记录,不保证是为原创,个别文章加入了转载的源地址,还有个别文章是汇总网上多份资料…

机器人模仿学习运动基元数学编码高效的方法还有用吗?

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

CF2152

CF2152B Catching the Krug 废物hdh 如果一开始 K 和 D 在同一行或者同一列,那么 K 的逃跑方向唯一,D 抓住它的时间就是到那个方向的边界的切比雪夫距离。否则,就是两个逃跑方向的切比雪夫距离取 \(\max\)。Code #i…

xyd 2025 NOIP 模拟赛

100 + 100 + 44 + 12 = 256, Rank 72/456.不知道 xyd 机子现在是不是抽卡,总之我 A 单 log 做法草过去了,最大点只跑了 521ms 😃 上次 xyd S 挂完了,所以这次 xyd NOIP 逆向挂完了,是这个意思吗?那我 NOIP 会不…

NET 8 封装自己的 rabbtMQ

项目地址 https://github.com/sansantang/Jonckers.RabbitMQ.HttpApi.Order 1 支持自定义 QoS (默认 PrefetchSize = 0, PrefetchCount = 1, Global = false) 2 支持死信队列 怎么使用 1. 服务注册 appsettings.json …

dropMimeData

ProjectViewModel::dropMimeData 是qt拖放

Terrorform-自动化创建EKS集群

需求: 当团队DevOps人数比较多或者外部团队申请EKS集群已经成为日常工作一部分,决定将这个过程通过Terrorform自动化进行创建,可追溯和减少手动操作的黑洞。 目标:1.提高自动化覆盖率。2.提高团队规范化创建流程 实…

最长单词2

点击查看代码 #include<iostream> #include<string> using namespace std; int main() {string s;getline(cin,s);int len = s.length();s[len-1] = ;int max=0, start=0, end=0;int temp=0;for (int i =…

Django 学习路线图 - 教程

Django 学习路线图 - 教程2025-11-23 14:52 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; f…

Tefrorform-自动化创建IAM

需求: 当团队DevOps人数比较多或者外部团队申请IAM权限已经成为日常工作一部分,决定将这个过程通过Terrorform自动化进行创建,可追溯和减少手动操作的黑洞。 目标:1.提高自动化覆盖率。2.提高团队规范化创建流程 实…

积极想到二维数组的递推

记忆化要dfs了 二维数组的想到和应用 !!!long long 类型 include<bits/stdc++.h> using namespace std; long long dp[50][2]; long long f(int x) { dp[1][0]=1;dp[1][1]=2; for(int i=2;i<=x;i++) { dp[…

[人工智能-大模型-55]:模型层技能 - AI的算法、数据结构中算法、逻辑处理的算法异同

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

Terrorform-自动化配置AWS EC2

需求: 当团队DevOps人数比较多或者外部团队申请EC2实例已经成为日常工作一部分,决定将这个过程通过Terrorform自动化进行创建,可追溯和减少手动操作的黑洞。 目标:1.提高自动化覆盖率。2.提高团队规范化创建流程 实…

Terrorform-自动化配置AWS Route53

待整理中http://www.cnblogs.com/Jame-mei

elasticSearch之API:索引运行

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …