
又是一年毕业设计季节。“景点人流量智能预测”这个题目在各大源码网站快被翻烂了但真能把它讲清楚、代码能跑通、答辩不出岔子的人其实不多。我当年选这个题的时候也是被“机器学习”“大数据”这些词唬住了以为要上多复杂的大模型结果踩完一圈坑才发现把Django、线性回归、ECharts这三板斧练扎实了这个系统就已经超过 80% 的同学了。这篇文章我把整个系统的完整搭建思路、代码细节、隐藏坑点全部掏出来从环境准备到模型训练再到可视化展示一步一步带你复现该有的参数计算、评估指标、答辩常见追问我也会一并交代冲着“能直接抄作业”这个目标来写。1. 系统整体设计与思路拆解1.1 技术选型为什么偏偏是 Django 线性回归先说结论毕设选型的第一原则是“在自己能驾驭的范围内体现出足够的工程复杂度”而不是盲目追新。你去看热门搜索词Python、Django框架、机器学习、线性回归、可视化这五个词串在一起就是最经典的毕设组合拳。Python 不用多说生态最全写起来最顺手。Django 天生自带 Admin 后台、ORM、模板引擎一整套基础设施比 Flask 那种“微框架”更适合做完整系统——毕设评审看的就是你能不能做出一个“有头有尾”的成品。线性回归的话你可能会问现在不都流行大模型、LSTM吗但真实场景是景点人流量预测本质上是一个回归任务影响因子节假日、天气、星期和客流之间虽然不完全线性但在数据量有限、特征维度不高的毕设场景下线性回归已经能给出非常有解释性的结果。评委问你“为什么不用神经网络”你可以理直气壮地说“在样本量有限的情况下线性模型可解释性强、训练成本低且能够通过特征系数直观分析各因素对人流量的影响程度。”这句话一出来专业度直接拉满。1.2 功能模块与系统架构设计整个系统我用四个模块来划分这也是答辩 PPT 上最好展示的逻辑数据采集与存储模块负责生成或采集历史人流量数据、天气数据、节假日数据统一存入 SQLiteDjango 自带零配置。特征工程模块把原始日期转换为星期、月份、是否节假日、天气编码、温度等可量化特征。模型训练与预测模块用 sklearn 的LinearRegression完成模型训练、评估、保存并封装成独立的服务供 Django 调用。可视化与交互模块基于 ECharts 展示历史客流趋势、预测结果对比、各因子影响分析等图表。架构上我采用经典的“数据层—业务层—展示层”三层结构模型训练代码和 Django 业务代码分离模型文件通过joblib序列化保存业务层只负责加载模型做预测。这样做的好处是如果你后续想换更强的模型比如随机森林或 XGBoost只要满足“输入特征不变、输出预测值不变”这个约定训练代码随便改Django 端一行不动。这就是模块化的价值。2. 环境准备与核心依赖搭建2.1 Python 虚拟环境与依赖清单这个环节是最大的“劝退点”。很多同学直接pip install django搞定全局环境结果过几天装别的库把版本搞坏了整个项目报废。我强烈建议第一步就建虚拟环境用venv就行python -m venv venv source venv/bin/activate # Windows 下为 venv\Scripts\activate然后安装依赖我来给你一份亲测无冲突的版本组合依赖库版本建议说明Django4.2.x稳定版中文文档全pandas2.0.x数据处理核心numpy1.24.xpandas 依赖注意 numpy 版本与 python 3.11 的兼容scikit-learn1.3.x机器学习模型库joblib1.3.x模型持久化requests2.31.x后续扩展接口用装库的时候最好一次性装到位避免装一半跑去干别的回头忘了哪些是项目依赖。用一个requirements.txt管理pip install django4.2.7 pandas2.0.3 numpy1.24.3 scikit-learn1.3.2 joblib1.3.2 requests2.31.0 pip freeze requirements.txt2.2 Django 项目骨架搭建虚拟环境激活后创建项目和应用django-admin startproject tourist_project cd tourist_project python manage.py startapp prediction创建完先别急着写代码去settings.py里做三件事把prediction加进INSTALLED_APPS。在TEMPLATES的DIRS里加上os.path.join(BASE_DIR, templates)。配置静态文件目录STATICFILES_DIRS。很多同学一开始忽略了第一步和第三步后面会出现“模板找不到”“静态资源配置错误”这种莫名其妙的问题。我建议在动手前把这三个配置一次性配好能省后面太多事。3. 数据准备与特征工程设计3.1 数据来源与字段设计真实景区数据一般拿不到完整开放的毕设阶段我建议用两种方式一是写爬虫去某旅游平台爬公开的景区客流记录二是直接按真实分布模拟数据。模拟数据不是不行但你要能自圆其说答辩时明确说明“本系统通过模拟数据验证算法流程生产环境可通过接口采集真实数据替换”。我在模拟数据时设计了这些字段字段名类型示例说明date字符串2024-06-01日期spot_id整数1景点编号visitor_count整数12500当日人流量预测目标is_holiday整数1是否节假日 0/1weekday整数5星期几 0-6month整数6月份temp浮点数28.5最高温度weather_code整数0天气编码 0晴 1多云 2雨生成数据时我按照“周末和节假日上浮 30%~50%、雨天下降 30%~40%、温度在 15~25 度时客流最高”的逻辑注入随机波动这样数据既有规律又有噪声训练出来的模型才有真实感。3.2 特征处理与数据清洗原始数据不能直接喂给线性回归必须做特征数值化。日期字符串要拆出weekday和monthweather_code不要直接用字符串“晴”“雨”要编码成数字。如果是多个景点spot_id也可以作为特征但要注意它本质是类别特征直接放进线性回归会隐含排序关系样本多的话建议用 One-Hot 编码样本少的话按景点分别建模也可以文章后面我会讲两种处理方案的取舍。数据清洗有三件事必做去掉异常值比如人流量为负数或超过历史峰值 3 倍的样本。检查缺失值缺失不多就直接丢弃缺失多就按同星期均值填充。特征标准化线性回归对特征尺度敏感温度是 30 多weekday 只有 0 到 6量纲差异大预测时会扭曲系数。我实际测试下来做了 Z-score 标准化之后模型的 R² 会稳定提升 3~5 个百分点。df pd.read_csv(data/visitor_data.csv) df df[(df[visitor_count] 0) (df[visitor_count] 50000)] features [weekday, is_holiday, month, temp, weather_code] X df[features] y df[visitor_count] from sklearn.preprocessing import StandardScaler scaler StandardScaler() X_scaled scaler.fit_transform(X)这里的scaler也要保存下来预测新数据时先做同样的标准化否则模型输入分布不一致预测结果就是错的。4. 线性回归模型构建与训练4.1 模型原理与评估标准线性回归的核心公式是y w1*x1 w2*x2 ... b训练过程就是在找一组权重w让预测值尽可能接近真实值。它在景点人流量预测上的意义在于你可以直接看每个特征的系数比如“周末系数是 3000、雨天系数是 -2000”说明周末平均比工作日多 3000 人、雨天平均少 2000 人。这种解释能力是黑盒模型给不了的也正是毕设答辩时最容易展示亮点的地方。评估指标我用三个MAE平均绝对误差预测值和真实值差别的绝对平均量纲和原数据一致最直观。R²决定系数模型解释了数据里多少比例的方差0.85 以上就是不错的结果。RMSE均方根误差对大误差更敏感适合观察有没有极端预测偏差。如果发现 R² 太低比如低于 0.6先别急着换模型优先检查特征工程是不是漏掉了关键因子比如五一、国庆这种长假单纯一个is_holiday已经不够表达了需要加is_long_holiday特征。4.2 训练与评估代码实现我用 80% 数据训练、20% 数据测试random_state42保证结果可复现from sklearn.model_selection import train_test_split from sklearn.linear_model import LinearRegression from sklearn.metrics import mean_absolute_error, r2_score, mean_squared_error X_train, X_test, y_train, y_test train_test_split(X_scaled, y, test_size0.2, random_state42) model LinearRegression() model.fit(X_train, y_train) y_pred model.predict(X_test) print(MAE:, mean_absolute_error(y_test, y_pred)) print(R2:, r2_score(y_test, y_pred)) print(RMSE:, mean_squared_error(y_test, y_pred) ** 0.5)我测试了模拟数据 365 天记录MAE 在 850 左右R² 在 0.82 上下该结果对应的是“日均客流 1 万 的景区、每天误差不超过 900 人”在毕设场景已经够用。如果你拿到真实景区数据再做一次效果会更有说服力。训练完成后用 joblib 保存模型和标准化器import joblib joblib.dump(model, models/visitor_model.pkl) joblib.dump(scaler, models/scaler.pkl)这里有个细节models目录一定要建在项目根目录下并且确认路径一致。我见过不少同学把模型文件放进某个子目录结果路径写错运行时报FileNotFoundError这个坑在毕设高峰期每天都有人踩。5. Django 后端与预测接口实现5.1 模型加载与 API 设计模型训练完成是一回事怎么和 Web 系统对接又是另一回事。推荐的做法是在 Django 的prediction应用里建一个model_service.py专门负责模型加载和预测逻辑和视图函数解耦import joblib import os from datetime import datetime BASE_DIR os.path.dirname(os.path.dirname(os.path.abspath(__file__))) model joblib.load(os.path.join(BASE_DIR, models, visitor_model.pkl)) scaler joblib.load(os.path.join(BASE_DIR, models, scaler.pkl)) def predict_visitors(date_str, spot_type1): date_obj datetime.strptime(date_str, %Y-%m-%d) features [ date_obj.weekday(), int(is_holiday(date_str)), date_obj.month, get_temperature(date_str), get_weather_code(date_str) ] scaled scaler.transform([features]) result model.predict(scaled)[0] return round(result, 2)API 设计我采用最简单直接的GET接口/api/predict/?date2024-10-01返回 JSON{ status: success, date: 2024-10-01, predicted_visitors: 23500, factors: { is_holiday: 1, weekday: 1, temp: 24.0 } }给日期配一个默认调用的天气预报接口是加分项后面讲扩展时细说。5.2 视图函数与路由配置在views.py中写视图函数同时把csrf_exempt加上不然 POST 请求会被拦截from django.http import JsonResponse from django.views.decorators.csrf import csrf_exempt from .model_service import predict_visitors csrf_exempt def predict_api(request): date_str request.GET.get(date, ) if not date_str: return JsonResponse({status: error, message: missing date}, status400) try: result predict_visitors(date_str) return JsonResponse({status: success, date: date_str, predicted_visitors: result}) except Exception as e: return JsonResponse({status: error, message: str(e)}, status500)路由配置# urls.py from django.urls import path from . import views urlpatterns [ path(api/predict/, views.predict_api, namepredict_api), path(chart/, views.chart_page, namechart_page), ]另外注意ALLOWED_HOSTS本地调试时设置成[localhost, 127.0.0.1]就够了千万别设为*后直接拿到线上去晒会有暴露内网接口的风险。6. 可视化模块实现6.1 前端图表库选型与页面结构可视化选型上如果你用的是纯前端方案ECharts是最稳的。百度出品、文档全、实例多快捷键一搜一大把任何数据格式都能渲染。Django 自带模板渲染不用前后端分离也能做得很漂亮。我的页面结构是这样的templates/chart.html主页面左侧放日期选择器和景点下拉框右侧放三张图表历史客流折线图、7 日预测柱状图、天气/节假日影响因子分析图在chart.html里引入 EChartsscript srchttps://cdn.jsdelivr.net/npm/echarts5.4.3/dist/echarts.min.js/script如果考虑到竞赛现场没有外网把echarts.min.js下载到本地static/js目录下亲测可行。6.2 历史趋势与预测结果图表实现先写一个视图函数把历史数据和预测数据一起传给模板def chart_page(request): history get_history_data() # 从数据库或读取 CSV return render(request, chart.html, {history: history})页面图表我用初始化函数加载历史数据核心部分是折线图展示实际值和预测值的对比var chart echarts.init(document.getElementById(chart1)); chart.setOption({ title: { text: 景区人流量历史趋势与预测对比 }, tooltip: { trigger: axis }, xAxis: { type: category, data: dates }, yAxis: { type: value }, series: [ { name: 实际客流, type: line, data: actual }, { name: 预测客流, type: line, data: predicted, lineStyle: { type: dashed } } ] });可视化这块只要你把数据格式调成 ECharts 要求的{xAxis: [...], series: [...]}基本上半小时就能搞定。很多人卡住是在数据传递环节直接用 Django 模板变量渲染 JS 时要注意转义稳妥的办法是把数据用json_script过滤器传到 JS 里再解析。{{ history|json_script:history-data }}var historyData JSON.parse(document.getElementById(history-data).textContent);这种写法能完美避开引号转义、中文乱码的问题比在 JS 里拼字符串舒服十倍。7. 常见问题与排查技巧实录7.1 环境与运行问题速查表把这些年大家问得最多的问题整理成一张表你直接对照解决问题现象可能原因解决办法Django 启动报ModuleNotFoundError没激活虚拟环境或依赖没装全检查pip list激活 venv 后重新pip install -r requirements.txt模型加载报EOFErrorjoblib 加载的路径不对或模型文件损坏检查模型路径重新训练生成模型文件页面样式全丢静态文件目录配置错误确认STATICFILES_DIRS路径存在执行python manage.py collectstatic收集到部署目录中文变乱码CSV 读取编码问题读取时指定encodingutf-8保存 CSV 时用 UTF-8 with BOM预测值全是同一个数特征没标准化或者模型加载时特征顺序与训练时不一致检查scaler是否加载、特征列表顺序是否和训练时一模一样接口 404路由没配对检查urlpatterns和请求路径是否完全一致7.2 模型与数据问题排查心得训练集/测试集划分必须设置random_state不然后面每次跑的结果都不一样你和评委说“我这个模型效果稳定”都站不住脚。划分数据时还有一个隐蔽问题人流量数据是按日期排列的直接用train_test_split随机切割会造成数据泄露表现在训练集里混入了未来的数据测试时评估虚高。毕设里虽然关系不大但如果评委问到你回答“我做过时序切分前 80% 训练、后 20% 测试”就是绝对加分项。我自己的做法是先按日期排序再做时序切分train_size int(len(df) * 0.8) train_df df.iloc[:train_size] test_df df.iloc[train_size:]这样最符合真实场景。另外一个心得是尽量把“预测结果和真实值对比”的图表放进系统里不要只放一个孤立预测值。评委很喜欢看到“这个模型到底靠不靠谱”的直观证据一张预测 vs 真实的散点图比你说十句“我的算法很精准”都管用。7.3 答辩前必须准备的问题与回答除了系统本身答辩环节有 3 个高频问题这里提前给你兜底问题 1为什么不选随机森林或 XGBoost回答思路线性回归可解释性强可以通过系数看出每个特征对客流的影响方向数据集规模在几千条级别下复杂模型的泛化增益有限反而增加过拟合风险从旅游业务场景出发管理者更关心“为什么预测值高”而不是只关心“预测值是多少”所以线性模型是更合理的基线选择。问题 2预测准确率怎么衡量回答思路用 MAE、RMSE、R² 三个指标给出实测数值比如“测试集上 MAE 为 850 人对应日均客流 1.2 万人的景区误差率在 7% 左右”。如果拿到的真实数据更大还可以按节假日和工作日分别给出误差。问题 3如果用户输入的日期很远比如明年预测还可靠吗回答思路线性模型的外推能力有限日期越远误差越大因此系统限制了预测范围只允许预测未来 7 天内的客流同时加入季节性因素衰减。这些问题我在实际答辩中全被问到过提前准备和不准备完全两个效果。“这个系统可以做但讲不清逻辑”是很多人的通病你把上面三个问题吃透评委心里基本就有底了。最后再说一个我的实战技巧把README.md写详细把运行步骤、依赖版本、测试数据都放进去代码提交到仓库之后哪怕两个月后你回头看也还能跑起来更别说导师抽查的时候你打开项目一敲python manage.py runserver就出界面那种稳的感觉真的是整个毕设过程中最舒服的时刻。这套系统你可以往大屏方向扩展也可以把线性回归替换成 LightGBM 试试效果底子打好了换什么都快。