☰
中文文本分类实战:从TF-IDF+SVM到RoBERTa的完整流程与避坑指南
2026/10/9 2:42:24 网站建设 项目流程

简介:基于搜狗新闻语料库的中文文本分类完整实践项目,覆盖传统机器学习与预训练模型两条技术路线,适合自然语言处理初学者、人工智能及相关专业学生用于课程设计、毕业设计或项目演示。包内共15个文件,以Python源码为主,包含数据切分、模型训练、结果可视化等脚本,另附词典、停用词表、说明文档与训练曲线图,便于对照理解分类流程。约208KB,轻量易部署,下载后即可本地运行调试。已有79人学习下载,代码均经过测试,可直接复现,也可在此基础上扩展多分类、调参或接入其他预训练模型,是快速上手中文文本分类的实用参考。

1. 搜狗新闻语料库上的中文文本分类:为什么先跑通传统方法再上预训练模型

拿到一份搜狗新闻语料库,目标是在上面做中文文本分类,很多人的第一反应是直接上一个预训练模型,但真正动手做过就会发现,这条路并不比传统机器学习方法省心。搜狗新闻语料库的特点是数据量大、类别多、文本长度差异悬殊,直接从预训练模型起步,很容易在数据清洗和训练资源上卡住。比较务实的做法是先建一条传统机器学习基线,用 TF-IDF 加 SVM 把完整流程跑通,把任务变成一份可评测、可对比的问题,然后再用预训练模型去冲击更高分数。这套思路适合正在做课程项目、实训作业或想系统掌握中文 NLP 落地步骤的读者,它不挑显卡,也不依赖某个特定的运行环境,只要有一台能跑 Python 的机器就能开始。本文会按数据准备、传统方法、预训练模型、踩坑记录这条线完整拆开讲。

2. 准备搜狗新闻语料库:解压、编码清洗与标签压缩的一线做法

2.1 语料库的目录结构与标签来源

搜狗新闻语料库最常见的形态是一个嵌套目录,外层是按新闻类别划分的文件夹。这里的关键点在于:这份数据本质上是从新闻网页抓取来的,原始格式不是干净的 CSV 或 JSON,而是带一组自定义标记的纯文本。部分版本的样本长这样:

<doc> <url>http://sports.sohu.com/...</url> <docno>xxx</docno> <content>比赛进行到第十分钟...</content> </doc>

新版 SogouCS 数据集则使用<url>、<docno>、<contenttitle>、<content>这四个闭合标签,并且所有字段值做了反转义处理,读起来更像一个半结构化文本。很多资料包里的版本是已经按类目拆好的目录,每个目录名对应一个类别,目录下每个文件是一篇新闻。这种情况下,标签的直接来源就是文件所在目录名,不需要额外标注。

拿到压缩包后,先别急着写训练代码。第一步是确认数据规模:每个类别的文件数量、总样本量、是否存在空文件、是否存在同一篇新闻的重复样本。常见做法是写一个快速统计脚本,把目录结构、文件数、平均字符数打印出来,先给数据打个分。我一般会把类别数量少于 100 条的子目录直接标注为弱类别,后面统一处理。

mkdir -p data/raw data/processed tar -zxvf sogou_news_dataset.tar.gz -C data/raw find data/raw -type f | wc -l

统计完文件总数后,再按目录聚合看类目分布,这时你就能判断这份资料能不能直接用来训练。如果类别高度不均衡,比如“体育”类有 10 万篇而“军事”类只有 2000 篇,那么后面做评估时就要以宏平均 F1 为主,而不是只看整体准确率。

2.2 编码清洗与数据切分脚本

搜狗新闻语料库的文本编码几乎都是 GBK 或 GB18030。用默认 UTF-8 直接打开必乱码或报错,这是新手翻车频率最高的地方。正确做法是在读取时显式指定编码,并统一转成 UTF-8 落盘,后续所有处理环节都只用 UTF-8 文本。

清洗规则要从新闻网页特点反推:正文里混着大量 HTML 实体、空白符、URL、特殊符号,还有可能的重复标题。这些噪声对传统机器学习方法和预训练模型的影响路径不同。对 TF-IDF 来说,URL 和特殊符号会被当作特征参与计算,等于引入了无关维度;对 BERT 这类模型来说,过长的噪声文本会浪费有限的序列长度。

import re import pandas as pd from pathlib import Path def clean_text(text: str) -> str: text = re.sub(r'<[^>]+>', '', text) text = re.sub(r'https?://\S+|www\.\S+', '', text) text = re.sub(r'\s+', ' ', text) text = re.sub(r'[^\u4e00-\u9fa5a-zA-Z0-9,。!?、:;""''()《》\s]', '', text) return text.strip() def build_dataset(root: Path): rows = [] for label_dir in root.iterdir(): if not label_dir.is_dir(): continue label = label_dir.name for fp in label_dir.glob('*.txt'): raw = fp.read_text(encoding='gb18030', errors='ignore') text = clean_text(raw) if len(text) >= 20: # 过滤过短文本,避免空样本进入训练集 rows.append({'label': label, 'text': text}) return pd.DataFrame(rows) df = build_dataset(Path('data/raw')) df.to_csv('data/processed/news_clean.csv', index=False) print(df['label'].value_counts())

这里的errors='ignore'是双刃剑。它能跳过个别损坏字节,但也可能让文本尾部直接断掉。比较稳的做法是先按 GB18030 解码,失败样本单独挑出来尝试 GBK 再失败就丢弃。len(text) >= 20这个阈值来自经验:新闻正文低于 20 个字符的样本,要么是抓取残缺,要么是纯标题,对分类任务几乎没有正向贡献。清洗后用label做一次value_counts(),如果看到某个类别的样本数低到个位数,直接决定它是否值得保留。

切分时强烈建议用train_test_split而不是手动按比例随机抽。手动抽容易出现多个类别只进了训练集但没进测试集的情况。这时要设置stratify参数保证每个类别的比例在训练集、验证集、测试集中保持一致。

from sklearn.model_selection import train_test_split train, tmp = train_test_split( df, test_size=0.2, stratify=df['label'], random_state=42 ) val, test = train_test_split( tmp, test_size=0.5, stratify=tmp['label'], random_state=42 ) print(train['label'].value_counts()) print(test['label'].value_counts())

random_state固定下来是保证实验可复现的关键。后面对比传统方法和预训练模型的分数时,如果切分不固定,两次结果之间的差异就混入了数据分布的随机性,无法准确判断是模型变强了还是运气变好了。

2.3 类别压缩与样本量下采样

搜狗新闻语料库原始类目有几十个,用于课程项目或实训时类别太多会带来两个问题:一是部分类目样本不足,训练不充分;二是评估指标变得极其分散,报告不好写。常见做法是把类目压缩到 10 个以内,或者只保留样本量最大的前 10 类,其余归入“其他”。

样本量不均衡也是必须处理的。假设“体育”类有 10 万条,“旅游”类只有 3000 条,训练时模型会天然偏向大类别。对这个任务,我一般不会直接做上采样复制,因为新闻文本重复太多会让模型记住文本本身而非类别规律。更稳妥的做法是做下采样,把大类压到与小类相近的量级,或者采用类别权重。

def downsample(df: pd.DataFrame, max_per_class: int = 10000): sampled = [] for label, group in df.groupby('label'): if len(group) > max_per_class: group = group.sample(max_per_class, random_state=42) sampled.append(group) return pd.concat(sampled) df = downsample(pd.read_csv('data/processed/news_clean.csv')) df.to_csv('data/processed/news_balanced.csv', index=False)

每个类别最多保留 1 万条,一方面压缩了后续训练时间,另一方面避免大类别主导决策边界。如果后面用预训练模型,这个下采样策略还能大幅缩短单轮训练时间,让你有更多机会调参而不是干等。

3. 传统机器学习基线:jieba + TF-IDF + 支持向量机的训练流程与关键参数

3.1 为什么要分词而不是直接按字建模

中文文本分类的第一步永远是分词,原因在于 TF-IDF 这类词袋模型以词为特征单位。按字建模虽然能避开分词错误,但字级别的特征无法表达“机器学习”和“机器”“学习”之间的语义差别,特征维度也会更高。搜狗新闻语料库的文本是正式书面语,句子结构完整,分词质量整体较高,非常适合 jieba 分词。

这里有个容易被忽视的细节:分词前要决定是否去停用词。新闻语料里“的”“了”“在”这类高频功能词,在 TF-IDF 的 IDF 机制下权重本来就会被压低,但它们依然占据特征矩阵的大量维度。常见做法是准备一份中文停用词表,在分词后直接过滤。停用词表的质量直接决定特征维度的干净程度,这一步不建议省。

import jieba import jieba.analyse STOP_WORDS = set() with open('data/stopwords.txt', encoding='utf-8') as f: for line in f: STOP_WORDS.add(line.strip()) def tokenize(text: str): words = jieba.lcut(text) return [w for w in words if w not in STOP_WORDS and len(w.strip()) > 0]

jieba.lcut返回的是一个列表,相比jieba.cut的生成器,在后续 DataFrame 操作中更直接。停用词过滤时只判断w not in STOP_WORDS还不够,数字、单个字母、无意义字符也要一并剔除。新闻文本里经常出现“2024年”“第10届”这类片段,如果不过滤,它们会成为高维稀疏特征,对模型预测没有帮助。

3.2 TF-IDF 参数与支持向量机训练脚本

特征工程部分的核心是TfidfVectorizer的参数设置。搜狗新闻语料库文本较长,如果完全不限制特征数量,特征矩阵会膨胀到几万甚至几十万维,内存占用飙升的同时,训练速度也急剧下降。这里有几个参数是必调的:max_features、min_df、sublinear_tf。

from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.svm import LinearSVC from sklearn.pipeline import Pipeline vectorizer = TfidfVectorizer( tokenizer=tokenize, max_features=50000, min_df=2, max_df=0.95, sublinear_tf=True, ngram_range=(1, 2) ) model = Pipeline([ ('tfidf', vectorizer), ('clf', LinearSVC(C=1.0, class_weight='balanced', max_iter=5000)) ])

min_df=2表示词至少出现在 2 篇文档中才被纳入特征,这会去噪;max_df=0.95表示词出现在超过 95% 的文档中则丢弃,这能剔除“新闻”“记者”“报道”这类在所有类别中都高频出现的词。sublinear_tf=True是把词频取对数压缩,防止长文本的词频优势过大。ngram_range=(1, 2)加入二元词组特征,对“深度学习”“人工智能”这类复合词有增量帮助。

训练时用LinearSVC而不是传统的 SVC 高斯核,核心原因是新闻多分类任务的样本量大,线性核完全够用且训练速度能差出两个数量级。class_weight='balanced'会自动调整类别权重,对不均衡数据很友好。

X_train = train['text'].tolist() y_train = train['label'].tolist() model.fit(X_train, y_train) from sklearn.metrics import classification_report y_pred = model.predict(test['text'].tolist()) print(classification_report(test['label'].tolist(), y_pred, digits=4))

第一次跑通时,重点不是刷分数,而是确认整条链路没有断点。文本要能从 CSV 走进 TF-IDF 矩阵,再走进分类器。如果跑不起来,八成问题出在tokenizer=tokenize这一行:TfidfVectorizer接收的是字符串列表,分词函数返回的也必须是字符串列表,返回生成器会报错。我一般会先拿 100 条样本做小验证,再全量训练,避免浪费半小时后才发现错误。

3.3 评估指标怎么读:宏平均与微平均的差别

传统机器学习方法跑完后会输出一份classification_report,这里的macro avg和weighted avg要会区分。宏平均是先按类别算出 F1 再平均,每个类别的权重相同。在类别不均衡的搜狗新闻语料库上,宏平均更能反映模型对小类别的区分能力。加权平均则按样本量加权,大类别表现好会掩盖小类别的失败。

如果宏平均 F1 明显低于加权平均,说明小类别的分类质量差。这时先不要换模型,检查是不是类别样本量太少或类别文本本身高度相似。比如“教育”和“文化”两个类别在新闻语境下边界模糊,模型分错是正常的,强行提升往往要靠引入更多外部特征。

我还建议在训练时把预测概率而不是预测标签存下来,这一点在传统机器学习模型上容易被忽略。LinearSVC默认不输出概率,需要开predict_proba必须改用CalibratedClassifierCV包装。对多数课程项目来说,直接打印分类报告就够了,但如果后面想画 ROC 曲线或做阈值调优,概率输出是必需品。

4. 预训练模型进阶选型:中文 RoBERTa 在分类任务上的实操要点

4.1 选哪类中文预训练模型:BERT 还是 RoBERTa

搜狗新闻语料库做分类,预训练模型的选型主要集中在两个方向:bert-base-chinese和基于哈工大讯飞联合发布的hfl/chinese-roberta-wwm-ext。这两个模型在中文 NLP 任务上都是主流选择。我的经验是:如果你没有特殊理由,直接用chinese-roberta-wwm-ext。它采用全词掩码策略,对中文这种词边界明确的语言更友好,在新闻分类这类长文本任务上通常比原始 BERT 高出 1 到 2 个百分点的 F1。

RoBERTa相比 BERT 的主要变化是去掉了下一句预测任务,采用了动态掩码和更大的训练批次。这些改进体现在下游任务上就是更稳定的收敛曲线。对有一定显卡资源但不算宽裕的场景,这是最适合起步的中文预训练模型。

选型号时要注意本地的 transformers 版本要够新,旧版本对AutoModelForSequenceClassification的支持不够完善。实际加载时用AutoModel系列 API 而不是直接BertForSequenceClassification,这样以后想换成bert-base-chinese或hfl/rbt3只需要改一行配置。

from transformers import AutoTokenizer, AutoModelForSequenceClassification model_name = "hfl/chinese-roberta-wwm-ext" tokenizer = AutoTokenizer.from_pretrained(model_name) id2label = {i: label for i, label in enumerate(train['label'].unique())} label2id = {v: k for k, v in id2label.items()} num_labels = len(id2label) model = AutoModelForSequenceClassification.from_pretrained( model_name, num_labels=num_labels, id2label=id2label, label2id=label2id )

num_labels必须和压缩后的类别数一致,不一致时模型最后一层维度会不匹配。id2label和label2id传进去后,模型输出的 logits 更容易对应回类别名,评估时省掉一层手工映射。

4.2 Tokenizer、截断与标签编码的实操脚本

预训练模型的输入处理和传统机器学习完全不同。传统方法直接把分词后的列表交给 TF-IDF,预训练模型则需要把文本转成input_ids、attention_mask和token_type_ids三个向量。搜狗新闻语料库的新闻正文一般比较长,必须处理截断逻辑。

有一个关键决策点:截断策略是截头部还是截尾部,或者是头尾各留一段。BERT 类模型有最大序列长度限制,bert-base-chinese是 512 token。新闻正文动辄一两千字,直接截断会丢失大量信息。常见做法是取开头 256 个字符加结尾 128 个字符拼接,因为新闻的首段通常包含导语,末尾通常包含结论,这两个位置信息密度最高。

def truncate_text(text, max_len=380): if len(text) <= max_len: return text head = text[:int(max_len * 0.6)] tail = text[-int(max_len * 0.4):] return head + tail def encode_texts(texts, tokenizer, max_len=512): encoded = tokenizer( texts, padding=True, truncation=True, max_length=max_len, return_tensors='pt' ) return encoded

传给 HF Tokenizer 时,我建议直接传原始字符串列表而不是预先分词的结果。因为 AutoTokenizer 内部会自动调用分词器,你手动用 jieba 分词后再传进去,反而会让模型看到被空格切碎的文本,影响语义完整性。

训练前要把标签列映射成数字索引。这一步很容易出错的地方是直接LabelEncoder然后忘记保存映射关系。预测新样本时映射反了,结果会完全混乱。

train['label_id'] = train['label'].map(label2id) val['label_id'] = val['label'].map(label2id) X_train = train['text'].tolist() y_train = train['label_id'].tolist()

保存模型时要把label2id和id2label一起存下来,或者直接用model.config里的字段,否则部署阶段你就得对着预测结果猜数字代表什么意思。

4.3 训练超参数的落法:batch size、warmup 与早停

预训练模型的训练环节是最玄学的部分,但好在已经有大量可参考的默认配置。搜狗新闻语料库分类任务,常见做法是建立在 transformers 的Trainer之上,把训练循环交给库处理,把精力集中在超参数上。

from transformers import Trainer, TrainingArguments training_args = TrainingArguments( output_dir='./results', num_train_epochs=3, per_device_train_batch_size=16, per_device_eval_batch_size=64, warmup_ratio=0.1, evaluation_strategy='epoch', save_strategy='epoch', load_best_model_at_end=True, metric_for_best_model='f1', save_total_limit=2, fp16=True, logging_steps=200 ) trainer = Trainer( model=model, args=training_args, train_dataset=train_dataset, eval_dataset=val_dataset, ) trainer.train()

per_device_train_batch_size要根据显卡显存调整。12GB 显存跑chinese-roberta-wwm-ext,序列长度 512 时 batch size 16 比较稳,低于 8GB 建议降到 8。fp16=True能省接近一半显存,但如果 CPU 训练则必须关掉。warmup_ratio=0.1表示前 10% 的训练步数用来让学习率从 0 线性增长到目标值,这对微调预训练模型很关键,能避免前期剧烈震荡打乱预训练权重。

load_best_model_at_end=True配合metric_for_best_model='f1'让训练结束后自动加载验证集上 F1 最高的 checkpoint。这一点很重要,最后一个 epoch 的模型往往不是最好的,尤其是在学习率衰减策略下,验证集最优值通常出现在中间阶段。如果训练完成后直接拿最终模型去测测试集,分数会比实际能拿到的低。

5. 中文文本分类避坑:从数据泄露到显存溢出的六条排查记录

5.1 训练集测试集重叠导致准确率虚高

现象:模型在测试集上的准确率达到 0.98,但实际拿一条新新闻去预测,结果明显不对。原因是数据准备阶段没有做去重,同一篇新闻在原始语料里出现了多次,切分后一部分进了训练集、一部分进了测试集,模型等于直接背下了答案。

解决:在做任何切分之前,先对文本做哈希去重。常见做法是计算每篇文本的 MD5 值,删除重复项后再切分。更严格的做法是计算文本的 SimHash 或编辑距离,但课程项目阶段 MD5 去重已经够用。注意去重必须在文件级别做,而不是在目录级别,因为重复样本可能分布在不同的类别目录下。

5.2 读取时报UnicodeDecodeError,怀疑资料包损坏

现象:用open('xxx', encoding='utf-8')读文件直接抛异常,报错指向第某个字节位置。原因不是文件损坏,而是搜狗新闻语料库的原始编码是 GBK 或 GB18030,遇到 UTF-8 解码器自然失败。

解决:读文件时统一用encoding='gb18030'。GB18030 是 GBK 的超集,兼容性最好。个别文件如果是 UTF-8 编码也不冲突,GB18030 能正确解码大部分 UTF-8 文本。如果还报错就加errors='ignore',把这些坏字节跳过。这一步处理后,生成的新 CSV 全部写 UTF-8 编码,之后所有环节都不再碰编码问题。

5.3 类别不均衡被宏平均 F1 惩罚,报告很难看

现象:模型整体准确率有 0.91,但macro avg F1只有 0.67。原因是某些小类别的新闻只有几百条,模型押注大类别的倾向很强。搜狗新闻语料库的原始分布就是如此,体育、财经、娱乐这些类别样本量远超其他类别。

解决:在传统机器学习路线中启用class_weight='balanced',在预训练模型路线中计算类别权重并传入损失函数。数据侧可以做下采样,但下采样后总样本量会变少,模型能力上限会相应降低。我一般会先做下采样到每类最多 8000 条,再看宏平均 F1,如果还不行才考虑类别权重叠加。

5.4 预训练模型训练时 CUDA 显存溢出

现象:CUDA out of memory报错,训练在第 1 步就停止。常见于batch_size=32+ 序列长度 512 的配置,显卡显存只有 8GB。

解决:优先降低per_device_train_batch_size到 8 甚至 4,这是最直接的止血方式。其次可以缩短max_length到 384,搜狗新闻截断到 384 token 通常还能保留 80% 以上的有效信息。再不行就开gradient_accumulation_steps=4,相当于用 4 小步凑一个大批次,稳定性和显存压力都能兼顾。

5.5 分词器对新闻标题和正文的语义权重一样

现象:模型预测结果里,“体育”和“娱乐”两个类别经常混淆,抽出来看新闻内容发现标题讲的是体育明星的娱乐八卦,正文也掺杂两类内容。

原因:新闻标题的信息密度远高于正文,但放进预训练模型时两者被无差别编码。传统 TF-IDF 方法同样存在这个问题,标题和正文的特征权重一致。

解决:常见做法是把标题和正文拼接时加分隔符,并适当增加标题在文本中的比重。拼接时用title + '。' + content比直接拼接更符合中文习惯,分隔符不会被分词器当噪声跳过。严格的方案是分别编码标题和正文再融合,但课程项目做到前一种就够了,分数提升通常在 1 到 2 个点。

5.6 预训练模型在短文本上反而不如传统方法

现象:对“湖人 121-114 击败凯尔特人”这类短新闻,传统 TF-IDF + SVM 分得很准,预训练模型反而给出奇怪的结果。原因在于预训练模型依赖上下文理解,短文本缺少足够上下文时,其优势发挥不出来。

解决:如果测试集中短文本占比高,不要盲目迷信预训练模型。可以把两者的预测结果做集成,或者至少在报告中诚实地对比两种方法在不同文本长度上的表现差异。常见做法是把测试集按文本长度分桶,分别统计 F1,这样能写进项目报告作为结论支撑。

6. 让分数再进一步:类别阈值调整与交叉验证验证技巧

6.1 用交叉验证替代单次切分,减少随机性

随机切分一次后的测试集分数,只能作为参考。如果你的课程资料需要提交一份有说服力的报告,建议直接用 10 折交叉验证。搜狗新闻语料库的类别分布无论怎么随机切分都可能在某一次切分中偏向容易或困难的子集,交叉验证能大幅度减少这种单次切分带来的误差。

from sklearn.model_selection import StratifiedKFold from sklearn.metrics import f1_score skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=42) for fold, (train_idx, test_idx) in enumerate(skf.split(X, y)): X_train_fold = [X[i] for i in train_idx] # 此处复用 3.2 的 TF-IDF + SVM 管线 model.fit(X_train_fold, [y[i] for i in train_idx]) y_pred = model.predict([X[i] for i in test_idx]) fold_f1 = f1_score([y[i] for i in test_idx], y_pred, average='macro') print(f'fold {fold}, macro F1: {fold_f1:.4f}')

首次跑交叉验证时,先跑 5 折而不是 10 折,单折训练一轮 TF-IDF + SVM 可能只要几分钟,但换成预训练模型就要按小时计算。折数越大,方差越小,但时间成本线性上升。从 5 折起步,看各折之间的 F1 波动范围,如果最大值和最小值超过 5 个点,说明数据分布很不稳定,增加折数才有意义。

6.2 预测概率阈值调整:不完全依赖 argmax

多数分类模型默认取 logits 最大的类作为预测结果,但新闻分类场景里某些类别的置信度天然偏低。比如“军事”与“国际”常常在特征空间里靠得很近,argmax 只会给你一个类别,但概率为 0.45 的区域往往是模型把握不大的地方。

获取概率后,可以对每个类别设定一个最低置信度阈值,低于阈值时判定为“不确定”,或者转向第二置信类别。这一步不能保证提升总体 F1,但能让你看清模型的可信边界在哪里,写入实验报告时是一张很有用的置信度分布表。

from sklearn.calibration import CalibratedClassifierCV calibrated = CalibratedClassifierCV(model, cv=3) calibrated.fit(X_train, y_train) proba = calibrated.predict_proba(X_test)

加了CalibratedClassifierCV后训练时间会翻几倍,但对最终报告的价值在于:你可以画出每个类别的置信度直方图,找出模型最犹豫的类别对。这也直接回答了一个常见问题:到底哪些类别最难分。从我的习惯来看,这个分析比单纯调参更能体现工程深度。

6.3 一份可复现的验证清单

项目收尾前,按下面这份清单检查一遍,能规避大部分低级问题:第一,确认训练集、验证集、测试集之间没有文本级别重复,这个用哈希去重做。第二,确认所有文本都转成了 UTF-8 编码,原始文件保持只读。第三,固定随机种子,包括数据切分、模型初始化、训练器参数。第四,记录两类方法的参数量和推理时间,传统方法单条预测应该在毫秒级,预训练模型在 GPU 上是 10 毫秒级,在 CPU 上会接近百毫秒级。第五,保留所有中间产物,包括清洗后的 CSV、TF-IDF 特征矩阵的稀疏存储版、预训练模型的 checkpoint。

我做这类项目养成的习惯是:每跑一次实验就把参数和 F1 分数记录在一个单独的文本文件里,不依赖记忆,不依赖 Jupyter 输出。因为调参过程中的失败组合往往比成功组合更有价值,翻看记录时能看到分数从 0.81 到 0.84 是靠哪个参数变过来的。这套方法在你换数据集、换题目时能直接复用。中文文本分类的核心链路就那么长,把数据和评估管好,模型反而不是最大的瓶颈,希望帮到你。

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询