要在GitHub上执行或查看/下载此笔记本
SpeechBrain 简介
SpeechBrain 是一个基于 PyTorch 的 开源 一体化 语音工具包。它旨在使语音技术的研究和开发更加容易。
动机
有许多语音和音频处理任务具有重要的实际和科学意义。
过去,主要的方法是开发一个针对每个不同任务的不同工具包。然而,学习多个工具包是耗时的,可能需要掌握不同的编程语言,并且迫使你熟悉不同的代码风格和标准(例如,数据读取器)。
如今,大多数这些任务都可以通过相同的深度学习技术来实现。 因此,我们明确设计了SpeechBrain以原生支持多种语音处理任务。我们认为这可能会大大简化语音开发人员的生活。此外,我们认为将不同的语音技术结合在单一的端到端和完全差分系统中,对于未来语音技术的发展至关重要。
我们尽力设计了一个工具包,它具有以下特点:
易于使用
易于定制
灵活的
模块化
文档齐全
支持的技术
因此,您可以使用speechbrain将语音转换为文本,使用speaker verification进行身份验证,提高语音信号的质量,结合来自多个麦克风的信息,以及许多其他功能。
更准确地说,SpeechBrain 目前支持许多对话式 AI 技术,包括:
语音识别
说话人识别
语音分离
语音增强
文本转语音
语音编码
口语理解
语音到语音翻译
语音翻译
情感分类
语言识别
语音活动检测
声音分类
自监督学习
可解释性
语音生成
度量学习
对齐
语音分割
语言建模
响应生成
字形到音素
对于所有这些任务,我们提出了在流行数据集上实现竞争性或最先进性能的配方。
SpeechBrain 是一个正在进行中的项目(仍处于测试版),我们正在建立一个大型社区,以进一步扩展当前的功能。
安装
基本上有两种安装SpeechBrain的方法:
本地安装:如果您想修改工具包或从头开始训练完整的语音处理系统,建议使用此方法。
通过 PyPI 安装:当您只想在项目中使用 SpeechBrain 的一些核心功能时,建议使用此方法。
本地安装(Git克隆)
%%capture
# Installing SpeechBrain via pip
BRANCH = 'develop'
!python -m pip install git+https://github.com/speechbrain/speechbrain.git@$BRANCH
# Clone SpeechBrain repository
!git clone https://github.com/speechbrain/speechbrain/
%cd /content/speechbrain/templates/speech_recognition/
安装完成后,您应该能够使用python导入speechbrain项目:
import speechbrain as sb
运行实验
要使用SpeechBrain运行实验,典型的语法是:
python train.py hparams.yaml
所有的超参数都总结在一个yaml文件中,而训练的主脚本是train.py。
例如,让我们运行一个SpeechBrain提供的最小示例:
%cd /content/speechbrain/tests/integration/ASR_CTC/
!python example_asr_ctc_experiment.py hyperparams.yaml
在这种情况下,我们使用存储在文件夹samples中的一个小数据集训练了一个基于CTC的语音识别器。正如你所看到的,训练损失非常小,这表明模型实现正确。然而,验证损失却很高。这是因为,正如预期的那样,数据集太小,无法让网络进行泛化。
有关最小示例的更详细描述,请参阅“逐步最小示例”教程。
所有实验的结果都存储在yaml文件中定义的output_folder中。在这里,你可以找到检查点、训练好的模型、一个总结性能的文件以及一个日志记录器。
这样,您可以将您的表现与我们实现的表现进行比较,并且您可以访问所有预训练的模型。
使用YAML进行超参数规范
机器学习系统通常需要指定多个超参数。在SpeechBrain中,我们使用YAML来完成这一任务。YAML使我们能够以优雅、灵活和透明的方式指定超参数。
让我们看看这个 yaml 片段:
dropout: 0.8
compute_features: !new:speechbrain.lobes.features.MFCC
n_mels: 40
left_frames: 5
right_frames: 5
model: !new:speechbrain.lobes.models.CRDNN.CRDNN
input_shape: [null, null, 440]
activation: !name:torch.nn.LeakyReLU []
dropout: !ref <dropout>
cnn_blocks: 2
cnn_channels: (32, 16)
cnn_kernelsize: (3, 3)
time_pooling: True
rnn_layers: 2
rnn_neurons: 512
rnn_bidirectional: True
dnn_blocks: 2
dnn_neurons: 1024
正如你所见,这不仅仅是一个简单的超参数列表。对于每个参数,我们指定了将要使用它的类(或函数)。这使得代码更加透明且更易于调试。
YAML 文件包含加载类时初始化类的所有信息。在 SpeechBrain 中,我们使用一个名为 load_hyperpyyaml 的特殊函数加载它,该函数为我们初始化所有声明的类。这使得代码非常易读且紧凑。
我们的hyperpyyaml是标准YAML的扩展。要了解所有支持功能的概述,请查看YAML教程。
请注意,所有超参数都可以从命令行覆盖。例如,要更改dropout因子:
python experiment.py params.yaml --dropout=0.5
实验文件
实验文件(例如,示例中的example_asr_ctc_experiment.py)通过结合yaml文件中声明的函数或类来训练模型。此脚本定义了数据处理流程,并从输入信号到最终成本函数定义了所有计算。所有设计都旨在**易于定制**。
数据规范
用户应准备一个数据规范文件(以CSV或JSON格式),该文件报告所有要处理的数据和标签。
例如,在前面运行的最小示例中,数据规范文件是这样的:
ID, duration, wav, wav_format, wav_opts, spk_id, spk_id_format, spk_id_opts, ali, ali_format, ali_opts, phn, phn_format, phn_opts,char,char_format,char_opts
spk1_snt5,2.6,$data_folder/spk1_snt5.wav, wav, ,spk1,string, ,$data_folder/spk1_snt5.pkl,pkl, ,s ah n vcl d ey ih z dh ax vcl b eh s cl t cl p aa r dx ax v dh ax w iy cl,string, ,s u n d a y i s t h e b e s t p a r t o f t h e w e e k,string,
spk2_snt5,1.98,$data_folder/spk2_snt5.wav, wav, ,spk2,string, ,$data_folder/spk2_snt5.pkl,pkl, ,vcl jh ah m cl p dh ax f eh n s ae n hh er iy ah cl p dh ax vcl b ae ng cl,string, ,k e n p a I r s l a c k f u l l f l a v o r,string,
您可以使用CSV阅读器打开此文件以获得更好的渲染效果。对于每一行,您都有一个示例,其中包含对应的wav信号和标签的路径。
作为替代方案,用户可以用JSON格式指定数据:
{
"spk1_snt5": {
"wav": "{data_root}/spk1_snt5.wav",
"length": 2.6,
"spk_id": "spk1",
"ali": "{data_root}/spk1_snt5.pkl",
"phn": "s ah n vcl d ey ih z dh ax vcl b eh s cl t cl p aa r dx ax v dh ax w iy cl",
"char": "s u n d a y i s t h e b e s t p a r t o f t h e w e e k"
},
"spk2_snt5": {
"wav": "{data_root}/spk2_snt5.wav",
"length": 1.98,
"spk_id": "spk2",
"ali": "{data_root}/spk2_snt5.pkl",
"phn": "vcl jh ah m cl p dh ax f eh n s ae n hh er iy ah cl p dh ax vcl b ae ng cl",
"char": "k e n p a i r s l a c k f u l l f l a v o r"
}
}
JSON 比 CSV 更不紧凑但更灵活。对于许多应用来说,使用 CSV 文件就足够了。然而,对于更复杂的任务(例如,说话人分割、说话人分割 + 识别),人们可能会利用 JSON 提供的层次结构。
所有数据集的格式都不同。通常,用户需要编写一个数据准备脚本来解析目标数据集并创建数据规范文件。然而,对于所有提出的方案,我们也发布了相应的数据准备库。
数据处理管道
感谢我们的动态数据集,数据读取管道可以直接在实验文件中完全自定义。例如,在最小示例中,您可以定义以下直观的函数来读取音频文件
# 2. Define audio pipeline:
@sb.utils.data_pipeline.takes("wav")
@sb.utils.data_pipeline.provides("sig")
def audio_pipeline(wav):
sig = sb.dataio.dataio.read_audio(wav)
return sig
该函数接收wav路径作为输入,并返回使用指定读取器读取的信号。在变量batch.sig中(参见example_asr_ctc_experiment.py),你将拥有准备使用的信号批次。请注意,在这里你可以通过编码所需的管道添加任何类型的处理(例如,添加噪声、语音变化、动态混合等)。
应该为我们的脚本要处理的所有条目编写一个类似的函数。例如,最小的示例也读取一系列音素标签:
@sb.utils.data_pipeline.takes("phn")
@sb.utils.data_pipeline.provides("phn_list", "phn_encoded")
def text_pipeline(phn):
phn_list = phn.strip().split()
yield phn_list
phn_encoded = label_encoder.encode_sequence_torch(phn_list)
yield phn_encoded
在这里,我们读取音素列表,用空格分隔每个条目,并将音素列表转换为它们对应的索引(使用本教程中描述的label_encoder)。
如你所见,我们在主脚本中直接暴露了数据读取管道,因为这增加了许多透明度和灵活性。
自定义前向和成本计算方法
用户通常希望定制的另一件事是从输入到最终成本函数的计算序列。在实验文件中,用户需要在forward和compute_objectives方法中指定它们。
在最小示例中,forward方法定义如下:
def compute_forward(self, batch, stage):
"Given an input batch it computes the output probabilities."
wavs, lens = batch.sig
feats = self.hparams.compute_features(wavs)
feats = self.modules.mean_var_norm(feats, lens)
x = self.modules.model(feats)
x = self.modules.lin(x)
outputs = self.hparams.softmax(x)
输入是变量 batch,它包含数据加载器中指定的所有条目(例如,我们有 batch.sig 和 batch.phn_encoded)。如你所见,我们计算特征,执行均值和方差归一化,并调用模型。最后,应用线性变换 + softmax。
计算目标函数看起来像这样:
def compute_objectives(self, predictions, batch, stage):
"Given the network predictions and targets computed the CTC loss."
predictions, lens = predictions
phns, phn_lens = batch.phn_encoded
loss = self.hparams.compute_cost(predictions, phns, lens, phn_lens)
if stage != sb.Stage.TRAIN:
seq = sb.decoders.ctc_greedy_decode(
predictions, lens, blank_id=self.hparams.blank_index
)
self.per_metrics.append(batch.id, seq, phns, target_len=phn_lens)
return loss
我们利用在前向步骤中完成的预测,并使用batch.phn_encoded中的编码标签计算成本函数。在验证/测试期间,我们还会对语音序列进行实际解码(在这种情况下使用贪心解码器,在更一般的情况下使用束搜索)以监控性能。
大脑类
为了使训练更容易,我们实现了一个简单的训练器,称为Brain类。Brain类定义了一组可定制的例程,这些例程实现了标准训练和验证循环中所需的所有步骤。在定义了数据管道、前向传播、计算目标和其他自定义方法之后,你可以调用brain类的fit方法进行训练(以及eval方法进行测试):
# Trainer initialization
ctc_brain = CTCBrain(hparams["modules"], hparams["opt_class"], hparams)
# Training/validation loop
ctc_brain.fit(
range(hparams["N_epochs"]),
train_data,
valid_data,
train_loader_kwargs=hparams["dataloader_options"],
valid_loader_kwargs=hparams["dataloader_options"],
)
# Evaluation is run separately (now just evaluating on valid data)
ctc_brain.evaluate(valid_data)
如需更详细的描述,请查看Brain类教程这里。
预训练和使用
有时你可能只想使用预训练模型,而不是从头开始训练。例如,你可能想要转录音频文件、计算说话者嵌入、应用语音活动检测器,并在脚本中执行许多其他操作。为了使这更容易,我们在HuggingFace上传了几个模型。这些模型使用推理类来简化推理过程。例如,要使用使用librispeech训练的模型转录音频文件,你可以简单地这样做:
from speechbrain.inference.ASR import EncoderDecoderASR
asr_model = EncoderDecoderASR.from_hparams(source="speechbrain/asr-crdnn-rnnlm-librispeech", savedir="pretrained_models/asr-crdnn-rnnlm-librispeech")
asr_model.transcribe_file('speechbrain/asr-crdnn-rnnlm-librispeech/example.wav')
正如你所见,在这种情况下,说话者所说的文本与音频文件的内容之间存在匹配。 我们有类似的函数用于说话者识别、语音分离和增强。
文件夹组织
主文件夹的组织方式如下:
SpeechBrain 包含了 SpeechBrain 的主要库。你可以在这里找到实现核心功能的 core.py,例如 Brain 类。你还可以在这里找到用于数据加载、解码器、神经网络、信号处理等的库。在 lobe 文件夹下,你可以找到我们认为对语音和音频处理有用的基本功能组合。例如,你可以在这里找到 FBANKs 和 MFCCs 等特征的实现,数据增强函数,以及在配方中经常使用的一些流行神经网络。
Recipes 包含多个语音数据集的训练脚本。例如,你可以找到 LibriSpeech、TIMIT、VoxCeleb、VoiceBank 等的训练脚本。
Samples 是一个用于训练最小示例和执行调试测试的小型语音数据集。
测试 是我们用于调试和持续集成的单元测试和集成测试的集合。
张量格式
SpeechBrain中的所有张量都按照以下约定格式化:
tensor=(batch, time_steps, channels[optional])
批次始终是第一个元素,时间步长始终是第二个元素。其余维度是通道,它们是可选的,并且可以根据需要设置多个。
现在让我们看一些例子。例如,让我们尝试计算输入信号的FBANKS:
import torch
from speechbrain.lobes.features import Fbank
signal = torch.rand([4, 16000]) # [batch, time]
print(signal.shape)
fbank_maker = Fbank()
fbanks = fbank_maker(signal) # [batch, time, features]
print(fbanks.shape)
Fbank 函数期望输入一个格式为 [batch, time] 的信号。它返回格式为 [batch, time, features] 的特征。
现在让我们尝试计算任何音频信号的STFT:
import torch
from speechbrain.dataio.dataio import read_audio
from speechbrain.processing.features import STFT
signal = torch.rand([4, 1600]) # [batch, time]
print(signal.shape)
compute_STFT = STFT(sample_rate=16000, win_length=25, hop_length=10, n_fft=400)
signal_STFT = compute_STFT(signal) #[batch, time, channel1, channel2]
print(signal_STFT.shape)
这里的输出是 [batch, time, channel1, channel2],其中 channel1 是特征轴,channel2 是实部和虚部。
为什么我们需要一个张量格式? 定义张量格式使得模型组合更加容易。有许多可能的格式。对于SpeechBrain,我们选择了这种格式,因为它通常在循环神经网络中使用。
在SpeechBrain中,神经网络的基本构建模块(例如,RNN、CNN、normalization、pooling,…)被设计为支持相同的张量格式,因此可以顺利组合。
为了说服你这一点,让我们尝试使用SpeechBrain结合CNN和RNN:
from speechbrain.nnet.CNN import Conv1d
from speechbrain.nnet.RNN import LSTM
inp_tensor = torch.rand([10, 15, 40])
print(inp_tensor.shape)
# CNN
CNN = Conv1d(input_shape=inp_tensor.shape, out_channels=8, kernel_size=5)
cnn_out = CNN(inp_tensor)
print(cnn_out.shape)
# RNN
RNN = LSTM(input_shape=cnn_out.shape, hidden_size=256, num_layers=1)
rnn_out, _ = RNN(cnn_out)
print(rnn_out.shape)
组合操作无需任何张量重塑(例如,我们不需要转置、压缩、解压缩)。基本的nnet函数是原始PyTorch函数的封装。不同之处在于,我们为您处理了所有烦人的张量重塑操作。这使得代码更清晰、更易于理解。 让我们尝试使用原始的PyTorch进行相同的操作:
import torch
inp_tensor = torch.rand([10, 15, 40])
print(inp_tensor.shape)
# CNN
CNN = torch.nn.Conv1d(in_channels=40, out_channels=8, kernel_size=5)
inp_tensor_tr = inp_tensor.transpose(1,2) # requires (N,C,L)
cnn_out_tr = CNN(inp_tensor_tr)
print(cnn_out_tr.shape)
# RNN
cnn_out_tr2 = cnn_out_tr.transpose(1,2)
RNN = torch.nn.LSTM(input_size=8, hidden_size=256, num_layers=1)
rnn_out, _ = RNN(cnn_out_tr2)
print(rnn_out.shape)
原始的pytorch方法需要两次转置操作,因为CNN和RNN模块使用的张量格式不同。在SpeechBrain中,这是内部管理的,用户不必担心。
引用SpeechBrain
如果您在研究中或业务中使用SpeechBrain,请使用以下BibTeX条目引用它:
@misc{speechbrainV1,
title={Open-Source Conversational AI with {SpeechBrain} 1.0},
author={Mirco Ravanelli and Titouan Parcollet and Adel Moumen and Sylvain de Langen and Cem Subakan and Peter Plantinga and Yingzhi Wang and Pooneh Mousavi and Luca Della Libera and Artem Ploujnikov and Francesco Paissan and Davide Borra and Salah Zaiem and Zeyu Zhao and Shucong Zhang and Georgios Karakasidis and Sung-Lin Yeh and Pierre Champion and Aku Rouhe and Rudolf Braun and Florian Mai and Juan Zuluaga-Gomez and Seyed Mahed Mousavi and Andreas Nautsch and Xuechen Liu and Sangeet Sagar and Jarod Duret and Salima Mdhaffar and Gaelle Laperriere and Mickael Rouvier and Renato De Mori and Yannick Esteve},
year={2024},
eprint={2407.00463},
archivePrefix={arXiv},
primaryClass={cs.LG},
url={https://arxiv.org/abs/2407.00463},
}
@misc{speechbrain,
title={{SpeechBrain}: A General-Purpose Speech Toolkit},
author={Mirco Ravanelli and Titouan Parcollet and Peter Plantinga and Aku Rouhe and Samuele Cornell and Loren Lugosch and Cem Subakan and Nauman Dawalatabad and Abdelwahab Heba and Jianyuan Zhong and Ju-Chieh Chou and Sung-Lin Yeh and Szu-Wei Fu and Chien-Feng Liao and Elena Rastorgueva and François Grondin and William Aris and Hwidong Na and Yan Gao and Renato De Mori and Yoshua Bengio},
year={2021},
eprint={2106.04624},
archivePrefix={arXiv},
primaryClass={eess.AS},
note={arXiv:2106.04624}
}