ES_VECTOR_SIMILARITY.md 6.73 KB

ES向量相似度索引生成

概述

i2i_content_similar.py 脚本从Elasticsearch获取商品向量,计算并生成两种内容相似度索引:

  1. 基于名称文本向量的相似度 (i2i_content_name)
  2. 基于图片向量的相似度 (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", "on_sell_days_boost"]
  }
}

返回字段:

  • _id: 商品ID
  • name_zh: 中文名称(用于debug输出)
  • embedding_name_zh: 名称文本向量 (1024维)
  • embedding_pic_h14: 图片向量列表,每个元素包含:
    • vector: 向量 (1024维)
    • url: 图片URL
  • on_sell_days_boost: 上架天数提权值 (0.9~1.1)

3. KNN向量相似度查询

使用商品的向量查询相似商品:

名称向量查询:

{
  "knn": {
    "field": "embedding_name_zh",
    "query_vector": [向量值],
    "k": 100,
    "num_candidates": 200
  },
  "_source": ["_id", "name_zh", "on_sell_days_boost"],
  "size": 100
}

图片向量查询:

{
  "knn": {
    "field": "embedding_pic_h14.vector",
    "query_vector": [向量值],
    "k": 100,
    "num_candidates": 200
  },
  "_source": ["_id", "name_zh", "on_sell_days_boost"],
  "size": 100
}

4. 应用上架天数提权

对每个查询结果,应用 on_sell_days_boost 提权:

base_score = knn_result['_score']  # KNN基础分数
boost = knn_result['_source']['on_sell_days_boost']  # 提权值 (0.9~1.1)
final_score = base_score * boost  # 最终分数

提权说明:

  • on_sell_days_boost 是基于商品上架天数计算的提权因子
  • 取值范围: 0.9 ~ 1.1
  • > 1.0: 提权(新品或热门商品)
  • = 1.0: 不提权(正常商品)
  • 如果字段缺失或异常,默认使用 1.0(不提权)

5. 生成索引文件

输出两个文件到 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分钟

优化建议

如果性能不够:

  1. 批量处理: 使用ES的 _mget 批量获取向量
  2. 并发查询: 使用多线程/异步IO提高查询并发
  3. 增量更新: 只处理新增/更新的商品
  4. 缓存结果: 将ES向量缓存到本地,避免重复查询

ES向量字段说明

embedding_name_zh

  • 类型: dense_vector
  • 维度: 1024
  • 相似度: dot_product
  • 用途: 基于商品名称的语义向量

embedding_pic_h14

  • 类型: nested
  • 结构: json [ { "vector": [1024维向量], "url": "图片URL" } ]
  • 相似度: dot_product
  • 用途: 基于商品图片的视觉向量

on_sell_days_boost

  • 类型: float
  • 取值范围: 0.9 ~ 1.1
  • 默认值: 1.0
  • 用途: 基于上架天数的提权因子
  • 计算逻辑: 最终分数 = KNN分数 × on_sell_days_boost

注意事项

  1. 网络连接: 确保能访问ES服务器
  2. 权限: 确保ES用户有查询权限
  3. 向量缺失: 部分商品可能没有向量,会被跳过
  4. 向量格式: 图片向量是嵌套结构,取第一个图片的向量
  5. 自我排除: KNN结果会排除商品自己
  6. 提权应用: 所有相似度分数都已应用 on_sell_days_boost 提权
  7. 提权范围: boost值会被限制在0.9~1.1范围内,异常值使用1.0

故障排查

连接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天(内容相似度变化慢)