news 2026/10/3 2:46:24

新闻标题分类系统实践:从TF-IDF到线性SVM的短文本分类指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
新闻标题分类系统实践:从TF-IDF到线性SVM的短文本分类指南

简介:面向人工智能、机器学习与深度学习方向的毕业设计及课程设计,天津科技大学本科毕业设计“基于机器学习的新闻标题分类系统”提供了一套从数据预处理、模型训练到网页端展示的完整参考方案。压缩包共63个文件,大小约10.93MB,包含7个核心脚本、16个网页页面、8个前端样式与交互脚本、9个文本数据及中文停用词表,并带有数据库脚本、交互式笔记、论文文档和说明文档,覆盖了工程实现、实验记录与文档材料。已有88人学习或下载,项目以轻量级网页框架搭建交互模块,可在浏览器中直观查看分类结果;预处理和训练脚本配合训练集、测试集及停用词表,可复现完整实验流程;数据库脚本提供数据表结构,笔记和论文文档记录了建模思路与最终成果。适合需要参考完整机器学习项目结构并快速上手中文文本分类实践的学生与开发者。

1. 从一篇本科毕设说起:新闻标题分类系统到底在解决什么问题

新闻标题分类,是 NLP 文本分类里最“短文本”的一类任务——输入只有一句话通常不到 30 个字,却要判断出财经、体育、娱乐、科技这类主题标签。放在毕业设计里做“基于机器学习的新闻标题分类系统”,本质上是在验证一条链路:拿新闻标题这种高噪声短文本,经过清洗、向量化、选模型、调参、评估,最终产出一个能批量打标签的分类器。这个方向最友好的地方在于,它不要求你有 GPU、不要求懂深度学习,用 sklearn 就能跑出可用结果,而且效果好坏一眼就能看出来——准确率、F1 这些指标比很多“看起来高级”的项目要直观得多。适合第一次完整接触“机器学习怎么落地”的本科生,也适合想在自己业务里快速验证文本分类可行性的从业者。

这套系统的核心问题很聚焦:标题文本太短,信息密度低,同义词和口语化表达又多,传统 TF-IDF 加线性模型是绝大多数毕设和入门项目的首选方案,而换到深度学习反而容易出现“数据量不够、过拟合严重”的翻车现场。所以这篇笔记会照着一条我在类似项目里反复走通的路线来讲——先把任务拆清楚,再给出一套能直接运行的实现,接着讲评估和调参,最后把最容易踩的坑逐个点名。整个过程中涉及到的机器学习算法选型、训练评估循环、以及模型导出这些环节,都会落到代码或具体参数上,照着做就能复现,而不是看完只记住几个名词。

2. 标题分类的技术底座:为什么短文本分类首选 TF-IDF + 线性模型

2.1 新闻标题分类的本质:一个多分类问题

先明确任务边界。输入是一个字符串,比如“XX 队客场逆转晋级决赛”,输出是一个离散标签,比如“体育”。这属于有监督多分类,类别之间互斥。跟长文本分类比,新闻标题有几个很明显的脾气:长度短(平均 15-30 个字符),没有上下文兜底,实体词和动作词占比高,还经常出现平台特有的标题党风格。这些特点决定了模型选择的方向——不是越复杂越好,而是越能抗稀疏、抗噪声越好。

从机器学习角度拆解,这个任务可以分成四个环节:数据获取与标注、文本表示(特征工程)、模型训练与评估、模型导出与应用。大部分毕设翻车都翻在前两个环节:数据集质量不行,或者向量化做得太草率,后面模型再换也救不回来。这也是为什么我在做这个方向时,会花至少一半时间在数据处理上,而不是急着调模型。

常见的公开数据集有 THUCNews 的子集、搜狗新闻语料,但很多下载链接已经失效;更可靠的路径是用爬虫自己去抓固定来源的新闻,按频道归类。这里有个细节:抓下来的数据一定要保留来源频道作为标签,而且要过滤掉“非新闻”页面,比如导航栏、相关推荐这些噪声。分类体系的设定也直接影响难度,类别越多、越接近(比如“时尚”和“娱乐”),模型就越难分。毕设一般控制在 5-10 个类别比较稳妥。

2.2 文本向量化:TF-IDF 为什么比 Word2Vec 更适合这个任务

文本不能直接进机器学习模型,得先变成向量。这个词到向量的映射方式直接决定模型效果的上限。常见的几种做法,我在不同项目里都试过,放在一起对比才能看出差距。

TF-IDF 的核心逻辑是 TF 词频乘以 IDF 逆文档频率。一个词在标题里出现次数越多越重要,但如果在所有文档里都频繁出现,那区分度就不高,权重会被压低。公式不复杂,但有两个参数值得注意:min_df和max_df,用来过滤掉只出现一两次的生僻词和几乎每篇都有的停用词。对新闻标题这个场景,min_df设为 1-2,max_df设为 0.7-0.9 左右是常见起点。

Word2Vec 的思路是用上下文预测词向量,产出的是稠密向量,理论上有语义信息。但它在短文本场景有个明显的坑:标题词太少,平均分词后也就 10 来个词,平均池化(mean)之后向量被严重稀释;而且 Word2Vec 需要在大语料上预训练,自己拿几万条标题训练出来的词向量质量很差。深度模型如 TextCNN、BERT 同理,数据量到不了万级以上的时候,优势发挥不出来,反而容易出现训练不收敛或过拟合。

所以我的默认线是:先 TF-IDF + 线性模型跑一版,拿到基线结果后,再按需尝试 Word2Vec 或微调 BERT 做对比。对毕设来说,这个“从简到繁”的过程本身就很有价值——你手里有对比数据,论文里就能写出为什么选这个方案。

2.3 模型选型:线性 SVM 与朴素贝叶斯的取舍

TF-IDF 出来的向量是高维稀疏向量(维度基本等于词表大小,几万维很常见),这种数据形态下,线性模型是性价比最高的选择。

朴素贝叶斯在短文本分类里一直表现不差,原因在于它假设特征独立,虽然这个假设在语言上不成立,但因为标题里词与词之间真正的强关联模式很少,误差反而可控。MultinomialNB的参数alpha做拉普拉斯平滑,默认是 1.0,在新闻标题这种场景通常不用动。它的缺点也明确:特征独立假设受损时(比如“篮球”这个词出现时“比赛”几乎必然出现),概率估计会偏,但对最终排序影响不大。

LinearSVM(用 sklearn 的LinearSVC)是另一个默认选项。它在高维稀疏文本特征上表现非常稳定,而且训练速度快。C值是关键参数,控制错误分类的惩罚力度,在文本分类上常见的有效范围是 0.1 到 10 之间,需要靠验证集去搜。要注意的是LinearSVC的loss默认是squared_hinge,如果发现训练不收敛或者验证集波动大,可以试hinge。

我个人的项目习惯是:先跑MultinomialNB拿快速基线,再用LinearSVC做主力模型。两个都是 sklearn 里现成的类,代码量差距不大,但 SVC 的上限通常更高,尤其类别数量超过 5 个的时候。

另外提一句周志华《机器学习》里讲到的“偏差-方差”视角:线性模型在短文本任务上偏差低、方差也可控,这正好解释了为什么它比复杂模型更稳。这个理论在论文里作为选型依据来写,是很自然的过渡。

3. 从数据集到分类器:一套可以直接运行的实现流程

3.1 数据集准备与预处理:清洗规则不能拍脑袋

先约定数据格式,我用 CSV,两列:label(类别标签)和title(标题文本)。类别用中文名直接存,后面可以用LabelEncoder转成数值。这里不硬性限定必须爬哪个网站,但有个经验:新闻源不要只取一个,至少两个来源交叉,能避免某些网站的固定表达让模型学到“来源特征”而不是“类别特征”。

清洗规则按优先级排序,代码层面长这样:

import pandas as pd import re def clean_title(text: str) -> str: if not isinstance(text, str): return "" # 去掉URL text = re.sub(r'https?://\S+|www\.\S+', '', text) # 去掉【】、()等括号内的频道标识,如【体育】、 (组图) text = re.sub(r'[【\[((][^】\]))]*[】\]))]', '', text) # 去掉多余空白和特殊符号 text = re.sub(r'[\s\u3000]+', ' ', text) text = re.sub(r'[^\w\u4e00-\u9fa5]', ' ', text) return text.strip() df = pd.read_csv('news_titles.csv') df['title_clean'] = df['title'].apply(clean_title) # 去掉清洗后为空的样本 df = df[df['title_clean'].str.len() > 3]

逻辑说明:第一条 URL 规则处理的是混进来的链接;第二条括号规则很关键,因为很多新闻标题里带着“(组图)”、“【专题】”这类本身就是分类信号的词,不删掉会让模型偷懒学这个模式;第三条把剩下所有非中文非数字字符替换成空格,避免标点符号干扰分词。清洗后长度小于等于 3 的标题信息量太低,直接丢弃。

参数说明:min_len=3是经验值,如果数据量不够,可以放宽到 2;str.len() > 3是字符级别的判断,这里要注意 pandas 的str.len()统计的是字符数而不是词数,中文标题一般 10 个字符起步,所以这个阈值不会误杀。

3.2 分词:jieba 的默认模式就够用

中文文本必须分词。用 jieba 的精确模式(cut),注意不要开HMM的 Paddle 模式,处理短标题反而可能引入分词错误。停用词表直接用一个常见的通用中文停用词表即可,但有几类词要手动保留——否定词(“不”、“没”)、程度词(“最”、“太”),它们在标题里有信息量,比如“最严新规”和“新规”差别很大。

import jieba stopwords = set() with open('stopwords.txt', 'r', encoding='utf-8') as f: for line in f: stopwords.add(line.strip()) def tokenize(text: str) -> list: words = jieba.lcut(text) # 过滤停用词和单字词,保留长度>=1的词 return [w for w in words if w not in stopwords and len(w.strip()) > 0]

逻辑说明:jieba.lcut返回一个分词列表,比jieba.cut(返回生成器)更好调试。过滤逻辑里没有去掉单字词,是因为“股”、“足”这类字在新闻标题里往往有实际信息量,比如“股市飘红”分出来可能是“股市”和“飘红”,但如果词典没覆盖,“股”字单独出现时不能直接删。

3.3 TF-IDF 向量化与训练集划分:先分层抽样再分特征

向量化时有两个容易忽略的点:一是必须在训练集上fit,再用同一个已fit的向量器去transform测试集,防止信息泄露;二是类别分布不均衡时要用stratify做分层抽样,保证训练集和测试集里各类比例一致。

from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.model_selection import train_test_split df['tokens'] = df['title_clean'].apply(tokenize) # 用空格把分词结果拼回去,TfidfVectorizer 默认按空白切分 df['token_str'] = df['tokens'].apply(lambda x: ' '.join(x)) X_train, X_test, y_train, y_test = train_test_split( df['token_str'], df['label'], test_size=0.2, random_state=42, stratify=df['label'] ) vectorizer = TfidfVectorizer( min_df=2, max_df=0.8, ngram_range=(1, 2), sublinear_tf=True ) X_train_vec = vectorizer.fit_transform(X_train) X_test_vec = vectorizer.transform(X_test)

逻辑说明:fit_transform在训练集上完成词表构建和 IDF 计算,transform在测试集上只做映射,这是整个 pipeline 里最容易被忽视的数据泄露点。ngram_range=(1, 2)表示同时用单个词和连续两个词作为特征,新闻标题里“男篮/世界杯”、“新冠/疫苗”这类双词组合有强类别信号,加入 bigram 能带来明显的 F1 提升。

参数说明:min_df=2过滤掉只在一条样本里出现的词,这类词通常是错别字或罕见命名实体,留着只能当噪声;max_df=0.8过滤掉出现率超过 80% 的词,这类词基本是“的”、“了”之类停用词没清干净的漏网之鱼,也可能是“新闻”、“今天”这类跨类别高频词,对分类没有区分度。sublinear_tf=True把词频做对数缩放(1 + log(tf)),防止某个词在某条标题里重复出现导致权重异常偏高。

3.4 训练与调参:LinearSVC 的 C 值怎么搜

向量化完成后,进入模型训练环节。我一般直接用GridSearchCV做交叉验证,同时搜索 C 和 loss,一步到位把参数定下来。

from sklearn.svm import LinearSVC from sklearn.model_selection import GridSearchCV from sklearn.pipeline import Pipeline pipeline = Pipeline([ ('tfidf', TfidfVectorizer(min_df=2, max_df=0.8, ngram_range=(1, 2), sublinear_tf=True)), ('clf', LinearSVC()) ]) param_grid = { 'tfidf__ngram_range': [(1, 2), (1, 3)], 'clf__C': [0.1, 0.5, 1.0, 2.0, 5.0], 'clf__loss': ['hinge', 'squared_hinge'] } grid = GridSearchCV( pipeline, param_grid, cv=5, scoring='f1_macro', n_jobs=-1, verbose=1 ) grid.fit(df['token_str'], df['label']) print(grid.best_params_) print(grid.best_score_)

逻辑说明:用 Pipeline 把向量化和分类器绑在一起,好处是交叉验证时每一折都重新做 TF-IDF 的fit,不会被整体fit过的向量器污染。scoring='f1_macro'对每个类别的 F1 取算术平均,这个指标在多分类里比 accuracy 更能反映小类别的表现。n_jobs=-1表示用满 CPU 核心,GridSearchCV 会并行跑所有参数组合。

参数说明:C 值的搜索范围根据文本特征维度来定。TF-IDF 向量维度通常在 5 万到 30 万之间,C 太小(0.01 以下)模型欠拟合,C 太大(10 以上)容易过拟合。我跑新闻标题分类时,最优 C 值经常落在 0.5-2.0 之间,如果数据集只有几千条,C 取小一点更稳。

3.5 模型持久化:导出为 joblib 文件并写一个调用接口

训练完成后需要把模型保存下来,供后续预测使用。同时导出的应该有向量器,因为预测时要做一模一样的预处理和向量化。

import joblib # 重新用最优参数训练最终模型 best_pipeline = grid.best_estimator_ best_pipeline.fit(df['token_str'], df['label']) joblib.dump(best_pipeline, 'news_classifier.joblib') joblib.dump(vectorizer, 'tfidf_vectorizer.joblib') # 保存类别映射,预测时用 label_map = {i: label for i, label in enumerate(best_pipeline.classes_)} joblib.dump(label_map, 'label_map.joblib') # 预测接口示例 def predict_title(text: str) -> str: clf = joblib.load('news_classifier.joblib') label_map = joblib.load('label_map.joblib') cleaned = clean_title(text) tokens = tokenize(cleaned) token_str = ' '.join(tokens) pred_id = clf.predict([token_str])[0] return label_map[pred_id] print(predict_title('中国男足世预赛出线形势分析')) print(predict_title('央行宣布降准释放长期资金'))

逻辑说明:这里把向量器也单独存了一份,但其实best_pipeline内部已经包含了 TF-IDF 步骤,直接predict就能完成文本到标签的全过程。单独保存vectorizer只是为了某些场景下需要查看特征名(比如用get_feature_names_out()找重要词)时方便加载。label_map用best_pipeline.classes_生成,是因为LabelEncoder里的类别排序不一定是中文拼音序,直接依赖索引会出错。

参数说明:joblib比pickle在处理 numpy 数组和 sklearn 模型时更高效,这是 sklearn 官方推荐的做法。保存路径如果有中文或空格,某些旧版 joblib 会警告,建议用纯英文路径。

4. 把分类效果看清楚:评估指标与错误分析的正确打开方式

4.1 准确率不是唯一指标,多分类要看 macro-F1

很多第一次做文本分类的人,拿到 85% 的准确率就觉得完工了,这个心态在新闻标题分类上尤其危险。新闻数据的类别天然不均衡:体育、娱乐的标题数量可能是“科技”、“教育”的两三倍。如果某个小类别只有 5% 的样本,模型直接把它全判成大类,准确率照样很高,但你的系统实际是瘸腿的。

正确的评估姿势是同时输出以下三组数字:分类报告(precision / recall / F1 按类拆开)、macro-F1(所有类 F1 的平均)、混淆矩阵(误差集中在哪一对类别)。代码不复杂,但每次训练完必须跑:

from sklearn.metrics import classification_report, confusion_matrix, f1_score import numpy as np y_pred = best_pipeline.predict(X_test_vec) print(classification_report(y_test, y_pred, target_names=best_pipeline.classes_)) cm = confusion_matrix(y_test, y_pred) # 归一化后更直观,按行归一化表示每个类别的召回情况 cm_norm = cm.astype('float') / cm.sum(axis=1, keepdims=True) print(np.round(cm_norm, 2)) print('macro-F1:', f1_score(y_test, y_pred, average='macro'))

逻辑说明:classification_report直接给出每个类别的 precision、recall、F1 和样本数,一眼能看出来哪些类被压制了。比如“体育”的 recall 很高但“科技”的 recall 低,说明模型倾向于把不确定的样本判成“体育”。归一化混淆矩阵可以定位具体是哪两个类别在互相串——在新闻标题分类里最常见的是“娱乐”和“时尚”互串、“财经”和“科技”互串。

4.2 错误分析:抽样看错题,比调参更有效率

评估指标只能告诉你“哪里差”,不能告诉你“为什么差”。补齐这个信息靠的是错误分析——把预测错误的样本拉出来,逐条看,通常十分钟就能找到问题的根源。

import pandas as pd results = pd.DataFrame({ 'true_label': y_test, 'pred_label': y_pred, 'title': X_test }) errors = results[results['true_label'] != results['pred_label']] # 按真实类别抽样,每类看5条 sample_errors = errors.groupby('true_label').apply( lambda x: x.sample(min(5, len(x)), random_state=42) ).reset_index(drop=True) print(sample_errors.to_string())

逻辑说明:这段代码不做任何模型层面的改进,但它能改变你的工作重心。常见的错误模式有:标题本身是模糊的(“盘点五位明星的商业版图”)+ 类别边界重叠;预处理时没洗干净(“某某公司发布新产品” 被误判为科技因为“公司”在科技类标题中出现多);训练数据里某个类别的样本本身标注不一致(爬虫来源频道跟内容实际类别对不上)。这些问题靠调参解决不了,只能回到数据处理环节去修正。

我自己的经验是:每次调参后只对比 macro-F1,一旦陷入小数点后两位的纠结但不见涨,就停下来做错误分析。错误分析定位到具体词条或规则缺失,修改数据或特征后再回来训练,通常都比盲目扩大搜索范围管用。

4.3 探索预测置信度与阈值调整

线性 SVM 的decision_function输出的是样本到超平面的距离(有正有负),可以作为置信度参考。有些场景下,我们宁可让模型“拒答”,也不要硬给一个低置信度的标签。比如新闻推荐系统里,给用户推错类别的标题,伤害比不推更大。

from scipy.special import softmax # 注意:LinearSVC 没有 predict_proba,只能用 decision_function 的值做近似 scores = best_pipeline.decision_function(['央行宣布降准释放长期资金']) conf_scores = softmax(scores, axis=1) print(conf_scores) # 设定阈值,低于阈值的标题标记为待人工审核 max_conf = conf_scores.max(axis=1) if max_conf < 0.5: print('低置信度,转人工审核')

逻辑说明:softmax把距离值缩放到 0-1 之间,可以近似看成概率分布。这里要注意,LinearSVC没有校准过的概率输出,softmax后的数值不是真实概率,只是相对置信度的排序。用max_conf和阈值做硬性过滤是可行的,但阈值大小需要结合验证集上的精确率-召回率曲线去选,不能拍脑袋定 0.5。

这个技巧放在毕设里的意义在于:它体现了你对“模型落地”的理解——分类器不是输出一个标签就完了,而是要知道自己的不确定性边界在哪里。

5. 新闻标题分类避坑指南:从数据爬到模型上线,我踩过的 5 个坑

5.1 爬虫标签不可信:来源频道和内容类别经常对不上

现象:训练集准确率 90% 以上,但测试集 F1 只有 70%,且错误完全没有规律。

原因:用新闻网站频道名当标签,但频道分类是编辑按版面划分的,不是按内容语义划分的。一篇“某公司发布新型电池技术”放在“汽车”频道,但它内容上更接近科技;一篇“明星跨界合作推出服装品牌”放在“娱乐”频道,但正文讲的是商业。这种标签噪声是系统性的,靠清洗没法完全消除。

解决:标签噪声比例超过 10% 时,建议人工抽样复核,把明显错标的数据修正掉。如果时间和精力不允许,至少把容易混淆的类别合并掉——比如“时尚”合并进“娱乐”、“教育”合并进“社会”,类别从 10 个降到 8 个甚至 6 个,F1 的提升会非常明显。

5.2 分词粒度不一致:同一个词在不同标题里被切成不同 token

现象:模型对某些关键词的权重不稳定,同一类别的标题有的分对有的分错。

原因:jieba 对日常词和新闻实体词的切分可能不一致。比如“世界杯预选赛”有时切成“世界杯/预选赛”,有时切成“世界/杯/预选赛”;“新冠疫苗”可能被切成“新冠/疫苗”也可能被切成“新/冠/疫苗”。这种不稳定会让 TF-IDF 把同一个概念拆成两套特征,稀释权重。

解决:在分词结果上做一个“新词合并”兜底规则——加载自定义词典,把领域词汇直接加进jieba.add_word,比如“世界杯”、“预选赛”、“新能源汽车”这类标题高频词。更省事的办法是直接给TfidfVectorizer传token_pattern,让它按空格切分后的完整字符串来做 n-gram,避免分词粒度问题传给下游。

5.3 TF-IDF 在测试集上重新 fit 了:信息泄露导致评估虚高

现象:本地验证 F1 很高,但部署到新数据上效果垮掉。

原因:这是最常见的翻车现场——把训练集和测试集合并在一起做向量化,或者测试集单独做了fit_transform。这样测试集的信息已经参与词表和 IDF 计算,评估结果会系统性偏高 3-10 个百分点。

解决:严格遵循“先 fit 后 transform”的顺序,且只对训练集fit。用 Pipeline 封装整个流程,交叉验证时 sklearn 会自动在每一折里重新fit,从机制上杜绝这个问题。

5.4 标题长度极端导致的向量化稀疏

现象:有些标题特别短(4-6 个字),比如“股市大涨”、“国足惨败”,向量化后几乎没有有效特征,模型只能靠猜。

原因:短标题的词覆盖率不足,ngram_range=(1, 3)也只能提取到很少的特征,且这些词可能在训练集里没出现过(min_df 过滤掉了)。

解决:不要直接丢弃短标题。两种补救思路:一是把min_df降为 1,让生僻词也进入词表,但这样会引入噪声,不能单独用,需要配合max_features限制总维度;二是给短标题补充来源特征——新闻来源网站本身是一个信号,“来自体育频道的超短标题”大概率是体育。在 pipeline 里做特征拼接,把来源 one-hot 后拼到 TF-IDF 特征后面,效果通常立竿见影。

5.5 导出的模型文件在新环境预测报错

现象:joblib.load时直接报ModuleNotFoundError或者ValueError。

原因:模型保存时的 sklearn 版本和加载环境版本不一致,或者自定义函数(如clean_title)没有被打包。joblib序列化模型时会关联类路径和函数引用,换环境后找不到了。

解决:保存模型时同步写一个requirements.txt,固定 sklearn、jieba、pandas 的主版本号。自定义预处理函数不要写在主脚本里,而是单独放在一个.py模块里,确保加载模型的环境能导入这个模块。这也是毕设答辩时老师最常问的问题——“你的模型换台电脑还能跑吗”。

6. 从模型到系统:给毕设加分的一个验证工具与交付套路

模型训练完成只是做完了一半,另外一半是把模型变成一个能演示、能验收的系统。对于毕设来说,“系统”两个字不需要一套 Web 服务,但至少要有一个控制台工具或者简单的 Web 页面,让人能输入标题、看到结果。这里我给一个我自己常用的轻量演示方案——Flask 单文件服务,代码控制在 60 行以内:

from flask import Flask, request, jsonify import joblib app = Flask(__name__) clf = joblib.load('news_classifier.joblib') # 保持和训练时完全一致的预处理逻辑 def preprocess(text): import re text = re.sub(r'[【\[((][^】\]))]*[】\]))]', '', text) text = re.sub(r'[\s\u3000]+', ' ', text) text = re.sub(r'[^\w\u4e00-\u9fa5]', ' ', text) return text @app.route('/classify', methods=['POST']) def classify(): data = request.get_json() title = data.get('title', '') cleaned = preprocess(title) pred = clf.predict([cleaned])[0] return jsonify({'title': title, 'category': pred}) if __name__ == '__main__': app.run(host='0.0.0.0', port=5000)

这段代码的核心是验证“训练环境和部署环境的预处理必须一致”——很多毕设系统上线后效果变差,就是因为 Web 端少做了括号去除,或者没有做分词。把预处理函数复制到服务端是最容易出的错,我的习惯是把它单独放到一个preprocess.py模块,训练脚本和 Flask 服务都从同一个模块导入,从物理上杜绝不一致。

如果不想引入 Flask 依赖,也可以做一个命令行批处理工具:输入一个txt文件,每行一条标题,输出一个带预测标签的文件。这个“输入-输出”闭环才是系统交付的完整形态——模型文件本身不算系统,能批量处理真实输入的才叫系统。

在项目文档里,我建议补上两件事:一是对预测失败的样例做一个“分析报告”,说明是哪类问题、怎么改;二是写清楚如何用新数据继续训练(把新标注的数据追加到原始 CSV,重跑 3.4 节那段 GridSearchCV 代码)。这两件事能让答辩老师快速理解你不是“调包跑通”,而是真正掌握了整个机器学习落地的闭环。

回到标题本身——基于机器学习的新闻标题分类系统,本质上是把文本分类的通用方法论在一个具体场景里做完整,并形成可交付的形态。整个过程中最有价值的收获不是哪个模型跑出了最高分,而是你学会了一件事:当一个模型的评估结果不符合预期时,你有一套自己的排查路径——先看数据、再看特征、最后才考虑换模型。我自己的习惯是永远留一份“最笨的基线模型”的结果,因为它能在你被花哨模型迷惑时,用一个朴素的结果把你拉回现实。希望这篇笔记能帮你在同样的方向上少走几步弯路。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/3 2:46:13

Python轨迹聚类实战:从距离度量到聚类算法与可视化

简介&#xff1a;TrajectoryClustering-master 是一份面向数据挖掘与地理空间分析学习者的 Python 轨迹聚类实战源码&#xff0c;适合希望理解 GPS 轨迹、移动设备位置记录等时空数据聚类流程的初学者与数据科学从业者。项目围绕轨迹数据预处理、距离度量、聚类算法实现与结果可…

作者头像 李华
网站建设 2026/10/3 2:46:10

MFC对话框添加工具栏实战:CToolBar创建与消息映射详解

简介&#xff1a;在Visual C的MFC环境中&#xff0c;许多入门开发者希望为对话框程序加上一组工具栏按钮&#xff0c;以便快速执行常用操作&#xff1b;压缩包内的完整代码正是围绕这一场景展开。压缩包内共包含19个文件&#xff0c;其中6个头文件与5个C源文件构成核心代码&…

作者头像 李华
网站建设 2026/10/3 2:45:52

灰狼算法优化SVM超参数:小样本非平衡数据的高效调参方案

简介&#xff1a;本资源是面向机器学习初学者与算法实践者的灰狼优化算法&#xff08;GWO&#xff09;与支持向量机&#xff08;SVM&#xff09;融合实现方案&#xff0c;聚焦SVM核函数参数与惩罚系数的自动寻优难题&#xff0c;适用于分类、回归及异常检测等典型任务。压缩包共…

作者头像 李华
网站建设 2026/10/3 2:45:21

VMD-SSA-LSTM时序预测:工业非平稳数据的分层净化与多尺度建模

简介&#xff1a;本资源是一套基于Python实现的VMD-SSA-LSTM混合时间序列预测模型完整方案&#xff0c;面向计算机、电子信息工程及数学等专业的本科生与研究生&#xff0c;适用于课程设计、期末大作业及毕业设计等实践场景&#xff0c;帮助学习者掌握信号分解、智能优化与深度…

作者头像 李华
网站建设 2026/10/3 2:44:44

电商评论情感分析Python源码实践:从预处理到模型评估

简介&#xff1a;面向电商产品评论情感分析场景的Python源码包&#xff0c;适合NLP初学者、电商数据分析师以及需要快速搭建文本分类流程的开发者。项目围绕中文用户评论数据&#xff0c;完整覆盖数据清洗、去停用词、jieba分词、情感词典匹配、TF-IDF与词袋特征构建&#xff0…

作者头像 李华
网站建设 2026/10/3 2:44:36

LVI-SAM跑KITTI炸图?IMU频率与数据同步避坑指南

第一次用LVI-SAM跑KITTI数据集&#xff0c;我的地图在五秒之内就炸了——视觉里程计直接冲向天空&#xff0c;激光点云散成一团雾&#xff0c;终端里疯狂刷NaN。当时我第一反应是外参标定错了&#xff0c;把calib文件翻来覆去算了三遍&#xff0c;反反复复折腾了一整天&#xf…

作者头像 李华