1. 项目概述:当天气遇上算法穿搭
去年帮表妹改毕业设计时,发现她的穿搭推荐系统只会机械匹配温度区间。比如15-20℃永远显示"薄外套+牛仔裤",完全无视用户历史偏好。这促使我开发了这套融合协同过滤算法的智能推荐系统——它能记住你上次在18℃时选择了碎花裙配针织开衫,当下次遇到相似天气时,会优先推荐这类搭配方案。
这个Python项目核心在于用协同过滤算法搭建用户-服装的评分矩阵。比如用户A给"20℃+衬衫+阔腿裤"组合打了5星,当用户B的穿搭偏好与A相似时,系统就会在相近温度下优先推荐这个组合。实测表明,这种个性化推荐比传统规则匹配的点击率高47%。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 系统架构设计
2.1 技术栈选型对比
最初在Django和Flask间犹豫时,我做了组压力测试:用JMeter模拟100并发用户请求时,Flask的响应时间稳定在120ms左右,而Django达到200ms。考虑到毕业设计对轻量化的需求,最终选择Flask作为web框架。数据库方面,MySQL的json类型支持直接存储穿搭组合的图片路径和标签,比MongoDB的文档结构更符合我们的关系型数据需求。
踩坑记录:第一次用SQLAlchemy时没配置pool_recycle参数,导致MySQL八小时闲置后连接自动断开。后来在create_engine时添加
pool_recycle=3600才解决。
2.2 数据流设计
系统工作流程像条智能流水线:
- 爬虫模块每天6:00抓取中国天气网数据,用BeautifulSoup解析出未来三天的温度、湿度、紫外线指数
- 预处理模块将天气参数离散化为[炎热/温暖/凉爽/寒冷]等标签
- 推荐引擎实时计算两种结果:
- 基于内容的推荐:匹配当前天气标签下的高频穿搭
- 协同过滤推荐:用surprise库计算用户相似度,生成个性化方案
- 前端用ECharts同时展示两种推荐结果,用户评分数据通过AJAX异步回传
3. 核心算法实现细节
3.1 协同过滤的三层过滤网
第一层——用户相似度计算采用改进的皮尔逊系数:
python复制def pearson_sim(user1, user2):
# 找出共同评分过的穿搭组合
common_ratings = {item: (user1[item], user2[item])
for item in user1 if item in user2}
n = len(common_ratings)
if n == 0: return 0
# 计算加权相似度(温度接近的评分权重更高)
sum1 = sum2 = sum1_sq = sum2_sq = p_sum = 0
for item, (r1, r2) in common_ratings.items():
temp_diff = abs(item.temp - current_temp)
weight = 1 / (1 + temp_diff*0.1) # 温度差每增加1℃,权重降低10%
sum1 += weight * r1
sum2 += weight * r2
sum1_sq += weight * (r1 ** 2)
sum2_sq += weight * (r2 ** 2)
p_sum += weight * r1 * r2
num = p_sum - (sum1 * sum2 / n)
den = sqrt((sum1_sq - pow(sum1, 2)/n) * (sum2_sq - pow(sum2, 2)/n))
return num/den if den != 0 else 0
第二层——穿搭组合的时效性衰减因子:
python复制def time_decay(original_score, days):
return original_score * (0.95 ** days) # 每天衰减5%
第三层——天气突变补偿机制:当检测到温度骤降超过5℃时,自动提高保暖类服装的推荐权重。
3.2 冷启动解决方案
新用户会遇到经典的"鸡生蛋"问题——没有评分数据就无法推荐。我们采用混合策略:
- 前三次登录时强制要求对20套基础穿搭进行1-5星评分
- 结合用户注册时填写的性别、年龄生成初始特征向量
- 用LightFM库实现混合矩阵分解:
python复制model = LightFM(loss='warp-kos',
item_alpha=1e-6,
user_alpha=1e-6)
model.fit(interactions, # 用户-物品交互矩阵
user_features=user_features, # 年龄性别等
item_features=item_features, # 服装材质风格等
epochs=30)
4. 关键实现难点与突破
4.1 天气数据与穿搭的语义映射
最初直接用温度区间匹配服装,发现推荐结果机械呆板。后来引入多维天气标签体系:
mermaid复制graph TD
A[温度22℃] --> B{时间段}
B -->|早晨| C[加薄外套]
B -->|午后| D[短袖+防晒衣]
A --> E[湿度65%]
E --> F[透气面料]
A --> G[紫外线指数强]
G --> H[推荐UPF50+衣物]
这个映射关系存储在MySQL的weather_rules表,包含字段:
sql复制CREATE TABLE `weather_rules` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`temp_range` varchar(20) DEFAULT NULL COMMENT '如15-20℃',
`weather_condition` enum('sunny','rainy','snowy') DEFAULT NULL,
`clothing_tags` json DEFAULT NULL COMMENT '["layered","windproof"]',
`priority` tinyint(4) DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
4.2 实时推荐性能优化
当用户数突破1万时,发现推荐响应时间从200ms飙升到1.2s。通过以下措施优化:
- 用Redis缓存用户最近10次评分记录
- 预计算天气相似度矩阵(每6小时更新)
- 对稀疏矩阵采用CSR存储格式
优化前后对比测试结果:
| 测试场景 | 原方案耗时 | 优化后耗时 |
|---|---|---|
| 新用户冷启动 | 1200ms | 300ms |
| 活跃用户请求 | 800ms | 150ms |
| 极端天气突发请求 | 2000ms | 400ms |
5. 部署与调试实战
5.1 远程开发环境配置
用VSCode Remote-SSH连接阿里云学生服务器时,遇到Python环境冲突问题。正确配置流程:
- 在.ssh/config添加服务器配置:
code复制Host weather-rs HostName 121.40.xxx.xxx User root Port 22 IdentityFile ~/.ssh/aliyun_key - 安装Remote Development扩展包
- 创建容器化的开发环境:
dockerfile复制FROM python:3.8-slim RUN apt-get update && apt-get install -y \ libmysqlclient-dev \ gcc COPY requirements.txt . RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
重要提示:务必在flask.run()前添加
host='0.0.0.0'参数,否则远程无法访问。我曾因此浪费两小时排查网络问题。
5.2 微信小程序对接技巧
为了让推荐结果能推送到微信,需要处理三个关键点:
- 获取用户openid的授权流程改造:
javascript复制wx.login({ success(res) { if (res.code) { wx.request({ url: 'https://yourdomain.com/api/wxauth', data: { code: res.code } }) } } }) - 服务端解密用户信息时,注意替换过期的session_key
- 模板消息推送要遵守微信内容规范,避免使用"最佳"等绝对化用语
6. 效果评估与迭代方向
6.1 A/B测试设计
将用户随机分为两组:
- 对照组:仅接收基于天气规则的推荐
- 实验组:接收协同过滤推荐
两周后的数据对比:
| 指标 | 对照组 | 实验组 | 提升率 |
|---|---|---|---|
| 点击率 | 31% | 45% | +45% |
| 平均评分 | 3.8 | 4.2 | +10.5% |
| 收藏行为次数 | 56 | 89 | +58.9% |
6.2 未来优化方向
- 图像识别增强:用户上传穿搭照片自动提取服装属性
- 社交化推荐:接入好友关系链做群体偏好分析
- 实时天气预警:当检测到1小时内降雨概率>60%时,推送雨具提醒
这个项目让我深刻体会到:好的推荐系统应该像贴心的造型师,既懂天气变化,也了解你的审美偏好。现在表妹的毕设拿了优秀,而我们的算法还在持续学习更多穿搭智慧——或许下次该教它识别今年流行的克莱因蓝?
