每年答辩季,我都能看到不少同学抱着“电影数据分析”这类题目上场,多数都在第一轮追问里被问住了。问住的原因不是题目不好,而是很多人把项目做成了“下载数据—画图—贴结论”三步曲,被老师追问“这些图说明了什么”“模型为什么这么选”“缺失值你是怎么处理的”就卡壳。TMDB电影数据分析与可视化这个题目,乍看是入门级,但要做出一个能打、能答辩、能讲的毕设项目,其实链路很长:数据获取、清洗、特征工程、可视化、深度学习建模、结果解释,再到Web系统集成,每一个环节都值得认真做。
这篇围绕的是一个完整的TMDB电影数据分析与可视化毕设项目来写。适合正在选大数据或深度学习方向、想拿电影数据做毕设、又担心项目深度不够的同学参考。我会按照项目的实际推进顺序,把每个环节的技术选型、实现细节、踩坑经验拆开讲,尤其会多说一些“答辩时要能讲清楚为什么”的地方。
1. 为什么这个题目在答辩中“稳”:选题逻辑与项目定位
1.1 TMDB数据集本身的优势
TMDB是The Movie Database的缩写,一个开放的互联网电影数据库。Kaggle上有一份非常经典的TMDB 5000 Movie Dataset,包含4800多部电影的元数据,字段覆盖预算、票房、类型、演员、导演、关键词、评分、用户投票数、简介文本等20多个维度。
这个数据集好在哪?首先,它是真实业务数据,不是人工造出来的,天然就有缺失值、极端值、长尾分布、多标签嵌套结构,这些正好是数据分析项目最需要的“问题素材”。其次,字段类型足够丰富:数值型、类别型、时间型、文本型、嵌套JSON型都有,一套完整的数据清洗流程可以从头走到底。第三,面向电影业务,结论容易被理解,答辩时不至于讲不清楚业务背景。
如果把项目定位成“从数据探索发现规律,用深度学习构建预测模型,用Web系统展示成果”,这就是一个完整的工程闭环,不是单纯的“画图项目”,也不是脱离业务场景的“炼丹项目”。
1.2 这个题目到底属于“大数据”还是“深度学习”方向
很多同学纠结这个定位,其实不用纠结。这类项目的正确说法是“数据科学与工程应用”,大数据体现在数据清洗、特征构造、分布式思维和数据分析流程上,深度学习则是预测模块的核心工具。我们不需要用Hadoop跑几千条数据,但处理流程和数据治理的思路是通用的。答辩老师关心的不是你的数据量级,而是你有没有完整地走通“数据—特征—模型—应用”这条链路。
毕设选题还有一个原则:宁可做小做深,不要做大做空。TMDB这个题目刚好卡在合适的量级上,几个人能在一学期内完成,又有足够的深度去支撑答辩。
1.3 适合谁做、需要什么基础
如果你已经掌握Python基础、Pandas常用操作、Matplotlib基本画图,这个项目就能上手。深度学习部分不需要你从头推公式,但至少要理解全连接网络的前向传播、反向传播、损失函数和过拟合这些基本概念。如果你还不会这些,边做边补也来得及,项目本身会逼着你把这些概念串起来。
我会在下面把整个流程拆成五个部分来讲:数据准备、可视化分析、深度学习建模、系统展示、答辩避坑。每一部分都有可以直接落地的细节,也会有“为什么这样做”的解释。
2. 数据清洗的完整链路:从JSON字段到干净的训练表
2.1 先搞清楚数据到底长什么样
TMDB 5000这个数据集在Kaggle上分两个文件:tmdb_5000_movies.csv和tmdb_5000_credits.csv。movies表每行是一部电影,credits表包含演员和剧组成员信息。先拿movies表说,它的核心字段如下:
| 字段名 | 类型 | 说明 | 在项目中的用途 |
|---|---|---|---|
| budget | int | 预算(美元) | 票房预测的重要特征 |
| genres | str(JSON) | 类型列表 | 多标签特征,可做类型分析 |
| homepage | str | 官网链接 | 缺失率极高,一般不参与建模 |
| id | int | TMDB电影ID | 关联credits表 |
| keywords | str(JSON) | 关键词列表 | 做词云和文本分析 |
| original_language | str | 原始语言 | 类别特征 |
| overview | str | 剧情简介 | 文本特征,可用于TF-IDF |
| popularity | float | 热度指数 | 强特征 |
| production_companies | str(JSON) | 制作公司列表 | 多标签类别特征 |
| release_date | str | 上映日期 | 提取年、月、星期等 |
| revenue | int | 票房收入 | 建模目标标签 |
| runtime | float | 时长 | 数值特征 |
| vote_average | float | 平均评分 | 描述性分析 |
| vote_count | int | 投票数 | 评分可信度参考 |
第一次拿到数据,不要急着画图,先做三件事:看行列数、看缺失值数量、看字段类型。一行df.info()和df.isnull().sum()就能把整体情况摸清楚。
2.2 非结构化字段的解析方法
麻烦的是genres、keywords、production_companies这几个字段,表面看是字符串,实际是JSON数组嵌套结构。比如genres字段长这样:
[{"id": 28, "name": "Action"}, {"id": 12, "name": "Adventure"}]直接当成字符串画图肯定不行。要把它解析成Python列表。这里推荐用ast.literal_eval,比json.loads更稳妥,因为数据里的引号格式有时不标准,json.loads偶尔会抛异常,而ast.literal_eval能识别Python字面量结构。
import ast df['genres_list'] = df['genres'].apply( lambda x: [item['name'] for item in ast.literal_eval(x)] if isinstance(x, str) else [] ) df['keywords_list'] = df['keywords'].apply( lambda x: [item['name'] for item in ast.literal_eval(x)] if isinstance(x, str) else [] ) df['companies_list'] = df['production_companies'].apply( lambda x: [item['name'] for item in ast.literal_eval(x)] if isinstance(x, str) else [] )这一步做完,每个电影就有了三个列表型字段。后面做类型分析时,可以用df.explode('genres_list')把一部电影按多个类型拆成多行;做特征工程时,可以先把每个列表展开成多标签矩阵。
2.3 缺失值和0值:不是所有“0”都是缺失
清洗过程中最容易糊涂的一个点是:budget和revenue字段里的大量0值,到底是“真实的0收入”,还是“没记录”?根据TMDB数据的实际情况,大部分0值都是数据缺失,而不是电影真的零预算零票房。如果直接把0值保留送进模型,模型会被这些假零值严重带偏;如果全部删除,样本量又会大幅缩水。
我的处理策略是分情况:
revenue为0且budget为0的行,直接剔除,因为没有有效财务数据;revenue为0但budget不为0的行,单独打一个标记列,比如is_revenue_missing = True,后续建模时可以选择剔除或单独分组训练;- 真正的分析场景里,描述统计图可以保留0值,但要在图上说明“0值包含缺失”。
有一个核心操作要先做:日期字段标准化。release_date字段转成datetime类型,然后提取年份、月份、星期几、季度。这些衍生特征在探索性分析和建模时都有用。
df['release_date'] = pd.to_datetime(df['release_date'], errors='coerce') df['release_year'] = df['release_date'].dt.year df['release_month'] = df['release_date'].dt.month还有一个容易被忽略的问题:重复电影。ID是唯一的,但同一部电影可能因为数据合并问题出现了重复记录,需要按id去重。
2.4 清洗到可以建模的最终数据集
我实际做下来,TMDB 5000原始数据大概4800多行,经过日期有效性和0值处理之后,最终能进模型的样本大约在3800到4200之间。这个数据量对深度学习来说不算大,但对一个毕设项目完全够用,关键是把每个样本的特征做扎实。
最终数据集应该包含:电影ID、年份、月份、预算、时长、热度、投票数、类型列表、制作公司列表、关键词列表,以及预测目标revenue。在答辩时,老师一定会问“你最终建模用了几条数据,为什么是这个数量”,你得能说清楚每一步筛选的条件和理由,而不是含糊地说“删掉了一些异常值”。
3. 可视化不是画图机器:用图表支撑分析结论的实操思路
3.1 先想清楚“要回答什么问题”,再决定画什么图
很多同学做可视化是看到什么画什么,最后堆了十几张图,每张图都蜻蜓点水,答辩老师随便问一张图“你从里面看出了什么”,自己都答不上来。正确的做法是先定义分析问题,再根据问题挑选图表类型。
我建议围绕这几个业务问题来做可视化:
| 问题 | 推荐图表 | 预期结论 |
|---|---|---|
| 电影数量随时间怎么变化 | 折线图 | 电影产量总体上升,但不同年代波动明显 |
| 预算和票房有没有关系 | 散点图+回归线 | 两者正相关,但存在许多高预算低票房的“亏损片” |
| 哪些类型更赚钱,哪些类型评分更高 | 箱线图或柱状图 | 动画、科幻类平均票房高,纪录片评分高但票房低 |
| 电影热度(popularity)和票房是否一致 | 散点图 | 热度高不一定票房高 |
| 关键词里隐藏了哪些题材趋势 | 词云 | 观众偏好的题材方向 |
| 电影评分分布 | 直方图/密度图 | 评分普遍集中在6-8分之间 |
每一张图放在论文里或者答辩PPT里,旁边配上一段“这说明什么”的文字,项目分析的完整度立刻就上来了。
3.2 预算与票房散点图:一个核心图的完整实现细节
预算和票房的关系是分析部分最值得做的一张图。但直接拿原始数据画散点图,效果通常很差,因为数据严重右偏:大部分电影预算集中在一千万到五千万美元,少数大片预算过亿,零星几个极端值就把图片压缩成了一团。
处理方法是做对数变换。用np.log1p而不是np.log,因为log1p在输入为0时返回0,不会得到负无穷,这样0值的样本不会被直接丢弃。
import numpy as np import seaborn as sns import matplotlib.pyplot as plt df['budget_log'] = np.log1p(df['budget']) df['revenue_log'] = np.log1p(df['revenue']) plt.figure(figsize=(10, 6)) sns.regplot(data=df[df['revenue'] > 0], x='budget_log', y='revenue_log', scatter_kws={'alpha': 0.4, 's': 20}, line_kws={'color': 'red'}) plt.xlabel('Log(Budget + 1)') plt.ylabel('Log(Revenue + 1)') plt.title('Budget vs Revenue (Log Scale)') plt.show()这张图能直观看出两件事:一是预算和票房整体呈现正相关,说明投入对产出有正向影响;二是有相当多样本落在回归线下方,说明高预算不一定带来高回报。答辩时,这两个结论比“我画了一张散点图”有说服力得多。
3.3 类型分析的坑:多标签数据不能直接画箱线图
genres是多标签字段,一部电影可能同时属于“动作”和“科幻”。如果直接把genres_list展开成多行再画箱线图,会导致同一部电影被重复计入多个类型箱体。这是合理的,因为类型分析本来就允许一部电影贡献给多个类型,但有一个问题必须处理:类型太多,图上会挤成一团。
我建议只保留出现频次最高的前10个类型,其余合并为“Other”。这样箱线图清晰、结论也更聚焦。
top_genres = df.explode('genres_list')['genres_list'].value_counts().head(10).index df_top = df.explode('genres_list') df_top = df_top[df_top['genres_list'].isin(top_genres)] plt.figure(figsize=(12, 6)) sns.boxplot(data=df_top, x='genres_list', y='vote_average') plt.xticks(rotation=45) plt.title('Vote Average by Genre') plt.show()通常得出的结论是:纪录片、音乐类平均评分偏高,而恐怖片、动作片平均评分偏低;但如果换成交量或总票房,动作片、科幻片又排到前面。这个结论本身就有分析价值——高评分和高票房不一定是同一批类型。
3.4 可视化工具选型:什么时候用Seaborn,什么时候用Pyecharts
毕设里涉及两类图表场景,选型逻辑不一样。
第一类是论文和答辩PPT里用的“论文图”,要求规范、静态、能说明问题。我推荐Matplotlib+Seaborn。Seaborn自带统计绘图能力,一行代码就能出带置信带的关系图、标准箱线图,配色也比Matplotlib默认的好看。
第二类是Web系统展示页里的“大屏图”,要求交互、美观、能点击。我推荐Pyecharts或ECharts。Pyecharts的优势是可以用Python生成ECharts的HTML,不需要单独写前端,对不熟悉前端的同学非常友好。
| 维度 | Matplotlib + Seaborn | Pyecharts |
|---|---|---|
| 适用场景 | 论文插图、答辩PPT | 系统展示页、交互大屏 |
| 交互性 | 无 | 悬停、缩放、点击事件 |
| 中文支持 | 需要手动配置字体 | 默认支持较好 |
| 学习成本 | 低 | 低到中等 |
| 输出形式 | PNG/SVG图片 | HTML/JavaScript |
我实际项目里两种都用了:论文和PPT放Seaborn图,系统的“数据洞察”页面用Pyecharts生成柱状图和折线图。
4. 票房预测模型的选型、训练与实验结果解读
4.1 任务定义:回归还是分类
分析做完之后,如果项目到此为止,深度学习的部分就体现不出来。我建议加一个票房预测模块,这样项目就从“数据分析与可视化”升级成了“分析+建模”。
任务形式有两种选择:一是回归,直接预测票房的对数值;二是分类,预测电影票房属于“低/中/高”哪个档位。我更推荐回归,因为信息量更大,而且用连续值预测能从误差分析里讲出更多故事。
为什么预测目标要对数化?因为票房分布极度右偏,头部电影和腰部电影相差好几个数量级。如果直接回归原始票房值,模型会为了拟合那几部超级大片而忽略绝大多数样本。对标签做log变换后,分布更接近正态,模型更容易收敛,评估指标也更有意义。这个理由在答辩时一定要讲清楚。
4.2 特征工程:哪些特征真正有用
特征工程决定模型上限,深度学习只是逼近这个上限。TMDB项目里,我主要做以下几类特征:
- 数值特征:预算(log)、时长、热度指数、投票数;
- 时间特征:上映年份、上映月份;
- 类别特征:原始语言、制作公司(取Top20做one-hot);
- 多标签特征:电影类型(取Top10做one-hot或multi-hot);
- 文本特征:剧情简介的TF-IDF向量,维度控制在100左右。
制片公司特征值得多说一句。头部公司比如华纳兄弟、环球影业、漫威,因为发行能力强,电影票房普遍偏高。直接把制作公司做one-hot会太稀疏,我通常取出现次数Top20的公司做二值特征,其余全部归入“Other”。
数值特征要注意量纲问题。DNN对输入尺度敏感,如果预算直接用亿元为单位、时长用分钟、popularity又是一个小数,不同特征尺度差异太大,会让梯度更新不稳定。统一用MinMaxScaler或StandardScaler归一化,模型训练会稳定很多。
from sklearn.preprocessing import MinMaxScaler from sklearn.model_selection import train_test_split feature_cols = ['budget_log', 'runtime', 'popularity', 'vote_count', 'release_year', 'release_month'] X = df[feature_cols].copy() # one-hot编码后的类型、公司列合并进来 # X = pd.concat([X, genre_dummies, company_dummies], axis=1) scaler = MinMaxScaler() X_scaled = scaler.fit_transform(X) y = df['revenue_log'].values X_train, X_test, y_train, y_test = train_test_split( X_scaled, y, test_size=0.2, random_state=42 )4.3 模型选型:为什么用DNN而不是LSTM或CNN
一个很容易被追问的问题:为什么选全连接网络?答辩时不能说“因为这个最简单”。合理的原因有三个:
第一,TMDB数据集没有时间序列结构,每部电影是一个独立的样本,不存在先后依赖关系。LSTM是为序列建模设计的,强行套用没有意义。第二,全连接网络能自动学习特征之间的非线性交互,比如“高预算+动画类型”对票房的联合效应,这是线性回归做不到的。第三,样本量只有几千条,CNN或Transformer这类大容量模型很容易过拟合,而且训练成本高,不适合毕设场景。
模型结构不要搞得太大。我用的结构是三层全连接,隐藏层分别128、64、32个神经元。激活函数用ReLU,输出层不用激活函数,因为任务是回归。
from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Dense, Dropout from tensorflow.keras.callbacks import EarlyStopping model = Sequential([ Dense(128, activation='relu', input_shape=(X_train.shape[1],)), Dropout(0.3), Dense(64, activation='relu'), Dropout(0.2), Dense(32, activation='relu'), Dense(1) ]) model.compile(optimizer='adam', loss='huber', metrics=['mae']) model.summary()4.4 损失函数和训练细节:Huber Loss为什么比MSE稳
回归任务的默认损失函数是均方误差(MSE),但在票房数据上,MSE有一个明显问题:个别极端值(比如某部电影实际票房远高于预测值)会产生非常大梯度的梯度,拖累整体训练。Huber Loss在误差较小时等价于MSE,误差较大时退化为线性,对异常值的敏感度显著降低。
我实测下来,在票房预测这类长尾任务上,Huber Loss的训练曲线比MSE稳定得多。一个可复现的训练配置是:
early_stop = EarlyStopping(monitor='val_loss', patience=10, restore_best_weights=True) history = model.fit( X_train, y_train, validation_split=0.1, epochs=100, batch_size=32, callbacks=[early_stop], verbose=1 )用EarlyStopping是因为样本量小、模型容易过拟合。训练时监控验证集损失,一旦验证集损失连续多个epoch不下降就停止,并恢复最佳权重,防止训练后期震荡。
4.5 实验结果怎么解读才能不被追问击穿
训练结束之后,要用R²、RMSE、MAE三个指标评估。R²表示模型相对平均值基线提升了多少,RMSE和MAE表示预测误差的量级。
| 指标 | 典型数值范围 | 说明 |
|---|---|---|
| R² | 0.45 ~ 0.60 | 模型解释了45%到60%的票房对数方差 |
| RMSE | 1.1 ~ 1.4 | 在对数空间里,平均误差大约在1.1到1.4个自然对数单位 |
| MAE | 0.8 ~ 1.1 | 比RMSE更稳定,受极端值影响小 |
这个结果不是特别高,但它是真实合理的。答辩时你应该主动说出这个局限性:电影票房受档期竞争、口碑传播、发行策略等大量模型无法观测的因素影响,仅靠TMDB元数据本身,能解释50%左右的方差已经是正常水平。说了这句话,老师就不会用“你的R²怎么不高”来问你,反而会觉得你有清醒的认知。
4.6 从Loss曲线判断过拟合
训练过程别忘了保存Loss曲线图。这个图要放进论文和答辩PPT里。典型的过拟合表现是:训练Loss持续下降,验证Loss先下降后回升。出现这种情况,就说明模型开始“背答案”而不是“学规律”了。
我在项目里第一次跑出来的图就是这样:训练集MAE降到0.6,测试集MAE还在1.0以上。后来加了Dropout和EarlyStopping,测试集MAE才下降到0.9左右。答辩的时候把这两条Loss曲线对比展示,会非常有说服力,它证明你真正理解了过拟合的诊断方法。
5. 把分析成果变成可演示系统:Flask集成的细节
5.1 为什么系统展示是必备的一环
毕设光有Jupyter Notebook里的分析过程,答辩时老师很难快速看到成果,演示效果也差。把分析结论和模型封装成一个Web页面,好处是直观、可交互、也说明你具备一定的工程落地能力。
技术选型上,我推荐Flask+Pyecharts。Flask足够轻量,几十行代码就能跑起一个Web服务;Pyecharts生成图表HTML,可以直接嵌入Jinja2模板。如果你的项目还涉及用户上传数据、实时计算,Flask也完全够用,没有必要为了“显得高级”去上Django。
5.2 页面结构怎么设计
我建议系统分三个页面或三个区域:
第一块是数据概览:展示数据集规模、字段数量、缺失值比例、关键指标统计卡片。第二块是数据分析:放三张核心图,预算票房散点图、类型评分箱线图、年份产量折线图。第三块是票房预测:用户输入预算、时长、类型、热度等信息,点击预测按钮,返回预测票房区间。
前端布局不用复杂,一个带导航的HTML模板,用Bootstrap搭栅格,或者直接用简单的CSS,重点是把图和交互功能放在最显眼的位置。
5.3 模型部署的完整流程
模型训练好之后,要保存两种文件:模型权重和归一化参数。否则预测时输入数据没有经过同样的归一化,预测结果就是错的。
import joblib model.save('model.h5') joblib.dump(scaler, 'scaler.pkl')Flask端加载模型:
from flask import Flask, request, jsonify, render_template import numpy as np import joblib from tensorflow.keras.models import load_model app = Flask(__name__) model = load_model('model.h5') scaler = joblib.load('scaler.pkl') @app.route('/') def index(): return render_template('index.html') @app.route('/predict', methods=['POST']) def predict(): data = request.get_json() # 输入字段: budget, runtime, popularity, vote_count, release_year, release_month features = np.array([[ np.log1p(float(data['budget'])), float(data['runtime']), float(data['popularity']), float(data['vote_count']), int(data['release_year']), int(data['release_month']) ]]) features_scaled = scaler.transform(features) pred_log = model.predict(features_scaled, verbose=0)[0][0] pred_value = np.expm1(pred_log) return jsonify({'predicted_revenue': round(float(pred_value), 2)}) if __name__ == '__main__': app.run(debug=True)有两个细节容易出问题:一是预测端必须复用训练时的scaler,不能重新fit;二是前端输入如果是原始美元值,后端要先np.log1p再进scaler,顺序颠倒结果会完全不对。
5.4 答辩现场演示节奏
现场演示非常考验节奏把控。我的建议是控制在8到10分钟:
| 时间 | 演示内容 | 想传达给老师的核心信息 |
|---|---|---|
| 前2分钟 | 数据集规模、字段 | 我用了什么数据,数据来源可靠 |
| 中间3分钟 | 三张分析图 | 我有分析结论,不是堆图 |
| 接下来3分钟 | 模型结构+Loss曲线+评估指标 | 我理解深度学习原理,会诊断问题 |
| 最后2分钟 | 现场输入一部电影参数,看预测结果 | 系统能跑通,工程能力过关 |
6. 答辩避坑实录:从Loss为NaN到回答不上来的问题
6.1 一个完整的排查案例:训练Loss为什么变成了NaN
这个坑我见过太多人踩,我自己也踩过。现象是训练到第三个epoch,Loss直接变成nan,后面所有指标全部是nan。
排查过程是这样的:
第一步,检查是不是学习率太高。把Adam默认的学习率从0.001降到0.0001,重新训练,还是nan。排除学习率因素。
第二步,检查特征矩阵里有没有NaN。用np.isnan(X_train).any()排查,结果没有NaN。排除特征缺失。
第三步,检查标签。这一查就发现了问题:当年在做特征工程时,为了处理revenue为0的情况,我直接用了np.log(df['revenue'])而不是np.log1p。revenue等于0的行会对log求值得到-inf,-inf作为标签参与MSE或Huber Loss计算,梯度直接变成NaN。
修复方法很简单:所有log操作统一改成np.log1p,或者在清洗阶段就剔除revenue为0的行。
# 错误写法 df['revenue_log'] = np.log(df['revenue']) # revenue=0 时为 -inf # 正确写法 df['revenue_log'] = np.log1p(df['revenue']) # revenue=0 时为 0这个排查过程本身就有答辩价值。老师问你“模型训练遇到问题时你怎么排查”,你把这个链路讲一遍,比背任何算法原理都更能证明你的实际工程能力。
6.2 这个“模型前处理+后处理”的坑
还有一个容易出错的点:模型预测结果是对数空间的值,要还原成原始票房一定要用np.expm1。如果用了np.exp,0值对应的就是1而不是0,计算误差会被放大;更重要的是,预测值本身可能有误差累积,post-processing的正确性在答辩演示时是要被亲眼检验的。
6.3 答辩高频问题及应答思路
整理了一组答辩老师大概率会问的问题,提前准备好,被问住的风险会小很多。
| 老师可能问的问题 | 正确的回答思路 |
|---|---|
| 数据从哪里来的 | 公开的Kaggle TMDB 5000 Movie Dataset,由TMDB社区维护 |
| 缺失值为什么这样处理 | 说清楚0值不等于缺失,所以单独做标记;日期缺失影响时间分析,所以剔除 |
| 为什么用DNN而不用线性回归 | 特征间存在非线性交互,DNN能自动学习;样本量不允许用大模型 |
| 为什么R²只有0.5左右 | 票房受外部因素影响大,现有特征只能解释部分方差,这是数据本身的限制 |
| 模型的参数量有多少 | 三层DNN总参数量在1万到2万之间,适合这个样本规模 |
| 这个项目能不能上线使用 | 不能,预测精度不足以支撑商业决策,但完整的分析链路和方法可以复用 |
| 可视化用了哪些库 | 论文图用Seaborn,系统页面用Pyecharts,各司其职 |
6.4 被问到“深度学习是不是噱头”怎么答
这个问题不好回答,但完全可以应对。核心思路是:深度学习在本项目不是噱头,因为对比实验表明,DNN在测试集上的R²比线性回归高出8到10个百分点,说明非线性交互是真实存在的。如果时间允许,可以在论文里加一个模型对比小节,放线性回归、决策树、DNN三个模型的评估结果对比表。这个对比表是“深度学习有用”的最直接证据。
6.5 最后再分享一点实操经验
作为一个做过多次这类项目的过来人,我最想提醒你的一点是:从项目第一天开始,就为答辩准备材料。数据清洗的每一次筛选,都记录下筛选前后的样本量和原因;模型的每一次实验,都保存Loss曲线和评估指标;Web系统的每一步修改,都截图留档。这些东西最后会成为你论文里的实验章节和答辩PPT的素材,省得到最后几天翻Jupyter Notebook找数字。
TMDB电影数据分析与可视化这个题目,表面看平平无奇,但如果能把数据解析、清洗策略、可视化结论、深度学习建模、Web集成这一条链路完整做下来,答辩时你手里有的不只是几张图,而是一套可以讲清楚“为什么这么做”的完整项目。祝答辩顺利。