ESP32静态对象存储:嵌入式应用平台的可靠基座
2026/10/31 17:25:23
校园餐饮服务是学生日常生活的重要组成部分,但传统餐饮模式存在选择单一、排队时间长、口味匹配度低等问题。基于Django框架和K-means算法的校园美食推荐系统,旨在通过数据驱动的方式优化餐饮体验,提升食堂运营效率与学生满意度。
将机器学习算法与校园场景结合,弥补传统推荐系统在高校餐饮领域的空白,为智慧校园建设提供实践案例。
Django框架结合K-means算法实现校园美食推荐系统,涉及前后端开发、数据处理及机器学习集成。以下是关键技术和工具:
scikit-learn实现K-means聚类算法,pandas和numpy处理数据预处理。joblib或pickle保存训练好的聚类模型,避免重复计算。该系统通过K-means分析用户行为模式,结合Django的高效开发能力,实现个性化美食推荐。
从数据库中获取用户历史订单数据,清洗并提取特征(如菜品类别、价格、评分等)。使用Django的ORM查询数据:
from django.db.models import Count from user.models import Order, FoodItem # 获取用户历史订单数据 def get_user_orders(user_id): orders = Order.objects.filter(user_id=user_id).select_related('food_items') return orders # 构建特征矩阵 def build_feature_matrix(): food_items = FoodItem.objects.all() features = [] for item in food_items: features.append([ item.category_id, # 类别特征 float(item.price), # 价格特征 item.avg_rating # 评分特征 ]) return np.array(features)使用scikit-learn实现K-means算法,对菜品进行聚类:
from sklearn.cluster import KMeans import numpy as np # 初始化K-means模型 def train_kmeans(feature_matrix, n_clusters=5): kmeans = KMeans(n_clusters=n_clusters, random_state=42) kmeans.fit(feature_matrix) return kmeans # 预测新菜品所属聚类 def predict_cluster(kmeans_model, new_item_features): cluster = kmeans_model.predict([new_item_features])[0] return cluster基于用户历史订单和聚类结果生成推荐:
# 获取用户偏好聚类 def get_user_preferred_clusters(user_id): orders = get_user_orders(user_id) clusters = [] for order in orders: for item in order.food_items.all(): features = [item.category_id, float(item.price), item.avg_rating] cluster = predict_cluster(kmeans_model, features) clusters.append(cluster) # 返回用户最常点的前3个聚类 from collections import Counter top_clusters = [c for c, _ in Counter(clusters).most_common(3)] return top_clusters # 生成推荐 def generate_recommendations(user_id, kmeans_model, n_recommendations=5): preferred_clusters = get_user_preferred_clusters(user_id) all_food_items = FoodItem.objects.all() # 筛选不属于用户已点过的菜品 ordered_items = set() for order in get_user_orders(user_id): ordered_items.update(order.food_items.all()) recommendations = [] for item in all_food_items: if item not in ordered_items: features = [item.category_id, float(item.price), item.avg_rating] cluster = predict_cluster(kmeans_model, features) if cluster in preferred_clusters: recommendations.append(item) # 按评分排序返回推荐结果 return sorted(recommendations, key=lambda x: x.avg_rating, reverse=True)[:n_recommendations]将推荐系统集成到Django视图中:
from django.http import JsonResponse from .recommendation import generate_recommendations def recommend_food(request): if not request.user.is_authenticated: return JsonResponse({'error': 'Authentication required'}, status=401) # 加载预训练的K-means模型 import joblib kmeans_model = joblib.load('kmeans_model.pkl') recommendations = generate_recommendations(request.user.id, kmeans_model) data = [{ 'id': item.id, 'name': item.name, 'price': str(item.price), 'rating': item.avg_rating } for item in recommendations] return JsonResponse({'recommendations': data})定期重新训练模型的Celery任务:
from celery import shared_task from .models import FoodItem from .recommendation import train_kmeans, build_feature_matrix @shared_task def retrain_kmeans_model(): feature_matrix = build_feature_matrix() kmeans_model = train_kmeans(feature_matrix) # 保存新模型 import joblib joblib.dump(kmeans_model, 'kmeans_model.pkl')该系统核心在于通过K-means聚类分析用户饮食偏好,基于聚类结果推荐相似菜品。注意需要定期更新模型以反映最新的菜品和用户行为数据。
数据库设计需围绕用户行为、菜品属性和聚类结果展开,核心表结构如下:
用户表(User)
user_id(PrimaryKey): 用户唯一标识username: 用户名password: 加密后的密码email: 用户邮箱preferences: JSON 字段,存储用户初始饮食偏好(如忌口、口味)菜品表(Food)
food_id(PrimaryKey): 菜品唯一标识name: 菜品名称price: 价格category: 分类(如快餐、面食)tags: JSON 字段,存储菜品特征(如辣度、甜度、热量)用户行为表(UserBehavior)
behavior_id(PrimaryKey): 行为记录IDuser_id(ForeignKey): 关联用户food_id(ForeignKey): 关联菜品rating: 评分(1-5分)timestamp: 行为时间戳聚类结果表(ClusterResult)
cluster_id: 聚类分组IDfood_ids: JSON 数组,存储该聚类下的菜品ID列表centroid: JSON 字段,存储聚类中心特征向量通过菜品特征(如价格、辣度、热量)构建特征向量,使用scikit-learn实现聚类:
from sklearn.cluster import KMeans import numpy as np # 示例:从数据库加载菜品特征 food_features = Food.objects.values_list('price', 'spicy_level', 'calories') X = np.array(list(food_features)) # 聚类(假设分为5类) kmeans = KMeans(n_clusters=5, random_state=42) kmeans.fit(X) # 保存聚类结果到数据库 for i in range(5): cluster_food_ids = Food.objects.filter( pk__in=np.where(kmeans.labels_ == i)[0] ).values_list('food_id', flat=True) ClusterResult.objects.create( cluster_id=i, food_ids=list(cluster_food_ids), centroid=kmeans.cluster_centers_[i].tolist() )def recommend_foods(user_id, top_n=5): user_prefs = calculate_user_preferences(user_id) # 自定义函数计算用户偏好 clusters = ClusterResult.objects.all() best_cluster = min(clusters, key=lambda c: np.linalg.norm(np.array(c.centroid) - user_prefs)) recommended = Food.objects.filter( food_id__in=best_cluster.food_ids ).exclude( userbehavior__user_id=user_id )[:top_n] return recommended单元测试
from django.test import TestCase from sklearn.metrics import silhouette_score class ClusteringTest(TestCase): def test_kmeans_output(self): X = np.random.rand(100, 3) # 模拟100个菜品特征 kmeans = KMeans(n_clusters=5).fit(X) self.assertEqual(len(np.unique(kmeans.labels_)), 5) self.assertGreater(silhouette_score(X, kmeans.labels_), 0) # 轮廓系数验证集成测试
性能测试
django-debug-toolbar监控推荐接口响应时间,确保在100ms内返回结果。StandardScaler),避免量纲影响聚类。