pytorch-kaldi
pytorch-kaldi 是一个专为构建顶尖语音识别系统而设计的开源工具包。它巧妙地将 PyTorch 在深度神经网络(DNN/RNN)训练上的灵活性与 Kaldi toolkit 在特征提取、标签计算及解码方面的成熟能力相结合,形成了一套高效的混合架构。
这一设计主要解决了传统语音识别开发中面临的痛点:研究人员既希望利用现代深度学习框架快速实验新模型,又难以舍弃 Kaldi 在信号处理和解码流程中经过工业验证的稳定性。通过分工协作,pytorch-kaldi 让用户无需重复造轮子,即可专注于核心算法的创新与调优。
该工具特别适合语音技术领域的研究人员和开发者使用,尤其是那些需要复现前沿论文成果、进行 DNN-HMM 混合系统实验,或希望在标准基准上验证自定义模型的团队。其独特的技术亮点在于清晰的模块化配置,支持用户轻松插入自定义模型、调整超参数或使用私有数据集,同时保持了极高的结果可复现性。
值得注意的是,虽然该项目目前仍提供维护支持,但其核心开发团队已推出功能更全面的继任者 SpeechBrain,涵盖了从语音识别到说话人确认等更多任务。对于新项目,建议关注 SpeechBrain;而对于需要经典混合架构的研究场景,pytorch-kaldi 依然是一个可靠且广泛引用的选择。
使用场景
某语音识别初创团队正致力于为医疗行业开发高精度的医生问诊录音转写系统,需要在快速迭代深度学习模型的同时,确保解码流程符合工业级标准。
没有 pytorch-kaldi 时
- 框架割裂严重:研究人员习惯用 PyTorch 构建灵活的 DNN/RNN 模型,但工程团队依赖 Kaldi 进行特征提取和解码,两边代码无法直接互通,需编写大量繁琐的中间接口脚本。
- 实验复现困难:每次调整网络结构(如从 CNN 改为 RNN),都需要手动重新对接数据流,导致实验周期长达数周,且容易因格式转换错误引入难以排查的 Bug。
- 性能瓶颈明显:由于缺乏统一的混合架构支持,难以利用 Kaldi 成熟的 HMM-GMM 对齐优势来辅助深度神经网络训练,最终模型的词错率(WER)始终无法突破行业基准。
使用 pytorch-kaldi 后
- 无缝混合架构:pytorch-kaldi 原生实现了"PyTorch 负责模型训练 + Kaldi 负责特征与解码”的分工,团队可直接将最新的 PyTorch 模型嵌入成熟的 Kaldi 工作流中,无需重复造轮子。
- 研发效率倍增:通过简单的配置文件即可切换不同的神经网络结构,原本需要两周的模型适配工作缩短至几天,让算法工程师能专注于优化网络本身而非数据管道。
- 精度显著提升:借助工具对 DNN/HMM 混合系统的深度优化,团队成功融合了 Kaldi 强大的时序建模能力与 PyTorch 的灵活表达力,在医疗垂直数据集上将识别准确率提升了 15%。
pytorch-kaldi 通过打破两大顶级框架的壁垒,让研发团队能以最低成本构建出兼具灵活性与工业级精度的语音识别系统。
运行环境要求
- Linux
必需 NVIDIA GPU,具体型号未说明,支持 CUDA 8.0, 9.0, 9.1
未说明

快速开始
PyTorch-Kaldi 语音识别工具包
PyTorch-Kaldi 是一个用于开发最先进 DNN/HMM 语音识别系统的开源仓库。其中,DNN 部分由 PyTorch 管理,而特征提取、标签计算和解码则使用 Kaldi 工具包完成。
本仓库包含 PyTorch-Kaldi 工具包的最新版本(PyTorch-Kaldi-v1.0)。如需查看上一版本(PyTorch-Kaldi-v0.1),请点击此处。
如果您使用了此代码或其部分内容,请引用以下论文:
M. Ravanelli, T. Parcollet, Y. Bengio, “The PyTorch-Kaldi Speech Recognition Toolkit”, arXiv
@inproceedings{pytorch-kaldi,
title = {The PyTorch-Kaldi Speech Recognition Toolkit},
author = {M. Ravanelli and T. Parcollet and Y. Bengio},
booktitle = {In Proc. of ICASSP},
year = {2019}
}
该工具包采用 知识共享署名 4.0 国际许可协议 发布。您可以出于研究、商业及非商业目的复制、分发或修改代码。我们仅要求您引用上述论文。
为提高语音识别结果的透明度和可复现性,我们允许用户在此仓库中发布其 PyTorch-Kaldi 模型。如有意发布,请随时与我们联系(或提交拉取请求)。此外,若您的论文使用了 PyTorch-Kaldi,也可在本仓库中进行宣传。
SpeechBrain
我们很高兴地宣布,SpeechBrain 项目(https://speechbrain.github.io/)现已公开!我们强烈建议用户迁移到 Speechbrain。这是一个更优秀的项目,已支持多种语音处理任务,如语音识别、说话人识别、SLU、语音增强、语音分离、多麦克风信号处理等。
我们的目标是开发一个 单一、灵活且 用户友好 的工具包,可用于轻松构建最先进的语音系统,涵盖端到端和 HMM-DNN 语音识别、说话人识别、语音分离、多麦克风信号处理(如波束成形)、自监督学习等多种任务。
该项目由 Mila 主导,并得到三星、Nvidia 和杜比的支持。SpeechBrain 还将受益于 Facebook/PyTorch、IBMResearch 和 FluentAI 等公司的合作与专业知识。
我们正在积极寻找合作伙伴。如果您有意合作,请随时通过 speechbrainproject@gmail.com 与我们联系。
得益于赞助商的支持,我们还能够招聘在 Mila 从事 SpeechBrain 项目的实习生。理想的候选人应为具有 PyTorch 和语音技术经验的博士生(请将简历发送至 speechbrainproject@gmail.com)。
SpeechBrain 的开发还需要几个月时间才能形成可用的仓库。在此期间,我们将继续为 PyTorch-Kaldi 项目提供支持。
敬请期待!
目录
简介
PyTorch-Kaldi 项目旨在弥合 Kaldi 和 PyTorch 工具包之间的差距,同时继承 Kaldi 的高效性和 PyTorch 的灵活性。PyTorch-Kaldi 不仅仅是一个简单的接口,它还内置了多项实用功能,用于开发现代语音识别器。例如,代码专门设计为可自然地插入用户自定义的声学模型。作为替代方案,用户也可以利用多个预置的神经网络,并通过直观的配置文件进行定制。PyTorch-Kaldi 支持多路特征和标签流,以及神经网络的组合,从而实现复杂的神经架构。该工具包随丰富的文档一起公开发布,专为本地环境或高性能计算集群运行而设计。
新版 PyTorch-Kaldi 工具包的一些特性:
- 与 Kaldi 的易用接口。
- 易于插入用户自定义模型。
- 多个预置模型(MLP、CNN、RNN、LSTM、GRU、Li-GRU、SincNet)。
- 基于多路特征、标签和复杂神经架构的自然实现。
- 简单灵活的配置文件。
- 自动从上次处理的片段恢复。
- 自动对输入特征进行分块和上下文扩展。
- 多 GPU 训练。
- 适用于本地环境或 HPC 集群。
- 提供 TIMIT 和 Librispeech 数据集的教程。
前置条件
- 如果尚未完成,请安装 Kaldi(http://kaldi-asr.org/)。按照安装说明,别忘了将 Kaldi 二进制文件的路径添加到 $HOME/.bashrc 中。例如,确保 .bashrc 包含以下路径:
export KALDI_ROOT=/home/mirco/kaldi-trunk
PATH=$PATH:$KALDI_ROOT/tools/openfst
PATH=$PATH:$KALDI_ROOT/src/featbin
PATH=$PATH:$KALDI_ROOT/src/gmmbin
PATH=$PATH:$KALDI_ROOT/src/bin
PATH=$PATH:$KALDI_ROOT//src/nnetbin
export PATH
请记得将 KALDI_ROOT 变量替换为您自己的路径。作为首次测试以检查安装是否成功,请打开一个 bash 终端,输入“copy-feats”或“hmm-info”,并确保没有出现任何错误。
如果尚未完成,请安装 PyTorch(http://pytorch.org/)。我们已在 PyTorch 1.0 和 PyTorch 0.4 上测试过我们的代码。使用较旧版本的 PyTorch 很可能会引发错误。要检查您的安装情况,输入“python”,进入控制台后输入“import torch”,并确保没有出现任何错误。
我们建议在配备 GPU 的机器上运行代码。请确保已安装并正确配置 CUDA 库(https://developer.nvidia.com/cuda-downloads)。我们已在 CUDA 9.0、9.1 和 8.0 上测试过我们的系统。请确认 Python 已安装(代码已在 Python 2.7 和 Python 3.7 上测试过)。虽然不是强制要求,但我们建议使用 Anaconda(https://anaconda.org/anaconda/python)。
最新更新
2019年2月19日:更新内容:
- 现在可以在训练过程中动态调整批量大小、学习率和 dropout 概率。为此,我们在配置文件中实现了一个调度器,支持以下格式:
batch_size_train = 128*12 | 64*10 | 32*2
上述语句表示:先用 128 个批次训练 12 个 epoch,再用 64 个批次训练 10 个 epoch,最后用 32 个批次训练 2 个 epoch。类似的方式也可用于学习率和 dropout 的调度。更多信息请参见本节。
2019年2月5日:更新内容:
- 我们的工具包现在支持并行数据加载(即在处理当前数据块的同时,将下一个数据块加载到内存中),从而显著提升速度。
- 在进行单音素正则化时,用户现在可以设置“dnn_lay = N_lab_out_mono”。这样,单音素的数量将由我们的工具包自动推断出来。
- 我们将 kaldi-io-for-python 项目的 kaldi-io 工具包集成到了 data_io-py 中。
- 我们为 SincNet 提供了更优的超参数设置(参见本节)。
- 我们发布了基于 DIRHA 数据集的一些基准模型(参见本节)。此外,我们还提供了一些简单自编码器的配置示例(参见本节)以及联合训练语音增强和语音识别模块的系统配置示例(参见本节)。
- 我们修复了一些小 bug。
关于下一版本的说明: 在下一版本中,我们计划进一步扩展工具包的功能,支持更多模型和特征格式。目标是使我们的工具包适用于其他语音相关任务,如端到端语音识别、说话人辨识、关键词检测、语音分离、语音活动检测、语音增强等。如果您希望提出一些新颖的功能,请通过填写这份问卷向我们反馈(https://docs.google.com/forms/d/12jd-QP5m8NAJVpiypvtVGy1n_d2iuWaLozXq5hsg4yA/edit?usp=sharing)。
安装方法
要安装 PyTorch-Kaldi,请按照以下步骤操作:
- 确保“前置条件”部分中推荐的所有软件均已安装且正常工作。
- 克隆 PyTorch-Kaldi 仓库:
git clone https://github.com/mravanelli/pytorch-kaldi
- 进入项目文件夹,并使用以下命令安装所需的依赖包:
pip install -r requirements.txt
TIMIT 教程
以下我们将基于流行的 TIMIT 数据集,提供一份 PyTorch-Kaldi 工具包的简短教程。
确保您已拥有 TIMIT 数据集。如果没有,可以从 LDC 网站下载(https://catalog.ldc.upenn.edu/LDC93S1)。
确保 Kaldi 和 PyTorch 的安装均无误。同时,请确认您的 KALDI 路径当前可用(请按照“前置条件”部分中的说明将 Kaldi 路径添加到 .bashrc 文件中)。例如,输入“copy-feats”和“hmm-info”,并确保没有出现任何错误。
运行 Kaldi 的 TIMIT s5 基准流程。此步骤对于计算后续用于训练 PyTorch 神经网络的特征和标签至关重要。我们建议运行完整的 timit s5 流程(包括 DNN 训练):
cd kaldi/egs/timit/s5
./run.sh
./local/nnet/run_dnn.sh
这样会生成所有必要的文件,用户可以直接比较 Kaldi 的结果与我们工具包的结果。
- 使用以下命令为测试和开发数据计算对齐信息(即音素状态标签)(请进入 $KALDI_ROOT/egs/timit/s5 目录)。如果要使用 tri3 对齐信息,输入:
steps/align_fmllr.sh --nj 4 data/dev data/lang exp/tri3 exp/tri3_ali_dev
steps/align_fmllr.sh --nj 4 data/test data/lang exp/tri3 exp/tri3_ali_test
如果要使用 dnn 对齐信息(推荐方式),输入:
steps/nnet/align.sh --nj 4 data-fmllr-tri3/train data/lang exp/dnn4_pretrain-dbn_dnn exp/dnn4_pretrain-dbn_dnn_ali
steps/nnet/align.sh --nj 4 data-fmllr-tri3/dev data/lang exp/dnn4_pretrain-dbn_dnn exp/dnn4_pretrain-dbn_dnn_ali_dev
steps/nnet/align.sh --nj 4 data-fmllr-tri3/test data/lang exp/dnn4_pretrain-dbn_dnn exp/dnn4_pretrain-dbn_dnn_ali_test
本教程从一个基于 mfcc 特征的简单 MLP 网络开始。在启动实验之前,请查看配置文件 cfg/TIMIT_baselines/TIMIT_MLP_mfcc_basic.cfg。有关其所有字段的详细说明,请参阅配置文件说明。
根据您的实际路径修改配置文件。具体来说:
- 将“fea_lst”设置为您 mfcc 训练列表的路径(该列表应位于 $KALDI_ROOT/egs/timit/s5/data/train/feats.scp 中)。
- 将您的路径(例如 $KALDI_ROOT/egs/timit/s5/data/train/utt2spk)添加到“--utt2spk=ark:”中。
- 添加您的 CMVN 变换文件路径,例如 $KALDI_ROOT/egs/timit/s5/mfcc/cmvn_train.ark。
- 添加存储标签的文件夹路径(例如 $KALDI_ROOT/egs/timit/s5/exp/dnn4_pretrain-dbn_dnn_ali 用于训练数据,$KALDI_ROOT/egs/timit/s5/exp/dnn4_pretrain-dbn_dnn_ali_dev 用于开发数据)。
为避免错误,请确保配置文件中的所有路径都存在。请勿使用包含 bash 变量的路径,因为这些路径会被原样读取,而不会自动展开(例如,应使用 /home/mirco/kaldi-trunk/egs/timit/s5/exp/dnn4_pretrain-dbn_dnn_ali,而不是 $KALDI_ROOT/egs/timit/s5/exp/dnn4_pretrain-dbn_dnn_ali)。
- 运行 ASR 实验:
python run_exp.py cfg/TIMIT_baselines/TIMIT_MLP_mfcc_basic.cfg
该脚本会启动一个完整的 ASR 实验,依次执行训练、验证、前向传播和解码步骤。进度条会显示上述各个阶段的进展。脚本 run_exp.py 会在输出目录中逐步生成以下文件:
- res.res:总结不同验证轮次下的训练和验证性能。
- log.log:记录可能的错误和警告信息。
- conf.cfg:配置文件的副本。
- model.svg:展示所用模型结构及各神经网络连接方式的图片。对于比当前模型更复杂的架构(例如基于多个神经网络的模型),此图非常有助于调试。
- 文件夹 exp_files 包含多个文件,用于总结各轮次训练和验证的进展。例如,.info 文件报告每个批次的损失、误差及训练时间等信息;.cfg 文件是对应批次的配置文件(详见整体架构);而 .lst 文件则列出用于训练该批次的具体特征列表。
- 训练结束后,会生成一个名为 generated outputs 的目录,其中包含各训练轮次的损失与误差曲线图。
请注意,您可以随时停止实验。 如果再次运行该脚本,它将自动从上次正确处理的批次继续执行。训练时间可能需要几小时,具体取决于可用 GPU 的性能。另外,如果您希望修改配置文件中的某些参数(如 n_chunks=、fea_lst=、batch_size_train= 等),则必须指定不同的输出目录(output_folder=)。
调试提示: 如果遇到错误,建议按以下步骤排查:
检查标准输出。
若无帮助,请查看 log.log 文件。
检查 core.py 库中的 run_nn 函数,在函数的不同部分添加打印语句,以定位问题并找出原因。
训练结束后,电话错误率 (PER%) 会被追加到 res.res 文件中。要查看解码结果的更多细节,可以进入输出目录中的 “decoding_test” 文件夹,查看生成的各种文件。对于本示例,我们得到了如下 res.res 文件:
ep=000 tr=['TIMIT_tr'] loss=3.398 err=0.721 valid=TIMIT_dev loss=2.268 err=0.591 lr_architecture1=0.080000 time(s)=86
ep=001 tr=['TIMIT_tr'] loss=2.137 err=0.570 valid=TIMIT_dev loss=1.990 err=0.541 lr_architecture1=0.080000 time(s)=87
ep=002 tr=['TIMIT_tr'] loss=1.896 err=0.524 valid=TIMIT_dev loss=1.874 err=0.516 lr_architecture1=0.080000 time(s)=87
ep=003 tr=['TIMIT_tr'] loss=1.751 err=0.494 valid=TIMIT_dev loss=1.819 err=0.504 lr_architecture1=0.080000 time(s)=88
ep=004 tr=['TIMIT_tr'] loss=1.645 err=0.472 valid=TIMIT_dev loss=1.775 err=0.494 lr_architecture1=0.080000 time(s)=89
ep=005 tr=['TIMIT_tr'] loss=1.560 err=0.453 valid=TIMIT_dev loss=1.773 err=0.493 lr_architecture1=0.080000 time(s)=88
.........
ep=020 tr=['TIMIT_tr'] loss=0.968 err=0.304 valid=TIMIT_dev loss=1.648 err=0.446 lr_architecture1=0.002500 time(s)=89
ep=021 tr=['TIMIT_tr'] loss=0.965 err=0.304 valid=TIMIT_dev loss=1.649 err=0.446 lr_architecture1=0.002500 time(s)=90
ep=022 tr=['TIMIT_tr'] loss=0.960 err=0.302 valid=TIMIT_dev loss=1.652 err=0.447 lr_architecture1=0.001250 time(s)=88
ep=023 tr=['TIMIT_tr'] loss=0.959 err=0.301 valid=TIMIT_dev loss=1.651 err=0.446 lr_architecture1=0.000625 time(s)=88
%WER 18.1 | 192 7215 | 84.0 11.9 4.2 2.1 18.1 99.5 | -0.583 | /home/mirco/pytorch-kaldi-new/exp/TIMIT_MLP_basic5/decode_TIMIT_test_out_dnn1/score_6/ctm_39phn.filt.sys
最终获得的 PER(%) 为 18.1%。需要注意的是,由于不同机器上的随机初始化差异,结果可能会有所波动。我们认为,对不同随机种子下得到的性能进行平均(即更改配置文件中的 seed 字段)对于 TIMIT 数据集至关重要,因为自然的性能波动可能会掩盖实验结果。我们在 TIMIT 实验中观察到约 0.2% 的标准偏差。
如果想要更换特征,首先需要用 Kaldi 工具包计算这些特征。要计算 fbank 特征,需打开 $KALDI_ROOT/egs/timit/s5/run.sh,并使用以下命令进行计算:
feadir=fbank
for x in train dev test; do
steps/make_fbank.sh --cmd "$train_cmd" --nj $feats_nj data/$x exp/make_fbank/$x $feadir
steps/compute_cmvn_stats.sh data/$x exp/make_fbank/$x $feadir
done
然后,将上述配置文件更新为新的特征列表。 如果您已经运行过完整的 TIMIT Kaldi 流程,可以直接在 $KALDI_ROOT/egs/timit/s5/data-fmllr-tri3 中找到 fmllr 特征。 若将这些特征输入神经网络,由于采用了说话人自适应技术,预计性能会有显著提升。
在 TIMIT_baseline 文件夹中,我们还提供了其他几种可能的 TIMIT 基线示例。与前面的例子类似,您只需输入以下命令即可运行:
python run_exp.py $cfg_file
其中包含一些基于循环神经网络(TIMIT_RNN*、TIMIT_LSTM*、TIMIT_GRU*、TIMIT_LiGRU*)和 CNN 架构(TIMIT_CNN*)的示例。此外,我们还提出了一种更高级的模型(TIMIT_DNN_liGRU_DNN_mfcc+fbank+fmllr.cfg),该模型结合了前馈神经网络和循环神经网络,并使用 mfcc、fbank 和 fmllr 特征的拼接作为输入。请注意,后一种配置文件对应于参考论文中描述的最佳架构。从上述配置文件可以看出,我们通过引入单音素正则化等技巧来提升 ASR 性能(即同时估计上下文相关和上下文无关的目标)。下表报告了运行这些系统后得到的平均 PER% 结果:
| 模型 | mfcc | fbank | fMLLR |
|---|---|---|---|
| Kaldi DNN 基线 | ----- | ------ | 18.5 |
| MLP | 18.2 | 18.7 | 16.7 |
| RNN | 17.7 | 17.2 | 15.9 |
| SRU | ----- | 16.6 | ----- |
| LSTM | 15.1 | 14.3 | 14.5 |
| GRU | 16.0 | 15.2 | 14.9 |
| Li-GRU | 15.5 | 14.9 | 14.2 |
结果显示,正如预期,fMLLR 特征由于其说话人自适应特性,性能明显优于 MFCC 和 Fbank 特征。循环神经网络模型的表现显著优于传统的 MLP 模型,尤其是在使用 LSTM、GRU 和 Li-GRU 架构时,这些架构通过乘性门控机制有效缓解了梯度消失问题。最佳结果 PER=14.2% 是由 Li-GRU 模型 [2,3] 实现的,该模型仅使用一个门控单元,因此相比标准 GRU 节省了 33% 的计算量。
实际上,最佳结果是通过一种更复杂的架构获得的,该架构结合了MFCC、FBANK和fMLLR特征(参见cfg/TIMI_baselines/TIMIT_mfcc_fbank_fmllr_liGRU_best.cfg)。据我们所知,后一种系统达到的**PER=13.8%**是在TIMIT测试集上已发表的最佳性能。
简单循环单元(SRU)是一种高效且高度可并行化的循环模型。其在自动语音识别任务上的表现不如标准的LSTM、GRU和Li-GRU模型,但速度显著更快。SRU已在这里实现,并在以下论文中进行了描述:
T. Lei, Y. Zhang, S. I. Wang, H. Dai, Y. Artzi, “用于高度可并行化循环的简单循环单元”,EMNLP 2018会议论文。arXiv
要使用该模型进行实验,请使用配置文件cfg/TIMIT_baselines/TIMIT_SRU_fbank.cfg。在此之前,您需要通过pip install sru安装该模型,并在neural_networks.py中取消注释“import sru”。
您可以通过访问这里直接将您的结果与我们的结果进行比较。在这个外部仓库中,您可以找到所有包含生成文件的文件夹。
Librispeech教程
在Librispeech数据集上运行PyTorch-Kaldi的步骤与上述TIMIT的步骤类似。以下教程基于100小时子集,但可以轻松扩展到完整数据集(960小时)。
- 运行Kaldi的Librispeech配方,至少执行到第13阶段(含)。
- 将exp/tri4b/trans.*文件复制到exp/tri4b/decode_tgsmall_train_clean_100/:
mkdir exp/tri4b/decode_tgsmall_train_clean_100 && cp exp/tri4b/trans.* exp/tri4b/decode_tgsmall_train_clean_100/
- 通过运行以下脚本计算fmllr特征:
. ./cmd.sh ## 您可能需要将cmd.sh修改为适合您系统的设置。
. ./path.sh ## 导入tools/utils(导入queue.pl)
gmmdir=exp/tri4b
for chunk in train_clean_100 dev_clean test_clean; do
dir=fmllr/$chunk
steps/nnet/make_fmllr_feats.sh --nj 10 --cmd "$train_cmd" \
--transform-dir $gmmdir/decode_tgsmall_$chunk \
$dir data/$chunk $gmmdir $dir/log $dir/data || exit 1
compute-cmvn-stats --spk2utt=ark:data/$chunk/spk2utt scp:fmllr/$chunk/feats.scp ark:$dir/data/cmvn_speaker.ark
done
- 使用以下命令计算对齐信息:
# 对dev_clean和test_clean的对齐
steps/align_fmllr.sh --nj 30 data/train_clean_100 data/lang exp/tri4b exp/tri4b_ali_clean_100
steps/align_fmllr.sh --nj 10 data/dev_clean data/lang exp/tri4b exp/tri4b_ali_dev_clean_100
steps/align_fmllr.sh --nj 10 data/test_clean data/lang exp/tri4b exp/tri4b_ali_test_clean_100
- 使用以下命令运行实验:
python run_exp.py cfg/Librispeech_baselines/libri_MLP_fmllr.cfg
如果您想使用循环模型,可以使用libri_RNN_fmllr.cfg、libri_LSTM_fmllr.cfg、libri_GRU_fmllr.cfg或libri_liGRU_fmllr.cfg。训练循环模型可能需要几天时间(取决于所使用的GPU)。使用tgsmall图得到的性能如表所示:
| 模型 | WER% |
|---|---|
| MLP | 9.6 |
| LSTM | 8.6 |
| GRU | 8.6 |
| li-GRU | 8.6 |
这些结果是在未添加音素网格重打分的情况下获得的(即仅使用tgsmall图)。您可以通过以下方式添加音素网格重打分来提高性能(从PyTorch-Kaldi的kaldi_decoding_script文件夹中运行):
data_dir=/data/milatmp1/ravanelm/librispeech/s5/data/
dec_dir=/u/ravanelm/pytorch-Kaldi-new/exp/libri_fmllr/decode_test_clean_out_dnn1/
out_dir=/u/ravanelm/pytorch-kaldi-new/exp/libri_fmllr/
steps/lmrescore_const_arpa.sh $data_dir/lang_test_{tgsmall,fglarge} \
$data_dir/test_clean $dec_dir $out_dir/decode_test_clean_fglarge || exit 1;
使用重打分(fglarge)得到的最终结果如下表所示:
| 模型 | WER% |
|---|---|
| MLP | 6.5 |
| LSTM | 6.4 |
| GRU | 6.3 |
| li-GRU | 6.2 |
您可以在此处查看获得的结果:bitbucket.org/mravanelli/pytorch-kaldi-exp-librispeech。
工具包架构概述
运行ASR实验的主要脚本是run_exp.py。该Python脚本执行训练、验证、前向传播和解码步骤。训练过程会经历多个epoch,逐步处理所有训练数据,并应用所选的神经网络。 每个训练epoch结束后,都会进行验证步骤,以监控系统在保留数据上的性能。训练结束后,通过计算指定测试数据集的后验概率来进行前向传播阶段。这些后验概率会根据先验概率(使用计数文件)进行归一化,并存储到一个ark文件中。随后进行解码步骤,以获取测试句子中说话者所说的最终词序列。
run_exp.py脚本会接收一个全局配置文件(例如cfg/TIMIT_MLP_mfcc.cfg),该文件指定了运行完整实验所需的所有选项。run_exp.py代码会调用另一个函数run_nn(见core.py库),该函数会对每一块数据执行训练、验证和前向传播操作。 run_nn函数会接收一个特定于数据块的配置文件(例如exp/TIMIT_MLP_mfcc/exp_files/train_TIMIT_tr+TIMIT_dev_ep000_ck00.cfg*),该文件指定了运行单个数据块实验所需的所有参数。run_nn函数会输出一些信息文件(例如exp/TIMIT_MLP_mfcc/exp_files/train_TIMIT_tr+TIMIT_dev_ep000_ck00.info),总结所处理数据块的损失和错误。
结果会被汇总到res.res文件中,而错误和警告则会被重定向到log.log文件中。
配置文件说明:
配置文件分为两种类型:全局配置文件和特定于数据块的配置文件。它们都采用INI格式,通过Python的configparser库进行读取、处理和修改。 全局配置文件包含多个部分,指定了语音识别实验的所有主要步骤(训练、验证、前向传播和解码)。 配置文件的结构在一个原型文件中进行了描述(例如proto/global.proto),该文件不仅列出了所有必需的部分和字段,还指定了每个字段的类型。例如,N_ep=int(1,inf)表示N_ep字段(即训练epoch数)必须是一个从1到无穷大的整数。同样,*lr=float(0,inf)*表示lr字段(即学习率)必须是一个从0到无穷大的浮点数。任何不符合这些规范的配置文件写入尝试都会引发错误。
现在让我们打开一个配置文件(例如cfg/TIMIT_baselines/TIMIT_MLP_mfcc_basic.cfg),并描述其中的主要部分:
[cfg_proto]
cfg_proto = proto/global.proto
cfg_proto_chunk = proto/global_chunk.proto
当前版本的配置文件首先在 [cfg_proto] 部分中指定了全局和分块专用原型文件的路径。
[exp]
cmd =
run_nn_script = run_nn
out_folder = exp/TIMIT_MLP_basic5
seed = 1234
use_cuda = True
multi_gpu = False
save_gpumem = False
n_epochs_tr = 24
[exp] 部分包含一些重要字段,例如输出文件夹(out_folder)以及分块处理脚本 run_nn 的路径(默认情况下,该函数应在 core.py 库中实现)。字段 N_epochs_tr 指定了所选的训练轮数。其他选项如 use_cuda、multi_gpu 和 save_gpumem 可由用户启用。字段 cmd 可用于附加命令,以便在 HPC 集群上运行脚本。
[dataset1]
data_name = TIMIT_tr
fea = fea_name=mfcc
fea_lst=quick_test/data/train/feats_mfcc.scp
fea_opts=apply-cmvn --utt2spk=ark:quick_test/data/train/utt2spk ark:quick_test/mfcc/train_cmvn_speaker.ark ark:- ark:- | add-deltas --delta-order=2 ark:- ark:- |
cw_left=5
cw_right=5
lab = lab_name=lab_cd
lab_folder=quick_test/dnn4_pretrain-dbn_dnn_ali
lab_opts=ali-to-pdf
lab_count_file=auto
lab_data_folder=quick_test/data/train/
lab_graph=quick_test/graph
n_chunks = 5
[dataset2]
data_name = TIMIT_dev
fea = fea_name=mfcc
fea_lst=quick_test/data/dev/feats_mfcc.scp
fea_opts=apply-cmvn --utt2spk=ark:quick_test/data/dev/utt2spk ark:quick_test/mfcc/dev_cmvn_speaker.ark ark:- ark:- | add-deltas --delta-order=2 ark:- ark:- |
cw_left=5
cw_right=5
lab = lab_name=lab_cd
lab_folder=quick_test/dnn4_pretrain-dbn_dnn_ali_dev
lab_opts=ali-to-pdf
lab_count_file=auto
lab_data_folder=quick_test/data/dev/
lab_graph=quick_test/graph
n_chunks = 1
[dataset3]
data_name = TIMIT_test
fea = fea_name=mfcc
fea_lst=quick_test/data/test/feats_mfcc.scp
fea_opts=apply-cmvn --utt2spk=ark:quick_test/data/test/utt2spk ark:quick_test/mfcc/test_cmvn_speaker.ark ark:- ark:- | add-deltas --delta-order=2 ark:- ark:- |
cw_left=5
cw_right=5
lab = lab_name=lab_cd
lab_folder=quick_test/dnn4_pretrain-dbn_dnn_ali_test
lab_opts=ali-to-pdf
lab_count_file=auto
lab_data_folder=quick_test/data/test/
lab_graph=quick_test/graph
n_chunks = 1
配置文件包含多个部分([dataset1]、[dataset2]、[dataset3] 等),用于描述 ASR 实验中使用的所有语料库。[dataset*] 部分中的字段描述了实验中考虑的所有特征和标签。 例如,特征是在 fea: 字段中指定的,其中 fea_name 包含特征的名称,fea_lst 是特征列表(以 Kaldi 的 scp 格式表示),fea_opts 允许用户指定如何处理这些特征(例如进行 CMVN 或添加导数),而 cw_left 和 cw_right 则设置了上下文窗口的特性(即要附加的左右帧数)。需要注意的是,当前版本的 PyTorch-Kaldi 工具包支持定义多个特征流。事实上,如 cfg/TIMIT_baselines/TIMIT_mfcc_fbank_fmllr_liGRU_best.cfg 所示,可以采用多种特征流(例如 mfcc、fbank、fmllr)。
同样地,lab 部分也包含一些子字段。例如,lab_name 指的是标签的名称,而 lab_folder 则包含了存储由 Kaldi 配方生成的对齐结果的文件夹。lab_opts 允许用户指定与所考虑对齐相关的选项。例如,lab_opts="ali-to-pdf" 会提取标准的上下文相关音素状态标签,而 lab_opts=ali-to-phones --per-frame=true 则可用于提取单音素目标。lab_count_file 用于指定包含所考虑音素状态计数的文件。 这些计数在前向传播阶段非常重要,在该阶段神经网络计算出的后验概率会除以其先验概率。PyTorch-Kaldi 允许用户指定外部计数文件,也可以自动获取(使用 lab_count_file=auto)。如果不需要严格使用计数文件,例如当标签对应于不用于生成前向传播中使用的后验概率的输出时(参见 cfg/TIMIT_baselines/TIMIT_MLP_mfcc.cfg 中的单音素目标),用户还可以指定 lab_count_file=none。而 lab_data_folder 则对应于 Kaldi 数据准备过程中创建的数据文件夹,其中包含若干文件,包括最终 WER 计算所用的文本文件。最后一个子字段 lab_graph 是用于生成标签的 Kaldi 图的路径。
完整的数据集通常较大,无法完全加载到 GPU 或内存中,因此需要将其拆分为多个分块。PyTorch-Kaldi 会自动将数据集拆分为 N_chunks 中指定的分块数量。分块的数量可能取决于具体的数据集。一般来说,我们建议将语音分块处理为约 1 至 2 小时的长度(具体取决于可用内存)。
[data_use]
train_with = TIMIT_tr
valid_with = TIMIT_dev
forward_with = TIMIT_test
这一部分说明了 [datasets*] 部分中列出的数据如何在 run_exp.py 脚本中被使用。 第一行表示我们将使用名为 TIMIT_tr 的数据进行训练。请注意,此数据集名称必须出现在其中一个数据集部分中,否则配置解析器将报错。类似地,第二行和第三行分别指定了用于验证和前向传播阶段的数据。
[batches]
batch_size_train = 128
max_seq_length_train = 1000
increase_seq_length_train = False
start_seq_len_train = 100
multply_factor_seq_len_train = 2
batch_size_valid = 128
max_seq_length_valid = 1000
batch_size_train 用于定义小批量中的训练样本数量。字段 max_seq_length_train 会截断超过指定值的句子。在对非常长的句子训练循环模型时,可能会出现内存不足的问题。通过此选项,我们可以允许用户通过截断长句子来缓解此类内存问题。此外,还可以通过设置 increase_seq_length_train=True 来逐步增加训练过程中的最大句子长度。如果启用此选项,训练将从 start_seq_len_train 中指定的最大句子长度开始(例如 start_seq_len_train=100)。每完成一个 epoch,最大句子长度就会乘以 multply_factor_seq_len_train(例如 multply_factor_seq_len_train=2)。 我们观察到,这种简单的策略通常能够提升系统性能,因为它鼓励模型首先关注短期依赖关系,而在后期再学习长期依赖关系。
同样地,batch_size_valid 和 max_seq_length_valid 分别指定了验证数据集的小批量样本数量以及最大序列长度。
[architecture1]
arch_name = MLP_layers1
arch_proto = proto/MLP.proto
arch_library = neural_networks
arch_class = MLP
arch_pretrain_file = none
arch_freeze = False
arch_seq_model = False
dnn_lay = 1024,1024,1024,1024,N_out_lab_cd
dnn_drop = 0.15,0.15,0.15,0.15,0.0
dnn_use_laynorm_inp = False
dnn_use_batchnorm_inp = False
dnn_use_batchnorm = True,True,True,True,False
dnn_use_laynorm = False,False,False,False,False
dnn_act = relu,relu,relu,relu,softmax
arch_lr = 0.08
arch_halving_factor = 0.5
arch_improvement_threshold = 0.001
arch_opt = sgd
opt_momentum = 0.0
opt_weight_decay = 0.0
opt_dampening = 0.0
opt_nesterov = False
[architecture*] 部分用于指定 ASR 实验中所涉及的神经网络架构。字段 arch_name 指定架构名称。由于不同的神经网络可能依赖于一组不同的超参数,用户需要在 proto 字段中添加包含这些超参数列表的 proto 文件路径。例如,标准 MLP 模型的原型文件包含以下字段:
[proto]
library=path
class=MLP
dnn_lay=str_list
dnn_drop=float_list(0.0,1.0)
dnn_use_laynorm_inp=bool
dnn_use_batchnorm_inp=bool
dnn_use_batchnorm=bool_list
dnn_use_laynorm=bool_list
dnn_act=str_list
与其他原型文件类似,每一行定义了一个超参数及其对应的值类型。所有在 proto 文件中定义的超参数都必须出现在全局配置文件的相应 [architecture*] 部分中。
字段 arch_library 指定模型的代码位置(例如 neural_nets.py),而 arch_class 则表示实现该架构的类名(例如,如果设置 class=MLP,则会执行 from neural_nets.py import MLP)。
字段 arch_pretrain_file 可用于使用先前训练好的架构对神经网络进行预训练;而 arch_freeze 如果设为 False,则会在训练过程中更新架构参数;若设为 True,则在训练期间保持参数固定(即冻结)。arch_seq_model 部分指示该架构是序列型(如 RNN)还是非序列型(如前馈 MLP 或 CNN)。PyTorch-Kaldi 在处理输入批次时,这两种情况的处理方式不同。对于循环神经网络(arch_seq_model=True),特征序列不会被随机化(以保留序列中的元素顺序),而对于前馈模型(arch_seq_model=False),我们会对特征进行随机化(这通常有助于提升性能)。当存在多个架构时,只要其中至少有一个被标记为序列型(arch_seq_model=True),就会采用序列处理方式。
需要注意的是,以 “arch_” 和 “opt_” 开头的超参数是必填项,必须出现在配置文件中指定的所有架构中。其他超参数(如 dnn_*)则特定于所考虑的架构(取决于用户实际如何实现 MLP 类),可以定义隐藏层的数量和类型、批归一化和层归一化等参数。
其他重要参数与所考虑架构的优化相关。例如,arch_lr 是学习率,而 arch_halving_factor 用于实现学习率退火。具体来说,当验证集上连续两轮之间的相对性能提升小于 arch_improvement_threshold 所指定的值时(例如,arch_improvement_threshold),我们将学习率乘以 arch_halving_factor(例如,arch_halving_factor=0.5)。字段 arch_opt 指定优化算法的类型。目前支持 SGD、Adam 和 Rmsprop。其他参数则特定于所选的优化算法(有关所有优化专用超参数的确切含义,请参阅 PyTorch 文档)。
需要注意的是,在 [architecture*] 中定义的不同架构可以具有不同的优化超参数,甚至可以使用不同的优化算法。
[model]
model_proto = proto/model.proto
model = out_dnn1=compute(MLP_layers1,mfcc)
loss_final=cost_nll(out_dnn1,lab_cd)
err_final=cost_err(out_dnn1,lab_cd)
本部分使用一种非常简单直观的元语言来指定如何将各种特征和架构组合起来。 字段 model: 描述了特征和架构是如何连接在一起,从而生成后验概率输出的。行 out_dnn1=compute(MLP_layers,mfcc) 的意思是:“将名为 MLP_layers1 的架构与名为 mfcc 的特征输入结合,并将输出存储到变量 out_dnn1 中。” 从神经网络输出 out_dnn1 中,通过名为 lab_cd 的标签计算误差和损失函数,这些标签必须事先在 [datasets*] 部分中定义好。err_final 和 loss_final 是必填的子字段,用于定义模型的最终输出。
一个更为复杂的例子(此处仅为了展示工具包的潜力而提及)见于 cfg/TIMIT_baselines/TIMIT_mfcc_fbank_fmllr_liGRU_best.cfg:
[model]
model_proto=proto/model.proto
model:conc1=concatenate(mfcc,fbank)
conc2=concatenate(conc1,fmllr)
out_dnn1=compute(MLP_layers_first,conc2)
out_dnn2=compute(liGRU_layers,out_dnn1)
out_dnn3=compute(MLP_layers_second,out_dnn2)
out_dnn4=compute(MLP_layers_last,out_dnn3)
out_dnn5=compute(MLP_layers_last2,out_dnn3)
loss_mono=cost_nll(out_dnn5,lab_mono)
loss_mono_w=mult_constant(loss_mono,1.0)
loss_cd=cost_nll(out_dnn4,lab_cd)
loss_final=sum(loss_cd,loss_mono_w)
err_final=cost_err(out_dnn4,lab_cd)
在这种情况下,我们首先将 mfcc、fbank 和 fmllr 特征拼接在一起,然后将其输入到一个 MLP 中。MLP 的输出再被送入一个循环神经网络(具体来说是 Li-GRU 模型)。随后又经过一层 MLP(MLP_layers_second),最后由两个 softmax 分类器(MLP_layers_last 和 MLP_layers_last2)进行分类。第一个分类器估计上下文相关的状态,第二个则估计单音素目标。最终的成本函数是这两者预测结果的加权和。通过这种方式实现了单音素正则化,已被证明有助于提升 ASR 性能。
完整模型可以被视为一个大型计算图,其中在“[model]”部分使用的所有基础架构都会被联合训练。对于每个小批量数据,输入特征会通过整个模型进行前向传播,并使用指定的标签计算 cost_final。随后,计算成本函数相对于该架构所有可学习参数的梯度。最后,所采用架构的所有参数将按照“[architecture*]”章节中指定的算法一起更新。
[forward]
forward_out = out_dnn1
normalize_posteriors = True
normalize_with_counts_from = lab_cd
save_out_file = True
require_decoding = True
“forward”部分首先定义要传递的输出(必须在“model”部分中定义)。如果 normalize_posteriors=True,则这些后验概率会根据先验概率(使用计数文件)进行归一化。如果 save_out_file=True,后验概率文件(通常是一个非常大的 ark 文件)会被保存;而如果 save_out_file=False,当不再需要时,该文件会被删除。
require_decoding 是一个布尔值,用于指定是否需要对指定的输出进行解码。字段 normalize_with_counts_from 用于设置用于归一化后验概率的计数文件来源。
[decoding]
decoding_script_folder = kaldi_decoding_scripts/
decoding_script = decode_dnn.sh
decoding_proto = proto/decoding.proto
min_active = 200
max_active = 7000
max_mem = 50000000
beam = 13.0
latbeam = 8.0
acwt = 0.2
max_arcs = -1
skip_scoring = false
scoring_script = local/score.sh
scoring_opts = "--min-lmwt 1 --max-lmwt 10"
norm_vars = False
“decoding”部分报告了与解码相关的参数,即从 DNN 提供的上下文相关概率序列转换为单词序列的步骤。“decoding_script_folder”字段指定了存储解码脚本的文件夹。“decoding script”字段是用于解码的脚本(例如 decode_dnn.sh),它应该位于之前指定的“decoding_script_folder”中。“decoding_proto”字段列出了所考虑的解码脚本所需的所有参数。
为了使代码更具灵活性,配置参数也可以在命令行中指定。例如,可以运行:
python run_exp.py quick_test/example_newcode.cfg --optimization,lr=0.01 --batches,batch_size=4
脚本会将指定 cfg 文件中的学习率替换为给定的 lr 值。修改后的配置文件随后会保存到 out_folder/config.cfg 中。
脚本 run_exp.py 会自动创建针对每个数据块的配置文件,这些文件由 run_nn 函数用于执行单个数据块的训练。块级配置文件的结构与全局配置文件非常相似。主要区别在于一个字段 to_do={train, valid, forward},它指定了对 fea 字段中指定的特征块进行的处理类型。
为什么使用 proto 文件? 不同的神经网络、优化算法和 HMM 解码器可能依赖于不同的超参数集。为了解决这个问题,我们目前的方案是定义一些原型文件(用于全局、块级和架构配置文件)。总体而言,这种方法使得对全局配置文件中指定的字段检查更加透明。此外,它还允许用户轻松添加新参数,而无需更改任何一行 Python 代码。
例如,要添加一个用户自定义的模型,就需要编写一个新的 proto 文件(如 user-model.proto),以指定相应的超参数。然后,用户只需在 neural_networks.py 中编写一个类(如 user-model),实现该架构即可。
[常见问题解答]
如何插入我的模型
该工具包旨在让用户轻松插入自己的声学模型。要添加自定义的神经网络模型,请按照以下步骤操作:
- 进入
proto文件夹,创建一个新的 proto 文件(例如:*proto/myDNN.proto*)。proto 文件用于指定模型的超参数列表,这些超参数稍后会被写入配置文件中。为了了解需要在 proto 文件中添加哪些信息,可以查看MLP.proto文件:
[proto]
dnn_lay=str_list
dnn_drop=float_list(0.0,1.0)
dnn_use_laynorm_inp=bool
dnn_use_batchnorm_inp=bool
dnn_use_batchnorm=bool_list
dnn_use_laynorm=bool_list
dnn_act=str_list
- 参数
dnn_lay必须是一个字符串列表;dnn_drop(即每一层的 dropout 概率)是一个介于 0.0 和 1.0 之间的浮点数列表;dnn_use_laynorm_inp和dnn_use_batchnorm_inp是布尔值,分别用于启用或禁用输入端的层归一化和批归一化。dnn_use_batchnorm和dnn_use_laynorm是布尔值列表,用于逐层决定是否使用批归一化或层归一化。
参数 dnn_act 同样是一个字符串列表,用于设置每一层的激活函数。由于每个模型都基于自己的一组超参数,因此不同的模型会有不同的 proto 文件。例如,您可以查看 GRU.proto,会发现其超参数列表与标准 MLP 的不同。与前面的例子类似,您应在此处添加自己的超参数列表并保存文件。
- 编写一个实现您模型的 PyTorch 类。
打开
neural_networks.py库,查看其中已实现的一些模型。为简单起见,您可以先从 MLP 类开始。这些类必须包含两个方法:__init__和forward。前者用于初始化网络架构,后者则指定需要执行的计算步骤。
__init__ 方法接受两个参数,这两个参数会在 run_nn 函数中自动计算得出。inp_dim 是神经网络输入的维度,而 options 是一个字典,包含了配置文件中 [architecture] 部分所指定的所有参数。
例如,可以通过以下方式访问各层的 DNN 激活函数:
options['dnn_lay'].split(',')
正如您在 MLP 类中看到的,初始化方法会定义并初始化神经网络的所有参数。forward 方法接收一个张量 x(即输入数据),并输出另一个包含 x 的向量。
如果您的模型是序列模型(即配置文件中至少有一个 arch_seq_model=true 的架构),那么 x 将是一个形状为 (time_steps, batches, N_in) 的张量;否则,它将是一个形状为 (batches, N_in) 的矩阵。forward 方法定义了将输入张量转换为相应输出张量的计算步骤。对于循环神经网络,输出必须具有序列格式 (time_steps, batches, N_out);而对于前馈网络,则为非序列格式 (batches, N_out)。
与已实现的模型类似,用户应编写一个新的类(例如 myDNN),以实现自定义模型:
class myDNN(nn.Module):
def __init__(self, options, inp_dim):
super(myDNN, self).__init__()
// 初始化参数
def forward(self, x):
// 执行一些计算 out=f(x)
return out
- 创建配置文件。
现在您已经定义了自己的模型及其超参数列表,接下来可以创建配置文件。要创建自己的配置文件,您可以参考现有的配置文件(例如,为了简单起见,可以考虑
cfg/TIMIT_baselines/TIMIT_MLP_mfcc_basic.cfg)。在定义了所采用的数据集及其相关特征和标签之后,配置文件中会有一些名为[architecture*]的部分。每个架构实现不同的神经网络。在cfg/TIMIT_baselines/TIMIT_MLP_mfcc_basic.cfg中,我们只有一个[architecture1],因为声学模型仅由一个神经网络组成。要添加您自己的神经网络,您需要按照以下方式编写一个架构部分(例如[architecture1]):
[architecture1]
arch_name= mynetwork (这是您希望在后续模型部分中用来指代此架构的名称)
arch_proto=proto/myDNN.proto (此处填写之前定义的 proto 文件名)
arch_library=neural_networks (这是实现 myDNN 的库名)
arch_class=myDNN (这必须是您实现的类名)
arch_pretrain_file=none (通过此选项可指定是否对模型进行预训练)
arch_freeze=False (若希望更新模型参数,则设为 False)
arch_seq_model=False (对于前馈网络设为 False,对于循环网络设为 True)
然后,您需要为 proto/myDNN.proto 中列出的所有超参数指定合适的值。以 MLP.proto 为例,我们可以这样设置:
dnn_lay=1024,1024,1024,1024,1024,N_out_lab_cd
dnn_drop=0.15,0.15,0.15,0.15,0.15,0.0
dnn_use_laynorm_inp=False
dnn_use_batchnorm_inp=False
dnn_use_batchnorm=True,True,True,True,True,False
dnn_use_laynorm=False,False,False,False,False,False
dnn_act=relu,relu,relu,relu,relu,softmax
接着,添加与您自己架构优化相关的参数。您可以在这里使用标准的 SGD、Adam 或 RMSprop(参见 cfg/TIMIT_baselines/TIMIT_LSTM_mfcc.cfg 中使用 RMSprop 的示例):
arch_lr=0.08
arch_halving_factor=0.5
arch_improvement_threshold=0.001
arch_opt=sgd
opt_momentum=0.0
opt_weight_decay=0.0
opt_dampening=0.0
opt_nesterov=False
将配置文件保存到
cfg文件夹中(例如:cfg/myDNN_exp.cfg)。运行实验:
python run_exp.py cfg/myDNN_exp.cfg
- 为了调试模型,您可以首先查看标准输出。
run_exp.py会自动解析配置文件,并在出现潜在问题时抛出错误。您还可以查看log.log文件,以获取有关可能错误的更多信息。
在实现新模型时,一项重要的调试测试是进行过拟合实验(以确保模型能够在一个小数据集上过拟合)。如果模型无法过拟合,则说明存在需要解决的重大错误。
- 超参数调优。 在深度学习中,经常需要调整超参数,以找到适合您模型的最佳设置。这项工作通常计算量大且耗时,但在引入新架构时往往十分必要。为了帮助进行超参数调优,我们开发了一款实现随机搜索超参数的工具(详情请参阅下一节)。
如何调优超参数?
在深度学习中,通常需要对超参数进行调优,以寻找合适的神经网络架构。为了帮助在 PyTorch-Kaldi 中进行超参数调优,我们实现了一个简单的工具,采用随机搜索的方法。具体来说,脚本 tune_hyperparameters.py 会生成一组随机的配置文件,可以通过以下方式运行:
python tune_hyperparameters.py cfg/TIMIT_MLP_mfcc.cfg exp/TIMIT_MLP_mfcc_tuning 10 arch_lr=randfloat(0.001,0.01) batch_size_train=randint(32,256) dnn_act=choose_str{relu,relu,relu,relu,softmax|tanh,tanh,tanh,tanh,softmax}
第一个参数是我们希望修改的参考配置文件,第二个参数是保存随机配置文件的文件夹,第三个参数是要生成的随机配置文件的数量。接下来是一系列需要更改的超参数。例如,arch_lr=randfloat(0.001,0.01) 会将 arch_lr 字段替换为一个介于 0.001 和 0.01 之间的随机浮点数。batch_size_train=randint(32,256) 则会将 batch_size_train 替换为 32 到 256 之间的随机整数,以此类推。 配置文件生成后,可以按顺序或并行地使用以下命令运行:
python run_exp.py $cfg_file
如何使用自己的数据集?
PyTorch-Kaldi 可以用于任何语音数据集。要使用自己的数据集,步骤与 TIMIT/Librispeech 教程中介绍的类似。一般来说,你需要执行以下操作:
- 使用 Kaldi 的数据处理流程来处理你的数据集。有关数据准备的详细信息,请参阅 Kaldi 官网。
- 对训练集、验证集和测试集分别计算对齐结果。
- 编写一个 PyTorch-Kaldi 配置文件 $cfg_file。
- 使用
python run_exp.py $cfg_file运行该配置文件。
如何接入自定义特征?
当前版本的 PyTorch-Kaldi 支持以 Kaldi ark 格式存储的输入特征。如果用户希望使用自定义特征进行实验,则必须先将这些特征转换为 ark 格式。有关如何将 NumPy 数组转换为 ark 文件的详细说明,请参阅 Kaldi-io-for-python 的 Git 仓库(https://github.com/vesis84/kaldi-io-for-python)。 此外,你还可以查看我们的工具脚本 save_raw_fea.py。该脚本会生成包含原始特征的 Kaldi ark 文件,这些原始特征随后可用于直接以原始波形作为输入来训练神经网络(请参阅关于使用 SincNet 处理音频的部分)。
如何转录我自己的音频文件
当前版本的 Pytorch-Kaldi 支持使用 Pytorch-Kaldi 预训练声学模型来转录音频文件的标准生产流程,可以处理单个或多个 .wav 文件。重要的是,您必须拥有一个已经训练好的 Pytorch-Kaldi 模型。虽然现在不再需要标签或对齐信息,但 Pytorch-Kaldi 仍然需要许多文件才能转录新的音频文件:
- 特征及其特征列表 feats.scp(包含 .ark 文件,详见 #如何接入自定义特征)
- 解码图(通常在之前的模型训练中通过 mkgraph.sh 脚本生成,例如三音素模型)。如果您不进行解码,则无需此图。
准备好所有这些文件后,您可以开始将您的数据集部分添加到全局配置文件中。最简单的方法是复制用于训练声学模型的 cfg 文件,并通过添加一个新的 [dataset] 来修改它:
[dataset4]
data_name = myWavFile
fea = fea_name=fbank
fea_lst=myWavFilePath/data/feats.scp
fea_opts=apply-cmvn --utt2spk=ark:myWavFilePath/data//utt2spk ark:myWavFilePath/cmvn_test.ark ark:- ark:- | add-deltas --delta-order=0 ark:- ark:- |
cw_left=5
cw_right=5
lab = lab_name=none
lab_data_folder=myWavFilePath/data/
lab_graph=myWavFilePath/exp/tri3/graph
n_chunks=1
[data_use]
train_with = TIMIT_tr
valid_with = TIMIT_dev
forward_with = myWavFile
用于音频文件转录的关键字符串是 lab_name=none。标签值为 none 表示 Pytorch-Kaldi 将进入仅执行前向传播和解码的“生产”模式,而不使用任何标签。您不需要在生产服务器上放置 TIMIT_tr 和 TIMIT_dev 数据集,因为 Pytorch-Kaldi 会跳过这些信息,直接进入 forward_with 字段中指定的数据集的前向阶段。如您所见,全局的 fea 字段需要与标准训练或测试数据集完全相同的参数,而 lab 字段只需两个参数即可。请注意,lab_data_folder 实际上就是 fea_lst 所指向的路径。最后,您仍需指定要将该文件分割成多少个块来处理(1 小时为 1 个块)。
警告
在您的标准 .cfg 文件中,可能使用了诸如 N_out_lab_cd 等关键字,但在生产场景中已无法再使用。这是因为,在生产环境中,您并不希望将训练数据保留在本地机器上。因此,.cfg 文件中所有的变量都需要替换为其实际值。对于所有 N_out_{mono,lab_cd} 的替换,您可以查看以下命令的输出:
hmm-info /path/to/the/final.mdl/used/to/generate/the/training/ali
然后,如果您按照 .cfg 文件中“forward”部分的设置对后验概率进行归一化:
normalize_posteriors = True
normalize_with_counts_from = lab_cd
则需要将其替换为:
normalize_posteriors = True
normalize_with_counts_from = /path/to/ali_train_pdf.counts
这一步归一化对于 HMM-DNN 语音识别至关重要。事实上,DNN 提供的是后验概率,而 HMM 是基于似然的概率生成模型。为了得到所需的似然值,只需将后验概率除以前验概率即可。要创建这个 ali_train_pdf.counts 文件,您可以按照以下步骤操作:
alidir=/path/to/the/exp/tri_ali (请替换为您存放 ali 文件的路径)
num_pdf=$(hmm-info $alidir/final.mdl | awk '/pdfs/{print $4}')
labels_tr_pdf="ark:ali-to-pdf $alidir/final.mdl \"ark:gunzip -c $alidir/ali.*.gz |\" ark:- |"
analyze-counts --verbose=1 --binary=false --counts-dim=$num_pdf "$labels_tr_pdf" ali_train_pdf.counts
这样就完成了!在生产场景中,您可能需要转录大量的音频文件,而不希望为每个文件都单独创建一个 .cfg 文件。为此,在创建好初始的生产用 .cfg 文件后(路径字段可以留空),您可以调用 run_exp.py 脚本,并传入针对不同 .wav 特征的具体参数:
python run_exp.py cfg/TIMIT_baselines/TIMIT_MLP_fbank_prod.cfg --dataset4,fea,0,fea_lst="myWavFilePath/data/feats.scp" --dataset4,lab,0,lab_data_folder="myWavFilePath/data/" --dataset4,lab,0,lab_graph="myWavFilePath/exp/tri3/graph/"
该命令会在内部根据您指定的路径修改配置文件,并运行您定义的特征!需要注意的是,向 run_exp.py 脚本传递长参数时,需要使用特定的格式。--dataset4 指定所创建节目的名称,fea 是更高级别的字段名,而 fea_lst 或 lab_graph 则是您想要更改的最低级别字段名。数字 0 用于指示要修改的最低级别字段的具体位置,因为某些配置文件可能为每个数据集包含多个 lab_graph。因此,0 表示第一个出现的实例,1 表示第二个……路径必须用双引号括起来,才能被正确解析为完整字符串!此外,如果您不希望不同 .wav 文件的转录结果相互覆盖(解码文件会根据 data_name 字段进行存储),则需要同时修改 data_name 和 forward_with 字段:--dataset4,data_name=MyNewName --data_use,forward_with=MyNewName。
批量大小、学习率和丢弃率调度
为了给用户提供更大的灵活性,PyTorch-Kaldi 的最新版本支持对批量大小、max_seq_length_train、学习率和丢弃因子进行调度。 这意味着现在可以在训练过程中动态调整这些参数。为此,我们在配置文件中引入了以下语法:
batch_size_train = 128*12 | 64*10 | 32*2
在这种情况下,前 12 个 epoch 的批量大小为 128,接下来的 10 个 epoch 为 64,最后两个 epoch 则为 32。默认情况下,“*”表示重复执行指定次数,“|”用于指示批量大小的变化。需要注意的是,如果用户仅设置 batch_size_train = 128,则批量大小将在整个训练过程中保持不变。
类似地,也可以通过以下语法实现学习率调度:
arch_lr = 0.08*10|0.04*5|0.02*3|0.01*2|0.005*2|0.0025*2
如果用户仅设置 arch_lr = 0.08,学习率将按照工具包旧版本中使用的 new-bob 算法进行退火。具体来说,我们会从指定的学习率开始,每当验证集上的性能提升低于 arch_improvement_threshold 字段中设定的阈值时,就将学习率减半。
此外,丢弃因子也可以在训练过程中按如下方式调整:
dnn_drop = 0.15*12|0.20*12,0.15,0.15*10|0.20*14,0.15,0.0
通过上述语法,我们可以为不同层和不同 epoch 设置不同的丢弃率。例如,第一隐藏层在前 12 个 epoch 的丢弃率为 0.15,随后的 12 个 epoch 则为 0.20;而第二隐藏层在整个训练过程中丢弃率始终保持为 0.15。所有层都采用相同的语法,其中“|”表示同一层内丢弃率的变化,“,”则表示不同层之间的切换。
您可以通过以下配置文件查看批量大小、学习率和丢弃因子如何变化的例子:
cfg/TIMIT_baselines/TIMIT_mfcc_basic_flex.cfg
或者:
cfg/TIMIT_baselines/TIMIT_liGRU_fmllr_lr_schedule.cfg
我如何参与该项目
目前项目仍处于初期阶段,我们诚挚邀请所有潜在贡献者加入。我们希望构建一个规模足够大的开发者社区,以逐步维护、改进并扩展当前工具包的功能。例如,报告任何 bug 或提出改进建议都将非常有帮助。此外,大家还可以通过添加新的神经网络模型来丰富现有架构库。
[额外]
使用 SincNet 从原始波形进行语音识别
SincNet 是一种最近提出的用于处理原始音频波形的卷积神经网络。其核心思想是利用参数化的 sinc 函数,促使第一层自动发现更具语义意义的滤波器。与传统 CNN 不同,后者会学习每个滤波器的所有参数,而 SincNet 只直接从数据中学习带通滤波器的低频和高频截止频率。这种归纳偏置提供了一种非常紧凑的方式来构建自定义的滤波器组前端,该前端仅依赖于几个具有明确物理意义的参数。
有关 SincNet 模型的更详细说明,请参阅以下论文:
M. Ravanelli, Y. Bengio, “使用 SincNet 从原始波形进行说话人识别”,SLT 2018 会议论文 ArXiv
M. Ravanelli, Y. Bengio, “具有可解释性的卷积滤波器:SincNet”,NIPS@IRASL 2018 会议论文 ArXiv
要在 TIMIT 数据集上使用此模型进行语音识别,请按照以下步骤操作:
- 按照“TIMIT 教程”中的步骤进行操作。
- 将原始波形保存为 Kaldi ark 格式。可以使用我们仓库中的
save_raw_fea.py工具脚本完成此操作。该脚本会将输入信号保存为二进制 Kaldi 归档文件,并保留与预计算标签的对齐信息。请对所有数据块(如 train、dev、test)分别运行此脚本。您还可以通过sig_wlen=200 # ms参数指定每帧的语音片段长度。 - 打开
cfg/TIMIT_baselines/TIMIT_SincNet_raw.cfg,修改路径后运行:
python ./run_exp.py cfg/TIMIT_baselines/TIMIT_SincNet_raw.cfg
- 使用该架构,我们获得了 PER(%)=17.1% 的结果。而使用相同特征输入的标准 CNN 则得到 PER(%)=18.%。更多结果请参阅 此处。我们的 SincNet 结果优于使用 MFCC 和 FBANK 特征输入的标准前馈网络所取得的效果。
下表比较了 SincNet 与其他前馈神经网络的结果:
| 模型 | WER(%) |
|---|---|
| MLP -fbank | 18.7 |
| MLP -mfcc | 18.2 |
| CNN -raw | 18.1 |
| SincNet -raw | 17.2 |
语音增强与自动语音识别的联合训练
在本节中,我们展示了如何使用 PyTorch-Kaldi 联合训练一个由语音增强网络和语音识别神经网络组成的级联系统。语音增强的目标是通过最小化干净特征与噪声特征之间的均方误差(MSE),来提升语音信号的质量。增强后的特征随后输入到另一个神经网络中,用于预测上下文相关的音素状态。
接下来,我们将报告一个基于 TIMIT 混响版本的玩具任务示例,该示例仅用于展示用户应如何配置文件以训练此类神经网络组合。尽管一些实现细节(以及所采用的数据集)有所不同,但本教程受到以下论文的启发:
- M. Ravanelli, P. Brakel, M. Omologo, Y. Bengio, “基于 DNN 的远场语音识别的批归一化联合训练”,STL 2016 年会议论文 arXiv
要运行该系统,请按照以下步骤操作:
确保您已准备好标准的 TIMIT 清晰版本数据。
运行 Kaldi s5 基线流程处理 TIMIT 数据。此步骤对于计算干净特征(将作为语音增强系统的标签)以及对齐信息(将作为语音识别系统的标签)至关重要。建议完整运行 timit s5 流程(包括 DNN 训练)。
标准的 TIMIT 流程使用 MFCC 特征,而在本教程中,我们改用 FBANK 特征。要在 $KALDI_ROOT/egs/TIMIT/s5 目录下计算 FBANK 特征,请运行以下脚本:
feadir=fbank
for x in train dev test; do
steps/make_fbank.sh --cmd "$train_cmd" --nj $feats_nj data/$x exp/make_fbank/$x $feadir
steps/compute_cmvn_stats.sh data/$x exp/make_fbank/$x $feadir
done
请注意,我们这里使用 40 维 FBANK 特征,而 Kaldi 默认使用 23 维。若需计算 40 维特征,请进入 $KALDI_ROOT/egs/TIMIT/conf/fbank.conf 文件,并修改输出滤波器的数量。
访问此外部仓库,按照说明从 TIMIT 清晰版本生成混响版本。请注意,这只是一个“玩具任务”,仅用于演示如何搭建联合训练系统。
为 TIMIT_rev 数据集计算 FBANK 特征。为此,您可以将 $KALDI_ROOT/egs/TIMIT/ 中的脚本复制到 $KALDI_ROOT/egs/TIMIT_rev/ 目录下。同时请复制 data 文件夹。需要注意的是,TIMIT_rev 文件夹中的音频文件采用标准的 WAV 格式,而原始 TIMIT 数据则使用 SPHERE 格式。为解决这一问题,打开 data/train/wav.scp、data/dev/wav.scp 和 data/test/wav.scp 文件,删除关于 SPHERE 格式的读取部分(例如 /home/mirco/kaldi-trunk/tools/sph2pipe_v2.5/sph2pipe -f wav)。此外,还需将路径从标准 TIMIT 修改为混响版本(例如将 /TIMIT/ 替换为 /TIMIT_rev/)。请务必移除末尾的管道符号“|”。保存更改后,按如下方式运行 FBANK 特征计算:
feadir=fbank
for x in train dev test; do
steps/make_fbank.sh --cmd "$train_cmd" --nj $feats_nj data/$x exp/make_fbank/$x $feadir
steps/compute_cmvn_stats.sh data/$x exp/make_fbank/$x $feadir
done
同时记得修改 $KALDI_ROOT/egs/TIMIT_rev/conf/fbank.conf 文件,以计算 40 维特征,而非默认配置中的 23 维 FBANK 特征。
- 特征计算完成后,打开以下配置文件:
cfg/TIMIT_baselines/TIMIT_rev/TIMIT_joint_training_liGRU_fbank.cfg
请根据您本地数据存储位置调整路径。如您所见,我们考虑了两类特征:fbank_rev 特征来自 TIMIT_rev 数据集,而 fbank_clean 特征则来自标准 TIMIT 数据集,用作语音增强神经网络的目标。在配置文件的 [model] 部分,可以看到语音增强与语音识别网络的级联结构。语音识别架构同时估计上下文相关和单音素目标(即采用所谓的单音素正则化)。 要运行实验,请输入以下命令:
python run_exp.py cfg/TIMIT_baselines/TIMIT_rev/TIMIT_joint_training_liGRU_fbank.cfg
- 结果 使用此配置文件,您应获得 音素错误率 (PER) = 28.1%。请注意,围绕该性能的小幅波动是正常现象,主要源于神经网络参数初始化的不同。
您可在此处进一步查看我们的实验结果:链接
基于DIRHA的远场语音识别
在本教程中,我们使用DIRHA-English数据集进行远场语音识别实验。DIRHA英语数据集是由欧盟项目DIRHA开发的多麦克风语音语料库。该语料库由在家庭环境中使用32个采样同步麦克风录制的真实和模拟序列组成。数据库包含具有不同噪声和混响特性的信号,因此适用于各种多麦克风信号处理和远场语音识别任务。目前发布的数据集部分由6位美国本地说话者(3名男性,3名女性)朗读409句《华尔街日报》句子构成。训练数据是通过一种真实的污染方法生成的,即利用在目标环境中测量的高质量多麦克风脉冲响应对干净的WSJ-5k语料中的句子进行污染。有关该数据集的更多详细信息,请参阅以下论文:
M. Ravanelli, L. Cristoforetti, R. Gretter, M. Pellin, A. Sosi, M. Omologo, “DIRHA-English语料库及用于家庭环境远场语音识别的相关任务”,ASRU 2015会议论文集。ArXiv
M. Ravanelli, P. Svaizer, M. Omologo, “用于远场语音识别的真实多麦克风数据仿真”,Interspeech 2016会议论文集。ArXiv
在本教程中,我们使用上述模拟数据进行训练(采用LA6麦克风),而测试则使用真实录音(LA6)。这项任务非常贴近实际场景,但也极具挑战性。语音信号的混响时间约为0.7秒。真实录音中还存在非平稳的家庭噪声(如吸尘器声、脚步声、电话铃声等)。
现在让我们开始实践教程。
如果尚未拥有,可从LDC网站下载DIRHA数据集。LDC以少量费用提供完整数据集。
访问此外部仓库。根据该仓库说明,您需要使用提供的MATLAB脚本生成污染后的WSJ数据集。随后,您可以运行建议的KALDI基线,以便为我们的pytorch-kaldi工具包准备好特征和标签。
打开以下配置文件:
cfg/DIRHA_baselines/DIRHA_liGRU_fmllr.cfg
该配置文件实现了一个基于轻量门控循环单元(Li-GRU)的简单RNN模型。我们使用fMLLR作为输入特征。请更改路径并运行以下命令:
python run_exp.py cfg/DIRHA_baselines/DIRHA_liGRU_fmllr.cfg
- 结果: 上述系统应给出词错误率(WER%)=23.2%。您可以在此处查看我们获得的结果:这里。
通过使用cfg/DIRHA_baselines文件夹中的其他配置文件,您可以尝试不同的设置。利用这些配置文件,您可以得到以下结果:
| 模型 | WER(%) |
|---|---|
| MLP | 26.1 |
| GRU | 25.3 |
| Li-GRU | 23.8 |
训练自编码器
当前版本的仓库主要用于语音识别实验。我们正在积极开发一个更加灵活的新版本,能够处理不同于Kaldi特征/标签的输入输出。不过,即使在当前版本中,也可以实现其他系统,例如自编码器。
自编码器是一种输入和输出相同的神经网络。其中间层通常包含一个瓶颈,迫使表示压缩输入信息。在本教程中,我们提供了一个基于TIMIT数据集的示例。例如,请查看以下配置文件:
cfg/TIMIT_baselines/TIMIT_MLP_fbank_autoencoder.cfg
我们的输入是标准的40维fbank系数,采用11帧的上下文窗口提取(即输入的总维度为440)。一个前馈神经网络(称为MLP_encoder)将特征编码为100维表示。解码器(称为MLP_decoder)接收学习到的表示,并尝试重建输出。该系统使用**均方误差(MSE)**指标进行训练。 请注意,在[Model]部分末尾添加了这一行:“err_final=cost_err(dec_out,lab_cd)”。事实上,当前版本的模型默认要求至少指定一个标签(我们将在下一版本中取消这一限制)。
您可以通过运行以下命令来训练该系统:
python run_exp.py cfg/TIMIT_baselines/TIMIT_MLP_fbank_autoencoder.cfg
结果应如下所示:
ep=000 tr=['TIMIT_tr'] loss=0.139 err=0.999 valid=TIMIT_dev loss=0.076 err=1.000 lr_architecture1=0.080000 lr_architecture2=0.080000 time(s)=41
ep=001 tr=['TIMIT_tr'] loss=0.098 err=0.999 valid=TIMIT_dev loss=0.062 err=1.000 lr_architecture1=0.080000 lr_architecture2=0.080000 time(s)=39
ep=002 tr=['TIMIT_tr'] loss=0.091 err=0.999 valid=TIMIT_dev loss=0.058 err=1.000 lr_architecture1=0.040000 lr_architecture2=0.040000 time(s)=39
ep=003 tr=['TIMIT_tr'] loss=0.088 err=0.999 valid=TIMIT_dev loss=0.056 err=1.000 lr_architecture1=0.020000 lr_architecture2=0.020000 time(s)=38
ep=004 tr=['TIMIT_tr'] loss=0.087 err=0.999 valid=TIMIT_dev loss=0.055 err=0.999 lr_architecture1=0.010000 lr_architecture2=0.010000 time(s)=39
ep=005 tr=['TIMIT_tr'] loss=0.086 err=0.999 valid=TIMIT_dev loss=0.054 err=1.000 lr_architecture1=0.005000 lr_architecture2=0.005000 time(s)=39
ep=006 tr=['TIMIT_tr'] loss=0.086 err=0.999 valid=TIMIT_dev loss=0.054 err=1.000 lr_architecture1=0.002500 lr_architecture2=0.002500 time(s)=39
ep=007 tr=['TIMIT_tr'] loss=0.086 err=0.999 valid=TIMIT_dev loss=0.054 err=1.000 lr_architecture1=0.001250 lr_architecture2=0.001250 time(s)=39
ep=008 tr=['TIMIT_tr'] loss=0.086 err=0.999 valid=TIMIT_dev loss=0.054 err=0.999 lr_architecture1=0.000625 lr_architecture2=0.000625 time(s)=41
ep=009 tr=['TIMIT_tr'] loss=0.086 err=0.999 valid=TIMIT_dev loss=0.054 err=0.999 lr_architecture1=0.000313 lr_architecture2=0.000313 time(s)=38
您只需关注“loss=”字段。由于上述原因,“err=”字段在此情况下并不重要。您可以通过以下命令查看生成的特征:
copy-feats ark:exp/TIMIT_MLP_fbank_autoencoder/exp_files/forward_TIMIT_test_ep009_ck00_enc_out.ark ark,t:- | more
参考文献
[1] M. Ravanelli, T. Parcollet, Y. Bengio,《PyTorch-Kaldi 语音识别工具包》,ArXiv
[2] M. Ravanelli, P. Brakel, M. Omologo, Y. Bengio,《通过改进门控循环单元提升语音识别性能》,载于 Interspeech 2017 年会议论文集。ArXiv
[3] M. Ravanelli, P. Brakel, M. Omologo, Y. Bengio,《用于语音识别的轻量级门控循环单元》,载于 IEEE 计算智能新兴领域汇刊。ArXiv
[4] M. Ravanelli,《远场语音识别中的深度学习》,博士论文,特伦托大学,2017 年。ArXiv
[5] T. Parcollet, M. Ravanelli, M. Morchid, G. Linarès, C. Trabelsi, R. De Mori, Y. Bengio,《四元数循环神经网络》,载于 ICLR 2019 年会议论文集。ArXiv
[6] T. Parcollet, M. Morchid, G. Linarès, R. De Mori,《面向语音识别的双向四元数长短时记忆循环神经网络》,载于 ICASSP 2019 年会议论文集。ArXiv
常见问题
相似工具推荐
openclaw
OpenClaw 是一款专为个人打造的本地化 AI 助手,旨在让你在自己的设备上拥有完全可控的智能伙伴。它打破了传统 AI 助手局限于特定网页或应用的束缚,能够直接接入你日常使用的各类通讯渠道,包括微信、WhatsApp、Telegram、Discord、iMessage 等数十种平台。无论你在哪个聊天软件中发送消息,OpenClaw 都能即时响应,甚至支持在 macOS、iOS 和 Android 设备上进行语音交互,并提供实时的画布渲染功能供你操控。 这款工具主要解决了用户对数据隐私、响应速度以及“始终在线”体验的需求。通过将 AI 部署在本地,用户无需依赖云端服务即可享受快速、私密的智能辅助,真正实现了“你的数据,你做主”。其独特的技术亮点在于强大的网关架构,将控制平面与核心助手分离,确保跨平台通信的流畅性与扩展性。 OpenClaw 非常适合希望构建个性化工作流的技术爱好者、开发者,以及注重隐私保护且不愿被单一生态绑定的普通用户。只要具备基础的终端操作能力(支持 macOS、Linux 及 Windows WSL2),即可通过简单的命令行引导完成部署。如果你渴望拥有一个懂你
stable-diffusion-webui
stable-diffusion-webui 是一个基于 Gradio 构建的网页版操作界面,旨在让用户能够轻松地在本地运行和使用强大的 Stable Diffusion 图像生成模型。它解决了原始模型依赖命令行、操作门槛高且功能分散的痛点,将复杂的 AI 绘图流程整合进一个直观易用的图形化平台。 无论是希望快速上手的普通创作者、需要精细控制画面细节的设计师,还是想要深入探索模型潜力的开发者与研究人员,都能从中获益。其核心亮点在于极高的功能丰富度:不仅支持文生图、图生图、局部重绘(Inpainting)和外绘(Outpainting)等基础模式,还独创了注意力机制调整、提示词矩阵、负向提示词以及“高清修复”等高级功能。此外,它内置了 GFPGAN 和 CodeFormer 等人脸修复工具,支持多种神经网络放大算法,并允许用户通过插件系统无限扩展能力。即使是显存有限的设备,stable-diffusion-webui 也提供了相应的优化选项,让高质量的 AI 艺术创作变得触手可及。
everything-claude-code
everything-claude-code 是一套专为 AI 编程助手(如 Claude Code、Codex、Cursor 等)打造的高性能优化系统。它不仅仅是一组配置文件,而是一个经过长期实战打磨的完整框架,旨在解决 AI 代理在实际开发中面临的效率低下、记忆丢失、安全隐患及缺乏持续学习能力等核心痛点。 通过引入技能模块化、直觉增强、记忆持久化机制以及内置的安全扫描功能,everything-claude-code 能显著提升 AI 在复杂任务中的表现,帮助开发者构建更稳定、更智能的生产级 AI 代理。其独特的“研究优先”开发理念和针对 Token 消耗的优化策略,使得模型响应更快、成本更低,同时有效防御潜在的攻击向量。 这套工具特别适合软件开发者、AI 研究人员以及希望深度定制 AI 工作流的技术团队使用。无论您是在构建大型代码库,还是需要 AI 协助进行安全审计与自动化测试,everything-claude-code 都能提供强大的底层支持。作为一个曾荣获 Anthropic 黑客大奖的开源项目,它融合了多语言支持与丰富的实战钩子(hooks),让 AI 真正成长为懂上
ComfyUI
ComfyUI 是一款功能强大且高度模块化的视觉 AI 引擎,专为设计和执行复杂的 Stable Diffusion 图像生成流程而打造。它摒弃了传统的代码编写模式,采用直观的节点式流程图界面,让用户通过连接不同的功能模块即可构建个性化的生成管线。 这一设计巧妙解决了高级 AI 绘图工作流配置复杂、灵活性不足的痛点。用户无需具备编程背景,也能自由组合模型、调整参数并实时预览效果,轻松实现从基础文生图到多步骤高清修复等各类复杂任务。ComfyUI 拥有极佳的兼容性,不仅支持 Windows、macOS 和 Linux 全平台,还广泛适配 NVIDIA、AMD、Intel 及苹果 Silicon 等多种硬件架构,并率先支持 SDXL、Flux、SD3 等前沿模型。 无论是希望深入探索算法潜力的研究人员和开发者,还是追求极致创作自由度的设计师与资深 AI 绘画爱好者,ComfyUI 都能提供强大的支持。其独特的模块化架构允许社区不断扩展新功能,使其成为当前最灵活、生态最丰富的开源扩散模型工具之一,帮助用户将创意高效转化为现实。
gemini-cli
gemini-cli 是一款由谷歌推出的开源 AI 命令行工具,它将强大的 Gemini 大模型能力直接集成到用户的终端环境中。对于习惯在命令行工作的开发者而言,它提供了一条从输入提示词到获取模型响应的最短路径,无需切换窗口即可享受智能辅助。 这款工具主要解决了开发过程中频繁上下文切换的痛点,让用户能在熟悉的终端界面内直接完成代码理解、生成、调试以及自动化运维任务。无论是查询大型代码库、根据草图生成应用,还是执行复杂的 Git 操作,gemini-cli 都能通过自然语言指令高效处理。 它特别适合广大软件工程师、DevOps 人员及技术研究人员使用。其核心亮点包括支持高达 100 万 token 的超长上下文窗口,具备出色的逻辑推理能力;内置 Google 搜索、文件操作及 Shell 命令执行等实用工具;更独特的是,它支持 MCP(模型上下文协议),允许用户灵活扩展自定义集成,连接如图像生成等外部能力。此外,个人谷歌账号即可享受免费的额度支持,且项目基于 Apache 2.0 协议完全开源,是提升终端工作效率的理想助手。
markitdown
MarkItDown 是一款由微软 AutoGen 团队打造的轻量级 Python 工具,专为将各类文件高效转换为 Markdown 格式而设计。它支持 PDF、Word、Excel、PPT、图片(含 OCR)、音频(含语音转录)、HTML 乃至 YouTube 链接等多种格式的解析,能够精准提取文档中的标题、列表、表格和链接等关键结构信息。 在人工智能应用日益普及的今天,大语言模型(LLM)虽擅长处理文本,却难以直接读取复杂的二进制办公文档。MarkItDown 恰好解决了这一痛点,它将非结构化或半结构化的文件转化为模型“原生理解”且 Token 效率极高的 Markdown 格式,成为连接本地文件与 AI 分析 pipeline 的理想桥梁。此外,它还提供了 MCP(模型上下文协议)服务器,可无缝集成到 Claude Desktop 等 LLM 应用中。 这款工具特别适合开发者、数据科学家及 AI 研究人员使用,尤其是那些需要构建文档检索增强生成(RAG)系统、进行批量文本分析或希望让 AI 助手直接“阅读”本地文件的用户。虽然生成的内容也具备一定可读性,但其核心优势在于为机器