Warp-CTC是一个可以应用在CPU和GPU上高效并行的CTC代码库 (library) 介绍 CTCConnectionist Temporal Classification作为一个损失函数,用于在序列数据上进行监督式学习,不需要对齐输入数据及标签。比如,CTC可以被用来训练端对端的语音识别系统,这正是我们在百度硅谷试验室所使用的方法。 端到端 系统 语音识别
上图展示了CTC计算输出序列(“THE CAT”)概率的过程,是对可能映射成“THE CAT”的所有可能输入序列对齐的和。这一过程考虑了标签会被复制的可能性,因为标签有可能在输入数据的几个时间步(time steps)时被拉伸 (请见上图底部的声谱图)。由于涉及到了组合学,计算所有可能概率的和的成本会很高,但是CTC运用了动态规划以大幅降低计算的复杂性。作为一个可微函数,CTC可以被用于深度神经网络的标准SGD训练。 我们实验室专注于递归神经网络(RNN)的可扩展性 (scalibility), 而CTC损失函数是其中很重要的一部分。为了让我们的系统更有效率,我们并行处理了CTC算法,正如这篇文章中所描述的 。这个项目包含了我们的高性能CPU以及CUDA版本的CTC损失函数, 以及绑定的Torch. 该代码库提供了简单的C接口,易于与深度学习框架整合。
这种执行方式提高了训练的的可扩展性,超过了并行CTC的实现方式。对于以GPU为核心的训练, 我们可用所有的的网络带宽来增加数据的可并行性。 性能 相起其他的开源工具,Warp-CTC的实现方式相对高效,且代码的数值稳定性也较好。因为CTC本身对数值较为敏感,因此即使使用双精度标准计算,也会出现下溢 (underflow)的情况。 具体来说,两个数值趋近于无穷小且相近的数字相除的结果应该大约为1,却因为分母接近为0而变成无穷。 然而,如果直接取对数执行运算,CTC会在数值上较为稳定,虽然会在单精度浮点中以高成本运算为代价。 我们将Warp-CTC和Eesen (建立在Theano上的CTC)以及仅运行Stanford-CTC的Cython CPU进行了比较。为了进行比较,我们对在32位浮点数上运行的Theano进行了基准测试,并且取对数计算。 而Stanford-CTC由于本身不支持对数运算,因此需要被修改。而且它也不支持大于1的迷你批处理 (minibatches), 所以需要在真正的训练流水线上布局非常规内存(我们假设成本与迷你批处理的规模是成正线性关系)。 我们在Deep Speech 2中分别展示了英文及中文端对端模型的结果, 其中T代表输入CTC的时间步数量,L代表每个例子的标签长度,A代表字母数量。 在GPU上,Warp-CTC对64个例子迷你批处理的表现比Eesen快7倍到155倍,比Theano快46倍到68倍
单核NVIDIA Titan X GPU基准测试
T=150, L=40, A=28 | warp-ctc | Eesen | Theano |
---|---|---|---|
N=1 | 3.1 ms | .5 ms | 67 ms |
N=16 | 3.2 ms | 6 ms | 94 ms |
N=32 | 3.2 ms | 12 ms | 119 ms |
N=64 | 3.3 ms | 24 ms | 153 ms |
N=128 | 3.5 ms | 49 ms | 231 ms |
T=150, L=20, A=5000 | warp-ctc | Eesen | Theano |
---|---|---|---|
N=1 | 7 ms | 40 ms | 120 ms |
N=16 | 9 ms | 619 ms | 385 ms |
N=32 | 11 ms | 1238 ms | 665 ms |
N=64 | 16 ms | 2475 ms | 1100 ms |
N=128 | 23 ms | 4950 ms | 2100 ms |
在一台有两个Intel E5-2660 v3处理器的双槽机上进行基准测试。Warp-CTC用了40个线程从而最大化了对CPU资源的利用。Eesen没有提供CPU实现方式。我们注意到Theano没有在多线程上进行并行计算。同样,Stanford-CTC没有提供多线程并行计算的机制。
T=150, L=40, A=28 | warp-ctc | Stanford-CTC | Theano |
---|---|---|---|
N=1 | 2.6 ms | 13 ms | 15 ms |
N=16 | 3.4 ms | 208 ms | 180 ms |
N=32 | 3.9 ms | 416 ms | 375 ms |
N=64 | 6.6 ms | 832 ms | 700 ms |
N=128 | 12.2 ms | 1684 ms | 1340 ms |
T=150, L=20, A=5000 | warp-ctc | Stanford-CTC | Theano |
---|---|---|---|
N=1 | 21 ms | 31 ms | 850 ms |
N=16 | 37 ms | 496 ms | 10800 ms |
N=32 | 54 ms | 992 ms | 22000 ms |
N=64 | 101 ms | 1984 ms | 42000 ms |
N=128 | 184 ms | 3968 ms | 86000 ms |
接口在include/ctc.h
中,它支持在CPU或者GPU上执行。 如果是在CPU上运行,可以指定OpenMP并行计算; 如果是在GPU上运行,请用CUDA stream。 为避免内存分配而导致的竞争及间接成本,我们会确保代码库不会在内部进行内存分配。
Warp-CTC已经在Ubuntu 14.04以及OSX 10.10进行了测试,现不支持Windows. 首先,请获取代码
git clone https://github.com/baidu-research/warp-ctc.git
cd warp-ctc
创建目录
mkdir build
cd build
假如使用非标准CUDA,请安装 export CUDA_BIN_PATH=/path_to_cuda
以便被CMake检测。且确保Torch被监测到,注意(th
is in $PATH
) 运行cmake, 创建
cmake ../
make
现在,C代码库以及与torch分享的代码库应当和测试可执行文件一同被创建。假如CUDA被检测到,test_gpu则被创建。 测试 为了运行测试,确保CUDA代码库在LD_LIBRARY_PATH
(DYLD_LIBRARY_PATH
for OSX)中。 Torch测试必须在 torch_binding/tests/
目录中运行。
luarocks make torch_binding/rocks/warp-ctc-scm-1.rockspec
即使不复制存储库(repository),你也可以安装
luarocks install http://raw.githubusercontent.com/baidu-research/warp-ctc/master/torch_binding/rocks/warp-ctc-scm-1.rockspec
请见Torch CTC教程。
CUDA的执行需要至少3.0的计算能力, 所支持的标签长度最大值为639 (时间步数是有限的)。
===============
最近在做中文字符串识别工作,需要调用warp_ctc。但是WIN10+cuda10+pytorch+py3.68环境下,pytorch调用过程中屡屡出错。
warp_ctc源码地址为:https://github.com/SeanNaren/Warp-ctc
按照github上的指令安装warpctc_pytorch,执行到这一步时报错:
python setup.py install
错误显示如下:
generating build/warpctc_pytorch/_warp_ctc/__warp_ctc.c
(already up-to-date)
not modified: 'build/warpctc_pytorch/_warp_ctc/__warp_ctc.c'
running install
running bdist_egg
running egg_info
writing warpctc_pytorch.egg-info/PKG-INFO
writing dependency_links to warpctc_pytorch.egg-info/dependency_links.txt
writing top-level names to warpctc_pytorch.egg-info/top_level.txt
reading manifest file 'warpctc_pytorch.egg-info/SOURCES.txt'
writing manifest file 'warpctc_pytorch.egg-info/SOURCES.txt'
installing library code to build/bdist.linux-x86_64/egg
running install_lib
running build_py
copying warpctc_pytorch/_warp_ctc/__init__.py -> build/lib.linux-x86_64-3.6/warpctc_pytorch/_warp_ctc
running build_ext
building 'warpctc_pytorch._warp_ctc.__warp_ctc' extension
gcc -pthread -B /home1/fzp/anaconda3/compiler_compat -Wl,--sysroot=/ -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-pib/include -I/home1/fzp/anaconda3/lib/python3.6/site-packages/torch/utils/ffi/../../lib/include/TH -I/home1/fzp/anaconda3/li-I/home1/fzp/attention-OCR/warp-ctc-pytorch_bindings/include -I/home1/fzp/anaconda3/include/python3.6m -c build/warpctc_pyto__warp_ctc.o -std=c++11 -fPIC -std=c99 -DWARPCTC_ENABLE_GPU
cc1: warning: command line option ‘-std=c++11’ is valid for C++/ObjC++ but not for C [enabled by default]
gcc -pthread -B /home1/fzp/anaconda3/compiler_compat -Wl,--sysroot=/ -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-pib/include -I/home1/fzp/anaconda3/lib/python3.6/site-packages/torch/utils/ffi/../../lib/include/TH -I/home1/fzp/anaconda3/li-I/home1/fzp/attention-OCR/warp-ctc-pytorch_bindings/include -I/home1/fzp/anaconda3/include/python3.6m -c /home1/fzp/attenti4-3.6/home1/fzp/attention-OCR/warp-ctc-pytorch_bindings/pytorch_binding/src/binding.o -std=c++11 -fPIC -std=c99 -DWARPCTC_EN
cc1plus: warning: command line option ‘-Wstrict-prototypes’ is valid for C/ObjC but not for C++ [enabled by default]
cc1plus: warning: command line option ‘-std=c99’ is valid for C/ObjC but not for C++ [enabled by default]
/home1/fzp/attention-OCR/warp-ctc-pytorch_bindings/pytorch_binding/src/binding.cpp: In function ‘int gpu_ctc(THCudaTensor*,
/home1/fzp/attention-OCR/warp-ctc-pytorch_bindings/pytorch_binding/src/binding.cpp:92:49: error: cannot convert ‘THCudaTensotTensor*, int)’
int probs_size = THFloatTensor_size(probs, 2);
^
/home1/fzp/attention-OCR/warp-ctc-pytorch_bindings/pytorch_binding/src/binding.cpp:105:61: error: invalid conversion from ‘s
void* gpu_workspace = THCudaMalloc(state, gpu_size_bytes);
^
/home1/fzp/attention-OCR/warp-ctc-pytorch_bindings/pytorch_binding/src/binding.cpp:105:61: error: too few arguments to funct
In file included from /home1/fzp/anaconda3/lib/python3.6/site-packages/torch/utils/ffi/../../lib/include/THC/THC.h:4:0,
from /home1/fzp/attention-OCR/warp-ctc-pytorch_bindings/pytorch_binding/src/binding.cpp:9:
/home1/fzp/anaconda3/lib/python3.6/site-packages/torch/utils/ffi/../../lib/include/THC/THCGeneral.h:209:21: note: declared h
THC_API cudaError_t THCudaMalloc(THCState *state, void **ptr, size_t size);
^
error: command 'gcc' failed with exit status 1
经过无数次的查阅资料和调试,终于把坑填平。大家可按照如下步骤完成从头到尾的编译和调用:
1.下载压缩包并解压,或直接git clone源码。
2.运行如下指令进行编译:
mv warp-ctc-pytorch_bindings/ warp-ctc
cd warp-ctc
mkdir build; cd build
cmake ..
make
(如果下载zip,解压后文件名是warp-ctc-pytorch_bindings,需要第一句的改名操作。如果git clone则不需要此操作)
3.按照如下解决方案进行pytorch_bingding/src/binding.cpp的代码段修改。这是造成上述错误的主要原因。(万分感谢jielingTang大神的答案)
1 at 92 line
int probs_size = THCudaTensor_size(state, probs, 2);
2 at l05 lines
void* gpu_workspace;
THCudaMalloc(state, &gpu_workspace, gpu_size_bytes);
4.开始安装:
cd pytorch_binding
python setup.py install
5.添加环境变量:
gedit ./.bashrc
export WARP_CTC_PATH=/home/xxx/warp-ctc/build
验证pytorch中warp-CTC是否可用GPU例子:
cd B:/warp-ctc/pytorch_binding/tests
python test_gpu.py
OK输出:若没有报错,则证明编译及运行成功。
或:
import torch
from torch.autograd import Variable
from warpctc_pytorch import CTCLoss
ctc_loss = CTCLoss()
# expected shape of seqLength x batchSize x alphabet_size
probs = torch.FloatTensor([[[0.1, 0.6, 0.1, 0.1, 0.1], [0.1, 0.1, 0.6, 0.1, 0.1]]]).transpose(0, 1).contiguous()
labels = Variable(torch.IntTensor([1, 2]))
label_sizes = Variable(torch.IntTensor([2]))
probs_sizes = Variable(torch.IntTensor([2]))
probs = Variable(probs, requires_grad=True) # tells autograd to compute gradients for probs
cost = ctc_loss(probs, labels, probs_sizes, label_sizes)
cost.backward()
print('PyTorch bindings for Warp-ctc')
6.将其应用于其他项目中。若某项目存在一py格式文件,存在如下调用方式:
则将warp-ctc/pytorch_binding/build/warpctc_pytorch 目录拷贝至与该py文件同级的目录下。
cp -r ~/warp-ctc/pytorch_binding/build/warpctc_pytorch .
再执行该py文件即可成功。