1. 项目背景与核心价值
去年帮学弟调试他的毕业设计时,我意外发现市面上80%的"电影推荐系统"作业都存在两个通病:要么是简单调用现成API的玩具项目,要么是算法与业务完全脱节的Demo。这个基于Django+协同过滤的实作方案,恰好解决了这两个痛点——它不仅包含完整的用户行为数据采集模块,更重要的是实现了可解释的推荐逻辑,这对计算机专业的学生理解推荐系统本质特别有帮助。
这个项目的独特之处在于:
- 采用经典的Item-CF算法但加入了时间衰减因子,避免"哈利波特效应"(热门物品长期霸榜)
- 前端用ECharts实现了推荐理由可视化,比如"因为你喜欢《盗梦空间》,所以推荐《源代码》"
- 预留了AB测试接口,方便对比不同算法的效果
- 数据库设计包含完整的用户画像维度(年龄/性别/地域)
提示:虽然项目文档中提供了默认电影数据集,但我强烈建议接入豆瓣API获取真实数据,这对理解数据清洗过程更有帮助。具体方法后文会详细说明。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术架构详解
2.1 整体架构设计
系统采用经典的三层架构,但有几个关键设计点值得注意:
code复制[客户端层]
├─ Vue.js + ElementUI (管理后台)
└─ Bootstrap (用户端)
[业务逻辑层]
├─ Django REST framework (API接口)
├─ 混合推荐引擎
│ ├─ 基于物品的协同过滤(主)
│ └─ 热门榜单(冷启动备用)
└─ 实时日志收集服务
[数据层]
├─ MySQL (用户数据/电影元数据)
├─ Redis (用户行为缓存)
└─ MongoDB (日志存储)
2.2 协同过滤算法实现
核心算法模块在recommend/engine.py中,主要包含三个关键函数:
python复制def calculate_similarity(items):
# 加入时间衰减因子的改进余弦相似度计算
time_decay = 1/(1 + math.log(time_interval + 1))
return adjusted_cosine(matrix) * time_decay
def generate_recommendations(user_id, top_n=10):
# 混合推荐策略:80%协同过滤 + 20%热门补全
cf_items = get_cf_items(user_id)
hot_items = get_hot_items()
return hybrid_sort(cf_items, hot_items)
def explain_recommendation(item_id):
# 可解释性增强:返回3个最相关的历史行为
return get_top_related_actions(user_id, item_id)
算法优化点包括:
- 相似度计算时排除共同评分少于5次的物品对
- 对近期行为赋予更高权重(最近一周行为权重=2)
- 使用Jaccard多样性系数防止推荐结果同质化
3. 关键模块实现
3.1 用户行为采集系统
在middleware/logging.py中实现的异步日志中间件是项目亮点:
python复制class UserActionMiddleware:
def __init__(self, get_response):
self.get_response = get_response
self.kafka_producer = KafkaProducer(
bootstrap_servers=['localhost:9092'],
value_serializer=lambda v: json.dumps(v).encode('utf-8')
)
def __call__(self, request):
# 记录页面停留时间等深度行为
if request.user.is_authenticated:
log_data = {
'user_id': request.user.id,
'url': request.path,
'timestamp': time.time(),
'ua': request.META.get('HTTP_USER_AGENT', '')
}
self.kafka_producer.send('user_actions', log_data)
return self.get_response(request)
注意:生产环境建议改用RabbitMQ替代Kafka,因为校园网环境下Kafka集群部署成本过高。我在测试时发现单机版Kafka在Windows开发机经常出现连接超时。
3.2 推荐结果可视化
前端采用ECharts实现的双维度分析图特别适合毕业答辩展示:
javascript复制// 在recommendation.vue中
function drawExplanationChart() {
const chart = echarts.init(this.$refs.chart)
chart.setOption({
radar: {
indicator: [
{ name: '类型相似度', max: 1 },
{ name: '导演重合度', max: 1 },
{ name: '演员关联度', max: 1 },
{ name: '评分接近度', max: 1 },
{ name: '年代相近度', max: 1 }
]
},
series: [{
data: [
{
value: [0.82, 0.65, 0.71, 0.88, 0.43],
name: '推荐关联度分析'
}
]
}]
})
}
4. 部署与调试技巧
4.1 开发环境快速搭建
使用我提供的docker-compose.yml可以一键启动所有依赖服务:
yaml复制version: '3'
services:
redis:
image: redis:alpine
ports:
- "6379:6379"
mongo:
image: mongo:4.4
volumes:
- ./data/db:/data/db
mysql:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: root
volumes:
- ./data/mysql:/var/lib/mysql
常见问题解决方案:
- 若遇到
mysqlclient安装失败,改用pymysql并在__init__.py中添加:python复制import pymysql pymysql.install_as_MySQLdb() - Django报
No module named 'goods'时,检查INSTALLED_APPS是否注册了所有子应用
4.2 性能优化实践
在settings.py中这些配置显著提升了我的测试结果:
python复制CACHES = {
'default': {
'BACKEND': 'django_redis.cache.RedisCache',
'LOCATION': 'redis://127.0.0.1:6379/1',
'OPTIONS': {
'CLIENT_CLASS': 'django_redis.client.DefaultClient',
'COMPRESSOR': 'django_redis.compressors.zlib.ZlibCompressor',
}
}
}
# 使用django-debug-toolbar时发现的分页优化
RECOMMENDATION_PER_PAGE = 10 # 超过20条会导致响应时间>500ms
5. 项目扩展方向
基于这个基础框架,我指导过的学生做过这些有趣变种:
- 跨域推荐:结合豆瓣读书数据实现"看过这本书的人也喜欢这些电影"
- 实时推荐:用WebSocket推送"正在观看本电影的用户还看了..."
- 社交化推荐:接入微信好友关系链做好友兴趣加权
- 冷启动优化:用电影海报CNN特征提取实现视觉相似推荐
对于想冲击优秀毕业设计的同学,我建议重点改造:
- 将算法部分抽象为gRPC微服务
- 增加推荐结果AB测试对比模块
- 用Django Channels实现实时点击反馈更新
这个项目最让我满意的设计是在recommend/utils.py中的评估模块,它可以直接输出算法指标的Markdown报告,这对毕业论文写作特别有用:
python复制def generate_report():
return f"""
## 算法评估报告
- 覆盖率: {coverage:.2%}
- 准确率: {precision:.2f}
- 多样性: {diversity:.2f}
- 新颖性: {novelty:.2f}

"""
最后分享一个调试技巧:当协同过滤推荐效果不理想时,先用manage.py shell手动检查相似度矩阵的计算结果,我经常发现是数据稀疏导致的问题,这时候需要适当调整min_common_users参数。
