news 2026/10/15 3:47:41

wav2letter 无重叠语言模型语料构建:从 Libri-Light 元数据提取古腾堡书目清单实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
wav2letter 无重叠语言模型语料构建:从 Libri-Light 元数据提取古腾堡书目清单实战指南
  • 人工智能
  • 语音
  • 深度学习

【免费下载链接】wav2letter

Facebook AI Research's Automatic Speech Recognition Toolkit

项目地址:https://gitcode.com/gh_mirrors/wa/wav2letter
点击查看免费下载

本篇指南围绕 wav2letter 仓库中 raw_lm_corpus 复现管线的一个关键前置步骤展开:从 Libri-Light 数据集的 JSON 元数据中批量提取音频来源书籍(LibriVox)的书目与古腾堡(Gutenberg)书籍 ID。读完本文,你将掌握使用jq+xargs并行解析 JSON 元数据、用纯 shell 管道清洗与归一化"标题|URL"映射表、以及提取 5561 个古腾堡书籍 ID 的完整命令链,并理解这些 ID 如何服务于论文中"no overlap"(与 LibriVox 音频无重叠)语言模型语料的构建。

一、背景:为什么需要 Libri-Light 书目清单

wav2letter 的 SOTA 2019 复现配方中,raw_lm_corpus 的目标是复现论文使用的"no overlap"语言模型语料:将 LibriSpeech LM 语料(源自古腾堡计划书籍)中所有出现在 LibriVox 有声书音频里的书剔除,从而避免训练语料与用于评估的 LibriVox 音频内容重叠,保证语言模型评估的公正性。

整个剔除流程需要两侧书目:

  • LibriSpeech 侧:从 LibriSpeech LM 语料的BOOKS.TXT元数据中提取古腾堡 ID;
  • LibriVox 侧:即本指南 get_libri-light_book_titles.md 负责的部分——从 Libri-Light 数据集的 JSON 元数据中提取每条音频对应的书籍标题与文本来源 URL,进而解析出古腾堡书籍 ID。

两侧 ID 生成后,通过comm -12取交集即可得到"LibriSpeech 语料中存在且同时被 LibriVox 音频朗读过"的书籍 ID,作为元数据层面的排除清单(见 README.md 中librispeech_minus_librivox.metadata_only.excluded.ids.lst的生成命令)。

二、前置准备:数据集、工具与环境

开始前需要准备三样东西:

  1. Libri-Light 数据集:下载 Libri-Light 数据集的全部三个子集small、medium与large。每个子集都包含各自的元数据 JSON 文件(内含book_meta等书籍信息字段)。注意:本指南只用到元数据 JSON 文件,无需处理音频本身。
  2. jq命令行工具:用于从 JSON 中提取字段。它是 get_title_url_table.sh 的核心依赖,请确保已安装且位于PATH中。
  3. Python 虚拟环境(可选但推荐):后续管线步骤(模糊匹配、按 ID 抓书等)依赖 requirements.txt 中的依赖,包括Gutenberg==0.8.0、python-Levenshtein==0.12.0、fuzzywuzzy==0.17.0、num2words、roman等。可在本目录执行:
pip install -r requirements.txt

仓库中与本流程直接相关的脚本清单如下:

脚本作用
get_title_url_table.sh用jq从单个 Libri-Light JSON 元数据文件中抽取标题|URL行
levenshtein-word.pl按词计算两个标题集合间的编辑距离,供模糊匹配
filter_distances.py按分数与距离比过滤模糊匹配结果
join_ids.py将 ID 清单与"标题→ID"表做连接
get_gb_books_by_id.py按 ID 从古腾堡拉取全文并去除头部

三、提取 JSON 元数据清单

下载好三个子集后,先用find把所有子集内的 JSON 元数据文件路径收集到一个清单文件中:

find small medium large -type f -name "*.json" > json.metadata.manifest

这一步把分散在small、medium、large三个目录树中的所有 JSON 元数据路径汇总为一行一个文件路径的清单,作为下一步并行处理的输入。文档后续命令中出现的all.json.metadata.out即指这份(或合并后)的 JSON 文件清单——若文件名不同,只需保证cat的对象是同一份逐行列出 JSON 路径的清单即可。

四、用 jq 并行生成"标题|URL"映射表

4.1 脚本源码剖析

核心抽取逻辑位于 get_title_url_table.sh,全文仅一行:

#!/bin/bash jq '.book_meta.title + "|" + .book_meta.url_text_source' $1 >> $2

它做的事情非常直接:对传入的第一个参数(单个 Libri-Light JSON 元数据文件),用jq读取路径book_meta.title(书名)与book_meta.url_text_source(文本来源 URL),拼接成标题|URL格式的一行,追加写入第二个参数指定的输出文件。因此:

  • 输出文件的每一行格式为title|url,字段间以|分隔;
  • 使用>>追加模式,多路并行写入同一文件时不会互相覆盖(这是下面并行调用的关键前提)。

4.2 并行调用命令

由于元数据文件数量可能很多,文档采用xargs并行执行:

cat all.json.metadata.out | \ xargs -I{} --max-procs=$(nproc) -n 1 \ bash get_title_url_table.sh \ {} \ libri-light_unnormalized_title_to_url_text_source.json

参数说明:

参数含义
-I{}用{}占位符接收清单中的每一行(即单个 JSON 文件路径)
--max-procs=$(nproc)并发进程数取当前 CPU 核数,实现全核并行解析
-n 1每次调用传递 1 个参数
bash get_title_url_table.sh {} <输出文件>对每个 JSON 文件执行抽取脚本,结果追加到libri-light_unnormalized_title_to_url_text_source.json

运行结束后,libri-light_unnormalized_title_to_url_text_source.json即为未清洗的原始映射表,包含全部子集的标题|URL行。

五、清洗映射表:去除引号、空白与坏 URL

原始映射表的每一行都带有 JSON 字符串的首尾引号,且部分条目存在前后空白、URL 前多余空格、或格式严重损坏的 URL。文档给出的清洗命令及其逐步含义如下:

cat libri-light_unnormalized_title_to_url_text_source.json | rev | \ cut -c2- | rev | cut -c2- | \ sort -S 75% --parallel=$(nproc) | uniq | \ awk '{$1=$1;print}' | sed "s/| h/|h/g" | grep -v -F " http" \ > libri-light_unnormalized_title_to_url_text_source.json.clean

管道中各段的作用:

管道段作用
rev \| cut -c2- \| rev \| cut -c2-经典的"去首尾各一个字符"技巧:rev反转每行,cut -c2-去掉反转后的第一个字符(即原行最后一个字符),再反转回来去掉原行第一个字符。两条引号(JSON 字符串的首尾")即被移除
sort -S 75% --parallel=$(nproc)按行排序,允许使用最多 75% 物理内存做外部排序,并按核数并行,以应对可能达到数 GB 的映射表
uniq去重
awk '{$1=$1;print}'触发 awk 对首字段的重新赋值,从而去除每行首尾的空白字符
sed "s/| h/|h/g"删除 URL 前多余的空格(修复title| http...这类格式)
grep -v -F " http"过滤掉仍然包含" http"(URL 前带空格)的损坏行;-F表示按固定字符串匹配而非正则

清洗结果写入libri-light_unnormalized_title_to_url_text_source.json.clean,作为后续提取 URL 与 ID 的输入。

六、生成规范化的唯一标题清单

除了 URL 侧,还需要一份去重后的标题清单,供后续与 LibriSpeech 侧书目做模糊匹配(详见第八节)。命令如下:

cat libri-light_unnormalized_title_to_url_text_source.json| rev | \ cut -c2- | rev | cut -c2- | awk -F"|" '{print $1}' | sort | uniq \ > libri-light_all_titles.norm.uniq.sorted.lst

其含义为:

  • 同样先用rev | cut -c2- | rev | cut -c2-去掉首尾引号;
  • awk -F"|" '{print $1}'以|为分隔符,只取第一个字段(标题部分),丢弃 URL;
  • sort | uniq排序并去重,得到规范化的唯一标题清单libri-light_all_titles.norm.uniq.sorted.lst。

这份标题清单在 README.md 的模糊匹配阶段被拆分为多个分片(split --lines=$NPIECES),配合 levenshtein-word.pl 做分布式书名近似匹配。

七、抓取古腾堡书籍 ID

映射表中的 URL 指向文本来源。古腾堡来源的 URL 形如./1234.txt或带参数的形式,需要从中提取纯数字的书籍 ID:

cat libri-light_unnormalized_title_to_url_text_source.json.clean | \ grep -F "gutenberg" | sed "s#./##g" | sed "s#?.##g" | \ sort | uniq | grep -v -e '^$' | grep -Eo '[0-9]+$' | sort | uniq \ > libri-light_title_to_url_text_source.gutenberg_ids.final.lst

逐步解析:

管道段作用
grep -F "gutenberg"只保留 URL 中包含gutenberg的行(即古腾堡来源,过滤掉其他文本源)
sed "s#./##g"删除 URL 中./前缀(这里用#作为sed的分隔符以避免与/冲突)
sed "s#?.##g"删除?.形式的杂散 URL 参数(如?.txt片段)
sort \| uniq排序去重
grep -v -e '^$'剔除空行
grep -Eo '[0-9]+$'用扩展正则提取行尾的纯数字串,即书籍 ID;-o只输出匹配部分
sort \| uniq再次排序去重,得到最终唯一 ID 清单

最终结果验证:

wc -l libri-light_title_to_url_text_source.gutenberg_ids.final.lst # 5561

即从 Libri-Light 元数据中共提取出5561 个古腾堡书籍 ID。注意 README.md 后续引用该清单时写为librilight_title_to_url_text_source.gutenberg_ids.final.lst,与本指南输出文件名仅差一个连字符,属于文档中的命名变体,指向同一份产物。

八、后续应用:从书目到无重叠语料

本指南生成的 ID 清单只是"no overlap"语料构建的第一步,其后续去向(详见 README.md)包括:

8.1 元数据层面的精确匹配

先用 LibriSpeech LM 语料的BOOKS.TXT生成 LibriSpeech 侧的古腾堡 ID 清单:

awk -F"|" '{print $1}' BOOKS.TXT | grep -Fv ";" | awk '{$1=$1;print}' | \ sort | uniq > librispeech_lm_corpus.gutenberg.ids.lst

再与 LibriVox 侧 ID 取交集,得到元数据层面的排除清单:

comm -12 <(sort librispeech_lm_corpus.gutenberg.ids.lst) \ <(sort librilight_title_to_url_text_source.gutenberg_ids.final.lst) \ > librispeech_minus_librivox.metadata_only.excluded.ids.lst

8.2 模糊匹配捕获命名变体

元数据精确匹配无法覆盖书名拼写差异(如冠词、大小写、标点不同)。为此,README 先用join_ids.py把 LibriSpeech 的 ID 映射到规范化标题,再用split把 LibriVox 标题清单分片,交给 levenshtein-word.pl 并行计算两两词级编辑距离:

find librivox_title_splits/ -type f | xargs --max-procs=80 -n 1 -I{} \ sh -c "levenshtein-word.pl {} librispeech_lm_corpus.gutenberg.ids.mapped_to_gutenberg_normalized_titles.titles.lst > {}.librispeech_lm_corpus.minus_librivox.norm.word.distances"

levenshtein-word.pl 的源码展示了其距离计算方式:将两个标题按空格切分为词序列,动态规划计算词级编辑距离,输出格式为str1|str2|lev。随后用 filter_distances.py 按--score 0.3 --distance_ratio 0.75过滤:

python3 filter_distances.py \ --infile combined.librispeech_lm_corpus.minus_librivox.norm.word.distances.lst \ --score 0.3 \ --distance_ratio 0.75

从 filter_distances.py 源码看,过滤条件为:两标题词数差与最小词数之比小于distance_ratio,且距离 ≤score × 最大词数。过滤结果经人工分析后形成手工排除清单,仓库中保留了成品 librispeech_lm_corpus.librivox.manual.excluded.titles.lst(形如libriVox标题|古腾堡标题|距离三列,当前仓库版本共 813 行)。

8.3 合并排除清单并生成最终语料

元数据排除与手工排除的 ID 合并后(README 记录为 2919 个 ID),用comm -23从 LibriSpeech 语料中剔除这些书。README 总结最终语料包含12046 本书,约为原始语料的 83%(对应命令wc -l输出为 11576 行,文档中两处数字略有出入,以实际复现为准)。缺失的书还会通过 get_gb_books_by_id.py(内部使用gutenberg.acquire.load_etext拉取全文、strip_headers去头)与 process_raw_text.py 补充,最终拼出librispeech_lm_corpus.minus_librivox.metadata_and_manual_and_missing.corpus.txt,再经 normalize_title.sh 等脚本规范化后用于训练 n-gram 语言模型。

九、实战注意事项

  1. 并行安全:get_title_url_table.sh 使用>>追加写输出文件,因此xargs的多进程并发是安全的;但若重复运行需先清空或删除旧输出文件,避免累积重复行。
  2. 大文件排序:映射表可能达数 GB,sort -S 75% --parallel=$(nproc)中的-S限制排序可用内存,避免 OOM;磁盘空间需预留足够临时空间。
  3. 书名规范化:标题清单的"规范化"主要指去除 JSON 引号、首尾空白与 URL 冗余部分;若需进一步统一书名拼写(去连字符、小写、&→and等),可复用 postprocessing_title.py 及 normalize_title.sh 中的规则,其接受字符集为小写字母、数字与单引号。
  4. 文件名变体:json.metadata.manifest与all.json.metadata.out、libri-light_...与librilight_...在文档各文件中存在命名差异,复现时保持同一份产物即可。
  5. 适用前提:本流程针对 2019 年前后 Libri-Light 数据集结构(JSON 中含book_meta.title与book_meta.url_text_source字段)编写;若数据集元数据格式变更,需先检查字段路径是否仍然有效。

十、总结

本文完整复现了 wav2letter SOTA 2019 配方中"从 Libri-Light 元数据提取书目与古腾堡 ID"的全部命令链:find收集 JSON 清单 →jq并行抽取标题|URL→ shell 管道清洗 → 生成唯一标题清单 → 提取 5561 个古腾堡 ID。这些 ID 随后通过精确匹配(comm -12)与词级编辑距离模糊匹配(levenshtein-word.pl + filter_distances.py)参与"no overlap"语言模型语料的构建,是保证 wav2letter 论文中语言模型评估严谨性的关键数据工程环节。整套流程以纯 shell 工具为主,数据量虽大但每一步都可拆分、可验证,适合作为大规模语料元数据清洗的参考实现。

  • 人工智能
  • 语音
  • 深度学习

【免费下载链接】wav2letter

Facebook AI Research's Automatic Speech Recognition Toolkit

项目地址:https://gitcode.com/gh_mirrors/wa/wav2letter
点击查看免费下载

相关推荐

上一篇:Valdi 视图体系入门:`<layout>` 与 `<view>` 的基础构件、性能取舍与 iOS 26 Liquid Glass
下一篇:Armbian 配置管理实战:新增开发板、Git 追踪与多架构复用

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

OpenEMR免费部署指南:从零搭建一套完整的开源电子病历系统

OpenEMR免费部署指南&#xff1a;从零搭建一套完整的开源电子病历系统 【免费下载链接】openemr The most popular open source electronic health records and medical practice management solution. 项目地址: https://gitcode.com/GitHub_Trending/op/openemr OpenE…

作者头像 李华
网站建设 2026/10/15 3:47:24

【点此获取源码】联系博主获取计算机毕设选题以及答辩资料

&#x1f64a;作者简介&#xff1a;多年一线开发工作经验&#xff0c;分享技术代码帮助学生学习。自有计算机毕设的工作室团队&#xff0c;专注计算机毕设开发、定制、远程、文档编写指导等。&#x1f44d; 文末查看联系方式 ⭐&#x1f345; 文末查看联系方式&#x1f345; ⬇…

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

cloudpods 中的 JWE 数据加密:基于 lestrrat-go/jwx 的 RFC 7516 加密实战指南

后端云原生运维虚拟化人工智能AI 应用 【免费下载链接】cloudpods 开源、云原生的多云管理及混合云融合平台 项目地址&#xff1a; https://gitcode.com/yunionio/cloudpods 点击查看 免费下载 导读 本文以 cloudpods 仓库内置的 vendor/github.com/lestrrat-go/jwx/jwe 包为…

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

若依前后端分离项目部署实战:从环境配置到Nginx反向代理

简介&#xff1a;若依前后端分离项目是目前广泛使用的开源快速开发平台&#xff0c;前端采用 Vue 与 Element UI&#xff0c;后端基于 Spring Boot、Spring Security、Redis 和 Jwt&#xff0c;并支持代码生成器一键生成前后端代码。部署文档面向后台开发、实施运维以及需要自行…

作者头像 李华
网站建设 2026/10/15 3:43:55

FPGA+CY68013 Slave FIFO高速Bulk传输实战调通指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华