news 2026/9/29 20:07:06

基于Hadoop+SpringBoot的健康饮食推荐系统设计与实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于Hadoop+SpringBoot的健康饮食推荐系统设计与实现

每年毕业季都会看到大量同学在选题和落地之间反复纠结,尤其是“大数据”方向的题目。要么是纯理论分析落到纸面上变成“PPT项目”,要么是技术栈堆得过高,答辩时连自己都解释不清楚。这次我拆解的这个题目——“基于Hadoop+SpringBoot的健康饮食推荐系统”,属于很典型的大数据离线处理 + 后端业务系统组合。它没有盲目追求实时计算这类高难度场景,而是把重心放在“数据仓库搭建、离线推荐计算、业务接口封装”这条完整链路上,非常适合用来展示大数据工程能力,同时又不会让自己陷进某个组件的泥潭里出不来。

这套方案的巧妙之处在于:它用Hadoop生态解决“数据存得下、算得动”的问题,用SpringBoot解决“业务能用、界面能看”的问题,再用推荐算法把两者串成一条有故事线的产品。换句话说,你既能讲清楚大数据平台怎么搭,又能演示一个完整的推荐闭环,这在毕业设计答辩里是很有竞争力的组合。

1. 项目整体设计与技术选型思路

1.1 需求拆解:健康饮食推荐到底要解决什么问题

很多同学看到“推荐系统”四个字,第一反应就是“我要写一个协同过滤算法”,然后一头扎进公式里,最后做出了一个“自己都不知道为什么推荐”的玩具。这个题目真正的核心需求并不是算法本身,而是**“用户特征—饮食数据—推荐结果”这三者之间的逻辑闭环**。

从实际使用场景出发,这个系统至少要完成四件事:

  • 用户管理:注册、登录、个人信息维护,其中身高体重、运动习惯、饮食禁忌这些字段必须得有,它们是后续推荐计算的输入基础。
  • 食材/菜品管理:维护一个食材营养数据库,包括热量、蛋白质、脂肪、碳水、维生素等关键营养指标,这是推荐系统的“物品”侧数据。
  • 用户行为采集:记录用户对菜品的浏览、收藏、评分、点餐记录,这些行为数据是协同过滤算法的“燃料”。
  • 推荐结果展示:根据用户画像和历史行为,在首页或专属推荐位展示“适合你”的菜品列表,并且附上推荐理由(比如“低脂高蛋白,适合减脂期”)。

这四件事拆分清楚后,你会发现技术选型就变得非常自然。Hadoop负责存行为日志和用户历史数据,Hive负责做离线清洗和特征计算,SpringBoot负责管理系统业务并提供推荐结果接口,前端则是常规的Vue/Thymeleaf页面。整个项目没有“为大数据而大数据”,每一步都有明确的数据流向支撑。

1.2 为什么是Hadoop+SpringBoot,而不是Spark+Flink

先回答大部分人的疑问:现在Spark这么火,为什么不直接用Spark做推荐?原因很现实——毕业设计要的是“可控”和“可讲”。Spark确实计算更快,但它带来的是更高的内存配置要求、更复杂的提交调度逻辑,以及和SpringBoot集成时更麻烦的生态连接。如果你只有一台8G内存的笔记本,跑一个Spark Streaming任务再开一个SpringBoot服务,很容易OOM,到时候光是调环境就要耗掉半个月。

Hadoop+Hive这条路虽然“土”一点,但有两个明显的优势。第一是稳定:HDFS存数据、Yarn管资源、Hive跑SQL,这套经典组合只要按照官方文档一步步配,几乎不会出幺蛾子。第二是好讲:答辩的时候,你可以清晰地说出“用户在页面上点击了一个菜品,这个行为通过日志落到了HDFS,第二天凌晨Hive定时任务清洗数据,计算出推荐列表更新到MySQL,用户再次登录时SpringBoot从MySQL里把推荐读出来”。一个完整的故事链,远胜于模糊的“我用Spark算了一下”。

SpringBoot在这个架构里的角色是“业务网关”。它不直接参与Hadoop的计算,而是负责用户请求接收、推荐结果查询、后台管理操作等常规Web功能。需要访问HDFS上的文件时,通过Hadoop Client API或者先让Hive把计算结果导出到MySQL再读,两种方式都很成熟,稳定性也有保障。

1.3 推荐算法选型:从“能跑”到“有说头”

推荐算法是这类系统的灵魂,也是答辩时老师最喜欢追问的部分。我不建议一上来就搞深度学习或者基于知识图谱的复杂推荐,因为数据量达不到,效果出不来,而且自己很难把原理讲透。**基于用户的协同过滤(UserCF)和基于物品的协同过滤(ItemCF)**是这个体量下最合适的两个算法。

具体选哪个,取决于你想强调的逻辑。如果系统强调“人以群分”——即根据相似用户的饮食偏好做推荐,那就选UserCF;如果强调“物以类聚”——即根据菜品本身的营养特征和共现规律做推荐,那就选ItemCF。我见过做得最聪明的实现是两者结合:先用ItemCF根据用户历史高评分菜品找出相似菜品,再用UserCF找相似用户爱吃但你还没吃过的菜品,最后把两部分结果按加权得分融合。这个方案在论文里可以写一章“融合推荐策略”,在答辩时也显得有层次。

关于冷启动问题,这几乎是必考题。解决方案也不复杂:新用户没有行为数据时,按照“国民膳食指南”的均衡营养标准推荐默认套餐(比如“低卡套餐”“高蛋白套餐”),同时用“热门菜品TopN”兜底;新菜品没有行为数据时,用内容属性(营养成分类似度)推荐给相关用户群。把这个逻辑讲清楚,老师的追问基本就能应付过去了。

2. 核心数据链路设计与关键模块实现

2.1 数据从哪来:日志埋点与数据集准备

任何推荐系统都依赖数据,而这个题目最容易让新手卡住的地方就是“我上哪儿找那么多用户行为数据”。这里提供三条可行的路径,优先级从高到低:

路径一:自建用户行为日志。在SpringBoot项目里加一个过滤器或拦截器,记录用户每次请求菜品详情的动作,输出为JSON格式的日志文件。日志内容包括:userId、itemId、actionType(view/favorite/score)、actionTime、scoreValue等字段。这个方案最推荐,因为它是你自己设计的埋点系统,和项目业务完全契合。

路径二:公开数据集迁移。网上有大量MovieLens、Amazon Review之类的公开推荐数据集,但直接用的时候要注意字段映射。比如MovieLens里的用户对电影评分,你需要加工成“用户对菜品评分”,把电影ID映射成你数据库里的菜品ID,并同时补充菜品的营养属性。这样做的好处是数据量大、算法效果好,坏处是答辩时容易被追问“数据来源是否真实”。

路径三:爬虫采集食谱平台数据。用爬虫去抓取一些公开的营养食谱网站数据,生成菜品库。但爬虫涉及robots协议和反爬策略,非技术风险可控,不过要控制爬取频率,同时注意素材版权的边界,建议只爬两三百条菜品基础信息作为种子数据即可,用户行为还是靠自己埋点。

实操中我建议“路径一 + 路径三”结合。菜品基础数据用爬虫+手工整理,用户行为数据靠系统运行时自己积累。为了让算法有充足数据可以跑,可以在开发阶段写一个模拟数据生成器,随机生成几百个用户、几千条行为记录,灌进数据库里验证推荐链路是否通畅。

2.2 离线数仓搭建:Hive表结构设计与ETL逻辑

数据到了HDFS之后,需要Like组织才能高效计算。我在这个项目里推荐分三层建表:ODS层(原始数据)、DWD层(清洗明细)、ADS层(应用汇总)。

ODS层就一张宽表,直接映射日志JSON,字段包括user_id、item_id、action_type、action_time、score_value、user_city、user_age_group等。这张表的价值是原样保存,方便排查数据和回溯。

DWD层要做的是:过滤异常数据(比如action_time为空、userId超出合理范围)、维度退化(把菜品名称、所属分类、热量等级关联进来)、事件统一(把actionType转换成标准枚举:1浏览、2收藏、3评分、4下单)。

ADS层就是面向应用的结果表,典型的如user_recommend表,结构可以是:

CREATE TABLE ads_user_recommend ( user_id STRING COMMENT '用户ID', recommend_list ARRAY<STRUCT<item_id:STRING, score:DOUBLE, reason:STRING>> COMMENT '推荐菜品列表', update_time STRING COMMENT '推荐生成时间' ) COMMENT '用户推荐结果表' PARTITIONED BY (dt STRING);

ETL调度我用的是Azkaban或Crontab,简单场景直接Linux定时任务跑HiveQL脚本就行,比如每天凌晨2点执行:

#!/bin/bash source /etc/profile hive -f /opt/data_etl/ods_to_dwd.sql hive -f /opt/data_etl/dwd_to_ads.sql

要注意的一点是,Hive的计算结果要同步到MySQL,SpringBoot才能快速读取。这里不建议在SpringBoot里直接用Hive JDBC,因为Hive查询响应速度太慢,可能秒级甚至分钟级。正确做法是:Hive计算完成后,用Sqoop把结果表导出,或者直接在脚本里调用MySQL JDBC把结果写入t_recommend_result表,业务系统只查MySQL。

2.3 推荐算法落地:从公式到Spark/Hive代码

推荐算法的核心计算可以放到Hive里用SQL表达一部分,比如计算菜品共现矩阵,“喜欢菜品A的用户也喜欢菜品B”这类逻辑,用SQL的count和join就能算出共现次数。但到了计算相似度权重、用户相似度矩阵这种更复杂的逻辑时,SQL会显得非常笨拙,此时建议把数据从Hive导出,用Spark任务(Python或Scala)计算,把结果回写Hive。

我以ItemCF算法为例,给出核心的伪代码逻辑,方便你理解计算流程:

# item_cf.py - 基于物品的协同过滤核心逻辑 # 输入:用户-菜品评分数据 (user_id, item_id, score) # 输出:菜品相似度字典 {itemA: {itemB: sim_score}} import math from collections import defaultdict def item_cf(user_item_scores): # 1. 构建用户-物品倒排表 item_users = defaultdict(set) for user_id, item_id, score in user_item_scores: item_users[item_id].add(user_id) # 2. 计算共现矩阵 co_occur = defaultdict(int) for item, users in item_users.items(): for u in users: for v in users: if u != v: co_occur[(item, v)] += 1 # 3. 计算相似度(余弦相似度简化版) item_sim = defaultdict(dict) for item, users in item_users.items(): for other_item in item_users: if item == other_item: continue common_users = co_occur.get((item, other_item), 0) if common_users == 0: continue sim = common_users / math.sqrt(len(item_users[item]) * len(item_users[other_item])) item_sim[item][other_item] = sim # 4. 按相似度排序,保留TopN for item, sims in item_sim.items(): item_sim[item] = dict(sorted(sims.items(), key=lambda x: x[1], reverse=True)[:10]) return item_sim

这段代码的核心思想很简单:如果两个菜品经常被同一批用户选择或评分,它们之间的相似度就高。这里用余弦相似度做标准化,避免高频菜品“以大欺小”。在实际的项目里还会加上时间衰减因子(越近的行为权重越高),以及用户活跃度惩罚(刷评分用户降权),这些细节都可以写进论文的“算法优化”小节里。

2.4 SpringBoot集成:接口开发与推荐结果展示

SpringBoot端要注意的是不要把Hadoop Client依赖直接打到Web项目的核心包里,否则会导致启动极其缓慢,而且多个Hadoop依赖的版本冲突会让人崩溃。正确做法是单独开一个hadoop-client模块,需要读取HDFS时再引入,主业务模块走MySQL。

用户端核心接口设计如下:

@RestController @RequestMapping("/api/recommend") public class RecommendController { @Resource private RecommendService recommendService; /** * 获取首页推荐列表 * GET /api/recommend/home?userId=1001&page=1&size=6 */ @GetMapping("/home") public Result<List<RecommendItem>> getHomeRecommend(@RequestParam Long userId, @RequestParam(defaultValue = "1") Integer page, @RequestParam(defaultValue = "6") Integer size) { List<RecommendItem> list = recommendService.getRecommendByUser(userId, page, size); return Result.success(list); } /** * 获取“为你定制”的每日套餐 * GET /api/recommend/daily?userId=1001&date=2025-05-20 */ @GetMapping("/daily") public Result<DailyPlan> getDailyPlan(@RequestParam Long userId, @RequestParam String date) { return Result.success(recommendService.generateDailyPlan(userId, date)); } }

推荐接口返回的数据结构里,除了菜品基本信息(名称、图片、热量、食材),强烈建议加上一个“推荐理由”字段。不要小看这个字段,它是项目实用性的最大证明。用户看到“根据你的低脂偏好,推荐这道鸡胸肉藜麦沙拉”和看到“推荐菜品编号23”,产品体验完全是两个级别。

3. 环境搭建与实操过程:从零到能跑

3.1 Hadoop集群搭建要点:伪分布式还是真集群

如果你的电脑内存低于16G,强烈建议只搭伪分布式模式,一个进程一个守护线程,跑通流程为上。如果组里有三台以上机器,可以搭一个真集群,这会成为答辩时展示“分布式部署能力”的加分项。

伪分布式搭建的关键配置文件如下。core-site.xml设置NameNode地址:

<configuration> <property> <name>fs.defaultFS</name> <value>hdfs://localhost:9000</value> </property> <property> <name>hadoop.tmp.dir</name> <value>/home/hadoop/tmp</value> </property> </configuration>

hdfs-site.xml设置副本数和NameNode目录:

<configuration> <property> <name>dfs.replication</name> <value>1</value> </property> <property> <name>dfs.namenode.name.dir</name> <value>file:///home/hadoop/hdfs/name</value> </property> <property> <name>dfs.datanode.data.dir</name> <value>file:///home/hadoop/hdfs/data</value> </property> </configuration>

特别提醒:伪分布式模式下dfs.replication必须设为1,否则副本数为默认3时DataNode会一直报块不足,磁盘空间也撑不住。

Hive的部署相对简单,用MySQL作为元数据库。在hive-site.xml里配置:

<property> <name>javax.jdo.option.ConnectionURL</name> <value>jdbc:mysql://localhost:3306/hive_meta?createDatabaseIfNotExist=true</value> </property> <property> <name>javax.jdo.option.ConnectionDriverName</name> <value>com.mysql.cj.jdbc.Driver</value> </property> <property> <name>datanucleus.schema.autoCreateAll</name> <value>true</value> </property>

这一步踩坑的概率极高,尤其是MySQL8.0+和Hive3.1.x的驱动兼容问题。如果启动Hive时报com.mysql.jdbc.Driver找不到,记得去检查驱动jar包有没有放进$HIVE_HOME/lib目录,以及驱动类名是com.mysql.cj.jdbc.Driver还是com.mysql.jdbc.Driver,版本不同类名不同。

3.2 SpringBoot接入Hadoop生态的几种方式

实际开发中SpringBoot并不需要频繁直接操作HDFS,更多是读取Hive算好的结果。但答辩或者功能演示时,可能会有“从HDFS下载日志文件”“查看HDFS上的数据文件”这类需求,所以还是要提供一个可用的接入方式。

第一种方式是引入Hadoop Client的Maven依赖,通过FileSystemAPI操作:

<dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-client</artifactId> <version>3.3.4</version> </dependency>

然后在代码里读取HDFS文件:

Configuration conf = new Configuration(); conf.set("fs.defaultFS", "hdfs://localhost:9000"); FileSystem fs = FileSystem.get(conf); Path path = new Path("/data/user_action/2025-05-20/action.log"); FSDataInputStream in = fs.open(path); BufferedReader reader = new BufferedReader(new InputStreamReader(in));

这种方式效率低、耦合高,我只建议把它放在一个独立的工具类里,给日志查看功能用。

第二种方式是远程执行Hive命令,通过Java调用HiveServer2的JDBC接口,但前面说了,不推荐高频调用。更好的做法是:Hive离线计算完结果,写回MySQL,SpringBoot只当MySQL的搬运工。很多同学觉得这样不够“大数据”,但我反而认为这恰恰是工程化的正确姿势。在线系统和离线系统解耦,各司其职,才是真实企业里的主流架构。

3.3 完整功能演示流程:数据->推荐->展示

为了让你对这个系统有个整体感知,我列一条完整的“黄金链路”。

  1. 用户登录系统,在“食材偏好”页面勾选了“低脂”“高蛋白”,同时设置每日目标摄入热量1800大卡。
  2. 用户浏览了几道菜品,对“香煎鸡胸肉”点了“喜欢”,对“红烧肉”点了“不喜欢”。此时SpringBoot后台日志分别记录了两条行为。
  3. 当天凌晨2点,Crontab触发Hive定时任务,读取昨天的全量行为日志,执行ETL清洗,再启动Spark任务计算ItemCF相似度矩阵,最终生成该用户的Top10推荐列表。
  4. 推荐列表通过Sqoop同步到MySQL的t_recommend_result表。
  5. 用户第二天打开首页,SpringBoot从MySQL查出推荐列表,前端以卡片形式展示,每张卡片附带“推荐理由”标签和“匹配度百分比”。
  6. 用户点进推荐菜品详情页,看到详细的营养解析,“为什么推荐给你”的算法逻辑说明(热度/相似度/偏好匹配),以及类似菜品推荐。

整个流程跑通后,录一个5分钟的演示视频,从数据源头到推荐结果完整串起来,答辩时直接展示这个视频,效果比你现场敲代码好得多。

3.4 项目代码结构规划

合理的工程结构能让答辩和毕业设计文档都更加分。这个项目的模块划分我建议这样:

health-diet-recommend/ ├── health-admin # 后台管理模块 ├── health-common # 公共工具类、统一返回结果 ├── health-recommend-core # 推荐算法核心模块(纯Java/Python计算逻辑) ├── health-user # 用户模块(注册、登录、画像) ├── health-data # 数据接入模块(日志采集、Hadoop/Hive交互) ├── health-web # 前端页面(Vue或Thymeleaf) └── sql/ # 建表语句和初始化数据

重点是health-recommend-core,这个模块一定要单独拆出来,不要和Web Controller混在一起。推荐算法后续要换模型时只改这个模块,其他模块完全不受影响。这样设计在论文里也有话可写——“系统采用模块化分层架构,降低耦合度,提升可扩展性”。

4. 常见问题与排查技巧实录

4.1 版本兼容性“全家桶”对照

做大数据项目的第一大坑就是版本兼容。我把一套验证过、能稳定运行的版本组合分享出来,记住这个组合能少掉很多头发:

组件推荐版本说明
JDK1.8大部分Hadoop组件对JDK11+兼容性不好
Hadoop3.3.4稳定,支持NameNode HA,文档丰富
Hive3.1.3搭配Hadoop3.x,元数据库用MySQL8.0
Spark3.2.1Scala 2.12,兼容Hive 3.x
Spring Boot2.7.x2.x系列稳定,和JDK8完美搭配
MySQL8.0.x注意驱动类名变化
Sqoop1.4.7新旧版本差异大,注意参数格式

Hadoop和Hive版本一旦不匹配,最常见的就是MetaException或者NullPointerException,根源多半是元数据库的schema版本和Hive代码不一致。遇到这个问题,直接去MySQL的hive_meta库看VERSION表,对比Hive官方对应版本号,不一致就升级或降级其中一个组件。

4.2 伪分布式环境下的内存与存储问题

我见过太多人在自己电脑上搭Hadoop,被内存和磁盘空间折磨疯。有两个最常见的错误。第一个是启动Hadoop后,NameNode一直处于SafeMode状态,日志提示空间不足。解决办法在hdfs-site.xml里调大:

<property> <name>dfs.namenode.safemode.threshold-pct</name> <value>0.999f</value> </property>

或者更直接的办法,检查dfs.datanode.data.dir指向的目录磁盘空间是不是不够了,用df -h看一眼,清出至少20G空间。

第二个是启动HDFS后DataNode启动失败,日志报Incompatible clusterIDs。原因是格式化NameNode之后,DataNode的数据目录还保留旧的clusterID。解决方法只有一条路:先停服务,把data目录清空,然后重新格式化NameNode,再启动。这个操作我写过无数次,每次都能救回来。

4.3 推荐效果排查:算法逻辑没错,但结果就是不对

新手最容易遇到的情况是:协同过滤代码逻辑看起来没问题,但推荐出来的菜品全是热门菜,完全没有个性化。这个问题几乎100%是因为数据分布不均匀——少数爆款菜品占据了绝大多数用户行为,导致相似度计算被“头部效应”主导。

解决办法有三个方向。第一:在相似度计算中加入惩罚因子,两个菜品共同被“非重度用户”选择时的权重应该更高,也就是对活跃度非常高的用户降权。第二:做去热门化处理,在读取训练数据时,过滤掉用户量超过阈值(比如500)的菜品。第三:推荐结果生成后做一个多样性重排,从Top20候选中强制按营养品类分散选取,确保用户看到的不全是荤菜或者全是面食。

另外要提醒的是,测试阶段要构造“边界用户”。我建议手造三个测试账号:一个全新用户(无行为),一个重度素食用户,一个健身高蛋白用户。分别查看推荐结果是否符合预期。如果新手用户拿到了和健身用户一样的推荐,说明冷启动的兜底逻辑没有生效,需要检查用户画像未命中时是否走了热门推荐分支。

4.4 答辩追问应对:怎么把“数据流”讲成故事

答辩时老师最常问的问题就三个,提前准备好就不会慌。

“为什么数据要经过Hive而不是直接写在MySQL里?”回答要点:用户行为数据是海量日志,MySQL存不下也查不动,Hive基于HDFS可以横向扩展存储,同时用SQL做批量清洗计算很高效。可以把MySQL理解成“超市收银台”,Hive是“后仓仓库”,收银台只放当天要卖的商品,仓库才能存全年的大量货品。

“推荐系统的准确率怎么评估?”这是一个好问题,如果确实没有做离线评测,就不要硬说“准确率很高”,而是坦诚回答:采用精确率(Precision)、召回率(Recall)、覆盖率(Coverage)三个指标和离线实验。比如预留20%的行为数据作为测试集,在剩余80%上训练模型,看推荐结果能否命中测试集里的菜品。简单的实验数据,算一算就能写在论文里。

“如果用户量扩大10倍,系统哪里会先崩?”这个问题考察你对架构瓶颈的判断。答:瓶颈最先出现在Hive离线计算任务(因为全量重算成本高),优化方向是把全量重算改成增量更新;其次是SpringBoot连接MySQL的连接池,可以扩容数据库连接上限和加Redis缓存热点推荐结果。这两个点能答出来,老师会觉得你是真做过系统设计的人。

5. 项目打磨与扩展建议

5.1 从“能用”到“好看”:推荐理由与前端展示的细节

一个毕业设计要拿高分,技术固然重要,但“演示效果”往往能带来超出技术本身的好感度。这里推荐做两个提升:

一是给推荐理由做规则标签。Spark算出的只是相似度得分,但对用户来说很抽象。你可以在生成推荐结果时写一个“理由生成器”,根据菜品属性标签(低脂、高蛋白、低碳水)和用户画像标签做匹配,输出“与你常吃的鸡胸肉沙拉食材相似”“满足你对低卡饮食的需求”“本周蛋白质摄入偏低,建议增加”这类文字说明,推荐温度瞬间拉满。

二是前端展示加一个营养成分雷达图。菜品详情页用ECharts画一个包含蛋白质、脂肪、碳水、维生素、矿物质五个维度的雷达图,让用户直观看到“这顿饭的营养结构”。这个小功能难度不高,但极大地提升了系统的完整度和“健康”主题的贴合度。

5.2 从“毕业设计”到“可扩展项目”:还能往哪些方向升级

如果时间富余,可以在当前基础架构上做一些低成本扩展,这些扩展点放在论文的“展望”章节里非常加分:

  • 引入实时热度统计:虽然离线推荐是主链路,但可以加一个简单的Flink或Spark Streaming任务,统计最近1小时热门菜品,叠加到推荐结果里,覆盖“突发兴趣”场景。
  • 用户画像升级:当前用户画像只是基础属性+行为标签,可以引入营养学知识库,根据用户的BMI、运动频次、慢性病史自动生成“饮食禁忌清单”,在推荐时做规则过滤。
  • 数据可视化大屏:做一个Hadoop集群数据监控大屏,实时展示HDFS存储量、DataNode节点状态、每日新增行为数据量、推荐任务执行时长。这个功能用来做答辩开场演示,效果非常震撼。

5.3 个人实操体会与建议

最后聊几句题外话。我接触过大量做这类题目的同学,发现最后拉开差距的往往不是技术能力,而是项目完整度和表达逻辑。技术能力再强,如果系统只能跑通一个单测用例,答辩也很难让人信服;反过来,一个逻辑清晰、数据流完整、演示流畅的项目,哪怕算法用的是最经典的协同过滤,也照样能拿高分。

我个人的建议是:不要把时间浪费在优化算法效果上,比如纠结相似度公式选皮尔逊还是Jaccard,机器跑出来的差别对你的成绩影响微乎其微。真正值得花时间的是三件事:第一,把数据流打通,让日志从产生到推荐结果展示的每个环节都能“可视化”;第二,把测试做足,至少要覆盖用户冷启动、无结果兜底、脏数据容忍等异常情况;第三,把演示脚本写好,用5分钟讲清楚“系统是什么、数据怎么走、推荐怎么算、结果怎么用”。

做出来一个项目只是第一步,把它讲成一个让人听得懂、信得过、觉得有价值的故事,才是毕业设计真正要训练的能力。这个健康饮食推荐系统,正好是一个练习这种能力的好载体。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/29 20:06:45

Clara BBS 怎么升级?覆盖文件 + 数据库升级的正确姿势

Clara BBS 升级只需两步&#xff1a;先完整覆盖上传新版本文件&#xff08;保留 config/、uploads/、content/plugins/ 等目录&#xff09;&#xff0c;再进后台「系统工具 → 数据库升级」执行一次增量 DDL&#xff0c;整个过程幂等可重复执行&#xff0c;不需要 Composer、不…

作者头像 李华
网站建设 2026/9/29 20:06:25

影刀RPA实操指南:企业年报与工商公示信息批量采集

影刀RPA实操指南&#xff1a;企业年报与工商公示信息批量采集 每个月要对账、审供应商、做背调的时候&#xff0c;最折磨人的就是打开国家企业信用信息公示系统&#xff0c;一家一家搜企业名称&#xff0c;等滑块验证码&#xff0c;再翻年报找股东和资产数据。三十家企业查下来…

作者头像 李华
网站建设 2026/9/29 20:05:12

HarmonyOS 7 局部深色主题终于跟到弹窗了,写死的文字颜色却可能看不见

HarmonyOS 7 局部深色主题终于跟到弹窗了&#xff0c;写死的文字颜色却可能看不见 页面中间是一块深色工具区&#xff0c;点开菜单却一直是浅色。升级target后菜单终于跟着变深&#xff0c;原来写死的深色文字又可能和背景挤在一起。这个变化不应简单归类成“主题坏了”&#…

作者头像 李华
网站建设 2026/9/29 20:04:42

智能体集群协同单视频流三维实时重构在园区安全生产巡检与隐患智能排查中的应用

智能体集群协同单视频流三维实时重构在园区安全生产巡检与隐患智能排查中的应用摘要传统园区安全生产巡检高度依赖人工现场巡查与二维视频监控体系&#xff0c;存在空间度量能力缺失、隐患定位精度不足、事件溯源困难、存量视频资源价值无法充分释放等行业痛点。本文以耿文海提…

作者头像 李华
网站建设 2026/9/29 20:04:39

太惊艳了!2 个让你的 Codex 狠狠省 Token 的开源项目,必须收藏!

哈喽&#xff0c;我是沐言Agent&#xff0c;又来给宝子们分享开源项目&#xff0c;我会从 AI 使用者和程序员的视角&#xff0c;给大家分享一些好用的开源工具&#xff0c;帮助打工人提升工作效率。Codex with ChatGPTCodex with ChatGPT 是一个把 ChatGPT 网页版接入 Codex 编…

作者头像 李华