多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

基于SpringBoot+Vue与协同过滤算法的体育商品推荐系统实战解析

基于SpringBoot+Vue与协同过滤算法的体育商品推荐系统实战解析 做毕设选到这个题目算是选到了一条比较稳的路子。SpringBoot加Vue是目前Java Web毕设的绝对主流组合协同过滤算法又是推荐系统里最经典、最能讲出东西的技术点体育商品这个业务场景贴近生活数据也好造演示效果直观。无论从工作量、创新点还是答辩时的可讲性来看这个题目都挺合适。不过题目归题目真正动手的时候很多同学还是会在几个地方卡住协同过滤的代码到底怎么写、评分矩阵怎么构建、前后端怎么串起来、SQL脚本导进去报错怎么办。这篇文章我就按一个完整项目的实际开发顺序把这套体育商品推荐系统的核心设计和实现细节掰开揉碎讲清楚包括算法部分的数学原理和代码落地、数据库表结构设计、后端接口封装、Vue前端联调以及我实际跑项目时踩过的坑和总结的排查经验。项目里有的细节我会按常见的合理实践做补全说明方便你直接照着落地。1. 项目整体设计与技术选型思路1.1 为什么是这套技术栈组合先讲技术选型的逻辑。SpringBoot负责后端接口Vue负责前端页面MySQL存业务数据协同过滤算法跑推荐这套组合能成为毕设热门不是没道理的。从工作量角度看SpringBoot把SSM那一大堆繁琐的XML配置全部干掉一个启动类加几个注解就能把项目跑起来对时间紧张的大四学生来说非常友好。Vue这边官方脚手架帮你把工程化的事全解决了组件化开发让页面代码结构清晰而且网上Vue的教学资源铺天盖地遇到问题基本都能搜到答案。从答辩角度讲这套组合的技术覆盖面很合适。SpringBoot体现了后端开发的规范性和工程化能力Vue展示了现代前端开发的组件化思路MySQL考察了数据库设计基本功协同过滤算法提供了理论深度。老师问后端有东西可问问前端有东西可答问算法你有公式和代码撑着整个体系很完整。1.2 为什么推荐算法选协同过滤体育商品推荐场景用协同过滤其实比用内容推荐更合理。内容推荐需要给每个商品打标签、做特征工程比如跑鞋要标注缓震轻量透气这些属性篮球要标注室内室外7号标准这些规格这个特征工程的工作量非常大而且特征的主观性很强标注标准不好统一。协同过滤的思路完全不一样。它不需要理解商品本身是什么只需要知道谁买了什么或者谁给什么打了分。核心逻辑就一句话找到和你兴趣相似的人把他们喜欢而你没见过的商品推荐给你。这背后的假设是过去行为相似的用户未来的偏好也大概率相似。放到体育商品的场景里这个逻辑非常通顺。买过某款篮球鞋的人大概率也对同类型的球袜、护踝感兴趣经常购买羽毛球装备的用户群消费习惯和品牌偏好往往有很高的重叠度。这种基于用户行为的相似性挖掘比硬给商品打标签要自然得多。协同过滤还分基于用户和基于物品两种思路。基于用户的协同过滤找的是和你像的人基于物品的协同过滤找的是和你要的东西像的其他东西。对于毕设这个数据规模基于用户的协同过滤实现起来更直观推荐结果的解释性也更强所以我建议主体算法用UserCF同时可以在论文里提一句ItemCF作为对照分析。1.3 系统功能模块和数据流梳理整个系统我按角色拆成两个端普通用户端和管理员后台再加上一个独立的推荐引擎模块。用户端走正常电商流程注册登录、浏览商品、按分类或关键词搜索、查看商品详情、加入购物车、提交订单、对已购商品评价打分、查看系统给自己生成的个性化推荐列表。管理员后台负责商品上下架、库存修改、订单状态管理、用户管理、数据统计。推荐引擎模块是整个系统的亮点它读取用户的评价记录和订单历史经过协同过滤计算后生成推荐列表通过推荐接口暴露给前端。数据流的走向是这样的用户在页面上的浏览、收藏、购买、评价行为都会落库成为行为数据。推荐引擎定时或按需读取这些数据构建用户-商品评分矩阵计算用户间相似度生成TopN推荐列表。当用户进入推荐页面时前端调用推荐接口后端直接返回已经算好的结果。2. 协同过滤算法核心实现解析2.1 评分矩阵的构建思路协同过滤的第一步是把用户对商品的反馈转化成数值化的评分。体育商品平台上用户的显式反馈是打分评价比如买完一双跑鞋后给个4星或5星隐式反馈包括浏览记录、收藏行为、加购行为、下单行为这些没有明确分数但能反映兴趣强度。实际操作中我用了加权映射的思路处理隐式反馈。浏览一次计1分收藏一次计4分加入购物车计6分完成购买且不退货计10分显式评分则直接采用用户打的星数。这样每个用户对每个商品都能算出一个综合得分然后构建一个以用户ID为行、商品ID为列的评分矩阵。这个矩阵在代码里我建议用Map嵌套来实现外层Map的key是用户ID内层Map的key是商品IDvalue是评分值。虽然Java里没有像Python的pandas那样方便的矩阵库但用哈希表存储稀疏矩阵反而更节省内存因为实际场景中大部分用户只评价过少量商品矩阵是非常稀疏的。// 构建用户-商品评分矩阵 public MapLong, MapLong, Double buildUserItemMatrix() { MapLong, MapLong, Double matrix new HashMap(); // userBehaviorService.getUserBehaviorList()从数据库读取用户全部行为记录 ListUserBehavior behaviors userBehaviorService.getUserBehaviorList(); for (UserBehavior behavior : behaviors) { matrix.computeIfAbsent(behavior.getUserId(), k - new HashMap()) .put(behavior.getProductId(), behavior.getScore()); } return matrix; }评分矩阵的质量直接决定推荐效果。我在造数据阶段发现一个非常典型的问题如果所有用户的评分都集中在高分区间大家都是4到5分那算出来的相似度区分度很差推荐的个性化效果不明显。正确做法是模拟真实用户的打分习惯让一部分用户群体偏好高分一部分用户打分比较苛刻还有一部分用户只对特定品类打分。2.2 用户相似度计算余弦相似度实战有了评分矩阵下一步就是计算用户之间的相似度。最常用的方法是余弦相似度公式是$$sim(u, v) \frac{\sum_{i \in I_{uv}} r_{ui} \cdot r_{vi}}{\sqrt{\sum_{i \in I_u} r_{ui}^2} \cdot \sqrt{\sum_{i \in I_v} r_{vi}^2}}$$其中$I_{uv}$是用户u和用户v共同评价过的商品集合$I_u$是用户u评价过的商品集合$r_{ui}$是用户u对商品i的评分。直观理解就是把每个用户对商品的评分看成高维空间里的一个向量两个向量的夹角越小说明两个用户的兴趣方向越一致。打个比方把每个用户想象成拥有一张兴趣地图地图的维度是平台的每一个商品坐标值是对该商品的评分。两个用户的兴趣地图重叠度越高他们的口味就越接近。代码实现时有几个容易踩的坑。第一个坑是浮点数除法溢出如果计算出来的点积和模长都是0要判断共同评分商品数是否为0直接返回相似度0。第二个坑是性能问题用户数量到几百之后两两计算相似度是O(n²)的复杂度对毕设数据量问题不大但也要注意只在有共同评分商品的用户对之间计算可以先按共同商品做预筛选。public double cosineSimilarity(MapLong, Double user1Ratings, MapLong, Double user2Ratings) { SetLong commonItems new HashSet(user1Ratings.keySet()); commonItems.retainAll(user2Ratings.keySet()); if (commonItems.isEmpty()) { return 0.0; } double dotProduct 0.0; double norm1 0.0; double norm2 0.0; for (Long item : commonItems) { dotProduct user1Ratings.get(item) * user2Ratings.get(item); norm1 Math.pow(user1Ratings.get(item), 2); norm2 Math.pow(user2Ratings.get(item), 2); } if (norm1 0.0 || norm2 0.0) { return 0.0; } return dotProduct / (Math.sqrt(norm1) * Math.sqrt(norm2)); }还有一个进阶处理是均值中心化。有的用户天生评分宽松什么都给5分有的用户比较严格最多给3分。这种情况下直接用原始评分算相似度会把打分手松和打分手紧误判为兴趣不一致。解决办法是先把评分减去该用户的平均分再做余弦计算这样反映的就是评分相对于个人基准的偏移更贴近真实的兴趣差异。2.3 推荐生成与冷启动处理计算出目标用户和其他所有用户的相似度之后推荐生成分三步走。第一步选K个最相似的用户作为邻居。K值我实际测试下来取10到20效果比较稳定太小了推荐结果波动大太大了又会被兴趣泛泛的用户拉低精准度。第二步从这些邻居的评价商品里过滤掉目标用户已经买过或评价过的商品。第三步对候选商品按相似度加权计算预测评分$$pred(u, i) \frac{\sum_{v \in N_u} sim(u, v) \cdot r_{vi}}{\sum_{v \in N_u} |sim(u, v)|}$$这个公式的含义是邻居用户v对商品i的评分用v与目标用户u的相似度做权重加权平均后就是预测的目标用户对商品i的评分。最后按预测分从高到低排列取前N个商品作为推荐结果。冷启动问题在毕设里遇到的主要是两种情况。新用户没有任何行为数据算不出相似度我的处理方案是给这类用户推荐平台热度最高的商品也就是销量和评分综合排序靠前的爆款。新商品没有用户评价永远进不了推荐池处理方案是给商品列表里最新上架的商品一个短期的展示权重保证新品有曝光机会。3. 后端核心模块实操解析3.1 数据库表设计核心表结构数据库设计是整个后端的骨架。我按照项目功能拆了七张核心表每张表的字段设计都经过实际业务验证。用户表保存账号密码和基础信息密码用BCrypt加密存储绝对不能明文保存。商品表包含名称、分类、价格、库存、主图URL、详情描述、上架状态价格用decimal类型避免浮点精度问题。订单表和订单明细表是一对多的关系订单表记录整体状态明细表记录每个商品的下单快照包括商品名称、单价、数量这样即使商品信息后续改动历史订单也能完整还原。评价表是推荐系统的数据金矿字段包括用户ID、商品ID、评分、评语、评价时间并建立用户和商品两个维度的联合索引因为算法模块会频繁按用户或按商品查询评价记录。收藏表记录用户的收藏行为设计上做了唯一约束避免同一个用户重复收藏同一个商品。表格结构我整理出来表名核心字段关键说明sys_userid, username, password, nickname, avatar, role角色区分普通用户和管理员productid, name, category, price, stock, image, status商品上下架状态位ordersid, user_id, total_amount, status, create_time订单状态机流转order_itemid, order_id, product_id, product_name, price, count下单快照冗余字段commentid, user_id, product_id, rating, content评分范围为1到5favoriteid, user_id, product_id, create_time联合唯一约束categoryid, name, sort商品分类表SQL脚本导入的时候有一点要提醒MySQL的版本差异会导致建表语句报错。比如MySQL 8.0默认字符集是utf8mb4如果你的脚本里写的是utf8且包含表情符号数据会存储失败。日期字段建议直接用datetime类型配合DEFAULT CURRENT_TIMESTAMP比手动维护时间字段省心得多。我实际开发中就在这上面吃过亏建表时没指定字符集导入中文数据直接乱码排查了好半天。3.2 登录认证与接口统一返回结构后端接口设计我采用了标准的RESTful风格并做了一层统一返回结构。所有接口的响应体都是统一的Result对象包含code、message和data三个字段。code为200表示成功其他值表示各种业务异常或参数错误。这样前端Axios拦截器只需要判断一次code就能统一处理成功、失败、登录过期等所有情况。登录认证我用JWT方案实现。用户在登录接口提交用户名密码后端校验通过后生成一个带过期时间的token返回给前端前端把token存在localStorage里之后每个请求都在Header里带上。后端通过一个拦截器统一校验token的合法性如果token缺失或过期直接返回401状态码前端收到后自动跳转登录页。拦截器注册时有个坑要注意SpringBoot里如果你写了一个WebMvcConfigurer配置类不小心覆盖了addInterceptors方法容易把静态资源的放行配置搞丢导致前端上传的图片无法访问。我的做法是注册拦截器时明确排除登录接口、注册接口和静态资源路径。3.3 商品模块与订单闭环商品模块是比较标准的前后端CRUD重点在分页查询和条件筛选。我用了MyBatis Plus的LambdaQueryWrapper实现动态SQL根据前端传来的分类ID、价格区间、搜索关键词、排序方式等参数动态拼查询条件分页交给PageHelper或MyBatis Plus自带的分页插件处理。订单模块是整个业务闭环的关键。用户下单的流程是前端把购物车勾选的商品ID和数量提交到后端后端先查询商品当前库存锁定库存成功后才创建订单记录和订单明细。这个先查库再锁库的操作在并发量高的场景下会有超卖风险但毕设系统单机部署没有并发压力做好事务控制就行。整个下单过程用Transactional注解保证原子性任何一步失败都会整体回滚不会出现订单创建成功但库存没扣减的脏数据。3.4 推荐接口完整链路推荐接口是系统的核心功能整个链路从Controller到Service到算法组件我用一段代码串起来。Controller层提供一个简单明了的接口GET /api/recommend/{userId}?limit10返回推荐商品列表。Service层处理业务编排先查用户是否有足够的历史行为数据如果没有就直接走热门推荐逻辑如果有就调用协同过滤算法组件。算法组件内部完成评分矩阵构建、相似度计算、推荐列表生成的全部过程。RestController RequestMapping(/api/recommend) public class RecommendController { Resource private RecommendService recommendService; GetMapping(/{userId}) public ResultListProductVO getRecommendations( PathVariable Long userId, RequestParam(defaultValue 10) Integer limit) { ListProductVO list recommendService.getRecommendList(userId, limit); return Result.success(list); } }Service层有一个细节我特别提一下算法算出来的商品ID列表回查商品详情的时候要按推荐顺序返回不能再用数据库默认排序或者重新按商品表主键排序否则前端看到的推荐顺序和算法算出来的不一致。我处理的方式是查出商品列表后在内存里按推荐顺序做一次排序映射。4. 前端Vue实现要点与前后端联调4.1 前端登录态管理与路由守卫Vue前端这部分我建议用Vue CLI或者Vite初始化项目配合Vue Router和Vuex或Pinia做状态管理。项目结构上按模块划分views目录包括登录注册页、商品列表页、商品详情页、购物车页、订单页、推荐页、个人中心页后台管理页面单独放一个admin目录。前端登录态管理是一个容易出错的地方。用户登录成功后拿到token和用户信息token存localStorage做持久化用户信息存Vuex或Pinia做全局状态共享。路由守卫里做两层判断第一层是未登录用户访问购物车、订单、推荐等需要登录态的页面时强制跳转到登录页第二层是普通用户访问/admin路由时校验用户角色是否为管理员不是就提示无权限。// 路由守卫核心逻辑 router.beforeEach((to, from, next) { const token localStorage.getItem(token) if (to.meta.requiresAuth !token) { next({ path: /login, query: { redirect: to.fullPath } }) } else if (to.path.startsWith(/admin) localStorage.getItem(role) ! ADMIN) { next(/403) } else { next() } })实际开发中我发现一个体验细节路由守卫里做跳转时把用户想访问的原目标地址作为query参数传给登录页登录成功后用router.replace跳回原目标页这样用户登录后能直接回到之前想看的页面体验感提升很明显。4.2 Axios封装与跨域问题Axios封装的目标是让所有请求都自动带上token统一处理错误码并对响应数据做一层解包。我在项目的api目录下建了一个request.js通过拦截器实现这些逻辑。请求拦截器负责从localStorage取出token写到请求header里。响应拦截器处理两层逻辑第一次判断HTTP状态码网络层出错直接弹错误提示第二次判断业务状态码如果后端返回301或401这样的状态说明登录过期清掉本地登录态并跳转登录页。这里要注意响应拦截器和后端返回的code要配合好避免前端误判。跨域问题是前后端分离项目绕不开的经典问题。开发环境下我在Vue的vue.config.js里配置devServer代理把所有以/api开头的请求转发到SpringBoot的实际服务端口。生产环境部署时用Nginx做反向代理前端静态资源和后端接口统一走Nginx转发。这里有一个重点无论开发环境还是生产环境后端的接口URL都要写相对路径比如/api/xxx不要写死成http://localhost:8080/xxx否则换个环境部署就要改一大堆代码。4.3 推荐商品展示页面设计推荐页是整个毕设项目的展示亮点前端呈现效果直接影响答辩印象分。我的设计思路是做一个为你推荐专区页面顶部是横向滚动的热门推荐位展示平台最热门的几个商品大图。下面的推荐列表是协同过滤算法的结果用卡片式布局展示商品主图、名称、价格、推荐理由。这里有一个值得讲的小技巧推荐理由的文案可以做得更智能。后端返回推荐结果时同时返回推荐来源信息比如和你兴趣相似的用户都买了这款。前端根据这个字段渲染推荐理由比单纯展示商品信息更有说服力答辩时老师看到这个细节会认为你对推荐逻辑的理解比较到位。计算推荐接口里的推荐来源实现上也不复杂。算法生成推荐列表时对每个候选商品记录贡献最大的邻居用户最终返回结果里带上该邻居用户最近购买的同类型商品名作为推荐理由的语料。5. 环境配置、部署运行与常见问题排查5.1 开发环境版本匹配建议版本匹配问题看似简单实际上每年有大量同学在环境上浪费好几天时间。你要是完全按我的推荐配置来可以少走很多弯路。组件推荐版本不推荐版本与原因JDK1.8 或 11JDK 17以上搭配SpringBoot 2.x会报错SpringBoot2.3.x 或 2.7.x3.x必须配JDK 17且部分依赖不兼容MySQL5.7 或 8.05.5太老8.0需注意连接驱动版本Node.js14 LTS 或 16 LTS18配老版本node-sass会编译失败Vue CLI4.x5.x需搭配Node 12老电脑可能卡Maven3.63.8以下在某些仓库源有下载问题这里补充一个非常典型的坑。如果启动SpringBoot时遇到Caused by: java.lang.NoClassDefFoundError: javax/servlet/Filter这类报错十有八九是版本不匹配。SpringBoot 3.x把javax包全面换成了jakarta包依赖里还有旧包就会冲突。现实情况是网上能找到的教程和代码大多数是SpringBoot 2.x的所以我强烈建议选择2.x版本省心省力。5.2 SQL脚本导入与数据库连接配置拿到项目的SQL脚本后导入步骤有讲究。不要直接双击脚本用图形化工具打开再执行那样容易遇到编码问题。正确流程是先用命令行或图形化工具新建一个空数据库指定字符集为utf8mb4再选择导入脚本文件执行。导入成功后要立刻验证几个关键点用户表里有没有预设好的管理员账号和测试用户商品表数据是否完整外键关系是否正常。很多项目脚本里会自带初始数据这给你的演示环节提供了很大便利不需要自己再造数据。SpringBoot数据库连接配置有几个常见错误。第一是时区问题连接串里要加上serverTimezoneAsia/Shanghai否则会报The server time zone value错误。第二是SSL警告本地开发时连接串建议加上useSSLfalse消除多余的手动配置。第三是配置校验兜底如果输入了错误的数据库密码SpringBoot启动时会一直重试连接看起来像卡死实际上不是卡死而是密码错了。5.3 实际问题排查速查表这套系统运行阶段我把实际遇到的高频问题整理成一张速查表你在部署时可以直接对照排查。问题现象可能原因排查与解决方法后端启动失败报端口被占用8080端口被其他进程占用命令行执行netstat查看占用进程改配置文件端口或杀掉进程前端请求接口报跨域错误代理未生效或后端未配CORS开发环境检查vue.config.js代理配置是否正确登录后请求接口返回401JWT过期或token未带在Header检查前端请求拦截器是否把token拼进headerSQL导入中文乱码脚本文件编码或数据库字符集不是utf8mb4重建数据库并指定字符集脚本另存为UTF-8启动后首页白屏前端路由模式history导致刷新404改为hash模式或在Nginx配置try_files回退index.html明明有商品但推荐结果为空用户无行为数据走了冷启动逻辑检查用户操作记录造几条行为数据再测试算法计算结果与预期不符评分矩阵构建遗漏了某类行为打印矩阵调试定位缺失数据的用户行为类型6. 实测效果与答辩准备建议6.1 项目演示路线规划系统做完以后演示顺序也是有讲究的好的演示节奏能让老师清晰看到你的工作量和技术亮点。我的建议演示路线是先走一遍完整的用户购物流程从注册登录开始浏览商品、搜索关键词、加购物车、下单支付这展示了基本功能的完整度和前后端联调能力。然后切换到管理员账号演示商品管理和订单管理功能展示后台数据维护能力。最后是重头戏推荐功能用事先准备好行为数据的测试账号登录进入推荐页展示个性化推荐结果。展示推荐效果时有一个技巧能让演示效果翻倍。提前准备两个行为数据差异非常大的测试账号一个喜欢篮球类装备一个喜欢跑步类装备演示时切换两个账号分别展示推荐页推荐结果是两种完全不同的商品列表这个对比效果比任何口头讲解都有说服力。老师一眼就能看出推荐算法是真正在起作用而不是随便拉个热门榜单糊弄。为了做到这一点我在造数据阶段就刻意设计了两类用户的评分行为。篮球爱好者账号集中评价篮球、球鞋、护具类商品跑者账号集中评价跑鞋、压缩袜、运动手表和能量补给类商品而且评分分布在3到5分之间保持一定的个性化差异。6.2 答辩常问问题准备答辩环节老师最常问的问题集中在三个方面协同过滤原理、数据冷启动、推荐效果评估。原理方面老师可能会问你基于用户和基于物品的协同过滤区别你要能清晰讲出两者在适用场景上的差异并解释为什么体育商品场景适合所选方案。冷启动问题是老师必问的高频题需要准备两个维度的对策。用户冷启动解释你如何处理没有任何行为记录的新用户我的方案是基于热度和分类偏好做默认推荐。商品冷启动解释新上架商品怎么获得曝光我的方案是给新品一段时间的加权展示权重。这两个方案都很务实在真实的电商系统里也是这么处理的。推荐效果评估这块很多同学没有准备被问到容易卡壳。你可以讲自己做过的离线实验留出一部分用户的评分数据做测试集基于剩余数据推荐计算推荐列表命中测试集商品的比例也就是命中率指标。毕设阶段不需要做复杂的精确率和召回率实验但你要能描述清楚这个评估思路证明你对推荐效果能不能量化这个问题有思考。6.3 论文写作与配图思路论文结构按标准的毕设论文框架来组织摘要、绪论、需求分析、系统设计、系统实现、系统测试、总结与展望。关键是把协同过滤算法这部分写深写透包括算法原理、公式推导、代码实现细节和实验结果分析这部分是你论文的主要创新点和得分点。论文插图建议画三张核心图一张是系统整体架构图展示前后端分离架构和推荐引擎的模块关系一张是推荐算法流程图从获取用户行为数据到生成推荐结果的完整流程一张是数据库ER图展示七张核心表之间的关系。这三张图画清楚整个论文的体系感立刻就出来了。我个人的建议是论文里公式不要只贴一个余弦相似度公式就完事把评分矩阵构建公式、相似度加权预测公式、冷启动策略都写清楚保持公式的连贯性。哪怕推导过程比较简单也要展示完整的算法流程这会明显提升论文的专业观感。这里还要提醒一点论文中的测试章节不要只写系统正常运行响应时间在可接受范围内这样的空话要把测试用例和测试数据写具体比如构造了什么特征的用户数据做推荐测试期望的推荐结果是什么实际的推荐结果是什么对比说明算法是否符合预期。7. 封板前的一些实操经验补充老实说我自己第一次跑通这套系统的时候也折腾了不少时间有几个细节我觉得值得单独拿出来再念叨一遍。第一是造数据这个环节提示一下不要偷懒。协同过滤推荐的效果极度依赖用户行为数据的质量和数量如果你只有三五个用户、每个用户评过一两个商品推荐结果大概率很随机。我当时一次性造了20个测试用户、每个用户至少对10个商品有过行为数据推荐结果才开始展现出明显的个性化差异。造数据不是浪费时间它是算法效果的基础保障。第二是算法组件的日志输出建议加上调试信息。我在协同过滤算法里打印了相似度最高的几个邻居用户ID和相似度值以及最终推荐列表的生成过程。调试的时候这些日志帮了大忙算法有问题一眼就能从日志里看出来不用反复打断点排查。第三是前端推荐页的加载体验这里有个细节值得优化接口性能。协同过滤算法目前是纯Java内存计算数据量小的时候毫秒级就出结果了实时响应没有问题。但如果未来数据量扩大这个方案就会响应变慢。扩展思路上可以改成定时把推荐结果算好存进数据库用户请求推荐页时后端直接查表返回响应速度能提升不少。这种离线计算的架构思路在答辩时主动提出来是很好的加分项。第四是扩展方向在你把基础功能都做完、时间还有富余的情况下可以动手升级一下推荐效果。给体育商品补上品类标签和属性标签在协同过滤的基础上混入一小部分基于内容的推荐结果组成混合推荐策略能明显改善新用户和新商品的冷启动问题。这块内容加到论文里属于系统优化与改进章节的扎实内容比空谈展望强得多。最后再补一句心里话做这个项目代码部分其实只是整个流程的一部分把每个模块之间的数据流理顺、把推荐算法的为什么这么选想清楚、把演示环节打磨流畅这些才是让这个毕设真正脱颖而出、经得起老师提问的关键。你可以把整个项目当成一个真实产品来做而不只是一个应付毕业设计的作业这样你的收获会远超一个通过的成绩。
返回列表