毕设题目写着“Python+Django考研院校推荐系统、考研分数线预测系统”的同学,这两年我见得特别多。原因很简单:这个题目技术栈主流、应用场景接地气、算法部分可深可浅,更重要的是它天然自带“数据分析+推荐算法+Web开发”三块内容,答辩的时候能聊的东西非常多。很多同学拿到题目之后最先问我的不是系统怎么做,而是这套东西到底要包含哪些模块、推荐和预测到底用什么算法才能过审。这篇文章我就按我实际带项目的经验,把这个题目从设计思路、数据库建模、算法实现到Django落地、论文撰写完整拆一遍。内容偏实操,代码直接可用,适合正在做毕设或者想拿这个题目练手的同学参考。
1. 一个毕设题目为什么能火:先搞清楚你做的到底是什么
很多同学看到题目里的“考研院校推荐系统”和“考研分数线预测系统”第一反应是慌,觉得自己要造一个“考研版知乎”或者“志愿填报助手”出来。其实不是,这类毕业设计题目的本质,是把你学过的数据库、算法、Web框架、数据处理这几门课串起来,做成一个能演示、能讲出逻辑的完整应用。两个系统不是要求你做得像商业产品那么庞大,而是要求你做到“逻辑闭环”:有人能注册登录、有学校数据可查、推荐结果能解释、预测数值能算出来、后台能管理数据。能做到这几点,论文和答辩基本就稳了。
1.1 不是两个系统,是三个核心问题的组合
我把这个题目拆开给你看,它其实是用一个Django项目同时解决三件事:数据管理、个性化推荐、数值预测。
数据管理部分是基础。你需要维护学校信息、专业信息、历年分数线、招生人数、报录比这些数据,这对应的是数据库设计和Django Admin后台开发。这一块是评委最看重的“系统完整性”来源,因为推荐和预测都需要数据支撑,没有数据后台,前面两个算法就是空中楼阁。
个性化推荐部分是核心亮点。系统根据用户填写的意向地区、专业方向、本科背景等条件,结合用户浏览、收藏行为,从学校库里筛选出合适的院校列表,这对应的是推荐算法的设计。这里的难度适中,用基于内容的筛选、协同过滤、或者简单加权评分都能实现,完全够用。
分数线预测部分是数据能力的体现。系统读取历年各校各专业的复试分数线,运用回归或时间序列模型预测下一年的趋势,这对应的是机器学习和数据分析能力。对毕设来说,线性回归已经足够,关键是你要能把特征工程讲清楚。
这三块内容混在一起,就是评委口中的“工作量”。工作量这个东西在毕业设计里非常玄学——同样是一个系统,有人只写“实现了增删改查”,有人写成“构建了数据采集—特征构建—算法推荐—结果可视化”的闭环,后者的评价会高一个档次。这个题目天然帮你凑齐了闭环。
1.2 技术栈选型背后的真实考量
为什么不是Java+SpringBoot,也不是Flask,而是Python+Django?我跟很多评审老师交流过,他们普遍认可这个组合,理由其实很朴素。
Python在数据处理和算法实现上有碾压级的优势。pandas做数据清洗、numpy做矩阵运算、sklearn一行代码调模型,这些库在毕设阶段能帮你把精力集中在业务逻辑上,而不是纠结怎么写一个矩阵乘法。你去看很多推荐系统的论文,实验部分几乎都是Python写的,你用Django做Web层,算法用Python实现,前后端语言统一,代码量直接砍半。
Django相对于Flask的核心优势是“全家桶”。自带ORM、Admin后台、认证系统、CSRF防护、模板引擎。做毕业设计时,你不会想为了一个登录功能去折腾flask-login,更不想在答辩前夜发现密码没加密。Django把这些全给你了,你只需要学会怎么用,不用重复造轮子。
MySQL用默认的InnoDB引擎,注意表结构设计时统一字符集为utf8mb4,中文字段存储不会出问题。至于大数据组件,Hadoop、Spark这类在这个题目里是加戏,除非你导师明确要求,否则不建议引入。
提醒一句:题目里的“大数据”更多是标签性质的,不代表你要搭建大数据集群。毕设阶段你把数据处理流程讲清楚,就是命中“大数据”关键词的正确方式。
1.3 这个题目在答辩时的闪光点在哪
答辩时间通常只有5到10分钟,评委没有太多精力陪你逐行看代码,他们更关注的是你能否清晰回答“为什么这么做”和“效果怎么样”这两个问题。这个题目给你提供了三个天然亮点。
第一个亮点是数据来源和业务逻辑的闭环。你可以说从公开渠道抓取了近五年考研分数线数据,清洗后存入MySQL,再由Django后端读取,经过算法处理后通过ECharts可视化呈现。这一整条链路有数据、有处理、有展示,比单纯“做了一个网站”听起来扎实得多。
第二个亮点是推荐系统里的可解释性。这是很多毕设容易忽略的点。我在系统里会给每个推荐结果加上“推荐理由”,比如“该院校与你的意向地区匹配”“该专业近三年分数线波动较小,推荐指数较高”。这种细节能体现你思考过用户体验和算法落地的问题,答辩时提出来很加分。
第三个亮点是预测系统的误差分析。你在预测模块里展示预测值和真实值的折线对比图,顺便说清楚模型误差有多少、哪些学校预测偏差大、下一步怎么优化。这种“承认不足并提出改进思路”的姿态,评委非常受用,基本不会追问太深。
2. 系统设计:模块拆分与数据库模型
拿到这个题目,第一步不是写代码,而是画模块图和数据表结构。我见过太多同学一上来就创建Django项目,结果数据表建了三张又想加字段,反复迁移,最后把自己绕晕。正确流程应该是先把角色理清、把表设计好,代码跟着表结构走,才不容易返工。
2.1 用户端、管理端、算法端三条线的划分
这个系统按使用角色划分,至少有两条主线:普通用户端和管理员端。
普通用户端做得比较常规:注册登录、修改个人信息、填写考研意向(目标省份、专业方向、当前水平)、浏览院校列表、查看学校详情和历年分数线图表、收藏对比院校、获取推荐列表、查看分数线预测结果。这些功能对应的是Django里的视图函数加模板渲染,或者如果你选择前后端分离,就用DRF写API接口加Vue页面。二选一都可以,但要提前定好,不要写到一半换方案。
管理员端主要依赖Django Admin,再加上自定义的几个后台页面。管理员负责管理学校基本信息、专业设置、分数线数据、招生人数、用户反馈等。Django Admin在默认情况下已经能覆盖大部分需求,你只需要注册模型、配置list_display和搜索字段,省时省力。
算法端就是独立的业务逻辑层,不在页面上直接暴露。推荐算法封装成一个Python模块,接收当前用户ID和请求参数,返回推荐院校列表及相关理由;预测算法封装成另一个模块,读取某校某专业的历年分数线,返回预测数值和趋势。两个模块都用Django的视图调用,测试时可以单独跑脚本,不用经过HTTP层。
表结构设计是这里面最重要的事。我建议把表拆成:用户表(继承Django的AbstractUser)、省份表(city/province)、学校表、专业表、学校专业分数线表、用户意向表、收藏表、用户行为日志表。设计时要注意一个关键点——分数线表要和学校表、专业表建立外键关联,并且加上年份字段和大年小年标记。同时,用户意向表建议设计成一对一的,每个用户一份意向,字段直接存文本和编码。行为日志表特别重要,协同过滤算法要靠它计算相似度,没有行为数据,推荐效果会很差。
2.2 数据库模型怎么设计才能不返工
我给你一个可以直接用的模型定义参考,基于Django自带的ORM来写。
from django.db import models from django.contrib.auth.models import AbstractUser class User(AbstractUser): # 扩展用户表,增加意向省份和专业方向 province = models.CharField(max_length=50, blank=True, null=True, verbose_name="意向省份") major_direction = models.CharField(max_length=100, blank=True, null=True, verbose_name="目标专业方向") base_level = models.CharField(max_length=20, blank=True, null=True, verbose_name="基础水平") class School(models.Model): name = models.CharField(max_length=100, unique=True, verbose_name="学校名称") city = models.CharField(max_length=50, verbose_name="所在城市") province = models.CharField(max_length=50, verbose_name="所在省份") level = models.CharField(max_length=10, verbose_name="院校层次", help_text="985/211/双一流/普通") type = models.CharField(max_length=20, verbose_name="院校类型", help_text="综合/理工/师范/财经等") tags = models.CharField(max_length=200, blank=True, verbose_name="特色标签") description = models.TextField(blank=True, verbose_name="学校简介") class Major(models.Model): name = models.CharField(max_length=100, unique=True, verbose_name="专业名称") category = models.CharField(max_length=50, verbose_name="学科门类") class ScoreLine(models.Model): school = models.ForeignKey(School, on_delete=models.CASCADE, verbose_name="学校") major = models.ForeignKey(Major, on_delete=models.CASCADE, verbose_name="专业") year = models.IntegerField(verbose_name="年份") score_line = models.FloatField(verbose_name="复试分数线") enroll_count = models.IntegerField(verbose_name="招生人数", null=True, blank=True) apply_count = models.IntegerField(verbose_name="报考人数", null=True, blank=True) class UserIntent(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="intent") target_province = models.CharField(max_length=50, blank=True) target_major = models.CharField(max_length=100, blank=True) preference_level = models.CharField(max_length=20, blank=True, help_text="院校层次偏好") created_time = models.DateTimeField(auto_now_add=True) class Favorite(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) school = models.ForeignKey(School, on_delete=models.CASCADE) created_time = models.DateTimeField(auto_now_add=True) class BehaviorLog(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) school = models.ForeignKey(School, on_delete=models.CASCADE) action = models.CharField(max_length=20, help_text="view/favorite/compare") created_time = models.DateTimeField(auto_now_add=True)这段代码你一定要自己敲一遍理解每个字段的用途。比如ScoreLine里为什么要存enroll_count和apply_count,表面上看是为了展示数据,实际上你是拿它们做特征送给预测模型的,报录比和大小年趋势都从这里来。再比如BehaviorLog,它不直接给用户看,但协同过滤的全靠它。如果你设计表的时候把这个忽略掉,后期想加协同过滤就非常被动。
2.3 推荐系统的业务逻辑:别一上来就上矩阵分解
推荐算法领域有一堆看起来很高级的东西,矩阵分解、词向量、深度学习,但在毕设阶段我强烈建议你用“基于规则的初筛 + 基于内容的相似度 + 基于行为的协同过滤”三层结构。每层都不复杂,但组合起来效果稳定、逻辑清晰、论文可写性强。
第一层是规则初筛。用户提交意向后,先从学校表中筛出目标省份匹配的学校,再把层次偏好(985/211)过滤一遍。这一层帮你把候选集缩小到几十个以内,后续计算量就小了。
第二层是基于内容的相似度匹配。计算每个用户的特征向量和每所学校的特征向量的余弦相似度,排序后取TopK。用户的特征来自意向表(省份、专业方向、层次偏好),学校的特征来自学校表(所在省份、类型、层次、专业覆盖情况)。如果你觉得纯文本特征不好编码,可以做一个简单的标签匹配打分模型,用你填写的专业方向去匹配学校开设专业的重合度。
第三层是协同过滤。统计用户行为表,找到和当前用户行为最相似的另外几个用户(皮尔逊相关系数或者余弦相似度都行),把这些相似用户收藏过的、而当前用户没看过的学校加权推荐出来。
说实话,第三层在数据量少的毕设系统里效果往往很一般,但它非常能体现你的算法素养。你可以把它做成“相似用户还收藏了”的小模块,只在推荐列表底部展示,不作为主结果。这样既能避免冷启动带来的尴尬,又能让论文多一章可写的内容。
3. 核心算法与实现细节
算法是这个题目的灵魂,也是论文里最难写的部分。我不会推导公式废话连篇,直接告诉你我实际在毕设里是怎么实现的,关键是跑通并能够解释清楚。
3.1 推荐算法的三步实现:画像、相似度、混合加权
先说一下特征编码怎么做。如果你不想用复杂的Word2Vec或者TF-IDF做文本向量,就用最简单的关键词匹配打分。
用户画像特征可以定义为:target_province权重0.3,target_major权重0.4,preference_level权重0.3。学校侧的特征就是学校所在地是否匹配、专业覆盖是否匹配(学校有没有开设这个专业方向)、院校层次是否匹配。每个匹配项得满分或零分,然后加权求和。
import numpy as np def content_match_score(user_intent, school): score = 0.0 total_weight = 0.0 if user_intent.target_province and school.province == user_intent.target_province: score += 0.3 total_weight += 0.3 if user_intent.target_major and school.majors.filter(name=user_intent.target_major).exists(): score += 0.4 total_weight += 0.4 if user_intent.preference_level and school.level == user_intent.preference_level: score += 0.3 total_weight += 0.3 return score / total_weight if total_weight else 0.0这一段代码逻辑上就完成了基于内容的推荐核型。对候选学校的每一个都算一次分数,按分数倒序取前N个。关键是,你得在视图层对推荐结果补充“推荐理由”,不然前端展示得莫名其妙。
协同过滤部分我用最简单的方式实现:先构建“用户—学校”收藏矩阵,然后计算当前用户和其他用户之间的余弦相似度,取Top3个最相似用户,把他们收藏且当前用户未收藏的学校找出来。如果当前用户的收藏记录不足5个,直接跳过这层,只展示内容推荐结果。
from sklearn.metrics.pairwise import cosine_similarity import pandas as pd def collaborative_rec(user_id, top_n=5): logs = BehaviorLog.objects.all().values('user_id', 'school_id') df = pd.DataFrame(list(logs)) if df.empty or df[df['user_id'] == user_id].shape[0] < 3: return [] user_item = df.pivot_table(index='user_id', columns='school_id', values='school_id', aggfunc='count', fill_value=0) target_row = user_item.loc[user_id].values.reshape(1, -1) sims = cosine_similarity(target_row, user_item.values)[0] similar_users = user_item.index[sims.argsort()[::-1][1:4]] rec_schools = set() for u in similar_users: rec_schools.update(user_item.loc[u][user_item.loc[u] > 0].index.tolist()) favorites = set(BehaviorLog.objects.filter(user_id=user_id).values_list('school_id', flat=True)) candidates = rec_schools - favorites return list(candidates)[:top_n]注意一个问题:矩阵构建时如果用户行为数据太稀疏,pivot_table会得到一个全是0的矩阵,余弦相似度计算出来毫无意义。所以我在代码里加了条件判断——行为少于3条时直接返回空列表。
3.2 分数线预测:线性回归为什么够用
好多同学看见“预测”两个字就想上LSTM或者Prophet,其实完全没必要。考研分数线这个序列是典型的少样本数据,一个学校一个专业5到10条历史数据,喂给任何复杂模型都是过拟合。线性回归在样本量只有5到10条的情况下已经不错了,而且还能解释清楚系数含义,答辩时不至于被问倒。
数据特征我通常选三个:年份(作为时间趋势)、招生人数(政策因素)、报考人数(热度因素)。如果报考人数拿不到,就用年份和招生人数两个特征。这里有个关键操作——归一化。年份的取值范围是整数,招生人数动辄几十上百甚至上千,如果不归一化,回归系数会被特征量纲带偏,解释起来非常难受。
from sklearn.linear_model import LinearRegression from sklearn.preprocessing import StandardScaler import numpy as np def predict_score_line(records): X = np.array([[r['year'], r.get('enroll_count', 30)] for r in records]) y = np.array([r['score_line'] for r in records]) if len(X) < 5: return None, 0.0 scaler = StandardScaler() X_scaled = scaler.fit_transform(X) model = LinearRegression() model.fit(X_scaled, y) next_year = records[-1]['year'] + 1 next_x = scaler.transform([[next_year, np.mean([r.get('enroll_count', 30) for r in records[-3:]])]]) pred = model.predict(next_x)[0] mae = np.mean(np.abs(model.predict(X_scaled) - y)) return round(pred, 1), round(mae, 2)预测之后一定要在页面上展示两个东西:预测结果和误差分析。把历史每一年的真实值和模型拟合值画在同一张折线图里,用ECharts展示,观众一眼就能看出趋势。误差MAE写在图表下方,比如“平均预测误差为6.3分”,这种信息非常能体现你做了实验验证,而不是随便调了个库。
3.3 冷启动与数据稀疏:毕设答辩最容易问倒你的地方
评委如果懂推荐系统,大概率会问:新用户第一次来,没有任何行为数据,你的推荐系统怎么工作?这个问题就是冷启动问题。
我的处理方案是混合式兜底策略:新用户没有行为记录时,完全依赖基于内容的推荐,此时用户画像来自注册时填写的意向表单,而不是历史行为。同时系统显式标注“根据你的意向为你推荐”,让用户对结果来源心里有数。如果意向也没填,就按综合热度推荐,学校被收藏次数、访问次数高的在前,这也是很多电商系统的做法。
数据稀疏的问题也类似。我的策略是后端降级:当协同过滤返回结果不足5条时,用内容推荐补齐。前端展示上,整体列表始终保持10条以上,用户感知不到稀疏问题。这部分逻辑在代码里用if判断就能实现,但在论文中最好画一张降级流程图,会显得你考虑问题全面。
4. Django落地实战:从环境搭建到可运行系统
好多同学代码能看懂,但一到自己动手就卡在环境上。这一章我把完整流程串一遍,每步都说明白为什么要这么做。
4.1 环境准备:Python版本、虚拟环境、依赖清单
Python别用最新版,Django兼容性容易出问题,也别用老到没法安装新库的版本。我建议Python 3.8或者3.10,Django 3.2或4.0左右。如果你本机有多个Python版本,建议用virtualenv或者conda创建独立环境,毕设项目依赖不会跟其他项目打架。
python -m venv venv source venv/bin/activate # Windows下用 venv\Scripts\activate pip install django==4.0.5 mysqlclient pandas numpy scikit-learn requests beautifulsoup4mysqlclient在Windows上安装经常报错,如果你遇到编译问题,可以直接改用PyMySQL,然后在项目的__init__.py里加一行pymysql.install_as_MySQLdb(),能省很多麻烦。数据可视化部分建议用ECharts,前端用一个静态文件引入,后端返回JSON数据,不需要额外装图表库。
创建一个孝研项目自带的Idea:django-admin startproject mysite和python manage.py startapp recommend_app。这个步骤没难度,但要注意app创建之后,一定要去settings.py的INSTALLED_APPS里注册,很多同学的报错都出在这里。
4.2 关键项目结构设计与代码组织
为了保证后期不混乱,我建议在recommend_app内部按功能分目录:views.py只放页面能渲染的函数,algorithms/目录放推荐和预测的算法代码,utils/放数据爬取和清洗脚本,templates/放前端页面模板。这样论文“系统实现”章节直接对着目录结构写就行,代码可读性也高。
下面是建议的目录结构:
recommend_app/ ├── migrations/ ├── algorithms/ │ ├── recommend.py │ └── predict.py ├── utils/ │ ├── data_spider.py │ └── data_clean.py ├── views/ │ ├── home.py │ ├── user.py │ ├── school.py │ └── recommend.py ├── models.py └── urls.pyviews再细化成模块的好处是,后期你写完推荐和预测函数时,不需要在一个几百行的views.py里搜来搜去。这属于代码组织习惯,不带什么高深技术,但非常影响你的开发效率和答辩印象分。
4.3 数据入库、后台管理与接口对接的实操过程
数据从哪里来?我强烈建议用公开渠道获取,最稳妥的是爬取研究生招生信息网的公开数据或者各省教育考试院公布的历年分数线。写一个爬虫脚本,把数据存入CSV,再用pandas统一清洗,最后通过Django的loaddata或者自己写一个管理命令一次性导入数据库。数据入库这一步,论文里可以写成“数据采集与预处理”章节,把清洗规则列出来:缺失值填充、异常值剔除、统一编码格式。
如果你不想爬虫,也可以找现成的开源数据集,但要注意数据时效性,最好自己补充最近一年的数据。
接口对接分两种。如果模板渲染方式,视图函数直接查询数据库、调用算法、把结果塞进模板上下文;如果前后端分离,你只需要用Django的JsonResponse返回JSON,前端页面用axios或fetch请求并渲染。毕设阶段我不推荐让前端过度复杂,能用Django模板就用模板,省掉跨域和鉴权的麻烦。
一个关键配置是Django Admin的优化。在admin.py里注册所有模型,设置list_display和搜索字段,这样答辩演示时你直接在后台查一条分数线数据,分分钟提升系统的“管理后台完成度”。
4.4 部署、演示与录屏注意事项
有的学校要求系统能在线访问,有的学校只要求本机演示。本机演示最省事,但要注意两点。
第一,演示前把MySQL服务提前启动,不要等老师坐好再敲命令。第二,准备一个README.md写了启动步骤:创建虚拟环境、安装依赖、迁移数据库、导入初始数据、运行runserver。很多答辩现场事故都出在环境起不来这一步。
如果你想让系统看起来更专业,把静态文件用python manage.py collectstatic收集到一个目录,然后部署到云服务器上用Nginx加uWSGI跑起来。这篇毕设不要求你研究怎么部署,但你可以在论文附录里加上“部署方案说明”,属于额外加分项。
录屏讲解视频如果要做,建议时长控制在10分钟以内,开头介绍系统背景和目标,中间分别演示推荐和预测流程,结尾总结算法效果。录制前先把页面切换路径演练两遍,避免录到一半发现某个按钮点不了。
5. 常见问题与排查技巧实录
这部分是我带毕设过程中被问过最多的问题汇总,每个都配了解法。你可以直接把这张表贴到论文的“系统测试”章节里当测试报告。
5.1 数据库连接与中文乱码问题
现象:
MysqlConnectionError,Django启动时连不上数据库。排查:确认MySQL服务是否启动,账号密码是否正确,settings.py里HOST是否写成了localhost还是127.0.0.1。如果你本机MySQL是8.0以上,记得在连接参数里加
OPTIONS={'charset': 'utf8mb4'},否则中文字符写进去会报错。处理:把settings.py里的DATABASES配置统一如下:
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'exam_system', 'USER': 'root', 'PASSWORD': 'your_password', 'HOST': '127.0.0.1', 'PORT': '3306', 'OPTIONS': {'charset': 'utf8mb4'} } }中文乱码现象多见于爬虫数据写入后变成乱码。用pandas清洗时统一指定encoding='utf-8'读取CSV,写入MySQL时确保表字符集是utf8mb4,迁移前先ALTER TABLE xxx CONVERT TO CHARACTER SET utf8mb4,基本能一次解决。
5.2 推荐结果为空或性能卡顿
现象:用户填完意向,推荐页面一片空白。
排查思路:先看数据库里学校数据有没有导入成功,再看用户意向字段是否确实保存到了数据库,最后在recommend视图里加打印日志,确认算法返回结果是否为空。
经验:多数情况不是算法问题,而是数据没入库。很多同学从网上下载数据后只存了Excel或CSV,没通过脚本导入Django模型。切记先跑一遍
python manage.py shell手动调一次查询,确认School.objects.count()大于0再谈推荐功能。卡顿问题:如果学校表数据上了几千条,每次做高维相似度计算会很慢。加一层缓存就行,在每次计算结果里按日期或用户ID做缓存。如果懒得集成Redis,可以用Django自带的cache框架,存内存缓存,设置过期时间,演示时完全够用。
5.3 预测结果明显偏离实际
现象:预测2024年某校某专业分数线为400分,实际只有350分,大相径庭。
原因分析:最常见的原因是训练数据里出现了异常值,某一年因为试卷难度骤增或骤降,分数波动巨大,线性回归被带偏。还有一些是因为数据量太少,特征只有年份,模型完全学不到规律。
处理:在预测函数里加一个离群点过滤逻辑,当某年分数偏离均值超过两个标准差时,把它标记为“大小年波动”,在训练时降权或者剔除。同时在模型评估里计算MAE并展示,如果MAE大于20分,页面提示“该专业历史数据波动较大,预测结果仅供参考”。这句话非常有用,它既保护了系统的可信度,也让你在答辩时有一句“我们引入了置信度评估”的话可说。
5.4 毕设论文与PPT准备的避坑指南
论文结构建议按这个顺序写:研究背景和意义、相关技术介绍(Django、MySQL、协同过滤、线性回归)、系统需求分析、系统总体设计、系统详细设计与实现、算法实现与实验分析、系统测试、总结与展望。
很多同学容易卡在“系统详细设计与实现”这一章,要么贴大量代码,要么全是截图。正确的做法是只贴关键代码片段,每段配一段文字解释这段代码完成了什么功能、为什么这样设计。截图只放页面效果图和时序图,切忌大段贴整个文件。
PPT控制在12到15页之间,页面风格走简洁路线,少动画。核心内容放系统功能结构图、数据库ER图、推荐流程图、预测结果对比图、测试结果表。答辩时不要照着PPT念,而是讲“我是怎么想、怎么做得、遇到什么问题怎么解决”的小故事。评委对“Debug经历”的记忆率最高,比如你提一句“在做协同过滤时发现冷启动问题,所以设计了三层降级推荐方案”,效果远好于说自己会写十个接口。
注意:论文里的图表一定用Visio或Draw.io画,不要用Word自带的文本框拼,答辩时那种图是肉眼可见的随意。
最后再分享一个小经验:如果你时间实在紧张,优先打磨“分数线趋势可视化”这个模块。它是预测系统最直观的展示窗口,又有历史曲线又有预测值,公示效果极好。推荐系统就算只做一个简单的意向筛选,也比不上一个精致的预测趋势图带来的冲击力。这个题目真正拿高分的地方,往往不是算法的深度,而是你把算法结果展示得有多漂亮、把业务逻辑讲得有多通顺。