From 522efcaadb4106dc6e6deff66446d69e90a41371 Mon Sep 17 00:00:00 2001 From: Xinghai Sun Date: Tue, 14 Nov 2017 06:36:30 -0600 Subject: [PATCH 1/3] Initial commit --- LICENSE | 201 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..261eeb9e --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. From d74f4ff3f512f26442533fd4f50884020c1fb022 Mon Sep 17 00:00:00 2001 From: lfchener Date: Thu, 17 Oct 2019 03:59:30 +0000 Subject: [PATCH 2/3] update deepspeech to fluid api --- README.md | 155 ++--- README_cn.md | 214 +++---- cloud/README.md | 63 -- cloud/_init_paths.py | 17 - cloud/pcloud_submit.sh | 29 - cloud/pcloud_train.sh | 46 -- cloud/pcloud_upload_data.sh | 22 - cloud/split_data.py | 41 -- cloud/upload_data.py | 129 ---- data/librispeech/librispeech.py | 8 +- data/noise/chime3_background.py | 3 +- data/voxforge/run_data.sh | 2 +- data/voxforge/voxforge.py | 2 +- data_utils/audio.py | 3 +- data_utils/data.py | 86 ++- data_utils/utility.py | 126 +--- decoders/decoders_deprecated.py | 6 +- deploy/demo_client.py | 26 +- deploy/demo_server.py | 35 +- docs/images/multi_gpu_speedup.png | Bin 156739 -> 211490 bytes examples/aishell/run_data.sh | 2 +- examples/aishell/run_infer.sh | 5 +- examples/aishell/run_infer_golden.sh | 9 +- examples/aishell/run_test.sh | 6 +- examples/aishell/run_test_golden.sh | 8 +- examples/aishell/run_train.sh | 11 +- examples/baidu_en8k/run_infer_golden.sh | 9 +- examples/baidu_en8k/run_test_golden.sh | 9 +- .../deploy_demo/run_english_demo_server.sh | 6 +- examples/librispeech/run_data.sh | 2 +- examples/librispeech/run_infer.sh | 5 +- examples/librispeech/run_infer_golden.sh | 7 +- examples/librispeech/run_test.sh | 6 +- examples/librispeech/run_test_golden.sh | 8 +- examples/librispeech/run_train.sh | 14 +- examples/librispeech/run_tune.sh | 3 +- examples/tiny/run_data.sh | 8 +- examples/tiny/run_infer.sh | 7 +- examples/tiny/run_infer_golden.sh | 7 +- examples/tiny/run_test.sh | 10 +- examples/tiny/run_test_golden.sh | 8 +- examples/tiny/run_train.sh | 17 +- examples/tiny/run_tune.sh | 11 +- infer.py | 40 +- model_utils/model.py | 571 +++++++++++------- model_utils/network.py | 421 ++++++++----- models/aishell/download_model.sh | 6 +- models/baidu_en8k/download_model.sh | 6 +- models/librispeech/download_model.sh | 6 +- requirements.txt | 2 +- test.py | 25 +- tools/profile.sh | 7 +- tools/tune.py | 28 +- train.py | 56 +- utils/error_rate.py | 6 +- 55 files changed, 1061 insertions(+), 1304 deletions(-) delete mode 100644 cloud/README.md delete mode 100644 cloud/_init_paths.py delete mode 100644 cloud/pcloud_submit.sh delete mode 100644 cloud/pcloud_train.sh delete mode 100644 cloud/pcloud_upload_data.sh delete mode 100644 cloud/split_data.py delete mode 100644 cloud/upload_data.py diff --git a/README.md b/README.md index 0dcf8b60..d12f2521 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # DeepSpeech2 on PaddlePaddle -*DeepSpeech2 on PaddlePaddle* is an open-source implementation of end-to-end Automatic Speech Recognition (ASR) engine, based on [Baidu's Deep Speech 2 paper](http://proceedings.mlr.press/v48/amodei16.pdf), with [PaddlePaddle](https://github.com/PaddlePaddle/Paddle) platform. Our vision is to empower both industrial application and academic research on speech recognition, via an easy-to-use, efficient and scalable implementation, including training, inference & testing module, distributed [PaddleCloud](https://github.com/PaddlePaddle/cloud) training, and demo deployment. Besides, several pre-trained models for both English and Mandarin are also released. +*DeepSpeech2 on PaddlePaddle* is an open-source implementation of end-to-end Automatic Speech Recognition (ASR) engine, based on [Baidu's Deep Speech 2 paper](http://proceedings.mlr.press/v48/amodei16.pdf), with [PaddlePaddle](https://github.com/PaddlePaddle/Paddle) platform. Our vision is to empower both industrial application and academic research on speech recognition, via an easy-to-use, efficient and scalable implementation, including training, inference & testing module, and demo deployment. Besides, several pre-trained models for both English and Mandarin are also released. ## Table of Contents - [Installation](#installation) @@ -10,7 +10,6 @@ - [Data Augmentation Pipeline](#data-augmentation-pipeline) - [Inference and Evaluation](#inference-and-evaluation) - [Running in Docker Container](#running-in-docker-container) -- [Distributed Cloud Training](#distributed-cloud-training) - [Hyper-parameters Tuning](#hyper-parameters-tuning) - [Training for Mandarin Language](#training-for-mandarin-language) - [Trying Live Demo with Your Own Voice](#trying-live-demo-with-your-own-voice) @@ -22,13 +21,45 @@ ## Installation -For this project was developed in PaddlePaddle V2 API, which is not maintained officially any more, we only support [running it in Docker container](#running-in-docker-container), instead of building environment from source code. And we are going to release the update to the latest Paddle Fluid API very soon, please keep an eye on this project. +To avoid the trouble of environment setup, [running in Docker container](#running-in-docker-container) is highly recommended. Otherwise follow the guidelines below to install the dependencies manually. + +### Prerequisites +- Python 2.7 only supported +- PaddlePaddle the latest version (please refer to the [Installation Guide](https://www.paddlepaddle.org.cn/documentation/docs/en/1.5/beginners_guide/install/index_en.html)) + +### Setup +- Make sure these libraries or tools installed: `pkg-config`, `flac`, `ogg`, `vorbis`, `boost` and `swig`, e.g. installing them via `apt-get`: + +```bash +sudo apt-get install -y pkg-config libflac-dev libogg-dev libvorbis-dev libboost-dev swig +``` + +or, installing them via `yum`: + +```bash +sudo yum install pkgconfig libogg-devel libvorbis-devel boost-devel +wget https://ftp.osuosl.org/pub/xiph/releases/flac/flac-1.3.1.tar.xz +xz -d flac-1.3.1.tar.xz +tar -xvf flac-1.3.1.tar +cd flac-1.3.1 +./configure +make +make install +``` + +- Run the setup script for the remaining dependencies + +```bash +git clone https://github.com/PaddlePaddle/DeepSpeech.git +cd DeepSpeech +sh setup.sh +``` ## Getting Started Several shell scripts provided in `./examples` will help us to quickly give it a try, for most major modules, including data preparation, model training, case inference and model evaluation, with a few public dataset (e.g. [LibriSpeech](http://www.openslr.org/12/), [Aishell](http://www.openslr.org/33)). Reading these examples will also help you to understand how to make it work with your own data. -Some of the scripts in `./examples` are configured with 8 GPUs. If you don't have 8 GPUs available, please modify `CUDA_VISIBLE_DEVICES` and `--trainer_count`. If you don't have any GPU available, please set `--use_gpu` to False to use CPUs instead. Besides, if out-of-memory problem occurs, just reduce `--batch_size` to fit. +Some of the scripts in `./examples` are configured with 8 GPUs. If you don't have 8 GPUs available, please modify `CUDA_VISIBLE_DEVICES`. If you don't have any GPU available, please set `--use_gpu` to False to use CPUs instead. Besides, if out-of-memory problem occurs, just reduce `--batch_size` to fit. Let's take a tiny sampled subset of [LibriSpeech dataset](http://www.openslr.org/12/) for instance. @@ -45,7 +76,7 @@ Let's take a tiny sampled subset of [LibriSpeech dataset](http://www.openslr.org sh run_data.sh ``` - `run_data.sh` will download dataset, generate manifests, collect normalizer's statistics and build vocabulary. Once the data preparation is done, you will find the data (only part of LibriSpeech) downloaded in `~/.cache/paddle/dataset/speech/libri` and the corresponding manifest files generated in `./data/tiny` as well as a mean stddev file and a vocabulary file. It has to be run for the very first time you run this dataset and is reusable for all further experiments. + `run_data.sh` will download dataset, generate manifests, collect normalizer's statistics and build vocabulary. Once the data preparation is done, you will find the data (only part of LibriSpeech) downloaded in `./dataset/librispeech` and the corresponding manifest files generated in `./data/tiny` as well as a mean stddev file and a vocabulary file. It has to be run for the very first time you run this dataset and is reusable for all further experiments. - Train your own ASR model ```bash @@ -139,20 +170,20 @@ python tools/build_vocab.py --help - Start training from scratch with 8 GPUs: ``` - CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 python train.py --trainer_count 8 + CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 python train.py ``` -- Start training from scratch with 16 CPUs: +- Start training from scratch with CPUs: ``` - python train.py --use_gpu False --trainer_count 16 + python train.py --use_gpu False ``` - Resume training from a checkpoint: ``` CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 \ python train.py \ - --init_model_path CHECKPOINT_PATH_TO_RESUME_FROM + --init_from_pretrain_model CHECKPOINT_PATH_TO_RESUME_FROM ``` For more help on arguments: @@ -162,6 +193,7 @@ python train.py --help ``` or refer to `example/librispeech/run_train.sh`. + ## Data Augmentation Pipeline Data augmentation has often been a highly effective technique to boost the deep learning performance. We augment our speech data by synthesizing new audios with small random perturbation (label-invariant transformation) added upon raw audios. You don't have to do the syntheses on your own, as it is already embedded into the data provider and is done on the fly, randomly for each epoch during training. @@ -206,8 +238,8 @@ A language model is required to improve the decoder's performance. We have prepa ```bash cd models/lm -sh download_lm_en.sh -sh download_lm_ch.sh +bash download_lm_en.sh +bash download_lm_ch.sh ``` If you wish to train your own better language model, please refer to [KenLM](https://github.com/kpu/kenlm) for tutorials. Here we provide some tips to show how we preparing our English and Mandarin language models. You can take it as a reference when you train your own. @@ -216,7 +248,7 @@ If you wish to train your own better language model, please refer to [KenLM](htt The English corpus is from the [Common Crawl Repository](http://commoncrawl.org) and you can download it from [statmt](http://data.statmt.org/ngrams/deduped_en). We use part en.00 to train our English language model. There are some preprocessing steps before training: - * Characters not in \[A-Za-z0-9\s'\] (\s represents whitespace characters) are removed and Arabic numbers are converted to English numbers like 1000 to one thousand. + * Characters not in \['A-Za-z0-9\s'\] (\s represents whitespace characters) are removed and Arabic numbers are converted to English numbers like 1000 to one thousand. * Repeated whitespace characters are squeezed to one and the beginning whitespace characters are removed. Notice that all transcriptions are lowercase, so all characters are converted to lowercase. * Top 400,000 most frequent words are selected to build the vocabulary and the rest are replaced with 'UNKNOWNWORD'. @@ -239,13 +271,13 @@ An inference module caller `infer.py` is provided to infer, decode and visualize - Inference with GPU: ```bash - CUDA_VISIBLE_DEVICES=0 python infer.py --trainer_count 1 + CUDA_VISIBLE_DEVICES=0 python infer.py ``` - Inference with CPUs: ```bash - python infer.py --use_gpu False --trainer_count 12 + python infer.py --use_gpu False ``` We provide two types of CTC decoders: *CTC greedy decoder* and *CTC beam search decoder*. The *CTC greedy decoder* is an implementation of the simple best-path decoding algorithm, selecting at each timestep the most likely token, thus being greedy and locally optimal. The [*CTC beam search decoder*](https://arxiv.org/abs/1408.2873) otherwise utilizes a heuristic breadth-first graph search for reaching a near global optimality; it also requires a pre-trained KenLM language model for better scoring and ranking. The decoder type can be set with argument `--decoding_method`. @@ -264,13 +296,13 @@ To evaluate a model's performance quantitatively, please run: - Evaluation with GPUs: ```bash - CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 python test.py --trainer_count 8 + CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 python test.py ``` - Evaluation with CPUs: ```bash - python test.py --use_gpu False --trainer_count 12 + python test.py --use_gpu False ``` The error rate (default: word error rate; can be set with `--error_rate_type`) will be printed. @@ -293,7 +325,6 @@ The hyper-parameters $\alpha$ (language model weight) and $\beta$ (word insertio ```bash CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 \ python tools/tune.py \ - --trainer_count 8 \ --alpha_from 1.0 \ --alpha_to 3.2 \ --num_alphas 45 \ @@ -332,7 +363,7 @@ Take several steps to launch the Docker image: - Download the Docker image ```bash -nvidia-docker pull paddlepaddle/deep_speech:latest-gpu +nvidia-docker pull hub.baidubce.com/paddlepaddle/deep_speech_fluid:latest-gpu ``` - Clone this repository @@ -344,72 +375,10 @@ git clone https://github.com/PaddlePaddle/DeepSpeech.git - Run the Docker image ```bash -sudo nvidia-docker run -it -v $(pwd)/DeepSpeech:/DeepSpeech paddlepaddle/deep_speech:latest-gpu /bin/bash +sudo nvidia-docker run -it -v $(pwd)/DeepSpeech:/DeepSpeech hub.baidubce.com/paddlepaddle/deep_speech_fluid:latest-gpu /bin/bash ``` Now go back and start from the [Getting Started](#getting-started) section, you can execute training, inference and hyper-parameters tuning similarly in the Docker container. -## Distributed Cloud Training - -We also provide a cloud training module for users to do the distributed cluster training on [PaddleCloud](https://github.com/PaddlePaddle/cloud), to achieve a much faster training speed with multiple machines. To start with this, please first install PaddleCloud client and register a PaddleCloud account, as described in [PaddleCloud Usage](https://github.com/PaddlePaddle/cloud/blob/develop/doc/usage_cn.md#%E4%B8%8B%E8%BD%BD%E5%B9%B6%E9%85%8D%E7%BD%AEpaddlecloud). - -Please take the following steps to submit a training job: - -- Go to directory: - - ```bash - cd cloud - ``` -- Upload data: - - Data must be uploaded to PaddleCloud filesystem to be accessed within a cloud job. `pcloud_upload_data.sh` helps do the data packing and uploading: - - ```bash - sh pcloud_upload_data.sh - ``` - - Given input manifests, `pcloud_upload_data.sh` will: - - - Extract the audio files listed in the input manifests. - - Pack them into a specified number of tar files. - - Upload these tar files to PaddleCloud filesystem. - - Create cloud manifests by replacing local filesystem paths with PaddleCloud filesystem paths. New manifests will be used to inform the cloud jobs of audio files' location and their meta information. - - It should be done only once for the very first time to do the cloud training. Later, the data is kept persisitent on the cloud filesystem and reusable for further job submissions. - - For argument details please refer to [Train DeepSpeech2 on PaddleCloud](https://github.com/PaddlePaddle/DeepSpeech/tree/develop/cloud). - - - Configure training arguments: - - Configure the cloud job parameters in `pcloud_submit.sh` (e.g. `NUM_NODES`, `NUM_GPUS`, `CLOUD_TRAIN_DIR`, `JOB_NAME` etc.) and then configure other hyper-parameters for training in `pcloud_train.sh` (just as what you do for local training). - - For argument details please refer to [Train DeepSpeech2 on PaddleCloud](https://github.com/PaddlePaddle/DeepSpeech/tree/develop/cloud). - - - Submit the job: - - By running: - - ```bash - sh pcloud_submit.sh - ``` - a training job has been submitted to PaddleCloud, with the job name printed to the console. - - - Get training logs - - Run this to list all the jobs you have submitted, as well as their running status: - - ```bash - paddlecloud get jobs - ``` - - Run this, the corresponding job's logs will be printed. - ```bash - paddlecloud logs -n 10000 $REPLACED_WITH_YOUR_ACTUAL_JOB_NAME - ``` - -For more information about the usage of PaddleCloud, please refer to [PaddleCloud Usage](https://github.com/PaddlePaddle/cloud/blob/develop/doc/usage_cn.md#提交任务). - -For more information about the DeepSpeech2 training on PaddleCloud, please refer to -[Train DeepSpeech2 on PaddleCloud](https://github.com/PaddlePaddle/DeepSpeech/tree/develop/cloud). ## Training for Mandarin Language @@ -417,14 +386,13 @@ The key steps of training for Mandarin language are same to that of English lang ## Trying Live Demo with Your Own Voice -Until now, an ASR model is trained and tested qualitatively (`infer.py`) and quantitatively (`test.py`) with existing audio files. But it is not yet tested with your own speech. `deploy/demo_server.py` and `deploy/demo_client.py` helps quickly build up a real-time demo ASR engine with the trained model, enabling you to test and play around with the demo, with your own voice. +Until now, an ASR model is trained and tested qualitatively (`infer.py`) and quantitatively (`test.py`) with existing audio files. But it is not yet tested with your own speech. `deploy/demo_english_server.py` and `deploy/demo_client.py` helps quickly build up a real-time demo ASR engine with the trained model, enabling you to test and play around with the demo, with your own voice. To start the demo's server, please run this in one console: ```bash CUDA_VISIBLE_DEVICES=0 \ python deploy/demo_server.py \ ---trainer_count 1 \ --host_ip localhost \ --host_port 8086 ``` @@ -436,7 +404,7 @@ For example, on MAC OS X: ```bash brew install portaudio pip install pyaudio -pip install pynput +pip install keyboard ``` Then to start the client, please run this in another console: @@ -452,7 +420,7 @@ Now, in the client console, press the `whitespace` key, hold, and start speaking Notice that `deploy/demo_client.py` must be run on a machine with a microphone device, while `deploy/demo_server.py` could be run on one without any audio recording hardware, e.g. any remote server machine. Just be careful to set the `host_ip` and `host_port` argument with the actual accessible IP address and port, if the server and client are running with two separate machines. Nothing should be done if they are running on one single machine. -Please also refer to `examples/mandarin/run_demo_server.sh`, which will first download a pre-trained Mandarin model (trained with 3000 hours of internal speech data) and then start the demo server with the model. With running `examples/mandarin/run_demo_client.sh`, you can speak Mandarin to test it. If you would like to try some other models, just update `--model_path` argument in the script.   +Please also refer to `examples/deploy_demo/run_english_demo_server.sh`, which will first download a pre-trained English model (trained with 3000 hours of internal speech data) and then start the demo server with the model. With running `examples/mandarin/run_demo_client.sh`, you can speak English to test it. If you would like to try some other models, just update `--model_path` argument in the script.   For more help on arguments: @@ -467,10 +435,10 @@ python deploy/demo_client.py --help Language | Model Name | Training Data | Hours of Speech :-----------: | :------------: | :----------: | -------: -English | [LibriSpeech Model](https://deepspeech.bj.bcebos.com/eng_models/librispeech_model.tar.gz) | [LibriSpeech Dataset](http://www.openslr.org/12/) | 960 h -English | [BaiduEN8k Model](https://deepspeech.bj.bcebos.com/demo_models/baidu_en8k_model.tar.gz) | Baidu Internal English Dataset | 8628 h -Mandarin | [Aishell Model](https://deepspeech.bj.bcebos.com/mandarin_models/aishell_model.tar.gz) | [Aishell Dataset](http://www.openslr.org/33/) | 151 h -Mandarin | [BaiduCN1.2k Model](https://deepspeech.bj.bcebos.com/demo_models/baidu_cn1.2k_model.tar.gz) | Baidu Internal Mandarin Dataset | 1204 h +English | [LibriSpeech Model](https://deepspeech.bj.bcebos.com/eng_models/librispeech_model_fluid.tar.gz) | [LibriSpeech Dataset](http://www.openslr.org/12/) | 960 h +English | [BaiduEN8k Model](https://deepspeech.bj.bcebos.com/demo_models/baidu_en8k_model_fluid.tar.gz) | Baidu Internal English Dataset | 8628 h +Mandarin | [Aishell Model](https://deepspeech.bj.bcebos.com/mandarin_models/aishell_model_fluid.tar.gz) | [Aishell Dataset](http://www.openslr.org/33/) | 151 h +Mandarin | [BaiduCN1.2k Model](https://deepspeech.bj.bcebos.com/demo_models/baidu_cn1.2k_model_fluid.tar.gz) | Baidu Internal Mandarin Dataset | 1204 h #### Language Model Released @@ -504,17 +472,16 @@ Baidu Internal Testset | 12.64 #### Acceleration with Multi-GPUs -We compare the training time with 1, 2, 4, 8, 16 Tesla K40m GPUs (with a subset of LibriSpeech samples whose audio durations are between 6.0 and 7.0 seconds). And it shows that a **near-linear** acceleration with multiple GPUs has been achieved. In the following figure, the time (in seconds) cost for training is printed on the blue bars. +We compare the training time with 1, 2, 4, 8 Tesla V100 GPUs (with a subset of LibriSpeech samples whose audio durations are between 6.0 and 7.0 seconds). And it shows that a **near-linear** acceleration with multiple GPUs has been achieved. In the following figure, the time (in seconds) cost for training is printed on the blue bars.
| # of GPU | Acceleration Rate | | -------- | --------------: | | 1 | 1.00 X | -| 2 | 1.97 X | -| 4 | 3.74 X | -| 8 | 6.21 X | -|16 | 10.70 X | +| 2 | 1.98 X | +| 4 | 3.73 X | +| 8 | 6.95 X | `tools/profile.sh` provides such a profiling tool. diff --git a/README_cn.md b/README_cn.md index 06bee58b..dfdc15d3 100644 --- a/README_cn.md +++ b/README_cn.md @@ -1,7 +1,7 @@ -# DeepSpeech2 +# 语音识别: DeepSpeech2 -*DeepSpeech2* 是一个采用[PaddlePaddle](https://github.com/PaddlePaddle/Paddle)平台的端到端自动语音识别(ASR)引擎的开源项目,具体原理请参考这篇论文[Baidu's Deep Speech 2 paper](http://proceedings.mlr.press/v48/amodei16.pdf)。 -我们的愿景是为语音识别在工业应用和学术研究上,提供易于使用、高效和可扩展的工具,包括训练,推理,测试模块,以及分布式的[PaddleCloud](https://github.com/PaddlePaddle/cloud)训练和demo部署。同时,我们还将发布一些预训练好的英语和普通话模型。 +*语音识别: DeepSpeech2*是一个采用[PaddlePaddle](https://github.com/PaddlePaddle/Paddle)平台的端到端自动语音识别(ASR)引擎的开源项目,具体原理参考这篇论文[Baidu's Deep Speech 2 paper](http://proceedings.mlr.press/v48/amodei16.pdf)。 +我们的愿景是为语音识别在工业应用和学术研究上,提供易于使用、高效和可扩展的工具,包括训练,推理,测试模块,以及demo部署。同时,我们还将发布一些预训练好的英语和普通话模型。 ## 目录 - [安装](#安装) @@ -11,7 +11,6 @@ - [数据增强管道](#数据增强管道) - [推断和评价](#推断和评价) - [在Docker容器上运行](#在Docker容器上运行) -- [分布式云训练](#分布式云训练) - [超参数调整](#超参数调整) - [训练汉语语言](#训练汉语语言) - [用自己的声音尝试现场演示](#用自己的声音尝试现场演示) @@ -20,18 +19,49 @@ - [问题和帮助](#问题和帮助) ## 安装 +为了避免环境配置问题,强烈建议在[Docker容器上运行](#在Docker容器上运行),否则请按照下面的指南安装依赖项。 -因该项目基于 PaddlePaddle V2 API 开发,其已不再被官方维护,目前我们仅支持 [在 Docker 容器中运行该项目](#在Docker容器上运行),而不支持从源码构建环境。我们很快会将这个项目升级到最新的 Paddle Fluid API,请保持关注。 +### 前提 +- 只支持Python 2.7 +- PaddlePaddle最新版本(请参考[安装指南](https://www.paddlepaddle.org.cn/start)) + +### 安装 +- 请确保以下库或工具已安装完毕:`pkg-config`, `flac`, `ogg`, `vorbis`, `boost` 和 `swig`, 如可以通过`apt-get`安装: + +```bash +sudo apt-get install -y pkg-config libflac-dev libogg-dev libvorbis-dev libboost-dev swig +``` + +或者,也可以通过`yum`安装: + +```bash +sudo yum install pkgconfig libogg-devel libvorbis-devel boost-devel +wget https://ftp.osuosl.org/pub/xiph/releases/flac/flac-1.3.1.tar.xz +xz -d flac-1.3.1.tar.xz +tar -xvf flac-1.3.1.tar +cd flac-1.3.1 +./configure +make +make install +``` + +- 运行脚本安装其余的依赖项 + +```bash +git clone https://github.com/PaddlePaddle/DeepSpeech.git +cd DeepSpeech +sh setup.sh +``` ## 开始 -`./examples`里的一些shell脚本将帮助我们在一些公开数据集(比如:[LibriSpeech](http://www.openslr.org/12/), [Aishell](http://www.openslr.org/33)) 进行快速尝试,包括了数据准备,模型训练,案例推断和模型评价。阅读这些例子将帮助你理解如何应用你的数据集。 +`./examples`里的一些shell脚本将帮助我们在一些公开数据集(比如:[LibriSpeech](http://www.openslr.org/12/), [Aishell](http://www.openslr.org/33)) 进行快速尝试,包括了数据准备,模型训练,案例推断和模型评价。阅读这些例子将帮助你理解如何使用你的数据集训练模型。 -`./examples`目录中的一些脚本配置使用了8个GPU。如果你没有8个可用的GPU,请修改`CUDA_VISIBLE_DEVICES`和`--trainer_count`。如果你没有可用的GPU,请设置`--use_gpu`为False,这样程序会用CPU代替GPU。另外如果发生内存不足的问题,减小`--batch_size`即可。 +`./examples`目录中的一些脚本配置使用了8个GPU。如果你没有8个可用的GPU,请修改`CUDA_VISIBLE_DEVICES`。如果你没有可用的GPU,请设置`--use_gpu`为False,这样程序会用CPU代替GPU。另外如果发生内存不足的问题,减小`--batch_size`即可。 让我们先看看[LibriSpeech dataset](http://www.openslr.org/12/)小样本集的例子。 -- 转到目录 +- 进到目录 ```bash cd examples/tiny @@ -44,21 +74,21 @@ sh run_data.sh ``` - 运行`run_data.sh`脚本将会下载数据集,产出manifests文件,收集一些归一化需要的统计信息并建立词表。当数据准备完成之后,下载完的数据(仅有LibriSpeech一部分)在`~/.cache/paddle/dataset/speech/libri`中;其对应的manifest文件,均值标准差和词表文件在`./data/tiny`中。在第一次执行的时候一定要执行这个脚本,在接下来所有的实验中我们都会用到这个数据集。 + 运行`run_data.sh`脚本将会下载数据集,产出manifests文件,收集一些归一化需要的统计信息并建立词表。当数据准备完成之后,下载完的数据(仅有LibriSpeech一部分)在`dataset/librispeech`中;其对应的manifest文件,均值标准差和词表文件在`./data/tiny`中。在第一次执行的时候一定要执行这个脚本,在接下来所有的实验中我们都会用到这个数据集。 - 训练你自己的ASR模型 ```bash sh run_train.sh ``` - `run_train.sh`将会启动训练任务,训练日志会打印到stdout,并且模型每个时期(epoch)的检查点都会保存到`./checkpoints/tiny`目录中。这些检查点可以用来恢复训练,推断,评价和部署。 + `run_train.sh`将会启动训练任务,训练日志会打印到终端,并且模型每个epoch的checkpoint都会保存到`./checkpoints/tiny`目录中。这些checkpoint可以用来恢复训练,推断,评价和部署。 - 用已有的模型进行案例推断 ```bash sh run_infer.sh ``` - `run_infer.sh`将会利用训完的模型展现一些(默认10个)样本语音到文本的解码结果。由于当前模型只使用了LibriSpeech一部分数据集训练,因此性能可能不会太好。为了看到更好模型上的表现,你可以下载一个已训练好的模型(用完整的LibriSpeech训练了好几天)来做推断。 + `run_infer.sh`将会利用训练好的模型展现一些(默认10个)样本语音到文本的解码结果。由于当前模型只使用了LibriSpeech一部分数据集训练,因此性能可能不会太好。为了看到更好模型上的表现,你可以下载一个已训练好的模型(用完整的LibriSpeech训练了好几天)来做推断。 ```bash sh run_infer_golden.sh @@ -82,20 +112,20 @@ ### 生成Manifest -*语音识别: DeepSpeech2*接受文本**manifest**文件作为数据接口。manifest文件包含了一系列语音数据,其中每一行代表一个json格式的音频元数据(比如文件路径,描述,时长)。具体格式如下: +*语音识别: DeepSpeech2*接受文本**manifest**文件作为数据接口。manifest文件包含了一系列语音数据,其中每一行代表一个[JSON](http://www.json.org/)格式的音频元数据(比如文件路径,描述,时长)。具体格式如下: ``` {"audio_filepath": "/home/work/.cache/paddle/Libri/134686/1089-134686-0001.flac", "duration": 3.275, "text": "stuff it into you his belly counselled him"} {"audio_filepath": "/home/work/.cache/paddle/Libri/134686/1089-134686-0007.flac", "duration": 4.275, "text": "a cold lucid indifference reigned in his soul"} ``` -如果你要使用自定义数据,你只需要按照以上格式生成自己的manifest文件即可。训练,推断以及其他所有模块都能够根据manifest文件获取到音频数据,包括他们的元数据。 +如果你要使用自定义数据,你只需要按照以上格式生成自己的manifest文件即可。给定manifest文件,训练,推断以及其他所有模块都能够访问到音频数据以及对应的时长和标签数据。 关于如何生成manifest文件,请参考`data/librispeech/librispeech.py`。该脚本将会下载LibriSpeech数据集并生成manifest文件。 ### 计算均值和标准差用于归一化 -为了对音频特征进行z-score归一化(零均值,单位标准差),我们必须预估一些训练样本特征的均值和标准差: +为了对音频特征进行z-score归一化(零均值,单位标准差),我们必须预估训练样本特征的均值和标准差: ```bash python tools/compute_mean_std.py \ @@ -105,11 +135,11 @@ python tools/compute_mean_std.py \ --output_path data/librispeech/mean_std.npz ``` -以上这段代码会计算在`data/librispeech/manifest.train`路径中,2000个随机采样音频剪辑的功率谱特征均值和标准差,并将结果保存在`data/librispeech/mean_std.npz`中,方便以后使用。 +以上这段代码会计算在`data/librispeech/manifest.train`路径中,2000个随机采样的语音频谱特征的均值和标准差,并将结果保存在`data/librispeech/mean_std.npz`中,方便以后使用。 ### 建立词表 -转换录音为索引用于训练,解码,再将一系列索引转换为文本等操作需要一个可能会出现字符集合的词表。`tools/build_vocab.py`脚本将生成这种基于字符的词表。 +我们需要一个包含可能会出现的字符集合的词表来在训练的时候将字符转换成索引,并在解码的时候将索引转换回文本。`tools/build_vocab.py`脚本将生成这种基于字符的词表。 ```bash python tools/build_vocab.py \ @@ -118,7 +148,7 @@ python tools/build_vocab.py \ --manifest_paths data/librispeech/manifest.train ``` -他将`data/librispeech/manifest.train`目录中的所有录音文本写入词表文件`data/librispeeech/eng_vocab.txt`,并且没有词汇截断(`--count_threshold 0`)。 +它将`data/librispeech/manifest.train`目录中的所有录音文本写入词表文件`data/librispeeech/eng_vocab.txt`,并且没有词汇截断(`--count_threshold 0`)。 ### 更多帮助 @@ -137,13 +167,13 @@ python tools/build_vocab.py --help - 开始使用8片GPU训练: ``` - CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 python train.py --trainer_count 8 + CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 python train.py ``` -- 开始使用16片GPU训练: +- 开始使用CPU训练: ``` - python train.py --use_gpu False --trainer_count 16 + python train.py --use_gpu False ``` - 从检查点恢复训练: @@ -151,7 +181,7 @@ python tools/build_vocab.py --help ``` CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 \ python train.py \ - --init_model_path CHECKPOINT_PATH_TO_RESUME_FROM + --init_from_pretrain_model CHECKPOINT_PATH_TO_RESUME_FROM ``` 获得更多帮助: @@ -161,11 +191,12 @@ python train.py --help ``` 或参考 `example/librispeech/run_train.sh`. + ## 数据增强管道 -数据增强是用来提升深度学习性能的非常有效的技术。我们通过在原始音频中添加小随机扰动(标签不变转换)获得新音频来增强我们的语音数据。你不必自己合成,因为数据增强已经嵌入到数据提供者中,能在训练模型时每个epoch中随机的合成音频。 +数据增强是用来提升深度学习性能的非常有效的技术。我们通过在原始音频中添加小的随机扰动(标签不变转换)获得新音频来增强我们的语音数据。你不必自己合成,因为数据增强已经嵌入到数据生成器中并且能够即时完成,在训练模型的每个epoch中随机合成音频。 -目前提供六个可选的增强组件供选择,配置并插入处理流水线。 +目前提供六个可选的增强组件供选择,配置并插入处理过程。 - 音量扰动 - 速度扰动 @@ -195,7 +226,7 @@ python train.py --help 有关其他配置实例,请参考`conf/augmenatation.config.example`. -使用数据增强技术时要小心,由于扩大了训练和测试集的差异,不恰当的增强会对训练模型不利。 +使用数据增强技术时要小心,由于扩大了训练和测试集的差异,不恰当的增强会对训练模型不利,导致训练和预测的差距增大。 ## 推断和评价 @@ -205,18 +236,18 @@ python train.py --help ```bash cd models/lm -sh download_lm_en.sh -sh download_lm_ch.sh +bash download_lm_en.sh +bash download_lm_ch.sh ``` -如果你想训练自己更好的语言模型,请参考[KenLM](https://github.com/kpu/kenlm)获取教程。在这里,我们提供一些技巧来展示我们如何准备我们的英语和普通话模型。开始训练的时候,你可以参考这些技巧。 +如果你想训练自己更好的语言模型,请参考[KenLM](https://github.com/kpu/kenlm)获取教程。在这里,我们提供一些技巧来展示我们如何准备我们的英语和普通话模型。当你训练自己的模型的时候,可以参考这些技巧。 #### 英语语言模型 -英语语料库来自[Common Crawl Repository](http://commoncrawl.org),您可以从[statmt](http://data.statmt.org/ngrams/deduped_en)下载它。我们使用en.00部分来训练我们的英语语言模型。训练前有一些预处理步骤如下: +英语语料库来自[Common Crawl Repository](http://commoncrawl.org),你可以从[statmt](http://data.statmt.org/ngrams/deduped_en)下载它。我们使用en.00部分来训练我们的英语语言模型。训练前有如下的一些预处理过程: - * 不在\[A-Za-z0-9\s'\](\s表示空白字符)中的字符将被删除,阿拉伯数字被转换为英文数字,比如“1000”转换为one thousand。 + * 不在\['A-Za-z0-9\s'\](\s表示空白字符)中的字符将被删除,阿拉伯数字被转换为英文数字,比如“1000”转换为one thousand。 * 重复的空白字符被压缩为一个,并且开始的空白字符将被删除。请注意,所有的录音都是小写字母,因此所有字符都转换为小写字母。 * 选择前40万个最常用的单词来建立词表,其余部分将被替换为“UNKNOWNWORD”。 @@ -224,7 +255,7 @@ sh download_lm_ch.sh #### 普通话语言模型 -与英语语言模型不同的是,普通话语言模型是基于字符的,其中每一位都是中文汉字。我们使用内部语料库来训练发布的汉语语言模型。该语料库包含数十亿汉字。预处理阶段与英语语言模型差别很小,主要步骤包括: +与英语语言模型不同的是,普通话语言模型是基于字符的,其中每一位都是中文汉字。我们使用内部语料库来训练发布的汉语语言模型。该语料库包含数十亿汉字。预处理阶段与英语语言模型有一些小的差别,主要步骤包括: * 删除开始和结尾的空白字符。 * 删除英文标点和中文标点。 @@ -234,18 +265,18 @@ sh download_lm_ch.sh ### 语音到文本推断 -推断模块调用者为`infer.py`,可以用来推断,解码,以及给一些给定音频剪辑进行可视化语音到文本的结果。这有助于对ASR模型的性能进行直观和定性的评估。 +推断模块使用`infer.py`进行调用,可以用来推断,解码,以及输出一些给定音频片段可视化到文本的结果。这有助于对ASR模型的性能进行直观和定性的评估。 - GPU版本的推断: ```bash - CUDA_VISIBLE_DEVICES=0 python infer.py --trainer_count 1 + CUDA_VISIBLE_DEVICES=0 python infer.py ``` - CPU版本的推断: ```bash - python infer.py --use_gpu False --trainer_count 12 + python infer.py --use_gpu False ``` 我们提供两种类型的CTC解码器:*CTC贪心解码器*和*CTC波束搜索解码器*。*CTC贪心解码器*是简单的最佳路径解码算法的实现,在每个时间步选择最可能的字符,因此是贪心的并且是局部最优的。[*CTC波束搜索解码器*](https://arxiv.org/abs/1408.2873)另外使用了启发式广度优先图搜索以达到近似全局最优; 它也需要预先训练的KenLM语言模型以获得更好的评分和排名。解码器类型可以用参数`--decoding_method`设置。 @@ -261,16 +292,16 @@ python infer.py --help 要定量评估模型的性能,请运行: -- 带GPU版本评估 +- GPU版本评估 ```bash - CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 python test.py --trainer_count 8 + CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 python test.py ``` - CPU版本评估 ```bash - python test.py --use_gpu False --trainer_count 12 + python test.py --use_gpu False ``` 错误率(默认:误字率;可以用--error_rate_type设置)将被打印出来。 @@ -286,14 +317,13 @@ python test.py --help [*CTC波束搜索解码器*](https://arxiv.org/abs/1408.2873)的超参数$\alpha$(语言模型权重)和$\beta$(单词插入权重)对解码器的性能有非常显著的影响。当声学模型更新时,最好在验证集上重新调整它们。 -`tools/tune.py`会进行2维网格查找超参数$\alpha$和$\beta$。您必须提供$\alpha$和$\beta$的范围,以及尝试的次数。 +`tools/tune.py`会进行2维网格查找超参数$\alpha$和$\beta$。你必须提供$\alpha$和$\beta$的范围,以及尝试的次数。 - 带GPU版的调整: ```bash CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 \ python tools/tune.py \ - --trainer_count 8 \ --alpha_from 1.0 \ --alpha_to 3.2 \ --num_alphas 45 \ @@ -307,14 +337,14 @@ python test.py --help ```bash python tools/tune.py --use_gpu False ``` -网格搜索将会在超参数空间的每个点处打印出WER(误字率)或者CER(字符错误率),并且可选择绘出误差曲面。合适的超参数范围应包括WER/CER误差表面的全局最小值,如下图所示。 +网格搜索将会在超参数空间的每个点处打印出WER(误字率)或者CER(字符错误率),并且可绘出误差曲面。一个合适的超参数范围应包括WER/CER误差表面的全局最小值,如下图所示。


调整LibriSpeech的dev-clean集合的误差曲面示例

-通常,如图所示,语言模型权重($\alpha$)的变化显著影响CTC波束搜索解码器的性能。更好的方法是首先调整多批数据(可指定数量)以找出适当的超参数范围,然后更改为整个验证集以进行精确调整。 +通常,如图所示,语言模型权重($\alpha$)的变化显著影响CTC波束搜索解码器的性能。更好的方法是首先调整多批数据(可指定数量)以找出适当的超参数范围,然后更改为完整的验证集以进行精确调整。 调整之后,您可以在推理和评价模块中重置$\alpha$和$\beta$,以检查它们是否真的有助于提高ASR性能。更多帮助如下: @@ -325,14 +355,14 @@ python tune.py --help ## 在Docker容器上运行 -Docker是一个开源工具,用于在孤立的环境中构建,发布和运行分布式应用程序。此项目的Docker镜像已在[hub.docker.com](https://hub.docker.com)中提供,并安装了所有依赖项,其中包括预先构建的PaddlePaddle,CTC解码器以及其他必要的Python和第三方库。这个Docker映像需要NVIDIA GPU的支持,所以请确保它的可用性并已完成[nvidia-docker](https://github.com/NVIDIA/nvidia-docker)的安装。 +Docker是一个开源工具,用于在孤立的环境中构建、发布和运行分布式应用程序。此项目的Docker镜像已在[hub.docker.com](https://hub.docker.com)中提供,并安装了所有依赖项,其中包括预先构建的PaddlePaddle,CTC解码器以及其他必要的Python和第三方库。这个Docker映像需要NVIDIA GPU的支持,所以请确保它的可用性并已完成[nvidia-docker](https://github.com/NVIDIA/nvidia-docker)的安装。 采取以下步骤来启动Docker镜像: - 下载Docker镜像 ```bash -nvidia-docker pull paddlepaddle/deep_speech:latest-gpu +nvidia-docker pull hub.baidubce.com/paddlepaddle/deep_speech_fluid:latest-gpu ``` - git clone这个资源库 @@ -344,90 +374,25 @@ git clone https://github.com/PaddlePaddle/DeepSpeech.git - 运行Docker镜像 ```bash -sudo nvidia-docker run -it -v $(pwd)/DeepSpeech:/DeepSpeech paddlepaddle/deep_speech:latest-gpu /bin/bash +sudo nvidia-docker run -it -v $(pwd)/DeepSpeech:/DeepSpeech hub.baidubce.com/paddlepaddle/deep_speech_fluid:latest-gpu /bin/bash ``` 现在返回并从[开始](#开始)部分开始,您可以在Docker容器中同样执行模型训练,推断和超参数调整。 -## 分布式云训练 - -我们还为用户提供云训练模块[PaddleCloud](https://github.com/PaddlePaddle/cloud)以便用户进行集群训练,利用多台机器达到更快的训练速度。首先,请按照[PaddleCloud用法](https://github.com/PaddlePaddle/cloud/blob/develop/doc/usage_cn.md#%E4%B8%8B%E8%BD%BD%E5%B9%B6%E9%85%8D%E7%BD%AEpaddlecloud)安装PaddleCloud客户端并注册PaddleCloud账户。 - -请按照以下步骤提交训练任务: - -- 转到目录: - - ```bash - cd cloud - ``` -- 上传数据: - - 数据必须上传到PaddleCloud文件系统才能在云作业中访问。`pcloud_upload_data.sh`负责进行数据打包和上传: - - ```bash - sh pcloud_upload_data.sh - ``` - - 给定manifest文件,`pcloud_upload_data.sh`会进行以下处理: - - - 提取输入清单中列出的音频文件。 - - 将它们打包成指定数量的tar文件。 - - 将这些tar文件上传到PaddleCloud文件系统。 - - 通过用PaddleCloud文件系统路径替换本地文件系统路径来创建云manifest文件。云作业将通过新的manifest文件获取到音频文件的位置及其元信息。 - - 对于云训练模型来说以上步骤只需做一次。之后这些数据会在云文件系统上保持不变,并可在之后的任务中反复使用。 - - 有关参数的详细信息,请参考[在PaddleCloud上训练DeepSpeech2](https://github.com/PaddlePaddle/DeepSpeech/tree/develop/cloud)。 - - - 配置训练参数 - - 在`pcloud_submit.sh`中配置云任务参数(例如`NUM_NODES`,`NUM_GPUS`,`CLOUD_TRAIN_DIR`,`JOB_NAME`等),然后在`pcloud_train.sh`中配置其他的超参数训练(和本地训练一样)。 - - 有关参数的详细信息,请参阅[在PaddleCloud上训练DeepSpeech2](https://github.com/PaddlePaddle/DeepSpeech/tree/develop/cloud)。 - - - - 提交任务 - - 运行: - - ```bash - sh pcloud_submit.sh - ``` - 一个训练任务已经提交给PaddleCloud,并将任务名输出到控制台。 - - - 获取训练日志 - - 执行以下命令以列出你提交的所有任务以及它们的运行状态: - - ```bash - paddlecloud get jobs - ``` - - 运行此操作,将打印相应的任务日志。 - - ```bash - paddlecloud logs -n 10000 $REPLACED_WITH_YOUR_ACTUAL_JOB_NAME - ``` - -有关PaddleCloud用法的更多信息,请参阅[PaddleCloud用法](https://github.com/PaddlePaddle/cloud/blob/develop/doc/usage_cn.md#提交任务)。 - -有关PaddleCloud的DeepSpeech2训练的更多信息,请参阅 -[Train DeepSpeech2 on PaddleCloud](https://github.com/PaddlePaddle/DeepSpeech/tree/develop/cloud). ## 训练普通话语言 -普通话语言训练与英语训练的关键步骤相同,我们提供了一个```examples/aishell```中Aishell的普通话训练例子。如上所述,请执行```sh run_data.sh```, ```sh run_train.sh```, ```sh run_test.sh```和```sh run_infer.sh```做相应的数据准备,训练,测试和推断。我们还准备了一个预训练过的模型(执行./models/aishell/download_model.sh下载)供用户使用```run_infer_golden.sh```和```run_test_golden.sh```来。请注意,与英语语言模型不同,普通话语言模型是基于汉字的,请运行```tools/tune.py```来查找最佳设置。 +普通话语言训练与英语训练的关键步骤相同,我们提供了一个使用Aishell进行普通话训练的例子```examples/aishell```。如上所述,请执行```sh run_data.sh```, ```sh run_train.sh```, ```sh run_test.sh```和```sh run_infer.sh```做相应的数据准备,训练,测试和推断。我们还准备了一个预训练过的模型(执行./models/aishell/download_model.sh下载)供用户使用```run_infer_golden.sh```和```run_test_golden.sh```来。请注意,与英语语言模型不同,普通话语言模型是基于汉字的,请运行```tools/tune.py```来查找最佳设置。 ##用自己的声音尝试现场演示 -到目前为止,一个ASR模型已经训练完毕,并且进行了定性测试(`infer.py`)和用现有的音频文件进行定量测试(`test.py`)。但目前还没有用你自己的声音进行测试。`deploy/demo_server.py`和`deploy/demo_client.py`能够快速构建一个利用训完的模型,对ASR引擎进行实时演示系统,使你能够用自己的语音测试和演示。 +到目前为止,一个ASR模型已经训练完毕,并且用现有的音频文件进行了定性测试(`infer.py`)和定量测试(`test.py`)。但目前还没有用你自己的声音进行测试。`deploy/demo_english_server.py`和`deploy/demo_client.py`能够快速构建一个利用已训练好的模型对ASR引擎进行实时演示的系统,使你能够用自己的语音测试和演示。 要启动演示服务,请在控制台中运行: ```bash CUDA_VISIBLE_DEVICES=0 \ python deploy/demo_server.py \ ---trainer_count 1 \ --host_ip localhost \ --host_port 8086 ``` @@ -439,7 +404,7 @@ python deploy/demo_server.py \ ```bash brew install portaudio pip install pyaudio -pip install pynput +pip install keyboard ``` 然后启动客户端,请在另一个控制台中运行: @@ -451,11 +416,11 @@ python -u deploy/demo_client.py \ --host_port 8086 ``` -现在,在客户端控制台中,按下`whitespace`键,按住并开始讲话。讲话完毕请释放该键以让控制台中显示的语音到文本结果。要退出客户端,只需按`ESC`键。 +现在,在客户端控制台中,按下`空格`键,按住并开始讲话。讲话完毕请释放该键以让控制台中显示语音的文本结果。要退出客户端,只需按`ESC`键。 请注意,`deploy/demo_client.py`必须在带麦克风设备的机器上运行,而`deploy/demo_server.py`可以在没有任何录音硬件的情况下运行,例如任何远程服务器机器。如果服务器和客户端使用两台独立的机器运行,只需要注意将`host_ip`和`host_port`参数设置为实际可访问的IP地址和端口。如果它们在单台机器上运行,则不用作任何处理。 -请参考`examples/mandarin/run_demo_server.sh`,它将首先下载一个预先训练过的普通话模型(用3000小时的内部语音数据训练),然后用模型启动演示服务器。通过运行`examples/mandarin/run_demo_client.sh`,你可以说普通话来测试它。如果您想尝试其他模型,只需更新脚本中的`--model_path`参数即可。 +请参考`examples/deploy_demo/run_english_demo_server.sh`,它将首先下载一个预先训练过的英语模型(用3000小时的内部语音数据训练),然后用模型启动演示服务器。通过运行`examples/mandarin/run_demo_client.sh`,你可以说英语来测试它。如果您想尝试其他模型,只需更新脚本中的`--model_path`参数即可。 获得更多帮助: @@ -470,10 +435,10 @@ python deploy/demo_client.py --help 语种 | 模型名 | 训练数据 | 语音时长 :-----------: | :------------: | :----------: | -------: -English | [LibriSpeech Model](https://deepspeech.bj.bcebos.com/eng_models/librispeech_model.tar.gz) | [LibriSpeech Dataset](http://www.openslr.org/12/) | 960 h -English | [BaiduEN8k Model](https://deepspeech.bj.bcebos.com/demo_models/baidu_en8k_model.tar.gz) | Baidu Internal English Dataset | 8628 h -Mandarin | [Aishell Model](https://deepspeech.bj.bcebos.com/mandarin_models/aishell_model.tar.gz) | [Aishell Dataset](http://www.openslr.org/33/) | 151 h -Mandarin | [BaiduCN1.2k Model](https://deepspeech.bj.bcebos.com/demo_models/baidu_cn1.2k_model.tar.gz) | Baidu Internal Mandarin Dataset | 1204 h +English | [LibriSpeech Model](https://deepspeech.bj.bcebos.com/eng_models/librispeech_model_fluid.tar.gz) | [LibriSpeech Dataset](http://www.openslr.org/12/) | 960 h +English | [BaiduEN8k Model](https://deepspeech.bj.bcebos.com/demo_models/baidu_en8k_model_fluid.tar.gz) | Baidu Internal English Dataset | 8628 h +Mandarin | [Aishell Model](https://deepspeech.bj.bcebos.com/mandarin_models/aishell_model_fluid.tar.gz) | [Aishell Dataset](http://www.openslr.org/33/) | 151 h +Mandarin | [BaiduCN1.2k Model](https://deepspeech.bj.bcebos.com/demo_models/baidu_cn1.2k_model_fluid.tar.gz) | Baidu Internal Mandarin Dataset | 1204 h #### 语言模型发布 @@ -483,9 +448,9 @@ Mandarin | [BaiduCN1.2k Model](https://deepspeech.bj.bcebos.com/demo_models/baid [Mandarin LM Small](https://deepspeech.bj.bcebos.com/zh_lm/zh_giga.no_cna_cmn.prune01244.klm) | Baidu Internal Corpus | Char-based | 2.8 GB | Pruned with 0 1 2 4 4;
About 0.13 billion n-grams;
'probing' binary with default settings [Mandarin LM Large](https://deepspeech.bj.bcebos.com/zh_lm/zhidao_giga.klm) | Baidu Internal Corpus | Char-based | 70.4 GB | No Pruning;
About 3.7 billion n-grams;
'probing' binary with default settings -## 实验和基准 +## 实验和baseline -#### 英语模型的基准测试结果(字错误率) +#### 英语模型的baseline测试结果(字错误率) 测试集 | LibriSpeech Model | BaiduEN8K Model :--------------------- | ---------------: | -------------------: @@ -500,7 +465,7 @@ Baidu Internal Testset  |   40.75 |   8.48 为了在VoxForge数据上重现基准测试结果,我们提供了一个脚本来下载数据并生成VoxForge方言manifest文件。请到```data/voxforge```执行````run_data.sh```来获取VoxForge方言manifest文件。请注意,VoxForge数据可能会持续更新,生成的清单文件可能与我们评估的清单文件有所不同。 -#### 普通话模型的基准测试结果(字符错误率) +#### 普通话模型的baseline测试结果(字符错误率) 测试集 | BaiduCN1.2k Model :--------------------- | -------------------: @@ -508,17 +473,16 @@ Baidu Internal Testset | 12.64 #### 多GPU加速 -我们对1,2,4,8,16个Tesla K40m GPU的训练时间(LibriSpeech样本的子集,其音频持续时间介于6.0和7.0秒之间)进行比较。它表明,已经实现了具有多个GPU的**近线性**加速。在下图中,训练的时间(以秒为单位)显示在蓝色条上。 +我们对1,2,4,8个Tesla V100 GPU的训练时间(LibriSpeech样本的子集,其音频持续时间介于6.0和7.0秒之间)进行比较。它表明,已经实现了具有多个GPU的**近线性**加速。在下图中,训练的时间(以秒为单位)显示在蓝色条上。
| # of GPU | 加速比 | | -------- | --------------: | | 1 | 1.00 X | -| 2 | 1.97 X | -| 4 | 3.74 X | -| 8 | 6.21 X | -|16 | 10.70 X | +| 2 | 1.98 X | +| 4 | 3.73 X | +| 8 | 6.95 X | `tools/profile.sh`提供了上述分析工具. diff --git a/cloud/README.md b/cloud/README.md deleted file mode 100644 index a5be1c42..00000000 --- a/cloud/README.md +++ /dev/null @@ -1,63 +0,0 @@ -# Train DeepSpeech2 on PaddleCloud - ->Note: ->Please make sure [PaddleCloud Client](https://github.com/PaddlePaddle/cloud/blob/develop/doc/usage_cn.md#%E4%B8%8B%E8%BD%BD%E5%B9%B6%E9%85%8D%E7%BD%AEpaddlecloud) has be installed and current directory is `deep_speech_2/cloud/` - -## Step 1: Upload Data - -Provided with several input manifests, `pcloud_upload_data.sh` will pack and upload all the containing audio files to PaddleCloud filesystem, and also generate some corresponding manifest files with updated cloud paths. - -Please modify the following arguments in `pcloud_upload_data.sh`: - -- `IN_MANIFESTS`: Paths (in local filesystem) of manifest files containing the audio files to be uploaded. Multiple paths can be concatenated with a whitespace delimeter. -- `OUT_MANIFESTS`: Paths (in local filesystem) to write the updated output manifest files to. Multiple paths can be concatenated with a whitespace delimeter. The values of `audio_filepath` in the output manifests are updated with cloud filesystem paths. -- `CLOUD_DATA_DIR`: Directory (in PaddleCloud filesystem) to upload the data to. Don't forget to replace `USERNAME` in the default directory and make sure that you have the permission to write it. -- `NUM_SHARDS`: Number of data shards / parts (in tar files) to be generated when packing and uploading data. Smaller `num_shards` requires larger temoporal local disk space for packing data. - -By running: - -``` -sh pcloud_upload_data.sh -``` -all the audio files will be uploaded to PaddleCloud filesystem, and you will get modified manifests files in `OUT_MANIFESTS`. - -You have to take this step only once, in the very first time you do the cloud training. Later on, the data is persisitent on the cloud filesystem and reusable for further job submissions. - -## Step 2: Configure Training - -Configure cloud training arguments in `pcloud_submit.sh`, with the following arguments: - -- `TRAIN_MANIFEST`: Manifest filepath (in local filesystem) for training. Notice that the`audio_filepath` should be in cloud filesystem, like those generated by `pcloud_upload_data.sh`. -- `DEV_MANIFEST`: Manifest filepath (in local filesystem) for validation. -- `CLOUD_MODEL_DIR`: Directory (in PaddleCloud filesystem) to save the model parameters (checkpoints). Don't forget to replace `USERNAME` in the default directory and make sure that you have the permission to write it. -- `BATCH_SIZE`: Training batch size for a single node. -- `NUM_GPU`: Number of GPUs allocated for a single node. -- `NUM_NODE`: Number of nodes (machines) allocated for this job. -- `IS_LOCAL`: Set to False to enable parameter server, if using multiple nodes. - -Configure other training hyper-parameters in `pcloud_train.sh` as you wish, just as what you can do in local training. - -By running: - -``` -sh pcloud_submit.sh -``` -you submit a training job to PaddleCloud. And you will see the job name when the submission is done. - - -## Step 3 Get Job Logs - -Run this to list all the jobs you have submitted, as well as their running status: - -``` -paddlecloud get jobs -``` - -Run this, the corresponding job's logs will be printed. -``` -paddlecloud logs -n 10000 $REPLACED_WITH_YOUR_ACTUAL_JOB_NAME -``` - -## More Help - -For more information about the usage of PaddleCloud, please refer to [PaddleCloud Usage](https://github.com/PaddlePaddle/cloud/blob/develop/doc/usage_cn.md#提交任务). diff --git a/cloud/_init_paths.py b/cloud/_init_paths.py deleted file mode 100644 index 3305d748..00000000 --- a/cloud/_init_paths.py +++ /dev/null @@ -1,17 +0,0 @@ -"""Set up paths for DS2""" -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -import os.path -import sys - - -def add_path(path): - if path not in sys.path: - sys.path.insert(0, path) - - -this_dir = os.path.dirname(__file__) -proj_path = os.path.join(this_dir, '..') -add_path(proj_path) diff --git a/cloud/pcloud_submit.sh b/cloud/pcloud_submit.sh deleted file mode 100644 index 99e458db..00000000 --- a/cloud/pcloud_submit.sh +++ /dev/null @@ -1,29 +0,0 @@ -#! /usr/bin/env bash - -TRAIN_MANIFEST="cloud/cloud_manifests/cloud.manifest.train" -DEV_MANIFEST="cloud/cloud_manifests/cloud.manifest.dev" -CLOUD_MODEL_DIR="./checkpoints" -BATCH_SIZE=512 -NUM_GPU=8 -NUM_NODE=1 -IS_LOCAL="True" - -JOB_NAME=deepspeech-`date +%Y%m%d%H%M%S` -DS2_PATH=${PWD%/*} -cp -f pcloud_train.sh ${DS2_PATH} - -paddlecloud submit \ --image bootstrapper:5000/paddlepaddle/pcloud_ds2:latest \ --jobname ${JOB_NAME} \ --cpu ${NUM_GPU} \ --gpu ${NUM_GPU} \ --memory 64Gi \ --parallelism ${NUM_NODE} \ --pscpu 1 \ --pservers 1 \ --psmemory 64Gi \ --passes 1 \ --entry "sh pcloud_train.sh ${TRAIN_MANIFEST} ${DEV_MANIFEST} ${CLOUD_MODEL_DIR} ${NUM_GPU} ${BATCH_SIZE} ${IS_LOCAL}" \ -${DS2_PATH} - -rm ${DS2_PATH}/pcloud_train.sh diff --git a/cloud/pcloud_train.sh b/cloud/pcloud_train.sh deleted file mode 100644 index d0c47dec..00000000 --- a/cloud/pcloud_train.sh +++ /dev/null @@ -1,46 +0,0 @@ -#! /usr/bin/env bash - -TRAIN_MANIFEST=$1 -DEV_MANIFEST=$2 -MODEL_PATH=$3 -NUM_GPU=$4 -BATCH_SIZE=$5 -IS_LOCAL=$6 - -python ./cloud/split_data.py \ ---in_manifest_path=${TRAIN_MANIFEST} \ ---out_manifest_path='/local.manifest.train' - -python ./cloud/split_data.py \ ---in_manifest_path=${DEV_MANIFEST} \ ---out_manifest_path='/local.manifest.dev' - -mkdir ./logs - -python -u train.py \ ---batch_size=${BATCH_SIZE} \ ---trainer_count=${NUM_GPU} \ ---num_passes=200 \ ---num_proc_data=${NUM_GPU} \ ---num_conv_layers=2 \ ---num_rnn_layers=3 \ ---rnn_layer_size=2048 \ ---num_iter_print=100 \ ---learning_rate=5e-4 \ ---max_duration=27.0 \ ---min_duration=0.0 \ ---use_sortagrad=True \ ---use_gru=False \ ---use_gpu=True \ ---is_local=${IS_LOCAL} \ ---share_rnn_weights=True \ ---train_manifest='/local.manifest.train' \ ---dev_manifest='/local.manifest.dev' \ ---mean_std_path='data/librispeech/mean_std.npz' \ ---vocab_path='data/librispeech/vocab.txt' \ ---output_model_dir='./checkpoints' \ ---output_model_dir=${MODEL_PATH} \ ---augment_conf_path='conf/augmentation.config' \ ---specgram_type='linear' \ ---shuffle_method='batch_shuffle_clipped' \ -2>&1 | tee ./logs/train.log diff --git a/cloud/pcloud_upload_data.sh b/cloud/pcloud_upload_data.sh deleted file mode 100644 index 71bb4af1..00000000 --- a/cloud/pcloud_upload_data.sh +++ /dev/null @@ -1,22 +0,0 @@ -#! /usr/bin/env bash - -mkdir cloud_manifests - -IN_MANIFESTS="../data/librispeech/manifest.train ../data/librispeech/manifest.dev-clean ../data/librispeech/manifest.test-clean" -OUT_MANIFESTS="cloud_manifests/cloud.manifest.train cloud_manifests/cloud.manifest.dev cloud_manifests/cloud.manifest.test" -CLOUD_DATA_DIR="/pfs/dlnel/home/USERNAME/deepspeech2/data/librispeech" -NUM_SHARDS=50 - -python upload_data.py \ ---in_manifest_paths ${IN_MANIFESTS} \ ---out_manifest_paths ${OUT_MANIFESTS} \ ---cloud_data_dir ${CLOUD_DATA_DIR} \ ---num_shards ${NUM_SHARDS} - -if [ $? -ne 0 ] -then - echo "Upload Data Failed!" - exit 1 -fi - -echo "All Done." diff --git a/cloud/split_data.py b/cloud/split_data.py deleted file mode 100644 index 3496d52b..00000000 --- a/cloud/split_data.py +++ /dev/null @@ -1,41 +0,0 @@ -"""This tool is used for splitting data into each node of -paddlecloud. This script should be called in paddlecloud. -""" -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -import os -import json -import argparse - -parser = argparse.ArgumentParser(description=__doc__) -parser.add_argument( - "--in_manifest_path", - type=str, - required=True, - help="Input manifest path for all nodes.") -parser.add_argument( - "--out_manifest_path", - type=str, - required=True, - help="Output manifest file path for current node.") -args = parser.parse_args() - - -def split_data(in_manifest_path, out_manifest_path): - with open("/trainer_id", "r") as f: - trainer_id = int(f.readline()[:-1]) - with open("/trainer_count", "r") as f: - trainer_count = int(f.readline()[:-1]) - - out_manifest = [] - for index, json_line in enumerate(open(in_manifest_path, 'r')): - if (index % trainer_count) == trainer_id: - out_manifest.append("%s\n" % json_line.strip()) - with open(out_manifest_path, 'w') as f: - f.writelines(out_manifest) - - -if __name__ == '__main__': - split_data(args.in_manifest_path, args.out_manifest_path) diff --git a/cloud/upload_data.py b/cloud/upload_data.py deleted file mode 100644 index 9973f8c7..00000000 --- a/cloud/upload_data.py +++ /dev/null @@ -1,129 +0,0 @@ -"""This script is for uploading data for DeepSpeech2 training on paddlecloud. - -Steps: -1. Read original manifests and extract local sound files. -2. Tar all local sound files into multiple tar files and upload them. -3. Modify original manifests with updated paths in cloud filesystem. -""" -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -import json -import os -import tarfile -import sys -import argparse -import shutil -from subprocess import call -import _init_paths -from data_utils.utils import read_manifest - -parser = argparse.ArgumentParser(description=__doc__) -parser.add_argument( - "--in_manifest_paths", - default=[ - "../datasets/manifest.train", "../datasets/manifest.dev", - "../datasets/manifest.test" - ], - type=str, - nargs='+', - help="Local filepaths of input manifests to load, pack and upload." - "(default: %(default)s)") -parser.add_argument( - "--out_manifest_paths", - default=[ - "./cloud.manifest.train", "./cloud.manifest.dev", - "./cloud.manifest.test" - ], - type=str, - nargs='+', - help="Local filepaths of modified manifests to write to. " - "(default: %(default)s)") -parser.add_argument( - "--cloud_data_dir", - required=True, - type=str, - help="Destination directory on paddlecloud to upload data to.") -parser.add_argument( - "--num_shards", - default=10, - type=int, - help="Number of parts to split data to. (default: %(default)s)") -parser.add_argument( - "--local_tmp_dir", - default="./tmp/", - type=str, - help="Local directory for storing temporary data. (default: %(default)s)") -args = parser.parse_args() - - -def upload_data(in_manifest_path_list, out_manifest_path_list, local_tmp_dir, - upload_tar_dir, num_shards): - """Extract and pack sound files listed in the manifest files into multple - tar files and upload them to padldecloud. Besides, generate new manifest - files with updated paths in paddlecloud. - """ - # compute total audio number - total_line = 0 - for manifest_path in in_manifest_path_list: - with open(manifest_path, 'r') as f: - total_line += len(f.readlines()) - line_per_tar = (total_line // num_shards) + 1 - - # pack and upload shard by shard - line_count, tar_file = 0, None - for manifest_path, out_manifest_path in zip(in_manifest_path_list, - out_manifest_path_list): - manifest = read_manifest(manifest_path) - out_manifest = [] - for json_data in manifest: - sound_filepath = json_data['audio_filepath'] - sound_filename = os.path.basename(sound_filepath) - if line_count % line_per_tar == 0: - if tar_file != None: - tar_file.close() - pcloud_cp(tar_path, upload_tar_dir) - os.remove(tar_path) - tar_name = 'part-%s-of-%s.tar' % ( - str(line_count // line_per_tar).zfill(5), - str(num_shards).zfill(5)) - tar_path = os.path.join(local_tmp_dir, tar_name) - tar_file = tarfile.open(tar_path, 'w') - tar_file.add(sound_filepath, arcname=sound_filename) - line_count += 1 - json_data['audio_filepath'] = "tar:%s#%s" % ( - os.path.join(upload_tar_dir, tar_name), sound_filename) - out_manifest.append("%s\n" % json.dumps(json_data)) - with open(out_manifest_path, 'w') as f: - f.writelines(out_manifest) - pcloud_cp(out_manifest_path, upload_tar_dir) - tar_file.close() - pcloud_cp(tar_path, upload_tar_dir) - os.remove(tar_path) - - -def pcloud_mkdir(dir): - """Make directory in PaddleCloud filesystem. - """ - if call(['paddlecloud', 'mkdir', dir]) != 0: - raise IOError("PaddleCloud mkdir failed: %s." % dir) - - -def pcloud_cp(src, dst): - """Copy src from local filesytem to dst in PaddleCloud filesystem, - or downlowd src from PaddleCloud filesystem to dst in local filesystem. - """ - if call(['paddlecloud', 'cp', src, dst]) != 0: - raise IOError("PaddleCloud cp failed: from [%s] to [%s]." % (src, dst)) - - -if __name__ == '__main__': - if not os.path.exists(args.local_tmp_dir): - os.makedirs(args.local_tmp_dir) - pcloud_mkdir(args.cloud_data_dir) - - upload_data(args.in_manifest_paths, args.out_manifest_paths, - args.local_tmp_dir, args.cloud_data_dir, args.num_shards) - - shutil.rmtree(args.local_tmp_dir) diff --git a/data/librispeech/librispeech.py b/data/librispeech/librispeech.py index 9a8e1c28..07cc0933 100644 --- a/data/librispeech/librispeech.py +++ b/data/librispeech/librispeech.py @@ -16,6 +16,7 @@ import argparse import soundfile import json import codecs +import io from data_utils.utility import download, unpack URL_ROOT = "http://www.openslr.org/resources/12" @@ -68,12 +69,11 @@ def create_manifest(data_dir, manifest_path): filename for filename in filelist if filename.endswith('trans.txt') ] if len(text_filelist) > 0: - text_filepath = os.path.join(data_dir, subfolder, text_filelist[0]) - for line in open(text_filepath): + text_filepath = os.path.join(subfolder, text_filelist[0]) + for line in io.open(text_filepath, encoding="utf8"): segments = line.strip().split() text = ' '.join(segments[1:]).lower() - audio_filepath = os.path.join(data_dir, subfolder, - segments[0] + '.flac') + audio_filepath = os.path.join(subfolder, segments[0] + '.flac') audio_data, samplerate = soundfile.read(audio_filepath) duration = float(len(audio_data)) / samplerate json_lines.append( diff --git a/data/noise/chime3_background.py b/data/noise/chime3_background.py index f79ca733..1aa7f8df 100644 --- a/data/noise/chime3_background.py +++ b/data/noise/chime3_background.py @@ -16,6 +16,7 @@ import zipfile import argparse import soundfile import json +import io from paddle.v2.dataset.common import md5file DATA_HOME = os.path.expanduser('~/.cache/paddle/dataset/speech') @@ -88,7 +89,7 @@ def create_manifest(data_dir, manifest_path): 'duration': duration, 'text': '' })) - with open(manifest_path, 'w') as out_file: + with io.open(manifest_path, mode='w', encoding='utf8') as out_file: for line in json_lines: out_file.write(line + '\n') diff --git a/data/voxforge/run_data.sh b/data/voxforge/run_data.sh index c6ff7111..0276744a 100644 --- a/data/voxforge/run_data.sh +++ b/data/voxforge/run_data.sh @@ -3,7 +3,7 @@ # download data, generate manifests PYTHONPATH=../../:$PYTHONPATH python voxforge.py \ --manifest_prefix='./manifest' \ ---target_dir='~/.cache/paddle/dataset/speech/VoxForge' \ +--target_dir='./dataset/VoxForge' \ --is_merge_dialect=True \ --dialects 'american' 'british' 'australian' 'european' 'irish' 'canadian' 'indian' diff --git a/data/voxforge/voxforge.py b/data/voxforge/voxforge.py index 63f052bd..b86b0f00 100644 --- a/data/voxforge/voxforge.py +++ b/data/voxforge/voxforge.py @@ -18,7 +18,7 @@ import shutil import subprocess from data_utils.utility import download_multi, unpack, getfile_insensitive -DATA_HOME = '~/.cache/paddle/dataset/speech' +DATA_HOME = './dataset' DATA_URL = 'http://www.repository.voxforge1.org/downloads/SpeechCorpus/Trunk/' \ 'Audio/Main/16kHz_16bit' diff --git a/data_utils/audio.py b/data_utils/audio.py index 3fb78295..e0feb21f 100644 --- a/data_utils/audio.py +++ b/data_utils/audio.py @@ -12,6 +12,7 @@ import resampy from scipy import signal import random import copy +import io class AudioSegment(object): @@ -154,7 +155,7 @@ class AudioSegment(object): fileno = int(matches.group(2)) # read headers - f = open(filename, 'rb') + f = io.open(filename, mode='rb', encoding='utf8') version = f.read(4) num_utterances = struct.unpack("i", f.read(4))[0] bytes_per_header = struct.unpack("i", f.read(4))[0] diff --git a/data_utils/data.py b/data_utils/data.py index f79a6395..72511b81 100644 --- a/data_utils/data.py +++ b/data_utils/data.py @@ -9,10 +9,9 @@ import random import tarfile import multiprocessing import numpy as np -import paddle.v2 as paddle +import paddle.fluid as fluid from threading import local from data_utils.utility import read_manifest -from data_utils.utility import xmap_readers_mp from data_utils.augmentor.augmentation import AugmentationPipeline from data_utils.featurizer.speech_featurizer import SpeechFeaturizer from data_utils.speech import SpeechSegment @@ -51,14 +50,17 @@ class DataGenerator(object): :param use_dB_normalization: Whether to normalize the audio to -20 dB before extracting the features. :type use_dB_normalization: bool - :param num_threads: Number of CPU threads for processing data. - :type num_threads: int :param random_seed: Random seed. :type random_seed: int :param keep_transcription_text: If set to True, transcription text will be passed forward directly without converting to index sequence. :type keep_transcription_text: bool + :param place: The place to run the program. + :type place: CPU or GPU + :param is_training: If set to True, generate text data for training, + otherwise, generate text data for infer. + :type is_training: bool """ def __init__(self, @@ -72,9 +74,10 @@ class DataGenerator(object): max_freq=None, specgram_type='linear', use_dB_normalization=True, - num_threads=multiprocessing.cpu_count() // 2, random_seed=0, - keep_transcription_text=False): + keep_transcription_text=False, + place=fluid.CPUPlace(), + is_training=True): self._max_duration = max_duration self._min_duration = min_duration self._normalizer = FeatureNormalizer(mean_std_filepath) @@ -87,14 +90,15 @@ class DataGenerator(object): window_ms=window_ms, max_freq=max_freq, use_dB_normalization=use_dB_normalization) - self._num_threads = num_threads self._rng = random.Random(random_seed) self._keep_transcription_text = keep_transcription_text self._epoch = 0 + self._is_training = is_training # for caching tar files info self._local_data = local() self._local_data.tar2info = {} self._local_data.tar2object = {} + self._place = place def process_utterance(self, audio_file, transcript): """Load, augment, featurize and normalize for speech data. @@ -121,7 +125,6 @@ class DataGenerator(object): def batch_reader_creator(self, manifest_path, batch_size, - min_batch_size=1, padding_to=-1, flatten=False, sortagrad=False, @@ -137,9 +140,6 @@ class DataGenerator(object): :type manifest_path: basestring :param batch_size: Number of instances in a batch. :type batch_size: int - :param min_batch_size: Any batch with batch size smaller than this will - be discarded. (To be deprecated in the future.) - :type min_batch_size: int :param padding_to: If set -1, the maximun shape in the batch will be used as the target shape for padding. Otherwise, `padding_to` will be the target shape. @@ -178,6 +178,7 @@ class DataGenerator(object): # sort (by duration) or batch-wise shuffle the manifest if self._epoch == 0 and sortagrad: manifest.sort(key=lambda x: x["duration"]) + else: if shuffle_method == "batch_shuffle": manifest = self._batch_shuffle( @@ -193,18 +194,16 @@ class DataGenerator(object): raise ValueError("Unknown shuffle method %s." % shuffle_method) # prepare batches - instance_reader, cleanup = self._instance_reader_creator(manifest) batch = [] - try: - for instance in instance_reader(): - batch.append(instance) - if len(batch) == batch_size: - yield self._padding_batch(batch, padding_to, flatten) - batch = [] - if len(batch) >= min_batch_size: + instance_reader = self._instance_reader_creator(manifest) + + for instance in instance_reader(): + batch.append(instance) + if len(batch) == batch_size: yield self._padding_batch(batch, padding_to, flatten) - finally: - cleanup() + batch = [] + if len(batch) >= 1: + yield self._padding_batch(batch, padding_to, flatten) self._epoch += 1 return batch_reader @@ -276,13 +275,11 @@ class DataGenerator(object): def reader(): for instance in manifest: - yield instance + inst = self.process_utterance(instance["audio_filepath"], + instance["text"]), + yield inst[0] - reader, cleanup_callback = xmap_readers_mp( - lambda instance: self.process_utterance(instance["audio_filepath"], instance["text"]), - reader, self._num_threads, 4096) - - return reader, cleanup_callback + return reader def _padding_batch(self, batch, padding_to=-1, flatten=False): """ @@ -304,14 +301,43 @@ class DataGenerator(object): "than any instance's shape in the batch") max_length = padding_to # padding + padded_audios = [] + texts, text_lens = [], [] + audio_lens = [] + masks = [] for audio, text in batch: padded_audio = np.zeros([audio.shape[0], max_length]) padded_audio[:, :audio.shape[1]] = audio if flatten: padded_audio = padded_audio.flatten() - padded_instance = [padded_audio, text, audio.shape[1]] - new_batch.append(padded_instance) - return new_batch + padded_audios.append(padded_audio) + if self._is_training: + texts += text + else: + texts.append(text) + text_lens.append(len(text)) + audio_lens.append(audio.shape[1]) + mask_shape0 = (audio.shape[0] - 1) // 2 + 1 + mask_shape1 = (audio.shape[1] - 1) // 3 + 1 + mask_max_len = (max_length - 1) // 3 + 1 + mask_ones = np.ones((mask_shape0, mask_shape1)) + mask_zeros = np.zeros((mask_shape0, mask_max_len - mask_shape1)) + mask = np.repeat( + np.reshape( + np.concatenate((mask_ones, mask_zeros), axis=1), + (1, mask_shape0, mask_max_len)), + 32, + axis=0) + masks.append(mask) + padded_audios = np.array(padded_audios).astype('float32') + if self._is_training: + texts = fluid.create_lod_tensor( + np.array(texts).astype('int32'), + recursive_seq_lens=[text_lens], + place=self._place) + audio_lens = np.array(audio_lens).astype('int64').reshape([-1, 1]) + masks = np.array(masks).astype('float32') + return padded_audios, texts, audio_lens, masks def _batch_shuffle(self, manifest, batch_size, clipped=False): """Put similarly-sized instances into minibatches for better efficiency diff --git a/data_utils/utility.py b/data_utils/utility.py index 89a74c41..7143f7de 100644 --- a/data_utils/utility.py +++ b/data_utils/utility.py @@ -11,7 +11,7 @@ import time from Queue import Queue from threading import Thread from multiprocessing import Process, Manager, Value -from paddle.v2.dataset.common import md5file +from paddle.dataset.common import md5file def read_manifest(manifest_path, max_duration=float('inf'), min_duration=0.0): @@ -88,127 +88,3 @@ def unpack(filepath, target_dir, rm_tar=False): class XmapEndSignal(): pass - - -def xmap_readers_mp(mapper, reader, process_num, buffer_size, order=False): - """A multiprocessing pipeline wrapper for the data reader. - - :param mapper: Function to map sample. - :type mapper: callable - :param reader: Given data reader. - :type reader: callable - :param process_num: Number of processes in the pipeline - :type process_num: int - :param buffer_size: Maximal buffer size. - :type buffer_size: int - :return: The wrappered reader and cleanup callback - :rtype: tuple - """ - end_flag = XmapEndSignal() - - read_workers = [] - handle_workers = [] - flush_workers = [] - - read_exit_flag = Value('i', 0) - handle_exit_flag = Value('i', 0) - flush_exit_flag = Value('i', 0) - - # define a worker to read samples from reader to in_queue with order flag - def order_read_worker(reader, in_queue): - for order_id, sample in enumerate(reader()): - if read_exit_flag.value == 1: break - in_queue.put((order_id, sample)) - in_queue.put(end_flag) - # the reading worker should not exit until all handling work exited - while handle_exit_flag.value == 0 or read_exit_flag.value == 0: - time.sleep(0.001) - - # define a worker to handle samples from in_queue by mapper and put results - # to out_queue with order - def order_handle_worker(in_queue, out_queue, mapper, out_order): - ins = in_queue.get() - while not isinstance(ins, XmapEndSignal): - if handle_exit_flag.value == 1: break - order_id, sample = ins - result = mapper(sample) - while order_id != out_order[0]: - time.sleep(0.001) - out_queue.put(result) - out_order[0] += 1 - ins = in_queue.get() - in_queue.put(end_flag) - out_queue.put(end_flag) - # wait for exit of flushing worker - while flush_exit_flag.value == 0 or handle_exit_flag.value == 0: - time.sleep(0.001) - read_exit_flag.value = 1 - handle_exit_flag.value = 1 - - # define a thread worker to flush samples from Manager.Queue to Queue - # for acceleration - def flush_worker(in_queue, out_queue): - finish = 0 - while finish < process_num and flush_exit_flag.value == 0: - sample = in_queue.get() - if isinstance(sample, XmapEndSignal): - finish += 1 - else: - out_queue.put(sample) - out_queue.put(end_flag) - handle_exit_flag.value = 1 - flush_exit_flag.value = 1 - - def cleanup(): - # first exit flushing workers - flush_exit_flag.value = 1 - for w in flush_workers: - w.join() - # next exit handling workers - handle_exit_flag.value = 1 - for w in handle_workers: - w.join() - # last exit reading workers - read_exit_flag.value = 1 - for w in read_workers: - w.join() - - def xreader(): - # prepare shared memory - manager = Manager() - in_queue = manager.Queue(buffer_size) - out_queue = manager.Queue(buffer_size) - out_order = manager.list([0]) - - # start a read worker in a process - target = order_read_worker - p = Process(target=target, args=(reader, in_queue)) - p.daemon = True - p.start() - read_workers.append(p) - - # start handle_workers with multiple processes - target = order_handle_worker - args = (in_queue, out_queue, mapper, out_order) - workers = [ - Process(target=target, args=args) for _ in xrange(process_num) - ] - for w in workers: - w.daemon = True - w.start() - handle_workers.append(w) - - # start a thread to read data from slow Manager.Queue - flush_queue = Queue(buffer_size) - t = Thread(target=flush_worker, args=(out_queue, flush_queue)) - t.daemon = True - t.start() - flush_workers.append(t) - - # get results - sample = flush_queue.get() - while not isinstance(sample, XmapEndSignal): - yield sample - sample = flush_queue.get() - - return xreader, cleanup diff --git a/decoders/decoders_deprecated.py b/decoders/decoders_deprecated.py index 17b28b0d..b9248b58 100644 --- a/decoders/decoders_deprecated.py +++ b/decoders/decoders_deprecated.py @@ -102,7 +102,7 @@ def ctc_beam_search_decoder(probs_seq, probs_b_prev, probs_nb_prev = {'\t': 1.0}, {'\t': 0.0} ## extend prefix in loop - for time_step in xrange(len(probs_seq)): + for time_step in range(len(probs_seq)): # prefix_set_next: the set containing candidate prefixes # probs_b_cur: prefixes' probability ending with blank in current step # probs_nb_cur: prefixes' probability ending with non-blank in current step @@ -114,7 +114,7 @@ def ctc_beam_search_decoder(probs_seq, if cutoff_prob < 1.0 or cutoff_top_n < cutoff_len: prob_idx = sorted(prob_idx, key=lambda asd: asd[1], reverse=True) cutoff_len, cum_prob = 0, 0.0 - for i in xrange(len(prob_idx)): + for i in range(len(prob_idx)): cum_prob += prob_idx[i][1] cutoff_len += 1 if cum_prob >= cutoff_prob: @@ -127,7 +127,7 @@ def ctc_beam_search_decoder(probs_seq, probs_b_cur[l], probs_nb_cur[l] = 0.0, 0.0 # extend prefix by travering prob_idx - for index in xrange(cutoff_len): + for index in range(cutoff_len): c, prob_c = prob_idx[index][0], prob_idx[index][1] if c == blank_id: diff --git a/deploy/demo_client.py b/deploy/demo_client.py index ddf4dd1b..7f886946 100644 --- a/deploy/demo_client.py +++ b/deploy/demo_client.py @@ -1,5 +1,5 @@ """Client-end for the ASR demo.""" -from pynput import keyboard +import keyboard import struct import socket import sys @@ -23,22 +23,17 @@ is_recording = False enable_trigger_record = True -def on_press(key): - """On-press keyboard callback function.""" +def on_press_release(x): + """Keyboard callback function.""" global is_recording, enable_trigger_record - if key == keyboard.Key.space: + press = keyboard.KeyboardEvent('down', 28, 'space') + release = keyboard.KeyboardEvent('up', 28, 'space') + if x.event_type == 'down' and x.name == press.name: if (not is_recording) and enable_trigger_record: sys.stdout.write("Start Recording ... ") sys.stdout.flush() is_recording = True - - -def on_release(key): - """On-release keyboard callback function.""" - global is_recording, enable_trigger_record - if key == keyboard.Key.esc: - return False - elif key == keyboard.Key.space: + if x.event_type == 'up' and x.name == release.name: if is_recording == True: is_recording = False @@ -80,9 +75,10 @@ def main(): stream.start_stream() # prepare keyboard listener - with keyboard.Listener( - on_press=on_press, on_release=on_release) as listener: - listener.join() + while (1): + keyboard.hook(on_press_release) + if keyboard.record('esc'): + break # close up stream.stop_stream() diff --git a/deploy/demo_server.py b/deploy/demo_server.py index 1cafb7a5..0f608989 100644 --- a/deploy/demo_server.py +++ b/deploy/demo_server.py @@ -8,7 +8,8 @@ from time import gmtime, strftime import SocketServer import struct import wave -import paddle.v2 as paddle +import paddle.fluid as fluid +import numpy as np import _init_paths from data_utils.data import DataGenerator from model_utils.model import DeepSpeech2Model @@ -141,13 +142,19 @@ def warm_up_test(audio_process_handler, def start_server(): """Start the ASR server""" # prepare data generator + if args.use_gpu: + place = fluid.CUDAPlace(0) + else: + place = fluid.CPUPlace() + data_generator = DataGenerator( vocab_filepath=args.vocab_path, mean_std_filepath=args.mean_std_path, augmentation_config='{}', specgram_type=args.specgram_type, - num_threads=1, - keep_transcription_text=True) + keep_transcription_text=True, + place = place, + is_training = False) # prepare ASR model ds2_model = DeepSpeech2Model( vocab_size=data_generator.vocab_size, @@ -155,7 +162,8 @@ def start_server(): num_rnn_layers=args.num_rnn_layers, rnn_layer_size=args.rnn_layer_size, use_gru=args.use_gru, - pretrained_model_path=args.model_path, + init_from_pretrain_model=args.model_path, + place=place, share_rnn_weights=args.share_rnn_weights) vocab_list = [chars.encode("utf-8") for chars in data_generator.vocab_list] @@ -166,8 +174,24 @@ def start_server(): # prepare ASR inference handler def file_to_transcript(filename): feature = data_generator.process_utterance(filename, "") + audio_len = feature[0].shape[1] + mask_shape0 = (feature[0].shape[0] - 1) // 2 + 1 + mask_shape1 = (feature[0].shape[1] - 1) // 3 + 1 + mask_max_len = (audio_len - 1) // 3 + 1 + mask_ones = np.ones((mask_shape0, mask_shape1)) + mask_zeros = np.zeros((mask_shape0, mask_max_len - mask_shape1)) + mask = np.repeat( + np.reshape( + np.concatenate((mask_ones, mask_zeros), axis=1), + (1, mask_shape0, mask_max_len)), + 32, + axis=0) + feature = (np.array([feature[0]]).astype('float32'), + None, + np.array([audio_len]).astype('int64').reshape([-1,1]), + np.array([mask]).astype('float32')) probs_split = ds2_model.infer_batch_probs( - infer_data=[feature], + infer_data=feature, feeding_dict=data_generator.feeding) if args.decoding_method == "ctc_greedy": @@ -207,7 +231,6 @@ def start_server(): def main(): print_arguments(args) - paddle.init(use_gpu=args.use_gpu, trainer_count=1) start_server() diff --git a/docs/images/multi_gpu_speedup.png b/docs/images/multi_gpu_speedup.png index 57a803bac8a6c793548abf71db2899aeac829fa1..286de51519203bb070ce9a539a21627808b7403c 100755 GIT binary patch literal 211490 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 literal 156739 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�sb6~OG>y~?L;1d>sW3BJ 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


调整LibriSpeech的dev-clean集合的误差曲面示例

-通常,如图所示,语言模型权重($\alpha$)的变化显著影响CTC波束搜索解码器的性能。更好的方法是首先调整多批数据(可指定数量)以找出适当的超参数范围,然后更改为完整的验证集以进行精确调整。 +通常,如图所示,语言模型权重($\alpha$)的变化显著影响 CTC波束搜索解码器的性能。更好的方法是首先调整多批数据(可指定数量)以找出适当的超参数范围,然后更改为完整的验证集以进行精确调整。 -调整之后,您可以在推理和评价模块中重置$\alpha$和$\beta$,以检查它们是否真的有助于提高ASR性能。更多帮助如下: +调整之后,您可以在推理和评价模块中重置$\alpha$和$\beta$,以检查它们是否真的有助于提高 ASR 性能。更多帮助如下: ```bash python tune.py --help @@ -355,23 +355,23 @@ python tune.py --help ## 在Docker容器上运行 -Docker是一个开源工具,用于在孤立的环境中构建、发布和运行分布式应用程序。此项目的Docker镜像已在[hub.docker.com](https://hub.docker.com)中提供,并安装了所有依赖项,其中包括预先构建的PaddlePaddle,CTC解码器以及其他必要的Python和第三方库。这个Docker映像需要NVIDIA GPU的支持,所以请确保它的可用性并已完成[nvidia-docker](https://github.com/NVIDIA/nvidia-docker)的安装。 +Docker 是一个开源工具,用于在孤立的环境中构建、发布和运行分布式应用程序。此项目的 Docker 镜像已在[hub.docker.com](https://hub.docker.com)中提供,并安装了所有依赖项,其中包括预先构建的PaddlePaddle,CTC解码器以及其他必要的 Python 和第三方库。这个 Docker 映像需要NVIDIA GPU的支持,所以请确保它的可用性并已完成[nvidia-docker](https://github.com/NVIDIA/nvidia-docker)的安装。 -采取以下步骤来启动Docker镜像: +采取以下步骤来启动 Docker 镜像: -- 下载Docker镜像 +- 下载 Docker 镜像 ```bash nvidia-docker pull hub.baidubce.com/paddlepaddle/deep_speech_fluid:latest-gpu ``` -- git clone这个资源库 +- git clone 这个资源库 ``` git clone https://github.com/PaddlePaddle/DeepSpeech.git ``` -- 运行Docker镜像 +- 运行 Docker 镜像 ```bash sudo nvidia-docker run -it -v $(pwd)/DeepSpeech:/DeepSpeech hub.baidubce.com/paddlepaddle/deep_speech_fluid:latest-gpu /bin/bash @@ -382,11 +382,11 @@ sudo nvidia-docker run -it -v $(pwd)/DeepSpeech:/DeepSpeech hub.baidubce.com/pad ## 训练普通话语言 -普通话语言训练与英语训练的关键步骤相同,我们提供了一个使用Aishell进行普通话训练的例子```examples/aishell```。如上所述,请执行```sh run_data.sh```, ```sh run_train.sh```, ```sh run_test.sh```和```sh run_infer.sh```做相应的数据准备,训练,测试和推断。我们还准备了一个预训练过的模型(执行./models/aishell/download_model.sh下载)供用户使用```run_infer_golden.sh```和```run_test_golden.sh```来。请注意,与英语语言模型不同,普通话语言模型是基于汉字的,请运行```tools/tune.py```来查找最佳设置。 +普通话语言训练与英语训练的关键步骤相同,我们提供了一个使用 Aishell 进行普通话训练的例子```examples/aishell```。如上所述,请执行```sh run_data.sh```, ```sh run_train.sh```, ```sh run_test.sh```和```sh run_infer.sh```做相应的数据准备,训练,测试和推断。我们还准备了一个预训练过的模型(执行./models/aishell/download_model.sh下载)供用户使用```run_infer_golden.sh```和```run_test_golden.sh```来。请注意,与英语语言模型不同,普通话语言模型是基于汉字的,请运行```tools/tune.py```来查找最佳设置。 ##用自己的声音尝试现场演示 -到目前为止,一个ASR模型已经训练完毕,并且用现有的音频文件进行了定性测试(`infer.py`)和定量测试(`test.py`)。但目前还没有用你自己的声音进行测试。`deploy/demo_english_server.py`和`deploy/demo_client.py`能够快速构建一个利用已训练好的模型对ASR引擎进行实时演示的系统,使你能够用自己的语音测试和演示。 +到目前为止,一个 ASR 模型已经训练完毕,并且用现有的音频文件进行了定性测试(`infer.py`)和定量测试(`test.py`)。但目前还没有用你自己的声音进行测试。`deploy/demo_english_server.py`和`deploy/demo_client.py`能够快速构建一个利用已训练好的模型对ASR引擎进行实时演示的系统,使你能够用自己的语音测试和演示。 要启动演示服务,请在控制台中运行: @@ -397,9 +397,9 @@ python deploy/demo_server.py \ --host_port 8086 ``` -对于运行demo客户端的机器(可能不是同一台机器),请在继续之前执行以下安装。 +对于运行 demo 客户端的机器(可能不是同一台机器),请在继续之前执行以下安装。 -比如,对于MAC OS X机器: +比如,对于 MAC OS X 机器: ```bash brew install portaudio diff --git a/data_utils/data.py b/data_utils/data.py index 72511b81..0fb2a88b 100644 --- a/data_utils/data.py +++ b/data_utils/data.py @@ -57,7 +57,7 @@ class DataGenerator(object): converting to index sequence. :type keep_transcription_text: bool :param place: The place to run the program. - :type place: CPU or GPU + :type place: CPUPlace or CUDAPlace :param is_training: If set to True, generate text data for training, otherwise, generate text data for infer. :type is_training: bool diff --git a/deploy/demo_server.py b/deploy/demo_server.py index 0f608989..68fcb245 100644 --- a/deploy/demo_server.py +++ b/deploy/demo_server.py @@ -162,7 +162,7 @@ def start_server(): num_rnn_layers=args.num_rnn_layers, rnn_layer_size=args.rnn_layer_size, use_gru=args.use_gru, - init_from_pretrain_model=args.model_path, + init_from_pretrained_model=args.model_path, place=place, share_rnn_weights=args.share_rnn_weights) diff --git a/examples/aishell/run_train.sh b/examples/aishell/run_train.sh index 48b49c41..335473fc 100644 --- a/examples/aishell/run_train.sh +++ b/examples/aishell/run_train.sh @@ -3,7 +3,7 @@ cd ../.. > /dev/null # train model -# if you wish to resume from an exists model, uncomment --init_from_pretrain_model +# if you wish to resume from an exists model, uncomment --init_from_pretrained_model export FLAGS_sync_nccl_allreduce=0 CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 \ python -u train.py \ diff --git a/examples/librispeech/run_train.sh b/examples/librispeech/run_train.sh index 5917a1d5..a568bf22 100644 --- a/examples/librispeech/run_train.sh +++ b/examples/librispeech/run_train.sh @@ -3,7 +3,7 @@ cd ../.. > /dev/null # train model -# if you wish to resume from an exists model, uncomment --init_from_pretrain_model +# if you wish to resume from an exists model, uncomment --init_from_pretrained_model export FLAGS_sync_nccl_allreduce=0 CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 \ diff --git a/examples/tiny/run_train.sh b/examples/tiny/run_train.sh index 9d436fb6..95ccd2bc 100644 --- a/examples/tiny/run_train.sh +++ b/examples/tiny/run_train.sh @@ -3,7 +3,7 @@ cd ../.. > /dev/null # train model -# if you wish to resume from an exists model, uncomment --init_from_pretrain_model +# if you wish to resume from an exists model, uncomment --init_from_pretrained_model export FLAGS_sync_nccl_allreduce=0 CUDA_VISIBLE_DEVICES=0,1,2,3 \ python -u train.py \ diff --git a/infer.py b/infer.py index 4dd1f275..e43aa526 100644 --- a/infer.py +++ b/infer.py @@ -12,6 +12,7 @@ import functools import paddle.fluid as fluid from data_utils.data import DataGenerator from model_utils.model import DeepSpeech2Model +from model_utils.model_check import check_cuda, check_version from utils.error_rate import wer, cer from utils.utility import add_arguments, print_arguments @@ -66,6 +67,12 @@ args = parser.parse_args() def infer(): """Inference for DeepSpeech2.""" + + # check if set use_gpu=True in paddlepaddle cpu version + check_cuda(args.use_gpu) + # check if paddlepaddle version is satisfied + check_version() + if args.use_gpu: place = fluid.CUDAPlace(0) else: @@ -94,7 +101,7 @@ def infer(): use_gru=args.use_gru, share_rnn_weights=args.share_rnn_weights, place=place, - init_from_pretrain_model=args.model_path) + init_from_pretrained_model=args.model_path) # decoders only accept string encoded in utf-8 vocab_list = [chars.encode("utf-8") for chars in data_generator.vocab_list] diff --git a/model_utils/model.py b/model_utils/model.py index ecc3f28a..fe1ae43d 100644 --- a/model_utils/model.py +++ b/model_utils/model.py @@ -44,7 +44,7 @@ class DeepSpeech2Model(object): for GRU, weight sharing is not supported. :type share_rnn_weights: bool :param place: Program running place. - :type place: CPU or GPU + :type place: CPUPlace or CUDAPlace :param init_from_pretrained_model: Pretrained model path. If None, will train from stratch. :type init_from_pretrained_model: string|None @@ -60,7 +60,7 @@ class DeepSpeech2Model(object): use_gru=False, share_rnn_weights=True, place=fluid.CPUPlace(), - init_from_pretrain_model=None, + init_from_pretrained_model=None, output_model_dir=None): self._vocab_size = vocab_size self._num_conv_layers = num_conv_layers @@ -69,7 +69,7 @@ class DeepSpeech2Model(object): self._use_gru = use_gru self._share_rnn_weights = share_rnn_weights self._place = place - self._init_from_pretrain_model = init_from_pretrain_model + self._init_from_pretrained_model = init_from_pretrained_model self._output_model_dir = output_model_dir self._ext_scorer = None self.logger = logging.getLogger("") @@ -90,13 +90,14 @@ class DeepSpeech2Model(object): if not is_infer: input_fields = { 'names': ['audio_data', 'text_data', 'seq_len_data', 'masks'], - 'shapes': [[-1, 161, 161], [-1, 1], [-1, 1], [-1, 32, 81, 1]], + 'shapes': + [[None, 161, None], [None, 1], [None, 1], [None, 32, 81, None]], 'dtypes': ['float32', 'int32', 'int64', 'float32'], 'lod_levels': [0, 1, 0, 0] } inputs = [ - fluid.layers.data( + fluid.data( name=input_fields['names'][i], shape=input_fields['shapes'][i], dtype=input_fields['dtypes'][i], @@ -104,7 +105,7 @@ class DeepSpeech2Model(object): for i in range(len(input_fields['names'])) ] - reader = fluid.io.PyReader( + reader = fluid.io.DataLoader.from_generator( feed_list=inputs, capacity=64, iterable=False, @@ -112,16 +113,19 @@ class DeepSpeech2Model(object): (audio_data, text_data, seq_len_data, masks) = inputs else: - audio_data = fluid.layers.data( + audio_data = fluid.data( name='audio_data', - shape=[-1, 161, 161], + shape=[None, 161, None], dtype='float32', lod_level=0) - seq_len_data = fluid.layers.data( - name='seq_len_data', shape=[-1, 1], dtype='int64', lod_level=0) - masks = fluid.layers.data( + seq_len_data = fluid.data( + name='seq_len_data', + shape=[None, 1], + dtype='int64', + lod_level=0) + masks = fluid.data( name='masks', - shape=[-1, 32, 81, 1], + shape=[None, 32, 81, None], dtype='float32', lod_level=0) text_data = None @@ -141,26 +145,26 @@ class DeepSpeech2Model(object): share_rnn_weights=self._share_rnn_weights) return reader, log_probs, loss - def init_from_pretrain_model(self, exe, program): + def init_from_pretrained_model(self, exe, program): '''Init params from pretrain model. ''' - assert isinstance(self._init_from_pretrain_model, str) + assert isinstance(self._init_from_pretrained_model, str) - if not os.path.exists(self._init_from_pretrain_model): - print(self._init_from_pretrain_model) + if not os.path.exists(self._init_from_pretrained_model): + print(self._init_from_pretrained_model) raise Warning("The pretrained params do not exist.") return False fluid.io.load_params( exe, - self._init_from_pretrain_model, + self._init_from_pretrained_model, main_program=program, filename="params.pdparams") print("finish initing model from pretrained params from %s" % - (self._init_from_pretrain_model)) + (self._init_from_pretrained_model)) pre_epoch = 0 - dir_name = self._init_from_pretrain_model.split('_') + dir_name = self._init_from_pretrained_model.split('_') if len(dir_name) >= 2 and dir_name[-2].endswith('epoch') and dir_name[ -1].isdigit(): pre_epoch = int(dir_name[-1]) @@ -186,7 +190,7 @@ class DeepSpeech2Model(object): return True - def test(self, exe, dev_batch_reader, test_program, test_pyreader, + def test(self, exe, dev_batch_reader, test_program, test_reader, fetch_list): '''Test the model. @@ -196,14 +200,14 @@ class DeepSpeech2Model(object): :type dev_batch_reader: read generator :param test_program: The program of test. :type test_program: Program - :param test_pyreader: Pyreader of test. - :type test_pyreader: Pyreader + :param test_reader: Reader of test. + :type test_reader: Reader :param fetch_list: Fetch list. :type fetch_list: list :return: An output unnormalized log probability. :rtype: array ''' - test_pyreader.start() + test_reader.start() epoch_loss = [] while True: try: @@ -214,7 +218,7 @@ class DeepSpeech2Model(object): epoch_loss.extend(np.array(each_loss[0])) except fluid.core.EOFException: - test_pyreader.reset() + test_reader.reset() break return np.mean(np.array(epoch_loss)) @@ -274,7 +278,7 @@ class DeepSpeech2Model(object): startup_prog = fluid.Program() with fluid.program_guard(train_program, startup_prog): with fluid.unique_name.guard(): - train_pyreader, log_probs, ctc_loss = self.create_network() + train_reader, log_probs, ctc_loss = self.create_network() # prepare optimizer optimizer = fluid.optimizer.AdamOptimizer( learning_rate=fluid.layers.exponential_decay( @@ -290,7 +294,7 @@ class DeepSpeech2Model(object): test_prog = fluid.Program() with fluid.program_guard(test_prog, startup_prog): with fluid.unique_name.guard(): - test_pyreader, _, ctc_loss = self.create_network() + test_reader, _, ctc_loss = self.create_network() test_prog = test_prog.clone(for_test=True) @@ -299,8 +303,8 @@ class DeepSpeech2Model(object): # init from some pretrain models, to better solve the current task pre_epoch = 0 - if self._init_from_pretrain_model: - pre_epoch = self.init_from_pretrain_model(exe, train_program) + if self._init_from_pretrained_model: + pre_epoch = self.init_from_pretrained_model(exe, train_program) build_strategy = compiler.BuildStrategy() exec_strategy = fluid.ExecutionStrategy() @@ -312,12 +316,12 @@ class DeepSpeech2Model(object): build_strategy=build_strategy, exec_strategy=exec_strategy) - train_pyreader.decorate_batch_generator(train_batch_reader) - test_pyreader.decorate_batch_generator(dev_batch_reader) + train_reader.set_batch_generator(train_batch_reader) + test_reader.set_batch_generator(dev_batch_reader) # run train for epoch_id in range(num_epoch): - train_pyreader.start() + train_reader.start() epoch_loss = [] time_begin = time.time() batch_id = 0 @@ -346,7 +350,7 @@ class DeepSpeech2Model(object): batch_id = batch_id + 1 except fluid.core.EOFException: - train_pyreader.reset() + train_reader.reset() break time_end = time.time() used_time = time_end - time_begin @@ -359,7 +363,7 @@ class DeepSpeech2Model(object): exe, dev_batch_reader=dev_batch_reader, test_program=test_prog, - test_pyreader=test_pyreader, + test_reader=test_reader, fetch_list=[ctc_loss]) print( "--------Time: %f sec, epoch: %d, train loss: %f, test loss: %f" @@ -402,10 +406,10 @@ class DeepSpeech2Model(object): exe = fluid.Executor(self._place) exe.run(startup_prog) - # init param from pretrain_model - if not self._init_from_pretrain_model: + # init param from pretrained_model + if not self._init_from_pretrained_model: exit("No pretrain model file path!") - self.init_from_pretrain_model(exe, infer_program) + self.init_from_pretrained_model(exe, infer_program) infer_results = [] time_begin = time.time() diff --git a/model_utils/model_check.py b/model_utils/model_check.py new file mode 100644 index 00000000..bf2c424f --- /dev/null +++ b/model_utils/model_check.py @@ -0,0 +1,49 @@ +# Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import sys +import paddle +import paddle.fluid as fluid + + +def check_cuda(use_cuda, err = \ + "\nYou can not set use_cuda = True in the model because you are using paddlepaddle-cpu.\n \ + Please: 1. Install paddlepaddle-gpu to run your models on GPU or 2. Set use_cuda = False to run models on CPU.\n" + ): + """ + Log error and exit when set use_gpu=true in paddlepaddle + cpu version. + """ + try: + if use_cuda == True and fluid.is_compiled_with_cuda() == False: + print(err) + sys.exit(1) + except Exception as e: + pass + + +def check_version(): + """ + Log error and exit when the installed version of paddlepaddle is + not satisfied. + """ + err = "PaddlePaddle version 1.6 or higher is required, " \ + "or a suitable develop version is satisfied as well. \n" \ + "Please make sure the version is good with your code." \ + + try: + fluid.require_version('1.6.0') + except Exception as e: + print(err) + sys.exit(1) diff --git a/model_utils/network.py b/model_utils/network.py index 0ba3a916..3a4f1dc3 100644 --- a/model_utils/network.py +++ b/model_utils/network.py @@ -61,17 +61,17 @@ def conv_bn_layer(input, filter_size, num_channels_in, num_channels_out, stride, def simple_rnn(input, size, param_attr=None, bias_attr=None, is_reverse=False): '''A simple rnn layer. - :param input:input layer. - :type input:Variable - :param size:Number of RNN cells. - :type size:int - :param param_attr:Parameter properties of hidden layer weights that + :param input: input layer. + :type input: Variable + :param size: Dimension of RNN cells. + :type size: int + :param param_attr: Parameter properties of hidden layer weights that can be learned - :type param_attr:ParamAttr - :param bias_attr:Bias properties of hidden layer weights that can be learned - :type bias_attr:ParamAttr - :param is_reverse:Whether to calculate the inverse RNN - :type is_reverse:bool + :type param_attr: ParamAttr + :param bias_attr: Bias properties of hidden layer weights that can be learned + :type bias_attr: ParamAttr + :param is_reverse: Whether to calculate the inverse RNN + :type is_reverse: bool :return: A simple RNN layer. :rtype: Variable ''' @@ -112,7 +112,7 @@ def bidirectional_simple_rnn_bn_layer(name, input, size, share_weights): :type name: string :param input: Input layer. :type input: Variable - :param size: Number of RNN cells. + :param size: Dimension of RNN cells. :type size: int :param share_weights: Whether to share input-hidden weights between forward and backward directional RNNs. @@ -206,7 +206,7 @@ def bidirectional_gru_bn_layer(name, input, size, act): :type name: string :param input: Input layer. :type input: Variable - :param size: Number of GRU cells. + :param size: Dimension of GRU cells. :type size: int :param act: Activation type. :type act: string @@ -317,7 +317,7 @@ def rnn_group(input, size, num_stacks, num_conv_layers, use_gru, """RNN group with stacked bidirectional simple RNN or GRU layers. :param input: Input layer. :type input: Variable - :param size: Number of RNN cells in each layer. + :param size: Dimension of RNN cells in each layer. :type size: int :param num_stacks: Number of stacked rnn layers. :type num_stacks: int @@ -373,7 +373,7 @@ def deep_speech_v2_network(audio_data, :type num_conv_layers: int :param num_rnn_layers: Number of stacking RNN layers. :type num_rnn_layers: int - :param rnn_size: RNN layer size (number of RNN cells). + :param rnn_size: RNN layer size (dimension of RNN cells). :type rnn_size: int :param use_gru: Use gru if set True. Use simple rnn if set False. :type use_gru: bool diff --git a/test.py b/test.py index 44307ba8..12df5521 100644 --- a/test.py +++ b/test.py @@ -8,6 +8,7 @@ import functools import paddle.fluid as fluid from data_utils.data import DataGenerator from model_utils.model import DeepSpeech2Model +from model_utils.model_check import check_cuda, check_version from utils.error_rate import char_errors, word_errors from utils.utility import add_arguments, print_arguments @@ -62,6 +63,12 @@ args = parser.parse_args() def evaluate(): """Evaluate on whole test data for DeepSpeech2.""" + + # check if set use_gpu=True in paddlepaddle cpu version + check_cuda(args.use_gpu) + # check if paddlepaddle version is satisfied + check_version() + if args.use_gpu: place = fluid.CUDAPlace(0) else: @@ -89,7 +96,7 @@ def evaluate(): use_gru=args.use_gru, share_rnn_weights=args.share_rnn_weights, place=place, - init_from_pretrain_model=args.model_path) + init_from_pretrained_model=args.model_path) # decoders only accept string encoded in utf-8 vocab_list = [chars.encode("utf-8") for chars in data_generator.vocab_list] diff --git a/tools/tune.py b/tools/tune.py index 843df0c6..7996e4d5 100644 --- a/tools/tune.py +++ b/tools/tune.py @@ -103,7 +103,7 @@ def tune(): rnn_layer_size=args.rnn_layer_size, use_gru=args.use_gru, place=place, - init_from_pretrain_model=args.model_path, + init_from_pretrained_model=args.model_path, share_rnn_weights=args.share_rnn_weights) # decoders only accept string encoded in utf-8 diff --git a/train.py b/train.py index 0d409d93..5dae4ccd 100644 --- a/train.py +++ b/train.py @@ -7,6 +7,7 @@ import argparse import functools import io from model_utils.model import DeepSpeech2Model +from model_utils.model_check import check_cuda, check_version from data_utils.data import DataGenerator from utils.utility import add_arguments, print_arguments @@ -34,7 +35,7 @@ add_arg('use_gru', bool, False, "Use GRUs instead of simple RNNs.") add_arg('is_local', bool, True, "Use pserver or not.") add_arg('share_rnn_weights',bool, True, "Share input-hidden weights across " "bi-directional RNNs. Not for GRU.") -add_arg('init_from_pretrain_model',str, +add_arg('init_from_pretrained_model',str, None, "If None, the training starts from scratch, " "otherwise, it resumes from the pre-trained model.") @@ -71,6 +72,12 @@ args = parser.parse_args() def train(): """DeepSpeech2 training.""" + + # check if set use_gpu=True in paddlepaddle cpu version + check_cuda(args.use_gpu) + # check if paddlepaddle version is satisfied + check_version() + if args.use_gpu: place = fluid.CUDAPlace(0) else: @@ -93,7 +100,7 @@ def train(): train_batch_reader = train_generator.batch_reader_creator( manifest_path=args.train_manifest, batch_size=args.batch_size, - sortagrad=args.use_sortagrad if args.init_from_pretrain_model is None else False, + sortagrad=args.use_sortagrad if args.init_from_pretrained_model is None else False, shuffle_method=args.shuffle_method) dev_batch_reader = dev_generator.batch_reader_creator( manifest_path=args.dev_manifest, @@ -109,7 +116,7 @@ def train(): use_gru=args.use_gru, share_rnn_weights=args.share_rnn_weights, place=place, - init_from_pretrain_model=args.init_from_pretrain_model, + init_from_pretrained_model=args.init_from_pretrained_model, output_model_dir=args.output_model_dir) ds2_model.train(

@z{D+tM{LISAKS|P(*oGdOJMB%if~6)ivQ^ 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 /dev/null # download data, generate manifests PYTHONPATH=.:$PYTHONPATH python data/aishell/aishell.py \ --manifest_prefix='data/aishell/manifest' \ ---target_dir='~/.cache/paddle/dataset/speech/Aishell' +--target_dir='./dataset/aishell' if [ $? -ne 0 ]; then echo "Prepare Aishell failed. Terminated." diff --git a/examples/aishell/run_infer.sh b/examples/aishell/run_infer.sh index e8bd9eab..c38325d1 100644 --- a/examples/aishell/run_infer.sh +++ b/examples/aishell/run_infer.sh @@ -4,7 +4,7 @@ cd ../.. > /dev/null # download language model cd models/lm > /dev/null -sh download_lm_ch.sh +bash download_lm_ch.sh if [ $? -ne 0 ]; then exit 1 fi @@ -15,7 +15,6 @@ cd - > /dev/null CUDA_VISIBLE_DEVICES=0 \ python -u infer.py \ --num_samples=10 \ ---trainer_count=1 \ --beam_size=300 \ --num_proc_bsearch=8 \ --num_conv_layers=2 \ @@ -31,7 +30,7 @@ python -u infer.py \ --infer_manifest='data/aishell/manifest.test' \ --mean_std_path='data/aishell/mean_std.npz' \ --vocab_path='data/aishell/vocab.txt' \ ---model_path='checkpoints/aishell/params.latest.tar.gz' \ +--model_path='checkpoints/aishell/srep_final' \ --lang_model_path='models/lm/zh_giga.no_cna_cmn.prune01244.klm' \ --decoding_method='ctc_beam_search' \ --error_rate_type='cer' \ diff --git a/examples/aishell/run_infer_golden.sh b/examples/aishell/run_infer_golden.sh index 68f5a521..56d3365d 100644 --- a/examples/aishell/run_infer_golden.sh +++ b/examples/aishell/run_infer_golden.sh @@ -4,7 +4,7 @@ cd ../.. > /dev/null # download language model cd models/lm > /dev/null -sh download_lm_ch.sh +bash download_lm_ch.sh if [ $? -ne 0 ]; then exit 1 fi @@ -13,7 +13,7 @@ cd - > /dev/null # download well-trained model cd models/aishell > /dev/null -sh download_model.sh +bash download_model.sh if [ $? -ne 0 ]; then exit 1 fi @@ -24,7 +24,6 @@ cd - > /dev/null CUDA_VISIBLE_DEVICES=0 \ python -u infer.py \ --num_samples=10 \ ---trainer_count=1 \ --beam_size=300 \ --num_proc_bsearch=8 \ --num_conv_layers=2 \ @@ -35,12 +34,12 @@ python -u infer.py \ --cutoff_prob=0.99 \ --cutoff_top_n=40 \ --use_gru=True \ ---use_gpu=True \ +--use_gpu=False \ --share_rnn_weights=False \ --infer_manifest='data/aishell/manifest.test' \ --mean_std_path='models/aishell/mean_std.npz' \ --vocab_path='models/aishell/vocab.txt' \ ---model_path='models/aishell/params.tar.gz' \ +--model_path='models/aishell' \ --lang_model_path='models/lm/zh_giga.no_cna_cmn.prune01244.klm' \ --decoding_method='ctc_beam_search' \ --error_rate_type='cer' \ diff --git a/examples/aishell/run_test.sh b/examples/aishell/run_test.sh index 35dfca82..2867444b 100644 --- a/examples/aishell/run_test.sh +++ b/examples/aishell/run_test.sh @@ -4,7 +4,7 @@ cd ../.. > /dev/null # download language model cd models/lm > /dev/null -sh download_lm_ch.sh +bash download_lm_ch.sh if [ $? -ne 0 ]; then exit 1 fi @@ -15,10 +15,8 @@ cd - > /dev/null CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 \ python -u test.py \ --batch_size=128 \ ---trainer_count=8 \ --beam_size=300 \ --num_proc_bsearch=8 \ ---num_proc_data=8 \ --num_conv_layers=2 \ --num_rnn_layers=3 \ --rnn_layer_size=1024 \ @@ -32,7 +30,7 @@ python -u test.py \ --test_manifest='data/aishell/manifest.test' \ --mean_std_path='data/aishell/mean_std.npz' \ --vocab_path='data/aishell/vocab.txt' \ ---model_path='checkpoints/aishell/params.latest.tar.gz' \ +--model_path='checkpoints/aishell/step_final' \ --lang_model_path='models/lm/zh_giga.no_cna_cmn.prune01244.klm' \ --decoding_method='ctc_beam_search' \ --error_rate_type='cer' \ diff --git a/examples/aishell/run_test_golden.sh b/examples/aishell/run_test_golden.sh index 8b5e6559..799f382f 100644 --- a/examples/aishell/run_test_golden.sh +++ b/examples/aishell/run_test_golden.sh @@ -4,7 +4,7 @@ cd ../.. > /dev/null # download language model cd models/lm > /dev/null -sh download_lm_ch.sh +bash download_lm_ch.sh if [ $? -ne 0 ]; then exit 1 fi @@ -13,7 +13,7 @@ cd - > /dev/null # download well-trained model cd models/aishell > /dev/null -sh download_model.sh +bash download_model.sh if [ $? -ne 0 ]; then exit 1 fi @@ -24,10 +24,8 @@ cd - > /dev/null CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 \ python -u test.py \ --batch_size=128 \ ---trainer_count=8 \ --beam_size=300 \ --num_proc_bsearch=8 \ ---num_proc_data=8 \ --num_conv_layers=2 \ --num_rnn_layers=3 \ --rnn_layer_size=1024 \ @@ -41,7 +39,7 @@ python -u test.py \ --test_manifest='data/aishell/manifest.test' \ --mean_std_path='models/aishell/mean_std.npz' \ --vocab_path='models/aishell/vocab.txt' \ ---model_path='models/aishell/params.tar.gz' \ +--model_path='models/aishell' \ --lang_model_path='models/lm/zh_giga.no_cna_cmn.prune01244.klm' \ --decoding_method='ctc_beam_search' \ --error_rate_type='cer' \ diff --git a/examples/aishell/run_train.sh b/examples/aishell/run_train.sh index e09205cb..48b49c41 100644 --- a/examples/aishell/run_train.sh +++ b/examples/aishell/run_train.sh @@ -3,17 +3,18 @@ cd ../.. > /dev/null # train model -# if you wish to resume from an exists model, uncomment --init_model_path +# if you wish to resume from an exists model, uncomment --init_from_pretrain_model +export FLAGS_sync_nccl_allreduce=0 CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 \ python -u train.py \ --batch_size=64 \ ---trainer_count=8 \ ---num_passes=50 \ ---num_proc_data=16 \ +--num_epoch=50 \ --num_conv_layers=2 \ --num_rnn_layers=3 \ --rnn_layer_size=1024 \ --num_iter_print=100 \ +--save_epoch=1 \ +--num_samples=120000 \ --learning_rate=5e-4 \ --max_duration=27.0 \ --min_duration=0.0 \ @@ -30,7 +31,7 @@ python -u train.py \ --output_model_dir='./checkpoints/aishell' \ --augment_conf_path='conf/augmentation.config' \ --specgram_type='linear' \ ---shuffle_method='batch_shuffle_clipped' +--shuffle_method='batch_shuffle_clipped' \ if [ $? -ne 0 ]; then echo "Failed in training!" diff --git a/examples/baidu_en8k/run_infer_golden.sh b/examples/baidu_en8k/run_infer_golden.sh index 68cf2fc9..2f3f0acf 100644 --- a/examples/baidu_en8k/run_infer_golden.sh +++ b/examples/baidu_en8k/run_infer_golden.sh @@ -4,7 +4,7 @@ cd ../.. > /dev/null # download language model cd models/lm > /dev/null -sh download_lm_en.sh +bash download_lm_en.sh if [ $? -ne 0 ]; then exit 1 fi @@ -13,7 +13,7 @@ cd - > /dev/null # download well-trained model cd models/baidu_en8k > /dev/null -sh download_model.sh +bash download_model.sh if [ $? -ne 0 ]; then exit 1 fi @@ -24,7 +24,6 @@ cd - > /dev/null CUDA_VISIBLE_DEVICES=0 \ python -u infer.py \ --num_samples=10 \ ---trainer_count=1 \ --beam_size=500 \ --num_proc_bsearch=5 \ --num_conv_layers=2 \ @@ -35,12 +34,12 @@ python -u infer.py \ --cutoff_prob=1.0 \ --cutoff_top_n=40 \ --use_gru=True \ ---use_gpu=True \ +--use_gpu=False \ --share_rnn_weights=False \ --infer_manifest='data/librispeech/manifest.test-clean' \ --mean_std_path='models/baidu_en8k/mean_std.npz' \ --vocab_path='models/baidu_en8k/vocab.txt' \ ---model_path='models/baidu_en8k/params.tar.gz' \ +--model_path='models/baidu_en8k' \ --lang_model_path='models/lm/common_crawl_00.prune01111.trie.klm' \ --decoding_method='ctc_beam_search' \ --error_rate_type='wer' \ diff --git a/examples/baidu_en8k/run_test_golden.sh b/examples/baidu_en8k/run_test_golden.sh index b471ac65..612e71a0 100644 --- a/examples/baidu_en8k/run_test_golden.sh +++ b/examples/baidu_en8k/run_test_golden.sh @@ -4,7 +4,7 @@ cd ../.. > /dev/null # download language model cd models/lm > /dev/null -sh download_lm_en.sh +bash download_lm_en.sh if [ $? -ne 0 ]; then exit 1 fi @@ -13,7 +13,7 @@ cd - > /dev/null # download well-trained model cd models/baidu_en8k > /dev/null -sh download_model.sh +bash download_model.sh if [ $? -ne 0 ]; then exit 1 fi @@ -24,7 +24,6 @@ cd - > /dev/null CUDA_VISIBLE_DEVICES=0,1,2,3 \ python -u test.py \ --batch_size=128 \ ---trainer_count=4 \ --beam_size=500 \ --num_proc_bsearch=8 \ --num_proc_data=8 \ @@ -36,12 +35,12 @@ python -u test.py \ --cutoff_prob=1.0 \ --cutoff_top_n=40 \ --use_gru=True \ ---use_gpu=True \ +--use_gpu=False \ --share_rnn_weights=False \ --test_manifest='data/librispeech/manifest.test-clean' \ --mean_std_path='models/baidu_en8k/mean_std.npz' \ --vocab_path='models/baidu_en8k/vocab.txt' \ ---model_path='models/baidu_en8k/params.tar.gz' \ +--model_path='models/baidu_en8k' \ --lang_model_path='models/lm/common_crawl_00.prune01111.trie.klm' \ --decoding_method='ctc_beam_search' \ --error_rate_type='wer' \ diff --git a/examples/deploy_demo/run_english_demo_server.sh b/examples/deploy_demo/run_english_demo_server.sh index 67532770..d67559f3 100644 --- a/examples/deploy_demo/run_english_demo_server.sh +++ b/examples/deploy_demo/run_english_demo_server.sh @@ -5,7 +5,7 @@ cd ../.. > /dev/null # download language model cd models/lm > /dev/null -sh download_lm_en.sh +bash download_lm_en.sh if [ $? -ne 0 ]; then exit 1 fi @@ -14,7 +14,7 @@ cd - > /dev/null # download well-trained model cd models/baidu_en8k > /dev/null -sh download_model.sh +bash download_model.sh if [ $? -ne 0 ]; then exit 1 fi @@ -40,7 +40,7 @@ python -u deploy/demo_server.py \ --warmup_manifest='data/tiny/manifest.test-clean' \ --mean_std_path='models/baidu_en8k/mean_std.npz' \ --vocab_path='models/baidu_en8k/vocab.txt' \ ---model_path='models/baidu_en8k/params.tar.gz' \ +--model_path='models/baidu_en8k' \ --lang_model_path='models/lm/common_crawl_00.prune01111.trie.klm' \ --decoding_method='ctc_beam_search' \ --specgram_type='linear' diff --git a/examples/librispeech/run_data.sh b/examples/librispeech/run_data.sh index 6e170c12..e4db1ac9 100644 --- a/examples/librispeech/run_data.sh +++ b/examples/librispeech/run_data.sh @@ -5,7 +5,7 @@ cd ../.. > /dev/null # download data, generate manifests PYTHONPATH=.:$PYTHONPATH python data/librispeech/librispeech.py \ --manifest_prefix='data/librispeech/manifest' \ ---target_dir='~/.cache/paddle/dataset/speech/libri' \ +--target_dir='./dataset/librispeech' \ --full_download='True' if [ $? -ne 0 ]; then diff --git a/examples/librispeech/run_infer.sh b/examples/librispeech/run_infer.sh index 44b97bac..91d8ff2e 100644 --- a/examples/librispeech/run_infer.sh +++ b/examples/librispeech/run_infer.sh @@ -4,7 +4,7 @@ cd ../.. > /dev/null # download language model cd models/lm > /dev/null -sh download_lm_en.sh +bash download_lm_en.sh if [ $? -ne 0 ]; then exit 1 fi @@ -15,7 +15,6 @@ cd - > /dev/null CUDA_VISIBLE_DEVICES=0 \ python -u infer.py \ --num_samples=10 \ ---trainer_count=1 \ --beam_size=500 \ --num_proc_bsearch=8 \ --num_conv_layers=2 \ @@ -31,7 +30,7 @@ python -u infer.py \ --infer_manifest='data/librispeech/manifest.test-clean' \ --mean_std_path='data/librispeech/mean_std.npz' \ --vocab_path='data/librispeech/vocab.txt' \ ---model_path='checkpoints/libri/params.latest.tar.gz' \ +--model_path='checkpoints/libri/step_final' \ --lang_model_path='models/lm/common_crawl_00.prune01111.trie.klm' \ --decoding_method='ctc_beam_search' \ --error_rate_type='wer' \ diff --git a/examples/librispeech/run_infer_golden.sh b/examples/librispeech/run_infer_golden.sh index 17379090..eb812129 100644 --- a/examples/librispeech/run_infer_golden.sh +++ b/examples/librispeech/run_infer_golden.sh @@ -4,7 +4,7 @@ cd ../.. > /dev/null # download language model cd models/lm > /dev/null -sh download_lm_en.sh +bash download_lm_en.sh if [ $? -ne 0 ]; then exit 1 fi @@ -13,7 +13,7 @@ cd - > /dev/null # download well-trained model cd models/librispeech > /dev/null -sh download_model.sh +bash download_model.sh if [ $? -ne 0 ]; then exit 1 fi @@ -24,7 +24,6 @@ cd - > /dev/null CUDA_VISIBLE_DEVICES=0 \ python -u infer.py \ --num_samples=10 \ ---trainer_count=1 \ --beam_size=500 \ --num_proc_bsearch=8 \ --num_conv_layers=2 \ @@ -40,7 +39,7 @@ python -u infer.py \ --infer_manifest='data/librispeech/manifest.test-clean' \ --mean_std_path='models/librispeech/mean_std.npz' \ --vocab_path='models/librispeech/vocab.txt' \ ---model_path='models/librispeech/params.tar.gz' \ +--model_path='models/librispeech' \ --lang_model_path='models/lm/common_crawl_00.prune01111.trie.klm' \ --decoding_method='ctc_beam_search' \ --error_rate_type='wer' \ diff --git a/examples/librispeech/run_test.sh b/examples/librispeech/run_test.sh index 11cd7411..9eebbbf2 100644 --- a/examples/librispeech/run_test.sh +++ b/examples/librispeech/run_test.sh @@ -4,7 +4,7 @@ cd ../.. > /dev/null # download language model cd models/lm > /dev/null -sh download_lm_en.sh +bash download_lm_en.sh if [ $? -ne 0 ]; then exit 1 fi @@ -15,10 +15,8 @@ cd - > /dev/null CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 \ python -u test.py \ --batch_size=128 \ ---trainer_count=8 \ --beam_size=500 \ --num_proc_bsearch=8 \ ---num_proc_data=8 \ --num_conv_layers=2 \ --num_rnn_layers=3 \ --rnn_layer_size=2048 \ @@ -32,7 +30,7 @@ python -u test.py \ --test_manifest='data/librispeech/manifest.test-clean' \ --mean_std_path='data/librispeech/mean_std.npz' \ --vocab_path='data/librispeech/vocab.txt' \ ---model_path='checkpoints/libri/params.latest.tar.gz' \ +--model_path='checkpoints/libri/step_final' \ --lang_model_path='models/lm/common_crawl_00.prune01111.trie.klm' \ --decoding_method='ctc_beam_search' \ --error_rate_type='wer' \ diff --git a/examples/librispeech/run_test_golden.sh b/examples/librispeech/run_test_golden.sh index 41dbc0da..abd89592 100644 --- a/examples/librispeech/run_test_golden.sh +++ b/examples/librispeech/run_test_golden.sh @@ -4,7 +4,7 @@ cd ../.. > /dev/null # download language model cd models/lm > /dev/null -sh download_lm_en.sh +bash download_lm_en.sh if [ $? -ne 0 ]; then exit 1 fi @@ -13,7 +13,7 @@ cd - > /dev/null # download well-trained model cd models/librispeech > /dev/null -sh download_model.sh +bash download_model.sh if [ $? -ne 0 ]; then exit 1 fi @@ -24,10 +24,8 @@ cd - > /dev/null CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 \ python -u test.py \ --batch_size=128 \ ---trainer_count=8 \ --beam_size=500 \ --num_proc_bsearch=8 \ ---num_proc_data=8 \ --num_conv_layers=2 \ --num_rnn_layers=3 \ --rnn_layer_size=2048 \ @@ -41,7 +39,7 @@ python -u test.py \ --test_manifest='data/librispeech/manifest.test-clean' \ --mean_std_path='models/librispeech/mean_std.npz' \ --vocab_path='models/librispeech/vocab.txt' \ ---model_path='models/librispeech/params.tar.gz' \ +--model_path='models/librispeech' \ --lang_model_path='models/lm/common_crawl_00.prune01111.trie.klm' \ --decoding_method='ctc_beam_search' \ --error_rate_type='wer' \ diff --git a/examples/librispeech/run_train.sh b/examples/librispeech/run_train.sh index 87e08721..5917a1d5 100644 --- a/examples/librispeech/run_train.sh +++ b/examples/librispeech/run_train.sh @@ -3,17 +3,19 @@ cd ../.. > /dev/null # train model -# if you wish to resume from an exists model, uncomment --init_model_path +# if you wish to resume from an exists model, uncomment --init_from_pretrain_model +export FLAGS_sync_nccl_allreduce=0 + CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 \ python -u train.py \ ---batch_size=160 \ ---trainer_count=8 \ ---num_passes=50 \ ---num_proc_data=16 \ +--batch_size=20 \ +--num_epoch=50 \ --num_conv_layers=2 \ --num_rnn_layers=3 \ --rnn_layer_size=2048 \ --num_iter_print=100 \ +--save_epoch=1 \ +--num_samples=280000 \ --learning_rate=5e-4 \ --max_duration=27.0 \ --min_duration=0.0 \ @@ -30,7 +32,7 @@ python -u train.py \ --output_model_dir='./checkpoints/libri' \ --augment_conf_path='conf/augmentation.config' \ --specgram_type='linear' \ ---shuffle_method='batch_shuffle_clipped' +--shuffle_method='batch_shuffle_clipped' \ if [ $? -ne 0 ]; then echo "Failed in training!" diff --git a/examples/librispeech/run_tune.sh b/examples/librispeech/run_tune.sh index 9fc9cbb9..af6e9daf 100644 --- a/examples/librispeech/run_tune.sh +++ b/examples/librispeech/run_tune.sh @@ -7,7 +7,6 @@ CUDA_VISIBLE_DEVICES=0,1,2,3 \ python -u tools/tune.py \ --num_batches=-1 \ --batch_size=128 \ ---trainer_count=4 \ --beam_size=500 \ --num_proc_bsearch=12 \ --num_conv_layers=2 \ @@ -27,7 +26,7 @@ python -u tools/tune.py \ --tune_manifest='data/librispeech/manifest.dev-clean' \ --mean_std_path='data/librispeech/mean_std.npz' \ --vocab_path='models/librispeech/vocab.txt' \ ---model_path='models/librispeech/params.tar.gz' \ +--model_path='models/librispeech' \ --lang_model_path='models/lm/common_crawl_00.prune01111.trie.klm' \ --error_rate_type='wer' \ --specgram_type='linear' diff --git a/examples/tiny/run_data.sh b/examples/tiny/run_data.sh index ba55d284..1428194d 100644 --- a/examples/tiny/run_data.sh +++ b/examples/tiny/run_data.sh @@ -7,11 +7,10 @@ if [ ! -e data/tiny ]; then mkdir data/tiny fi - # download data, generate manifests PYTHONPATH=.:$PYTHONPATH python data/librispeech/librispeech.py \ --manifest_prefix='data/tiny/manifest' \ ---target_dir='~/.cache/paddle/dataset/speech/libri' \ +--target_dir='./dataset/librispeech' \ --full_download='False' if [ $? -ne 0 ]; then @@ -21,12 +20,11 @@ fi head -n 64 data/tiny/manifest.dev-clean > data/tiny/manifest.tiny - # build vocabulary python tools/build_vocab.py \ --count_threshold=0 \ --vocab_path='data/tiny/vocab.txt' \ ---manifest_paths='data/tiny/manifest.dev-clean' +--manifest_paths='data/tiny/manifest.tiny' if [ $? -ne 0 ]; then echo "Build vocabulary failed. Terminated." @@ -47,5 +45,5 @@ if [ $? -ne 0 ]; then fi -echo "Tiny data preparation done." +echo "LibriSpeech Data preparation done." exit 0 diff --git a/examples/tiny/run_infer.sh b/examples/tiny/run_infer.sh index 0cc140c8..bded0e7b 100644 --- a/examples/tiny/run_infer.sh +++ b/examples/tiny/run_infer.sh @@ -4,7 +4,7 @@ cd ../.. > /dev/null # download language model cd models/lm > /dev/null -sh download_lm_en.sh +bash download_lm_en.sh if [ $? -ne 0 ]; then exit 1 fi @@ -15,7 +15,6 @@ cd - > /dev/null CUDA_VISIBLE_DEVICES=0 \ python -u infer.py \ --num_samples=10 \ ---trainer_count=1 \ --beam_size=500 \ --num_proc_bsearch=8 \ --num_conv_layers=2 \ @@ -28,10 +27,10 @@ python -u infer.py \ --use_gru=False \ --use_gpu=True \ --share_rnn_weights=True \ ---infer_manifest='data/tiny/manifest.tiny' \ +--infer_manifest='data/tiny/manifest.test-clean' \ --mean_std_path='data/tiny/mean_std.npz' \ --vocab_path='data/tiny/vocab.txt' \ ---model_path='checkpoints/tiny/params.pass-19.tar.gz' \ +--model_path='./checkpoints/tiny/step_final' \ --lang_model_path='models/lm/common_crawl_00.prune01111.trie.klm' \ --decoding_method='ctc_beam_search' \ --error_rate_type='wer' \ diff --git a/examples/tiny/run_infer_golden.sh b/examples/tiny/run_infer_golden.sh index cf9aa84c..33662622 100644 --- a/examples/tiny/run_infer_golden.sh +++ b/examples/tiny/run_infer_golden.sh @@ -4,7 +4,7 @@ cd ../.. > /dev/null # download language model cd models/lm > /dev/null -sh download_lm_en.sh +bash download_lm_en.sh if [ $? -ne 0 ]; then exit 1 fi @@ -13,7 +13,7 @@ cd - > /dev/null # download well-trained model cd models/librispeech > /dev/null -sh download_model.sh +bash download_model.sh if [ $? -ne 0 ]; then exit 1 fi @@ -24,7 +24,6 @@ cd - > /dev/null CUDA_VISIBLE_DEVICES=0 \ python -u infer.py \ --num_samples=10 \ ---trainer_count=1 \ --beam_size=500 \ --num_proc_bsearch=8 \ --num_conv_layers=2 \ @@ -40,7 +39,7 @@ python -u infer.py \ --infer_manifest='data/tiny/manifest.test-clean' \ --mean_std_path='models/librispeech/mean_std.npz' \ --vocab_path='models/librispeech/vocab.txt' \ ---model_path='models/librispeech/params.tar.gz' \ +--model_path='models/librispeech' \ --lang_model_path='models/lm/common_crawl_00.prune01111.trie.klm' \ --decoding_method='ctc_beam_search' \ --error_rate_type='wer' \ diff --git a/examples/tiny/run_test.sh b/examples/tiny/run_test.sh index a9fe5b93..1dfc65e1 100644 --- a/examples/tiny/run_test.sh +++ b/examples/tiny/run_test.sh @@ -4,7 +4,7 @@ cd ../.. > /dev/null # download language model cd models/lm > /dev/null -sh download_lm_en.sh +bash download_lm_en.sh if [ $? -ne 0 ]; then exit 1 fi @@ -14,11 +14,9 @@ cd - > /dev/null # evaluate model CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 \ python -u test.py \ ---batch_size=16 \ ---trainer_count=8 \ +--batch_size=128 \ --beam_size=500 \ --num_proc_bsearch=8 \ ---num_proc_data=8 \ --num_conv_layers=2 \ --num_rnn_layers=3 \ --rnn_layer_size=2048 \ @@ -29,10 +27,10 @@ python -u test.py \ --use_gru=False \ --use_gpu=True \ --share_rnn_weights=True \ ---test_manifest='data/tiny/manifest.tiny' \ +--test_manifest='data/tiny/manifest.test-clean' \ --mean_std_path='data/tiny/mean_std.npz' \ --vocab_path='data/tiny/vocab.txt' \ ---model_path='checkpoints/tiny/params.pass-19.tar.gz' \ +--model_path='checkpoints/tiny/step_final' \ --lang_model_path='models/lm/common_crawl_00.prune01111.trie.klm' \ --decoding_method='ctc_beam_search' \ --error_rate_type='wer' \ diff --git a/examples/tiny/run_test_golden.sh b/examples/tiny/run_test_golden.sh index e87ce6ee..54255265 100644 --- a/examples/tiny/run_test_golden.sh +++ b/examples/tiny/run_test_golden.sh @@ -4,7 +4,7 @@ cd ../.. > /dev/null # download language model cd models/lm > /dev/null -sh download_lm_en.sh +bash download_lm_en.sh if [ $? -ne 0 ]; then exit 1 fi @@ -13,7 +13,7 @@ cd - > /dev/null # download well-trained model cd models/librispeech > /dev/null -sh download_model.sh +bash download_model.sh if [ $? -ne 0 ]; then exit 1 fi @@ -24,10 +24,8 @@ cd - > /dev/null CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 \ python -u test.py \ --batch_size=128 \ ---trainer_count=8 \ --beam_size=500 \ --num_proc_bsearch=8 \ ---num_proc_data=8 \ --num_conv_layers=2 \ --num_rnn_layers=3 \ --rnn_layer_size=2048 \ @@ -41,7 +39,7 @@ python -u test.py \ --test_manifest='data/tiny/manifest.test-clean' \ --mean_std_path='models/librispeech/mean_std.npz' \ --vocab_path='models/librispeech/vocab.txt' \ ---model_path='models/librispeech/params.tar.gz' \ +--model_path='models/librispeech' \ --lang_model_path='models/lm/common_crawl_00.prune01111.trie.klm' \ --decoding_method='ctc_beam_search' \ --error_rate_type='wer' \ diff --git a/examples/tiny/run_train.sh b/examples/tiny/run_train.sh index e03a8aff..9d436fb6 100644 --- a/examples/tiny/run_train.sh +++ b/examples/tiny/run_train.sh @@ -3,17 +3,18 @@ cd ../.. > /dev/null # train model -# if you wish to resume from an exists model, uncomment --init_model_path +# if you wish to resume from an exists model, uncomment --init_from_pretrain_model +export FLAGS_sync_nccl_allreduce=0 CUDA_VISIBLE_DEVICES=0,1,2,3 \ python -u train.py \ ---batch_size=16 \ ---trainer_count=4 \ ---num_passes=20 \ ---num_proc_data=1 \ +--batch_size=4 \ +--num_epoch=20 \ --num_conv_layers=2 \ --num_rnn_layers=3 \ --rnn_layer_size=2048 \ ---num_iter_print=100 \ +--num_iter_print=1 \ +--save_epoch=1 \ +--num_samples=64 \ --learning_rate=1e-5 \ --max_duration=27.0 \ --min_duration=0.0 \ @@ -30,10 +31,10 @@ python -u train.py \ --output_model_dir='./checkpoints/tiny' \ --augment_conf_path='conf/augmentation.config' \ --specgram_type='linear' \ ---shuffle_method='batch_shuffle_clipped' +--shuffle_method='batch_shuffle_clipped' \ if [ $? -ne 0 ]; then - echo "Fail in training!" + echo "Failed in training!" exit 1 fi diff --git a/examples/tiny/run_tune.sh b/examples/tiny/run_tune.sh index 89f8adf4..87bcb67b 100644 --- a/examples/tiny/run_tune.sh +++ b/examples/tiny/run_tune.sh @@ -3,11 +3,10 @@ cd ../.. > /dev/null # grid-search for hyper-parameters in language model -CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 \ +CUDA_VISIBLE_DEVICES=0,1,2,3 \ python -u tools/tune.py \ ---num_batches=1 \ ---batch_size=24 \ ---trainer_count=8 \ +--num_batches=-1 \ +--batch_size=128 \ --beam_size=500 \ --num_proc_bsearch=12 \ --num_conv_layers=2 \ @@ -24,10 +23,10 @@ python -u tools/tune.py \ --use_gru=False \ --use_gpu=True \ --share_rnn_weights=True \ ---tune_manifest='data/tiny/manifest.tiny' \ +--tune_manifest='data/tiny/manifest.dev-clean' \ --mean_std_path='data/tiny/mean_std.npz' \ --vocab_path='data/tiny/vocab.txt' \ ---model_path='checkpoints/params.pass-9.tar.gz' \ +--model_path='models/librispeech' \ --lang_model_path='models/lm/common_crawl_00.prune01111.trie.klm' \ --error_rate_type='wer' \ --specgram_type='linear' diff --git a/infer.py b/infer.py index f4d75685..4dd1f275 100644 --- a/infer.py +++ b/infer.py @@ -3,9 +3,13 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +import sys +reload(sys) +sys.setdefaultencoding('utf-8') + import argparse import functools -import paddle.v2 as paddle +import paddle.fluid as fluid from data_utils.data import DataGenerator from model_utils.model import DeepSpeech2Model from utils.error_rate import wer, cer @@ -15,7 +19,6 @@ parser = argparse.ArgumentParser(description=__doc__) add_arg = functools.partial(add_arguments, argparser=parser) # yapf: disable add_arg('num_samples', int, 10, "# of samples to infer.") -add_arg('trainer_count', int, 8, "# of Trainers (CPUs or GPUs).") add_arg('beam_size', int, 500, "Beam search width.") add_arg('num_proc_bsearch', int, 8, "# of CPUs for beam search.") add_arg('num_conv_layers', int, 2, "# of convolution layers.") @@ -63,20 +66,25 @@ args = parser.parse_args() def infer(): """Inference for DeepSpeech2.""" + if args.use_gpu: + place = fluid.CUDAPlace(0) + else: + place = fluid.CPUPlace() + data_generator = DataGenerator( vocab_filepath=args.vocab_path, mean_std_filepath=args.mean_std_path, augmentation_config='{}', specgram_type=args.specgram_type, - num_threads=1, - keep_transcription_text=True) + keep_transcription_text=True, + place = place, + is_training = False) batch_reader = data_generator.batch_reader_creator( manifest_path=args.infer_manifest, batch_size=args.num_samples, - min_batch_size=1, sortagrad=False, shuffle_method=None) - infer_data = batch_reader().next() + infer_data = next(batch_reader()) ds2_model = DeepSpeech2Model( vocab_size=data_generator.vocab_size, @@ -84,16 +92,19 @@ def infer(): num_rnn_layers=args.num_rnn_layers, rnn_layer_size=args.rnn_layer_size, use_gru=args.use_gru, - pretrained_model_path=args.model_path, - share_rnn_weights=args.share_rnn_weights) + share_rnn_weights=args.share_rnn_weights, + place=place, + init_from_pretrain_model=args.model_path) # decoders only accept string encoded in utf-8 vocab_list = [chars.encode("utf-8") for chars in data_generator.vocab_list] if args.decoding_method == "ctc_greedy": ds2_model.logger.info("start inference ...") - probs_split = ds2_model.infer_batch_probs(infer_data=infer_data, + probs_split = ds2_model.infer_batch_probs( + infer_data=infer_data, feeding_dict=data_generator.feeding) + result_transcripts = ds2_model.decode_batch_greedy( probs_split=probs_split, vocab_list=vocab_list) @@ -101,9 +112,11 @@ def infer(): ds2_model.init_ext_scorer(args.alpha, args.beta, args.lang_model_path, vocab_list) ds2_model.logger.info("start inference ...") - probs_split = ds2_model.infer_batch_probs(infer_data=infer_data, + probs_split= ds2_model.infer_batch_probs( + infer_data=infer_data, feeding_dict=data_generator.feeding) - result_transcripts = ds2_model.decode_batch_beam_search( + + result_transcripts= ds2_model.decode_batch_beam_search( probs_split=probs_split, beam_alpha=args.alpha, beam_beta=args.beta, @@ -114,7 +127,7 @@ def infer(): num_processes=args.num_proc_bsearch) error_rate_func = cer if args.error_rate_type == 'cer' else wer - target_transcripts = [data[1] for data in infer_data] + target_transcripts = infer_data[1] for target, result in zip(target_transcripts, result_transcripts): print("\nTarget Transcription: %s\nOutput Transcription: %s" % (target, result)) @@ -125,9 +138,6 @@ def infer(): def main(): print_arguments(args) - paddle.init(use_gpu=args.use_gpu, - rnn_use_batch=True, - trainer_count=args.trainer_count) infer() diff --git a/model_utils/model.py b/model_utils/model.py index 4b3764bf..ecc3f28a 100644 --- a/model_utils/model.py +++ b/model_utils/model.py @@ -10,8 +10,13 @@ import logging import gzip import copy import inspect +import cPickle as pickle +import collections +import multiprocessing +import numpy as np from distutils.dir_util import mkpath -import paddle.v2 as paddle +import paddle.fluid as fluid +import paddle.fluid.compiler as compiler from decoders.swig_wrapper import Scorer from decoders.swig_wrapper import ctc_greedy_decoder from decoders.swig_wrapper import ctc_beam_search_decoder_batch @@ -32,37 +37,197 @@ class DeepSpeech2Model(object): :type num_rnn_layers: int :param rnn_layer_size: RNN layer size (number of RNN cells). :type rnn_layer_size: int - :param pretrained_model_path: Pretrained model path. If None, will train - from stratch. - :type pretrained_model_path: basestring|None + :param use_gru: Use gru if set True. Use simple rnn if set False. + :type use_gru: bool :param share_rnn_weights: Whether to share input-hidden weights between forward and backward directional RNNs.Notice that for GRU, weight sharing is not supported. :type share_rnn_weights: bool + :param place: Program running place. + :type place: CPU or GPU + :param init_from_pretrained_model: Pretrained model path. If None, will train + from stratch. + :type init_from_pretrained_model: string|None + :param output_model_dir: Output model directory. If None, output to current directory. + :type output_model_dir: string|None """ - def __init__(self, vocab_size, num_conv_layers, num_rnn_layers, - rnn_layer_size, use_gru, pretrained_model_path, - share_rnn_weights): - self._create_network(vocab_size, num_conv_layers, num_rnn_layers, - rnn_layer_size, use_gru, share_rnn_weights) - self._create_parameters(pretrained_model_path) - self._inferer = None - self._loss_inferer = None - self._ext_scorer = None + def __init__(self, + vocab_size, + num_conv_layers, + num_rnn_layers, + rnn_layer_size, + use_gru=False, + share_rnn_weights=True, + place=fluid.CPUPlace(), + init_from_pretrain_model=None, + output_model_dir=None): + self._vocab_size = vocab_size self._num_conv_layers = num_conv_layers + self._num_rnn_layers = num_rnn_layers + self._rnn_layer_size = rnn_layer_size + self._use_gru = use_gru + self._share_rnn_weights = share_rnn_weights + self._place = place + self._init_from_pretrain_model = init_from_pretrain_model + self._output_model_dir = output_model_dir + self._ext_scorer = None self.logger = logging.getLogger("") self.logger.setLevel(level=logging.INFO) + def create_network(self, is_infer=False): + """Create data layers and model network. + :param is_training: Whether to create a network for training. + :type is_training: bool + :return reader: Reader for input. + :rtype reader: read generater + :return log_probs: An output unnormalized log probability layer. + :rtype lig_probs: Varable + :return loss: A ctc loss layer. + :rtype loss: Variable + """ + + if not is_infer: + input_fields = { + 'names': ['audio_data', 'text_data', 'seq_len_data', 'masks'], + 'shapes': [[-1, 161, 161], [-1, 1], [-1, 1], [-1, 32, 81, 1]], + 'dtypes': ['float32', 'int32', 'int64', 'float32'], + 'lod_levels': [0, 1, 0, 0] + } + + inputs = [ + fluid.layers.data( + name=input_fields['names'][i], + shape=input_fields['shapes'][i], + dtype=input_fields['dtypes'][i], + lod_level=input_fields['lod_levels'][i]) + for i in range(len(input_fields['names'])) + ] + + reader = fluid.io.PyReader( + feed_list=inputs, + capacity=64, + iterable=False, + use_double_buffer=True) + + (audio_data, text_data, seq_len_data, masks) = inputs + else: + audio_data = fluid.layers.data( + name='audio_data', + shape=[-1, 161, 161], + dtype='float32', + lod_level=0) + seq_len_data = fluid.layers.data( + name='seq_len_data', shape=[-1, 1], dtype='int64', lod_level=0) + masks = fluid.layers.data( + name='masks', + shape=[-1, 32, 81, 1], + dtype='float32', + lod_level=0) + text_data = None + reader = fluid.DataFeeder([audio_data, seq_len_data, masks], + self._place) + + log_probs, loss = deep_speech_v2_network( + audio_data=audio_data, + text_data=text_data, + seq_len_data=seq_len_data, + masks=masks, + dict_size=self._vocab_size, + num_conv_layers=self._num_conv_layers, + num_rnn_layers=self._num_rnn_layers, + rnn_size=self._rnn_layer_size, + use_gru=self._use_gru, + share_rnn_weights=self._share_rnn_weights) + return reader, log_probs, loss + + def init_from_pretrain_model(self, exe, program): + '''Init params from pretrain model. ''' + + assert isinstance(self._init_from_pretrain_model, str) + + if not os.path.exists(self._init_from_pretrain_model): + print(self._init_from_pretrain_model) + raise Warning("The pretrained params do not exist.") + return False + fluid.io.load_params( + exe, + self._init_from_pretrain_model, + main_program=program, + filename="params.pdparams") + + print("finish initing model from pretrained params from %s" % + (self._init_from_pretrain_model)) + + pre_epoch = 0 + dir_name = self._init_from_pretrain_model.split('_') + if len(dir_name) >= 2 and dir_name[-2].endswith('epoch') and dir_name[ + -1].isdigit(): + pre_epoch = int(dir_name[-1]) + + return pre_epoch + 1 + + def save_param(self, exe, program, dirname): + '''Save model params to dirname''' + + assert isinstance(self._output_model_dir, str) + + param_dir = os.path.join(self._output_model_dir) + + if not os.path.exists(param_dir): + os.mkdir(param_dir) + + fluid.io.save_params( + exe, + os.path.join(param_dir, dirname), + main_program=program, + filename="params.pdparams") + print("save parameters at %s" % (os.path.join(param_dir, dirname))) + + return True + + def test(self, exe, dev_batch_reader, test_program, test_pyreader, + fetch_list): + '''Test the model. + + :param exe:The executor of program. + :type exe: Executor + :param dev_batch_reader: The reader of test dataa. + :type dev_batch_reader: read generator + :param test_program: The program of test. + :type test_program: Program + :param test_pyreader: Pyreader of test. + :type test_pyreader: Pyreader + :param fetch_list: Fetch list. + :type fetch_list: list + :return: An output unnormalized log probability. + :rtype: array + ''' + test_pyreader.start() + epoch_loss = [] + while True: + try: + each_loss = exe.run( + program=test_program, + fetch_list=fetch_list, + return_numpy=False) + epoch_loss.extend(np.array(each_loss[0])) + + except fluid.core.EOFException: + test_pyreader.reset() + break + return np.mean(np.array(epoch_loss)) + def train(self, train_batch_reader, dev_batch_reader, feeding_dict, learning_rate, gradient_clipping, - num_passes, - output_model_dir, - is_local=True, + num_epoch, + batch_size, + num_samples, + save_epoch=100, num_iterations_print=100, test_off=False): """Train the model. @@ -78,104 +243,138 @@ class DeepSpeech2Model(object): :type learning_rate: float :param gradient_clipping: Gradient clipping threshold. :type gradient_clipping: float - :param num_passes: Number of training epochs. - :type num_passes: int + :param num_epoch: Number of training epochs. + :type num_epoch: int + :param batch_size: Number of batch size. + :type batch_size: int + :param num_samples: The num of train samples. + :type num_samples: int + :param save_epoch: Number of training iterations for save checkpoint and params. + :type save_epoch: int :param num_iterations_print: Number of training iterations for printing a training loss. - :type rnn_iteratons_print: int - :param is_local: Set to False if running with pserver with multi-nodes. - :type is_local: bool - :param output_model_dir: Directory for saving the model (every pass). - :type output_model_dir: basestring + :type num_iteratons_print: int :param test_off: Turn off testing. :type test_off: bool """ # prepare model output directory - if not os.path.exists(output_model_dir): - mkpath(output_model_dir) + if not os.path.exists(self._output_model_dir): + mkpath(self._output_model_dir) - # adapt the feeding dict and reader according to the network + # adapt the feeding dict according to the network adapted_feeding_dict = self._adapt_feeding_dict(feeding_dict) - adapted_train_batch_reader = self._adapt_data(train_batch_reader) - adapted_dev_batch_reader = self._adapt_data(dev_batch_reader) - - # prepare optimizer and trainer - optimizer = paddle.optimizer.Adam( - learning_rate=learning_rate, - gradient_clipping_threshold=gradient_clipping) - trainer = paddle.trainer.SGD( - cost=self._loss, - parameters=self._parameters, - update_equation=optimizer, - is_local=is_local) - - # create event handler - def event_handler(event): - global start_time, cost_sum, cost_counter - if isinstance(event, paddle.event.EndIteration): - cost_sum += event.cost - cost_counter += 1 - if (event.batch_id + 1) % num_iterations_print == 0: - output_model_path = os.path.join(output_model_dir, - "params.latest.tar.gz") - with gzip.open(output_model_path, 'w') as f: - trainer.save_parameter_to_tar(f) - print("\nPass: %d, Batch: %d, TrainCost: %f" % - (event.pass_id, event.batch_id + 1, - cost_sum / cost_counter)) - cost_sum, cost_counter = 0.0, 0 - else: - sys.stdout.write('.') - sys.stdout.flush() - if isinstance(event, paddle.event.BeginPass): - start_time = time.time() - cost_sum, cost_counter = 0.0, 0 - if isinstance(event, paddle.event.EndPass): - if test_off: - print("\n------- Time: %d sec, Pass: %d" % - (time.time() - start_time, event.pass_id)) - else: - result = trainer.test( - reader=adapted_dev_batch_reader, - feeding=adapted_feeding_dict) - print( - "\n------- Time: %d sec, Pass: %d, " - "ValidationCost: %s" % - (time.time() - start_time, event.pass_id, result.cost)) - output_model_path = os.path.join( - output_model_dir, "params.pass-%d.tar.gz" % event.pass_id) - with gzip.open(output_model_path, 'w') as f: - trainer.save_parameter_to_tar(f) - - # run train - trainer.train( - reader=adapted_train_batch_reader, - event_handler=event_handler, - num_passes=num_passes, - feeding=adapted_feeding_dict) - - # TODO(@pkuyym) merge this function into infer_batch - def infer_loss_batch(self, infer_data): - """Model inference. Infer the ctc loss for a batch of speech - utterances. - - :param infer_data: List of utterances to infer, with each utterance a - tuple of audio features and transcription text (empty - string). - :type infer_data: list - :return: List of ctc loss. - :rtype: List of float - """ - # define inferer - if self._loss_inferer == None: - self._loss_inferer = paddle.inference.Inference( - output_layer=self._loss, parameters=self._parameters) - # run inference - return self._loss_inferer.infer(input=infer_data) + + if isinstance(self._place, fluid.CUDAPlace): + dev_count = fluid.core.get_cuda_device_count() + else: + dev_count = int(os.environ.get('CPU_NUM', 1)) + + # prepare the network + train_program = fluid.Program() + startup_prog = fluid.Program() + with fluid.program_guard(train_program, startup_prog): + with fluid.unique_name.guard(): + train_pyreader, log_probs, ctc_loss = self.create_network() + # prepare optimizer + optimizer = fluid.optimizer.AdamOptimizer( + learning_rate=fluid.layers.exponential_decay( + learning_rate=learning_rate, + decay_steps=num_samples / batch_size / dev_count, + decay_rate=0.83, + staircase=True)) + fluid.clip.set_gradient_clip( + clip=fluid.clip.GradientClipByGlobalNorm( + clip_norm=gradient_clipping)) + optimizer.minimize(loss=ctc_loss) + + test_prog = fluid.Program() + with fluid.program_guard(test_prog, startup_prog): + with fluid.unique_name.guard(): + test_pyreader, _, ctc_loss = self.create_network() + + test_prog = test_prog.clone(for_test=True) + + exe = fluid.Executor(self._place) + exe.run(startup_prog) + + # init from some pretrain models, to better solve the current task + pre_epoch = 0 + if self._init_from_pretrain_model: + pre_epoch = self.init_from_pretrain_model(exe, train_program) + + build_strategy = compiler.BuildStrategy() + exec_strategy = fluid.ExecutionStrategy() + + # pass the build_strategy to with_data_parallel API + compiled_prog = compiler.CompiledProgram( + train_program).with_data_parallel( + loss_name=ctc_loss.name, + build_strategy=build_strategy, + exec_strategy=exec_strategy) + + train_pyreader.decorate_batch_generator(train_batch_reader) + test_pyreader.decorate_batch_generator(dev_batch_reader) + + # run train + for epoch_id in range(num_epoch): + train_pyreader.start() + epoch_loss = [] + time_begin = time.time() + batch_id = 0 + step = 0 + while True: + try: + fetch_list = [ctc_loss.name] + + if batch_id % num_iterations_print == 0: + fetch = exe.run( + program=compiled_prog, + fetch_list=fetch_list, + return_numpy=False) + each_loss = fetch[0] + epoch_loss.extend(np.array(each_loss[0]) / batch_size) + + print("epoch: %d, batch: %d, train loss: %f\n" % + (epoch_id, batch_id, + np.mean(each_loss[0]) / batch_size)) + + else: + each_loss = exe.run( + program=compiled_prog, + fetch_list=[], + return_numpy=False) + + batch_id = batch_id + 1 + except fluid.core.EOFException: + train_pyreader.reset() + break + time_end = time.time() + used_time = time_end - time_begin + if test_off: + print("\n--------Time: %f sec, epoch: %d, train loss: %f\n" % + (used_time, epoch_id, np.mean(np.array(epoch_loss)))) + else: + print('\n----------Begin test...') + test_loss = self.test( + exe, + dev_batch_reader=dev_batch_reader, + test_program=test_prog, + test_pyreader=test_pyreader, + fetch_list=[ctc_loss]) + print( + "--------Time: %f sec, epoch: %d, train loss: %f, test loss: %f" + % (used_time, epoch_id + pre_epoch, + np.mean(np.array(epoch_loss)), test_loss / batch_size)) + if (epoch_id + 1) % save_epoch == 0: + self.save_param(exe, train_program, + "epoch_" + str(epoch_id + pre_epoch)) + + self.save_param(exe, train_program, "step_final") + + print("\n------------Training finished!!!-------------") def infer_batch_probs(self, infer_data, feeding_dict): """Infer the prob matrices for a batch of speech utterances. - :param infer_data: List of utterances to infer, with each utterance consisting of a tuple of audio features and transcription text (empty string). @@ -188,26 +387,55 @@ class DeepSpeech2Model(object): :rtype: List of matrix """ # define inferer - if self._inferer == None: - self._inferer = paddle.inference.Inference( - output_layer=self._log_probs, parameters=self._parameters) + infer_program = fluid.Program() + startup_prog = fluid.Program() + + # adapt the feeding dict according to the network adapted_feeding_dict = self._adapt_feeding_dict(feeding_dict) - adapted_infer_data = self._adapt_data(infer_data) + + # prepare the network + with fluid.program_guard(infer_program, startup_prog): + with fluid.unique_name.guard(): + feeder, log_probs, _ = self.create_network(is_infer=True) + + infer_program = infer_program.clone(for_test=True) + exe = fluid.Executor(self._place) + exe.run(startup_prog) + + # init param from pretrain_model + if not self._init_from_pretrain_model: + exit("No pretrain model file path!") + self.init_from_pretrain_model(exe, infer_program) + + infer_results = [] + time_begin = time.time() + # run inference - infer_results = self._inferer.infer( - input=adapted_infer_data, feeding=adapted_feeding_dict) - start_pos = [0] * (len(adapted_infer_data) + 1) - for i in xrange(len(adapted_infer_data)): - start_pos[i + 1] = start_pos[i] + adapted_infer_data[i][3][0] + for i in range(infer_data[0].shape[0]): + each_log_probs = exe.run( + program=infer_program, + feed=feeder.feed( + [[infer_data[0][i], infer_data[2][i], infer_data[3][i]]]), + fetch_list=[log_probs], + return_numpy=False) + infer_results.extend(np.array(each_log_probs[0])) + + # slice result + infer_results = np.array(infer_results) + seq_len = (infer_data[2] - 1) // 3 + 1 + + start_pos = [0] * (infer_data[0].shape[0] + 1) + for i in range(infer_data[0].shape[0]): + start_pos[i + 1] = start_pos[i] + seq_len[i][0] probs_split = [ infer_results[start_pos[i]:start_pos[i + 1]] - for i in xrange(0, len(adapted_infer_data)) + for i in range(0, infer_data[0].shape[0]) ] + return probs_split def decode_batch_greedy(self, probs_split, vocab_list): """Decode by best path for a batch of probs matrix input. - :param probs_split: List of 2-D probability matrix, and each consists of prob vectors for one speech utterancce. :param probs_split: List of matrix @@ -221,12 +449,12 @@ class DeepSpeech2Model(object): output_transcription = ctc_greedy_decoder( probs_seq=probs, vocabulary=vocab_list) results.append(output_transcription) + print(results) return results def init_ext_scorer(self, beam_alpha, beam_beta, language_model_path, vocab_list): """Initialize the external scorer. - :param beam_alpha: Parameter associated with language model. :type beam_alpha: float :param beam_beta: Parameter associated with word count. @@ -261,7 +489,6 @@ class DeepSpeech2Model(object): beam_size, cutoff_prob, cutoff_top_n, vocab_list, num_processes): """Decode by beam search for a batch of probs matrix input. - :param probs_split: List of 2-D probability matrix, and each consists of prob vectors for one speech utterancce. :param probs_split: List of matrix @@ -319,124 +546,16 @@ class DeepSpeech2Model(object): if isinstance(feeding_dict, dict): adapted_feeding_dict["sequence_offset"] = len(adapted_feeding_dict) adapted_feeding_dict["sequence_length"] = len(adapted_feeding_dict) - for i in xrange(self._num_conv_layers): + for i in range(self._num_conv_layers): adapted_feeding_dict["conv%d_index_range" %i] = \ len(adapted_feeding_dict) elif isinstance(feeding_dict, list): adapted_feeding_dict.append("sequence_offset") adapted_feeding_dict.append("sequence_length") - for i in xrange(self._num_conv_layers): + for i in range(self._num_conv_layers): adapted_feeding_dict.append("conv%d_index_range" % i) else: raise ValueError("Type of feeding_dict is %s, not supported." % type(feeding_dict)) return adapted_feeding_dict - - def _adapt_data(self, data): - """Adapt data according to network struct. - - For each convolution layer in the conv_group, to remove impacts from - padding data, we can multiply zero to the padding part of the outputs - of each batch normalization layer. We add a scale_sub_region layer after - each batch normalization layer to reset the padding data. - For rnn layers, to remove impacts from padding data, we can truncate the - padding part before output data feeded into the first rnn layer. We use - sub_seq layer to achieve this. - - :param data: Data from data_provider. - :type data: list|function - :return: Adapted data. - :rtype: list|function - """ - - def adapt_instance(instance): - if len(instance) < 2 or len(instance) > 3: - raise ValueError("Size of instance should be 2 or 3.") - padded_audio = instance[0] - text = instance[1] - # no padding part - if len(instance) == 2: - audio_len = padded_audio.shape[1] - else: - audio_len = instance[2] - adapted_instance = [padded_audio, text] - # Stride size for conv0 is (3, 2) - # Stride size for conv1 to convN is (1, 2) - # Same as the network, hard-coded here - padded_conv0_h = (padded_audio.shape[0] - 1) // 2 + 1 - padded_conv0_w = (padded_audio.shape[1] - 1) // 3 + 1 - valid_w = (audio_len - 1) // 3 + 1 - adapted_instance += [ - [0], # sequence offset, always 0 - [valid_w], # valid sequence length - # Index ranges for channel, height and width - # Please refer scale_sub_region layer to see details - [1, 32, 1, padded_conv0_h, valid_w + 1, padded_conv0_w] - ] - pre_padded_h = padded_conv0_h - for i in xrange(self._num_conv_layers - 1): - padded_h = (pre_padded_h - 1) // 2 + 1 - pre_padded_h = padded_h - adapted_instance += [ - [1, 32, 1, padded_h, valid_w + 1, padded_conv0_w] - ] - return adapted_instance - - if isinstance(data, list): - return map(adapt_instance, data) - elif inspect.isgeneratorfunction(data): - - def adapted_reader(): - for instance in data(): - yield map(adapt_instance, instance) - - return adapted_reader - else: - raise ValueError("Type of data is %s, not supported." % type(data)) - - def _create_parameters(self, model_path=None): - """Load or create model parameters.""" - if model_path is None: - self._parameters = paddle.parameters.create(self._loss) - else: - self._parameters = paddle.parameters.Parameters.from_tar( - gzip.open(model_path)) - - def _create_network(self, vocab_size, num_conv_layers, num_rnn_layers, - rnn_layer_size, use_gru, share_rnn_weights): - """Create data layers and model network.""" - # paddle.data_type.dense_array is used for variable batch input. - # The size 161 * 161 is only an placeholder value and the real shape - # of input batch data will be induced during training. - audio_data = paddle.layer.data( - name="audio_spectrogram", - type=paddle.data_type.dense_array(161 * 161)) - text_data = paddle.layer.data( - name="transcript_text", - type=paddle.data_type.integer_value_sequence(vocab_size)) - seq_offset_data = paddle.layer.data( - name='sequence_offset', - type=paddle.data_type.integer_value_sequence(1)) - seq_len_data = paddle.layer.data( - name='sequence_length', - type=paddle.data_type.integer_value_sequence(1)) - index_range_datas = [] - for i in xrange(num_rnn_layers): - index_range_datas.append( - paddle.layer.data( - name='conv%d_index_range' % i, - type=paddle.data_type.dense_vector(6))) - - self._log_probs, self._loss = deep_speech_v2_network( - audio_data=audio_data, - text_data=text_data, - seq_offset_data=seq_offset_data, - seq_len_data=seq_len_data, - index_range_datas=index_range_datas, - dict_size=vocab_size, - num_conv_layers=num_conv_layers, - num_rnn_layers=num_rnn_layers, - rnn_size=rnn_layer_size, - use_gru=use_gru, - share_rnn_weights=share_rnn_weights) diff --git a/model_utils/network.py b/model_utils/network.py index 7b4b8ab2..0ba3a916 100644 --- a/model_utils/network.py +++ b/model_utils/network.py @@ -1,188 +1,322 @@ -"""Contains DeepSpeech2 layers and networks.""" from __future__ import absolute_import from __future__ import division from __future__ import print_function -import paddle.v2 as paddle +import collections +import paddle.fluid as fluid +import numpy as np def conv_bn_layer(input, filter_size, num_channels_in, num_channels_out, stride, - padding, act, index_range_data): + padding, act, masks, name): """Convolution layer with batch normalization. :param input: Input layer. - :type input: LayerOutput + :type input: Variable :param filter_size: The x dimension of a filter kernel. Or input a tuple for two image dimension. :type filter_size: int|tuple|list :param num_channels_in: Number of input channels. :type num_channels_in: int - :type num_channels_out: Number of output channels. - :type num_channels_in: out + :param num_channels_out: Number of output channels. + :type num_channels_out: int + :param stride: The x dimension of the stride. Or input a tuple for two + image dimension. + :type stride: int|tuple|list :param padding: The x dimension of the padding. Or input a tuple for two image dimension. :type padding: int|tuple|list :param act: Activation type. - :type act: BaseActivation - :param index_range_data: Index range to indicate sub region. - :type index_range_data: LayerOutput + :type act: string + :param masks: Masks data layer to reset padding. + :type masks: Variable + :param name: Name of the layer. + :param name: string :return: Batch norm layer after convolution layer. - :rtype: LayerOutput + :rtype: Variable + """ - conv_layer = paddle.layer.img_conv( + conv_layer = fluid.layers.conv2d( input=input, - filter_size=filter_size, - num_channels=num_channels_in, num_filters=num_channels_out, + filter_size=filter_size, stride=stride, padding=padding, - act=paddle.activation.Linear(), + param_attr=fluid.ParamAttr(name=name + '_conv2d_weight'), + act=None, bias_attr=False) - batch_norm = paddle.layer.batch_norm(input=conv_layer, act=act) + + batch_norm = fluid.layers.batch_norm( + input=conv_layer, + act=act, + param_attr=fluid.ParamAttr(name=name + '_batch_norm_weight'), + bias_attr=fluid.ParamAttr(name=name + '_batch_norm_bias'), + moving_mean_name=name + '_batch_norm_moving_mean', + moving_variance_name=name + '_batch_norm_moving_variance') + # reset padding part to 0 - scale_sub_region = paddle.layer.scale_sub_region( - batch_norm, index_range_data, value=0.0) - return scale_sub_region + padding_reset = fluid.layers.elementwise_mul(batch_norm, masks) + return padding_reset + + +def simple_rnn(input, size, param_attr=None, bias_attr=None, is_reverse=False): + '''A simple rnn layer. + :param input:input layer. + :type input:Variable + :param size:Number of RNN cells. + :type size:int + :param param_attr:Parameter properties of hidden layer weights that + can be learned + :type param_attr:ParamAttr + :param bias_attr:Bias properties of hidden layer weights that can be learned + :type bias_attr:ParamAttr + :param is_reverse:Whether to calculate the inverse RNN + :type is_reverse:bool + :return: A simple RNN layer. + :rtype: Variable + ''' + if is_reverse: + input = fluid.layers.sequence_reverse(x=input) + + pad_value = fluid.layers.assign(input=np.array([0.0], dtype=np.float32)) + input, length = fluid.layers.sequence_pad(input, pad_value) + rnn = fluid.layers.StaticRNN() + input = fluid.layers.transpose(input, [1, 0, 2]) + with rnn.step(): + in_ = rnn.step_input(input) + mem = rnn.memory(shape=[-1, size], batch_ref=in_) + out = fluid.layers.fc( + input=mem, + size=size, + act=None, + param_attr=param_attr, + bias_attr=bias_attr) + out = fluid.layers.elementwise_add(out, in_) + out = fluid.layers.brelu(out) + rnn.update_memory(mem, out) + rnn.output(out) + + out = rnn() + out = fluid.layers.transpose(out, [1, 0, 2]) + out = fluid.layers.sequence_unpad(x=out, length=length) + + if is_reverse: + out = fluid.layers.sequence_reverse(x=out) + return out -def bidirectional_simple_rnn_bn_layer(name, input, size, act, share_weights): +def bidirectional_simple_rnn_bn_layer(name, input, size, share_weights): """Bidirectonal simple rnn layer with sequence-wise batch normalization. The batch normalization is only performed on input-state weights. - - :param name: Name of the layer. + :param name: Name of the layer parameters. :type name: string :param input: Input layer. - :type input: LayerOutput + :type input: Variable :param size: Number of RNN cells. :type size: int - :param act: Activation type. - :type act: BaseActivation :param share_weights: Whether to share input-hidden weights between forward and backward directional RNNs. :type share_weights: bool :return: Bidirectional simple rnn layer. - :rtype: LayerOutput + :rtype: Variable """ if share_weights: - # input-hidden weights shared between bi-direcitonal rnn. - input_proj = paddle.layer.fc( + #input-hidden weights shared between bi-directional rnn. + input_proj = fluid.layers.fc( input=input, size=size, - act=paddle.activation.Linear(), + act=None, + param_attr=fluid.ParamAttr(name=name + '_fc_weight'), bias_attr=False) + # batch norm is only performed on input-state projection - input_proj_bn = paddle.layer.batch_norm( - input=input_proj, act=paddle.activation.Linear()) - # forward and backward in time - forward_simple_rnn = paddle.layer.recurrent( - input=input_proj_bn, act=act, reverse=False) - backward_simple_rnn = paddle.layer.recurrent( - input=input_proj_bn, act=act, reverse=True) + input_proj_bn = fluid.layers.batch_norm( + input=input_proj, + act=None, + param_attr=fluid.ParamAttr(name=name + '_batch_norm_weight'), + bias_attr=fluid.ParamAttr(name=name + '_batch_norm_bias'), + moving_mean_name=name + '_batch_norm_moving_mean', + moving_variance_name=name + '_batch_norm_moving_variance') + #forward and backword in time + forward_rnn = simple_rnn( + input=input_proj_bn, + size=size, + param_attr=fluid.ParamAttr(name=name + '_forward_rnn_weight'), + bias_attr=fluid.ParamAttr(name=name + '_forward_rnn_bias'), + is_reverse=False) + + reverse_rnn = simple_rnn( + input=input_proj_bn, + size=size, + param_attr=fluid.ParamAttr(name=name + '_reverse_rnn_weight'), + bias_attr=fluid.ParamAttr(name=name + '_reverse_rnn_bias'), + is_reverse=True) else: - input_proj_forward = paddle.layer.fc( + input_proj_forward = fluid.layers.fc( input=input, size=size, - act=paddle.activation.Linear(), + act=None, + param_attr=fluid.ParamAttr(name=name + '_forward_fc_weight'), bias_attr=False) - input_proj_backward = paddle.layer.fc( + input_proj_backward = fluid.layers.fc( input=input, size=size, - act=paddle.activation.Linear(), + act=None, + param_attr=fluid.ParamAttr(name=name + '_reverse_fc_weight'), bias_attr=False) - # batch norm is only performed on input-state projection - input_proj_bn_forward = paddle.layer.batch_norm( - input=input_proj_forward, act=paddle.activation.Linear()) - input_proj_bn_backward = paddle.layer.batch_norm( - input=input_proj_backward, act=paddle.activation.Linear()) + #batch norm is only performed on input-state projection + input_proj_bn_forward = fluid.layers.batch_norm( + input=input_proj_forward, + act=None, + param_attr=fluid.ParamAttr( + name=name + '_forward_batch_norm_weight'), + bias_attr=fluid.ParamAttr(name=name + '_forward_batch_norm_bias'), + moving_mean_name=name + '_forward_batch_norm_moving_mean', + moving_variance_name=name + '_forward_batch_norm_moving_variance') + input_proj_bn_backward = fluid.layers.batch_norm( + input=input_proj_backward, + act=None, + param_attr=fluid.ParamAttr( + name=name + '_reverse_batch_norm_weight'), + bias_attr=fluid.ParamAttr(name=name + '_reverse_batch_norm_bias'), + moving_mean_name=name + '_reverse_batch_norm_moving_mean', + moving_variance_name=name + '_reverse_batch_norm_moving_variance') # forward and backward in time - forward_simple_rnn = paddle.layer.recurrent( - input=input_proj_bn_forward, act=act, reverse=False) - backward_simple_rnn = paddle.layer.recurrent( - input=input_proj_bn_backward, act=act, reverse=True) - - return paddle.layer.concat(input=[forward_simple_rnn, backward_simple_rnn]) + forward_rnn = simple_rnn( + input=input_proj_bn_forward, + size=size, + param_attr=fluid.ParamAttr(name=name + '_forward_rnn_weight'), + bias_attr=fluid.ParamAttr(name=name + '_forward_rnn_bias'), + is_reverse=False) + reverse_rnn = simple_rnn( + input=input_proj_bn_backward, + size=size, + param_attr=fluid.ParamAttr(name=name + '_reverse_rnn_weight'), + bias_attr=fluid.ParamAttr(name=name + '_reverse_rnn_bias'), + is_reverse=True) + out = fluid.layers.concat(input=[forward_rnn, reverse_rnn], axis=1) + return out def bidirectional_gru_bn_layer(name, input, size, act): """Bidirectonal gru layer with sequence-wise batch normalization. The batch normalization is only performed on input-state weights. - :param name: Name of the layer. :type name: string :param input: Input layer. - :type input: LayerOutput - :param size: Number of RNN cells. + :type input: Variable + :param size: Number of GRU cells. :type size: int :param act: Activation type. - :type act: BaseActivation - :return: Bidirectional simple rnn layer. - :rtype: LayerOutput + :type act: string + :return: Bidirectional GRU layer. + :rtype: Variable """ - input_proj_forward = paddle.layer.fc( + input_proj_forward = fluid.layers.fc( input=input, size=size * 3, - act=paddle.activation.Linear(), + act=None, + param_attr=fluid.ParamAttr(name=name + '_forward_fc_weight'), bias_attr=False) - input_proj_backward = paddle.layer.fc( + input_proj_backward = fluid.layers.fc( input=input, size=size * 3, - act=paddle.activation.Linear(), + act=None, + param_attr=fluid.ParamAttr(name=name + '_reverse_fc_weight'), bias_attr=False) - # batch norm is only performed on input-related projections - input_proj_bn_forward = paddle.layer.batch_norm( - input=input_proj_forward, act=paddle.activation.Linear()) - input_proj_bn_backward = paddle.layer.batch_norm( - input=input_proj_backward, act=paddle.activation.Linear()) - # forward and backward in time - forward_gru = paddle.layer.grumemory( - input=input_proj_bn_forward, act=act, reverse=False) - backward_gru = paddle.layer.grumemory( - input=input_proj_bn_backward, act=act, reverse=True) - return paddle.layer.concat(input=[forward_gru, backward_gru]) + #batch norm is only performed on input-related prohections + input_proj_bn_forward = fluid.layers.batch_norm( + input=input_proj_forward, + act=None, + param_attr=fluid.ParamAttr(name=name + '_forward_batch_norm_weight'), + bias_attr=fluid.ParamAttr(name=name + '_forward_batch_norm_bias'), + moving_mean_name=name + '_forward_batch_norm_moving_mean', + moving_variance_name=name + '_forward_batch_norm_moving_variance') + input_proj_bn_backward = fluid.layers.batch_norm( + input=input_proj_backward, + act=None, + param_attr=fluid.ParamAttr(name=name + '_reverse_batch_norm_weight'), + bias_attr=fluid.ParamAttr(name=name + '_reverse_batch_norm_bias'), + moving_mean_name=name + '_reverse_batch_norm_moving_mean', + moving_variance_name=name + '_reverse_batch_norm_moving_variance') + #forward and backward in time + forward_gru = fluid.layers.dynamic_gru( + input=input_proj_bn_forward, + size=size, + gate_activation='sigmoid', + candidate_activation=act, + param_attr=fluid.ParamAttr(name=name + '_forward_gru_weight'), + bias_attr=fluid.ParamAttr(name=name + '_forward_gru_bias'), + is_reverse=False) + reverse_gru = fluid.layers.dynamic_gru( + input=input_proj_bn_backward, + size=size, + gate_activation='sigmoid', + candidate_activation=act, + param_attr=fluid.ParamAttr(name=name + '_reverse_gru_weight'), + bias_attr=fluid.ParamAttr(name=name + '_reverse_gru_bias'), + is_reverse=True) + return fluid.layers.concat(input=[forward_gru, reverse_gru], axis=1) -def conv_group(input, num_stacks, index_range_datas): +def conv_group(input, num_stacks, seq_len_data, masks): """Convolution group with stacked convolution layers. - :param input: Input layer. - :type input: LayerOutput + :type input: Variable :param num_stacks: Number of stacked convolution layers. :type num_stacks: int - :param index_range_datas: Index ranges for each convolution layer. - :type index_range_datas: tuple|list + :param seq_len_data:Valid sequence length data layer. + :type seq_len_data:Variable + :param masks: Masks data layer to reset padding. + :type masks: Variable :return: Output layer of the convolution group. - :rtype: LayerOutput + :rtype: Variable """ + filter_size = (41, 11) + stride = (2, 3) + padding = (20, 5) conv = conv_bn_layer( input=input, - filter_size=(11, 41), + filter_size=filter_size, num_channels_in=1, num_channels_out=32, - stride=(3, 2), - padding=(5, 20), - act=paddle.activation.BRelu(), - index_range_data=index_range_datas[0]) - for i in xrange(num_stacks - 1): + stride=stride, + padding=padding, + act="brelu", + masks=masks, + name='layer_0', ) + + seq_len_data = (np.array(seq_len_data) - filter_size[1] + 2 * padding[1] + ) // stride[1] + 1 + + output_height = (161 - 1) // 2 + 1 + + for i in range(num_stacks - 1): + #reshape masks + output_height = (output_height - 1) // 2 + 1 + masks = fluid.layers.slice( + masks, axes=[2], starts=[0], ends=[output_height]) conv = conv_bn_layer( input=conv, - filter_size=(11, 21), + filter_size=(21, 11), num_channels_in=32, num_channels_out=32, - stride=(1, 2), - padding=(5, 10), - act=paddle.activation.BRelu(), - index_range_data=index_range_datas[i + 1]) - output_num_channels = 32 - output_height = 160 // pow(2, num_stacks) + 1 - return conv, output_num_channels, output_height + stride=(2, 1), + padding=(10, 5), + act="brelu", + masks=masks, + name='layer_{}'.format(i + 1), ) + output_num_channels = 32 + return conv, output_num_channels, output_height, seq_len_data -def rnn_group(input, size, num_stacks, use_gru, share_rnn_weights): - """RNN group with stacked bidirectional simple RNN layers. +def rnn_group(input, size, num_stacks, num_conv_layers, use_gru, + share_rnn_weights): + """RNN group with stacked bidirectional simple RNN or GRU layers. :param input: Input layer. - :type input: LayerOutput + :type input: Variable :param size: Number of RNN cells in each layer. :type size: int :param num_stacks: Number of stacked rnn layers. @@ -194,32 +328,30 @@ def rnn_group(input, size, num_stacks, use_gru, share_rnn_weights): It is only available when use_gru=False. :type share_weights: bool :return: Output layer of the RNN group. - :rtype: LayerOutput + :rtype: Variable """ output = input - for i in xrange(num_stacks): + for i in range(num_stacks): if use_gru: output = bidirectional_gru_bn_layer( - name=str(i), + name='layer_{}'.format(i + num_conv_layers), input=output, size=size, - act=paddle.activation.Relu()) - # BRelu does not support hppl, need to add later. Use Relu instead. + act="relu") else: + name = 'layer_{}'.format(i + num_conv_layers) output = bidirectional_simple_rnn_bn_layer( - name=str(i), + name=name, input=output, size=size, - act=paddle.activation.BRelu(), share_weights=share_rnn_weights) return output def deep_speech_v2_network(audio_data, text_data, - seq_offset_data, seq_len_data, - index_range_datas, + masks, dict_size, num_conv_layers=2, num_rnn_layers=3, @@ -227,17 +359,14 @@ def deep_speech_v2_network(audio_data, use_gru=False, share_rnn_weights=True): """The DeepSpeech2 network structure. - :param audio_data: Audio spectrogram data layer. - :type audio_data: LayerOutput + :type audio_data: Variable :param text_data: Transcription text data layer. - :type text_data: LayerOutput - :param seq_offset_data: Sequence offset data layer. - :type seq_offset_data: LayerOutput + :type text_data: Variable :param seq_len_data: Valid sequence length data layer. - :type seq_len_data: LayerOutput - :param index_range_datas: Index ranges data layers. - :type index_range_datas: tuple|list + :type seq_len_data: Variable + :param masks: Masks data layer to reset padding. + :type masks: Variable :param dict_size: Dictionary size for tokenized transcription. :type dict_size: int :param num_conv_layers: Number of stacking convolution layers. @@ -254,49 +383,53 @@ def deep_speech_v2_network(audio_data, :type share_weights: bool :return: A tuple of an output unnormalized log probability layer ( before softmax) and a ctc cost layer. - :rtype: tuple of LayerOutput + :rtype: tuple of LayerOutput """ + audio_data = fluid.layers.unsqueeze(audio_data, axes=[1]) + # convolution group - conv_group_output, conv_group_num_channels, conv_group_height = conv_group( + conv_group_output, conv_group_num_channels, conv_group_height, seq_len_data = conv_group( input=audio_data, num_stacks=num_conv_layers, - index_range_datas=index_range_datas) + seq_len_data=seq_len_data, + masks=masks) + # convert data form convolution feature map to sequence of vectors - conv2seq = paddle.layer.block_expand( - input=conv_group_output, - num_channels=conv_group_num_channels, - stride_x=1, - stride_y=1, - block_x=1, - block_y=conv_group_height) + transpose = fluid.layers.transpose(conv_group_output, perm=[0, 3, 1, 2]) + reshape_conv_output = fluid.layers.reshape( + x=transpose, + shape=[0, -1, conv_group_height * conv_group_num_channels], + inplace=False) # remove padding part - remove_padding_data = paddle.layer.sub_seq( - input=conv2seq, - offsets=seq_offset_data, - sizes=seq_len_data, - act=paddle.activation.Linear(), - bias_attr=False) - # rnn group + seq_len_data = fluid.layers.reshape(seq_len_data, [-1]) + sequence = fluid.layers.sequence_unpad( + x=reshape_conv_output, length=seq_len_data) + #rnn group rnn_group_output = rnn_group( - input=remove_padding_data, + input=sequence, size=rnn_size, num_stacks=num_rnn_layers, + num_conv_layers=num_conv_layers, use_gru=use_gru, share_rnn_weights=share_rnn_weights) - fc = paddle.layer.fc( + fc = fluid.layers.fc( input=rnn_group_output, size=dict_size + 1, - act=paddle.activation.Linear(), - bias_attr=True) - # probability distribution with softmax - log_probs = paddle.layer.mixed( - input=paddle.layer.identity_projection(input=fc), - act=paddle.activation.Softmax()) - # ctc cost - ctc_loss = paddle.layer.warp_ctc( - input=fc, - label=text_data, - size=dict_size + 1, - blank=dict_size, - norm_by_times=True) - return log_probs, ctc_loss + act=None, + param_attr=fluid.ParamAttr( + name='layer_{}'.format(num_conv_layers + num_rnn_layers) + + '_fc_weight'), + bias_attr=fluid.ParamAttr( + name='layer_{}'.format(num_conv_layers + num_rnn_layers) + + '_fc_bias')) + # pribability distribution with softmax + log_probs = fluid.layers.softmax(fc) + log_probs.persistable = True + if not text_data: + return log_probs, None + else: + #ctc cost + ctc_loss = fluid.layers.warpctc( + input=fc, label=text_data, blank=dict_size, norm_by_times=True) + ctc_loss = fluid.layers.reduce_sum(ctc_loss) + return log_probs, ctc_loss diff --git a/models/aishell/download_model.sh b/models/aishell/download_model.sh index 1c4be79f..76ac4d00 100644 --- a/models/aishell/download_model.sh +++ b/models/aishell/download_model.sh @@ -2,9 +2,9 @@ . ../../utils/utility.sh -URL='https://deepspeech.bj.bcebos.com/mandarin_models/aishell_model.tar.gz' -MD5=0ee83aa15fba421e5de8fc66c8feb350 -TARGET=./aishell_model.tar.gz +URL='https://deepspeech.bj.bcebos.com/mandarin_models/aishell_model_fluid.tar.gz' +MD5=2bf0cc8b6d5da2a2a787b5cc36a496b5 +TARGET=./aishell_model_fluid.tar.gz echo "Download Aishell model ..." diff --git a/models/baidu_en8k/download_model.sh b/models/baidu_en8k/download_model.sh index 9ce67282..bbdb32b6 100644 --- a/models/baidu_en8k/download_model.sh +++ b/models/baidu_en8k/download_model.sh @@ -2,9 +2,9 @@ . ../../utils/utility.sh -URL='https://deepspeech.bj.bcebos.com/demo_models/baidu_en8k_model.tar.gz' -MD5=5fe7639e720d51b3c3bdf7a1470c6272 -TARGET=./baidu_en8k_model.tar.gz +URL='https://deepspeech.bj.bcebos.com/demo_models/baidu_en8k_model_fluid.tar.gz' +MD5=7e58fbf64aa4ecf639b049792ddcf788 +TARGET=./baidu_en8k_model_fluid.tar.gz echo "Download BaiduEn8k model ..." diff --git a/models/librispeech/download_model.sh b/models/librispeech/download_model.sh index 123bcb81..edf85305 100644 --- a/models/librispeech/download_model.sh +++ b/models/librispeech/download_model.sh @@ -2,9 +2,9 @@ . ../../utils/utility.sh -URL='https://deepspeech.bj.bcebos.com/eng_models/librispeech_model.tar.gz' -MD5=1f72d0c5591f453362f0caa09dd57618 -TARGET=./librispeech_model.tar.gz +URL='https://deepspeech.bj.bcebos.com/eng_models/librispeech_model_fluid.tar.gz' +MD5=fafb11fe57c3ecd107147056453f5348 +TARGET=./librispeech_model_fluid.tar.gz echo "Download LibriSpeech model ..." diff --git a/requirements.txt b/requirements.txt index e104f633..8c57208a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -scipy==0.13.1 +scipy==1.2.1 resampy==0.1.5 SoundFile==0.9.0.post1 python_speech_features diff --git a/test.py b/test.py index e5a3346a..44307ba8 100644 --- a/test.py +++ b/test.py @@ -5,7 +5,7 @@ from __future__ import print_function import argparse import functools -import paddle.v2 as paddle +import paddle.fluid as fluid from data_utils.data import DataGenerator from model_utils.model import DeepSpeech2Model from utils.error_rate import char_errors, word_errors @@ -15,10 +15,8 @@ parser = argparse.ArgumentParser(description=__doc__) add_arg = functools.partial(add_arguments, argparser=parser) # yapf: disable add_arg('batch_size', int, 128, "Minibatch size.") -add_arg('trainer_count', int, 8, "# of Trainers (CPUs or GPUs).") add_arg('beam_size', int, 500, "Beam search width.") add_arg('num_proc_bsearch', int, 8, "# of CPUs for beam search.") -add_arg('num_proc_data', int, 8, "# of CPUs for data preprocessing.") add_arg('num_conv_layers', int, 2, "# of convolution layers.") add_arg('num_rnn_layers', int, 3, "# of recurrent layers.") add_arg('rnn_layer_size', int, 2048, "# of recurrent cells per layer.") @@ -64,17 +62,22 @@ args = parser.parse_args() def evaluate(): """Evaluate on whole test data for DeepSpeech2.""" + if args.use_gpu: + place = fluid.CUDAPlace(0) + else: + place = fluid.CPUPlace() + data_generator = DataGenerator( vocab_filepath=args.vocab_path, mean_std_filepath=args.mean_std_path, augmentation_config='{}', specgram_type=args.specgram_type, - num_threads=args.num_proc_data, - keep_transcription_text=True) + keep_transcription_text=True, + place = place, + is_training = False) batch_reader = data_generator.batch_reader_creator( manifest_path=args.test_manifest, batch_size=args.batch_size, - min_batch_size=1, sortagrad=False, shuffle_method=None) @@ -84,8 +87,9 @@ def evaluate(): num_rnn_layers=args.num_rnn_layers, rnn_layer_size=args.rnn_layer_size, use_gru=args.use_gru, - pretrained_model_path=args.model_path, - share_rnn_weights=args.share_rnn_weights) + share_rnn_weights=args.share_rnn_weights, + place=place, + init_from_pretrain_model=args.model_path) # decoders only accept string encoded in utf-8 vocab_list = [chars.encode("utf-8") for chars in data_generator.vocab_list] @@ -115,7 +119,7 @@ def evaluate(): cutoff_top_n=args.cutoff_top_n, vocab_list=vocab_list, num_processes=args.num_proc_bsearch) - target_transcripts = [data[1] for data in infer_data] + target_transcripts = infer_data[1] for target, result in zip(target_transcripts, result_transcripts): errors, len_ref = errors_func(target, result) @@ -131,9 +135,6 @@ def evaluate(): def main(): print_arguments(args) - paddle.init(use_gpu=args.use_gpu, - rnn_use_batch=True, - trainer_count=args.trainer_count) evaluate() diff --git a/tools/profile.sh b/tools/profile.sh index 19abe7ed..830a6761 100644 --- a/tools/profile.sh +++ b/tools/profile.sh @@ -9,14 +9,13 @@ function join_by { local IFS="$1"; shift; echo "$*"; } for NUM_GPUS in 16 8 4 2 1 do DEVICES=$(join_by , $(seq 0 $(($NUM_GPUS-1)))) - BATCH_SIZE=$(($BATCH_SIZE_PER_GPU * $NUM_GPUS)) + BATCH_SIZE=$(($BATCH_SIZE_PER_GPU)) CUDA_VISIBLE_DEVICES=$DEVICES \ python train.py \ --batch_size=$BATCH_SIZE \ - --num_passes=1 \ + --num_epoch=1 \ --test_off=True \ - --trainer_count=$NUM_GPUS \ --min_duration=$MIN_DURATION \ --max_duration=$MAX_DURATION > tmp.log 2>&1 @@ -24,7 +23,7 @@ do exit 1 fi - cat tmp.log | grep "Time" | awk '{print "GPU Num: " "'"$NUM_GPUS"'" " Time: "$3}' + cat tmp.log | grep "Time" | awk '{print "GPU Num: " "'"$NUM_GPUS"'" " Time: "$2}' rm tmp.log done diff --git a/tools/tune.py b/tools/tune.py index da785189..843df0c6 100644 --- a/tools/tune.py +++ b/tools/tune.py @@ -10,7 +10,7 @@ import argparse import functools import gzip import logging -import paddle.v2 as paddle +import paddle.fluid as fluid import _init_paths from data_utils.data import DataGenerator from model_utils.model import DeepSpeech2Model @@ -26,7 +26,6 @@ add_arg('batch_size', int, 256, "# of samples per batch.") add_arg('trainer_count', int, 8, "# of Trainers (CPUs or GPUs).") add_arg('beam_size', int, 500, "Beam search width.") add_arg('num_proc_bsearch', int, 8, "# of CPUs for beam search.") -add_arg('num_proc_data', int, 8, "# of CPUs for data preprocessing.") add_arg('num_conv_layers', int, 2, "# of convolution layers.") add_arg('num_rnn_layers', int, 3, "# of recurrent layers.") add_arg('rnn_layer_size', int, 2048, "# of recurrent cells per layer.") @@ -77,13 +76,19 @@ def tune(): if not args.num_betas >= 0: raise ValueError("num_betas must be non-negative!") + if args.use_gpu: + place = fluid.CUDAPlace(0) + else: + place = fluid.CPUPlace() + data_generator = DataGenerator( vocab_filepath=args.vocab_path, mean_std_filepath=args.mean_std_path, augmentation_config='{}', specgram_type=args.specgram_type, - num_threads=args.num_proc_data, - keep_transcription_text=True) + keep_transcription_text=True, + place = place, + is_training = False) batch_reader = data_generator.batch_reader_creator( manifest_path=args.tune_manifest, @@ -97,7 +102,8 @@ def tune(): num_rnn_layers=args.num_rnn_layers, rnn_layer_size=args.rnn_layer_size, use_gru=args.use_gru, - pretrained_model_path=args.model_path, + place=place, + init_from_pretrain_model=args.model_path, share_rnn_weights=args.share_rnn_weights) # decoders only accept string encoded in utf-8 @@ -109,8 +115,8 @@ def tune(): params_grid = [(alpha, beta) for alpha in cand_alphas for beta in cand_betas] - err_sum = [0.0 for i in xrange(len(params_grid))] - err_ave = [0.0 for i in xrange(len(params_grid))] + err_sum = [0.0 for i in range(len(params_grid))] + err_ave = [0.0 for i in range(len(params_grid))] num_ins, len_refs, cur_batch = 0, 0, 0 # initialize external scorer ds2_model.init_ext_scorer(args.alpha_from, args.beta_from, @@ -123,7 +129,7 @@ def tune(): probs_split = ds2_model.infer_batch_probs( infer_data=infer_data, feeding_dict=data_generator.feeding) - target_transcripts = [ data[1] for data in infer_data ] + target_transcripts = infer_data[1] num_ins += len(target_transcripts) # grid search @@ -137,7 +143,6 @@ def tune(): cutoff_top_n=args.cutoff_top_n, vocab_list=vocab_list, num_processes=args.num_proc_bsearch) - for target, result in zip(target_transcripts, result_transcripts): errors, len_ref = errors_func(target, result) err_sum[index] += errors @@ -163,7 +168,7 @@ def tune(): # output WER/CER at every (alpha, beta) print("\nFinal %s:\n" % args.error_rate_type) - for index in xrange(len(params_grid)): + for index in range(len(params_grid)): print("(alpha, beta) = (%s, %s), [%s] = %f" % ("%.3f" % params_grid[index][0], "%.3f" % params_grid[index][1], args.error_rate_type, err_ave[index])) @@ -179,9 +184,6 @@ def tune(): def main(): print_arguments(args) - paddle.init(use_gpu=args.use_gpu, - rnn_use_batch=True, - trainer_count=args.trainer_count) tune() diff --git a/train.py b/train.py index 16415713..0d409d93 100644 --- a/train.py +++ b/train.py @@ -5,23 +5,25 @@ from __future__ import print_function import argparse import functools -import paddle.v2 as paddle +import io from model_utils.model import DeepSpeech2Model from data_utils.data import DataGenerator from utils.utility import add_arguments, print_arguments +import paddle.fluid as fluid + parser = argparse.ArgumentParser(description=__doc__) add_arg = functools.partial(add_arguments, argparser=parser) # yapf: disable add_arg('batch_size', int, 256, "Minibatch size.") -add_arg('trainer_count', int, 8, "# of Trainers (CPUs or GPUs).") -add_arg('num_passes', int, 200, "# of training epochs.") -add_arg('num_proc_data', int, 16, "# of CPUs for data preprocessing.") +add_arg('num_epoch', int, 200, "# of training epochs.") add_arg('num_conv_layers', int, 2, "# of convolution layers.") add_arg('num_rnn_layers', int, 3, "# of recurrent layers.") add_arg('rnn_layer_size', int, 2048, "# of recurrent cells per layer.") -add_arg('num_iter_print', int, 100, "Every # iterations for printing " +add_arg('num_iter_print', int, 100, "Every # batch for printing " "train cost.") +add_arg('save_epoch', int, 10, "# Every # batch for save checkpoint and modle params ") +add_arg('num_samples', int, 10000, "The num of train samples.") add_arg('learning_rate', float, 5e-4, "Learning rate.") add_arg('max_duration', float, 27.0, "Longest audio duration allowed.") add_arg('min_duration', float, 0.0, "Shortest audio duration allowed.") @@ -31,7 +33,12 @@ add_arg('use_gpu', bool, True, "Use GPU or not.") add_arg('use_gru', bool, False, "Use GRUs instead of simple RNNs.") add_arg('is_local', bool, True, "Use pserver or not.") add_arg('share_rnn_weights',bool, True, "Share input-hidden weights across " - "bi-directional RNNs. Not for GRU.") + "bi-directional RNNs. Not for GRU.") +add_arg('init_from_pretrain_model',str, + None, + "If None, the training starts from scratch, " + "otherwise, it resumes from the pre-trained model.") + add_arg('train_manifest', str, 'data/librispeech/manifest.train', "Filepath of train manifest.") @@ -44,10 +51,6 @@ add_arg('mean_std_path', str, add_arg('vocab_path', str, 'data/librispeech/vocab.txt', "Filepath of vocabulary.") -add_arg('init_model_path', str, - None, - "If None, the training starts from scratch, " - "otherwise, it resumes from the pre-trained model.") add_arg('output_model_dir', str, "./checkpoints/libri", "Directory for saving checkpoints.") @@ -68,30 +71,33 @@ args = parser.parse_args() def train(): """DeepSpeech2 training.""" + if args.use_gpu: + place = fluid.CUDAPlace(0) + else: + place = fluid.CPUPlace() + train_generator = DataGenerator( vocab_filepath=args.vocab_path, mean_std_filepath=args.mean_std_path, - augmentation_config=open(args.augment_conf_path, 'r').read(), + augmentation_config=io.open(args.augment_conf_path, mode='r', encoding='utf8').read(), max_duration=args.max_duration, min_duration=args.min_duration, specgram_type=args.specgram_type, - num_threads=args.num_proc_data) + place=place) dev_generator = DataGenerator( vocab_filepath=args.vocab_path, mean_std_filepath=args.mean_std_path, augmentation_config="{}", specgram_type=args.specgram_type, - num_threads=args.num_proc_data) + place = place) train_batch_reader = train_generator.batch_reader_creator( manifest_path=args.train_manifest, batch_size=args.batch_size, - min_batch_size=args.trainer_count, - sortagrad=args.use_sortagrad if args.init_model_path is None else False, + sortagrad=args.use_sortagrad if args.init_from_pretrain_model is None else False, shuffle_method=args.shuffle_method) dev_batch_reader = dev_generator.batch_reader_creator( manifest_path=args.dev_manifest, batch_size=args.batch_size, - min_batch_size=1, # must be 1, but will have errors. sortagrad=False, shuffle_method=None) @@ -101,27 +107,27 @@ def train(): num_rnn_layers=args.num_rnn_layers, rnn_layer_size=args.rnn_layer_size, use_gru=args.use_gru, - pretrained_model_path=args.init_model_path, - share_rnn_weights=args.share_rnn_weights) + share_rnn_weights=args.share_rnn_weights, + place=place, + init_from_pretrain_model=args.init_from_pretrain_model, + output_model_dir=args.output_model_dir) + ds2_model.train( train_batch_reader=train_batch_reader, dev_batch_reader=dev_batch_reader, feeding_dict=train_generator.feeding, learning_rate=args.learning_rate, gradient_clipping=400, - num_passes=args.num_passes, + batch_size=args.batch_size, + num_samples=args.num_samples, + num_epoch=args.num_epoch, + save_epoch=args.save_epoch, num_iterations_print=args.num_iter_print, - output_model_dir=args.output_model_dir, - is_local=args.is_local, test_off=args.test_off) def main(): print_arguments(args) - paddle.init(use_gpu=args.use_gpu, - rnn_use_batch=True, - trainer_count=args.trainer_count, - log_clipping=True) train() diff --git a/utils/error_rate.py b/utils/error_rate.py index 9aa90017..d84d9f87 100644 --- a/utils/error_rate.py +++ b/utils/error_rate.py @@ -36,15 +36,15 @@ def _levenshtein_distance(ref, hyp): distance = np.zeros((2, n + 1), dtype=np.int32) # initialize distance matrix - for j in xrange(n + 1): + for j in range(n + 1): distance[0][j] = j # calculate levenshtein distance - for i in xrange(1, m + 1): + for i in range(1, m + 1): prev_row_idx = (i - 1) % 2 cur_row_idx = i % 2 distance[cur_row_idx][0] = i - for j in xrange(1, n + 1): + for j in range(1, n + 1): if ref[i - 1] == hyp[j - 1]: distance[cur_row_idx][j] = distance[prev_row_idx][j - 1] else: From d89c3a48a7699195cd54fce3c09629c7010c0764 Mon Sep 17 00:00:00 2001 From: lfchener Date: Fri, 18 Oct 2019 11:46:00 +0000 Subject: [PATCH 3/3] unify api to 1.6 version and fix some problems --- README.md | 4 +- README_cn.md | 94 +++++++++++++++---------------- data_utils/data.py | 2 +- deploy/demo_server.py | 2 +- examples/aishell/run_train.sh | 2 +- examples/librispeech/run_train.sh | 2 +- examples/tiny/run_train.sh | 2 +- infer.py | 9 ++- model_utils/model.py | 76 +++++++++++++------------ model_utils/model_check.py | 49 ++++++++++++++++ model_utils/network.py | 28 ++++----- test.py | 9 ++- tools/tune.py | 2 +- train.py | 13 ++++- 14 files changed, 184 insertions(+), 110 deletions(-) create mode 100644 model_utils/model_check.py diff --git a/README.md b/README.md index d12f2521..80607008 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ To avoid the trouble of environment setup, [running in Docker container](#runnin ### Prerequisites - Python 2.7 only supported -- PaddlePaddle the latest version (please refer to the [Installation Guide](https://www.paddlepaddle.org.cn/documentation/docs/en/1.5/beginners_guide/install/index_en.html)) +- PaddlePaddle 1.6 version (Coming soon ...) ### Setup - Make sure these libraries or tools installed: `pkg-config`, `flac`, `ogg`, `vorbis`, `boost` and `swig`, e.g. installing them via `apt-get`: @@ -183,7 +183,7 @@ python tools/build_vocab.py --help ``` CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 \ python train.py \ - --init_from_pretrain_model CHECKPOINT_PATH_TO_RESUME_FROM + --init_from_pretrained_model CHECKPOINT_PATH_TO_RESUME_FROM ``` For more help on arguments: diff --git a/README_cn.md b/README_cn.md index dfdc15d3..90ae6f48 100644 --- a/README_cn.md +++ b/README_cn.md @@ -1,16 +1,16 @@ # 语音识别: DeepSpeech2 -*语音识别: DeepSpeech2*是一个采用[PaddlePaddle](https://github.com/PaddlePaddle/Paddle)平台的端到端自动语音识别(ASR)引擎的开源项目,具体原理参考这篇论文[Baidu's Deep Speech 2 paper](http://proceedings.mlr.press/v48/amodei16.pdf)。 -我们的愿景是为语音识别在工业应用和学术研究上,提供易于使用、高效和可扩展的工具,包括训练,推理,测试模块,以及demo部署。同时,我们还将发布一些预训练好的英语和普通话模型。 +*DeepSpeech2*是一个采用[PaddlePaddle](https://github.com/PaddlePaddle/Paddle)平台的端到端自动语音识别(ASR)引擎的开源项目,具体原理参考这篇论文[Baidu's Deep Speech 2 paper](http://proceedings.mlr.press/v48/amodei16.pdf)。 +我们的愿景是为语音识别在工业应用和学术研究上,提供易于使用、高效和可扩展的工具,包括训练,推理,测试模块,以及 demo 部署。同时,我们还将发布一些预训练好的英语和普通话模型。 ## 目录 - [安装](#安装) - [开始](#开始) - [数据准备](#数据准备) - [训练模型](#训练模型) -- [数据增强管道](#数据增强管道) +- [数据增强流水线](#数据增强流水线) - [推断和评价](#推断和评价) -- [在Docker容器上运行](#在Docker容器上运行) +- [在 Docker 容器上运行](#在Docker容器上运行) - [超参数调整](#超参数调整) - [训练汉语语言](#训练汉语语言) - [用自己的声音尝试现场演示](#用自己的声音尝试现场演示) @@ -23,7 +23,7 @@ ### 前提 - 只支持Python 2.7 -- PaddlePaddle最新版本(请参考[安装指南](https://www.paddlepaddle.org.cn/start)) +- PaddlePaddle 1.6 版本(即将发布) ### 安装 - 请确保以下库或工具已安装完毕:`pkg-config`, `flac`, `ogg`, `vorbis`, `boost` 和 `swig`, 如可以通过`apt-get`安装: @@ -55,40 +55,40 @@ sh setup.sh ## 开始 -`./examples`里的一些shell脚本将帮助我们在一些公开数据集(比如:[LibriSpeech](http://www.openslr.org/12/), [Aishell](http://www.openslr.org/33)) 进行快速尝试,包括了数据准备,模型训练,案例推断和模型评价。阅读这些例子将帮助你理解如何使用你的数据集训练模型。 +`./examples`里的一些 shell 脚本将帮助我们在一些公开数据集(比如:[LibriSpeech](http://www.openslr.org/12/), [Aishell](http://www.openslr.org/33)) 进行快速尝试,包括了数据准备,模型训练,案例推断和模型评价。阅读这些例子将帮助你理解如何使用你的数据集训练模型。 -`./examples`目录中的一些脚本配置使用了8个GPU。如果你没有8个可用的GPU,请修改`CUDA_VISIBLE_DEVICES`。如果你没有可用的GPU,请设置`--use_gpu`为False,这样程序会用CPU代替GPU。另外如果发生内存不足的问题,减小`--batch_size`即可。 +`./examples`目录中的一些脚本配置使用了 8 个 GPU。如果你没有 8 个可用的 GPU,请修改环境变量`CUDA_VISIBLE_DEVICES`。如果你没有可用的 GPU,请设置`--use_gpu`为 False,这样程序会用 CPU 代替 GPU。另外如果发生内存不足的问题,减小`--batch_size`即可。 让我们先看看[LibriSpeech dataset](http://www.openslr.org/12/)小样本集的例子。 -- 进到目录 +- 进入目录 ```bash cd examples/tiny ``` - 注意这仅仅是LibriSpeech一个小数据集的例子。如果你想尝试完整的数据集(可能需要花好几天来训练模型),请使用这个路径`examples/librispeech`。 + 注意这仅仅是 LibriSpeech 一个小数据集的例子。如果你想尝试完整的数据集(可能需要花好几天来训练模型),请使用这个路径`examples/librispeech`。 - 准备数据 ```bash sh run_data.sh ``` - 运行`run_data.sh`脚本将会下载数据集,产出manifests文件,收集一些归一化需要的统计信息并建立词表。当数据准备完成之后,下载完的数据(仅有LibriSpeech一部分)在`dataset/librispeech`中;其对应的manifest文件,均值标准差和词表文件在`./data/tiny`中。在第一次执行的时候一定要执行这个脚本,在接下来所有的实验中我们都会用到这个数据集。 -- 训练你自己的ASR模型 + 运行`run_data.sh`脚本将会下载数据集,产出 manifests 文件,收集一些归一化需要的统计信息并建立词表。当数据准备完成之后,下载完的数据(仅有 LibriSpeech 一部分)在`dataset/librispeech`中;其对应的 manifest 文件,均值标准差和词表文件在`./data/tiny`中。在第一次执行的时候一定要执行这个脚本,在接下来所有的实验中我们都会用到这个数据集。 +- 训练你自己的 ASR 模型 ```bash sh run_train.sh ``` - `run_train.sh`将会启动训练任务,训练日志会打印到终端,并且模型每个epoch的checkpoint都会保存到`./checkpoints/tiny`目录中。这些checkpoint可以用来恢复训练,推断,评价和部署。 + `run_train.sh`将会启动训练任务,训练日志会打印到终端,并且模型每个 epoch 的 checkpoint 都会保存到`./checkpoints/tiny`目录中。这些 checkpoint 可以用来恢复训练,推断,评价和部署。 - 用已有的模型进行案例推断 ```bash sh run_infer.sh ``` - `run_infer.sh`将会利用训练好的模型展现一些(默认10个)样本语音到文本的解码结果。由于当前模型只使用了LibriSpeech一部分数据集训练,因此性能可能不会太好。为了看到更好模型上的表现,你可以下载一个已训练好的模型(用完整的LibriSpeech训练了好几天)来做推断。 + `run_infer.sh`将会利用训练好的模型展现一些(默认 10 个)样本语音到文本的解码结果。由于当前模型只使用了 LibriSpeech 一部分数据集训练,因此性能可能不会太好。为了看到更好模型上的表现,你可以下载一个已训练好的模型(用完整的 LibriSpeech 训练了好几天)来做推断。 ```bash sh run_infer_golden.sh @@ -105,27 +105,27 @@ sh setup.sh sh run_test_golden.sh ``` -更多细节会在接下来的章节中阐述。祝你在*语音识别: DeepSpeech2*ASR引擎学习中过得愉快! +更多细节会在接下来的章节中阐述。祝你在*DeepSpeech2*ASR引擎学习中过得愉快! ## 数据准备 ### 生成Manifest -*语音识别: DeepSpeech2*接受文本**manifest**文件作为数据接口。manifest文件包含了一系列语音数据,其中每一行代表一个[JSON](http://www.json.org/)格式的音频元数据(比如文件路径,描述,时长)。具体格式如下: +*DeepSpeech2*接受文本**manifest**文件作为数据接口。manifest 文件包含了一系列语音数据,其中每一行代表一个[JSON](http://www.json.org/)格式的音频元数据(比如文件路径,描述,时长)。具体格式如下: ``` {"audio_filepath": "/home/work/.cache/paddle/Libri/134686/1089-134686-0001.flac", "duration": 3.275, "text": "stuff it into you his belly counselled him"} {"audio_filepath": "/home/work/.cache/paddle/Libri/134686/1089-134686-0007.flac", "duration": 4.275, "text": "a cold lucid indifference reigned in his soul"} ``` -如果你要使用自定义数据,你只需要按照以上格式生成自己的manifest文件即可。给定manifest文件,训练,推断以及其他所有模块都能够访问到音频数据以及对应的时长和标签数据。 +如果你要使用自定义数据,你只需要按照以上格式生成自己的 manifest 文件即可。给定 manifest 文件,训练、推断以及其它所有模块都能够访问到音频数据以及对应的时长和标签数据。 -关于如何生成manifest文件,请参考`data/librispeech/librispeech.py`。该脚本将会下载LibriSpeech数据集并生成manifest文件。 +关于如何生成 manifest 文件,请参考`data/librispeech/librispeech.py`。该脚本将会下载 LibriSpeech 数据集并生成 manifest 文件。 ### 计算均值和标准差用于归一化 -为了对音频特征进行z-score归一化(零均值,单位标准差),我们必须预估训练样本特征的均值和标准差: +为了对音频特征进行 z-score 归一化(零均值,单位标准差),我们必须预估训练样本特征的均值和标准差: ```bash python tools/compute_mean_std.py \ @@ -135,7 +135,7 @@ python tools/compute_mean_std.py \ --output_path data/librispeech/mean_std.npz ``` -以上这段代码会计算在`data/librispeech/manifest.train`路径中,2000个随机采样的语音频谱特征的均值和标准差,并将结果保存在`data/librispeech/mean_std.npz`中,方便以后使用。 +以上这段代码会计算在`data/librispeech/manifest.train`路径中,2000 个随机采样的语音频谱特征的均值和标准差,并将结果保存在`data/librispeech/mean_std.npz`中,方便以后使用。 ### 建立词表 @@ -164,13 +164,13 @@ python tools/build_vocab.py --help `train.py`是训练模块的主要调用者。使用示例如下。 -- 开始使用8片GPU训练: +- 开始使用 8 片 GPU 训练: ``` CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 python train.py ``` -- 开始使用CPU训练: +- 开始使用 CPU 训练: ``` python train.py --use_gpu False @@ -181,7 +181,7 @@ python tools/build_vocab.py --help ``` CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 \ python train.py \ - --init_from_pretrain_model CHECKPOINT_PATH_TO_RESUME_FROM + --init_from_pretrained_model CHECKPOINT_PATH_TO_RESUME_FROM ``` 获得更多帮助: @@ -192,7 +192,7 @@ python train.py --help 或参考 `example/librispeech/run_train.sh`. -## 数据增强管道 +## 数据增强流水线 数据增强是用来提升深度学习性能的非常有效的技术。我们通过在原始音频中添加小的随机扰动(标签不变转换)获得新音频来增强我们的语音数据。你不必自己合成,因为数据增强已经嵌入到数据生成器中并且能够即时完成,在训练模型的每个epoch中随机合成音频。 @@ -222,7 +222,7 @@ python train.py --help }] ``` -当`trainer.py`的`--augment_conf_file`参数被设置为上述示例配置文件的路径时,每个epoch中的每个音频片段都将被处理。首先,均匀随机采样速率会有60%的概率在0.95和1.05之间对音频片段进行速度扰动。然后,音频片段有80%的概率在时间上被挪移,挪移偏差值是-5毫秒和5毫秒之间的随机采样。最后,这个新合成的音频片段将被传送给特征提取器,以用于接下来的训练。 +当`trainer.py`的`--augment_conf_file`参数被设置为上述示例配置文件的路径时,每个 epoch 中的每个音频片段都将被处理。首先,均匀随机采样速率会有60%的概率在 0.95 和 1.05 之间对音频片段进行速度扰动。然后,音频片段有 80% 的概率在时间上被挪移,挪移偏差值是 -5 毫秒和 5 毫秒之间的随机采样。最后,这个新合成的音频片段将被传送给特征提取器,以用于接下来的训练。 有关其他配置实例,请参考`conf/augmenatation.config.example`. @@ -247,11 +247,11 @@ bash download_lm_ch.sh 英语语料库来自[Common Crawl Repository](http://commoncrawl.org),你可以从[statmt](http://data.statmt.org/ngrams/deduped_en)下载它。我们使用en.00部分来训练我们的英语语言模型。训练前有如下的一些预处理过程: - * 不在\['A-Za-z0-9\s'\](\s表示空白字符)中的字符将被删除,阿拉伯数字被转换为英文数字,比如“1000”转换为one thousand。 + * 不在\['A-Za-z0-9\s'\](\s表示空白字符)中的字符将被删除,阿拉伯数字被转换为英文数字,比如“1000”转换为 one thousand。 * 重复的空白字符被压缩为一个,并且开始的空白字符将被删除。请注意,所有的录音都是小写字母,因此所有字符都转换为小写字母。 - * 选择前40万个最常用的单词来建立词表,其余部分将被替换为“UNKNOWNWORD”。 + * 选择前 40 万个最常用的单词来建立词表,其余部分将被替换为“UNKNOWNWORD”。 -现在预处理完成了,我们得到一个干净的语料库来训练语言模型。我们发布的语言模型版本使用了参数“-o 5 --prune 0 1 1 1 1”来训练。“-o 5”表示语言模型的最大order为5。“--prune 0 1 1 1 1”表示每个order的计数阈值,更具体地说,它将第2个以及更高的order修剪为单个。为了节省磁盘存储空间,我们将使用参数“-a 22 -q 8 -b 8”将arpa文件转换为“trie”二进制文件。“-a”表示在“trie”中用于切分的指针的最高位数。“-q -b”是概率和退避的量化参数。 +现在预处理完成了,我们得到一个干净的语料库来训练语言模型。我们发布的语言模型版本使用了参数“-o 5 --prune 0 1 1 1 1”来训练。“-o 5”表示语言模型的最大order为 5。“--prune 0 1 1 1 1”表示每个 order 的计数阈值,更具体地说,它将第 2 个以及更高的 order 修剪为单个。为了节省磁盘存储空间,我们将使用参数“-a 22 -q 8 -b 8”将 arpa 文件转换为“trie”二进制文件。“-a”表示在“trie”中用于切分的指针的最高位数。“-q -b”是概率和退避的量化参数。 #### 普通话语言模型 @@ -261,25 +261,25 @@ bash download_lm_ch.sh * 删除英文标点和中文标点。 * 在两个字符之间插入空白字符。 -请注意,发布的语言模型只包含中文简体字。预处理完成后,我们开始训练语言模型。这个小的语言模型训练关键参数是“-o 5 --prune 0 1 2 4 4”,“-o 5”是针对大语言模型。请参考上面的部分了解每个参数的含义。我们还使用默认设置将arpa文件转换为二进制文件。 +请注意,发布的语言模型只包含中文简体字。预处理完成后,我们开始训练语言模型。这个小的语言模型训练关键参数是“-o 5 --prune 0 1 2 4 4”,“-o 5”是针对大语言模型。请参考上面的部分了解每个参数的含义。我们还使用默认设置将 arpa 文件转换为二进制文件。 ### 语音到文本推断 推断模块使用`infer.py`进行调用,可以用来推断,解码,以及输出一些给定音频片段可视化到文本的结果。这有助于对ASR模型的性能进行直观和定性的评估。 -- GPU版本的推断: +- GPU 版本的推断: ```bash CUDA_VISIBLE_DEVICES=0 python infer.py ``` -- CPU版本的推断: +- CPU 版本的推断: ```bash python infer.py --use_gpu False ``` -我们提供两种类型的CTC解码器:*CTC贪心解码器*和*CTC波束搜索解码器*。*CTC贪心解码器*是简单的最佳路径解码算法的实现,在每个时间步选择最可能的字符,因此是贪心的并且是局部最优的。[*CTC波束搜索解码器*](https://arxiv.org/abs/1408.2873)另外使用了启发式广度优先图搜索以达到近似全局最优; 它也需要预先训练的KenLM语言模型以获得更好的评分和排名。解码器类型可以用参数`--decoding_method`设置。 +我们提供两种类型的 CTC 解码器:*CTC贪心解码器*和*CTC波束搜索解码器*。*CTC贪心解码器*是简单的最佳路径解码算法的实现,在每个时间步选择最可能的字符,因此是贪心的并且是局部最优的。[*CTC波束搜索解码器*](https://arxiv.org/abs/1408.2873)另外使用了启发式广度优先图搜索以达到近似全局最优; 它也需要预先训练的KenLM语言模型以获得更好的评分和排名。解码器类型可以用参数`--decoding_method`设置。 获得更多帮助: @@ -292,13 +292,13 @@ python infer.py --help 要定量评估模型的性能,请运行: -- GPU版本评估 +- GPU 版本评估 ```bash CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 python test.py ``` -- CPU版本评估 +- CPU 版本评估 ```bash python test.py --use_gpu False @@ -319,7 +319,7 @@ python test.py --help `tools/tune.py`会进行2维网格查找超参数$\alpha$和$\beta$。你必须提供$\alpha$和$\beta$的范围,以及尝试的次数。 -- 带GPU版的调整: +- GPU 版的调整: ```bash CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 \ @@ -332,21 +332,21 @@ python test.py --help --num_betas 8 ``` -- CPU版的调整: +- CPU 版的调整: ```bash python tools/tune.py --use_gpu False ``` -网格搜索将会在超参数空间的每个点处打印出WER(误字率)或者CER(字符错误率),并且可绘出误差曲面。一个合适的超参数范围应包括WER/CER误差表面的全局最小值,如下图所示。 +网格搜索将会在超参数空间的每个点处打印出 WER (误字率)或者 CER (字符错误率),并且可绘出误差曲面。一个合适的超参数范围应包括 WER/CER 误差表面的全局最小值,如下图所示。