资讯动态

中文情感分类实战:从网易云音乐数据集到BERT微调避坑指南

发布时间:2026/10/8 23:22:07 来源:尧图企业网站定制
简介网易云音乐情感分类数据集收录约四十万条来自网易云音乐官方的音乐情感标注记录每条记录包含歌曲标识、歌单标识和情感标签三项面向音乐情绪识别、推荐系统与文本挖掘研究者为情感分类模型的构建与验证提供了规模可观的数据支撑。压缩包内共有八个文件主体为训练、验证、测试三个子集的JSON Lines格式文件可直接用于常见机器学习框架的读取另有若干JSON文件保存标签映射与数据集描述信息并辅以说明文档及Git配置文件方便使用者了解数据口径并纳入版本管理整个压缩包仅三兆余轻量实用。当前已有四百八十人学习下载特别适合自然语言处理与数据科学方向的学生、工程师直接作为实验基准数据省去自行爬取和清洗的环节同时也能基于数十万级样本分析歌曲、歌单与情感倾向之间的潜在规律为细粒度音乐理解或推荐场景中的情绪因素利用打下基础。1. 网易云音乐情感分类数据集是什么拿到 .rar 之后先别急着解压第一次拿到这个 .rar 时我对着解压密码栏发了十分钟呆这几乎是每个做中文情感分类的人都会撞上的第一道坎。这个数据集圈子里流通的版本核心是网易云音乐歌曲的热门评论以及人工或半自动打好的情感标签常见格式是 CSV 或 JSON。它要解决的问题很直接中文情感分析不缺模型缺的是带真实口语、带语境、带网络用语的标注语料。和豆瓣、微博数据集相比网易云评论短、情绪浓度高、反讽多“这歌让我想起前任”这种文本在通用情感词典里大概率被误判。这份数据集适合做文本分类入门、毕业设计、推荐系统里的评论情感侧特征也适合用来检验一个预训练模型对网络语言的理解能力。但解压之前先想清楚一件事你是要拿来训一个正经模型还是只想跑个基线发论文这决定你后面怎么对待里面的标签。2. 解压与第一眼这个 rar 里到底装着什么格式的数据2.1 用 unrar 解开 rar 包图形界面、命令行与“伪加密”现象我一般不在生产环境用图形解压软件因为重复操作一多点点点会让人烦躁。命令行只用一条unrar x 网易云音乐情感分类数据集.rar参数说明x表示保留压缩包内的目录结构完整解压和e全部解压到当前目录不同。如果包内本来就有train/、test/、dev/子目录用x能避免文件互相覆盖如果你只想快速看内容用unrar l 网易云音乐情感分类数据集.rar列出清单确认大小和文件数再解。但网上这类数据集流通时经常被二次压缩最常见的坑是“伪加密”。现象是 WinRAR 或 7-Zip 打开时提示需要密码但你把网上流传的通用密码输入进去又提示错误。这不是你运气差而是有人用十六进制编辑器改了压缩包头的加密标志位。真正的加密需要用rar的加密算法处理而伪加密只是把标志位改成“有密码”实际内容没有加密解压软件却会停下来问你要密码。遇到这种情况先别急着找所谓的“密码移除工具”。常见做法是再用 7-Zip 试一次有时 7-Zip 不理会这个标志位直接解如果不行就用7z x 网易云音乐情感分类数据集.rar逻辑说明7z在 9.20 以上版本对 rar 伪加密的处理和 WinRAR 不一样经常能绕过去。如果两种工具都卡在密码弹窗那才是真加密只能回找资源发布者要密码。至于网上那些“rar password cracker”我劝你别浪费时间和机器性能真正加密的 rar 暴力破解成本远高过重新找一份资源。解压完先看一眼顶层文件名。常见布局是一个文件夹包含三个文件train.csv、dev.csv、test.csv或者一个raw_data.json加一个label_map.txt。极少数版本会带一个README.txt里面写的是标签说明和来源声明这份文件优先级最高先读它。2.2 字段结构从 CSV 到 JSON情感标签到底怎么编码的我见过两个主流版本CSV 版和 JSON 版。CSV 版的长相大概是字段名类型说明song_idstr/int歌曲唯一标识song_namestr歌名commentstr评论原文未脱敏like_countint评论点赞数labelstr情感标签如 积极/消极/中性表格里的五列是基础款。like_count容易被忽略但它其实很有用高赞评论往往代表群体情绪低赞则更个人化。训练时如果按 like_count 加权模型会更关注大多数人的感知而不是被个别人口嗨带偏。JSON 版大同小异每条记录是一个 dict{ song_id: 123456, content: 这首歌陪我熬过很多失眠的夜, sentiment: 1, like_count: 2048 }逻辑说明sentiment的 0、1、2 到底对应什么标签不同版本不一样有的用 0消极、1中性、2积极有的正好反过来。不要依赖直觉必须从 README 或label_map.txt里确认。我接手过一版把 0 当积极的数据跑出的精心调参模型在测试集上 F1 只有 0.3最后发现是标签语义反了整个黑匣子都在鬼打墙。读入 CSV 的代码也要注意编码import pandas as pd df pd.read_csv(train.csv, encodingutf-8-sig, enginepython) print(df[label].value_counts()) print(df.sample(5).to_string())参数说明encodingutf-8-sig是为了兜住 UTF-8 带 BOM 的文件否则第一列列名会变成\ufeffcomment后面所有代码都踩坑enginepython则针对文件里有杂散分隔符的情况C 引擎遇到格式不干净的行会直接报错python 引擎虽然慢一点但容错更好。2.3 先画分布标签不平衡比你想的更严重拿到数据集后第一件事不是写模型而是画三张图标签分布、评论长度分布、每首歌评论数分布。网易云评论数据集的特点是高赞热门评论和普通评论混在一起导致标签天然不平衡。常见情况是“消极”占比超过 50%因为网易云热评里的丧文化浓度确实高。如果不做处理一个全预测为“消极”的班戟模型就能拿到 50% 准确率让人误以为跑通了。另一个隐藏问题是演唱会和 live 版本评论里大量重复文本比如“呜呜呜”“好听”这类短文本在去重前会重复出现在训练集和测试集造成虚假高分。我在第 5 章会讲怎么避坑这里先给你一个自查动作print(df[song_id].nunique()) print(df.duplicated(subset[comment]).sum())逻辑说明nunique()看歌曲覆盖度如果只有几十首歌说明数据来自少量热门歌曲泛化性差duplicated()看重复评论条数如果有大量重复后续训练必须去重。3. 把评论文本变成可训练样本清洗、标签统一与数据划分3.1 清洗规则不要过度清洗但要处理 URL、 和乱码情感分类的清洗逻辑和做检索不一样。检索希望去掉停用词情感分类则要保留标点和否定词“我不开心”如果去掉“不”就彻底反了。我一般只做四个清洗动作去掉用户、去掉 URL、去掉 HTML 标签、把过短的文本标记出来而不是删掉。import re def clean_comment(text: str) - str: text re.sub(r[\w\u4e00-\u9fa5][:]?, , text) # 去除 用户 text re.sub(rhttps?://\S, , text) # 去除 URL text re.sub(r[^], , text) # 去除 HTML 标签 text re.sub(r\s, , text).strip() return text df[comment_clean] df[comment].astype(str).map(clean_comment) df[len] df[comment_clean].apply(len)参数说明正则里的[\w\u4e00-\u9fa5]同时匹配中英文昵称方便去掉“张三”这类前缀astype(str)是为了防空值 NaN否则.map会把 NaN 传进正则导致报错。清洗完之后看df[len].describe()如果大量评论长度小于 2好好想想是保留还是过滤——我一般保留因为“哈哈”“哭了”也是有效情感信号直接丢掉反而损失特征。网易云评论里还有大量表情符号。表情符号在like_count高的评论里特别多它是真实情感信号。不建议用emoji库直接删更好的做法是转成文本标记比如把[流泪]替换成[cry]。这样模型能学到“歌词本身平静 表情强烈”的反差情绪。3.2 标签统一把模糊的多分类映射成你能解释的体系不同版本的数据集标签五花八门。我见过happy/sad/angry/lonely/healing五分类也见过直接把1~5打分当标签的版本。如果你要复现别人的结果标签体系跟着原数据集走如果你要自己做应用建议统一成三分类积极、中性、消极。理由很朴素五分类里“孤独”和“伤感”在人类标注时都高度模糊模型学到的边界没什么可解释性。三分类则保留了商业上最关心的正负向判断又不至于像二分类那样强迫所有文本站队。映射逻辑写在函数里可以随时回滚label_map { happy: pos, 温暖: pos, 治愈: pos, 振奋: pos, lonely: neg, emo: neg, 伤感: neg, 愤怒: neg, 平静: neu, 歌词打卡: neu, 无感: neu } def map_label(x): return label_map.get(str(x).strip().lower(), neu) df[label_final] df[label].map(map_label)逻辑说明get的默认值设成neu需要谨慎如果原标签里有你没见过的值它会全变成中性导致数据比例漂移。更稳的写法是print(df[label].value_counts())先看全部类别再手工把映射表写全宁可多写十条也不要留默认值。3.3 按歌曲 ID 划分数据防止“记忆”而不是“理解”这是新手最容易翻车的一步。直接train_test_split(df, test_size0.2, random_state42)会把同一首歌的高赞评论同时分到训练和测试模型根本不需要理解情感只要记住“这首歌相关评论都偏向某个标签”就能答对。在本地测出来准确率 90%一换新歌就掉到 60%这就是泄漏。正确做法是按song_id分组划分from sklearn.model_selection import GroupShuffleSplit gss GroupShuffleSplit(n_splits1, test_size0.2, random_state42) train_idx, test_idx next(gss.split(df, df[label_final], groupsdf[song_id])) train_df df.iloc[train_idx] test_df df.iloc[test_idx]参数说明groupsdf[song_id]确保同一个song_id的所有评论只落在同一边random_state42固定划分结果不然复现实验时每次数据都变调参全成玄学。n_splits1表示只生成一次划分如果你需要交叉验证则把它调大并配合循环。划分之后还要确认验证集标签分布和训练集接近。如果训练集里消极 60%、验证集里消极 40%那评估会失真。常见修复方法是用带stratify的分层采样但注意它只对单标签生效要和GroupShuffleSplit一起用比较麻烦我的做法是先按歌曲 id 聚合分组再在歌曲级别做分层抽样。song_stats df.groupby(song_id).agg( song_label(label_final, lambda x: x.mode().iloc[0]) )这段先给每首歌定一个主导标签后续用StratifiedShuffleSplit在歌曲列表上划分再把评论映射回去。这样既保证组不泄漏又保证标签比例一致。虽然代码多写几行但至少测试集结果是可信的。4. 用本地模型跑通情感分类从 TF-IDF 到 BERT 的关键参数4.1 先跑一个不丢脸的基线TF-IDF 逻辑回归很多人一上来就上 BERT结果连tokenizer报错都调不明白。我建议先跑一个 TF-IDF 逻辑回归的基线五分钟出结果用它来验证数据质量。如果基线 F1 就在 0.7 以上说明数据没大毛病如果基线才 0.3就别急着调神经网络先回头查标签和数据泄漏。from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.linear_model import LogisticRegression from sklearn.pipeline import make_pipeline vectorizer TfidfVectorizer( ngram_range(1, 2), max_features50000, min_df2, sublinear_tfTrue ) model make_pipeline( vectorizer, LogisticRegression(C1.0, max_iter1000, class_weightbalanced) ) model.fit(train_df[comment_clean], train_df[label_final]) test_score model.score(test_df[comment_clean], test_df[label_final]) print(Test Accuracy:, test_score)参数说明ngram_range(1, 2)把“不好”的“不好”两个词作为整体特征比纯单词更能捕捉否定短语min_df2去掉只出现一次的词汇这类词大多是错别字或刷屏内容max_features50000限制词表大小避免内存爆炸sublinear_tfTrue用1 log(tf)替代原始词频削弱高频停用词影响class_weightbalanced自动调整正负样本权重应对我们说的标签不平衡。如果跑完准确率还行但 F1 很拉问题多半出在“中性类”上。中性评论在网易云数据集里经常是“打卡”“第一”这类无情绪内容和强情绪的积极/消极样本混在一起特征空间重叠大。可以看看混淆矩阵from sklearn.metrics import classification_report, confusion_matrix y_pred model.predict(test_df[comment_clean]) print(classification_report(test_df[label_final], y_pred))classification_report里macro avg比accuracy重要。0.8 准确率可能是把 60% 的消极样本全猜对换来的而中性类召回率接近 0。这类问题不是调参能解决的需要回到数据层面增加中性样本的多样性。4.2 微调中文 BERT学习率、批大小和序列长度怎么配基线验证数据靠谱后再上预训练模型。我用transformers的中文bert-base-chinese做序列分类关键参数不是神经网络的层数而是学习率、批大小和最大序列长度。网易云评论平均长度只有 20~30 个字序列长度设 64 就够设 128 只会浪费显存。from transformers import AutoTokenizer, AutoModelForSequenceClassification, Trainer, TrainingArguments tokenizer AutoTokenizer.from_pretrained(bert-base-chinese) model AutoModelForSequenceClassification.from_pretrained( bert-base-chinese, num_labels3 ) def tokenize(batch): return tokenizer( batch[comment_clean], truncationTrue, max_length64, paddingmax_length )代码只是骨架核心是后面训练参数training_args TrainingArguments( output_dir./results, learning_rate2e-5, per_device_train_batch_size32, per_device_eval_batch_size64, num_train_epochs3, warmup_ratio0.1, logging_dir./logs, eval_strategyepoch )参数说明learning_rate2e-5是中文 BERT 微调的安全区间高于 5e-5 很容易让预训练权重被新数据冲垮per_device_train_batch_size32在 16G 显存下跑 BERT-base 没问题显存小就降到 16max_length64是看了评论长度分布后定的eval_strategyepoch保证每个 epoch 结束后看一次验证集而不是只在最后看。这里有一个血泪经验如果你在训练时发现 loss 下降很慢先检查是不是标签映射写反了再检查学习率顺序不能反。BERT 的 loss 曲线本身是黑匣子输入输出都不直观唯一能快速确认的是每轮验证集 F1。如果三个 epoch 后 F1 和基线差不多说明数据质量有问题再叠模型层数也没救。4.3 用 F1 和混淆矩阵做评估而不是只看准确率情感分类里准确率会骗人。网易云这个数据集如果“消极”占 60%一个全部预测“消极”的模型准确率就是 60%看起来比随机好实际什么也没学会。我习惯先打印classification_report重点看macro avg再画一个三分类混淆矩阵。import matplotlib.pyplot as plt from sklearn.metrics import ConfusionMatrixDisplay ConfusionMatrixDisplay.from_predictions( test_df[label_final], y_pred, labels[neg, neu, pos], normalizetrue ) plt.show()normalizetrue把矩阵按行归一化能看出每一类真实样本有多少被猜对。比如“中性”这一行如果颜色很浅说明中性样本大量被归到积极/消极这不是调参能解决的而是中性样本本身和另外两类分不开。这时候要回去看清洗逻辑、标签映射甚至重新定义三分类的边界。5. 避坑指南我在这份数据集上踩过的五个坑5.1 现象解压到一半提示 CRC 错误文件损坏用 WinRAR 解压时到 80% 弹出“CRC 校验失败”中断退出。原因多半是压缩包在网盘传输过程中被截断或者二次打包时源文件本身已经不完整。我踩坑后第一时间不是重新下载而是先用unrar t测试完整性unrar t 网易云音乐情感分类数据集.rart参数会遍历包内所有文件并校验。如果输出大量 CRC 错误说明包确实坏了直接换个来源如果只有最后一个文件报错并且不是关键文件可以用unrar e把其他文件强制解出来。强制解压的命令是unrar x -kb 网易云音乐情感分类数据集.rar其中-kb表示保留损坏文件之前已解压的内容这个参数适合“缺一两个文件但能继续用”的场景。如果坏的是train.csv那就别挣扎了数据缺一块会让标签分布失真不值得为省下载时间付出后续排错成本。5.2 现象CSV 读取后列名变成\ufeffcomment所有代码都报 KeyError第一个坑还好这个才是真正让人挠头的。用 pandas 直接read_csv打印df.columns发现第一列是\ufeffcomment不是comment。原因是文件是 UTF-8 with BOM 编码Excel 转存 CSV 时常出现尤其是中文数据集几乎十有七八。解决是在read_csv时指定encodingutf-8-sig或者更通用一点先检测编码with open(train.csv, rb) as f: raw f.read(4) print(raw)如果开头是b\xef\xbb\xbf就是带 BOM。之后读取统一加encodingutf-8-sig。另外评论里如果夹杂 emoji普通 UTF-8 编码也能存但如果你用enginec遇到怪字符会直接崩溃这时候切到enginepython是后悔药它慢但不容易翻车。5.3 现象训练集准确率 92%换成新歌只有 61%这是我复现别人实验时遇到的真事。模型在随机划分的测试集上表现很好一部署到实际场景就露馅。原因就是我在第 3 章强调过的数据泄漏同一首歌的评论同时出现在训练和测试里模型学会了“这首歌偏消极”而不是“这句话偏消极”。解决方法是按song_id做 GroupShuffleSplit。如果原始数据集没有song_id只有song_name就用song_name作为 group。如果连歌名都没有那就只能做去重后按时间切分按时间靠前评论做训练、靠后评论做测试模拟真实场景。这个坑让我后来所有分类实验都养成了“先看分组字段再看模型”的习惯。5.4 现象清洗后标签数量对不上原文件train.csv 少了几百行这份数据集经常是多个来源合并的某一行song_id为空、某一行comment是 NaN、还有的整行都是重复。我一开始直接dropna()结果发现丢掉的行里大量是负样本因为采集时负样本更容易出现空字段导致清洗后标签比例严重失衡。正确做法是先区分“该删”和“不该删”。comment为空必须删因为没内容可训练song_id为空但不能删因为你还需要这句话可以先填未知值。重复评论则按“保留点赞最高的那条”去重df.dropna(subset[comment], inplaceTrue) df[song_id] df[song_id].fillna(unknown) df df.sort_values(like_count, ascendingFalse).drop_duplicates(subset[comment]).sort_index()逻辑说明先按like_count降序排序再按comment去重这样同一条评论重复出现时保留点赞数最高的版本。后面sort_index()恢复原顺序。去重后再重新统计标签分布你会看到分布可能和原始文件完全不同这才是真实可用的样本分布。5.5 现象rar 提示需要密码但来源说明里没有密码密码框还拦着不让解这就是前面提到过的“伪加密”。压缩包本身没加密只是文件头被改成了“有密码”状态WinRAR 看到标志位就弹窗。我用 7-Zip 直接解压成功过也见过用十六进制编辑器改回来才能解的例子。安全范围内的解决办法是先试 7-Zip再试 FastResume 之类的修复开关终极手段是把 rar 头中标识加密的字节还原。但只要是正经来源伪加密大多是打包者手滑不是故意为难不必一上来就动二进制。真遇到需要密码的加密包老老实实去找原始分享说明别浪费时间在破解上。6. 进阶从这份数据集出发构建你自己的网易云音乐情感数据集如果你用这份公开数据跑通了流程下一步很可能是想做自己的垂直数据。我建议不要一上来就大规模爬取更不要去碰需要逆向解析接口的东西规范化做法是两条路一是在自己的使用范围内做小规模人工采集二是用现有公开数据集做起点用模型辅助标注来扩充。无论哪条路都要先想清楚合规边界网易云音乐的用户评论受用户协议约束公开数据集能用于学习但自己采集并二次发布就可能越界。构建自己的数据集时标注质量比数量重要。我习惯先让三个人标注同一批 500 条样本计算两两之间的 Cohens KappaKappa 低于 0.6 就说明标注标准不统一。常见的分歧点是“调侃算积极还是消极”比如“这歌词是把我家监控拆了吗”有人觉得幽默积极有人觉得阴阳怪气消极。解决方式是写一份两页的标注规范里面放 20 条典型例子作为锚点标注时先把锚点过一遍。数据收集的另一个技巧是按歌曲类型分层民谣、电子、说唱、流行各采样一部分。网易云不同歌曲风格的情感表达差异很大只按热门榜采样会得到清一色的“深夜伤感”训练出的模型到电商客服场景基本废掉。我在做自建数据集时会控制每首歌不超过 200 条评论保证歌曲覆盖数量而不是单曲深度。最后验证模型效果我不用测试集 F1 当唯一标准。常见做法是抽 200 条样本人工盲测把模型预测结果和“标注者共识”对比这能暴露测试集本身标注错误的问题。如果你发现模型把“所以暂时将我眼睛闭了起来”预测为积极但人工共识是中性那不是模型错了而是原数据集没有歌词类样本模型没见过这种语境。此时要回到训练集补充类似表达。我自己的教训是第一次做网易云情感分类时花了大量时间调 BERT最后发现是数据划分泄漏导致虚假高分回头看最初 5 分钟跑完的 TF-IDF 才有参考价值。从那以后我所有文本分类项目都把数据检查排在模型调参之前这个习惯帮我省了很多冤枉时间。希望这篇笔记能让你少走几步弯路把火力集中在真正影响效果的数据质量上。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑