ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

中文歌词库NLP语料处理实战:从数据清洗到分类模型

中文歌词库NLP语料处理实战:从数据清洗到分类模型 简介面向NLP与数据分析实践的中文歌词数据集收录102197首歌曲、4019位歌手覆盖绝大多数华语歌手2019年前作品歌词按歌手聚类并按作品数降序排列便于开展歌手维度的对比研究与数据划分。其中作品数20首以上的歌手有1086人100首以上233人数据覆盖度较高。资源包共6个文件主体为5个json数据文件分别存放按歌手聚类的歌词正文、词频排序、句子开头词频统计及押韵表另有1个md说明文档整体压缩包约34.15MB轻量易用。已有1068人学习下载。借助歌词正文与统计结果可支持词频分析、押韵规律研究、歌词文本生成、歌手风格特征提取等常见NLP任务也可作为中文分词、情感分析和语言模型训练的基础语料数据字段清晰歌名、歌手、歌词适合自然语言处理入门者及数据分析从业者快速开展实验。1. 为什么我把中文歌词库当成 NLP 入门的第一份语料刚开始跑 NLP 项目时我最头疼的不是模型选型而是找一份能反复折腾的中文语料。后来我换了个思路把 ChineseLyrics 中文歌词数据库当成练习场它既是标准的 NLP 自然语义处理数据集又不像新闻、百科那样充满长句和套话。歌词短、情绪浓、句式重复非常适合验证分词、词频统计、情感分析和文本分类这些入门任务。这篇文章会从下载、清洗到踩坑把这份数据集完整跑一遍。想用歌词做情感分析、歌词生成或者中文 NLP 入门练手的人可以直接照着抄。2. 拿到 ChineseLyrics 数据集下载、字段摸底与内存预估2.1 用一行代码把数据拉下来很多人第一次接触数据集习惯去 GitHub 上下载 CSV再自己写脚本解析。但 ChineseLyrics 这类在 Hugging Face 上维护的数据集最省事的做法是用datasets库直接加载它自动完成下载、缓存和格式转换不用关心底层文件到底存成了 parquet 还是 arrow。常见做法是直接指定数据集名和划分第一次运行会显示下载进度之后走本地缓存不会再联网# 用 datasets 库直接加载首次会自动下载并缓存 from datasets import load_dataset ds load_dataset(Ampersand/ChineseLyrics, splittrain) print(ds.column_names) # 查看字段名 print(len(ds)) # 查看总条数 print(ds[0]) # 查看第一条样本这里有两个参数需要理解splittrain表示取训练划分有的版本还会带validation和test加载测试集时改成对应名字即可column_names返回列表里面是每条样本的字段名。如果下载速度很慢常见做法是先在终端里指定镜像源再跑上面的命令# 如果下载慢先指定国内镜像源再执行 python 脚本 export HF_ENDPOINThttps://hf-mirror.comdatasets库会把数据缓存到~/.cache/huggingface目录重复加载不需要重新下载。需要注意的是不同上传者对字段命名可能不一样有的叫song有的叫title下载后先打印column_names别想当然。2.2 字段结构、语料规模与内存预估拿到数据的下一步是搞清楚每一列到底是什么类型。以常见的 ChineseLyrics 版本为例字段大致长这样字段名类型含义典型示例song_namestr歌名晴天singerstr歌手周杰伦albumstr专辑名叶惠美lyricsstr歌词正文故事的小黄花从出生那年就飘着genrestr曲风标签流行 / 摇滚 / 民谣lyrics是核心字段其它字段大多用于去重和标签构造。歌词正文通常带换行也可能混入时间戳、间奏注释。先把整列转成 Pandas DataFrame看长度分布这是判断语料能不能用最快的方法import pandas as pd df pd.DataFrame(ds) df[lyrics_len] df[lyrics].apply(len) print(df[lyrics_len].describe())describe()输出的min、mean、max三个值最重要如果min接近 0说明存在大量空歌词如果mean只有几十说明语料可能是片段而非完整歌词如果max超过一万说明混入了一些长文需要结合业务判断是否要裁掉。内存预估也很简单中文字符在 UTF-8 下通常占 3 字节拿len(ds)乘以平均长度再乘 3就是原始文本的大致体积。实际跑 NLP 任务时还要算分词后的 token 数一般按字符数的三分之一到二分之一估。这套估算方法对任何中文文本数据集都适用不只在歌词上有效。3. 歌词清洗从原始文本到可训练词表的四个关键步骤3.1 文本清洗与繁简转换歌词文本最大的特点是“脏”得很有规律换行符多、全角标点密、括号里塞着“间奏”“独白”之类的舞台提示还有的版本带了卡拉 OK 时间戳。清洗目标不是把所有非中文字符删光而是保留语义信息、去掉排版噪音。我一般会先建一个清洗函数按固定顺序处理import re def clean_lyrics(raw): # 去掉括号里的注释如间奏、[01:23.45]这类时间戳 raw re.sub(r[\[\(].*?[\]\)], , raw) # 全角标点统一替换成空格避免和文字粘连 raw re.sub(r[。、《》], , raw) # 连续空白折叠成一个空格包括换行和制表符 raw re.sub(r\s, , raw) return raw.strip()第一个正则用.*?非贪婪匹配保证间奏和[00:12.34]成对删除不会误删括号后面的正文第二个正则把中文标点换成空格是因为多数分词器按空白切词标点混在词里会把“舍不得”切成“舍不得”最后一步折叠空白避免分词结果里出现空串。标点归一化之后接着处理繁体。港台歌手的歌词很多是繁体如果不转简体同一个词会被拆成两个特征比如“愛”和“爱”。常见做法是用zhconv批量转换from zhconv import convert def to_simplified(text): return convert(text, zh-cn)convert的第二个参数指定目标语言zh-cn是简体中文转换规则。需要注意zhconv对粤语方言词支持有限“嘅”“唔”这类字会被原样保留这是正常的如果你后续要做粤语歌词分析反而要防止它们被误转。3.2 分词与词表构建两个必调参数清洗完的文本还不能直接喂给模型中文必须先分词。最常用的分词器是jieba它在歌词这类短文本上表现尚可而且支持用户自定义词典。我一般在项目里用精确模式而不是全模式因为全模式会产生大量重叠词词表会虚胖。import jieba from collections import Counter def tokenize(text): return [w for w in jieba.cut(text, cut_allFalse) if w.strip()] counter Counter() for t in clean_samples[:20000]: counter.update(tokenize(t)) # 过滤掉出现次数小于 min_count 的词 vocab {w: i for i, (w, c) in enumerate(counter.items()) if c 3}这里有两个参数必须调cut_all必须设为False不然“我会变成”会被切成“我会”“变成”“会变”一堆冗余片段min_count设为 3 是歌词场景的经验值比它再高会把“遗憾”“温柔”这类低频但情感强烈的词丢掉比它低又会保留大量只在某一首歌里出现一次的人名和地名。分词后还要不要删停用词我的建议是歌词场景谨慎删。像“你”“我”“的”这类词在新闻分类里是噪音但在歌词情感分析里恰恰承载了人称视角和情绪指向。真要删只删语气词“啦”“哦”“呀”这类纯衬字不要套用通用停用词表。清洗和分词是另一个层面的“黑匣子”很多人直接拿原始歌词喂 word2vec结果学出来的词向量里全是标点和“咦”“呀”“哈”模型跑通是跑通了但下游任务效果差。先把这里做好后面省很多事。4. 踩坑实录处理中文歌词语料的五个典型问题与排查4.1 副歌重复导致数据集“虚胖”现象统计词频后“眼泪”“爱你”这类词出现次数异常高但实际语料多样性很差做情感分析时模型只学会看到“眼泪”就判伤感。原因一首歌的副歌会原样重复两到三遍同一首歌也可能同时存在专辑版、现场版、翻唱版数据集里是按条目存的所以重复文本比例可能高到离谱。解决先按歌名和歌手做行级去重再做段落级去重只保留每首歌的第一段和第二段副歌出现的次数降下来后再跑统计。dedup df.drop_duplicates(subset[song_name, singer]) print(len(dedup), len(df))4.2 繁体词和简体词被当成两个特征现象词表里同时出现“愛情”和“爱情”“尋找”和“寻找”词表规模虚增一倍模型泛化变差。原因数据源来自多个音乐平台港台歌手的歌词条目是繁体清洗时没做统一转换。解决在清洗流程里加一道zhconv转换。注意要在分词之前转分词之后再转就来不及了因为 jieba 对繁简体用同一套词典但得到的 token 不会合并。4.3 空歌词和“暂无歌词”混入语料现象清洗后出现空字符串模型训练时 loss 突然变成 NaN或者输出一堆空白。原因部分条目没有版权歌词平台用“暂无歌词”“纯音乐”“间奏”这类占位符填充。解决加一道长度阈值过滤同时把占位符文本直接剔除。def is_valid(text): if len(text) 10: return False if any(k in text for k in [暂无, 纯音乐, 间奏]): return False return True4.4 加载数据集时卡在下载进度条现象load_dataset一直停留在Downloading...进度条不动最后报连接超时。原因Hugging Face 的存储节点国内直连不稳定这是网络问题不是代码问题。解决在终端设置HF_ENDPOINThttps://hf-mirror.com或者直接在 Python 里os.environ[HF_ENDPOINT] https://hf-mirror.com再重新执行加载。镜像站是只读的接口兼容下载完缓存后后续不需要再走网络。4.5 读取本地文件时遇到编码报错现象用open()读 JSON 或 CSV 时报UnicodeDecodeError或者打印出来是一堆乱码。原因歌词数据可能来自 Windows 平台导出文件编码是GBK或GB18030而默认打开方式是utf-8。解决读文件时显式指定编码多个候选编码依次尝试for enc in [utf-8, gb18030, gbk]: try: with open(path, r, encodingenc) as f: data f.read() break except UnicodeDecodeError: continue这五条是我跑歌词语料时真实翻过车的场景尤其是副歌重复和繁简混用几乎每个新手都会踩。排查顺序建议是先看空值占比再做去重最后看词表里有没有明显重复的繁简对。5. 把数据集用到实处训练一个曲风主题分类器5.1 用 TF-IDF 加逻辑回归快速验证语料质量清洗好的歌词最好落在一个真实任务上验证别只停留在跑通分词。最省事的验证方案是拿曲风标签做分类把清洗后的歌词当成文本用 TF-IDF 特征加逻辑回归先看一个 baseline 分数。分数高说明语料干净、标签有意义分数低先别怀疑模型回头查清洗和标签质量。from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.linear_model import LogisticRegression from sklearn.model_selection import train_test_split X clean_samples y genre_labels # 比如 流行 / 摇滚 / 民谣 X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.2, random_state42 ) vec TfidfVectorizer(max_features20000, ngram_range(1, 2)) X_vec vec.fit_transform(X_train) clf LogisticRegression(max_iter500) clf.fit(X_vec, y_train) print(clf.score(vec.transform(X_test), y_test))max_features20000限制特征维度避免词表太大导致内存溢出ngram_range(1, 2)让特征里包含“不是”“没有”这类双词搭配对否定情感的表达很重要。逻辑回归的max_iter500是小型文本分类的稳妥值太小可能没收敛。我现在每次换新语料第一步永远是画词频分布和文本长度分布确认清洗干净再进模型这个习惯救过我不少次。分类 baseline 跑通之后再上词向量、微调预训练模型都来得及。希望这些步骤能帮你在 ChineseLyrics 上少走弯路。本文还有配套的精品资源点击获取
返回列表