作为一名在推荐系统领域摸爬滚打多年的工程师,我见过太多"纸上谈兵"的毕业设计项目。今天要分享的这个酒店推荐系统,是我指导过的一个真实本科毕业设计案例,它成功融合了机器学习算法与工程实践,最终获得了校级优秀论文奖。不同于市面上那些只跑通Demo就交差的毕设,这个项目从数据采集、特征工程到线上部署都经过了完整闭环验证。
为什么酒店推荐值得用机器学习来做?传统基于规则的推荐(比如按价格排序)存在三个致命缺陷:一是无法捕捉用户潜在偏好(比如某用户总选健身房好的酒店但从不主动筛选);二是难以处理多维特征组合(价格+位置+设施的综合考量);三是冷启动问题严重。而机器学习模型通过分析用户历史行为数据,能自动学习到"商务旅客偏好安静房间"、"家庭用户关注儿童设施"等隐藏规律。
这个项目的技术栈选择也很有代表性:
提示:选择Django而非Flask是因为毕业设计需要展示完整的MVC架构,且Admin后台能快速生成数据管理界面,方便答辩演示。
系统采用典型的三层架构,但针对推荐场景做了特殊优化:
code复制用户层
├─ 前端展示(Bootstrap)
├─ 交互逻辑(jQuery)
└─ 可视化(ECharts)
服务层
├─ 推荐API(Django REST)
├─ 用户认证(JWT)
└─ 日志收集(Celery)
数据层
├─ 特征存储(MySQL)
├─ 实时缓存(Redis)
└─ 模型文件(HDF5)
这种架构的优势在于:
推荐系统的核心在于数据流动效率。我们设计的流水线包含四个关键环节:
离线训练(每日凌晨执行)
在线推荐(实时响应)
python复制def recommend_hotels(user_id):
# 从Redis读取实时特征
user_features = redis.get(f'user:{user_id}')
# 加载预训练模型
model = load_model('xgb_20230515.h5')
# 生成推荐得分
scores = model.predict(user_features)
# 混合协同过滤结果
cf_scores = cf_model.recommend(user_id)
return hybrid_sort(scores, cf_scores)
反馈收集(异步处理)
AB测试(关键创新点)
酒店推荐的特征构建比想象中复杂,我们最终确定了7大类特征:
| 特征类型 | 示例字段 | 处理方式 |
|---|---|---|
| 用户静态特征 | 年龄、职业、会员等级 | One-Hot编码 |
| 用户动态特征 | 最近点击品类、价格敏感度 | 滑动窗口统计 |
| 酒店属性特征 | 星级、设施、位置评分 | 标准化处理 |
| 上下文特征 | 季节、节假日、当前城市 | 人工分段离散化 |
| 交互特征 | 用户-酒店历史评分 | 矩阵分解降维 |
| 交叉特征 | 商务客×会议室面积 | 特征积+分箱 |
| 图关系特征 | 相似用户偏好传播 | Graph Embedding > |
处理技巧:
我们对比了三种经典算法:
协同过滤(Surprise库实现)
python复制from surprise import SVD
from surprise import Dataset
from surprise.model_selection import cross_validate
data = Dataset.load_builtin('ml-100k')
algo = SVD(n_factors=100, n_epochs=20, lr_all=0.005, reg_all=0.1)
cross_validate(algo, data, measures=['RMSE'], cv=5, verbose=True)
XGBoost分类模型
python复制import xgboost as xgb
params = {
'max_depth': 6,
'learning_rate': 0.1,
'subsample': 0.8,
'colsample_bytree': 0.8,
'objective': 'binary:logistic',
'eval_metric': 'auc'
}
dtrain = xgb.DMatrix(X_train, label=y_train)
model = xgb.train(params, dtrain, num_boost_round=200)
Wide & Deep混合模型
最终采用XGBoost+协同过滤的混合方案,线上A/B测试显示CTR提升23.7%。
针对新酒店和新用户的冷启动问题,我们设计了三级降级策略:
新用户:
新酒店:
sql复制-- 计算酒店相似度
SELECT
h2.hotel_id,
AVG(similarity(h1.features, h2.features)) AS sim_score
FROM hotels h1, hotels h2
WHERE h1.hotel_id = [新酒店ID]
GROUP BY h2.hotel_id
ORDER BY sim_score DESC
LIMIT 10;
全局兜底:
为提高响应速度,我们采用以下优化手段:
特征缓存:
模型分片加载:
python复制# 按地域加载模型
def get_regional_model(city_code):
model_key = f'model_{city_code[:2]}'
if not cache.has_key(model_key):
with h5py.File(f'/models/{model_key}.h5', 'r') as f:
cache.set(model_key, pickle.load(f['model']))
return cache.get(model_key)
结果预计算:
使用ECharts实现三类核心图表:
用户偏好雷达图
javascript复制option = {
radar: {
indicator: [
{ name: '价格敏感度', max: 1},
{ name: '设施要求', max: 1},
{ name: '位置偏好', max: 1},
{ name: '服务重视', max: 1}
]
},
series: [{
data: [{
value: [0.7, 0.5, 0.9, 0.6],
name: '当前用户'
}]
}]
};
推荐多样性热力图
AB测试对比柱状图
除常规的准确率、召回率外,我们特别关注:
惊喜度(Serendipity)
多样性(Diversity)
python复制def diversity(recommendations):
categories = [h.category for h in recommendations]
return len(set(categories)) / len(categories)
商业价值
最终在测试集上达到:
在项目开发过程中,我们踩过几个典型的坑:
数据泄露问题
特征存储误区
模型更新策略
给后来者的建议:
这个项目的完整代码已整理成可运行的Docker镜像,包含预处理好的示例数据集,特别适合作为毕业设计的基础框架。如果需要进一步优化,可以考虑引入强化学习实现动态调参,或者用知识图谱增强推荐解释性。