ES_VECTOR_SIMILARITY.md
5.67 KB
ES向量相似度索引生成
概述
i2i_content_similar.py 脚本从Elasticsearch获取商品向量,计算并生成两种内容相似度索引:
- 基于名称文本向量的相似度 (
i2i_content_name) - 基于图片向量的相似度 (
i2i_content_pic)
使用方法
运行脚本
cd /home/tw/recommendation/offline_tasks
python scripts/i2i_content_similar.py
脚本无需任何参数,所有配置都在代码中设置好。
配置说明
脚本内置配置(位于 i2i_content_similar.py 头部):
# ES配置
ES_CONFIG = {
'host': 'http://localhost:9200',
'index_name': 'spu',
'username': 'essa',
'password': '4hOaLaf41y2VuI8y'
}
# 算法参数
TOP_N = 50 # 每个商品返回的相似商品数量
KNN_K = 100 # knn查询返回的候选数
KNN_CANDIDATES = 200 # knn查询的候选池大小
工作流程
1. 获取活跃商品
从数据库查询最近1年内有过行为的商品:
SELECT DISTINCT item_id
FROM sensors_events
WHERE event IN ('click', 'contactFactory', 'addToPool', 'addToCart', 'purchase')
AND create_time >= '1年前'
AND item_id IS NOT NULL
2. 从ES获取向量
对每个活跃商品,从Elasticsearch查询:
{
"query": {
"term": {
"_id": "商品ID"
}
},
"_source": {
"includes": ["_id", "name_zh", "embedding_name_zh", "embedding_pic_h14"]
}
}
返回字段:
_id: 商品IDname_zh: 中文名称(用于debug输出)embedding_name_zh: 名称文本向量 (1024维)embedding_pic_h14: 图片向量列表,每个元素包含:vector: 向量 (1024维)url: 图片URL
3. KNN向量相似度查询
使用商品的向量查询相似商品:
名称向量查询:
{
"knn": {
"field": "embedding_name_zh",
"query_vector": [向量值],
"k": 100,
"num_candidates": 200
},
"_source": ["_id", "name_zh"],
"size": 100
}
图片向量查询:
{
"knn": {
"field": "embedding_pic_h14.vector",
"query_vector": [向量值],
"k": 100,
"num_candidates": 200
},
"_source": ["_id", "name_zh"],
"size": 100
}
4. 生成索引文件
输出两个文件到 output/ 目录:
i2i_content_name_YYYYMMDD.txt: 基于名称向量的相似索引i2i_content_pic_YYYYMMDD.txt: 基于图片向量的相似索引
文件格式:
item_id\titem_name\tsimilar_id1:score1,similar_id2:score2,...
示例:
123456 香蕉干 234567:0.9234,345678:0.8756,456789:0.8432
输出说明
Redis Key 格式
名称向量相似
- Key:
item:similar:content_name:{item_id} - Value:
[[similar_id1,score1],[similar_id2,score2],...] - TTL: 30天
图片向量相似
- Key:
item:similar:content_pic:{item_id} - Value:
[[similar_id1,score1],[similar_id2,score2],...] - TTL: 30天
使用示例
import redis
import json
r = redis.Redis(host='localhost', port=6379, db=0)
# 获取基于名称向量的相似商品
similar_items = json.loads(r.get('item:similar:content_name:123456'))
# 返回: [[234567, 0.9234], [345678, 0.8756], ...]
# 获取基于图片向量的相似商品
similar_items = json.loads(r.get('item:similar:content_pic:123456'))
# 返回: [[567890, 0.8123], [678901, 0.7856], ...]
性能说明
运行时间估算
假设有 50,000 个活跃商品:
- ES查询获取向量: ~50,000次,每次约10ms = 8-10分钟
- KNN相似度查询: ~50,000次,每次约50ms = 40-50分钟
- 总计: 约50-60分钟
优化建议
如果性能不够:
- 批量处理: 使用ES的
_mget批量获取向量 - 并发查询: 使用多线程/异步IO提高查询并发
- 增量更新: 只处理新增/更新的商品
- 缓存结果: 将ES向量缓存到本地,避免重复查询
ES向量字段说明
embedding_name_zh
- 类型:
dense_vector - 维度: 1024
- 相似度:
dot_product - 用途: 基于商品名称的语义向量
embedding_pic_h14
- 类型:
nested - 结构:
json [ { "vector": [1024维向量], "url": "图片URL" } ] - 相似度:
dot_product - 用途: 基于商品图片的视觉向量
注意事项
- 网络连接: 确保能访问ES服务器
- 权限: 确保ES用户有查询权限
- 向量缺失: 部分商品可能没有向量,会被跳过
- 向量格式: 图片向量是嵌套结构,取第一个图片的向量
- 自我排除: KNN结果会排除商品自己
故障排查
连接ES失败
# 检查ES配置
curl -u essa:4hOaLaf41y2VuI8y http://localhost:9200/_cat/indices
查询超时
调整超时参数:
es = Elasticsearch(
[ES_CONFIG['host']],
basic_auth=(ES_CONFIG['username'], ES_CONFIG['password']),
request_timeout=60 # 增加到60秒
)
向量字段不存在
检查ES mapping:
curl -u essa:4hOaLaf41y2VuI8y http://localhost:9200/spu/_mapping
与其他相似度算法的对比
| 算法 | 数据源 | 优势 | 适用场景 |
|---|---|---|---|
| Swing | 用户行为 | 捕获真实交互关系 | 行为相似推荐 |
| W2V | 用户会话 | 捕获序列关系 | 下一个商品推荐 |
| DeepWalk | 行为图 | 发现深层关联 | 潜在兴趣挖掘 |
| 名称向量 | ES语义向量 | 语义理解强 | 文本相似推荐 |
| 图片向量 | ES视觉向量 | 视觉相似性强 | 外观相似推荐 |
更新频率建议
- 名称向量相似: 每周更新(商品名称变化少)
- 图片向量相似: 每周更新(商品图片变化少)
- Redis TTL: 30天(内容相似度变化慢)