1. 项目概述与核心价值
超市商品推荐系统是电商领域提升用户体验和销售额的关键技术方案。这个基于Python+Django+Vue3的协同过滤推荐系统,通过分析用户历史行为数据,为每位顾客提供个性化的商品推荐。不同于传统超市的"一刀切"促销方式,这种智能推荐能有效提高转化率30%以上。
我在实际零售系统开发中发现,优秀的推荐系统需要平衡三个核心要素:推荐准确度、系统响应速度和可解释性。本方案采用前后端分离架构,后端使用Django处理复杂的推荐算法逻辑,前端用Vue3构建动态交互界面,既保证了计算效率,又提供了流畅的用户体验。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术栈选型解析
2.1 后端技术栈
Django作为Python最成熟的Web框架,其ORM系统能高效处理商品和用户关系数据。特别在零售场景中,Django的模型关联特性可以优雅地表达"用户-商品-评分"这种多对多关系:
python复制class User(models.Model):
username = models.CharField(max_length=100)
class Product(models.Model):
name = models.CharField(max_length=200)
price = models.DecimalField(max_digits=10, decimal_places=2)
class Rating(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
product = models.ForeignKey(Product, on_delete=models.CASCADE)
score = models.IntegerField()
timestamp = models.DateTimeField(auto_now_add=True)
提示:为提升查询性能,建议在Rating模型的user和product字段上建立复合索引,这在用户行为数据量大的场景下尤为关键。
2.2 前端技术栈
Vue3的组合式API相比选项式API更适合处理复杂的推荐界面交互。例如在商品推荐组件中,我们可以用setup()函数清晰地组织逻辑:
javascript复制import { ref, onMounted } from 'vue'
import { fetchRecommendations } from '@/api/recommend'
export default {
setup() {
const recommendations = ref([])
const loading = ref(true)
onMounted(async () => {
try {
const { data } = await fetchRecommendations()
recommendations.value = data
} finally {
loading.value = false
}
})
return { recommendations, loading }
}
}
2.3 协同过滤算法选型
在超市场景中,我推荐采用基于物品的协同过滤(Item-CF),因为:
- 超市商品相对稳定,物品相似度矩阵可以离线计算
- 用户可能同时购买多个商品,物品共现模式明显
- 计算复杂度与用户数无关,适合用户量大的场景
3. 系统架构设计
3.1 数据流设计
系统采用分层架构处理推荐流程:
- 数据采集层:收集用户浏览、购买、评分等隐式/显式反馈
- 特征工程层:构建用户-物品交互矩阵,处理数据稀疏性
- 算法层:计算相似度并生成推荐结果
- 服务层:通过REST API提供推荐服务
- 展示层:Vue3动态渲染推荐结果
3.2 数据库设计
针对超市场景优化的数据库表结构:
python复制class SupermarketProduct(models.Model):
barcode = models.CharField(max_length=20, unique=True)
category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True)
price = models.DecimalField(max_digits=8, decimal_places=2)
# 添加商品特征字段便于后续算法扩展
is_fresh = models.BooleanField(default=False)
is_discount = models.BooleanField(default=False)
class UserBehavior(models.Model):
BEHAVIOR_TYPES = (
('view', '浏览'),
('cart', '加购'),
('buy', '购买'),
('fav', '收藏'),
)
user = models.ForeignKey(User, on_delete=models.CASCADE)
product = models.ForeignKey(SupermarketProduct, on_delete=models.CASCADE)
behavior_type = models.CharField(max_length=10, choices=BEHAVIOR_TYPES)
weight = models.FloatField(default=1.0) # 行为权重
created_at = models.DateTimeField(auto_now_add=True)
4. 协同过滤算法实现细节
4.1 相似度计算优化
传统余弦相似度在超市场景的改进方案:
python复制def improved_cosine_sim(item1, item2, behavior_data):
"""考虑行为类型权重的改进相似度计算"""
common_users = set(behavior_data[item1].keys()) & set(behavior_data[item2].keys())
if not common_users:
return 0
vec1 = []
vec2 = []
for user in common_users:
# 根据行为类型赋予不同权重
vec1.append(behavior_data[item1][user]['weight'])
vec2.append(behavior_data[item2][user]['weight'])
# 添加时间衰减因子
time_decay = 1 / (1 + abs(behavior_data[item1][user]['time'] - behavior_data[item2][user]['time']))
return (1 - cosine(vec1, vec2)) * time_decay
4.2 推荐结果生成
python复制def generate_recommendations(user_id, top_n=10):
# 获取用户最近交互的20个商品
user_items = get_user_recent_items(user_id, limit=20)
# 初始化推荐池
recommendation_pool = defaultdict(float)
for item_id, _ in user_items:
# 获取相似商品
similar_items = get_similar_items(item_id, top_k=50)
for similar_item, similarity in similar_items:
# 排除用户已经交互过的商品
if not has_interacted(user_id, similar_item):
# 综合相似度和商品热度
recommendation_pool[similar_item] += similarity * get_item_popularity(similar_item)
# 混合策略:70%协同过滤结果 + 30%热门商品
final_recommendations = []
cf_items = sorted(recommendation_pool.items(), key=lambda x: x[1], reverse=True)[:top_n*2]
hot_items = get_hot_items(top_n)
# 按比例混合结果
cf_ratio = 0.7
hot_ratio = 0.3
for i in range(top_n):
if i < int(top_n * cf_ratio) and i < len(cf_items):
final_recommendations.append(cf_items[i][0])
else:
if hot_items:
final_recommendations.append(hot_items.pop(0))
return final_recommendations[:top_n]
5. 性能优化实战
5.1 离线计算策略
超市推荐系统的性能瓶颈通常在相似度计算环节。我们采用以下优化方案:
- 定时任务:每天凌晨计算商品相似度矩阵
- 增量更新:每小时更新新用户行为的相似度影响
- 分区存储:按商品类别分区存储相似度结果
python复制# 在settings.py中配置Celery定时任务
CELERY_BEAT_SCHEDULE = {
'compute-item-similarities': {
'task': 'recommend.tasks.compute_item_similarities',
'schedule': crontab(hour=3, minute=30), # 每天3:30执行
},
'update-recent-similarities': {
'task': 'recommend.tasks.update_recent_similarities',
'schedule': crontab(minute='*/30'), # 每30分钟执行
},
}
5.2 缓存策略设计
采用多级缓存提升响应速度:
- Redis缓存热门推荐结果(5分钟过期)
- Memcached缓存个性化推荐结果(1小时过期)
- 本地内存缓存高频访问商品数据
python复制def get_cached_recommendations(user_id):
cache_key = f'rec:{user_id}'
# 先尝试从Redis获取
recommendations = cache.get(cache_key)
if recommendations is None:
# 缓存未命中,从数据库生成
recommendations = generate_recommendations(user_id)
# 存入缓存,设置1小时过期
cache.set(cache_key, recommendations, timeout=3600)
return recommendations
6. 前端交互优化
6.1 推荐结果展示
Vue3实现带视觉吸引力的商品卡片组件:
vue复制<template>
<div class="recommendation-container">
<h3>为您推荐</h3>
<div v-if="loading" class="loading-spinner">
<i class="fas fa-spinner fa-spin"></i>
</div>
<div v-else class="product-grid">
<div
v-for="product in recommendations"
:key="product.id"
class="product-card"
@click="viewProduct(product.id)"
>
<img :src="product.image" :alt="product.name" />
<div class="product-info">
<h4>{{ product.name }}</h4>
<p class="price">{{ formatPrice(product.price) }}</p>
<div class="actions">
<button @click.stop="addToCart(product)">
<i class="fas fa-cart-plus"></i>
</button>
<button @click.stop="toggleFavorite(product)">
<i :class="['far', 'fa-heart', { 'fas': product.is_favorite }]"></i>
</button>
</div>
</div>
</div>
</div>
</div>
</template>
6.2 实时反馈收集
通过自定义事件收集用户交互数据:
javascript复制// 在商品卡片组件中
const emit = defineEmits(['interaction'])
const handleInteraction = (type, product) => {
emit('interaction', {
type,
productId: product.id,
timestamp: Date.now()
})
// 实时调整推荐结果
if (type === 'purchase') {
fetchNewRecommendations()
}
}
7. 部署与监控
7.1 生产环境部署
推荐使用Docker Compose编排服务:
yaml复制version: '3.8'
services:
web:
build: .
command: gunicorn supermarket.wsgi:application --bind 0.0.0.0:8000
volumes:
- .:/code
ports:
- "8000:8000"
depends_on:
- redis
- db
redis:
image: redis:alpine
ports:
- "6379:6379"
db:
image: postgres:13
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:
7.2 监控指标设计
关键监控指标应包括:
- 推荐点击率(CTR)
- 推荐转化率
- 算法响应时间
- 冷启动比例
- 推荐多样性指标
python复制# 在Django中埋点采集指标
class RecommendationMetricsMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
if request.path.startswith('/api/recommend'):
user_id = request.user.id
rec_ids = extract_recommendation_ids(response)
# 记录曝光日志
log_exposure(user_id, rec_ids)
# 定时批量上报到分析系统
if random.random() < 0.1: # 采样率10%
async_log_to_analytics({
'user_id': user_id,
'rec_ids': rec_ids,
'timestamp': time.time()
})
return response
8. 常见问题与解决方案
8.1 冷启动问题
超市新商品解决方案:
- 基于商品类目进行相似推荐
- 使用商品基础属性(价格区间、品牌等)计算相似度
- 混合热门商品作为兜底
python复制def cold_start_recommendations(product_id):
# 获取商品类目
product = SupermarketProduct.objects.get(pk=product_id)
# 同类目商品
same_category = SupermarketProduct.objects.filter(
category=product.category
).exclude(
pk=product_id
).order_by('-sales')[:10]
# 相似价格带商品(±20%)
price_lower = product.price * 0.8
price_upper = product.price * 1.2
similar_price = SupermarketProduct.objects.filter(
price__gte=price_lower,
price__lte=price_upper
).exclude(
pk=product_id
).order_by('-sales')[:10]
# 合并结果并去重
recommendations = list({p.id: p for p in chain(same_category, similar_price)}.values())
return recommendations[:5]
8.2 数据稀疏性问题
用户-商品交互矩阵通常非常稀疏,我们采用以下策略:
- 行为权重分配:购买=5分,加购=3分,浏览=1分
- 时间衰减:最近行为权重更高
- 商品属性补充:当交互数据不足时,使用商品属性相似度
python复制def get_user_item_matrix():
"""构建带权重的用户-物品矩阵"""
behaviors = UserBehavior.objects.select_related('user', 'product')
matrix = defaultdict(dict)
for behavior in behaviors:
weight = {
'buy': 5,
'cart': 3,
'view': 1
}.get(behavior.behavior_type, 1)
# 时间衰减因子 (最近30天内的行为保持全权重)
days_ago = (timezone.now() - behavior.created_at).days
time_decay = max(0.1, 1 - days_ago/30)
matrix[behavior.user_id][behavior.product_id] = weight * time_decay
return matrix
9. 项目扩展方向
9.1 多算法融合
在实际应用中,可以结合多种推荐算法:
- 协同过滤:基于用户行为
- 内容过滤:基于商品特征
- 时序模型:考虑购买周期
- 图算法:构建用户-商品关系图
python复制class HybridRecommender:
def __init__(self):
self.cf_recommender = CollaborativeFiltering()
self.content_recommender = ContentBased()
self.temporal_model = TemporalModel()
def recommend(self, user_id, top_n=10):
# 各算法结果
cf_recs = self.cf_recommender.recommend(user_id, top_n*2)
content_recs = self.content_recommender.recommend(user_id, top_n*2)
temporal_recs = self.temporal_model.recommend(user_id, top_n)
# 融合策略
combined = []
combined.extend([(item, score*0.5) for item, score in cf_recs])
combined.extend([(item, score*0.3) for item, score in content_recs])
combined.extend([(item, score*0.2) for item, score in temporal_recs])
# 去重并排序
final_recs = {}
for item, score in combined:
if item not in final_recs or score > final_recs[item]:
final_recs[item] = score
return sorted(final_recs.items(), key=lambda x: x[1], reverse=True)[:top_n]
9.2 实时推荐系统
使用Kafka构建实时推荐流水线:
- 用户行为实时采集
- Flink实时计算特征
- 在线模型预测
- Redis存储实时推荐结果
python复制# Django消费者示例
from kafka import KafkaConsumer
import json
consumer = KafkaConsumer(
'user_behavior',
bootstrap_servers=['kafka:9092'],
value_deserializer=lambda m: json.loads(m.decode('utf-8'))
)
for message in consumer:
behavior = message.value
# 实时更新用户特征
update_user_profile(behavior['user_id'], behavior)
# 触发实时推荐更新
if behavior['type'] in ['purchase', 'cart']:
update_realtime_recommendations(behavior['user_id'])
在开发这类系统时,我发现最大的挑战不是算法实现,而是如何在保证推荐质量的同时处理高并发请求。一个实用的技巧是采用"预计算+实时修正"的策略 - 提前为每个用户计算好基础推荐列表,当用户有新行为时,只需对预计算结果进行小范围调整,这能大幅降低实时计算压力。
