做毕业设计选题的时候,我在“新闻大数据”这个方向上纠结了很久。新闻数据天然具备三个特点:量大、实时、带有明显的情绪倾向,这让它成为同时展示爬虫、自然语言处理和时序预测三大技术点的绝佳载体。最终我定了“AI大模型:python新闻数据可视化分析系统”这个题目,技术路线很清晰——requests爬虫采集新闻数据,SnowNLP做情感分析,ARIMA模型做时间序列预测,最后用Flask+ECharts把结果可视化展示出来。这篇文章就把整条链路完整拆开,从数据采集到预测落地,给正在做相关毕业设计、或者想入门数据分析和NLP的朋友当一份参考地图。
先说明一下,这套方案不是纸上谈兵。我完整做过一遍,也陪着好几届学弟学妹走过类似的选题,知道哪里会卡壳、哪里能偷懒、哪里必须死磕。下面把这些经验一次说清楚。
1. 项目整体设计与技术选型思路
1.1 为什么选这个题目:兼顾技术广度与完成度
毕业设计最怕的是“题目看着高大上,但三个月做不出来”。新闻可视化分析系统这个题目之所以稳妥,是因为它的技术链路完整但不极端。
爬虫是Python最成熟的方向之一,有大量现成库可以用;SnowNLP是一个开箱即用的中文情感分析库,不需要自己从零训练深度模型;ARIMA是统计学经典模型,statsmodels库封装得很完善,数学门槛可控;可视化用ECharts,出图效果直接拉满。整条链路每一环都有成熟的工具支撑,适合在有限时间内做出完整成果,而且每一步都能讲出原理,不会让答辩变成“调包侠”现场。
很多同学习惯在选题时走两个极端。一个是纯调包,全用现成模块拼起来,比如爬点数据画几个图就交差,答辩时老师一问算法原理就答不上来;另一个是纯造轮子,非要自己从零实现情感分析模型,结果训练数据、调参、算力全都不够,项目烂尾。我自己这个方案处在中间——每个环节都有底层原理需要讲清楚,又有成熟的库来降低开发成本。既能体现工作量,又能把核心原理讲明白,这正是评审老师愿意看到的状态。
1.2 技术栈选型:为什么是这些库而不是别的
先把完整的技术栈列出来:
| 模块 | 技术选型 | 选型理由 |
|---|---|---|
| 数据采集 | requests + BeautifulSoup + 多线程 | 轻量灵活,适合中小规模新闻站点采集 |
| 数据存储 | SQLite / Pandas + CSV | 毕业设计级够用,免部署,可视化查看方便 |
| 文本清洗 | re正则 + jieba分词 | 中文场景通用方案,处理新闻标题与正文 |
| 情感分析 | SnowNLP | 基于朴素贝叶斯,中文场景开箱即用,可训练自定义模型 |
| 时序预测 | statsmodels ARIMA | 经典统计模型,对趋势性数据表现稳定,可解释性强 |
| 可视化 | ECharts + Flask | ECharts交互效果好,Flask轻量易集成,答辩演示方便 |
| 大模型辅助 | 调用LLM API做摘要与解读 | 呼应题目中的“AI大模型”,体现AI增强能力 |
这里说下为什么没用Scrapy。Scrapy功能强大,但学习曲线陡,对单个新闻站点中小规模的采集来说有点重。requests+BeautifulSoup的组合足够应付毕业设计的数据量需求,代码直观,答辩时能讲清楚每一行在干什么。当然,如果题目里明确写了“分布式爬虫”,那Scrapy就是必修课——但这个题目没到这个复杂度,没必要为难自己。
关于“AI大模型”这个前缀,我把它落在两个地方:一是新闻文本的智能摘要提取,调用大模型API生成每条新闻的一句话摘要;二是情感分析结果的整体解读,让大模型把当天“新闻情绪”翻译成一段人话。这样既扣住题目中的“AI大模型”,又不喧宾夺主,核心算法依然是SnowNLP和ARIMA。如果你也想在毕业设计里挂“大模型”的名头,推荐这种“辅助增强”的落点,而不是强行让大模型替代核心算法,否则工作量会完全失控。
2. 新闻数据采集模块设计要点
2.1 数据源选择:合规与稳定是第一原则
数据源是整个系统的地基。第一步就要把目标源定下来,我的建议是优先选这三类:
- 新闻网站的RSS输出,最省事,结构固定,基本无反爬;
- 自带开放API的新闻平台;
- 综合新闻站点的列表页加详情页,需要自己写解析规则。
这里必须强调底线问题:爬虫只采集公开可访问的数据,采集前先看robots.txt,尊重网站的访问声明;单线程或低并发限速采集,不要给对方服务器造成压力;采集到的数据仅用于学习研究,绝不用于商业用途或公开传播。毕业设计答辩时老师大概率会问数据来源合规性,你得清楚说出“数据公开、频率克制、用途正当”这三点。
我最终选择的是某新闻门户的科技频道列表页作为主数据源。列表页每天更新几十条新闻,每条包含标题、发布时间、来源、摘要,点进详情页还能拿到正文。整个采集脚本控制在150行以内,逻辑非常清晰,维护成本也不高。
2.2 多线程采集与反爬规避的平衡
提到爬虫,大家最关心反爬。我实际遇到的干扰主要是两类:请求频率过高触发IP临时限制,UA特征明显被识别。解决方案比较朴素:
import requests from bs4 import BeautifulSoup from concurrent.futures import ThreadPoolExecutor import time import random HEADERS = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", "Accept-Language": "zh-CN,zh;q=0.9", } def fetch_news_list(page_url): """获取新闻列表页并提取每条新闻的链接与标题""" resp = requests.get(page_url, headers=HEADERS, timeout=10) resp.encoding = "utf-8" soup = BeautifulSoup(resp.text, "html.parser") items = [] for li in soup.select(".news-list li a"): title = li.get_text(strip=True) href = li.get("href") if title and href: items.append({"title": title, "url": href}) return items def fetch_news_detail(item): """抓取详情页正文,并做简单清洗""" try: resp = requests.get(item["url"], headers=HEADERS, timeout=10) resp.encoding = "utf-8" soup = BeautifulSoup(resp.text, "html.parser") content_div = soup.select_one(".article-content") if content_div: content = content_div.get_text(separator="\n", strip=True) item["content"] = content else: item["content"] = item["title"] time.sleep(random.uniform(0.5, 1.5)) # 限速,不要给对方服务器压力 return item except Exception as e: print(f"[采集失败] {item['url']} -> {e}") return None # 使用线程池并发采集详情页 with ThreadPoolExecutor(max_workers=4) as executor: results = list(executor.map(fetch_news_detail, news_items))实测心得:
- max_workers设4就够,太大容易触发反爬。见过一些同学一上来就开几十个线程,数据没采多少,IP先进了黑名单。
- 每次请求之间加随机延时,模拟真人访问,这个“浪费”的时间换来的是采集的稳定性。
- 如果目标网站做了更严格的反爬,比如需要登录、JS渲染、滑块验证,别硬刚。换一个数据源,或者改用Selenium/Playwright做浏览器渲染,都是更省力的选择。新闻数据是海量存在的,可选源很多,执念最不值钱。
2.3 数据清洗与存储:脏数据比你想的更缠人
爬下来的原始数据直接进数据库是不行的。新闻数据的“脏”主要体现在这几个方面:
- 标题里混入“【专题】”“|”等栏目前缀;
- 正文里夹杂推广链接、图片alt文本、脚本残留;
- 发布时间格式不统一,有的是“2024-12-01 10:23”,有的是“12月1日”;
- 部分详情页404,抓到空正文。
我的清洗思路是“正则+白名单策略”。先定义一条新闻需要保留的最小字段集合:标题、发布时间、来源、正文纯文本、URL。然后:
import re def clean_title(title): """去掉标题中的栏目前缀和杂质""" title = re.sub(r"^【.*?】", "", title) title = re.sub(r"\s*[|\|]\s*.*$", "", title) return title.strip() def clean_content(content): """去除正文中的脚本、样式、空行""" content = re.sub(r"<script.*?</script>", "", content, flags=re.S) content = re.sub(r"<style.*?</style>", "", content, flags=re.S) content = re.sub(r"\n{3,}", "\n\n", content) return content.strip()存储我用了SQLite。原因很简单:零配置、单文件、Python内置sqlite3模块直接支持,对毕业设计的数据量,几万条以内完全够用。建表语句:
CREATE TABLE IF NOT EXISTS news ( id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT NOT NULL, publish_time TEXT, source TEXT, content TEXT, url TEXT UNIQUE, crawl_time TEXT DEFAULT CURRENT_TIMESTAMP );这里建议给URL加UNIQUE约束,防止重复采集。后面做去重、更新、增量采集都方便很多。
3. SnowNLP情感分析:中文文本的情绪判定
3.1 朴素贝叶斯与SnowNLP工作原理
SnowNLP是一个专门针对中文文本的Python库,核心是一个基于朴素贝叶斯分类器的情感判断工具。给定一段文本,它计算这段文本是正面还是负面的概率,输出一个0到1之间的情感分数。越接近1代表越正面,越接近0代表越负面,0.5附近代表中性。
原理并不复杂。朴素贝叶斯公式:
P(正面 | 文本) = P(文本 | 正面) × P(正面) / P(文本)
实际实现中,SnowNLP会把文本分词,然后假设每个词的出现是相互独立的——这正是“朴素”的含义——用语料中每个词在正面文本和负面文本中的出现频率,计算整个文本的正面概率。虽然“词与词相互独立”这个假设在真实语言中并不成立,但对于情感倾向这种粗粒度的判断,效果已经足够好。
SnowNLP自带的模型是用电商购物评论训练的,这带来一个我在项目中实际遇到的问题:它对新闻类文本的适应性一般。购物评论里“质量好”“物流快”“客服热情”是高频正面词,而新闻文本里大量出现的是“发展”“增长”“宣布”“发布”这类中性词,负面新闻则常用“事故”“违规”“暴跌”等词。默认模型看到“某公司发布新一代产品,性能大幅提升”这种句子,判断偏正面,这个大体是准的;但遇到“某公司因违规操作被处罚,市值蒸发”这类句子,它容易被“公司”“产品”这类中性词干扰,导致结果偏中性,不够尖锐。
3.2 优化策略:训练自定义情感模型
要解决SnowNLP对新闻文本适配度一般的问题,有两条路。一条是直接调用大模型API做情感判断,精度高,但成本高、速度慢;另一条是利用SnowNLP官方的训练机制,用标注好的新闻语料重新训练情感分类器。
我的实际策略是“两条腿走路”:核心情感指标用SnowNLP跑全量数据,速度快,能算出每天的总体情感走势;同时用大模型对部分重点新闻做细粒度的情感与立场分析,形成对照。这样既保证了效率,又在关键环节展示了“AI大模型”的能力。
SnowNLP支持自定义训练,操作很直接。准备两个文本文件,一个全是正面文本,一个全是负面文本,然后调用训练接口生成新模型:
from snownlp import sentiment # 每行一条语料 with open("pos_news.txt", "r", encoding="utf-8") as f: pos_texts = f.read().split("\n") with open("neg_news.txt", "r", encoding="utf-8") as f: neg_texts = f.read().split("\n") # 训练并保存模型 sentiment.train(pos_texts, neg_texts) sentiment.save("sentiment.marshal")预测时指定模型路径:
from snownlp import SnowNLP s = SnowNLP("某科技公司发布新一代AI芯片,性能大幅提升", path="sentiment.marshal") print(s.sentiment)训练工作里最耗时的是标注语料,大概标了800条正面、800条负面新闻语料,够用了。如果你想省事,也可以直接调用默认模型,但建议在论文和答辩中主动说明默认模型的局限,并展示你的优化思路——这反而是加分项。
3.3 情感分析结果的可视化设计
情感分析产出的核心指标是每条新闻的情感得分,但单纯展示一堆0到1的小数是没意义的。我做的是三个层次的聚合展示:
- 日粒度情感均值曲线:把每天所有新闻的情感得分取平均,画成折线图,看一段时间内情绪走势;
- 正/中/负面新闻占比图:设定阈值,得分大于0.6算正面,小于0.4算负面,中间算中性,按天统计占比;
- 极端情感新闻Top榜:找出情感得分最高和最低的几条新闻,配合大模型摘要,展示“为什么这条新闻被判定为极端正面或负面”。
核心计算逻辑:
import pandas as pd from snownlp import SnowNLP # df是包含title和publish_time的DataFrame df["sentiment_score"] = df["title"].apply(lambda x: SnowNLP(x).sentiment) df["date"] = pd.to_datetime(df["publish_time"]).dt.date daily_sentiment = df.groupby("date")["sentiment_score"].mean().reset_index() print(daily_sentiment.tail())这里有一个细节:情感分析用标题还是正文?我的实测结论是,标题的情感信息密度更高。新闻标题往往凝练了最核心的情绪倾向;正文虽然信息全,但大量中性描述会稀释情感浓度。所以我先用标题计算情感得分,遇到标题过短的再结合正文首段。
4. ARIMA时间序列预测:新闻热度趋势怎么预测
4.1 为什么要用ARIMA:统计学模型的经典价值
做新闻数据趋势预测时,可选方案很多:LSTM、Prophet、XGBoost,甚至大模型。但在毕业设计场景下,我强烈推荐ARIMA,原因有三个:
- 可解释性强。ARIMA的每一个参数都有明确的统计含义,答辩时能讲清楚“为什么是这个参数”;换成LSTM,老师一问调参逻辑,很难讲透。
- 对数据量要求低。新闻情感均值和新闻数量是典型的日粒度数据,样本量通常只有几百条,LSTM在这种小样本上几乎学不到东西,ARIMA则在小样本时间序列上表现稳健。
- 实现成本低。statsmodels库现成可用,效果可量化,论文篇幅也好展开。
ARIMA全称是自回归积分滑动平均模型,括号里通常带三个参数:ARIMA(p,d,q)。分别代表:
- p:自回归项数,用过去几个时刻的值来预测当前值;
- d:差分次数,为了让时间序列平稳,需要做几阶差分;
- q:滑动平均项数,用过去几个时刻的预测误差来修正当前预测。
通俗理解:AR看的是“过去值”对当前的影响,MA看的是“过去误差”对当前的影响,差分是对付数据不稳定的手段。新闻数量这类数据往往存在明显的趋势和波动,直接建模效果不好,需要先差分消除趋势,再用AR和MA捕捉剩余规律。
4.2 建模流程:平稳性检验、定阶、拟合、评估
ARIMA建模有一条固定的操作流水线,我总结成四步。
第一步,构造并检查时间序列。以“每天发布的新闻数量”或“每日情感得分均值”作为预测目标,按日期整理成pd.Series:
import pandas as pd # 统计每日新闻数量 daily_count = df.groupby("date")["id"].count() daily_count.index = pd.to_datetime(daily_count.index) print(daily_count.head())第二步,平稳性检验。ADF检验是判断序列是否平稳的标准工具:
from statsmodels.tsa.stattools import adfuller result = adfuller(daily_count.dropna()) print(f"ADF统计量: {result[0]:.4f}") print(f"p值: {result[1]:.4f}") if result[1] < 0.05: print("序列平稳,无需差分") else: print("序列不平稳,需要进行差分")如果p值大于0.05,说明序列不平稳,需要对序列做一阶差分,然后重新检验。差分本质上就是计算相邻两天的差值:diff_t = value_t - value_{t-1},它能去掉趋势让序列围绕均值波动。
第三步,模型定阶。定阶有两种方法:看ACF/PACF图的截尾拖尾特征,或者用AIC/BIC信息准则自动搜索。手工看图需要经验,推荐两者结合:先用自动搜索缩小范围,再人工确认。
import warnings warnings.filterwarnings("ignore") from statsmodels.tsa.arima.model import ARIMA best_aic = float("inf") best_order = None for p in range(0, 4): for d in range(0, 2): for q in range(0, 4): try: model = ARIMA(daily_count, order=(p, d, q)) model_fit = model.fit() if model_fit.aic < best_aic: best_aic = model_fit.aic best_order = (p, d, q) except Exception: continue print(f"最优模型: ARIMA{best_order}, AIC={best_aic:.2f}")AIC(赤池信息准则)是一个兼顾拟合优度和参数数量的指标,值越小代表模型在“解释数据”和“保持简单”之间平衡得越好。遍历出来的最优参数通常就是合理答案。
第四步,拟合与预测评估。将数据划分为训练集和测试集,比如前80%做训练,后20%做验证,用滚动预测的方式评估误差:
from sklearn.metrics import mean_absolute_error, mean_squared_error import numpy as np train_size = int(len(daily_count) * 0.8) train, test = daily_count[:train_size], daily_count[train_size:] model = ARIMA(train, order=best_order) model_fit = model.fit() forecast = model_fit.forecast(steps=len(test)) mae = mean_absolute_error(test, forecast) rmse = np.sqrt(mean_squared_error(test, forecast)) print(f"MAE: {mae:.2f}, RMSE: {rmse:.2f}")4.3 预测结果展示与局限性说明
预测结果通过ECharts展示成“历史+预测”的折线图。历史部分用实线,预测部分用虚线,再给预测值画一个置信区间阴影带。这样不仅能直观展示趋势,还能体现你对预测不确定性的理解。预测值不是确定的点,而是一个区间,越往后置信区间越宽,这是时间序列模型的内在特性。
我必须提醒一个容易踩坑的点:新闻数据本质上非常难以预测,因为它受突发事件的驱动。可能昨天还很平稳,今天一件大事就彻底打破规律。ARIMA适合做“惯性趋势”的预测——比如在没有突发事件的情况下,新闻发布量会维持在一个平均水平附近,情感均值会延续近期的走势——但不要指望它能准确预报“明天会出什么大新闻”。在论文里,我把这部分定位为“基于历史规律的短期趋势参考”,并用置信区间来表达不确定性,这既符合学术规范,也避免了答辩时“预测不准怎么办”的尴尬。
4.4 给答辩准备的追问清单
关于ARIMA,答辩老师大概率会问这些问题,建议提前想好答案:
- 为什么不用LSTM?答:新闻数据的样本量只有几百天,LSTM需要大量数据才能训练,小样本下ARIMA表现更好且可解释性更强。
- 序列存在季节性怎么办?答:可以考虑SARIMA,它在ARIMA基础上加了季节分量,参数变成(p,d,q)(P,D,Q,s),其中s是季节周期。
- 预测结果不稳定怎么解释?答:新闻数据受随机突发事件影响大,模型捕捉的是系统性趋势而非随机噪声,预测置信区间也反映了不确定性。
5. 系统集成与可视化界面实现
5.1 Flask + ECharts的整体架构
系统的工程形态是一个本地Web应用:Python后端负责数据处理、模型计算、API输出,前端负责可视化展示。这个架构的好处是演示方便,答辩时打开浏览器就能看到完整效果,不像Jupyter Notebook那样零散。
后端用Flask实现,核心路由不超过5个:
from flask import Flask, jsonify, render_template import pandas as pd app = Flask(__name__) @app.route("/") def index(): return render_template("index.html") @app.route("/api/sentiment_daily") def sentiment_daily(): # 从SQLite读取数据,计算每日情感均值 df = pd.read_sql_query("SELECT publish_time, title FROM news", conn) df["sentiment_score"] = df["title"].apply(lambda x: SnowNLP(x).sentiment) df["date"] = pd.to_datetime(df["publish_time"]).dt.date result = df.groupby("date")["sentiment_score"].mean().reset_index() return jsonify(result.to_dict(orient="records")) if __name__ == "__main__": app.run(debug=True, port=5000)前端页面用ECharts渲染,核心是拿到后端API返回的JSON数组,配置图表参数:
fetch('/api/sentiment_daily') .then(res => res.json()) .then(data => { const dates = data.map(d => d.date); const scores = data.map(d => d.sentiment_score); const chart = echarts.init(document.getElementById('sentimentChart')); chart.setOption({ tooltip: { trigger: 'axis' }, xAxis: { type: 'category', data: dates }, yAxis: { type: 'value', name: '情感得分', min: 0, max: 1 }, series: [{ name: '每日情感均值', type: 'line', data: scores, smooth: true, areaStyle: { opacity: 0.15 } }] }); });5.2 三大核心页面与功能设计
系统里做了三个核心页面,对应三个分析维度。
数据总览页。顶部是KPI卡片,显示总新闻量、情感均值、最近更新时间、正负面占比;中间是新闻发布量时间分布柱状图;下方是新闻列表,支持按情感倾向筛选。
情感分析页。左侧是每日情感均值折线图,右侧是正/中/负占比环形图,下方是情感Top榜,每条新闻配一句大模型生成的短评,解释为什么被判定为正面或负面。
趋势预测页。展示ARIMA模型的预测结果,包含历史数据与未来7天预测值及置信区间,旁边附模型参数(p,d,q值、AIC、MAE、RMSE)和一段大模型生成的趋势解读,把冷冰冰的模型指标翻译成人话。
5.3 细节体验优化:答辩演示的加分项
有几个小细节在答辩演示时非常加分:
- 所有图表都设置loading状态,切换页面不会白屏;
- 情感Top榜的新闻卡片用颜色区分情绪倾向,视觉上“一眼见情绪”;
- 增加一个时间范围选择器,可以只看最近7天、30天或全部数据。这个功能本身代码量很小,但展示了数据交互意识;
- 前端用原生HTML+JS+ECharts CDN,不引入重前端框架。毕业设计的重点在算法与流程,不必为了“炫技”把工程复杂度拉满。
6. 常见问题与排坑记录
6.1 爬虫采集过程中的典型问题
先说采集阶段我实际遇到过的问题和解决办法。
列表页结构变了。网站改版是爬虫的常态。用CSS选择器写好的解析规则,某天一跑发现全空了。应对方案是:解析之前先打印HTML片段检查,确认是网站结构变了还是请求被拦截。确认结构变了就改用更宽松的解析规则,或者准备一个备用数据源。
抓到的正文大量重复。有些网站把“相关阅读”“热门推荐”模块也抓了进来。解决办法是只选取正文容器节点,并过滤包含ad、recommend、related等关键字的子节点。
编码问题导致乱码。国内新闻站大多是utf-8或gbk。建议requests拿到响应后先看headers里的charset,再决定用哪个编码解码。
6.2 SnowNLP情感分析的准确性调优
用默认模型时,最头疼的是它会把不少中性新闻判断为正。调试经验是:先用小批量数据比如500条跑一遍,随机抽50条人工看结果。你会发现判断错误的模式高度集中,要么是专业术语导致误判,要么是句式太长吸收不了关键情绪词。针对性优化方法有三个:
- 补充自定义词典,把新闻领域高频情感词加进分词器;
- 训练自己的情感模型,用标注语料重新训练;
- 只对标题做情感分析,减少无关内容的干扰。
6.3 ARIMA预测效果不好时的排查方向
跑完ARIMA发现预测结果很差,按这三个方向排查:
- 数据没预处理干净。时间戳重复、空值、异常跳变都会直接影响模型效果。先做缺失值填补,可以用前值填充或插值,再剔除极端离群点;
- d阶数选错了。序列不平稳会导致预测严重偏移,重新做ADF检验,确认差分次数;
- 测试集太小。新闻数据本身噪声大,如果测试集只有3到5天,误差指标波动会很大。测试集至少占样本总量的15%。
还有一个经验:不要直接预测原始新闻数量,可以先取对数,或者用滑动平均平滑掉短期波动,模型效果会明显提升。在预测“每日情感均值”时我也用了类似思路——情感均值本身被压缩在0到1区间,模型预测容易偏向中间值,结合滑动平均处理后再建模会更稳定。
6.4 毕业设计全流程节奏建议
最后聊一个容易被忽略但又很重要的问题:怎么控制整个毕业设计的节奏。建议分成四个阶段,每个阶段留出缓冲时间。
- 阶段一(2周):数据采集与清洗。目标拿到持续积累的干净结构化数据。数据要尽早开始积累,因为时序预测需要历史数据,数据越多模型效果越好;
- 阶段二(2周):情感分析与数据探索。跑通SnowNLP,产出情感分析结果,从数据中找故事;
- 阶段三(3周):ARIMA建模与调参。重点是定阶逻辑和评估流程,这部分论文里的篇幅最多;
- 阶段四(2周):系统集成与界面。把所有环节串成Web应用,整理演示脚本。
阶段四只留2周看似紧张,其实不然。前三个阶段已经把核心指标都算好了,集成阶段只是把结果“搬”到页面上而已。真正怕的是前面卡壳,比如数据结构不统一、模型一直跑不出理想结果,所有时间都花在调试上,最后来不及做界面。这是历届同学翻车的重灾区。
6.5 关于“AI大模型”功能的落地细节
题目里带“AI大模型”字样的话,建议把大模型能力的集成做得“看得见、讲得清”。什么叫讲得清?老师在答辩时问“你的系统哪里用到了大模型”,你不能含糊地说“用GPT做了摘要”。要把三件事说明白:
- 调用的是哪个API、什么模型规模;
- prompt是怎么设计的,输入什么、输出什么;
- 大模型产出的内容在系统里起到什么作用,和传统方法比差异在哪。
我在系统里做了两个大模型功能点:一个是对单条新闻生成一句话摘要,放在新闻卡片上;另一个是每天生成一段“新闻情绪回顾”,基于当天情感分析结果和Top新闻生成叙事性总结。展示效果好,因为用户能直接感知到“AI的存在”,同时代码量很小,只是封装一个调用LLM API的函数。如果不方便申请付费API,本地部署一个开源小模型也可以,但要注意本地小模型在新闻摘要上的质量通常不如成熟API,答辩效果会打折扣。
整个项目做下来,我最大的体会是:数据分析和机器学习类毕业设计,最难的不是某个算法,而是把“数据获取—数据处理—算法建模—结果呈现”这条链路完整跑通。爬虫、SnowNLP、ARIMA这三个技术点任何一个单拎出来都不算难,但把它们放进一个系统里,每一步都会遇到真实的工程问题。数据源变了、文本清洗不彻底、时间序列不平稳、预测结果被质疑,这些坑你多踩几个,反而能把原理理解得更深。
如果你也在做类似方向的毕业设计,不用追求大而全,也不要想着一口气把所有模块做到完美。先把最小链路跑通,让数据从采集到展示形成闭环,再逐步优化每个环节。最后分享一个小技巧:所有图表和页面做完后,都要用真实数据完整走一遍演示流程。答辩时真正能问倒你的,往往不是评委老师,而是你自己写出来的那些假设。别让“我以为这里没问题”成为最后的遗憾。