From 336283f8721c4f38a14b139b0fbbe2cf5893f4f7 Mon Sep 17 00:00:00 2001 From: Fangjun Kuang Date: Wed, 17 Nov 2021 19:24:07 +0800 Subject: [PATCH 1/3] New label smoothing (#109) * Modify label smoothing to match the one implemented in PyTorch. * Enable CI for torch 1.10 * Fix CI errors. * Fix CI installation errors. * Fix CI installation errors. * Minor fixes. * Minor fixes. * Minor fixes. * Minor fixes. * Minor fixes. * Fix CI errors. --- .github/workflows/run-pretrained.yml | 9 +- .github/workflows/run-yesno-recipe.yml | 6 +- .github/workflows/test.yml | 28 +++++- .../ASR/conformer_ctc/label_smoothing.py | 98 +++++++++++++++++++ .../ASR/conformer_ctc/test_label_smoothing.py | 52 ++++++++++ .../ASR/conformer_ctc/transformer.py | 70 +------------ 6 files changed, 185 insertions(+), 78 deletions(-) create mode 100644 egs/librispeech/ASR/conformer_ctc/label_smoothing.py create mode 100755 egs/librispeech/ASR/conformer_ctc/test_label_smoothing.py diff --git a/.github/workflows/run-pretrained.yml b/.github/workflows/run-pretrained.yml index 97d3c32d2..710ca2603 100644 --- a/.github/workflows/run-pretrained.yml +++ b/.github/workflows/run-pretrained.yml @@ -31,8 +31,9 @@ jobs: matrix: os: [ubuntu-18.04] python-version: [3.6, 3.7, 3.8, 3.9] - torch: ["1.8.1"] - k2-version: ["1.9.dev20210919"] + torch: ["1.10.0"] + torchaudio: ["0.10.0"] + k2-version: ["1.9.dev20211101"] fail-fast: false @@ -49,7 +50,9 @@ jobs: - name: Install Python dependencies run: | python3 -m pip install --upgrade pip pytest - pip install torch==${{ matrix.torch }}+cpu -f https://download.pytorch.org/whl/torch_stable.html + # numpy 1.20.x does not support python 3.6 + pip install numpy==1.19 + pip install torch==${{ matrix.torch }}+cpu torchaudio==${{ matrix.torchaudio }}+cpu -f https://download.pytorch.org/whl/cpu/torch_stable.html pip install k2==${{ matrix.k2-version }}+cpu.torch${{ matrix.torch }} -f https://k2-fsa.org/nightly/ python3 -m pip install git+https://github.com/lhotse-speech/lhotse diff --git a/.github/workflows/run-yesno-recipe.yml b/.github/workflows/run-yesno-recipe.yml index 876b95e71..98b2e4ebd 100644 --- a/.github/workflows/run-yesno-recipe.yml +++ b/.github/workflows/run-yesno-recipe.yml @@ -33,8 +33,9 @@ jobs: # TODO: enable macOS for CPU testing os: [ubuntu-18.04] python-version: [3.8] - torch: ["1.8.1"] - k2-version: ["1.9.dev20210919"] + torch: ["1.10.0"] + torchaudio: ["0.10.0"] + k2-version: ["1.9.dev20211101"] fail-fast: false steps: @@ -57,6 +58,7 @@ jobs: - name: Install Python dependencies run: | python3 -m pip install -U pip + pip install torch==${{ matrix.torch }}+cpu torchaudio==${{ matrix.torchaudio }}+cpu -f https://download.pytorch.org/whl/cpu/torch_stable.html pip install k2==${{ matrix.k2-version }}+cpu.torch${{ matrix.torch }} -f https://k2-fsa.org/nightly/ python3 -m pip install git+https://github.com/lhotse-speech/lhotse diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b5c8cfcfa..e897c3fb5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -33,8 +33,14 @@ jobs: # disable macOS test for now. os: [ubuntu-18.04] python-version: [3.6, 3.7, 3.8, 3.9] - torch: ["1.8.1"] - k2-version: ["1.9.dev20210919"] + torch: ["1.8.0", "1.10.0"] + torchaudio: ["0.8.0", "0.10.0"] + k2-version: ["1.9.dev20211101"] + exclude: + - torch: "1.8.0" + torchaudio: "0.10.0" + - torch: "1.10.0" + torchaudio: "0.8.0" fail-fast: false @@ -58,6 +64,15 @@ jobs: - name: Install Python dependencies run: | python3 -m pip install --upgrade pip pytest + # numpy 1.20.x does not support python 3.6 + pip install numpy==1.19 + pip install torch==${{ matrix.torch }}+cpu -f https://download.pytorch.org/whl/cpu/torch_stable.html + if [[ ${{ matrix.torchaudio }} == "0.10.0" ]]; then + pip install torchaudio==${{ matrix.torchaudio }}+cpu -f https://download.pytorch.org/whl/cpu/torch_stable.html + else + pip install torchaudio==${{ matrix.torchaudio }} + fi + pip install k2==${{ matrix.k2-version }}+cpu.torch${{ matrix.torch }} -f https://k2-fsa.org/nightly/ pip install git+https://github.com/lhotse-speech/lhotse # icefall requirements @@ -83,7 +98,10 @@ jobs: ls -lh export PYTHONPATH=$PWD:$PWD/lhotse:$PYTHONPATH echo $PYTHONPATH - pytest ./test + pytest -v -s ./test + # runt tests for conformer ctc + cd egs/librispeech/ASR/conformer_ctc + pytest -v -s - name: Run tests if: startsWith(matrix.os, 'macos') @@ -93,8 +111,8 @@ jobs: lib_path=$(python -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())") echo "lib_path: $lib_path" export DYLD_LIBRARY_PATH=$lib_path:$DYLD_LIBRARY_PATH - pytest ./test + pytest -v -s ./test # runt tests for conformer ctc cd egs/librispeech/ASR/conformer_ctc - pytest + pytest -v -s diff --git a/egs/librispeech/ASR/conformer_ctc/label_smoothing.py b/egs/librispeech/ASR/conformer_ctc/label_smoothing.py new file mode 100644 index 000000000..cdc85ce9a --- /dev/null +++ b/egs/librispeech/ASR/conformer_ctc/label_smoothing.py @@ -0,0 +1,98 @@ +# Copyright 2021 Xiaomi Corp. (authors: Fangjun Kuang) +# +# See ../../../../LICENSE for clarification regarding multiple authors +# +# 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 torch + + +class LabelSmoothingLoss(torch.nn.Module): + """ + Implement the LabelSmoothingLoss proposed in the following paper + https://arxiv.org/pdf/1512.00567.pdf + (Rethinking the Inception Architecture for Computer Vision) + + """ + + def __init__( + self, + ignore_index: int = -1, + label_smoothing: float = 0.1, + reduction: str = "sum", + ) -> None: + """ + Args: + ignore_index: + ignored class id + label_smoothing: + smoothing rate (0.0 means the conventional cross entropy loss) + reduction: + It has the same meaning as the reduction in + `torch.nn.CrossEntropyLoss`. It can be one of the following three + values: (1) "none": No reduction will be applied. (2) "mean": the + mean of the output is taken. (3) "sum": the output will be summed. + """ + super().__init__() + assert 0.0 <= label_smoothing < 1.0 + self.ignore_index = ignore_index + self.label_smoothing = label_smoothing + self.reduction = reduction + + def forward(self, x: torch.Tensor, target: torch.Tensor) -> torch.Tensor: + """ + Compute loss between x and target. + + Args: + x: + prediction of dimension + (batch_size, input_length, number_of_classes). + target: + target masked with self.ignore_index of + dimension (batch_size, input_length). + + Returns: + A scalar tensor containing the loss without normalization. + """ + assert x.ndim == 3 + assert target.ndim == 2 + assert x.shape[:2] == target.shape + num_classes = x.size(-1) + x = x.reshape(-1, num_classes) + # Now x is of shape (N*T, C) + + # We don't want to change target in-place below, + # so we make a copy of it here + target = target.clone().reshape(-1) + + ignored = target == self.ignore_index + target[ignored] = 0 + + true_dist = torch.nn.functional.one_hot( + target, num_classes=num_classes + ).to(x) + + true_dist = ( + true_dist * (1 - self.label_smoothing) + + self.label_smoothing / num_classes + ) + # Set the value of ignored indexes to 0 + true_dist[ignored] = 0 + + loss = -1 * (torch.log_softmax(x, dim=1) * true_dist) + if self.reduction == "sum": + return loss.sum() + elif self.reduction == "mean": + return loss.sum() / (~ignored).sum() + else: + return loss.sum(dim=-1) diff --git a/egs/librispeech/ASR/conformer_ctc/test_label_smoothing.py b/egs/librispeech/ASR/conformer_ctc/test_label_smoothing.py new file mode 100755 index 000000000..5d4438fd1 --- /dev/null +++ b/egs/librispeech/ASR/conformer_ctc/test_label_smoothing.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +# Copyright 2021 Xiaomi Corp. (authors: Fangjun Kuang) +# +# See ../../../../LICENSE for clarification regarding multiple authors +# +# 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 distutils.version import LooseVersion + +import torch +from label_smoothing import LabelSmoothingLoss + +torch_ver = LooseVersion(torch.__version__) + + +def test_with_torch_label_smoothing_loss(): + if torch_ver < LooseVersion("1.10.0"): + print(f"Current torch version: {torch_ver}") + print("Please use torch >= 1.10 to run this test - skipping") + return + torch.manual_seed(20211105) + x = torch.rand(20, 30, 5000) + tgt = torch.randint(low=-1, high=x.size(-1), size=x.shape[:2]) + for reduction in ["none", "sum", "mean"]: + custom_loss_func = LabelSmoothingLoss( + ignore_index=-1, label_smoothing=0.1, reduction=reduction + ) + custom_loss = custom_loss_func(x, tgt) + + torch_loss_func = torch.nn.CrossEntropyLoss( + ignore_index=-1, reduction=reduction, label_smoothing=0.1 + ) + torch_loss = torch_loss_func(x.reshape(-1, x.size(-1)), tgt.reshape(-1)) + assert torch.allclose(custom_loss, torch_loss) + + +def main(): + test_with_torch_label_smoothing_loss() + + +if __name__ == "__main__": + main() diff --git a/egs/librispeech/ASR/conformer_ctc/transformer.py b/egs/librispeech/ASR/conformer_ctc/transformer.py index c9666362f..f93914aaa 100644 --- a/egs/librispeech/ASR/conformer_ctc/transformer.py +++ b/egs/librispeech/ASR/conformer_ctc/transformer.py @@ -20,6 +20,7 @@ from typing import Dict, List, Optional, Tuple import torch import torch.nn as nn +from label_smoothing import LabelSmoothingLoss from subsampling import Conv2dSubsampling, VggSubsampling from torch.nn.utils.rnn import pad_sequence @@ -152,7 +153,7 @@ class Transformer(nn.Module): d_model, self.decoder_num_class ) - self.decoder_criterion = LabelSmoothingLoss(self.decoder_num_class) + self.decoder_criterion = LabelSmoothingLoss() else: self.decoder_criterion = None @@ -799,73 +800,6 @@ class Noam(object): setattr(self, key, value) -class LabelSmoothingLoss(nn.Module): - """ - Label-smoothing loss. KL-divergence between - q_{smoothed ground truth prob.}(w) - and p_{prob. computed by model}(w) is minimized. - Modified from - https://github.com/espnet/espnet/blob/master/espnet/nets/pytorch_backend/transformer/label_smoothing_loss.py # noqa - - Args: - size: the number of class - padding_idx: padding_idx: ignored class id - smoothing: smoothing rate (0.0 means the conventional CE) - normalize_length: normalize loss by sequence length if True - criterion: loss function to be smoothed - """ - - def __init__( - self, - size: int, - padding_idx: int = -1, - smoothing: float = 0.1, - normalize_length: bool = False, - criterion: nn.Module = nn.KLDivLoss(reduction="none"), - ) -> None: - """Construct an LabelSmoothingLoss object.""" - super(LabelSmoothingLoss, self).__init__() - self.criterion = criterion - self.padding_idx = padding_idx - assert 0.0 < smoothing <= 1.0 - self.confidence = 1.0 - smoothing - self.smoothing = smoothing - self.size = size - self.true_dist = None - self.normalize_length = normalize_length - - def forward(self, x: torch.Tensor, target: torch.Tensor) -> torch.Tensor: - """ - Compute loss between x and target. - - Args: - x: - prediction of dimension - (batch_size, input_length, number_of_classes). - target: - target masked with self.padding_id of - dimension (batch_size, input_length). - - Returns: - A scalar tensor containing the loss without normalization. - """ - assert x.size(2) == self.size - # batch_size = x.size(0) - x = x.view(-1, self.size) - target = target.view(-1) - with torch.no_grad(): - true_dist = x.clone() - true_dist.fill_(self.smoothing / (self.size - 1)) - ignore = target == self.padding_idx # (B,) - total = len(target) - ignore.sum().item() - target = target.masked_fill(ignore, 0) # avoid -1 index - true_dist.scatter_(1, target.unsqueeze(1), self.confidence) - kl = self.criterion(torch.log_softmax(x, dim=1), true_dist) - # denom = total if self.normalize_length else batch_size - denom = total if self.normalize_length else 1 - return kl.masked_fill(ignore.unsqueeze(1), 0).sum() / denom - - def encoder_padding_mask( max_len: int, supervisions: Optional[Supervisions] = None ) -> Optional[torch.Tensor]: From 0660d12e4ea7463c048c3b6f84595b808cc8eb15 Mon Sep 17 00:00:00 2001 From: Fangjun Kuang Date: Wed, 17 Nov 2021 19:25:47 +0800 Subject: [PATCH 2/3] Fix computing WERs for empty hypotheses (#118) * Fix computing WERs when empty lattices are generated. * Minor fixes. --- egs/librispeech/ASR/conformer_ctc/decode.py | 28 +++++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/egs/librispeech/ASR/conformer_ctc/decode.py b/egs/librispeech/ASR/conformer_ctc/decode.py index 96f6134f1..f5ffe026e 100755 --- a/egs/librispeech/ASR/conformer_ctc/decode.py +++ b/egs/librispeech/ASR/conformer_ctc/decode.py @@ -239,7 +239,7 @@ def decode_one_batch( is a 3-gram LM, while this G is a 4-gram LM. Returns: Return the decoding result. See above description for the format of - the returned dict. + the returned dict. Note: If it decodes to nothing, then return None. """ if HLG is not None: device = HLG.device @@ -392,8 +392,7 @@ def decode_one_batch( hyps = [[word_table[i] for i in ids] for ids in hyps] ans[lm_scale_str] = hyps else: - for lm_scale in lm_scale_list: - ans[f"{lm_scale}"] = [[] * lattice.shape[0]] + ans = None return ans @@ -467,16 +466,29 @@ def decode_dataset( eos_id=eos_id, ) - for lm_scale, hyps in hyps_dict.items(): + if hyps_dict is not None: + for lm_scale, hyps in hyps_dict.items(): + this_batch = [] + assert len(hyps) == len(texts) + for hyp_words, ref_text in zip(hyps, texts): + ref_words = ref_text.split() + this_batch.append((ref_words, hyp_words)) + + results[lm_scale].extend(this_batch) + else: + assert ( + len(results) > 0 + ), "It should not decode to empty in the first batch!" this_batch = [] - assert len(hyps) == len(texts) - for hyp_words, ref_text in zip(hyps, texts): + hyp_words = [] + for ref_text in texts: ref_words = ref_text.split() this_batch.append((ref_words, hyp_words)) - results[lm_scale].extend(this_batch) + for lm_scale in results.keys(): + results[lm_scale].extend(this_batch) - num_cuts += len(batch["supervisions"]["text"]) + num_cuts += len(texts) if batch_idx % 100 == 0: batch_str = f"{batch_idx}/{num_batches}" From 30c43b7f69a836c5beff2f77f042d624ae52166d Mon Sep 17 00:00:00 2001 From: Wei Kang Date: Thu, 18 Nov 2021 10:00:47 +0800 Subject: [PATCH 3/3] Add aishell recipe (#30) * Add aishell recipe * Remove unnecessary code and update docs * adapt to k2 v1.7, add docs and results * Update conformer ctc model * Update docs, pretrained.py & results * Fix code style * Fix code style * Fix code style * Minor fix * Minor fix * Fix pretrained.py * Update pretrained model & corresponding docs --- .flake8 | 1 + docs/source/recipes/aishell.rst | 10 + docs/source/recipes/aishell/conformer_ctc.rst | 625 +++++++++++ .../aishell-conformer-ctc-tensorboard-log.jpg | Bin 0 -> 315797 bytes .../aishell-tdnn-lstm-ctc-tensorboard-log.jpg | Bin 0 -> 436167 bytes docs/source/recipes/aishell/tdnn_lstm_ctc.rst | 504 +++++++++ docs/source/recipes/index.rst | 2 + egs/aishell/ASR/README.md | 3 + egs/aishell/ASR/RESULTS.md | 56 + egs/aishell/ASR/conformer_ctc/README.md | 4 + egs/aishell/ASR/conformer_ctc/__init__.py | 0 .../ASR/conformer_ctc/asr_datamodule.py | 1 + egs/aishell/ASR/conformer_ctc/conformer.py | 917 ++++++++++++++++ egs/aishell/ASR/conformer_ctc/decode.py | 585 ++++++++++ egs/aishell/ASR/conformer_ctc/pretrained.py | 380 +++++++ egs/aishell/ASR/conformer_ctc/subsampling.py | 161 +++ .../ASR/conformer_ctc/test_subsampling.py | 49 + .../ASR/conformer_ctc/test_transformer.py | 100 ++ egs/aishell/ASR/conformer_ctc/train.py | 679 ++++++++++++ egs/aishell/ASR/conformer_ctc/transformer.py | 998 ++++++++++++++++++ egs/aishell/ASR/local/__init__.py | 0 egs/aishell/ASR/local/compile_hlg.py | 156 +++ .../ASR/local/compute_fbank_aishell.py | 109 ++ egs/aishell/ASR/local/compute_fbank_musan.py | 110 ++ egs/aishell/ASR/local/prepare_char.py | 248 +++++ egs/aishell/ASR/local/prepare_lang.py | 381 +++++++ egs/aishell/ASR/local/test_prepare_lang.py | 106 ++ egs/aishell/ASR/prepare.sh | 162 +++ egs/aishell/ASR/shared | 1 + egs/aishell/ASR/tdnn_lstm_ctc/README.md | 4 + egs/aishell/ASR/tdnn_lstm_ctc/__init__.py | 0 .../ASR/tdnn_lstm_ctc/asr_datamodule.py | 331 ++++++ egs/aishell/ASR/tdnn_lstm_ctc/decode.py | 394 +++++++ egs/aishell/ASR/tdnn_lstm_ctc/model.py | 103 ++ egs/aishell/ASR/tdnn_lstm_ctc/pretrained.py | 228 ++++ egs/aishell/ASR/tdnn_lstm_ctc/train.py | 616 +++++++++++ icefall/char_graph_compiler.py | 99 ++ icefall/utils.py | 1 - 38 files changed, 8123 insertions(+), 1 deletion(-) create mode 100644 docs/source/recipes/aishell.rst create mode 100644 docs/source/recipes/aishell/conformer_ctc.rst create mode 100644 docs/source/recipes/aishell/images/aishell-conformer-ctc-tensorboard-log.jpg create mode 100644 docs/source/recipes/aishell/images/aishell-tdnn-lstm-ctc-tensorboard-log.jpg create mode 100644 docs/source/recipes/aishell/tdnn_lstm_ctc.rst create mode 100644 egs/aishell/ASR/README.md create mode 100644 egs/aishell/ASR/RESULTS.md create mode 100644 egs/aishell/ASR/conformer_ctc/README.md create mode 100644 egs/aishell/ASR/conformer_ctc/__init__.py create mode 120000 egs/aishell/ASR/conformer_ctc/asr_datamodule.py create mode 100644 egs/aishell/ASR/conformer_ctc/conformer.py create mode 100755 egs/aishell/ASR/conformer_ctc/decode.py create mode 100755 egs/aishell/ASR/conformer_ctc/pretrained.py create mode 100644 egs/aishell/ASR/conformer_ctc/subsampling.py create mode 100755 egs/aishell/ASR/conformer_ctc/test_subsampling.py create mode 100644 egs/aishell/ASR/conformer_ctc/test_transformer.py create mode 100755 egs/aishell/ASR/conformer_ctc/train.py create mode 100644 egs/aishell/ASR/conformer_ctc/transformer.py create mode 100644 egs/aishell/ASR/local/__init__.py create mode 100755 egs/aishell/ASR/local/compile_hlg.py create mode 100755 egs/aishell/ASR/local/compute_fbank_aishell.py create mode 100755 egs/aishell/ASR/local/compute_fbank_musan.py create mode 100755 egs/aishell/ASR/local/prepare_char.py create mode 100755 egs/aishell/ASR/local/prepare_lang.py create mode 100755 egs/aishell/ASR/local/test_prepare_lang.py create mode 100755 egs/aishell/ASR/prepare.sh create mode 120000 egs/aishell/ASR/shared create mode 100644 egs/aishell/ASR/tdnn_lstm_ctc/README.md create mode 100644 egs/aishell/ASR/tdnn_lstm_ctc/__init__.py create mode 100644 egs/aishell/ASR/tdnn_lstm_ctc/asr_datamodule.py create mode 100755 egs/aishell/ASR/tdnn_lstm_ctc/decode.py create mode 100644 egs/aishell/ASR/tdnn_lstm_ctc/model.py create mode 100644 egs/aishell/ASR/tdnn_lstm_ctc/pretrained.py create mode 100755 egs/aishell/ASR/tdnn_lstm_ctc/train.py create mode 100644 icefall/char_graph_compiler.py diff --git a/.flake8 b/.flake8 index b8f0e4715..19c3a9bd6 100644 --- a/.flake8 +++ b/.flake8 @@ -5,6 +5,7 @@ max-line-length = 80 per-file-ignores = # line too long egs/librispeech/ASR/*/conformer.py: E501, + egs/aishell/ASR/*/conformer.py: E501, exclude = .git, diff --git a/docs/source/recipes/aishell.rst b/docs/source/recipes/aishell.rst new file mode 100644 index 000000000..71ccaa1fc --- /dev/null +++ b/docs/source/recipes/aishell.rst @@ -0,0 +1,10 @@ +Aishell +======= + +We provide the following models for the Aishell dataset: + +.. toctree:: + :maxdepth: 2 + + aishell/conformer_ctc + aishell/tdnn_lstm_ctc diff --git a/docs/source/recipes/aishell/conformer_ctc.rst b/docs/source/recipes/aishell/conformer_ctc.rst new file mode 100644 index 000000000..20967780a --- /dev/null +++ b/docs/source/recipes/aishell/conformer_ctc.rst @@ -0,0 +1,625 @@ +Confromer CTC +============= + +This tutorial shows you how to run a conformer ctc model +with the `Aishell `_ dataset. + + +.. HINT:: + + We assume you have read the page :ref:`install icefall` and have setup + the environment for ``icefall``. + +.. HINT:: + + We recommend you to use a GPU or several GPUs to run this recipe. + +In this tutorial, you will learn: + + - (1) How to prepare data for training and decoding + - (2) How to start the training, either with a single GPU or multiple GPUs + - (3) How to do decoding after training, with 1best and attention decoder rescoring + - (4) How to use a pre-trained model, provided by us + +Data preparation +---------------- + +.. code-block:: bash + + $ cd egs/aishell/ASR + $ ./prepare.sh + +The script ``./prepare.sh`` handles the data preparation for you, **automagically**. +All you need to do is to run it. + +The data preparation contains several stages, you can use the following two +options: + + - ``--stage`` + - ``--stop-stage`` + +to control which stage(s) should be run. By default, all stages are executed. + + +For example, + +.. code-block:: bash + + $ cd egs/aishell/ASR + $ ./prepare.sh --stage 0 --stop-stage 0 + +means to run only stage 0. + +To run stage 2 to stage 5, use: + +.. code-block:: bash + + $ ./prepare.sh --stage 2 --stop-stage 5 + +.. HINT:: + + If you have pre-downloaded the `Aishell `_ + dataset and the `musan `_ dataset, say, + they are saved in ``/tmp/aishell`` and ``/tmp/musan``, you can modify + the ``dl_dir`` variable in ``./prepare.sh`` to point to ``/tmp`` so that + ``./prepare.sh`` won't re-download them. + +.. HINT:: + + A 3-gram language model will be downloaded from huggingface, we assume you have + intalled and initialized ``git-lfs``. If not, you could install ``git-lfs`` by + + .. code-block:: bash + + $ sudo apt-get install git-lfs + $ git-lfs install + + If you don't have the ``sudo`` permission, you could download the + `git-lfs binary `_ here, then add it to you ``PATH``. + +.. NOTE:: + + All generated files by ``./prepare.sh``, e.g., features, lexicon, etc, + are saved in ``./data`` directory. + + +Training +-------- + +Configurable options +~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: bash + + $ cd egs/aishell/ASR + $ ./conformer_ctc/train.py --help + +shows you the training options that can be passed from the commandline. +The following options are used quite often: + + - ``--exp-dir`` + + The experiment folder to save logs and model checkpoints, + default ``./conformer_ctc/exp``. + + - ``--num-epochs`` + + It is the number of epochs to train. For instance, + ``./conformer_ctc/train.py --num-epochs 30`` trains for 30 epochs + and generates ``epoch-0.pt``, ``epoch-1.pt``, ..., ``epoch-29.pt`` + in the folder set by ``--exp-dir``. + + - ``--start-epoch`` + + It's used to resume training. + ``./conformer_ctc/train.py --start-epoch 10`` loads the + checkpoint ``./conformer_ctc/exp/epoch-9.pt`` and starts + training from epoch 10, based on the state from epoch 9. + + - ``--world-size`` + + It is used for multi-GPU single-machine DDP training. + + - (a) If it is 1, then no DDP training is used. + + - (b) If it is 2, then GPU 0 and GPU 1 are used for DDP training. + + The following shows some use cases with it. + + **Use case 1**: You have 4 GPUs, but you only want to use GPU 0 and + GPU 2 for training. You can do the following: + + .. code-block:: bash + + $ cd egs/aishell/ASR + $ export CUDA_VISIBLE_DEVICES="0,2" + $ ./conformer_ctc/train.py --world-size 2 + + **Use case 2**: You have 4 GPUs and you want to use all of them + for training. You can do the following: + + .. code-block:: bash + + $ cd egs/aishell/ASR + $ ./conformer_ctc/train.py --world-size 4 + + **Use case 3**: You have 4 GPUs but you only want to use GPU 3 + for training. You can do the following: + + .. code-block:: bash + + $ cd egs/aishell/ASR + $ export CUDA_VISIBLE_DEVICES="3" + $ ./conformer_ctc/train.py --world-size 1 + + .. CAUTION:: + + Only multi-GPU single-machine DDP training is implemented at present. + Multi-GPU multi-machine DDP training will be added later. + + - ``--max-duration`` + + It specifies the number of seconds over all utterances in a + batch, before **padding**. + If you encounter CUDA OOM, please reduce it. For instance, if + your are using V100 NVIDIA GPU, we recommend you to set it to ``200``. + + .. HINT:: + + Due to padding, the number of seconds of all utterances in a + batch will usually be larger than ``--max-duration``. + + A larger value for ``--max-duration`` may cause OOM during training, + while a smaller value may increase the training time. You have to + tune it. + + +Pre-configured options +~~~~~~~~~~~~~~~~~~~~~~ + +There are some training options, e.g., weight decay, +number of warmup steps, etc, +that are not passed from the commandline. +They are pre-configured by the function ``get_params()`` in +`conformer_ctc/train.py `_ + +You don't need to change these pre-configured parameters. If you really need to change +them, please modify ``./conformer_ctc/train.py`` directly. + + +.. CAUTION:: + + The training set is perturbed by speed with two factors: 0.9 and 1.1. + Each epoch actually processes ``3x150 == 450`` hours of data. + + +Training logs +~~~~~~~~~~~~~ + +Training logs and checkpoints are saved in the folder set by ``--exp-dir`` +(default ``conformer_ctc/exp``). You will find the following files in that directory: + + - ``epoch-0.pt``, ``epoch-1.pt``, ... + + These are checkpoint files, containing model ``state_dict`` and optimizer ``state_dict``. + To resume training from some checkpoint, say ``epoch-10.pt``, you can use: + + .. code-block:: bash + + $ ./conformer_ctc/train.py --start-epoch 11 + + - ``tensorboard/`` + + This folder contains TensorBoard logs. Training loss, validation loss, learning + rate, etc, are recorded in these logs. You can visualize them by: + + .. code-block:: bash + + $ cd conformer_ctc/exp/tensorboard + $ tensorboard dev upload --logdir . --description "Conformer CTC training for Aishell with icefall" + + It will print something like below: + + .. code-block:: + + TensorFlow installation not found - running with reduced feature set. + Upload started and will continue reading any new data as it's added to the logdir. + + To stop uploading, press Ctrl-C. + + New experiment created. View your TensorBoard at: https://tensorboard.dev/experiment/WE1DocDqRRCOSAgmGyClhg/ + + [2021-11-16T10:51:46] Started scanning logdir. + [2021-11-16T10:52:32] Total uploaded: 111606 scalars, 0 tensors, 0 binary objects + Listening for new data in logdir... + + Note there is a URL in the above output, click it and you will see + the following screenshot: + + .. figure:: images/aishell-conformer-ctc-tensorboard-log.jpg + :width: 600 + :alt: TensorBoard screenshot + :align: center + :target: https://tensorboard.dev/experiment/WE1DocDqRRCOSAgmGyClhg/ + + TensorBoard screenshot. + + - ``log/log-train-xxxx`` + + It is the detailed training log in text format, same as the one + you saw printed to the console during training. + +Usage examples +~~~~~~~~~~~~~~ + +The following shows typical use cases: + +**Case 1** +^^^^^^^^^^ + +.. code-block:: bash + + $ cd egs/aishell/ASR + $ ./conformer_ctc/train.py --max-duration 200 + +It uses ``--max-duration`` of 200 to avoid OOM. + + +**Case 2** +^^^^^^^^^^ + +.. code-block:: bash + + $ cd egs/aishell/ASR + $ export CUDA_VISIBLE_DEVICES="0,3" + $ ./conformer_ctc/train.py --world-size 2 + +It uses GPU 0 and GPU 3 for DDP training. + +**Case 3** +^^^^^^^^^^ + +.. code-block:: bash + + $ cd egs/aishell/ASR + $ ./conformer_ctc/train.py --num-epochs 10 --start-epoch 3 + +It loads checkpoint ``./conformer_ctc/exp/epoch-2.pt`` and starts +training from epoch 3. Also, it trains for 10 epochs. + +Decoding +-------- + +The decoding part uses checkpoints saved by the training part, so you have +to run the training part first. + +.. code-block:: bash + + $ cd egs/aishell/ASR + $ ./conformer_ctc/decode.py --help + +shows the options for decoding. + +The commonly used options are: + + - ``--method`` + + This specifies the decoding method. + + The following command uses attention decoder for rescoring: + + .. code-block:: + + $ cd egs/aishell/ASR + $ ./conformer_ctc/decode.py --method attention-decoder --max-duration 30 --nbest-scale 0.5 + + - ``--nbest-scale`` + + It is used to scale down lattice scores so that there are more unique + paths for rescoring. + + - ``--max-duration`` + + It has the same meaning as the one during training. A larger + value may cause OOM. + +Pre-trained Model +----------------- + +We have uploaded a pre-trained model to +``_. + +We describe how to use the pre-trained model to transcribe a sound file or +multiple sound files in the following. + +Install kaldifeat +~~~~~~~~~~~~~~~~~ + +`kaldifeat `_ is used to +extract features for a single sound file or multiple sound files +at the same time. + +Please refer to ``_ for installation. + +Download the pre-trained model +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The following commands describe how to download the pre-trained model: + +.. code-block:: + + $ cd egs/aishell/ASR + $ mkdir tmp + $ cd tmp + $ git lfs install + $ git clone https://huggingface.co/pkufool/icefall_asr_aishell_conformer_ctc + +.. CAUTION:: + + You have to use ``git lfs`` to download the pre-trained model. + +.. CAUTION:: + + In order to use this pre-trained model, your k2 version has to be v1.7 or later. + +After downloading, you will have the following files: + +.. code-block:: bash + + $ cd egs/aishell/ASR + $ tree tmp + +.. code-block:: bash + + tmp/ + `-- icefall_asr_aishell_conformer_ctc + |-- README.md + |-- data + | `-- lang_char + | |-- HLG.pt + | |-- tokens.txt + | `-- words.txt + |-- exp + | `-- pretrained.pt + `-- test_waves + |-- BAC009S0764W0121.wav + |-- BAC009S0764W0122.wav + |-- BAC009S0764W0123.wav + `-- trans.txt + + 5 directories, 9 files + +**File descriptions**: + + - ``data/lang_char/HLG.pt`` + + It is the decoding graph. + + - ``data/lang_char/tokens.txt`` + + It contains tokens and their IDs. + Provided only for convenience so that you can look up the SOS/EOS ID easily. + + - ``data/lang_char/words.txt`` + + It contains words and their IDs. + + - ``exp/pretrained.pt`` + + It contains pre-trained model parameters, obtained by averaging + checkpoints from ``epoch-25.pt`` to ``epoch-84.pt``. + Note: We have removed optimizer ``state_dict`` to reduce file size. + + - ``test_waves/*.wav`` + + It contains some test sound files from Aishell ``test`` dataset. + + - ``test_waves/trans.txt`` + + It contains the reference transcripts for the sound files in `test_waves/`. + +The information of the test sound files is listed below: + +.. code-block:: bash + + $ soxi tmp/icefall_asr_aishell_conformer_ctc/test_wavs/*.wav + + Input File : 'tmp/icefall_asr_aishell_conformer_ctc/test_waves/BAC009S0764W0121.wav' + Channels : 1 + Sample Rate : 16000 + Precision : 16-bit + Duration : 00:00:04.20 = 67263 samples ~ 315.295 CDDA sectors + File Size : 135k + Bit Rate : 256k + Sample Encoding: 16-bit Signed Integer PCM + + + Input File : 'tmp/icefall_asr_aishell_conformer_ctc/test_waves/BAC009S0764W0122.wav' + Channels : 1 + Sample Rate : 16000 + Precision : 16-bit + Duration : 00:00:04.12 = 65840 samples ~ 308.625 CDDA sectors + File Size : 132k + Bit Rate : 256k + Sample Encoding: 16-bit Signed Integer PCM + + + Input File : 'tmp/icefall_asr_aishell_conformer_ctc/test_waves/BAC009S0764W0123.wav' + Channels : 1 + Sample Rate : 16000 + Precision : 16-bit + Duration : 00:00:04.00 = 64000 samples ~ 300 CDDA sectors + File Size : 128k + Bit Rate : 256k + Sample Encoding: 16-bit Signed Integer PCM + + Total Duration of 3 files: 00:00:12.32 + +Usage +~~~~~ + +.. code-block:: + + $ cd egs/aishell/ASR + $ ./conformer_ctc/pretrained.py --help + +displays the help information. + +It supports three decoding methods: + + - CTC decoding + - HLG decoding + - HLG + attention decoder rescoring + +CTC decoding +^^^^^^^^^^^^ + +CTC decoding only uses the ctc topology for decoding without a lexicon and language model + +The command to run CTC decoding is: + +.. code-block:: bash + + $ cd egs/aishell/ASR + $ ./conformer_ctc/pretrained.py \ + --checkpoint ./tmp/icefall_asr_aishell_conformer_ctc/exp/pretrained.pt \ + --tokens-file ./tmp/icefall_asr_aishell_conformer_ctc/data/lang_char/tokens.txt \ + --method ctc-decoding \ + ./tmp/icefall_asr_aishell_conformer_ctc/test_wavs/BAC009S0764W0121.wav \ + ./tmp/icefall_asr_aishell_conformer_ctc/test_wavs/BAC009S0764W0122.wav \ + ./tmp/icefall_asr_aishell_conformer_ctc/test_wavs/BAC009S0764W0123.wav + +The output is given below: + +.. code-block:: + + 2021-11-18 07:53:41,707 INFO [pretrained.py:229] {'sample_rate': 16000, 'subsampling_factor': 4, 'feature_dim': 80, 'nhead': 4, 'attention_dim': 512, 'num_decoder_layers': 6, 'vgg_frontend': False, 'use_feat_batchnorm': True, 'search_beam': 20, 'output_beam': 8, 'min_active_states': 30, 'max_active_states': 10000, 'use_double_scores': True, 'env_info': {'k2-version': '1.9', 'k2-build-type': 'Release', 'k2-with-cuda': True, 'k2-git-sha1': 'f2fd997f752ed11bbef4c306652c433e83f9cf12', 'k2-git-date': 'Sun Sep 19 09:41:46 2021', 'lhotse-version': '0.11.0.dev+git.33cfe45.clean', 'torch-cuda-available': True, 'torch-cuda-version': '10.1', 'python-version': '3.8', 'icefall-git-branch': 'aishell', 'icefall-git-sha1': 'd57a873-dirty', 'icefall-git-date': 'Wed Nov 17 19:53:25 2021', 'icefall-path': '/ceph-hw/kangwei/code/icefall_aishell3', 'k2-path': '/ceph-hw/kangwei/code/k2_release/k2/k2/python/k2/__init__.py', 'lhotse-path': '/ceph-hw/kangwei/code/lhotse/lhotse/__init__.py'}, 'checkpoint': './tmp/icefall_asr_aishell_conformer_ctc/exp/pretrained.pt', 'tokens_file': './tmp/icefall_asr_aishell_conformer_ctc/data/lang_char/tokens.txt', 'words_file': None, 'HLG': None, 'method': 'ctc-decoding', 'num_paths': 100, 'ngram_lm_scale': 0.3, 'attention_decoder_scale': 0.9, 'nbest_scale': 0.5, 'sos_id': 1, 'eos_id': 1, 'num_classes': 4336, 'sound_files': ['./tmp/icefall_asr_aishell_conformer_ctc/test_waves/BAC009S0764W0121.wav', './tmp/icefall_asr_aishell_conformer_ctc/test_waves/BAC009S0764W0122.wav', './tmp/icefall_asr_aishell_conformer_ctc/test_waves/BAC009S0764W0123.wav']} + 2021-11-18 07:53:41,708 INFO [pretrained.py:240] device: cuda:0 + 2021-11-18 07:53:41,708 INFO [pretrained.py:242] Creating model + 2021-11-18 07:53:51,131 INFO [pretrained.py:259] Constructing Fbank computer + 2021-11-18 07:53:51,134 INFO [pretrained.py:269] Reading sound files: ['./tmp/icefall_asr_aishell_conformer_ctc/test_waves/BAC009S0764W0121.wav', './tmp/icefall_asr_aishell_conformer_ctc/test_waves/BAC009S0764W0122.wav', './tmp/icefall_asr_aishell_conformer_ctc/test_waves/BAC009S0764W0123.wav'] + 2021-11-18 07:53:51,138 INFO [pretrained.py:275] Decoding started + 2021-11-18 07:53:51,241 INFO [pretrained.py:293] Use CTC decoding + 2021-11-18 07:53:51,704 INFO [pretrained.py:369] + ./tmp/icefall_asr_aishell_conformer_ctc/test_waves/BAC009S0764W0121.wav: + 甚 至 出 现 交 易 几 乎 停 止 的 情 况 + + ./tmp/icefall_asr_aishell_conformer_ctc/test_waves/BAC009S0764W0122.wav: + 一 二 线 城 市 虽 然 也 处 于 调 整 中 + + ./tmp/icefall_asr_aishell_conformer_ctc/test_waves/BAC009S0764W0123.wav: + 但 因 为 聚 集 了 过 多 公 共 资 源 + + + 2021-11-18 07:53:51,704 INFO [pretrained.py:371] Decoding Done + + +HLG decoding +^^^^^^^^^^^^ + +HLG decoding uses the best path of the decoding lattice as the decoding result. + +The command to run HLG decoding is: + +.. code-block:: bash + + $ cd egs/aishell/ASR + $ ./conformer_ctc/pretrained.py \ + --checkpoint ./tmp/icefall_asr_aishell_conformer_ctc/exp/pretrained.pt \ + --words-file ./tmp/icefall_asr_aishell_conformer_ctc/data/lang_char/words.txt \ + --HLG ./tmp/icefall_asr_aishell_conformer_ctc/data/lang_char/HLG.pt \ + --method 1best \ + ./tmp/icefall_asr_aishell_conformer_ctc/test_wavs/BAC009S0764W0121.wav \ + ./tmp/icefall_asr_aishell_conformer_ctc/test_wavs/BAC009S0764W0122.wav \ + ./tmp/icefall_asr_aishell_conformer_ctc/test_wavs/BAC009S0764W0123.wav + +The output is given below: + +.. code-block:: + + 2021-11-18 07:37:38,683 INFO [pretrained.py:229] {'sample_rate': 16000, 'subsampling_factor': 4, 'feature_dim': 80, 'nhead': 4, 'attention_dim': 512, 'num_decoder_layers': 6, 'vgg_frontend': False, 'use_feat_batchnorm': True, 'search_beam': 20, 'output_beam': 8, 'min_active_states': 30, 'max_active_states': 10000, 'use_double_scores': True, 'env_info': {'k2-version': '1.9', 'k2-build-type': 'Release', 'k2-with-cuda': True, 'k2-git-sha1': 'f2fd997f752ed11bbef4c306652c433e83f9cf12', 'k2-git-date': 'Sun Sep 19 09:41:46 2021', 'lhotse-version': '0.11.0.dev+git.33cfe45.clean', 'torch-cuda-available': True, 'torch-cuda-version': '10.1', 'python-version': '3.8', 'icefall-git-branch': 'aishell', 'icefall-git-sha1': 'd57a873-clean', 'icefall-git-date': 'Wed Nov 17 19:53:25 2021', 'icefall-path': '/ceph-hw/kangwei/code/icefall_aishell3', 'k2-path': '/ceph-hw/kangwei/code/k2_release/k2/k2/python/k2/__init__.py', 'lhotse-path': '/ceph-hw/kangwei/code/lhotse/lhotse/__init__.py'}, 'checkpoint': './tmp/icefall_asr_aishell_conformer_ctc/exp/pretrained.pt', 'tokens_file': None, 'words_file': './tmp/icefall_asr_aishell_conformer_ctc/data/lang_char/words.txt', 'HLG': './tmp/icefall_asr_aishell_conformer_ctc/data/lang_char/HLG.pt', 'method': '1best', 'num_paths': 100, 'ngram_lm_scale': 0.3, 'attention_decoder_scale': 0.9, 'nbest_scale': 0.5, 'sos_id': 1, 'eos_id': 1, 'num_classes': 4336, 'sound_files': ['./tmp/icefall_asr_aishell_conformer_ctc/test_waves/BAC009S0764W0121.wav', './tmp/icefall_asr_aishell_conformer_ctc/test_waves/BAC009S0764W0122.wav', './tmp/icefall_asr_aishell_conformer_ctc/test_waves/BAC009S0764W0123.wav']} + 2021-11-18 07:37:38,684 INFO [pretrained.py:240] device: cuda:0 + 2021-11-18 07:37:38,684 INFO [pretrained.py:242] Creating model + 2021-11-18 07:37:47,651 INFO [pretrained.py:259] Constructing Fbank computer + 2021-11-18 07:37:47,654 INFO [pretrained.py:269] Reading sound files: ['./tmp/icefall_asr_aishell_conformer_ctc/test_waves/BAC009S0764W0121.wav', './tmp/icefall_asr_aishell_conformer_ctc/test_waves/BAC009S0764W0122.wav', './tmp/icefall_asr_aishell_conformer_ctc/test_waves/BAC009S0764W0123.wav'] + 2021-11-18 07:37:47,659 INFO [pretrained.py:275] Decoding started + 2021-11-18 07:37:47,752 INFO [pretrained.py:321] Loading HLG from ./tmp/icefall_asr_aishell_conformer_ctc/data/lang_char/HLG.pt + 2021-11-18 07:37:51,887 INFO [pretrained.py:340] Use HLG decoding + 2021-11-18 07:37:52,102 INFO [pretrained.py:370] + ./tmp/icefall_asr_aishell_conformer_ctc/test_waves/BAC009S0764W0121.wav: + 甚至 出现 交易 几乎 停止 的 情况 + + ./tmp/icefall_asr_aishell_conformer_ctc/test_waves/BAC009S0764W0122.wav: + 一二 线 城市 虽然 也 处于 调整 中 + + ./tmp/icefall_asr_aishell_conformer_ctc/test_waves/BAC009S0764W0123.wav: + 但 因为 聚集 了 过多 公共 资源 + + + 2021-11-18 07:37:52,102 INFO [pretrained.py:372] Decoding Done + + +HLG decoding + attention decoder rescoring +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +It extracts n paths from the lattice, recores the extracted paths with +an attention decoder. The path with the highest score is the decoding result. + +The command to run HLG decoding + attention decoder rescoring is: + +.. code-block:: bash + + $ cd egs/aishell/ASR + $ ./conformer_ctc/pretrained.py \ + --checkpoint ./tmp/icefall_asr_aishell_conformer_ctc/exp/pretrained.pt \ + --words-file ./tmp/icefall_asr_aishell_conformer_ctc/data/lang_char/words.txt \ + --HLG ./tmp/icefall_asr_aishell_conformer_ctc/data/lang_char/HLG.pt \ + --method attention-decoder \ + ./tmp/icefall_asr_aishell_conformer_ctc/test_wavs/BAC009S0764W0121.wav \ + ./tmp/icefall_asr_aishell_conformer_ctc/test_wavs/BAC009S0764W0122.wav \ + ./tmp/icefall_asr_aishell_conformer_ctc/test_wavs/BAC009S0764W0123.wav + +The output is below: + +.. code-block:: + + 2021-11-18 07:42:05,965 INFO [pretrained.py:229] {'sample_rate': 16000, 'subsampling_factor': 4, 'feature_dim': 80, 'nhead': 4, 'attention_dim': 512, 'num_decoder_layers': 6, 'vgg_frontend': False, 'use_feat_batchnorm': True, 'search_beam': 20, 'output_beam': 8, 'min_active_states': 30, 'max_active_states': 10000, 'use_double_scores': True, 'env_info': {'k2-version': '1.9', 'k2-build-type': 'Release', 'k2-with-cuda': True, 'k2-git-sha1': 'f2fd997f752ed11bbef4c306652c433e83f9cf12', 'k2-git-date': 'Sun Sep 19 09:41:46 2021', 'lhotse-version': '0.11.0.dev+git.33cfe45.clean', 'torch-cuda-available': True, 'torch-cuda-version': '10.1', 'python-version': '3.8', 'icefall-git-branch': 'aishell', 'icefall-git-sha1': 'd57a873-dirty', 'icefall-git-date': 'Wed Nov 17 19:53:25 2021', 'icefall-path': '/ceph-hw/kangwei/code/icefall_aishell3', 'k2-path': '/ceph-hw/kangwei/code/k2_release/k2/k2/python/k2/__init__.py', 'lhotse-path': '/ceph-hw/kangwei/code/lhotse/lhotse/__init__.py'}, 'checkpoint': './tmp/icefall_asr_aishell_conformer_ctc/exp/pretrained.pt', 'tokens_file': None, 'words_file': './tmp/icefall_asr_aishell_conformer_ctc/data/lang_char/words.txt', 'HLG': './tmp/icefall_asr_aishell_conformer_ctc/data/lang_char/HLG.pt', 'method': 'attention-decoder', 'num_paths': 100, 'ngram_lm_scale': 0.3, 'attention_decoder_scale': 0.9, 'nbest_scale': 0.5, 'sos_id': 1, 'eos_id': 1, 'num_classes': 4336, 'sound_files': ['./tmp/icefall_asr_aishell_conformer_ctc/test_waves/BAC009S0764W0121.wav', './tmp/icefall_asr_aishell_conformer_ctc/test_waves/BAC009S0764W0122.wav', './tmp/icefall_asr_aishell_conformer_ctc/test_waves/BAC009S0764W0123.wav']} + 2021-11-18 07:42:05,966 INFO [pretrained.py:240] device: cuda:0 + 2021-11-18 07:42:05,966 INFO [pretrained.py:242] Creating model + 2021-11-18 07:42:16,821 INFO [pretrained.py:259] Constructing Fbank computer + 2021-11-18 07:42:16,822 INFO [pretrained.py:269] Reading sound files: ['./tmp/icefall_asr_aishell_conformer_ctc/test_waves/BAC009S0764W0121.wav', './tmp/icefall_asr_aishell_conformer_ctc/test_waves/BAC009S0764W0122.wav', './tmp/icefall_asr_aishell_conformer_ctc/test_waves/BAC009S0764W0123.wav'] + 2021-11-18 07:42:16,826 INFO [pretrained.py:275] Decoding started + 2021-11-18 07:42:16,916 INFO [pretrained.py:321] Loading HLG from ./tmp/icefall_asr_aishell_conformer_ctc/data/lang_char/HLG.pt + 2021-11-18 07:42:21,115 INFO [pretrained.py:345] Use HLG + attention decoder rescoring + 2021-11-18 07:42:21,888 INFO [pretrained.py:370] + ./tmp/icefall_asr_aishell_conformer_ctc/test_waves/BAC009S0764W0121.wav: + 甚至 出现 交易 几乎 停止 的 情况 + + ./tmp/icefall_asr_aishell_conformer_ctc/test_waves/BAC009S0764W0122.wav: + 一二 线 城市 虽然 也 处于 调整 中 + + ./tmp/icefall_asr_aishell_conformer_ctc/test_waves/BAC009S0764W0123.wav: + 但 因为 聚集 了 过多 公共 资源 + + + 2021-11-18 07:42:21,889 INFO [pretrained.py:372] Decoding Done + + +Colab notebook +-------------- + +We do provide a colab notebook for this recipe showing how to use a pre-trained model. + +|aishell asr conformer ctc colab notebook| + +.. |aishell asr conformer ctc colab notebook| image:: https://colab.research.google.com/assets/colab-badge.svg + :target: https://colab.research.google.com/drive/1WnG17io5HEZ0Gn_cnh_VzK5QYOoiiklC + +.. HINT:: + + Due to limited memory provided by Colab, you have to upgrade to Colab Pro to + run ``HLG decoding + attention decoder rescoring``. + Otherwise, you can only run ``HLG decoding`` with Colab. + +**Congratulations!** You have finished the aishell ASR recipe with +conformer CTC models in ``icefall``. diff --git a/docs/source/recipes/aishell/images/aishell-conformer-ctc-tensorboard-log.jpg b/docs/source/recipes/aishell/images/aishell-conformer-ctc-tensorboard-log.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7ea2e83698edae33a347d6e45ec73cffbd421af6 GIT binary patch literal 315797 zcmeFZXIxWF*Dt(7=)LzQy(1l^1VoyMAV?RG4kEn;iS!PFpn{45B8pN)dJP>Ly-6oQ zM0x@W5dt|IuX5k#Iq!#ap7-4E@BMHM%$|SNUbAM_>?v!_o`mp)umsRw(lgWpAP@k! z2mS#B6cDTn_i_gSV`D%90044;7{UpVfCyv(G$CAnV?Br%0R2rT0)QkhfcQ_ID`0vW zKxx18{E-qB68*(N{-Y537lxjkvJ$ocRZ~yDV80+wKYxA&nX`cE1w&)vQ;A^sjfHEPX7M4i0A>p$2U08O#cGE zwT&%5*$Su&6rcr^0bVDUAb)LB)61ta|4M($|NF8(`Md7GnDnWvzsdi5fYH@0$OTmX zI>_$q8sy>w;tl{He(K^M7z_ZUr*y%vVEU7Zv#M~g(^SyQD@}G2PcP~9d5QDvi2<{bZcn!qtAWn7*(l!5+r!dgZ?9Z}@ z>fHl%wEv{PcM1g2A7w3scw3y(Pv!4=x*7f{A4+@M^O_Y%rvw0~P^g#X>FA&Zu}qM+ z`DuN?xv6 znip&b=(}LgYX%?&+Xvd?;`F=zpf1p1H(%{P+XNcw7G!-|H;|vG-qr1*E{H+hq2Jwn zEl%}4m4ovSzHnL=n3tH+|JLtu0@8^E+-~Wg(gi@Q7!+#$XI^5<;J|CAbg-Vp?*751 zr)>zBoOl|Hvy1xc|Nz`a6d=@C_`%2QUI| zfuBP_>;~rft29gCD@gJB`}1F=JApD?!1~?-ZX%h&t;bUpqq&Fpu5yus(< z^*7I7`kp@V(=t!{N6^`_vukJZe@F>-g9n5C8PM_b4-fS6@C@eH23H3+enVdu87Y4G zv+{BPaJtr<@&Ldd>+dxL!us)Fv^a2#Yxoifgw}u2j1B>y_6#`um;OZ)9R;TeaGrjj zcyfCJcHJ;8n+2!sI$ zAO=VT(!kaDA@Bq!0A2vEfePRq&;Yaooj@P(2^a<@fLXBjtNb3^9Y)KyE-hAij_g2m%rZNrPlVoM-ax7$O^{B=2gnFy z8iInXL3SaBL{K7XB4#2UA`v24B2^-7A|s+}MD|1;L;*y%iQQ0_L|IAMOF2imM@2;?Ky{AlDwP*i zG}R-jw^Z+`P*lID8L1_xb*QgXhfrrwmr!?5PgC#F(9np`Xwlfx1k+^DyrJo)S)jqu zGSSM=8q&JbM$zWc*3*vCZqrfF3DarQIndpv%b}~G8=~8!r=S<1*P(Z!kEG9|Z=#=~ z|H;6_Aje?B;KPv4P|EOu;X5N4qX?reqbp-P;|s=a#$_fblOU50lM7QEQ!!I7(+V>w zvnaD6^G)V7<_hLPW(*4>iz1693!Ej7rHy5Y70N2YYRGzvHIwxn>m=(T8xNZ{n;TmS zTP52l+W|WlyB50}dn$Vs`vm(T2S0}{hc`zSM+3(^Co!i4=T*)y&V0^Z&P^_6E;TL} zu2imfTr=E6+!EYo+!5R_xIc6M6@SdrMc zIH|a*xVQK-@nH!f2_*?ni9CrRNg_#QNiWG~k|R*q@tT*zTy`pCM9E~B&9B;V`UZPK;=s1H5DP18!As#rc{|#O;yuX-=8Bnci~*r zxz=;P&MTh}KL76gj+(TZw_2&%cXd&9H}zumWeouhCynPCOPc(eH#7@1mtbdLPOu^v zT1!yNRqK`3s~+?F(lw1YW4SaG-Nu=Z;RtMd(HSi>Vg}bs2Rnbf4%h=n3d~ z=#}YV^p*4@^g9el42%r245kcu3|$Q07-BA|T)K0q$B5d<+~|oB`m)63z{}0XM8=nl z?;Fou5x(MkrNIO+F*LbvGH)ts8erOTmGr9V)x4|U%;d}vX8q<&=8op2=KI$!T+6&R zYawP4V$o$uXL;T7jpc#WMXPM9C2LvhJJz3UIBmRa8g0pJEp1=f{H%M++-6*|*cQSD*a{B3P=={_f$2gh<@&&N z%}v8C+ilfd!#&&myN8CyeUCLym}idXrk9S_6EEydgPR3654=shOS}oUtZr5Lko(;5 zY4TMbw~To^GHafb7WVPU{rk6O0<6T z>ln%y@0fwuv$5H+KjN(7n&WxmqvMwo^b^VwX%hnzr;^l?3X+MFy^;r06jC0ioTR#@ zeoQ-?mXn50cS-+vSMKhkyMzq)jKNIh%=~+#_k8b7X2G&vXES8q&R)K6e82ty|AW*A zKOQ7vG94i~C=yzI^kF^Htib;}YMJrPpS!d)}zLc~i<= znps9v7E-oWe!YCS;$lT(rF7-%Mbu}sIeK>4WqIRk&{zCQ{5P6!IjelDZ@$ZaZ(Y+{ z8(z0tU)k{AIND6yV%U1REw){|qqXxHV~ttC24V@j>3bY|B|j8@bp15_xv=lEe{_(F z$X!AHH-JzFf~EO>|Gz$_n=^_*PrLUkvL*$75R!8tINf|8Yuor6sTvho{%gpx}_uFnIXwxcG#`q~w&;?E4QM=Hxzl{G{kb@yk~wuiuou ztEsK4Z)j|4?&|L8?dyO4;p6Do_{8MYm+2W4dim?hx7F`!>)74BA3ygGaK8>u^@0G< zKh*kLv;U$O1E?1fF)@^w>{KrZQ5YDZ48$a7W15-^aGgH{?T zDLEzi??Cxyp#B|bPXpcGfdC4DfHH`QiOIl!dMXMk`v2oVm+ z7&(GCM>EiOFLFYzsWsc)GPsG&Yb7CF68Zk>qqkqt(J+VaRjGKMBOS!8W=td!8`NJw zeWhS2epK(x^WKs1Fo!CLoarpyYecJOo-&VJ*f3*mJ4Qd_RDc5OSQOuEFUT| zg)R2E@~)$e&CMF4a_i0j0XZa81v3*y*UE_nt^xyto_H~gNaS^i-InGDfs>GLA9>P_?==tR3)~g1I zg8J!hZtc(hU;S&Kd+DjWI}|5luv(Sgd7Zvy+0LD$=F6jSLHqIGyu4#O)9i&oCoh@z zMKLaVS*yV$#e-kQ0t16O$iDNi>=A&?X>1Q3feV*StqKmsoYWMrv)O8vmDI*M`9--~ z4OrZRG#R+@FQ+d*bv=e?kuYEVC;rn0|8pN;`HcHy*NjadFH1OUG_8V(B3d zc96_GqpNlKA{Lgii8n;etC&t!sO$Kl#oV(JS|yome+B%C8871*xxb5F;{LIk3hd8_ zl^%qJ*0a7_SorwXuH)s`toIfcSF;T@fI=!}tHJZKTWqL#^FDdcsk3>;oMr-b?TF~n zj8|Hb>&kj#6SwOXc8|Gf!Qp$#40+M(%wJW`7)roZm5vIG$x}bC7b>`jaz70o01$py0?mNJM<9VD(=1@_aF}dW&|&tbW1ZjT*z0M78oPP8q*;!N`9s$TMK}HfVqVFH<9HUm z6ztQO*ho=at|s1YYChPMtPA-z6Cb0gKmevqu(Bt!Q}fsU8O8t1WdCa);O6UDQ~H9S zDK$iOi?v<5%zo~Xej8$p@92U?PuP!dt@n)xKs@biFE5u#ysCGTFx2!&&EUg6P5Sk@ z?f0}?zVnO9@E=t#*GiL%ADU8eKc#&Y&Ep6|7-I@D+xc<%V_mP8O)$y2Pa=|Mr6t8z zY;JFpZOcmHFJ_bM zf2{dGJQ^rr?0EKMWQqWMry~IODNdN9JU0ly4>AJqA)WwGe)lY-jX2VGBmjl5lgpyG ztH&>@2*5BO0T5xrOFl1(KDV>Q6Lk_z0Dhe!T&V%Kb`BJ;q=c0^3Rm{&m!^9viOe$@{i5+ zkCpk4UHy+I@sIEHkGJ@bfBgU5Rs>=EpRKfiw$lDzz2JrtCjPAtwW^?#w!|?yOOr2o z)3AKKrfav;@12R-h z7rKqx;t<&D^Y(HEMdpmv)HXI(mWb}@+(-p}UXo15>i5W!!DTHmCrM}@!&`o>7Ge85 z^77f|8k?w)pGa6@@h{FfleLArHyl}>47GD(!!fkg%Up2vi_H&gwX5mp)Cqu3o^Q`g z7GLh_^$#cI9y!dAA4)8H13O!GN1AIVib<%6sdS&Io|+A)wh>7pYV~Bq!=OjkQZQj& zAX5=7b$<^Npppr@85PY(jW-gFSNC4#@_|`4?4FEJ_G)z0?P-bc=fIr}O}dat^|rikmSIdbYoWYCLS6@E=e)f-(gx>5v_?w9UHn6D6bCEy!m0L4 zaS-hJ4V$+ZSlaXP%33b{_Lk_`xlZ|+KB(eIzoNltA#o79)BB$sz#(HQu55{JD-%U` zH;M`Gg4vf$zFK><#~SZk*Q(!MlfkEK=q~^2%d`Q%!fM@PNU?weW0VZkG^HtK1fD-ZZPf2AfY?R8eNq4l@yF*RKT0J3wU3^#YE zn=Id!_G8lz&Io_rH2%CH+q&Wvg9t865gw)BJ~Cd#4Ef2z^6OW{$$}q=R^lRtmk5nxHZQcB=HGqZ zUWJy)sd6Yne$2C=3#g+!k+B4Ty-u=?4Yinp8viND%=pPm$b9DduZzo{t$kfm7Bmaa zzj4r4Pe&nikIP{m$OK;D`<*B1*mTawYTx9&*?y9Nk$Ri6rgKWQX60%z#Ni2W{vQI- zn#o12%RNzSC+s-=4sonekEZauT1;`ZzM^gB6JCmJr$_jry!3?r`D?`aT}_J#j>Q}K;oeNYGt+3~~ zJTp749TxlJq|52W8NMJA8KIlOOyjzQ)n>%ChS zRp?-|?z7d(#riA1rsSi_I93vXJ2bk8y@=CUpgHR98C*!nGFJ#z>ab(jtkbD6oB-6? zjLI=sB%{I%UJR(F3E}bF#>+!91xsYzFvbrkI!;{QtjRq<=L^a>3~=JNAIx5wDSoX7GraR2o55N)NSY1BEw*O^b~>vhaAijh2x&}aN8V6+ zKIN2;()aDcCVM{DpaGhJA9A^@d*MdyOk@7Jp9Iy>(VDeIt#l}>EvhBD^*7QLZO^_mqd1d{K^l9}vEfSGQgWT$Lk#|exT!t6 z<5JgjWv=ONPoMgh4ATlt`f@68c#`^SuYa-5YV#P=-xCDa?^}>-sGg_@Kf_Dh0W->dAlcG4!@Nxe&!&X zh~$H_*7a;LXnj$uD9Ue34x_THR~3XJ07<+ON#+yM&P;8^_paN_v0s6~v+VVmngcam ziK)}`b)Dg}`>n@MBYAL@%bl9C*t)u$D)%*>&t5bGJ)uKqx+;2xFJdn&6zQ9(feo2e zRBG+`Wj#mvF#mA?&-}AFFGYomoy$4r0M}r*_ii_|iMbgD?7$gX>^~SWi>Z9IC7pC} zwhwO0_C&Ghyj+*RAfx&5-cZQ-4ntn=ejo12tgn2}q8;dz+QP6cDC6AtS~{K&Xd^EK z44wBWf<}3tX0JCWB)C@~GE-t8dwc~t$y3Z1pas8?nX^)Qo-f_K8 z3)9Vuk&e%TL=UU;txd^>$E}7`kl-naqY~UGUy_xBT!SOyP&o~W6f0L!!IADWK?WA< z47T7@^|9o4CPSS)3+l&jP5^`gRw|z!Tb1rpdu+S->FA;)^8wM+08ldHKt9huM=m(v zwiKtur*+lAX&H7GMtQ{1~Co)N9&BH#thucuUAmUHn?9^lW+#`aQq8UCrB?*qZLcd>S6JkN_Z1&X7`uMGkRk?pKTdZC$YSTgQ|#W;YT0yT-^AhE8b=ea~@enQ%ZiNBgQrK zvLWkpdkRSB*BcZ(ZNrijBhtLt9^P$LxIFO9AnSgeP0Kxb@2W|d_t12U7WR5O)dW7o z&F{_Z+;N7>JNLTSCFL>ZDQ}MYl+LB3dkk^;iP4((iW*_bFeW?%Q`R*KpF*=X`4xSy zeplG|IE8kb;@VwPh4-6~Gp4NkjHHlC7jVc!Fj31cj=h+no~)Y(=N%U7>=eyy=Pz)* z&}jRpD`p0tZ}5c=dP2W^uX?QHI4imDHll8?602mwJKb4o2Uf&=cbjumGJUC67~SJ@ zHHMgeG@U*uo%7Jk#$HF9nBkuO1u@8feC_&cU94ilJv-7vu;R|W?tFpJ#j2loe-Xeo z!#W|5zrLiM-R|A{yXP~sfjwWHbA00D9A01;!Sn)QFrjYl!Ips64j`$>DK2-d&+*Q_ zc+*v@lhh(kVe1SDd9gL<@z2`It2|@n>*KO3zAqq8N2v+OLz3+Rc=k+uIv*K2<1Z{UFr>S)UE) zT#bvSb1G^aBEnz9z{HQhm@|X+5B+u3zSen0Upkt_RVW)E&eGyDyy{pmv$#c3gpfL} zYz=q9>i5yTgkPHKzHKyZGa&S?&rkGW99M*Ocgx3*=XQtdA)+yk*YPsA7R=(ZNg@&@ zgLA6vuJSUH)Y|Q-;?kD@E*UbHX6t?7M?GL97mTF=ZtMR4>|`AuVe)TZ1&XSg*0{B; zDH%D!_@QPoNxmwlpc=5lbbBGAERCqIiLN z7;Ers*}>g!5q1%E&)O#i$I#jwL3x*S!xm^v>bjpM1zrq^b6zC%Maa1$n1?Hn`_9h|E=ZCQGoR^B z;=*^#9^hvig0%P)P9_fOU6!pj7fT)w+r!daA3D#ecXQ4@^q`vZl!9o;>sM$WNqceH z96yipqVb=(7{Y*7GYarG<+uoQpMMK8ZOJeoBmTMN@B+p6Wo+LcqgP!F&(y{|ws*YH zl(GJCH{xhEE!j2Y5YDE(E(pe4OD`zfVHypd0p?RwBnN8cR1476H(B3h|Gx8cUj z*?5nqPmWD6N!?K-I7$N0V_OjaW9RK0uFCX|xp~xio5+!He#%j2s~e92#A}v2B;opZ z34m+n^bwjZWk=lw?MLNtZM-XOOW0jNXVo7Yfkgqgh|1(T{Hx zJQBdGU@a?3;FC14UIjf_X}c|Dm9uopcK!*w94^MmYKYbVM?HjHeM8-Gb32jaY@c9b z`)I3)pL*)qQC*tS51ew_ERV9bz1Q*xK%66W9mCR(JnclWR_OV;?*VqLIar%ZZ&qTn zy56S~Ve7hO5$<($1&JqAQ+PkrPV!;Jqiok+*oQe>N{-c9U?bWNoW^X zw?uky&bPFFEEm{iw2^WP@=_>vYv382h*WJ~`J?r+rQpa<(hpZ@4a2c7x~eVBvNYK zHY_Dl)H7<*0Gn7pHA>1V( zEGUGlKY;I{&`po5Y5Ec_)0o97rPY)prHuu$5h-=?BMpR3JIUB&Di&V$-y#aq*BfNOvh1X%A zG0(WWGAQny!ME$Au#lw5Hd+F(l-t#2g-WREtgz~S>wr7oHzR2vCF&*2pbN~hPTQwH zAEwLEI_g{v^@M&an6Xq7J}!oNgtw|ytKT@BSU;DJb{`?B;TjQHxa@MbrE%`c`MQ9^ zuz0-NbKEj|@h;50Ev!3Vb+oR{HUw*uq=frc-xy~aE8oD1br2Kuj=fMm@+ew}v~Stb z5+Q&5ERqhvKj8}=e(ZB-`(e4Ee7AJJH%NLZ8p+l&UQ@yLXMx97c76>OH?ccyF3x2A3d{n|cjr>%F~IvZY&$ zgDo${)n3G9h812nEXLjM9vd9K?uEUCm<_L3?a87K><$PSyzu1EqlXWw$pC+WnrP_q z3F@l1;$^J1o}B48lc5$Rsm95gUe>oPx~fMV7#M!82WNkzg6GDaD|3J+b=;7DgP4JFAVjD#3!`bl&rSU`6*!Riw=<0YexC9F7S`lEzCSs*jBeOsP;O5~ z*bxAVrz4lSBMHC}$BlHa=C@T zc+@qt*vxJ@3(69)+`6IvsB>`PC%9_$3{9skW%ka8Ag(SK(B64rwX0j38`@xH$z*HnreI1GPAGKQ-+w3P1tELYKF>E9L_+rcy@bbFld-DK9wf*H2` zds8&U`d4`cYa7@|AP;o*eP*FQsT#jV`pb1E}U$q?P`j;A?lgh=IzY1%It${xq~?- zwbuo1SByJ+;x>krFmEul?c)W<0GDyw%kY89&c z0IpJKglMPRQ6uxZn0$p6(Yi+6!*wJ##jwoJ%BIn z8ypw3pMmG^^=XP=>O+h#i?wHu?r!(WUifiz*|J8LyMMen`!=IKGX%3xffvs&7g zWY7NI`xi7qrZeSPFL+TlDZJm>A0u%}m`_)E=?rVxozprLDh88ST0Z!(JSfe#7Uz~q z?vUlWE`QMHZD)h?TWX8yJK@D;maQ#BCAW(6%-Q-(J(KuFfrwR$St(0iydA9>;(Wf6 z20&CCNgEN#k^u~aEHLAAFk>Aj&^%Obg1UxJ3EcUc`12Ke5^wxd^*0E6aN$YCa|%U5+!_55%2Y zLMCw*bV&<#qoc@g?yBdWzw@)_U_>rNw=3_lkgEm5bFE?$rzZbtrMpWe(;iF6uB|Jp zJq2`%3a@Z6TduYB~? zM}r@I_}%KSx6@vXXxzvUgMRb-qO3u=u_S_or7SmS3N=sFE#i!FmWUR8j;_Uwem5K( zAsytq+jLO%RFem1-WhrB_-^nHC9a_NMHi>^YQ}a_tlzePcOIfYLeg4C$Yi%wrt50m zv=#SiI$yiG&ymRKx@-Y@R2^wNPAq}sdVP%CsZaAF48W3rXIuAocL`tDqjQ37}S1|I?`0W7jbX}vy+17 zKrN=lXZLyp0*!{+@fg4`k!4GRqNoeTj7@OaiP@z9PWNZhAP-Z zVsub^$&S74g@aToyC?pJ*11lAp*KR>!}Cz{A?jFS=)&-pz}vA}TsBn%oL-;# zsvc31KqX)S1t>@UgIii+g>;EX*Pk_wxQe5T##KdptOTITL(!a!4|&pOEy#I8t=&)R z)h@Ct!YTm~R*Mrx?ZoD@x8NlG3oxl)@HS(eKcg6`~!|WZI;j7&Ro)h>iAL03miHZ0za7`N$pBc4I|BxXkvPnxS`KA>oiYWqT zo-_nU6Q=hu#{5D(_zj)Zgfryj-1MeNwA_AsP`|}J-+AzBM?*(e3)7i*9cv=58*vn%-;ka0-+lygbKY2^Kw^PfF{x~nRw_nUz?cbaWD)snYoxRR%M9p>XayBP8Vy??^G_-OEKOOgbD;btV$SbKL6 zx=s71u`zzl?MU})w4`B*eXJ{Fx6tAT%L=c`aW>3jC)q)?6`PsTD*epdoKm*9wzZ|& zXt+&tjHP@;U+$+&aejPOFMv=fLn!ewVlp?=FpIsm_0N{A6$t?I0DEhlU+tH<4)tlD zF1Gh>ca{0KcCo#8IIzAm3sd{+IEpAg_6+pVC9Fp4u2{DrvvQe`XMdxmvwl<6E58#O zg#5UE+^7#Jdl80uBj|ar@2*|1n?y+tr9PFwS*pG%>Nf0?$;n92qHx3_liCH>55o%3 zvXuH^ta%};m)b8l@@FiC-$bh{6w*Dj&L{&n9VH__@yYh>%v?}L^`}|Z0X93Z0cvS7>1xBko0h+wFO0oUf-!^r`<7F0t zknH_Rqj>f@oB_COnAmIh<&5BEWfMg2TS+%~weDIk)a1AOH`2r%#F6y#TTPzu;G9rC z(B6gu21HyC`q;K>%49r5epkFDV;B+N!Sz0U`%~l=*>w+=70#qhza!=Ke8DEH(oQVO ztIAh%D&S^=ieZUyAi3tP94fIo_xB$@TZ;y+gVpay>0}_3R|5OMfeCll zMflYVRMNQ5%{#*nFE82RXXB(mx!y+-t#q`-AgA$h260MzssxNjZDku1Q#S7v`hkN-Al>h z>RyrWGvb0rRn%F`*&4SP3bDF@i&QX=sCXEu-_Fkhz*BF^VtiOP=uS{jz@0Fm zOWF*-4$LmCKL$3#r-NVOo5)BjMFl#Ne}@3kXc9SxNg=+f3XQfckaNN+#(&`38U;#IRbqnE(W*dO>D z_Sz2a zqPmRsBi`fn{a%|y9p^E_$I_$RpD3|zQGCR=)`tuFgfI3uCQR{BfnFwG*NMvH59zQg z&A0})FrnM#HD0002aE-^)(@Z7_ath|d<|98?q&@1{!xIo+8n}|qbHGUsd#VHj*4BX zY)#&VT1$oIHv`z}gLk$@OqU)lk%>ZINp``!kkbUfI4aJ81ZRhN(TV-^d@WyQq|!Hd z!!xc=%1mFy>@s)uQsU?Il{Am1!%&!yYH(xSVsy>-51hCr^{8U~SC1MCHub}1ulcNQ z9)*S@yYDukD-h&I+ytQRU<(RMv4Ek(Qhpe0UM$#P(>)S>?{g6KN%=mh{nPMA^MjIK z@FYi)2r`@(`a3=Z#Yg??{Cuk)OwkLG2tgpnZCT@Sm zF+q@%an`FqxDxSj++hG&Ppz#=R}=6wBMg#Ha_0_Onrq(&d3+zC;)Z3}@;TwGd{(Sf zTdkh;AZnf~G-eBVTiAl2Y znD9w49h{^F4FzKZ9L_zD?1$BaCE~Aoqvr)Xv-HE9{HH?iX$*|lD>qOZaol*9ZCQW! zU7&Iw(LKs&T_9XPF1SK|KZ&^@7wmfm#YgrGaNNLX+pes%W zEQh_o_q01(N+s5P{B@j_G5&&A6By^dv}U(!*f(juYOkt3^)=M`4|99Dq}4uQHLE>n z5+)X(iSJ2Q%m#a{u*u1c&6~#wbuJpwaxHcQIcmI4a($#Ri(zpUiVUFH)zQ6(P_dW zMh(Xd_X1Myj17Sb+k!+acHNIUGn4fthP@+4)eM|F3FPOYW8nqI;YB~tR1OwB{t)=A6{jB zg>P^DS-ia|Nj;L7%I z;!@T1U(T*aO>?roc|CnxBz%AKAZOn^+`PY$=bgxMU6Plf?ZZtGl9M`D`IZQmv&*Ld|Gz?>$HH?1um|4(w z$*CqTe%_LKP59IA8qvh%|p{d)ee?r zUh45W$(`xkCE?1KLHh-p1!*(B1(3a&6|;q@Yt05OhL1?I1hrV$V|F1O+@@q3KMwYl zONWAjxFynA(i%-UnxXf{_gNJ8y1j{WRpg~idtT0ei7qXbHx!Kq*1h*iIvt5lSnU8BJ8k>-Oa2O zSo0;TjtciV(e440Bm2tW`Ce&1;gLV!9!2z0!vg-FsW3#oL!&OQ<_UF8HyfnDu=a-itccFOeu3Zr848*x7 z8{R>-u5J}tW8jqNnyqUQSlV%~>c9|M-A~pg#b!ArvEwIksk&NEtTWneo%TG#oYhy6 znxzU!l;5TiX4wMg^D@oe5gm<5EI>={-QKU6w{^T&jx|Db>G)Bx(vwovi!DMz)A?L* zZkPx(S#-Os4%(Ow_3bXEq3hr_>2tTTwHf!814w$@nC6LA(dQbh4Ky5h8JtwTe zln=I{^8Dj+%s{063|(>`VYD3YO4YK-=blcz&-}f*OXX~1a*$eLF~GwTw`N> zHDzI8geNEJbGgA6W%16=59qrvQ2h{Cifu_(n&I5WjK`QK%t@1hEQNPp(Vdj>lOFYw?eY`}u}k#79DT_sdb&ICT$KYx zrK>8jIcjTqIpRo`+H3Ma*@0*Dr%^cLj1s)6a@#ity+Y2x_)#^CJO2md;22)jS&-U* zWOl>;2+Lvk64k|puF&tU{^jd9l=0zA$m4gUlYWXTdRqOq`=$7ViIB2+71Uy{2H)2G zwPw*&&GR2#c;{MfJ7@C<{H$QzI7r*$_b0y95tpRd$j?{le|`3PlJaPAk+Rq`jOwQoUL1&Xt}^otrxF{C+PdP1?)JIc`wqoa$pqpAK{e9I(?KEyCs+Dw(hFg zj!Ef1B>8#w+2h6xv~|pk!;Gn%j7t6S%Zva=W!ww!$WDAK&kJ}ix}b-Lm5&?lzSCp2 z{sybi)m-j_rV-v>Y2I6NvXV1De}V3&7WjJoi(1*NB#RYzRBGNnRy?bVsK1b- z&+tc?#V-^ViGpJn`!)1?{c&MBxG|R!&(L}+P3G3|>?zZc&)d7w^W}l0aVp|?Gxnzs zxr92FzYk42T3|w}F-%=y4v>}!-yf<)`Q)(rdDn5LT^XU2tyMRG@632lNzdiTqEtGohp7%Ft{R>IDn5Zt~-AEGL9S;;B=h>c zbt~2TTW@&Y8nU8AT!j1rXRR8pYVp;L+1uIGdIiW|98>P0?lfvBT79$6ypm4}$af)MNXDD#eVZwPsz0eiEi!#S5yPD1 zqU~jF-1->-ue`Bvq1q7K08M{-*8DyAQsw9d+^RcL;`m9sKqkXl=wZRWUP9?ju-jy}QX03M-hb#tBrU_@7wMGfs3Je+LyS4OG@uUcHaiu!_HO3NYNn4~ zaXtG`bWo6SZ|@C1#u$iv-d^&m|7Px}eNX-94XIbU2iz53Xk_v6)#>B7lJlPA4P~_WV<%_xQ&5Es4#a-bwT8M0nQZn^cSy0pFo_;NBHEvf8FF~6aeTM5W^S&Z@&$?WHZ!Sj^w*yn z3C8M}nNHz>&uPqZ;$flu5~b~1#Ox3z{z zZLuJqz0_&9ela-y_$}EJQVcVoH5eY1bRvxvO+h-r62MK?iaH86tZdIDIPxv2Vtc=( z_FTV`dw=hKvLa5Xb2IeFlx(qpQu9nN)&#Yki)H1}G?wVMwegj9c@`5|%P8Ne=1-JT zL?y}Ka zaM{b~1U_m?CHYl&bm@(hs^#=O)k3;)v}v5H~cu% zH1|oPl8`00e?j+STIw2c^GD|tnS^5RL|x6%D5w2#@+t3|fqO zg)3A)Q-VvyFSL~(SmusMs+%pIy*Jy{8xM)yN>%Bwe?j);gag5gi&>IQ8^+z&!G*s7 zPo1_c#Jsk-c^LY*k^p$VDjX50t9aj_T)$*Qh0m1z+++BGLoFJnOLCl&BSzBW4qEnJ zt-c{Vm(st+%%!5v;7U*&Ct`C5{){k9{<_f@liWVMCetsUZH(f;yL?(P0?K%PqH2P^o7X;rF(jnI=Dl2>z#I{8Y@@C>Ui%GV`A7 ztTxxzk^8zETuf&Odu#vsw%Cx_9mzdd4=P z`hmHw^t-R&(*C=KXCC_ZWN;Bh!?e76BL(pmZ5Wjv$HYkThPN5(e7rZ=>diiHTU1O= z4s7cPMC-7M*T!YgdOI#X%Sn5Mm%uFKp@vutmwjXgXFt?W3O^K$XeG40y$-bSEbwWbOGE@j5 z3PlVdvQ4rJQ+7&1$U2ODH`ZYm->Y+09xA!&gYkOU< z<@s7JO9JCGsFvao@2^-EJKnqRc&Pmq>1Q$F#{Q?2n)Wm4MP4)w3-i{n7@yV;5~?>I zxR(`qMQ0aUx{94Bg0}?ayHxNWMv&obE|&OsOl|Lc9RKQ+;++8atKvS5IjHcO`#sUO z3)<<=Vz0x)-?sZ$<1j;!v$$;h%Nb3a1=`Wx3*kBpJz&Xs0VmIV;acd#En}ai+%J4R zo&)ylhBel^;T`xer$`>5gA zSa5I!E6Rr&k6H}-P*MV=b$89}=^dObUrS-{kRbHE3bKA%R9fsD+i_XBfVoWOPW8`o z&T9C5DR}AkP$;H)9m!;k*Ts_5m7>~fG^>IZYU1nC3nz1LryP_%EG`aV=T-mKlGxJ( zA?^7ePFkY=8&&ulRrniK_#0LD8&&w{ z{f7G@N-xp@PmP6Ew?ceq@F|Pxrg+ZuK0I8nTmF1JD=9bX1nG5}He4j`pjmiBtJJvU zV-3PHaoRgB7J@jjVN|dL0Uc_|A`c(_Xc_8vxV&o~m5y@?$f{4`U#z&3KyAXO$B@0Y zE5o5q=%z280AcF-nB6D0x3;9C!RgTl6^##6R$p$6Jee|pFF(O{*UTV75G*SQ4!d5P zNE}M*&0>0?*sy}Bu9o)so>QY|8nTq4kNG#bvVUtiS$jM6=KYr>c7mXTA{`pfozgJ0 zPttkTo84)S4PzQ*gMJ%L7py7D-F@%Pxf48eJ^^ZW)RUY4OVM`n6V(_NBJT*4-Lv3* zJm36g#(nF;ApDsCc6j6NPkws4Jp3O?bJ6n%SDJoQD~GctGBgX_d3bt|WrhFl$RJu? zaW4^u*Iis5S)V(MrDJ0HHhIfax$sp{QhS#~baj_6w{1B=k!6GJyD2bMQ>eE-|Cd+`5Dq|bqZylv^{ptaA5!px-D{wUrql3s0{1o9QA9&=* zshGnL=PQnGDk9U22j}eyNwU+8m#j<7{3GT2zBMZTd=*li=T}GGwdfoMvqjN!-)(UZ zTx<<>Pt^J;-kwK2VjiPgu8}7_|FP6SKL6;GCr?@+zQ~bCb~_}KJT%vHqBdIMuFZX0 z7vEc#_dKq1;0G`hBZFuBS)sCM;AQmX43pdd8_>F(~{@`f<*c8wZ7W1?gFq z?O1f>S1c_UGu68QdEjVd^ocAxUpiZm$S8WjJ$V1-*G27quXa(ERW$^ zhox&;RH`v=GyL_`f?AcjQL)}Lrt-b%A6ru;o;;`L*Ia&BTS1)GkUyjZ&2)Y}mEW7b z66YdX_>AsE)Oo4-J)Gxc=8SkmyWI!&EAX#yGZb|oGW$%-0?UH>W{V5N4-P=jMV`JO zv(#~_XG7ftFWi7;s^a#1G9rQ8N2FUUZ)iB=$*WWtq^01hN1zQ}F@<+WVcCjj9B!n)@f*o8rM^uXK&5Lt(=Kd(B>O5h8c_CJ4xk%t9)p$U~ZpeYN zNtOUa3-i&$I)Bp{M$}|Go;UW+yd%es*d?V(=elnpUrdS>x~4RAi5ID*3>VAA(!B2t&f_bu}d;-x!-PR z9AP=S&d|ZSu}UyCp0260r19H}hu3_8Cmrfc{~A~ytoYI`TModSVH)9yX(hW(M8>|0 zS7yG#CmyJ9M)58_W3dm*RDuDcMXZ>96OHu0vOHtMll`lKZZTVn+_UYY? z?8lU+U8XD(F^8&HeH20T59g5WBQoPR^_TF??oiPc(~+C=9S*(bqzaS=e;=FGt;;VP zZ#;3`bF9R6Po~dVyfLr=$-%h$4KNN7EE+6bNYTJ4t(kV8xn14bj>S>EiojZT&@<*_lWtxLCtdz#Kd+O}S?HGDLcH&tQ(oY(1I-FEAYBFH%X@i}qiCsQ+UnSo6{5R)&`~aOW zi9G#!MEEJ>GVL@Aa3pApR-EOF{t$3ncvn-B+K>$UdN%9EGKwg$Nc+LEH*QG3wT9t@ z1iSo2AN7ps7V0ubwIhY&Wse5Virc3dKUQ4l4;g(@4^z(kzgd6upVjDr?L_^_a%iF^ z10Uv!GbD(hLd0@a6Tg0Rk*#sxtHKc$_A~iH`sEk{&nCzaPt52YOuqDNi$k;3qSpzU zDOX2M2kAN17x~Qsd)gT4`w)rB$B!mIdfm)jw5ksxZ(HZ+7E=vzI+1;~YZ%(2xDn31 zbB+r+KAHme-D*T`lze?EFDzNCAw>0bH_*{D|mS1TxDU?&(9oYwGO#4-i zHiPsl-L~Lc%^H%UNnE5Pzk_&#)*2}e#i-N4A4&==r*^>!P2>i7+!4-eu{QiP7hcx) zs6yS9$1Af!A&Z!Y$O4ZKsL&+-;5xG87n2F2P%681w)HpzZG|`d52T^ivBxC5V0V;i zO3tflrI9})_DF~^+AA`*5v5||r2_NRv09u)^G*hGzE=d#@HNU0vKmDn+k#w`z1hGz zS9qBg3K$EOr%v_YQQYBBH%{o==_HXP&csX3Qig;J#W)e>;%=L(eH?++yJ^{vCc#^M z1PKa6`9(#Lf~r;hrPVqE&wB~ou@Wxvsl(Ki`=WLH_>e^1xV@>o96YX+e)4TrZkU+9($qbfvv7N z4BbDIMBgs2z&Vv9XlQO^{!wyvGiYV0wb$vCg=X4@CS4iXEU^^z^Gkn4r^Vpes71Q> zy=&oEBoqF&ZZ`g|ia?^P>ubw_CI@=Q!*S5wQ(SwCWq2&4+|Kn=@g%1DoLFQECZ0uk z%4xKdTT}7z-h^B=CPmxj@vk2_Uk!dXm#=PkU`Bb>(v42@?^U9V-WT%WyTg<(qdqS3TL_aPNN-TYGk zDDRRPF=oVZHBXh^mXTSN1u?r~cs&FUY!W?ViRb--*w~Nqj9a^iry7ACa^Mlgi3Qe; zr{p}|ychN^(@~6Hzn4F${Y3PjrugTzM=zGUX?&ro5YN1K1bHGa?y!G_!eYmjwlwmG z#pi*APea${Im39Jg3f(1)csTfd2qe#3|B;1cG7A5iJ=8n{L4Np*Dhbd`gq3&<-S4r zaEUMx=2C>%C;yVD+xZ&fs#*_6wFlHqR;R%r6D%JvqxjE@Y{UTiG4uR zn|1Y!zZdEM< zac7~zBAF4k$OlN4)zS)W>>Q6?jw)@BU!Rq?$E*IPo0oi^TNlK$MJrxn{YdrX(T(m@ zyh=3>JMfbN;XvyttsSh<=2l9~h8rEe>GDd8%Y!f4ID{{sFIrQe{Ni7#{_^h_`rpj; zZ|3?pbN%0DuH{S|exEF9$j3bIP1GrhE)vY9P42036Fzvk+p;CU3C|B}6its14o?jj z&%U*b)E2tlD@6TK-hR<=I3sd+aYgZX8^F%@zPP8&pED8vVfIbR{tIiULn1drnV-mA z^xr#Vz*GzEsTrE6WALib8DZEr)+rF+=pb?u2qb-mIA^f&(%=S|>XLhBR#c+*9$kKZ|vQQ2AogqE* zqs6b+##IU9q=V_pgEBKq$f{!lX@{}L9uTZ6E81#Y3SFM-MnGtWu9qXBpazgNPFl0Q z(D|@kh=?qmbH|OMXj9IxLj|^*5^E@ye1_y*nIAMD2X2W^gR3<{r=SI>58;R3o0QbZ zS<)*@2Nz9oII3~J<}Z(3viY$5sx)!X_A%>~Jj>e$_D2N-`^W%Qn#Jd2SDp{J>frd* z&iNs>aBpvKkIequtT)$aZVzgoRX=c)`=Qb~_NHBx|HIDy?*RkLhw(CtQ{?0QM1Ar{ zVXW4SuC4o-{!4EL&L60MiTwtPI&qa>Kk1CpIofnD?vhz;!da8I&xkx1m1WKP)Oy1S zstE+78PCX}$TretLy z$BPc_(@U{Zkv=Z_J~`y=Kh1vP3sbgT@_vrIxQv;2^YO6kzVv~J6#Cfp1C3{*RZl*3 zyVidun!!sj7zPAi6>Gs_OHgFmPsbJ=XS+9*;>k;h{8o9jJ>RUKhbS`(1yJ29=IVG(qDzAz@zZd^<8oaF%g)nA)i9dFi8g*@I6FyGA4-EeJ8>OJmS5@ zp~aGi@~YUxJq@$v8DWA!6M6|PG2}MU3N0GPqMjJ3`jlG%%Jmw8@ynQfZeJX0QC z@5*A~*&ciH-VW3XiC6oqL|0eCmFG5Pr3~U;@dkZw*dF^odd~>&&rD`y!V1+1MfLL9_Jb;1f(6RSC>!RmxyFi z+q4bo>^3-jyTw~ErBc3NEg>u}+FtR>`FTW~pp)=7kS~)^ag4y{vujbRGSxGqhRpTU zfz0!`DZ{LP+Hn20$$d`Mv4*v<;9a5->T%(TjM5PG3_HwzA8Me%)6Wbtwo9N3CdmRx z^Pex$nCBUl9+jG_k!*CaYq4HS=$mO#^UO8P zInd-Kk;`IBEzExT*4Y>P!L35nP5i(gpXVHSz=tXB!oX01+r4uuAX>P8F}5T3lS=Ed z&vNlqgYio)_oJc=iDN!seO4$w6GAMOGg|OlE*|9~B;h+*|i2SjX3X_;Z2Dqcbz}x`A z#I#CU#c{1H{lKyJyRG^fxXaCpmU#Y%v$JRpD#Pr$ zR`xj?Ew5)$v107~erxc_EFtQ;s-xsq%YBN14pJtqp>BreI+seMZdur`dze@^_dY=$ z{b((6s?EI`1d89H5~!s9V6ks8qXtQDgg^U%Hs(k)h}wYadNt2a)+#rXgLNndgsuH8Z7M;y?Ky ztDs(k7P5lkEhdGaZQura(ECjqf?5f7eY$A7oUsVq(^3zer22@{`XRR5AEm#fg9#QhE2fWos|f zsh5^il)tr~3lKS0N)XB4m)b;lyNA2{;7N1AHCMcNil?jQVnpO{VPRXL=xx|RquvJB z+xdOdQ8G~i%HxY!wNXr)DIGTFP>#ST2AQLHx@tc*9PPsjz2tACxU0Aui~ZBCUT@L8 z{3RhjhZnyCMFPK`Iv{keiDuctdl=TUFgy{kirMdA!4~8#3j4s}PDZBLzp{z%{Wh&9 z(k)H(O6=^#zB{|x4=_KYYVnR?q543)fVUdb3EkX}hhz6V;mN(m)#Q5M6i#b*t#J>i zbJZkr<&*{!r|{2FFAiCrAv%(txp~5Dp%1I5@chZ_L``g;_pK#!izbDE*~cxMLh(yv zo7>DPtPDr>n|i4PVQ^g~9)=-QPsUJ#zmLA-NF<}DPhHNp8a_5>g|W_l1LjZS$Bk=T zM50WEnc@y)LCSOkvCl`udV+@#kv^K2!eOeR!LWlq3Rc62!;|^_Q=3<#K3+fSCCdLcnz>lIIKC$}c31Y& zeNHhhH*A@ya}R1L7v(Q$86=LsB^7|uVeNVu>3(}%I_|*5C+d9bHhQkS!u1c>;*$H; zZwvPW10QC#$n*eAHMX*PGVR_ z>MptSb&*_nWVRrYzMSOhF4(5TWm+v#E}R5d-Xf1P`FP|U+;U!L3*x_wz_F&QLTt7m zaFZ>_Z3K}vVGHswm0;3McmfJt$YY4A_PR=3dGAIn8S%E-zLw_krgG<+vo+Q_9@B9# zMm=fDy_RDf!+6j)%@$^pkU_#(C=k>UO((u0W{OJ4;U;U}&?9ZIerR(*YG@fgaVT5C zrlV$Ex?MdJGt&5=x8KPpdJoJaB6(G^lX48G$MU9I5dM+(TadMnTM)HM-&6}Jy=R{* zrt9s!-@Yw*Y1@Hg)6}BXVUX2E+w<6ZJKrg6yK@#%l#3{Xk*QlizRcCLGqG%6G+kvs zN7bf(BgH$hs%Z`@2w#6Iue=30%B@ANd;vsG1t|Ia%NGW6jx!la^YelGa!7a#p zFEl>1{iQ#})O5Fxt}rv1Ud#EwRLR37Q?L2VId+)Mi))XEBJ}dJVZB}Gek8yF$G0F@ zVX=Vi^b9Jl(CW#E#znT8N^1ldG5aIBy?9F4IG|z7T;Rs6x`fJq^VcSaU6P zWZ5L#sVtX?d_EpS^2s2Fnm{@zzVhcLaRJ8|zkbD7EXgKBzsIiyw!h~C;n~EV97@W_ zd8f0%vC6c$c7LPN?JHHn_NDj%VP~~q86=%z8#k~X=Z8TDC)0NMjmyUOed@QSuI8>HfK3<_i&c3t-K@luTjQ$cJ zUG86p;dd1C#}s^Up;p#0{N2ES7p@K}g0XoqBFG)Ra}upb5RE0iWDrd@dA{7_2P;EC zzgP9(cTQheZZ61DOMeDV9E4qP-k{QE2DU_71x~|3@I?WCiOhdvzJ+>44+_L9)fsXf zFDQ|}m9-BRbA14xpqXzpINN$4{zBkcM_3DAc+pj#L`_MwnR*0b1f#YEc~cZg4rieP z=Xm>B-O1>Fa3E-f^YGm@RqP#>hTS%?pFf|;YF8*6-PJ&yc4G-{1ZT7Mcz~q&ulV2= zWTX@E3nL7!z^4v{!wibPpu|Q)$tyNT!gK2<*m)nRMdHi&x|MMvQ3sapA zG9DE|KIIT)hh~)*&g$11{c!V51*+uEw~Do8MhG9VZ1U_>i|_s6U}HhA17jwqmDl(T zKU+WlG-H^prsHqT2e>?n!|+fL&uie=XvY2wc2OmST_ zkL-CheDy}sq4r{7-dgAq)mQXPuQLhK-G*coG3k8TmX@D08$nIIW?x1dMPwD+&LX~F zZ}`|cgX9vq1yN?b`vaEMItSPN{9Ph(0Ev`bgxizg>&!innWT}D!bAeDPEm+E&CHJT35kcc7q znE@KCF_-+2Y@{TalZD`DI`PFH@mce}v+pPYoI&9OjEWN};BXegHul32t4qku6Lx=% z#{jn@d_eO?l~+8!p*2B*C~QkRZ}ozsU^^##I|mzue}&ETGL5fx>|o`vZG6E1=#msH zG+X+iL}$4v??lJ|T_E^)*5iGIXVZYqzXmeU3FsIo8T5)oG6U=nC7|>lZd7ett?bQ1 zD$Zg_Z_N(oM;7QTvvNi*-rY|zg96FO4Ted?YL_#KrL+ADr8N5EDVX7dwF{XOA{A)z z@===-6Q?HjpSv_(JQI(DZRX06(Q}9u*}o*Iw9p5pilr7j+$S1XdP}7Z|7k68@SqR#3&8A=>vf*%bKF}Hz6@Q!?7J|VlJGvDSVih@L2e;V z?uj@)f(^bW>i*G^q2IDGK5=r-5eC2@={1fhTF9LAUdt=lPFy|#*dkT@#?W)|&*7>nP{i~kQQi~pIT_=xpaMNuaLR4i2gm!e2v)BQ<3aS!*xL$?;i&)x)# zqOiAJuQ6AjcHjlhXDAo{;Maxif(U7cZ8;qFg2a1TJ5@46xRjogie><(9>#A68DX&*0VXgL}jmES+85>#* zHFyOEV+vEoI37j}T5a8&VFGsCpA=a7=|Fv>U+mKmGkfeuNyF6?Q7C)FZ1g z93ss`l30~EEVmm|Kd?7<&M?d!HPv-z$=ocYT`0iDx!}?*+P0I{opbCeCod_pLnk`` zl%ZE=xpc|_wpxddx!Jb`X{fNAM=d4qNBo6uLma`{&1yIj*O}$iFq0jRWVud{$>}4v zX+Nybhmor$aU{g|opS$knhNy5)XP~TB&=2F2Hl!HdFbe&b@8uV1FoQ~9`7T>>JUiO zk^GC=;whl^_NWPzFSpU1w4LohK97J5%RMnbY*zwpLxFO47)tU1t2Wu07yAR%{Rixz zqn5*QwcOlfV@XxuPDxJ&`-cWMR@?1D+r|?{R(&V7ZVIxAB>&us2|je|Ib~g-Bi{ls za0mJ+?PttT!#T+kv(8{*I7bQTHV6pmnfwb1b{ZemllLrCVK9Jq*aiwNw`Cwizn_@| znvwat)Mf((NG45Tk5C5yoqTay5Z&)`%9H~ zBbYBWe>7d_&X^eWt2>o%GtJF*$AF#2^pi3znd%b7k+onVh&%MY%2*s8`f8jOQN5%g z+Vd9S#tgL+%rv-8n>4rO#IEv=-5e+X9rLY*!xScv9 z@NGn1_(f+t(lt?wIe;2&CrjX^Hir&IZ5$mzwVV|q=}4|K`0U0teSSWIp@$n@{AhpR zQ5?0*lFi_dw|~tts&wUJ&%D#AYfm_@oik(X;oUTBSe%1jcagv>3$CN^v{Nq}1FNX1 zj1hcs17diA&KsWh$x5#i!#6@j}cqkw0Hgm;^wBS3Sj~NTor+9K2i?7Nh|{k z6;$pp?js877<(XAH(a+MsSIxa_@<#`3NQ}zzgVF>egqpe1-OqpV&&NPR;K|f>O>#`MEFafTj4KjX5dr+FkA11&0#U}J@~}} zcjN{&2GP9_v2sX>lgjCj`ycZ-_Eo;3EKrs5+_nZQKg~zVr{oc z<;Q`a3N(*+Of%DXLY3o*BLX=o30-OHG05R92o0$w^mHDIVc3Pam#c|5fL570*@&Yh z`n!v5t|fq5?!e$t(x0+qx^a2yZ`^QSGQ+l$X zi7m*>*ljeDu+2ZvNx|=ar4I@u3+z0_^LF|GtmE-u@D{|}2JDdbcb>YP=YdP000NT- zuib)77cOi9xE&Dh3>X>3A10~Of7|hRTre@r12c~z196;3L4E%?1}$BPQ6^vDX5t55 z(zd5ydUn(o|5+wYxM>WHvkjHMmN&^^kk1nUPxgI&KDS)Q{dPC=z6+zx7jw(_YLf-V zJx4d{ArNp`ilwoP!n*6KA_x)k~$82h|}@To2y~6=#pz zyL70m^EAmKCL5osj0;5FC+c}IW;un%`L=+%7sj7E6Yw;t1{~~_nze?Oizj1ryADB7jVt?>bi6`|po-LUQ zq@6Q>X!G6xhW88WfdYrh1j!xjma6ElLc>rx3(@%DC8E*=P)K%Kp7T|}W$puw;qC}% zb(vQ4*U#;t4MmTd0heVM;$#n?s7O!rfaRFc;7QQjRTp$3O3b#wkQK1sMN|w#`=6tr z(EGb3DIULk7cNw09f-yeC<&;$;U+*xI&W}+OM1Uc=bBL$YQM{P!duxlrLr;ODHo-0 z&Y;}s;4Gh7Vij22C70K0EyFnsgUzP$0n^sI%_`#fS;MO1)6a~G&qO?{N8*=Da2~Z{ zVcknpP=?&mj+OUyww;2_FTADYbYA9JrfjIe2Nb!8M;1{vW2R%4bE4J(81Hi*cir7^ zxP8ETsiBNFbmO_rkw@^c57{akgP67HnGL8HSHkWXe!Vk3ow9m5mINEVx|3aWz_mMCQ$AXUFX>fr=F3X_dGXLk z`q7HAxyDzYycp=~EO~cryGosVvZV|CuOrW(`#k+u;`(JLcl@7rtK*+_34h@|D6WoV z;0$z#A5ZI@n~zGJ>V7-5=_9pAD6A4WKT-O8fIG433tzaE;Ky(NZ^f-5tx&9O?rC`E z%$Y%G_pEbo^~B}UuWmC5T6EcyV-cj5+P0D&tEXwNZ!h^j+A}J2HGhzWIt%Ze>#!Lf z`}!q5^qPCNrxRIQc6?aZ>M%r|yY>*PZ#>ZI6$1<9%2j}kQ56k81DCMJZ2KlL$zNq^6 zSy$iay%(Z;YD8{*>ub7|Ql)AnIuh;rWGwdDXJJ=tZuora@VVSVg4Zbx-Q6@vRLS(tp=8mx3$kLtxkZTCLpd$NW|%OYRkJC^K#`2 zH0hb|g?}p3x7q&+=`Z$Em0(iGc^v;>M!LG4$%0PT6+3r1(|a?c+8kyoEaVH#{7mE4 z9>+I~NJH7sgAzKzb>#i{M>hq(z69D_z7BVxwmeQH^E~g_H1T^&M+Od@IbLwn=I4E8 zEQM8;96lG@DwI=<25PRQ7-4E$z1`uG&tgy<46$vZ)oM$pt}k=P+$;{kzWG^6+5#U^6Cqbbebr2+&1dJ5S1{z-unfedfENwx0<;a?s0Gl<>MXxw? z7uNx;CWJgh)?Y@?Q4h}v>)@>r?hX-eMT&>mV%51CQ&YuRXI=2>=LsjFCoM~1V-;1% zg)j9bimIfvm8r3|6;X3zp9K4ffB-=k`!-{ZBlVDwg4PTRm(`L$0eE2a@Mn{&YA}N) zR18^uvfMo~Af>cKjZw^s-JW|h_0Dxw?}Z0G;xAh{&Z-~VLnE&vG!v0)f$-Vx*hxH#o9G<8?-r{o1@z6t#)%sz5+15t|TMHRwC zWe2va&La}7dnawR3k6Pi1;I9)#n#mc`rbPh7|8cB6#jyn*v6O`X$t~$^sv;OP11IF zG99EABLWM_(-z3(L1*$QVA}1&>!=_Yjn1kH{A5KoZI(l>Wm30I{?F{D4y88lg$j}v zOsPz46W6R80P!`JVz#h3LqITlBLczYBEYUdgSa3!ASukciN|FR6PM!1TM%Fl)&cpx zvrYF7!&9B|7v0h?!NeSOO!k~mG!3L)2ZYrsxdn0XR}cstM-MZ9K~FqIuam(VL{cu{ zcQx#f8_)p7G75DWh*LXQLbtXB96qc-kAFpye|=hX2sSgeidf4AbD`Y!|A_j5phl9_ zW^^`}!Dgylgl!*YSs76f7%$bv4oO#^Nkt=9!Hj%iy~#|PKc<2o6AFaVinegf2CHWd zzo5(V%-*JTVGNvOZSsH{a`EA$<#MwnVGAO?1vv~f3Dy=wHE#-{^#o#ph#{Iof7gJ* z_Ws=_VJ-Jf!r71y)5bTyAy9Gewjh;CJWo_zEh)dV<9AoQ7f)Zc={g2nSh6q$oN-nNt3fAU>gt?kBGPAet#P2D zIEeV@g(ye#CNmEHQ-S_hP2l|{1+9)ZmrYHJzJ@(gOFMD%1&>j{`|%2N{oN`Qe{syX zU4d%B)qLUS*X1H#DC!0gy;e{rI~X;H-0JN@Owvk|NMT!$&{P5(n2pI?nDsR=^2u@s zA?oKpcn=tLFYT4Dd45MQb*||j;q0-PGiU4HUss(?OM-tJ>2gQD%_P?(%rkAk4`&cM zLGwZnVsxT9`JE|ZvJ>SPNmeiFf9?QxoXuZ~4#fMr)yoV(xLY=GiuVUW!St5vRzS*QA;Gq7(=u99S z1|3Jggvde*p0Ex~S2usG=xVyR1PK5{K< zeXR=sK1wp^g;`6Y{!M!dc;hndS<1fDDO$UIy-a($_j3W@5490a$mK4u3uO!YW;m+x zx8I)%IZJh9q9yDrFxM<1Fm5E_#6@70nIK5Fp`SoC^5P=oCKcdy2mmf(Gb#2hFFq79 zj`%@?WlMTE$NPfv`VjFgh*l|}@qC02=nI4qZ=Vs*4pi^QAKuY(c0!wb_|Fb^+c@|d zr0I}@bq({~q^y-JiZBzZzdjvPb1Ps4KX^slf?U^r;!MkP(*i~AbVK%;w2~lzD$w}| z+*Olpm|`-cEd~8Y&gI&Y{aq25Z)kkh6iBt8d|g&n6mCU6_|AY_n*h5J7bzvSkU`L& z(%%6)Qm!6!d++)kAVRg3Vs(G_o(G;i!||c3@VuL5z`>S)@w(Re1X9)%)MXLZigcN|I0~}V4OvAeL5VICbeDKRD~gYs&{B)La*SPC;BAUn1WVwbzgZMZyUeW zc2Ato>YjSG;U~+&#Pm5D}?mAtVph+@B3j9-8AHw#plOe zKDjVY&7&)!c{sCF`6s(2D_>PjiOq~V05lE`TcJ)Mlk0%GWpJr7XGZY+SLHSVNT2ri ztzaVP4;rXHgpE?a1`s}GlM3|?cI)z-V=@OI(HX_a{(Nl2DKQ9See8h9$yFSkVu0}dFLN=)*E&q<&c$$*sflWTMGy!0F zj;YKaidRbUo9C?BB^mH~=7QZ5uKrU9@59h{mTTGV*_3E@GR#+I;53X#&T z;PT49izeu|Bew6aE?BkgQ23uar{m*Yl9Bj};9Bp4H%ZYJ^54)^$T`DwLrEAhybHNH zAx#c?3ZdlF6uld21Md=SJC$7h-FvS*R1Tchq-|fD0F9OuZNgz#x$|0f8pYD2Q|hcg zCM`-{?dr$hC3&9>nRxJ8*o+mqSZra1&jtud;tf?3|U6Gvi=T zn}BYS*Yb7pBCtWqVcXfFB_;g7L)`vQ6Ude`>T-XQHhBN#Pqa~jK;0Pt>W=ev9d(<- zU?bJI5O11`pQtUyaB#dIFm8UGu9DpxRYQv7&)Gd%YF)asX>C-2Y z?+xuvl6-uEo*MFvH-&v(hd>Abqde&NkW> z!1=na_7cn&8|>8r@3S0>Obho=$4%5G(%=o&xD9m{ze>j$#@%@<@H7p!IDmyfBPnl;x z_>;W#@W%Dx_JB@Q8YasK)pDF0U8NWGfD30)V74Qy2H**MN6{-s&_Hnr0qPkr%PF1> zwE#_8E=B-jR2itC1U!E4)nm3_qe2Ew+1RDbZw2JKndgxBZwwt@eivTG~oi z4DE`{DL)RoL*bW}4y=vNMyT#Z%en1lT1Khh7KjfAkAoN=#|d(X!+6#HEl88d;sVJV zNn*&P2FmM$+m@U3mH;RL2tHP5$Fp!ckd!FAIzQl`fIE|jIv|mT^0C}Rh`OaPlIfy* z?o9+7L$Aej{KCY#R`+P$6EbrXVp1Fd6ieWodYG#I-LnA9e)DTUu?F7S|76y{Zl+u; znJmw{x+uF;f(3poPiFZL@49c*#g)+URh^9^5<2U7uoZoXAdxp3XyrhgC6fier?>;EDZn$xI5ABXF|64mdzi+y^ zIMZ4s4x}uW%p6Cwssc6pceC2*4EPUD$WB`McL&X@KSrq-B1P|O%xchA`KiN0ayLJu+f=I*F7 zo_=V4J5My0Eqpkewh~=#D(9zkhp=>-eB|qGoiDa%ZumHzF!CXk!#(?31vmQqm$AJC zgBM+RU(QqS_Tn$wxI9uIC0zaKY~z*abWK<7*;tTEa5zD+L||C<8ORm)I_Va>6dTsj zvLTFC$pn1wqwkpo0^NnLVnr=777K5J#{>W%fAqlTqE3V5Aiv0$khf&h~usr%sIPt-qcOw-=5Tr=#G zk?($G$j=p>?&WRf4T`G=-UW_SB9l66-PK!<-OhL}t++$$L5T(;;A;Z&pJi)4#P;gH zF!6hyY2MrWUaEmbo8x$-5{)OT>+dLO)3c8Mh7Zg5Xn)##&v@^8aQfl9=g8evG8NR% z4@C~339RiDXO;y7slX(hH;K?q(V6sDnm;<^dAn>|9&XY7y3Rmh0BPOI4C7LUDEf@U_Yi9 zn0>;LS$Sq>`kO|ar3uJ&GsML;bTDR#0pI~B4a5p7>KN&}$5$J;-BFq7r!kY5eUfv6 zwX!18Ci0+0dg$IOv~tGc$4|~5`I(7*ro9TrAk-lBnv?X5oH128`PoP2e0tu~43C-S zyQ_bP1N}c84rJkh7|9;*T4kWC?q#TdcPhflbn1$c<8Y|)fs02CVgkH~#p=BfC2kLm zG_1eE!O)2cQLHHw+hji6hNv{FM z>LW8`+5)>+9x{anxUkhwtm*{rV;up@&5Gk}?edOp$c zh3ZH5EF9f+wX~${o}k8<_{DdoZrUQ(I@=UCWBR2XA@e&z>E7L?3_Is}>|#w!}0C1i*1F#46!1`QGY#ax-j6R}xCttqt7#Lnw7TxYqZ{@Hp0G zY@oJgiFdR6g&$>$W^pa@VId+~Z&Oe#2CoCOA7{VdN&Y`RIoZh1>51DNF{wN3*WDnR zVDAp}uKU7{KYXE8|IJl@cGwxe3}9{4Mzs6_kT=| zGP$xanXVwW1vTT*3^W`rUqRIX6x0BTHA%ZGI##kX=OwwdE|=$*5JX@2!9Q@XHk*Rmc89MAnv<8KO2aeR-xN|!JvBUm zU0^fyyjb6BTZq)H{OZKk-rW4{MAGzdC-OQwJM;PaNZx`s`WI{jLz}+%IQn{FSr?HZ zg~o0QSG)}?i+OH(NUa~ZFd01?b6Tagy`J0LaN%Cy`|HU(_bC%YS^K(~N01=t7$3}lJfOSA{9<`B1~Sw8FfA4aIrwo1+NcAF{dwSj!wkmeHc6&Bod|H zJwniJL7s2cJ3e?(>X&F;Xv;_TDJDkx{b97$JX2HH-_cqQQ~&p(wSI+2OOafNhN{S4 z0|A9|D&Ixa_spjox<|4zzrG`LZdhILyKlcj$6BE{rg(7D>uzEgch?eqz?nz%5jqOL zIQMPI2eY9YYk-lxw}({&^d|=~(YpZh`_sUEk&vm(ygzOb+<;!<^$a6_C_!%WXUF4( zK@MI)4SIDRu_Bd$$J7?s$T+!!PTYaFQN<>DD_O3yVQ^u(! zA5KueMJARXIBiGWH~E7ee>fy_iny(!@pAQ0k)WbnWPv%cy=Dt?Y6;QGzXr_b?eq4R zbr60I?6#~1vTxq^1Y(`V)SV5s8^O{PFUwl=>e$pR+DvD=eIy%*@0x(moBWh&O2Y6g zu>15Qi3D>{`a%LZtWM-NfGy8?fI1oNh(L(j*B>;{`FG~8AvHFV#i%5>Xg6E8)#(yb zFIwkxU^>5QXpAIrEX+r4+_*@j1o6ON+ddX0Zpk0DprZ&s z>yF36>)3>OQWM}+&Urd)OVE)`L(M<^QEo|!R1|yI@X7ow2ojDa?s-BKPH<)c&Y@~c zPEz~=^qLFceoM9_2XF^ex~^F(#p*#9V?fK+A`F>YlgvWZ@yG8WRe&-dn;}-0oxg`< zmzykGvfy7f71r+RT_7upZuT|8#$FQsThsaBDuR@o4YpbIfHR4{Tg$>4l%=sR9^@#n zPbt4l?YidCFsRu1+4J3qbZ{Y^^O@E0LUr2f&z@o_fW_?5~fPs zhl{GSwC+~8JC1gQ{-s33NKF;X6Pc)E(VC|YO(#3ICZ9}t_YjpT&y<4a99|9nMpQ^2 z;LC%=Vzq4T$F?9|YY_@8*VM0BO0PaLfZ=(@VB>H@GV3NfT5)9B*zXc5j5Oyws-sE< zaF2lOx^1E-Y)Ets<(DLauk>^`U8~`L=-gk|FC6p!92tAf_3InS1rycE%8Z8~9?Gce z$n|@jy3FUZG8rL|TacC42ufObgHwHslgh%_yc-vG-tc%L@4SZc5NnFYR%1qkAm?Y58P0d=t~F z%%bR6Wy~+qv%KfrNm!z{Xk~XO@geS-V|Xgrv?PP@lxi4V#Nt5Sr>0<)#0E8cLoPC1 zGjw;R9mtdsb{A4?xM{oDPX027(iwsmAnfT~)JMf{Jk5tzT|ReG?uB7I`IDbeXYPCv zl)gvV2}k2y*`rJ8r`RrSPs?Y*CvgNoh zW=Cv6CW&H-If-{?>MXyRM9k3rtk@!j@Wb@OW(_CRu??n_wuPC^b9XFyw(ln+Q>&&( zFf9=D#p+G5wjc|}P;w2$hG-2e0U=-CD=KYYTdHN=HMB6{LW1GGQMOAfTTQ?Q~ zc!8e#j-XQv!~YOvAiag-a2S#$OfEN8s@6AeBxkPs6PUCn%>KyIz-Kp#rN2dxsAicCV*rfWZTKA|Y4Wh_(ZsT2$pK|c6VZ;jIt10oR=%AIxAgs9s=xFp4V|J=c%24asQhrp{C<&Fgo`9o4t zJlSX#n6+uGBBlZ-2PavL+POezwyeYYRShrcOW<<{tiL3v#I#^Z~S_^}jxq z?Lh?xZr~&~>ydYhJ*1f%=-2F>*5*W%MLUn# zjfv#6dpQh8u|EHxloW@B?Vn5%F22`i68Nq6qF_lZdwOxwzVlBpEMMMgaO9%5d*J!sZ^==UK8UV8n{+ar*Vl3Atrqnmsc9~IMPGR%$)iMZw(RebJ@nP#_xcp z7{p4zkqfvC^lcqr7peDsKjTW7h($r*r2EB%QZ;}@ZteycNdSx#2zA2gkamIS%lAlf z^><$zh(GGxGh-eHWRs%HH^hSotGkB*?3Gu&+8L|8N=JK7!2csoW4}mHNQsRJK z!(oR3i)wwSr4%nocqym-Opx>W^umr+SjyXd)fo)fNzB!OZc~Ze4OkiSu5une0*f`h z(SCh^iIyZ7QA!>&=tfmsaudBE6}J~^lOQ+;n}x0ktDlc+ttwC8^!Ze*aK_cdk1{Fn za;lygs7x5bMNF@M^k!D{i8j&`YNSNuj27*T@Vv?1KOasahu=u{KgRSfj z-h%8x5I~8WTzbZ9s0v*Gv)5+vAeWcHX)%Ni%Pky=WHh2_ALjjd1ZKYu#82w)q@x4` z^VbLggpK%OU2NS;v>t3h()$q~TYV=;p;La_sYj49r|kc*_vP_Ww(Z|jDs3o5p-hrg zk``OG(IQDmma$7@jUjuMX+^|@P!!!H$}))|>trWe)(Ii&*ct1X&3kH{(S6r*|DN}s z_x=3-xIf)yuDP!3JkR4i&SUu=-{Uy?Up*3>a`X4f5>iZ+?}XZe#I4d08Kgrl=kH}K zdX%Go;xFJrE$H_8WP|JDboKQT&Z|D!jM5f>0kJV_qt>FH9^1KoMB{AAnNUf%>7Z zN$@|++_bF`8D!Ag_4uR=cHJ|7M^-cL_;SY4%L^mB6SEk@WA@PxdMO3H1IMTv5G7fi zf=8^#8E+Ly&Y7?V4-f>o1{Q;{)bqa|31XYE+Y_S84A^-*@R$rd(Rb;rrXR<0o~M7c zCfassUOlMMs82)oH~W+pAtJERm^q;=`g8Hany~*b&%9pPmYFeQ4Pw;f`1`imnK8K$ zvK|*cV5Q0aTgTORU0bWfD>-2J@e}{itq0y69n)>^a1-j`M0Mv&U(79Na2}Cv{^XUcs^oUiC9a%DaT;wFL@tGz zUl2|71_6wS7{t6#&9eGppw44q^NLf?HWPfy%Ua5Bb_Zyr>1&eB%%F$UYFkD%9VYak z>EbVuP+z;Nq96IPAE*eu5$%y++B}`LsyDbU-#I2@^eTf?VSC8Xg z)_fUn<;kM0Fsnt#C1B$jb}*)fsQW1UiW^1p)TvQcfd|-S9xX!p@zh{isS*8Ta-bQV zxaA5Xj^WW?U`8xnJ%I@{feSzf#sGT)==616Zcp50oX_=3)$$rD z{q|>2_)FNNKPWO@o9=*#Ex;qoF%VorI2w6OfFn_vLHq5O5eA_&*Pj#*D{2^2&L5sB z6jhJNQx%i7;WpS4b+?YBrq=Nlzha4;+S&qull`!niyu}nJn~Np_t*JzPf3}-hwa{v zP$G(!;vJ^dUQ19UYy|G}yl)7yC2*%NudFkE-#C9MiPM4)#}76ciV zpg7>upClC!hJzNxa5{a#H~oJ0qO9jT1!-;d>l(V3K#pzKX+zkLsi6!Kqt2MB1IQwV zr~Jus1t7-)!tnsLj`$*2V@et=v~~Z3f&`=1Ev>XFMg$Z$+hnB zT#6KvfI+`Rk?@SQ?K=yA+HcYmsS&^V@)?`@j~e@WV9Q9PB5^v%nTt4OgBH{xgfHKb zmIIOrvEcx~^o7?Usu|XIsUFt(7NGC68W`%t6PccWzZcWr(McsEIFJ?Di6F1XNz+P4 zfRPXYgT(tAd%yoGa2=XoY4REEeBHQ+*fi`K6~22pl`y(D4ua6LZeN@MekQ9|1lnLYi= zBW^>loN@~a)b%SDM51dCiEzJvlD_`A*NJ7>-Z-qBN*K^e9AS>#VkT@Y@YBV4jNrv@VHe*M^(6l6SZw)^!@&QBB?&mV zgo$nBBuY{VjFDHQ>!*w!7uj+EQ(|4b>&05xwUy|*F!OnnUXO~x1--&b-X6;|%E)*Z zJF>jVcpRx=yq;DU9DwlCdnga>&^`ZF)?2q{2M$j;jqN_Qky!H!MaAa8UVF5VQgiTL9D$m>Py-@FyB$88J;ZJ&j1ym*u2~)`tO* z1s%|y4vAsIKuMEovpfL!h0B41LG>^3IMBo0f08UQav_1s=wTk;Me!#o%@UsgJ%z~M ziz1v6?BFuX$d&Xn%ErsF3>cJ+k%#>q71t+Vurw*s25FirWjb}@?`oN!IjJOh=|nj% zW>WFCjE2?cF0PTb{)&y4eTFWhXxGm*Br1?BLI+ofkpz3xh@=2&-LTD61R(Ty&Vvar3tM}$FsbfAv*blUulj&?54G*eFa=WW4Csds`GIgyEvsL?h$o1 z`b^nT{Di&i$OlibUw_j3yRnUq^yqs4JKx<~Kgo(|bmEDLpY%;5ukEZJxYsHkVgmsw z8TWOyJ5`?b-cY9sjUPRK@uko6377f>7)O6Y9IE6@i+Th_;YAHYKd%)OED58eIUBmBZ7r6(}v36j-0235feE(rz_34QGksW?$kDN@+eZ z%EcD$^xCR!h!5glUOHpAW%(!aJ9mEPOkw21$zDd!^i87Z<$CGlV~~3~;x2Le!2085 z7TOZ9YPBQSDis~TAUASE4q5@;8-~B>bY%-j2J_{!(Q;~lu8ah_62nkJ_mz$WcW)8W zY}GXjxYq%t*wRVH@WE2G?>8zg2H27TBQ4n1K{9e6H~fR6{M}(*`j?US3yxq!{%l>* z{#~7P8#5Hu+Ji)hI+Pr@0QaRa5`-0XQBNbsQT_6~P(rVKvy4i&&{M%P0d;u~PFC{v ztF&KPMX8qG&LtDwJT*UB=`I|BLYw)m)K?8woj4^5Q#(hFD2XA=ZX?Gu;fi4CIikF> zSjGOh*AI7GzZZ+HbtD}){(|>SN3K`bBz}wn^>^&1*l{bL4h3P)3?%6sOmT#sm%Sx_ znY*-|BA?Fa3u!uG7uEnU+IC<_Y=$Q;fpAyw{L+46FzT0&AcKS7DZG}E&NVOByWkdG&0OQN>z*mcZ8Y*ow%TD|wPg#YwdxH@q^imz-m|;A@pBi1a)Edg+3PW4C~*Nd z!I#%KF1C(+Yp4pRc$(4B z6sK&~cIEL&T>ZN@>GiwvPw*i zIr_=$v!a#2*wc6Sg0@_(=h%G|GknUhp5jgrJR!%C@2k~F5o76Z?(awr5Z(MqH2|?X zJ9wQ2KYtbfzCF(r4z8Km!_=Cz%q_^N`nWec(@hv}W5u&QSYE*1@!i#+>+nZzRf^4~ znGJb0=I*Y;E(eYVvn13SKQg)gfjJq_Q_Ss60hL0zC~}VoZ7*t6MW1%t6$*%nC@NpF zi`08b$PaeCG-ALa#{qC6FFA%`K7~~C73rv+e8y#@z%#Eq8|i&wIf&Ac;3;x ze|Mq%#<@^=-Y!6g@G&xrx@H_U;fEzg!qUVLB$iLeuFXh-=odbX-@Gt4J^ijtO-3M( zmQ+jT8jR#_oog-%b>k7#$f19ALts@5$4nizjF~V%4!%;OpB=}@7lE$=JrtPro`m3b zj0T{9)s!pG8~oqAzsldjpH}w-ZqwrBZCcloaEZ@OTw#bdc2$2cCo33AQ5}~Xq^-?| zbv$ED1zaEWbA`NY-8I7lyt4vOuGO=oII_|7?+>M)Wr)l%TGB;eu#;n`tN<&7V6kj_ ziBd1aNS4mlO)7u{{k+X{T1hi@Py#rfo(dp8@s(kM{wB+27AM*@C0Py*K(-|S5`$zp z+QwO9CnL(R?Hc$|k=hC@9;A@cztUy==8nIYR^DZRr>QP39b-MKvyCI6F*AOLb9Yx# zduA4Fs%U%^<=aK-n3RER2Z!suM_P;0xOikY-Z`{c4J-IstTd>4zsYC3wzgtYnAzL= zwhHI&=p#t99NvXwVtCd0Te_Z2ntq(_hPTRYI18WvU!XyY_kO?urk6`ZbSuOSODNt$ z^cg6yM@#IxdH{9CJAY*~i}nX^PRbb~x_=nCS>#3i%mvqCbI6vn((F%G1H@4wLIE;R z5IhM$a=Ru|pG3la(a+N`sxIYQPdUt9h9C5*+*{yv&U7TJ`3x zg>^I8%MU9t7ZcK$YY{_{Bd&`hUhi`YC_9EMI)$z{l@WTSJCLen9AQEon0u#3TJswb zAnjl^R%Bs4cjOI)YOK+F>?(dsP|}#gu>mh>fmY#=88&A6BBp7?I?J{sH<#)_YiAz) zz+j{sSU^C~K(9=4*$yrdB{Av@MTScNuzxu(y4DcP;tU`T2t zWF}H5l2H=t8FbWF)|=n#1PCM6$rf$dmY7>VoucaKc4SJSe7x)5D~YHS}>>?DW@e-|CxoSH?+R}KXehd+`%OXZz!HKW*1}eD2Wyf=^1F* zc?PfAm=ZEzc{wvc)zNm3|LYt!*>QI5X|>u{>Y9OhH#}@P2Cys$vDH~PPvMsx%1DX3 z7>UM)0rReduVprM>MsPjyPmbXDDF}v&1b$RP3%3zx=}_^Ec|hj9?_>)wec#(Yb`aX z#xvq=@T{_viG#!2^pomo{kzV`6x2RXfq2Ao6cgKvBV+u1LZ6>u|dB^ z_RXoi73w|3HyRfdCabbJ9`qgID04%oHHwP(I}Y-$3vN`(YUs1otH0tdoPyTVVF@a| zT($MhNjvV-=Q)jqpIp0h!^3cy$!Y4~h_KpVVEF!Z$)iu>g_>rc&7!4nPuy_E9|p1- zJX6ke%vpyY{20c%t%gaEIYD&AP=+>)vPX}Zx+(=bF@+3-P6k^-XV^0VN|K^ipe?fqtT%Su-+8VbfKsnU$LK+-34#Eu$IR3pyJ!pCfQa z*(QE6YA-spE66auSy%bSxd&?MA6m+=Jv&zo>iKbprR{A)EL@HGBsWV^;I4nkAvs!C zoTj5&pE#tcms0D?7<9-E6e$6HUu;)2rC^(Yau*II$919^=dvZ?_#fw&du%yhvo2!O zAded5dpvQxH{aIbBejdkX^#8T8d|FUiz*Lg#_O$bVV6^eK^gN?Kf01f-Vz#$)FflJuE z`vYuH00b_Pp%hC1=nRkthF4e?m8M2`ww}TLyp=&%a~lj=`&n0;_($=68FTFL1pQJv8VL~A+^V-~cjhr&B1*tWAxIyXJ^rK% z{xEgQ^q8)lhM<5)NWYe#wA9au>ACTW zm-_6NB53-cwlp8&tVze*{hh&EE1!&LjUh`{krjD7KaGymx=c4p&I5c=3`GEI-cV3K z2VGdNGuk=;3_MBG<74+{{wCoH=(x&hPheBRPy*NpjlML6ua((7KuQzXC;^HTZP-jV zNK)B=>i(ttDzck@5pvfQNsXIRSFR9XU9Xeik;_<` ze?|qa^gxN{XpP$*&m9~c8zA8Z_F{6$pa9=n!hH(A^H|;ty1DL0l=U&M;ACocJTYlh zDkbh6DX>^nC`_P1Y3-^@(U=7UwBcbkx1sSM@`RhT(Izd;NR{|$%)~rzKUvl~BH?WF zjG<)lK=MobA^@Rsx^a88+prY8AvlHuX)?m+U5ZMVa~#0)@WgwjkwHOtg}xy$lHIT~ zQY4ZtH)M*qb$!97e*c0F5ckwRCv$*s9k3M zM^K%Pw-WqY0qW%rntZMtdby+TJ~E|D9HWsQ9G`JZkzB*Q1(?_VBcLAcNAzpPsox#Y zUupE%6o+$8A%ksbLQs-Dc$W-hDLBPcp$nWjdO|I7R|j}#TXrVUWTcRddU%Q;m}?}3 zKb%LdIIC)VT~zdoze~gdikxrvKoOIXL&d;h$9*A?_`cS0-=BtAVllAkMiG?@%AM0k zCCP^6#uDg9Hekfx7%}#J$(YBp3MiO&+0$AZb8`#ZOwc{ULylixOnuug3%8-v|-Fi!PW6kaDPAfhr1>pjll@r zjkHJ{tQ$rI_Dc7T*R69q3v|jnKh25_)+{#=Are3K2c6>E$Mka-FzjH!B8V(9oRdz8 zF)42wms-g8ECz<%x1-AHS9r*ed;WtW1e{k(Ta2ux*FLucfb?S|XznRM56~4nXF&dR zlV#cz=oGNU1f+cAigQONEvR-<`A*pHn)g@W$M?7YCmk~Y6zH8?fWJ2;5<2FTkoeRi z`9ckhOstR}vd(aB16H2zTl&0;ra31_XS%zI{-t*cRL}9AVLwKX~*P_!U$B``|kO!xaW*j+5d7P0VnDg0Rm9^ zxgE9!y)|{6fY0N{$+nD^3j19Z|HBLbj~%Rw@0`l`#B0-vP}m4E$L62#gh$WDK6W{G z6Su3|=gf%;84|bGR)_|F;O-MU&TZay1M-gPqsHK~mCNc@GgAf2p`euyK$L#%*>x+L+ohPoe{{DP4IC<%qgtC|Y{VlN&MN`}k@KlB05E^t`|4SK)M5AHx z79ny=)tq`$!^05xm6NQh^$I;FZ&lkfU$hCrQA}P8wp{C|lCeLrwyJJ_Tfj`6#?bI} z^E_maNLiqWd{{=}iY8}mY121Z$J_AF!hGzJt&ptO%wq2?q0F9F2z#fXn<)m_9?}BR z&l1EPr&*to!c-jIrX66jGwitpXE*=7lZn*f z>GF#np_LPcr8c)JLL$-r5rAQ3^&l4hvM!R~6tB{4ziCc0dX5-R+wbjP)da9PB&Ob# z00F~l115D!xD}bxMdDg&&cYDD`<5XBr)O{+i0P+lW6820+D(Va4&%?pYVmFp z%LyCCeo&FERuT<7pw%k;dSMpJFm^35!{6YaK#-1xc9%%UxPj;JTy zd`@cXa`CMq%o$5@W$qTX@}QE?)lte|B1Ws!W^_Psi?V@QKL*F9J54Oi2GEGclZgit z{M!{Vk>+gy8{H)Z6PYlU<-1k5tGM33t&nS;=rAfTo60pv`sc;j?-$!<_Y|N7VoMvz z0W^+UqM~YJolnM;?PbCD(02t1Z8>wlbd(aKdxJQ#gerjA>R>1C0qW<8h9kkvd%BS~k@yfY{K|5;#8o=!Q>2qh4i|q&{6Ejq zKBmBoMlealbF(YvbkgQ5VK=>u+j5NQAJ5IubnSPuz&NCVgfDkiwqf!@wwgxr z051-5l|Q&4 zFs0?oh(5Rer;7`!GOXI%0#r+rjR}C^7RV+j(s9vZ#610vCp?JY{WJl^Y7}g=wPFjcKEdLK9`(26##W2`Y= zRx&LSnfH56t**)48hq-81YdWr=OJRNzBL}SR0$wJ)hEr`oL>ZYlb;$XCv`||cwBoa z9g|g%8`MPA=~t z@>YKll8B<#Qxcg%e%z}K6k1!wpsAMjb-)jY&W-T->9kamc z+(nv2QdcM8B@eh33ACn<7X%P0Hb+)GrJi>-I)XNs-DMCj{T-<@#uZ-Ssm% zax+Bea&`wl?WB}185qYW#fF*?k%D#g{`OJGmV}ebn5&6Xp;NGZ}Z?ATY( zG~HixSRY16jtxUQweNP^&%Thrj!OpN6<#v!E%48uMbaB`)9XCpJ!6gr%^7v8baZ83 z+&$2)=8BZ@OYd;E5h`4N`u@q-oHdU^G4uNZ{Xy22BosPn0SG*W>f7c#P9=2dsfopp z#YsLWbhInobKx^fg_~Q~h5~Wzw(NKP-n%J^O`crhPpzK2dE?F;@}HxdTyG4Y4 zv{DMU72pf2&$#j-yZF%Oqil)jmVgx5agonC???SE-R>+nKqSN&TN@pjoM^oiqUmD! zvF!O6b$C|t-AE@^w)Z}!DfZQ@+VmTk)ntrJ;6~-*jFf%DWWCXuiB^<>tzuz_ZuKp( zhNsWiV)C{x+=zZuM)BrCd$*+8j*ALkII-(mc%#M6f-`7eta-pl#f0;Sz++nNhcjie z<>oy^;j9<-N21@N(SHH=pB3QzjOu`Z$X@>>5afK=DVBo!< z?p7x&G}tXVY}Gz1w>xDU_kKA5e)RU=ml}HGe|vF$>&;20Yi#IG>HoeL=Yh^n{h>L~ zcC7R=ipTF_dFaieTWW$0dBtT$LLbJ3Gvc;3K!r5ZT&meo56{QtIO3jxd!&+?)Mi|dph)_up(EFOqL#t2vy6`TEnHd zcP~@Oqc5ad;(->Ejq;gq!&=UcRb1i=^Ks3xf6hGv;{|Ffut$WvrV}|Bo@((~?3%NYj1q z7?}{@#E-U2-W$3e$3-pany#b1|Am}dfW%Ch52aDS3oMa=uk*eM=uto-8M_6vbN?E6 z`_m;$?9`ltBHd#rw5^VsAQns{63Ag`h@LUXiS5&U70Hxj``lQPsW|nn z9KsSzi%2R-bprU-ZljHF6n5e3PZ+6VJVQUXK znVO+|s~ryzb5aZT+FkTAo{gQ7X)l!%{t$CsK7Hu~=RXG%`h1xP$iP80!CMgJ z8vu;sOZ8d}_8=|rFW2txM4Q*PTZD5^sk>dw>Ujl-Vuf#6!l3~Y6~>!`a^9bOWd9Sf zkud4$SnC$0Wh(mUh`#Ck7MCtsDG2>*L#IToyJp|xK(GRkng2<~LFV&Mm#~TB^7Q`_ z>kK;G;F)zJ<`b~GWV)6s70@u9J{tFLwTk%&@1YO+XA9J29v=qxKe(4R1gdm%uQRsM z{QI((ZxvZ97V8;fcHb=3FEPFUx$iSJ_dSgKy9%tmXyM#I0r%Jkc8Uj|^M0OGxE^M2 zKh#4&?Cr`Z(zzLwuQro<&}>I?@W>VCt;e5JfIDLzVb+WpOW;X~WgZ%UfBXOr2WH?) zp)J5^z+0e1REbyUhWg9xntYu-tu1twUwmr;xA>0hH#+i1M$TgU)}<)_VVj1EeDMS(%SoMG2g|nKl!feKLN(+BN&|Oi5%S5n z-^dO-+`9;IK+bG73QjZRN<)e7v1Yg?e3gqaqXN!=bwuanFCl$_~mWDEq z4er9py!(ZFEFU}6+CMT4IKP2?xt4~i-a*7+{R7VcH9(@A1M%IKlAZw zV8t+(+J$$UD*%oFxpfzT_j#m|ugPDZMx;3ULd289L)!PeIko9xc&Xiso97+V>v=j=gL)+728iZ3SIH#w+;?^&MVaU zDp_1y8@Fwn%N(Ipwp~bN_bzx?@X7ryJJQxeR?R?IA3}`EU4_%jO^+5HFT-8wWR{_1 zbM*#c26&IXAso=RGV)H?__+Dt$(}B|mT6x>{PA8Hc=B?FU@I?Qz<#q8Bo$U*$x?E~ zfTw8v34ns`qCWjf0|4C$Ht0n*${OG@43gOZZ_a*Z8WVEP8JIOt3EBtooKfSAh)xn| ze>Z!3Kj+RnF^5f`mgProfNpi)+^gxk#0?5`iudo+^yCqdEy$~SYnr-+gVL3G-u|Q$@zj*?Z0MWEpIKoZAu z5xK427I=K1Sk0+-SWb(kR$Q zo+Q8A!{oi?T5xf28(@M6)gte`L*xmlJ=V4T9A;9eB**7vx7y~xZ9y+s4wO)ztS-K+ zzTY#N(#x?h4i9kitbM_eFW{1|hwbyOFX3`>c+9e~=t#!1hx!FWa>liFl?HPl&a#Q> z)6RWIXR48=idXr~ zFBId0w@$V)_wUVT?(Rgprw;M*HjAy~9`M-Lb_N2et`AXVW=iq0-Du#QHY(K$3mf%z zxL;-Mr8aW?TBrInR+u)X+CD0`AGn3jp+pt{;=oBfZzqP5PZD4lKDdiul=oXfSh-QC zf%zkcl*(~4v|V~etY<2x#9g&hM?0%Zy4qdkt?kD@Uh}S_O^}_Ux4a=7pX|S>qPj^Y z?dBZP5j61(@0#Mx1tA=u$FIZ{{p_Kob;@G6q6`5&Ey3^t0PaR7P$TiNna5deet*Rc z8C)@^k)XJ%zO$qv$q;be&UYf)QzICD)$mI@tw=gybz+e6FXk}AuR(v;R<{^{D=14? z3$q0En{l($Hb5c>W@cIaA=Ctrcdgz9s@M>;TGVS|0`1lVQ_hXqfmN+LW$uKa1S%xAEzxx$>!0`32w{v^C|H?T*|0BlnEVa~On73cFLzMNL(Gumvil%Ns0HGSB z!koIsa7qkIJjfV0`}6cH8wZxX)$NHw!gy0RY^deqB1CZlOZ^pBMZXY=3={PQC|N+S z*BF-YORu9m!z(=w-R%u+Pxjav$hq zU!7D87Nq1N-vIILOn3en@foq2_{K8TQ~lY;;YRuR&EsQnkHgkg${Q-Rsc8**_(QsB zyd&K3n4UV08uyLd7WX_Aved$LIXFKTTiGPA9SmV|Pj82X-JiG^e{F4w$bHz<-ctao z^b};NRa?S3m18ZlI5WeKebleCy+lw#Y&m_G&u#4yQR_3C%H%(uS>JnKE2)Y{_{?V8 zME!EdwQhau4lo-MBtyiD&FmB}yua=P36g)tY6@Z%S(6w{OqdzzMaoOHIa{gsyORV; z`nf7Pf$3`*oFo(Erm1nG2BYVDS4KFweb~`0x6IX{b7WrKeZ$VTCRV0bb&h9cb@TcNt9?og?CKLh=-wody#3SP#-|8FP&=@-p` zbeUWZ4jvGWFzPS}irIScL?YMLBRsFq_Ss*D^B&ky!{1o-YHGjI0+g9n7wFkGo@8r! z^j)2GvTmqbQH5lgVv3jZ&X{|w0m-&ae?jyrV`jXu{Kzb0F(Qvr<|MM5MXfmJ!tUy} zunT=@>npc*cs%%I(NKU1pvgz#sMjmO=_BTeVm?uXdJ|4~7)*lS!|=n|37gvN??l9% z?F|9%Xn-Uf2^bflyq*I)PtnGr$9PO=li0o!Q)k#($+n2OVX;LB97+xVxAGsNFH4_! zNQ1=;d&(lZMHCk}f49v6I@fZ5yS!9djiRy(cw2J7!f~YidZ1lD_Dcaf%fC2De$@s4 zkDOkA*7lKY;EV*VAScBnmoU9C>0~U~xq(V=KPsy&aL=-l=58Cq|;8 zt4cs&Nw^+r4BS7&$h)rnI&$d*X2=Y$VEEB;gY?g5ZzlRm4{|JJ(@s@(&(<^=s&W2H zCvy5z5cIn|bsb7|jsid%F(=^K|NanMJ`93z#Jv(d?=jUaw5PVH8E^6;q-zOK4F)%y zG4b88g8X+f)n3|SB*?onU-)IwndaV6B8_jUpE~_0P|FZ^zuOxi1Wflj&QZy_ZgJ$j z^HR_ExP!LiS!6+K&e+I5cUq}-%Po1??X{~@aYbIiTL;7y>l93?odJ9B?b|nR=(exg zV_oa5CAy-q-bevK5K?c-+yA+px=lFMPQj(QgxE`yok5Z}=m08?dikB0Z{>YEVo=DwGlXr_+X&c< zGF)sDPE)e*MUH#|m)RPM{N_t}-nbt;4{;!ffdJNGD#(=%#xJ$LVT?6@rCX7Bg{&xy zMdmvI&`HwsRD>qTdfq<02)W)11ndH{(zn~KVfM%N88jhB0+0tnusdK)UelrQTGo?k14?UY+dqKbbq-CR;rHFDde7t9 zVkrD_tFvs8dJi9}?c>b4KhKZo;?HKb9M-=j1TXAbamZO{mS9oZo}O%Ndn?l;ebuEM zcRep1W+rZ3wS)TEX21q7CRADfuKe+AM5_@xX-cuvMAFEIHL_%&v0qJ#gHToPWZW4Z zeZEIH)my+55jK`5#^dHuGH8FhUY@$ueHbnaQ3Jfm|z zG(R9C>nNom*WGVjodR#w&5_U=k3EM=5$q>c9&{*M`6_XR<`<&>RCnx8x+<3|3p@5J zw`+OMN*6>2{MC<_(S>hT8~*4J(nb!wcQ87TT!x;JeN=!l@wFF|5#J0cb>fWJV`Bhtf0 zq|{?aCXs_#OW?s}F~={`rA^K+ixA4ie^>h0Fi}8Pxon?dLRu?P_W z<#V(u0+b432vfSSvM)I&`VUa_mwqo{y6XH$ZhKdy`%CI8KH&n53eCESHOHA{;BVT8 zymwFWmt~1Qe|C7ln^sc$3K%I z$M%ODnlYnI@=w2fsBvhEC8eHFnO9Fcx^Qdov0hJUn}U4yJHM&8+wX6W+l+pk8FL%V zDKs?xVgorHU*PF1aHqx=x1V@st^Ik=>$*cwCg~g6M)?jwvqLe=1-qc!L=l6`e5)(X zqU2+9j}13(u8uW~U&&i&@2yV6;j>wEE>tI(Jf966Fcx#cLf=sn0w!mV=<@RHTsyS7 z>JUk6>s-59=}tW>5g)LmSJfa;W*KPh{NRavsw!-oIRDU>k8;_^CW?>99e3@$C6P0>QTv0L|!R=kE#y zt`JeQ+sK83F};d&#vs2x2t4o*@X}v$Z495(4CYw)sV1bXNVyaMSR{`+k}>mtSKmbc z#D6=A7TkFP8>k_;L2JX0PCCw+%_6T4A?ZZ#S7)C79Yv8phx0W9`SWjsPi+={NWgXs zZ8rezvAwHfy40?NvZ4fVD&#cM@_^^?q2UJGfAjY3@J5-FV!$M_*;6IX)*6cHkjQt6 zY4zp@)^-<785Cy!!W#LXKQ0@~J`~Nj*@}z-D3%0$uw$LOX8*<<`kinBclx&vtjRNc z;daN(WhN8z7WnVgw~4;X2C%GD>OY-)-JG(=J$%nQLsR*8 z1u(dCg*Lx^Vd1c>5Wy3_eKI=BwsKpi3DU|3Ysl%pL-;Kmnj)~S?&mUErz zF4&H=`7=pKVgJ+htEJnST}^bjby-r<_g4t>t@0MrFu)0$-%vWP?-uLH9Q=-1R;qXB zfz+q&eQG7$>hz#xO#G_}V9cW^0ZHnQsoyCVlOfn<)?Wr9K+Qt<07C)U7R%;`;ZH~DfP>h-w z?mWHsQ{2fCyHHp6Gg;TT!Sbm6sNI*Pg$uBf9yeC~{+?T|x0zBo0-v;9uG zg_X1$J{sGQ!t`M6gpM504=51JO})Lq-J$jtdjif?V16I3a=;7=(D$;WGk%P_X zADnF$R$*#~<{D41%tzln)pvh>yI8%3p=;d!@wJH$4>gJ>Xq8IN!(`=-4P_N@5t@Ai zTYBf=*Ay}Q6~W%MiQ9Qg4$qTtP0>3E!dSmNrbMEDnYh1n(s5n(^L7x#sV6&JX3;T7 zt9|J&EJH2EYmW9(`!%RS$L3sfL&-eloIwkxOnCMQ{$(tYfUohki0J8rN<3XVChP5z z50GT@p7=vLwLJ0nqvl@@jquv(d#lonESj`KL|Y!5>(CPwgpM;|KyGcy? z4kpuo-+U$iYORjDT!KvxgwXY38w^z^)Nft}@ErSExhJ?b^~CH2L~6|A z1(ySN@|FFgW7jU{XQD_!yHo?hAyxDn7qmUHza`k;%tLI|RNyrBeq=ZzC zZ|Nu%d@4jq*gsX~zioA2$GGO5HLEs1@VLMXLV)XMm3q^NVksk1o+O3j0uJ>6M^S zxp?Wc^VA6e!aR#BT#jdQY`{n6h^s9NUA3*t@T479ZFw1jmyAF}>~Eke@s6R&sJh}g2o0ym7_V4{LnH6)O4>wAL? z{E|kc{{TvNOX&`=}a-mZnsc?y7SzP*mh-dy9!0W4tM?k>_ijKp(+S@(BObTp=W zg?jocmtHo?3fSbTn3S6-m+qNVl7Yn>Kc5;(7AZl_@GL?q%>X}&C~|>iBxbe+O5KWS z_`obie~abAV|W_@8uOl_c43)$Z)D~ECXJ4)5Z|$Suc;=(tUKpkNIM?TTg)zL9mo+T+)^{SzgQoZ^6LdM?HO3xM@(= z@$N2Y&s9OSJQnxkK@N%=^YJco%G%Uz8iP}++e>=Q7C2(F5T_$tI`1LR;ZG#F&E`Q9 ztd9*x^G&Uah!EJV>{dPP2~v>Ry(15puL;%7*ly@aD65!uv~Od(dj&Sa1@X8ur`2Z0 zJiKLC!L@6nH?vjQcyB3elK|~gOUQtNnPX1JPBy_+EcoMP^6J#iW5()`t&la4F(b{R zqpD)lrqF}1Fj-?_jGDrU?-IOQ2QnkMODZZx?(Xt zXzfpxC~=LesDpQq?v<6ix1Ws)rPD7IV8<9ryl{8lJ`HW zCQzT2tp{SEGm!t{-P`6K_iT2J!|T-|*1+n4Z-`yyS~0|^{^Y4KY~FO|z+)w+mRQ*; zrUZINE2)hWOFaDa?J9q=k%F4qFC`ZA|1LHzk6`s-79l%{(na%DCg|b0Iaf94)Ba=T z3ch>XlLJE1R<1pIcpJ;O6^ibc=!9_M$+Hsrd-rL*G} z>)KR=F`?^ro`_30Hw}%ja3U;pYKWWZTvLp!$QIhP>oz~+HuK&aQf)%fSb~L*Xbr0f zdzW=)y%l@|&nd@&m;NT=GU)v`cc0pO=3TaMaMtle3al5(;ub&7_hBNW$3xb~ZM&#O z$)4KcJx5muGucWj?_;@r|1${wF%tX!8-ubP1a5jeMdslPaKB}KWdUQ{n7IU*;Z@)% z5^uPu4QmWEwm$ z!N2?5Oz3=E&S-Wcp5(nI%RhK^AmWpYJ!k*_Ci1R z4nk-_xz6%hrJ#7^+^SRk6VvNcd!HIn0O_V}M1T+xTM}j>^0jWVqD|Q#&~8&6pae3qmr*wO27Z! zvx_W0loOU!%(GzUtaK=jy?sDDNR0U?>+lM|Hp9ZBI|Y2*d!M?TkX8Et(JNYXS(n)# zHAXj%1AS|2L%SV{>`MH?oQpw|SXBW0Efy3te2HxHQJ*=r56ZA57#bMoH`yePeym8k z^&zdI4c3ZA+03BIJJ(_e6L+6A92z%j=F8vWtFTc?r`4g3+!gP+t+$T#1b|x`6R)>u zM+%+d#d+H8KHI$Tj)|B=P(AieQ>!2i;oRy86aj?xauO>McTl7$biOeZlVj+-@FYm} zNL&6yq4>NAfvs?J`L+7op;q|%=g(SUkj=M=B-~A0HbtiSQXcW%=knVrm?-_%6?>$T zdnbq4WRr?2_lCK3EyRJ6SN;*VS5aw892av#|)mD_P zgjq1hm*sXuckWA>@epzf#JS9UT!j=@+L;UQYAh?`dOlR;5@P(AIOh2(UKJXzx8dx2 z6-o!n#7jbZp`v+UMS4s}dBw<(A=}NFKtqb)i=#FgyC1z>xi9FrT#}JM_r#Wwte9<- zQ{72X>3gHBtj+w{lkS@IO>JlCD(fIqg+3MR>`*0X1!g<;AKW2w^|rCb!`?WpERJS$ zc1(-|r~1V^rd(plnguF`p0!bA9&oZg>+6~y28_+wWJ7)(sj>Hg)|XB?Pl1)TphnJ| zlpl78!~?9trJOI-68F&NnS@z6W0uLf4+EG$e)zV`6PTBe!bkcQ%K530oe|2-&+b

Y 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�xkB?Dsg15Cx5}Neei@(j zKe)fu<@rBBTi~J&#>sy`U3&8m%m1}P`P!FOtatvM3|wYl4;+VVH17Vb51hHNTl`)5 zZ2d#DB*+dl$^l^%Q0roZP6JqqY`S*s+Ob>K)*3>sdod|^41Ull6)qCO|-Kg07c`#-1^)~7z) z|NKhblgjldsn7vrj0}=7RiPpXUGmUWDG+t*){Wcl>8V`Nw+}5;?la}+SiB%qhQXHA z-&OSaw%fa{gSK@5hxD9j+Tq19(_;VsD&Z0iSIIXju0hY*Xt3JF{2z2X^`7tlgg04a z%S^ofeg5BG`498zFZcg*1+It8V7{7{I3PDB@qAbSc5HB*XR2`{Ow;J2etAEYCJB;CBLBd;V7;s2w+I>u3m%rl!%HGg?XrkCup|bPZ8wd!5l36$ xqdkt%-qmPNav1lT-~aG^R+qdv!1jsye}>e>|Af8g|NP?r`weg?l%f9rO#t;n-U9#t literal 0 HcmV?d00001 diff --git a/docs/source/recipes/aishell/images/aishell-tdnn-lstm-ctc-tensorboard-log.jpg b/docs/source/recipes/aishell/images/aishell-tdnn-lstm-ctc-tensorboard-log.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b31db3ab5286366db670aa8fbc06d9836f7ae110 GIT binary patch literal 436167 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%0DN2o{1DGEi>r`In<9{B{FB{$3UnHXLUq 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

TM=ni)m9bC6r&M>OJsCr; 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 z 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 J@3cve{6EQ<%7g#_ literal 0 HcmV?d00001 diff --git a/docs/source/recipes/aishell/tdnn_lstm_ctc.rst b/docs/source/recipes/aishell/tdnn_lstm_ctc.rst new file mode 100644 index 000000000..e9b0ea656 --- /dev/null +++ b/docs/source/recipes/aishell/tdnn_lstm_ctc.rst @@ -0,0 +1,504 @@ +TDNN-LSTM CTC +============= + +This tutorial shows you how to run a tdnn-lstm ctc model +with the `Aishell `_ dataset. + + +.. HINT:: + + We assume you have read the page :ref:`install icefall` and have setup + the environment for ``icefall``. + +.. HINT:: + + We recommend you to use a GPU or several GPUs to run this recipe. + +In this tutorial, you will learn: + + - (1) How to prepare data for training and decoding + - (2) How to start the training, either with a single GPU or multiple GPUs + - (3) How to do decoding after training. + - (4) How to use a pre-trained model, provided by us + +Data preparation +---------------- + +.. code-block:: bash + + $ cd egs/aishell/ASR + $ ./prepare.sh + +The script ``./prepare.sh`` handles the data preparation for you, **automagically**. +All you need to do is to run it. + +The data preparation contains several stages, you can use the following two +options: + + - ``--stage`` + - ``--stop-stage`` + +to control which stage(s) should be run. By default, all stages are executed. + + +For example, + +.. code-block:: bash + + $ cd egs/aishell/ASR + $ ./prepare.sh --stage 0 --stop-stage 0 + +means to run only stage 0. + +To run stage 2 to stage 5, use: + +.. code-block:: bash + + $ ./prepare.sh --stage 2 --stop-stage 5 + +.. HINT:: + + If you have pre-downloaded the `Aishell `_ + dataset and the `musan `_ dataset, say, + they are saved in ``/tmp/aishell`` and ``/tmp/musan``, you can modify + the ``dl_dir`` variable in ``./prepare.sh`` to point to ``/tmp`` so that + ``./prepare.sh`` won't re-download them. + +.. HINT:: + + A 3-gram language model will be downloaded from huggingface, we assume you have + intalled and initialized ``git-lfs``. If not, you could install ``git-lfs`` by + + .. code-block:: bash + + $ sudo apt-get install git-lfs + $ git-lfs install + + If you don't have the ``sudo`` permission, you could download the + `git-lfs binary `_ here, then add it to you ``PATH``. + +.. NOTE:: + + All generated files by ``./prepare.sh``, e.g., features, lexicon, etc, + are saved in ``./data`` directory. + + +Training +-------- + +Configurable options +~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: bash + + $ cd egs/aishell/ASR + $ ./tdnn_lstm_ctc/train.py --help + +shows you the training options that can be passed from the commandline. +The following options are used quite often: + + + - ``--num-epochs`` + + It is the number of epochs to train. For instance, + ``./tdnn_lstm_ctc/train.py --num-epochs 30`` trains for 30 epochs + and generates ``epoch-0.pt``, ``epoch-1.pt``, ..., ``epoch-29.pt`` + in the folder ``./tdnn_lstm_ctc/exp``. + + - ``--start-epoch`` + + It's used to resume training. + ``./tdnn_lstm_ctc/train.py --start-epoch 10`` loads the + checkpoint ``./tdnn_lstm_ctc/exp/epoch-9.pt`` and starts + training from epoch 10, based on the state from epoch 9. + + - ``--world-size`` + + It is used for multi-GPU single-machine DDP training. + + - (a) If it is 1, then no DDP training is used. + + - (b) If it is 2, then GPU 0 and GPU 1 are used for DDP training. + + The following shows some use cases with it. + + **Use case 1**: You have 4 GPUs, but you only want to use GPU 0 and + GPU 2 for training. You can do the following: + + .. code-block:: bash + + $ cd egs/aishell/ASR + $ export CUDA_VISIBLE_DEVICES="0,2" + $ ./tdnn_lstm_ctc/train.py --world-size 2 + + **Use case 2**: You have 4 GPUs and you want to use all of them + for training. You can do the following: + + .. code-block:: bash + + $ cd egs/aishell/ASR + $ ./tdnn_lstm_ctc/train.py --world-size 4 + + **Use case 3**: You have 4 GPUs but you only want to use GPU 3 + for training. You can do the following: + + .. code-block:: bash + + $ cd egs/aishell/ASR + $ export CUDA_VISIBLE_DEVICES="3" + $ ./tdnn_lstm_ctc/train.py --world-size 1 + + .. CAUTION:: + + Only multi-GPU single-machine DDP training is implemented at present. + Multi-GPU multi-machine DDP training will be added later. + + - ``--max-duration`` + + It specifies the number of seconds over all utterances in a + batch, before **padding**. + If you encounter CUDA OOM, please reduce it. For instance, if + your are using V100 NVIDIA GPU, we recommend you to set it to ``2000``. + + .. HINT:: + + Due to padding, the number of seconds of all utterances in a + batch will usually be larger than ``--max-duration``. + + A larger value for ``--max-duration`` may cause OOM during training, + while a smaller value may increase the training time. You have to + tune it. + + +Pre-configured options +~~~~~~~~~~~~~~~~~~~~~~ + +There are some training options, e.g., weight decay, +number of warmup steps, results dir, etc, +that are not passed from the commandline. +They are pre-configured by the function ``get_params()`` in +`tdnn_lstm_ctc/train.py `_ + +You don't need to change these pre-configured parameters. If you really need to change +them, please modify ``./tdnn_lstm_ctc/train.py`` directly. + + +.. CAUTION:: + + The training set is perturbed by speed with two factors: 0.9 and 1.1. + Each epoch actually processes ``3x150 == 450`` hours of data. + + +Training logs +~~~~~~~~~~~~~ + +Training logs and checkpoints are saved in ``tdnn_lstm_ctc/exp``. +You will find the following files in that directory: + + - ``epoch-0.pt``, ``epoch-1.pt``, ... + + These are checkpoint files, containing model ``state_dict`` and optimizer ``state_dict``. + To resume training from some checkpoint, say ``epoch-10.pt``, you can use: + + .. code-block:: bash + + $ ./tdnn_lstm_ctc/train.py --start-epoch 11 + + - ``tensorboard/`` + + This folder contains TensorBoard logs. Training loss, validation loss, learning + rate, etc, are recorded in these logs. You can visualize them by: + + .. code-block:: bash + + $ cd tdnn_lstm_ctc/exp/tensorboard + $ tensorboard dev upload --logdir . --description "TDNN-LSTM CTC training for Aishell with icefall" + + It will print something like below: + + .. code-block:: + + TensorFlow installation not found - running with reduced feature set. + Upload started and will continue reading any new data as it's added to the logdir. + + To stop uploading, press Ctrl-C. + + New experiment created. View your TensorBoard at: https://tensorboard.dev/experiment/LJI9MWUORLOw3jkdhxwk8A/ + + [2021-09-13T11:59:23] Started scanning logdir. + [2021-09-13T11:59:24] Total uploaded: 4454 scalars, 0 tensors, 0 binary objects + Listening for new data in logdir... + + Note there is a URL in the above output, click it and you will see + the following screenshot: + + .. figure:: images/aishell-tdnn-lstm-ctc-tensorboard-log.jpg + :width: 600 + :alt: TensorBoard screenshot + :align: center + :target: https://tensorboard.dev/experiment/LJI9MWUORLOw3jkdhxwk8A/ + + TensorBoard screenshot. + + - ``log/log-train-xxxx`` + + It is the detailed training log in text format, same as the one + you saw printed to the console during training. + +Usage examples +~~~~~~~~~~~~~~ + +The following shows typical use cases: + +**Case 1** +^^^^^^^^^^ + +.. code-block:: bash + + $ cd egs/aishell/ASR + $ export CUDA_VISIBLE_DEVICES="0,3" + $ ./tdnn_lstm_ctc/train.py --world-size 2 + +It uses GPU 0 and GPU 3 for DDP training. + +**Case 2** +^^^^^^^^^^ + +.. code-block:: bash + + $ cd egs/aishell/ASR + $ ./tdnn_lstm_ctc/train.py --num-epochs 10 --start-epoch 3 + +It loads checkpoint ``./tdnn_lstm_ctc/exp/epoch-2.pt`` and starts +training from epoch 3. Also, it trains for 10 epochs. + +Decoding +-------- + +The decoding part uses checkpoints saved by the training part, so you have +to run the training part first. + +.. code-block:: bash + + $ cd egs/aishell/ASR + $ ./tdnn_lstm_ctc/decode.py --help + +shows the options for decoding. + +The commonly used options are: + + - ``--method`` + + This specifies the decoding method. + + The following command uses attention decoder for rescoring: + + .. code-block:: + + $ cd egs/aishell/ASR + $ ./tdnn_lstm_ctc/decode.py --method 1best --max-duration 100 + + - ``--max-duration`` + + It has the same meaning as the one during training. A larger + value may cause OOM. + +Pre-trained Model +----------------- + +We have uploaded a pre-trained model to +``_. + +We describe how to use the pre-trained model to transcribe a sound file or +multiple sound files in the following. + +Install kaldifeat +~~~~~~~~~~~~~~~~~ + +`kaldifeat `_ is used to +extract features for a single sound file or multiple sound files +at the same time. + +Please refer to ``_ for installation. + +Download the pre-trained model +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The following commands describe how to download the pre-trained model: + +.. code-block:: + + $ cd egs/aishell/ASR + $ mkdir tmp + $ cd tmp + $ git lfs install + $ git clone https://huggingface.co/pkufool/icefall_asr_aishell_tdnn_lstm_ctc + +.. CAUTION:: + + You have to use ``git lfs`` to download the pre-trained model. + +.. CAUTION:: + + In order to use this pre-trained model, your k2 version has to be v1.7 or later. + +After downloading, you will have the following files: + +.. code-block:: bash + + $ cd egs/aishell/ASR + $ tree tmp + +.. code-block:: bash + + tmp/ + `-- icefall_asr_aishell_tdnn_lstm_ctc + |-- README.md + |-- data + | `-- lang_phone + | |-- HLG.pt + | |-- tokens.txt + | `-- words.txt + |-- exp + | `-- pretrained.pt + `-- test_waves + |-- BAC009S0764W0121.wav + |-- BAC009S0764W0122.wav + |-- BAC009S0764W0123.wav + `-- trans.txt + + 5 directories, 9 files + +**File descriptions**: + + - ``data/lang_phone/HLG.pt`` + + It is the decoding graph. + + - ``data/lang_phone/tokens.txt`` + + It contains tokens and their IDs. + Provided only for convenience so that you can look up the SOS/EOS ID easily. + + - ``data/lang_phone/words.txt`` + + It contains words and their IDs. + + - ``exp/pretrained.pt`` + + It contains pre-trained model parameters, obtained by averaging + checkpoints from ``epoch-18.pt`` to ``epoch-40.pt``. + Note: We have removed optimizer ``state_dict`` to reduce file size. + + - ``test_waves/*.wav`` + + It contains some test sound files from Aishell ``test`` dataset. + + - ``test_waves/trans.txt`` + + It contains the reference transcripts for the sound files in `test_waves/`. + +The information of the test sound files is listed below: + +.. code-block:: bash + + $ soxi tmp/icefall_asr_aishell_tdnn_lstm_ctc/test_wavs/*.wav + + Input File : 'tmp/icefall_asr_aishell_tdnn_lstm_ctc/test_waves/BAC009S0764W0121.wav' + Channels : 1 + Sample Rate : 16000 + Precision : 16-bit + Duration : 00:00:04.20 = 67263 samples ~ 315.295 CDDA sectors + File Size : 135k + Bit Rate : 256k + Sample Encoding: 16-bit Signed Integer PCM + + + Input File : 'tmp/icefall_asr_aishell_tdnn_lstm_ctc/test_waves/BAC009S0764W0122.wav' + Channels : 1 + Sample Rate : 16000 + Precision : 16-bit + Duration : 00:00:04.12 = 65840 samples ~ 308.625 CDDA sectors + File Size : 132k + Bit Rate : 256k + Sample Encoding: 16-bit Signed Integer PCM + + + Input File : 'tmp/icefall_asr_aishell_tdnn_lstm_ctc/test_waves/BAC009S0764W0123.wav' + Channels : 1 + Sample Rate : 16000 + Precision : 16-bit + Duration : 00:00:04.00 = 64000 samples ~ 300 CDDA sectors + File Size : 128k + Bit Rate : 256k + Sample Encoding: 16-bit Signed Integer PCM + + Total Duration of 3 files: 00:00:12.32 + +Usage +~~~~~ + +.. code-block:: + + $ cd egs/aishell/ASR + $ ./tdnn_lstm_ctc/pretrained.py --help + +displays the help information. + + +HLG decoding +^^^^^^^^^^^^ + +HLG decoding uses the best path of the decoding lattice as the decoding result. + +The command to run HLG decoding is: + +.. code-block:: bash + + $ cd egs/aishell/ASR + $ ./tdnn_lstm_ctc/pretrained.py \ + --checkpoint ./tmp/icefall_asr_aishell_tdnn_lstm_ctc/exp/pretrained.pt \ + --words-file ./tmp/icefall_asr_aishell_tdnn_lstm_ctc/data/lang_phone/words.txt \ + --HLG ./tmp/icefall_asr_aishell_tdnn_lstm_ctc/data/lang_phone/HLG.pt \ + --method 1best \ + ./tmp/icefall_asr_aishell_tdnn_lstm_ctc/test_wavs/BAC009S0764W0121.wav \ + ./tmp/icefall_asr_aishell_tdnn_lstm_ctc/test_wavs/BAC009S0764W0122.wav \ + ./tmp/icefall_asr_aishell_tdnn_lstm_ctc/test_wavs/BAC009S0764W0123.wav + +The output is given below: + +.. code-block:: + + 2021-09-13 15:00:55,858 INFO [pretrained.py:140] device: cuda:0 + 2021-09-13 15:00:55,858 INFO [pretrained.py:142] Creating model + 2021-09-13 15:01:05,389 INFO [pretrained.py:154] Loading HLG from ./tmp/icefall_asr_aishell_tdnn_lstm_ctc/data/lang_phone/HLG.pt + 2021-09-13 15:01:06,531 INFO [pretrained.py:161] Constructing Fbank computer + 2021-09-13 15:01:06,536 INFO [pretrained.py:171] Reading sound files: ['./tmp/icefall_asr_aishell_tdnn_lstm_ctc/test_waves/BAC009S0764W0121.wav', './tmp/icefall_asr_aishell_tdnn_lstm_ctc/test_waves/BAC009S0764W0122.wav', './tmp/icefall_asr_aishell_tdnn_lstm_ctc/test_waves/BAC009S0764W0123.wav'] + 2021-09-13 15:01:06,539 INFO [pretrained.py:177] Decoding started + 2021-09-13 15:01:06,917 INFO [pretrained.py:207] Use HLG decoding + 2021-09-13 15:01:07,129 INFO [pretrained.py:220] + ./tmp/icefall_asr_aishell_tdnn_lstm_ctc/test_waves/BAC009S0764W0121.wav: + 甚至 出现 交易 几乎 停滞 的 情况 + + ./tmp/icefall_asr_aishell_tdnn_lstm_ctc/test_waves/BAC009S0764W0122.wav: + 一二 线 城市 虽然 也 处于 调整 中 + + ./tmp/icefall_asr_aishell_tdnn_lstm_ctc/test_waves/BAC009S0764W0123.wav: + 但 因为 聚集 了 过多 公共 资源 + + + 2021-09-13 15:01:07,129 INFO [pretrained.py:222] Decoding Done + + +Colab notebook +-------------- + +We do provide a colab notebook for this recipe showing how to use a pre-trained model. + +|aishell asr conformer ctc colab notebook| + +.. |aishell asr conformer ctc colab notebook| image:: https://colab.research.google.com/assets/colab-badge.svg + :target: https://colab.research.google.com/drive/1qULaGvXq7PCu_P61oubfz9b53JzY4H3z + +**Congratulations!** You have finished the aishell ASR recipe with +TDNN-LSTM CTC models in ``icefall``. diff --git a/docs/source/recipes/index.rst b/docs/source/recipes/index.rst index a4362cc00..78e9ea569 100644 --- a/docs/source/recipes/index.rst +++ b/docs/source/recipes/index.rst @@ -16,4 +16,6 @@ We may add recipes for other tasks as well in the future. librispeech + aishell + timit diff --git a/egs/aishell/ASR/README.md b/egs/aishell/ASR/README.md new file mode 100644 index 000000000..3fd177376 --- /dev/null +++ b/egs/aishell/ASR/README.md @@ -0,0 +1,3 @@ + +Please refer to +for how to run models in this recipe. diff --git a/egs/aishell/ASR/RESULTS.md b/egs/aishell/ASR/RESULTS.md new file mode 100644 index 000000000..589d9ee7b --- /dev/null +++ b/egs/aishell/ASR/RESULTS.md @@ -0,0 +1,56 @@ +## Results + +### Aishell training results (Conformer-CTC) +#### 2021-11-16 +(Wei Kang): Result of https://github.com/k2-fsa/icefall/pull/30 + +Pretrained model is available at https://huggingface.co/pkufool/icefall_asr_aishell_conformer_ctc + +The best decoding results (CER) are listed below, we got this results by averaging models from epoch 60 to 84, and using `attention-decoder` decoder with num_paths equals to 100. + +||test| +|--|--| +|CER| 4.26% | + +To get more unique paths, we scaled the lattice.scores with 0.5 (see https://github.com/k2-fsa/icefall/pull/10#discussion_r690951662 for more details), we searched the lm_score_scale and attention_score_scale for best results, the scales that produced the CER above are also listed below. + +||lm_scale|attention_scale| +|--|--|--| +|test|0.3|0.9| + +You can use the following commands to reproduce our results: + +```bash +git clone https://github.com/k2-fsa/icefall +cd icefall + +cd egs/aishell/ASR +./prepare.sh + +export CUDA_VISIBLE_DEVICES="0,1,2,3" +python conformer_ctc/train.py --bucketing-sampler True \ + --max-duration 200 \ + --start-epoch 0 \ + --num-epoch 90 \ + --world-size 4 + +python conformer_ctc/decode.py --nbest-scale 0.5 \ + --epoch 84 \ + --avg 25 \ + --method attention-decoder \ + --max-duration 20 \ + --num-paths 100 +``` + +### Aishell training results (Tdnn-Lstm) +#### 2021-09-13 + +(Wei Kang): Result of phone based Tdnn-Lstm model, https://github.com/k2-fsa/icefall/pull/30 + +Pretrained model is available at https://huggingface.co/pkufool/icefall_asr_aishell_conformer_ctc_lstm_ctc + +The best decoding results (CER) are listed below, we got this results by averaging models from epoch 19 to 8, and using `1best` decoding method. + +||test| +|--|--| +|CER| 10.16% | diff --git a/egs/aishell/ASR/conformer_ctc/README.md b/egs/aishell/ASR/conformer_ctc/README.md new file mode 100644 index 000000000..50596ee92 --- /dev/null +++ b/egs/aishell/ASR/conformer_ctc/README.md @@ -0,0 +1,4 @@ + +Please visit + +for how to run this recipe. diff --git a/egs/aishell/ASR/conformer_ctc/__init__.py b/egs/aishell/ASR/conformer_ctc/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/egs/aishell/ASR/conformer_ctc/asr_datamodule.py b/egs/aishell/ASR/conformer_ctc/asr_datamodule.py new file mode 120000 index 000000000..fa1b8cca3 --- /dev/null +++ b/egs/aishell/ASR/conformer_ctc/asr_datamodule.py @@ -0,0 +1 @@ +../tdnn_lstm_ctc/asr_datamodule.py \ No newline at end of file diff --git a/egs/aishell/ASR/conformer_ctc/conformer.py b/egs/aishell/ASR/conformer_ctc/conformer.py new file mode 100644 index 000000000..7bd0f95cf --- /dev/null +++ b/egs/aishell/ASR/conformer_ctc/conformer.py @@ -0,0 +1,917 @@ +#!/usr/bin/env python3 +# Copyright (c) 2021 University of Chinese Academy of Sciences (author: Han Zhu) +# +# See ../../../../LICENSE for clarification regarding multiple authors +# +# 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 math +import warnings +from typing import Optional, Tuple + +import torch +from torch import Tensor, nn +from transformer import Supervisions, Transformer, encoder_padding_mask + + +class Conformer(Transformer): + """ + Args: + num_features (int): Number of input features + num_classes (int): Number of output classes + subsampling_factor (int): subsampling factor of encoder (the convolution layers before transformers) + d_model (int): attention dimension + nhead (int): number of head + dim_feedforward (int): feedforward dimention + num_encoder_layers (int): number of encoder layers + num_decoder_layers (int): number of decoder layers + dropout (float): dropout rate + cnn_module_kernel (int): Kernel size of convolution module + normalize_before (bool): whether to use layer_norm before the first block. + vgg_frontend (bool): whether to use vgg frontend. + use_feat_batchnorm(bool): whether to use batch-normalize the input. + """ + + def __init__( + self, + num_features: int, + num_classes: int, + subsampling_factor: int = 4, + d_model: int = 256, + nhead: int = 4, + dim_feedforward: int = 2048, + num_encoder_layers: int = 12, + num_decoder_layers: int = 6, + dropout: float = 0.1, + cnn_module_kernel: int = 31, + normalize_before: bool = True, + vgg_frontend: bool = False, + use_feat_batchnorm: bool = False, + ) -> None: + super(Conformer, self).__init__( + num_features=num_features, + num_classes=num_classes, + subsampling_factor=subsampling_factor, + d_model=d_model, + nhead=nhead, + dim_feedforward=dim_feedforward, + num_encoder_layers=num_encoder_layers, + num_decoder_layers=num_decoder_layers, + dropout=dropout, + normalize_before=normalize_before, + vgg_frontend=vgg_frontend, + use_feat_batchnorm=use_feat_batchnorm, + ) + + self.encoder_pos = RelPositionalEncoding(d_model, dropout) + + encoder_layer = ConformerEncoderLayer( + d_model, + nhead, + dim_feedforward, + dropout, + cnn_module_kernel, + normalize_before, + ) + self.encoder = ConformerEncoder(encoder_layer, num_encoder_layers) + self.normalize_before = normalize_before + if self.normalize_before: + self.after_norm = nn.LayerNorm(d_model) + else: + # Note: TorchScript detects that self.after_norm could be used inside forward() + # and throws an error without this change. + self.after_norm = identity + + def run_encoder( + self, x: Tensor, supervisions: Optional[Supervisions] = None + ) -> Tuple[Tensor, Optional[Tensor]]: + """ + Args: + x: + The model input. Its shape is [N, T, C]. + supervisions: + Supervision in lhotse format. + See https://github.com/lhotse-speech/lhotse/blob/master/lhotse/dataset/speech_recognition.py#L32 # noqa + CAUTION: It contains length information, i.e., start and number of + frames, before subsampling + It is read directly from the batch, without any sorting. It is used + to compute encoder padding mask, which is used as memory key padding + mask for the decoder. + + Returns: + Tensor: Predictor tensor of dimension (input_length, batch_size, d_model). + Tensor: Mask tensor of dimension (batch_size, input_length) + """ + x = self.encoder_embed(x) + x, pos_emb = self.encoder_pos(x) + x = x.permute(1, 0, 2) # (B, T, F) -> (T, B, F) + mask = encoder_padding_mask(x.size(0), supervisions) + if mask is not None: + mask = mask.to(x.device) + x = self.encoder(x, pos_emb, src_key_padding_mask=mask) # (T, B, F) + + if self.normalize_before: + x = self.after_norm(x) + + return x, mask + + +class ConformerEncoderLayer(nn.Module): + """ + ConformerEncoderLayer is made up of self-attn, feedforward and convolution networks. + See: "Conformer: Convolution-augmented Transformer for Speech Recognition" + + Args: + d_model: the number of expected features in the input (required). + nhead: the number of heads in the multiheadattention models (required). + dim_feedforward: the dimension of the feedforward network model (default=2048). + dropout: the dropout value (default=0.1). + cnn_module_kernel (int): Kernel size of convolution module. + normalize_before: whether to use layer_norm before the first block. + + Examples:: + >>> encoder_layer = ConformerEncoderLayer(d_model=512, nhead=8) + >>> src = torch.rand(10, 32, 512) + >>> pos_emb = torch.rand(32, 19, 512) + >>> out = encoder_layer(src, pos_emb) + """ + + def __init__( + self, + d_model: int, + nhead: int, + dim_feedforward: int = 2048, + dropout: float = 0.1, + cnn_module_kernel: int = 31, + normalize_before: bool = True, + ) -> None: + super(ConformerEncoderLayer, self).__init__() + self.self_attn = RelPositionMultiheadAttention( + d_model, nhead, dropout=0.0 + ) + + self.feed_forward = nn.Sequential( + nn.Linear(d_model, dim_feedforward), + Swish(), + nn.Dropout(dropout), + nn.Linear(dim_feedforward, d_model), + ) + + self.feed_forward_macaron = nn.Sequential( + nn.Linear(d_model, dim_feedforward), + Swish(), + nn.Dropout(dropout), + nn.Linear(dim_feedforward, d_model), + ) + + self.conv_module = ConvolutionModule(d_model, cnn_module_kernel) + + self.norm_ff_macaron = nn.LayerNorm( + d_model + ) # for the macaron style FNN module + self.norm_ff = nn.LayerNorm(d_model) # for the FNN module + self.norm_mha = nn.LayerNorm(d_model) # for the MHA module + + self.ff_scale = 0.5 + + self.norm_conv = nn.LayerNorm(d_model) # for the CNN module + self.norm_final = nn.LayerNorm( + d_model + ) # for the final output of the block + + self.dropout = nn.Dropout(dropout) + + self.normalize_before = normalize_before + + def forward( + self, + src: Tensor, + pos_emb: Tensor, + src_mask: Optional[Tensor] = None, + src_key_padding_mask: Optional[Tensor] = None, + ) -> Tensor: + """ + Pass the input through the encoder layer. + + Args: + src: the sequence to the encoder layer (required). + pos_emb: Positional embedding tensor (required). + src_mask: the mask for the src sequence (optional). + src_key_padding_mask: the mask for the src keys per batch (optional). + + Shape: + src: (S, N, E). + pos_emb: (N, 2*S-1, E) + src_mask: (S, S). + src_key_padding_mask: (N, S). + S is the source sequence length, N is the batch size, E is the feature number + """ + + # macaron style feed forward module + residual = src + if self.normalize_before: + src = self.norm_ff_macaron(src) + src = residual + self.ff_scale * self.dropout( + self.feed_forward_macaron(src) + ) + if not self.normalize_before: + src = self.norm_ff_macaron(src) + + # multi-headed self-attention module + residual = src + if self.normalize_before: + src = self.norm_mha(src) + src_att = self.self_attn( + src, + src, + src, + pos_emb=pos_emb, + attn_mask=src_mask, + key_padding_mask=src_key_padding_mask, + )[0] + src = residual + self.dropout(src_att) + if not self.normalize_before: + src = self.norm_mha(src) + + # convolution module + residual = src + if self.normalize_before: + src = self.norm_conv(src) + src = residual + self.dropout(self.conv_module(src)) + if not self.normalize_before: + src = self.norm_conv(src) + + # feed forward module + residual = src + if self.normalize_before: + src = self.norm_ff(src) + src = residual + self.ff_scale * self.dropout(self.feed_forward(src)) + if not self.normalize_before: + src = self.norm_ff(src) + + if self.normalize_before: + src = self.norm_final(src) + + return src + + +class ConformerEncoder(nn.TransformerEncoder): + r"""ConformerEncoder is a stack of N encoder layers + + Args: + encoder_layer: an instance of the ConformerEncoderLayer() class (required). + num_layers: the number of sub-encoder-layers in the encoder (required). + norm: the layer normalization component (optional). + + Examples:: + >>> encoder_layer = ConformerEncoderLayer(d_model=512, nhead=8) + >>> conformer_encoder = ConformerEncoder(encoder_layer, num_layers=6) + >>> src = torch.rand(10, 32, 512) + >>> pos_emb = torch.rand(32, 19, 512) + >>> out = conformer_encoder(src, pos_emb) + """ + + def __init__( + self, encoder_layer: nn.Module, num_layers: int, norm: nn.Module = None + ) -> None: + super(ConformerEncoder, self).__init__( + encoder_layer=encoder_layer, num_layers=num_layers, norm=norm + ) + + def forward( + self, + src: Tensor, + pos_emb: Tensor, + mask: Optional[Tensor] = None, + src_key_padding_mask: Optional[Tensor] = None, + ) -> Tensor: + r"""Pass the input through the encoder layers in turn. + + Args: + src: the sequence to the encoder (required). + pos_emb: Positional embedding tensor (required). + mask: the mask for the src sequence (optional). + src_key_padding_mask: the mask for the src keys per batch (optional). + + Shape: + src: (S, N, E). + pos_emb: (N, 2*S-1, E) + mask: (S, S). + src_key_padding_mask: (N, S). + S is the source sequence length, T is the target sequence length, N is the batch size, E is the feature number + + """ + output = src + + for mod in self.layers: + output = mod( + output, + pos_emb, + src_mask=mask, + src_key_padding_mask=src_key_padding_mask, + ) + + if self.norm is not None: + output = self.norm(output) + + return output + + +class RelPositionalEncoding(torch.nn.Module): + """Relative positional encoding module. + + See : Appendix B in "Transformer-XL: Attentive Language Models Beyond a Fixed-Length Context" + Modified from https://github.com/espnet/espnet/blob/master/espnet/nets/pytorch_backend/transformer/embedding.py + + Args: + d_model: Embedding dimension. + dropout_rate: Dropout rate. + max_len: Maximum input length. + + """ + + def __init__( + self, d_model: int, dropout_rate: float, max_len: int = 5000 + ) -> None: + """Construct an PositionalEncoding object.""" + super(RelPositionalEncoding, self).__init__() + self.d_model = d_model + self.xscale = math.sqrt(self.d_model) + self.dropout = torch.nn.Dropout(p=dropout_rate) + self.pe = None + self.extend_pe(torch.tensor(0.0).expand(1, max_len)) + + def extend_pe(self, x: Tensor) -> None: + """Reset the positional encodings.""" + if self.pe is not None: + # self.pe contains both positive and negative parts + # the length of self.pe is 2 * input_len - 1 + if self.pe.size(1) >= x.size(1) * 2 - 1: + # Note: TorchScript doesn't implement operator== for torch.Device + if self.pe.dtype != x.dtype or str(self.pe.device) != str( + x.device + ): + self.pe = self.pe.to(dtype=x.dtype, device=x.device) + return + # Suppose `i` means to the position of query vecotr and `j` means the + # position of key vector. We use position relative positions when keys + # are to the left (i>j) and negative relative positions otherwise (i Tuple[Tensor, Tensor]: + """Add positional encoding. + + Args: + x (torch.Tensor): Input tensor (batch, time, `*`). + + Returns: + torch.Tensor: Encoded tensor (batch, time, `*`). + torch.Tensor: Encoded tensor (batch, 2*time-1, `*`). + + """ + self.extend_pe(x) + x = x * self.xscale + pos_emb = self.pe[ + :, + self.pe.size(1) // 2 + - x.size(1) + + 1 : self.pe.size(1) // 2 # noqa E203 + + x.size(1), + ] + return self.dropout(x), self.dropout(pos_emb) + + +class RelPositionMultiheadAttention(nn.Module): + r"""Multi-Head Attention layer with relative position encoding + + See reference: "Transformer-XL: Attentive Language Models Beyond a Fixed-Length Context" + + Args: + embed_dim: total dimension of the model. + num_heads: parallel attention heads. + dropout: a Dropout layer on attn_output_weights. Default: 0.0. + + Examples:: + + >>> rel_pos_multihead_attn = RelPositionMultiheadAttention(embed_dim, num_heads) + >>> attn_output, attn_output_weights = multihead_attn(query, key, value, pos_emb) + """ + + def __init__( + self, + embed_dim: int, + num_heads: int, + dropout: float = 0.0, + ) -> None: + super(RelPositionMultiheadAttention, self).__init__() + self.embed_dim = embed_dim + self.num_heads = num_heads + self.dropout = dropout + self.head_dim = embed_dim // num_heads + assert ( + self.head_dim * num_heads == self.embed_dim + ), "embed_dim must be divisible by num_heads" + + self.in_proj = nn.Linear(embed_dim, 3 * embed_dim, bias=True) + self.out_proj = nn.Linear(embed_dim, embed_dim, bias=True) + + # linear transformation for positional encoding. + self.linear_pos = nn.Linear(embed_dim, embed_dim, bias=False) + # these two learnable bias are used in matrix c and matrix d + # as described in "Transformer-XL: Attentive Language Models Beyond a Fixed-Length Context" Section 3.3 + self.pos_bias_u = nn.Parameter(torch.Tensor(num_heads, self.head_dim)) + self.pos_bias_v = nn.Parameter(torch.Tensor(num_heads, self.head_dim)) + + self._reset_parameters() + + def _reset_parameters(self) -> None: + nn.init.xavier_uniform_(self.in_proj.weight) + nn.init.constant_(self.in_proj.bias, 0.0) + nn.init.constant_(self.out_proj.bias, 0.0) + + nn.init.xavier_uniform_(self.pos_bias_u) + nn.init.xavier_uniform_(self.pos_bias_v) + + def forward( + self, + query: Tensor, + key: Tensor, + value: Tensor, + pos_emb: Tensor, + key_padding_mask: Optional[Tensor] = None, + need_weights: bool = True, + attn_mask: Optional[Tensor] = None, + ) -> Tuple[Tensor, Optional[Tensor]]: + r""" + Args: + query, key, value: map a query and a set of key-value pairs to an output. + pos_emb: Positional embedding tensor + key_padding_mask: if provided, specified padding elements in the key will + be ignored by the attention. When given a binary mask and a value is True, + the corresponding value on the attention layer will be ignored. When given + a byte mask and a value is non-zero, the corresponding value on the attention + layer will be ignored + need_weights: output attn_output_weights. + attn_mask: 2D or 3D mask that prevents attention to certain positions. A 2D mask will be broadcasted for all + the batches while a 3D mask allows to specify a different mask for the entries of each batch. + + Shape: + - Inputs: + - query: :math:`(L, N, E)` where L is the target sequence length, N is the batch size, E is + the embedding dimension. + - key: :math:`(S, N, E)`, where S is the source sequence length, N is the batch size, E is + the embedding dimension. + - value: :math:`(S, N, E)` where S is the source sequence length, N is the batch size, E is + the embedding dimension. + - pos_emb: :math:`(N, 2*L-1, E)` where L is the target sequence length, N is the batch size, E is + the embedding dimension. + - key_padding_mask: :math:`(N, S)` where N is the batch size, S is the source sequence length. + If a ByteTensor is provided, the non-zero positions will be ignored while the position + with the zero positions will be unchanged. If a BoolTensor is provided, the positions with the + value of ``True`` will be ignored while the position with the value of ``False`` will be unchanged. + - attn_mask: 2D mask :math:`(L, S)` where L is the target sequence length, S is the source sequence length. + 3D mask :math:`(N*num_heads, L, S)` where N is the batch size, L is the target sequence length, + S is the source sequence length. attn_mask ensure that position i is allowed to attend the unmasked + positions. If a ByteTensor is provided, the non-zero positions are not allowed to attend + while the zero positions will be unchanged. If a BoolTensor is provided, positions with ``True`` + is not allowed to attend while ``False`` values will be unchanged. If a FloatTensor + is provided, it will be added to the attention weight. + + - Outputs: + - attn_output: :math:`(L, N, E)` where L is the target sequence length, N is the batch size, + E is the embedding dimension. + - attn_output_weights: :math:`(N, L, S)` where N is the batch size, + L is the target sequence length, S is the source sequence length. + """ + return self.multi_head_attention_forward( + query, + key, + value, + pos_emb, + self.embed_dim, + self.num_heads, + self.in_proj.weight, + self.in_proj.bias, + self.dropout, + self.out_proj.weight, + self.out_proj.bias, + training=self.training, + key_padding_mask=key_padding_mask, + need_weights=need_weights, + attn_mask=attn_mask, + ) + + def rel_shift(self, x: Tensor) -> Tensor: + """Compute relative positional encoding. + + Args: + x: Input tensor (batch, head, time1, 2*time1-1). + time1 means the length of query vector. + + Returns: + Tensor: tensor of shape (batch, head, time1, time2) + (note: time2 has the same value as time1, but it is for + the key, while time1 is for the query). + """ + (batch_size, num_heads, time1, n) = x.shape + assert n == 2 * time1 - 1 + # Note: TorchScript requires explicit arg for stride() + batch_stride = x.stride(0) + head_stride = x.stride(1) + time1_stride = x.stride(2) + n_stride = x.stride(3) + return x.as_strided( + (batch_size, num_heads, time1, time1), + (batch_stride, head_stride, time1_stride - n_stride, n_stride), + storage_offset=n_stride * (time1 - 1), + ) + + def multi_head_attention_forward( + self, + query: Tensor, + key: Tensor, + value: Tensor, + pos_emb: Tensor, + embed_dim_to_check: int, + num_heads: int, + in_proj_weight: Tensor, + in_proj_bias: Tensor, + dropout_p: float, + out_proj_weight: Tensor, + out_proj_bias: Tensor, + training: bool = True, + key_padding_mask: Optional[Tensor] = None, + need_weights: bool = True, + attn_mask: Optional[Tensor] = None, + ) -> Tuple[Tensor, Optional[Tensor]]: + r""" + Args: + query, key, value: map a query and a set of key-value pairs to an output. + pos_emb: Positional embedding tensor + embed_dim_to_check: total dimension of the model. + num_heads: parallel attention heads. + in_proj_weight, in_proj_bias: input projection weight and bias. + dropout_p: probability of an element to be zeroed. + out_proj_weight, out_proj_bias: the output projection weight and bias. + training: apply dropout if is ``True``. + key_padding_mask: if provided, specified padding elements in the key will + be ignored by the attention. This is an binary mask. When the value is True, + the corresponding value on the attention layer will be filled with -inf. + need_weights: output attn_output_weights. + attn_mask: 2D or 3D mask that prevents attention to certain positions. A 2D mask will be broadcasted for all + the batches while a 3D mask allows to specify a different mask for the entries of each batch. + + Shape: + Inputs: + - query: :math:`(L, N, E)` where L is the target sequence length, N is the batch size, E is + the embedding dimension. + - key: :math:`(S, N, E)`, where S is the source sequence length, N is the batch size, E is + the embedding dimension. + - value: :math:`(S, N, E)` where S is the source sequence length, N is the batch size, E is + the embedding dimension. + - pos_emb: :math:`(N, 2*L-1, E)` or :math:`(1, 2*L-1, E)` where L is the target sequence + length, N is the batch size, E is the embedding dimension. + - key_padding_mask: :math:`(N, S)` where N is the batch size, S is the source sequence length. + If a ByteTensor is provided, the non-zero positions will be ignored while the zero positions + will be unchanged. If a BoolTensor is provided, the positions with the + value of ``True`` will be ignored while the position with the value of ``False`` will be unchanged. + - attn_mask: 2D mask :math:`(L, S)` where L is the target sequence length, S is the source sequence length. + 3D mask :math:`(N*num_heads, L, S)` where N is the batch size, L is the target sequence length, + S is the source sequence length. attn_mask ensures that position i is allowed to attend the unmasked + positions. If a ByteTensor is provided, the non-zero positions are not allowed to attend + while the zero positions will be unchanged. If a BoolTensor is provided, positions with ``True`` + are not allowed to attend while ``False`` values will be unchanged. If a FloatTensor + is provided, it will be added to the attention weight. + + Outputs: + - attn_output: :math:`(L, N, E)` where L is the target sequence length, N is the batch size, + E is the embedding dimension. + - attn_output_weights: :math:`(N, L, S)` where N is the batch size, + L is the target sequence length, S is the source sequence length. + """ + + tgt_len, bsz, embed_dim = query.size() + assert embed_dim == embed_dim_to_check + assert key.size(0) == value.size(0) and key.size(1) == value.size(1) + + head_dim = embed_dim // num_heads + assert ( + head_dim * num_heads == embed_dim + ), "embed_dim must be divisible by num_heads" + scaling = float(head_dim) ** -0.5 + + if torch.equal(query, key) and torch.equal(key, value): + # self-attention + q, k, v = nn.functional.linear( + query, in_proj_weight, in_proj_bias + ).chunk(3, dim=-1) + + elif torch.equal(key, value): + # encoder-decoder attention + # This is inline in_proj function with in_proj_weight and in_proj_bias + _b = in_proj_bias + _start = 0 + _end = embed_dim + _w = in_proj_weight[_start:_end, :] + if _b is not None: + _b = _b[_start:_end] + q = nn.functional.linear(query, _w, _b) + # This is inline in_proj function with in_proj_weight and in_proj_bias + _b = in_proj_bias + _start = embed_dim + _end = None + _w = in_proj_weight[_start:, :] + if _b is not None: + _b = _b[_start:] + k, v = nn.functional.linear(key, _w, _b).chunk(2, dim=-1) + + else: + # This is inline in_proj function with in_proj_weight and in_proj_bias + _b = in_proj_bias + _start = 0 + _end = embed_dim + _w = in_proj_weight[_start:_end, :] + if _b is not None: + _b = _b[_start:_end] + q = nn.functional.linear(query, _w, _b) + + # This is inline in_proj function with in_proj_weight and in_proj_bias + _b = in_proj_bias + _start = embed_dim + _end = embed_dim * 2 + _w = in_proj_weight[_start:_end, :] + if _b is not None: + _b = _b[_start:_end] + k = nn.functional.linear(key, _w, _b) + + # This is inline in_proj function with in_proj_weight and in_proj_bias + _b = in_proj_bias + _start = embed_dim * 2 + _end = None + _w = in_proj_weight[_start:, :] + if _b is not None: + _b = _b[_start:] + v = nn.functional.linear(value, _w, _b) + + if attn_mask is not None: + assert ( + attn_mask.dtype == torch.float32 + or attn_mask.dtype == torch.float64 + or attn_mask.dtype == torch.float16 + or attn_mask.dtype == torch.uint8 + or attn_mask.dtype == torch.bool + ), "Only float, byte, and bool types are supported for attn_mask, not {}".format( + attn_mask.dtype + ) + if attn_mask.dtype == torch.uint8: + warnings.warn( + "Byte tensor for attn_mask is deprecated. Use bool tensor instead." + ) + attn_mask = attn_mask.to(torch.bool) + + if attn_mask.dim() == 2: + attn_mask = attn_mask.unsqueeze(0) + if list(attn_mask.size()) != [1, query.size(0), key.size(0)]: + raise RuntimeError( + "The size of the 2D attn_mask is not correct." + ) + elif attn_mask.dim() == 3: + if list(attn_mask.size()) != [ + bsz * num_heads, + query.size(0), + key.size(0), + ]: + raise RuntimeError( + "The size of the 3D attn_mask is not correct." + ) + else: + raise RuntimeError( + "attn_mask's dimension {} is not supported".format( + attn_mask.dim() + ) + ) + # attn_mask's dim is 3 now. + + # convert ByteTensor key_padding_mask to bool + if ( + key_padding_mask is not None + and key_padding_mask.dtype == torch.uint8 + ): + warnings.warn( + "Byte tensor for key_padding_mask is deprecated. Use bool tensor instead." + ) + key_padding_mask = key_padding_mask.to(torch.bool) + + q = q.contiguous().view(tgt_len, bsz, num_heads, head_dim) + k = k.contiguous().view(-1, bsz, num_heads, head_dim) + v = v.contiguous().view(-1, bsz * num_heads, head_dim).transpose(0, 1) + + src_len = k.size(0) + + if key_padding_mask is not None: + assert key_padding_mask.size(0) == bsz, "{} == {}".format( + key_padding_mask.size(0), bsz + ) + assert key_padding_mask.size(1) == src_len, "{} == {}".format( + key_padding_mask.size(1), src_len + ) + + q = q.transpose(0, 1) # (batch, time1, head, d_k) + + pos_emb_bsz = pos_emb.size(0) + assert pos_emb_bsz in (1, bsz) # actually it is 1 + p = self.linear_pos(pos_emb).view(pos_emb_bsz, -1, num_heads, head_dim) + p = p.transpose(1, 2) # (batch, head, 2*time1-1, d_k) + + q_with_bias_u = (q + self.pos_bias_u).transpose( + 1, 2 + ) # (batch, head, time1, d_k) + + q_with_bias_v = (q + self.pos_bias_v).transpose( + 1, 2 + ) # (batch, head, time1, d_k) + + # compute attention score + # first compute matrix a and matrix c + # as described in "Transformer-XL: Attentive Language Models Beyond a Fixed-Length Context" Section 3.3 + k = k.permute(1, 2, 3, 0) # (batch, head, d_k, time2) + matrix_ac = torch.matmul( + q_with_bias_u, k + ) # (batch, head, time1, time2) + + # compute matrix b and matrix d + matrix_bd = torch.matmul( + q_with_bias_v, p.transpose(-2, -1) + ) # (batch, head, time1, 2*time1-1) + matrix_bd = self.rel_shift(matrix_bd) + + attn_output_weights = ( + matrix_ac + matrix_bd + ) * scaling # (batch, head, time1, time2) + + attn_output_weights = attn_output_weights.view( + bsz * num_heads, tgt_len, -1 + ) + + assert list(attn_output_weights.size()) == [ + bsz * num_heads, + tgt_len, + src_len, + ] + + if attn_mask is not None: + if attn_mask.dtype == torch.bool: + attn_output_weights.masked_fill_(attn_mask, float("-inf")) + else: + attn_output_weights += attn_mask + + if key_padding_mask is not None: + attn_output_weights = attn_output_weights.view( + bsz, num_heads, tgt_len, src_len + ) + attn_output_weights = attn_output_weights.masked_fill( + key_padding_mask.unsqueeze(1).unsqueeze(2), + float("-inf"), + ) + attn_output_weights = attn_output_weights.view( + bsz * num_heads, tgt_len, src_len + ) + + attn_output_weights = nn.functional.softmax(attn_output_weights, dim=-1) + attn_output_weights = nn.functional.dropout( + attn_output_weights, p=dropout_p, training=training + ) + + attn_output = torch.bmm(attn_output_weights, v) + assert list(attn_output.size()) == [bsz * num_heads, tgt_len, head_dim] + attn_output = ( + attn_output.transpose(0, 1) + .contiguous() + .view(tgt_len, bsz, embed_dim) + ) + attn_output = nn.functional.linear( + attn_output, out_proj_weight, out_proj_bias + ) + + if need_weights: + # average attention weights over heads + attn_output_weights = attn_output_weights.view( + bsz, num_heads, tgt_len, src_len + ) + return attn_output, attn_output_weights.sum(dim=1) / num_heads + else: + return attn_output, None + + +class ConvolutionModule(nn.Module): + """ConvolutionModule in Conformer model. + Modified from https://github.com/espnet/espnet/blob/master/espnet/nets/pytorch_backend/conformer/convolution.py + + Args: + channels (int): The number of channels of conv layers. + kernel_size (int): Kernerl size of conv layers. + bias (bool): Whether to use bias in conv layers (default=True). + + """ + + def __init__( + self, channels: int, kernel_size: int, bias: bool = True + ) -> None: + """Construct an ConvolutionModule object.""" + super(ConvolutionModule, self).__init__() + # kernerl_size should be a odd number for 'SAME' padding + assert (kernel_size - 1) % 2 == 0 + + self.pointwise_conv1 = nn.Conv1d( + channels, + 2 * channels, + kernel_size=1, + stride=1, + padding=0, + bias=bias, + ) + self.depthwise_conv = nn.Conv1d( + channels, + channels, + kernel_size, + stride=1, + padding=(kernel_size - 1) // 2, + groups=channels, + bias=bias, + ) + self.norm = nn.BatchNorm1d(channels) + self.pointwise_conv2 = nn.Conv1d( + channels, + channels, + kernel_size=1, + stride=1, + padding=0, + bias=bias, + ) + self.activation = Swish() + + def forward(self, x: Tensor) -> Tensor: + """Compute convolution module. + + Args: + x: Input tensor (#time, batch, channels). + + Returns: + Tensor: Output tensor (#time, batch, channels). + + """ + # exchange the temporal dimension and the feature dimension + x = x.permute(1, 2, 0) # (#batch, channels, time). + + # GLU mechanism + x = self.pointwise_conv1(x) # (batch, 2*channels, time) + x = nn.functional.glu(x, dim=1) # (batch, channels, time) + + # 1D Depthwise Conv + x = self.depthwise_conv(x) + x = self.activation(self.norm(x)) + + x = self.pointwise_conv2(x) # (batch, channel, time) + + return x.permute(2, 0, 1) + + +class Swish(torch.nn.Module): + """Construct an Swish object.""" + + def forward(self, x: Tensor) -> Tensor: + """Return Swich activation function.""" + return x * torch.sigmoid(x) + + +def identity(x): + return x diff --git a/egs/aishell/ASR/conformer_ctc/decode.py b/egs/aishell/ASR/conformer_ctc/decode.py new file mode 100755 index 000000000..58ce39cca --- /dev/null +++ b/egs/aishell/ASR/conformer_ctc/decode.py @@ -0,0 +1,585 @@ +#!/usr/bin/env python3 +# Copyright 2021 Xiaomi Corporation (Author: Liyong Guo, +# Fangjun Kuang, +# Wei Kang) +# +# See ../../../../LICENSE for clarification regarding multiple authors +# +# 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 argparse +import logging +from collections import defaultdict +from pathlib import Path +from typing import Dict, List, Optional, Tuple + +import k2 +import torch +import torch.nn as nn +from asr_datamodule import AishellAsrDataModule +from conformer import Conformer + +from icefall.char_graph_compiler import CharCtcTrainingGraphCompiler +from icefall.checkpoint import average_checkpoints, load_checkpoint +from icefall.decode import ( + get_lattice, + nbest_decoding, + nbest_oracle, + one_best_decoding, + rescore_with_attention_decoder, +) +from icefall.lexicon import Lexicon +from icefall.utils import ( + AttributeDict, + get_env_info, + get_texts, + setup_logger, + store_transcripts, + str2bool, + write_error_stats, +) + + +def get_parser(): + parser = argparse.ArgumentParser( + formatter_class=argparse.ArgumentDefaultsHelpFormatter + ) + + parser.add_argument( + "--epoch", + type=int, + default=49, + help="It specifies the checkpoint to use for decoding." + "Note: Epoch counts from 0.", + ) + parser.add_argument( + "--avg", + type=int, + default=20, + help="Number of checkpoints to average. Automatically select " + "consecutive checkpoints before the checkpoint specified by " + "'--epoch'. ", + ) + + parser.add_argument( + "--method", + type=str, + default="attention-decoder", + help="""Decoding method. + Supported values are: + - (0) ctc-decoding. Use CTC decoding. It maps the tokens ids to + tokens using token symbol tabel directly. + - (1) 1best. Extract the best path from the decoding lattice as the + decoding result. + - (2) nbest. Extract n paths from the decoding lattice; the path + with the highest score is the decoding result. + - (3) attention-decoder. Extract n paths from the lattice, + the path with the highest score is the decoding result. + - (4) nbest-oracle. Its WER is the lower bound of any n-best + rescoring method can achieve. Useful for debugging n-best + rescoring method. + """, + ) + + parser.add_argument( + "--num-paths", + type=int, + default=100, + help="""Number of paths for n-best based decoding method. + Used only when "method" is one of the following values: + nbest, attention-decoder, and nbest-oracle + """, + ) + + parser.add_argument( + "--nbest-scale", + type=float, + default=0.5, + help="""The scale to be applied to `lattice.scores`. + It's needed if you use any kinds of n-best based rescoring. + Used only when "method" is one of the following values: + nbest, attention-decoder, and nbest-oracle + A smaller value results in more unique paths. + """, + ) + + parser.add_argument( + "--export", + type=str2bool, + default=False, + help="""When enabled, the averaged model is saved to + conformer_ctc/exp/pretrained.pt. Note: only model.state_dict() is saved. + pretrained.pt contains a dict {"model": model.state_dict()}, + which can be loaded by `icefall.checkpoint.load_checkpoint()`. + """, + ) + + parser.add_argument( + "--exp-dir", + type=str, + default="conformer_ctc/exp", + help="The experiment dir", + ) + + parser.add_argument( + "--lang-dir", + type=str, + default="data/lang_char", + help="The lang dir", + ) + + parser.add_argument( + "--lm-dir", + type=str, + default="data/lm", + help="""The LM dir. + It should contain either G_3_gram.pt or G_3_gram.fst.txt + """, + ) + + return parser + + +def get_params() -> AttributeDict: + params = AttributeDict( + { + # parameters for conformer + "subsampling_factor": 4, + "feature_dim": 80, + "nhead": 4, + "attention_dim": 512, + "num_encoder_layers": 12, + "num_decoder_layers": 6, + "vgg_frontend": False, + "use_feat_batchnorm": True, + # parameters for decoder + "search_beam": 20, + "output_beam": 7, + "min_active_states": 30, + "max_active_states": 10000, + "use_double_scores": True, + "env_info": get_env_info(), + } + ) + return params + + +def decode_one_batch( + params: AttributeDict, + model: nn.Module, + HLG: Optional[k2.Fsa], + H: Optional[k2.Fsa], + batch: dict, + lexicon: Lexicon, + sos_id: int, + eos_id: int, +) -> Dict[str, List[List[int]]]: + """Decode one batch and return the result in a dict. The dict has the + following format: + + - key: It indicates the setting used for decoding. For example, + if decoding method is 1best, the key is the string `no_rescore`. + If attention rescoring is used, the key is the string + `ngram_lm_scale_xxx_attention_scale_xxx`, where `xxx` is the + value of `lm_scale` and `attention_scale`. An example key is + `ngram_lm_scale_0.7_attention_scale_0.5` + - value: It contains the decoding result. `len(value)` equals to + batch size. `value[i]` is the decoding result for the i-th + utterance in the given batch. + Args: + params: + It's the return value of :func:`get_params`. + + - params.method is "1best", it uses 1best decoding without LM rescoring. + - params.method is "nbest", it uses nbest decoding without LM rescoring. + - params.method is "attention-decoder", it uses attention rescoring. + + model: + The neural model. + HLG: + The decoding graph. Used when params.method is NOT ctc-decoding. + H: + The ctc topo. Used only when params.method is ctc-decoding. + batch: + It is the return value from iterating + `lhotse.dataset.K2SpeechRecognitionDataset`. See its documentation + for the format of the `batch`. + lexicon: + It contains the token symbol table and the word symbol table. + sos_id: + The token ID of the SOS. + eos_id: + The token ID of the EOS. + Returns: + Return the decoding result. See above description for the format of + the returned dict. + """ + if HLG is not None: + device = HLG.device + else: + device = H.device + + feature = batch["inputs"] + assert feature.ndim == 3 + feature = feature.to(device) + # at entry, feature is (N, T, C) + + supervisions = batch["supervisions"] + + nnet_output, memory, memory_key_padding_mask = model(feature, supervisions) + # nnet_output is (N, T, C) + + supervision_segments = torch.stack( + ( + supervisions["sequence_idx"], + supervisions["start_frame"] // params.subsampling_factor, + supervisions["num_frames"] // params.subsampling_factor, + ), + 1, + ).to(torch.int32) + + if H is None: + assert HLG is not None + decoding_graph = HLG + else: + assert HLG is None + decoding_graph = H + + lattice = get_lattice( + nnet_output=nnet_output, + decoding_graph=decoding_graph, + supervision_segments=supervision_segments, + search_beam=params.search_beam, + output_beam=params.output_beam, + min_active_states=params.min_active_states, + max_active_states=params.max_active_states, + subsampling_factor=params.subsampling_factor, + ) + + if params.method == "ctc-decoding": + best_path = one_best_decoding( + lattice=lattice, use_double_scores=params.use_double_scores + ) + # Note: `best_path.aux_labels` contains token IDs, not word IDs + # since we are using H, not HLG here. + # + # token_ids is a lit-of-list of IDs + token_ids = get_texts(best_path) + + key = "ctc-decoding" + hyps = [[lexicon.token_table[i] for i in ids] for ids in token_ids] + return {key: hyps} + + if params.method == "nbest-oracle": + # Note: You can also pass rescored lattices to it. + # We choose the HLG decoded lattice for speed reasons + # as HLG decoding is faster and the oracle WER + # is only slightly worse than that of rescored lattices. + best_path = nbest_oracle( + lattice=lattice, + num_paths=params.num_paths, + ref_texts=supervisions["text"], + word_table=lexicon.word_table, + nbest_scale=params.nbest_scale, + oov="", + ) + hyps = get_texts(best_path) + hyps = [[lexicon.word_table[i] for i in ids] for ids in hyps] + key = f"oracle_{params.num_paths}_nbest_scale_{params.nbest_scale}" # noqa + return {key: hyps} + + if params.method in ["1best", "nbest"]: + if params.method == "1best": + best_path = one_best_decoding( + lattice=lattice, use_double_scores=params.use_double_scores + ) + key = "no_rescore" + else: + best_path = nbest_decoding( + lattice=lattice, + num_paths=params.num_paths, + use_double_scores=params.use_double_scores, + nbest_scale=params.nbest_scale, + ) + key = f"no_rescore-scale-{params.nbest_scale}-{params.num_paths}" # noqa + + hyps = get_texts(best_path) + hyps = [[lexicon.word_table[i] for i in ids] for ids in hyps] + return {key: hyps} + + assert params.method == "attention-decoder" + + best_path_dict = rescore_with_attention_decoder( + lattice=lattice, + num_paths=params.num_paths, + model=model, + memory=memory, + memory_key_padding_mask=memory_key_padding_mask, + sos_id=sos_id, + eos_id=eos_id, + nbest_scale=params.nbest_scale, + ) + ans = dict() + if best_path_dict is not None: + for lm_scale_str, best_path in best_path_dict.items(): + hyps = get_texts(best_path) + hyps = [[lexicon.word_table[i] for i in ids] for ids in hyps] + ans[lm_scale_str] = hyps + return ans + + +def decode_dataset( + dl: torch.utils.data.DataLoader, + params: AttributeDict, + model: nn.Module, + HLG: Optional[k2.Fsa], + H: Optional[k2.Fsa], + lexicon: Lexicon, + sos_id: int, + eos_id: int, +) -> Dict[str, List[Tuple[List[int], List[int]]]]: + """Decode dataset. + + Args: + dl: + PyTorch's dataloader containing the dataset to decode. + params: + It is returned by :func:`get_params`. + model: + The neural model. + HLG: + The decoding graph. Used when params.method is NOT ctc-decoding. + H: + The ctc topo. Used only when params.method is ctc-decoding. + lexicon: + It contains the token symbol table and the word symbol table. + sos_id: + The token ID for SOS. + eos_id: + The token ID for EOS. + Returns: + Return a dict, whose key may be "no-rescore" if the decoding method is + 1best or it may be "ngram_lm_scale_0.7_attention_scale_0.5" if attention + rescoring is used. Its value is a list of tuples. Each tuple contains two + elements: The first is the reference transcript, and the second is the + predicted result. + """ + results = [] + + num_cuts = 0 + + try: + num_batches = len(dl) + except TypeError: + num_batches = "?" + + results = defaultdict(list) + for batch_idx, batch in enumerate(dl): + texts = batch["supervisions"]["text"] + + hyps_dict = decode_one_batch( + params=params, + model=model, + HLG=HLG, + H=H, + batch=batch, + lexicon=lexicon, + sos_id=sos_id, + eos_id=eos_id, + ) + + for lm_scale, hyps in hyps_dict.items(): + this_batch = [] + assert len(hyps) == len(texts) + for hyp_words, ref_text in zip(hyps, texts): + ref_words = ref_text.split() + this_batch.append((ref_words, hyp_words)) + + results[lm_scale].extend(this_batch) + + num_cuts += len(batch["supervisions"]["text"]) + + if batch_idx % 100 == 0: + batch_str = f"{batch_idx}/{num_batches}" + + logging.info( + f"batch {batch_str}, cuts processed until now is {num_cuts}" + ) + return results + + +def save_results( + params: AttributeDict, + test_set_name: str, + results_dict: Dict[str, List[Tuple[List[int], List[int]]]], +): + if params.method == "attention-decoder": + # Set it to False since there are too many logs. + enable_log = False + else: + enable_log = True + test_set_wers = dict() + for key, results in results_dict.items(): + recog_path = params.exp_dir / f"recogs-{test_set_name}-{key}.txt" + store_transcripts(filename=recog_path, texts=results) + if enable_log: + logging.info(f"The transcripts are stored in {recog_path}") + + # The following prints out WERs, per-word error statistics and aligned + # ref/hyp pairs. + errs_filename = params.exp_dir / f"errs-{test_set_name}-{key}.txt" + # we compute CER for aishell dataset. + results_char = [] + for res in results: + results_char.append((list("".join(res[0])), list("".join(res[1])))) + with open(errs_filename, "w") as f: + wer = write_error_stats( + f, f"{test_set_name}-{key}", results_char, enable_log=enable_log + ) + test_set_wers[key] = wer + + if enable_log: + logging.info( + "Wrote detailed error stats to {}".format(errs_filename) + ) + + test_set_wers = sorted(test_set_wers.items(), key=lambda x: x[1]) + errs_info = params.exp_dir / f"cer-summary-{test_set_name}.txt" + with open(errs_info, "w") as f: + print("settings\tCER", file=f) + for key, val in test_set_wers: + print("{}\t{}".format(key, val), file=f) + + s = "\nFor {}, CER of different settings are:\n".format(test_set_name) + note = "\tbest for {}".format(test_set_name) + for key, val in test_set_wers: + s += "{}\t{}{}\n".format(key, val, note) + note = "" + logging.info(s) + + +@torch.no_grad() +def main(): + parser = get_parser() + AishellAsrDataModule.add_arguments(parser) + args = parser.parse_args() + args.exp_dir = Path(args.exp_dir) + args.lang_dir = Path(args.lang_dir) + args.lm_dir = Path(args.lm_dir) + + params = get_params() + params.update(vars(args)) + + setup_logger(f"{params.exp_dir}/log-{params.method}/log-decode") + logging.info("Decoding started") + logging.info(params) + + lexicon = Lexicon(params.lang_dir) + max_token_id = max(lexicon.tokens) + num_classes = max_token_id + 1 # +1 for the blank + + device = torch.device("cpu") + if torch.cuda.is_available(): + device = torch.device("cuda", 0) + + logging.info(f"device: {device}") + + graph_compiler = CharCtcTrainingGraphCompiler( + lexicon=lexicon, + device=device, + sos_token="", + eos_token="", + ) + sos_id = graph_compiler.sos_id + eos_id = graph_compiler.eos_id + + if params.method == "ctc-decoding": + HLG = None + H = k2.ctc_topo( + max_token=max_token_id, + modified=False, + device=device, + ) + else: + H = None + HLG = k2.Fsa.from_dict( + torch.load(f"{params.lang_dir}/HLG.pt", map_location=device) + ) + assert HLG.requires_grad is False + + if not hasattr(HLG, "lm_scores"): + HLG.lm_scores = HLG.scores.clone() + + model = Conformer( + num_features=params.feature_dim, + nhead=params.nhead, + d_model=params.attention_dim, + num_classes=num_classes, + subsampling_factor=params.subsampling_factor, + num_encoder_layers=params.num_encoder_layers, + num_decoder_layers=params.num_decoder_layers, + vgg_frontend=params.vgg_frontend, + use_feat_batchnorm=params.use_feat_batchnorm, + ) + + if params.avg == 1: + load_checkpoint(f"{params.exp_dir}/epoch-{params.epoch}.pt", model) + else: + start = params.epoch - params.avg + 1 + filenames = [] + for i in range(start, params.epoch + 1): + if start >= 0: + filenames.append(f"{params.exp_dir}/epoch-{i}.pt") + logging.info(f"averaging {filenames}") + model.to(device) + model.load_state_dict(average_checkpoints(filenames, device=device)) + + if params.export: + logging.info(f"Export averaged model to {params.exp_dir}/pretrained.pt") + torch.save( + {"model": model.state_dict()}, f"{params.exp_dir}/pretrained.pt" + ) + return + + model.to(device) + model.eval() + num_param = sum([p.numel() for p in model.parameters()]) + logging.info(f"Number of model parameters: {num_param}") + + aishell = AishellAsrDataModule(args) + + test_sets = ["test"] + for test_set, test_dl in zip(test_sets, aishell.test_dataloaders()): + results_dict = decode_dataset( + dl=test_dl, + params=params, + model=model, + HLG=HLG, + H=H, + lexicon=lexicon, + sos_id=sos_id, + eos_id=eos_id, + ) + + save_results( + params=params, test_set_name=test_set, results_dict=results_dict + ) + + logging.info("Done!") + + +torch.set_num_threads(1) +torch.set_num_interop_threads(1) + +if __name__ == "__main__": + main() diff --git a/egs/aishell/ASR/conformer_ctc/pretrained.py b/egs/aishell/ASR/conformer_ctc/pretrained.py new file mode 100755 index 000000000..8657968ec --- /dev/null +++ b/egs/aishell/ASR/conformer_ctc/pretrained.py @@ -0,0 +1,380 @@ +#!/usr/bin/env python3 +# Copyright 2021 Xiaomi Corp. (authors: Fangjun Kuang, +# Wei Kang) +# +# See ../../../../LICENSE for clarification regarding multiple authors +# +# 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 argparse +import logging +import math +from typing import List + +import k2 +import kaldifeat +import torch +import torchaudio +from conformer import Conformer +from torch.nn.utils.rnn import pad_sequence + +from icefall.decode import ( + get_lattice, + one_best_decoding, + rescore_with_attention_decoder, +) +from icefall.utils import AttributeDict, get_env_info, get_texts + + +def get_parser(): + parser = argparse.ArgumentParser( + formatter_class=argparse.ArgumentDefaultsHelpFormatter + ) + + parser.add_argument( + "--checkpoint", + type=str, + required=True, + help="Path to the checkpoint. " + "The checkpoint is assumed to be saved by " + "icefall.checkpoint.save_checkpoint().", + ) + + parser.add_argument( + "--tokens-file", + type=str, + help="Path to tokens.txt" "Used only when method is ctc-decoding", + ) + + parser.add_argument( + "--words-file", + type=str, + help="Path to words.txt" "Used when method is NOT ctc-decoding", + ) + + parser.add_argument( + "--HLG", + type=str, + help="Path to HLG.pt." "Used when method is NOT ctc-decoding", + ) + + parser.add_argument( + "--method", + type=str, + default="1best", + help="""Decoding method. + Possible values are: + (0) ctc-decoding - Use ctc decoding. It maps the tokens ids to tokens + using the token symbol table directly. + (1) 1best - Use the best path as decoding output. Only + the transformer encoder output is used for decoding. + We call it HLG decoding. + (2) attention-decoder - Extract n paths from the rescored + lattice and use the transformer attention decoder for + rescoring. + We call it HLG decoding + n-gram LM rescoring + attention + decoder rescoring. + """, + ) + + parser.add_argument( + "--num-paths", + type=int, + default=100, + help=""" + Used only when method is attention-decoder. + It specifies the size of n-best list.""", + ) + + parser.add_argument( + "--ngram-lm-scale", + type=float, + default=0.3, + help=""" + Used only when method is attention-decoder. + It specifies the scale for n-gram LM scores. + (Note: You need to tune it on a dataset.) + """, + ) + + parser.add_argument( + "--attention-decoder-scale", + type=float, + default=0.9, + help=""" + Used only when method is attention-decoder. + It specifies the scale for attention decoder scores. + (Note: You need to tune it on a dataset.) + """, + ) + + parser.add_argument( + "--nbest-scale", + type=float, + default=0.5, + help=""" + Used only when method is attention-decoder. + It specifies the scale for lattice.scores when + extracting n-best lists. A smaller value results in + more unique number of paths with the risk of missing + the best path. + """, + ) + + parser.add_argument( + "--sos-id", + type=int, + default=1, + help=""" + Used only when method is attention-decoder. + It specifies ID for the SOS token. + """, + ) + + parser.add_argument( + "--eos-id", + type=int, + default=1, + help=""" + Used only when method is attention-decoder. + It specifies ID for the EOS token. + """, + ) + + parser.add_argument( + "--num_classes", + type=int, + default=4336, + help="The Vocab size.", + ) + + parser.add_argument( + "sound_files", + type=str, + nargs="+", + help="The input sound file(s) to transcribe. " + "Supported formats are those supported by torchaudio.load(). " + "For example, wav and flac are supported. " + "The sample rate has to be 16kHz.", + ) + + return parser + + +def get_params() -> AttributeDict: + params = AttributeDict( + { + "sample_rate": 16000, + # parameters for conformer + "subsampling_factor": 4, + "feature_dim": 80, + "nhead": 4, + "attention_dim": 512, + "num_decoder_layers": 6, + "vgg_frontend": False, + "use_feat_batchnorm": True, + # parameters for deocding + "search_beam": 20, + "output_beam": 8, + "min_active_states": 30, + "max_active_states": 10000, + "use_double_scores": True, + "env_info": get_env_info(), + } + ) + return params + + +def read_sound_files( + filenames: List[str], expected_sample_rate: float +) -> List[torch.Tensor]: + """Read a list of sound files into a list 1-D float32 torch tensors. + Args: + filenames: + A list of sound filenames. + expected_sample_rate: + The expected sample rate of the sound files. + Returns: + Return a list of 1-D float32 torch tensors. + """ + ans = [] + for f in filenames: + wave, sample_rate = torchaudio.load(f) + assert sample_rate == expected_sample_rate, ( + f"expected sample rate: {expected_sample_rate}. " + f"Given: {sample_rate}" + ) + # We use only the first channel + ans.append(wave[0]) + return ans + + +def main(): + parser = get_parser() + args = parser.parse_args() + + params = get_params() + params.update(vars(args)) + logging.info(f"{params}") + + if args.method != "attention-decoder": + # to save memory as the attention decoder + # will not be used + params.num_decoder_layers = 0 + + device = torch.device("cpu") + if torch.cuda.is_available(): + device = torch.device("cuda", 0) + + logging.info(f"device: {device}") + + logging.info("Creating model") + model = Conformer( + num_features=params.feature_dim, + nhead=params.nhead, + d_model=params.attention_dim, + num_classes=params.num_classes, + subsampling_factor=params.subsampling_factor, + num_decoder_layers=params.num_decoder_layers, + vgg_frontend=params.vgg_frontend, + use_feat_batchnorm=params.use_feat_batchnorm, + ) + + checkpoint = torch.load(args.checkpoint, map_location="cpu") + model.load_state_dict(checkpoint["model"], strict=False) + model.to(device) + model.eval() + + logging.info("Constructing Fbank computer") + opts = kaldifeat.FbankOptions() + opts.device = device + opts.frame_opts.dither = 0 + opts.frame_opts.snip_edges = False + opts.frame_opts.samp_freq = params.sample_rate + opts.mel_opts.num_bins = params.feature_dim + + fbank = kaldifeat.Fbank(opts) + + logging.info(f"Reading sound files: {params.sound_files}") + waves = read_sound_files( + filenames=params.sound_files, expected_sample_rate=params.sample_rate + ) + waves = [w.to(device) for w in waves] + + logging.info("Decoding started") + features = fbank(waves) + + features = pad_sequence( + features, batch_first=True, padding_value=math.log(1e-10) + ) + + # Note: We don't use key padding mask for attention during decoding + with torch.no_grad(): + nnet_output, memory, memory_key_padding_mask = model(features) + + batch_size = nnet_output.shape[0] + supervision_segments = torch.tensor( + [[i, 0, nnet_output.shape[1]] for i in range(batch_size)], + dtype=torch.int32, + ) + + if params.method == "ctc-decoding": + logging.info("Use CTC decoding") + token_sym_table = k2.SymbolTable.from_file(params.tokens_file) + max_token_id = params.num_classes - 1 + + H = k2.ctc_topo( + max_token=max_token_id, + modified=True, + device=device, + ) + + lattice = get_lattice( + nnet_output=nnet_output, + decoding_graph=H, + supervision_segments=supervision_segments, + search_beam=params.search_beam, + output_beam=params.output_beam, + min_active_states=params.min_active_states, + max_active_states=params.max_active_states, + subsampling_factor=params.subsampling_factor, + ) + + best_path = one_best_decoding( + lattice=lattice, use_double_scores=params.use_double_scores + ) + token_ids = get_texts(best_path) + hyps = [[token_sym_table[i] for i in ids] for ids in token_ids] + elif params.method in ["1best", "attention-decoder"]: + logging.info(f"Loading HLG from {params.HLG}") + HLG = k2.Fsa.from_dict(torch.load(params.HLG, map_location="cpu")) + HLG = HLG.to(device) + if not hasattr(HLG, "lm_scores"): + # For whole-lattice-rescoring and attention-decoder + HLG.lm_scores = HLG.scores.clone() + + lattice = get_lattice( + nnet_output=nnet_output, + decoding_graph=HLG, + supervision_segments=supervision_segments, + search_beam=params.search_beam, + output_beam=params.output_beam, + min_active_states=params.min_active_states, + max_active_states=params.max_active_states, + subsampling_factor=params.subsampling_factor, + ) + + if params.method == "1best": + logging.info("Use HLG decoding") + best_path = one_best_decoding( + lattice=lattice, use_double_scores=params.use_double_scores + ) + elif params.method == "attention-decoder": + logging.info("Use HLG + attention decoder rescoring") + best_path_dict = rescore_with_attention_decoder( + lattice=lattice, + num_paths=params.num_paths, + model=model, + memory=memory, + memory_key_padding_mask=memory_key_padding_mask, + sos_id=params.sos_id, + eos_id=params.eos_id, + nbest_scale=params.nbest_scale, + ngram_lm_scale=params.ngram_lm_scale, + attention_scale=params.attention_decoder_scale, + ) + best_path = next(iter(best_path_dict.values())) + + hyps = get_texts(best_path) + word_sym_table = k2.SymbolTable.from_file(params.words_file) + hyps = [[word_sym_table[i] for i in ids] for ids in hyps] + else: + raise ValueError(f"Unsupported decoding method: {params.method}") + + s = "\n" + for filename, hyp in zip(params.sound_files, hyps): + words = " ".join(hyp) + s += f"{filename}:\n{words}\n\n" + logging.info(s) + + logging.info("Decoding Done") + + +if __name__ == "__main__": + formatter = ( + "%(asctime)s %(levelname)s [%(filename)s:%(lineno)d] %(message)s" + ) + + logging.basicConfig(format=formatter, level=logging.INFO) + main() diff --git a/egs/aishell/ASR/conformer_ctc/subsampling.py b/egs/aishell/ASR/conformer_ctc/subsampling.py new file mode 100644 index 000000000..720ed6c22 --- /dev/null +++ b/egs/aishell/ASR/conformer_ctc/subsampling.py @@ -0,0 +1,161 @@ +# Copyright 2021 Xiaomi Corp. (authors: Fangjun Kuang) +# +# See ../../../../LICENSE for clarification regarding multiple authors +# +# 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 torch +import torch.nn as nn + + +class Conv2dSubsampling(nn.Module): + """Convolutional 2D subsampling (to 1/4 length). + + Convert an input of shape [N, T, idim] to an output + with shape [N, T', odim], where + T' = ((T-1)//2 - 1)//2, which approximates T' == T//4 + + It is based on + https://github.com/espnet/espnet/blob/master/espnet/nets/pytorch_backend/transformer/subsampling.py # noqa + """ + + def __init__(self, idim: int, odim: int) -> None: + """ + Args: + idim: + Input dim. The input shape is [N, T, idim]. + Caution: It requires: T >=7, idim >=7 + odim: + Output dim. The output shape is [N, ((T-1)//2 - 1)//2, odim] + """ + assert idim >= 7 + super().__init__() + self.conv = nn.Sequential( + nn.Conv2d( + in_channels=1, out_channels=odim, kernel_size=3, stride=2 + ), + nn.ReLU(), + nn.Conv2d( + in_channels=odim, out_channels=odim, kernel_size=3, stride=2 + ), + nn.ReLU(), + ) + self.out = nn.Linear(odim * (((idim - 1) // 2 - 1) // 2), odim) + + def forward(self, x: torch.Tensor) -> torch.Tensor: + """Subsample x. + + Args: + x: + Its shape is [N, T, idim]. + + Returns: + Return a tensor of shape [N, ((T-1)//2 - 1)//2, odim] + """ + # On entry, x is [N, T, idim] + x = x.unsqueeze(1) # [N, T, idim] -> [N, 1, T, idim] i.e., [N, C, H, W] + x = self.conv(x) + # Now x is of shape [N, odim, ((T-1)//2 - 1)//2, ((idim-1)//2 - 1)//2] + b, c, t, f = x.size() + x = self.out(x.transpose(1, 2).contiguous().view(b, t, c * f)) + # Now x is of shape [N, ((T-1)//2 - 1))//2, odim] + return x + + +class VggSubsampling(nn.Module): + """Trying to follow the setup described in the following paper: + https://arxiv.org/pdf/1910.09799.pdf + + This paper is not 100% explicit so I am guessing to some extent, + and trying to compare with other VGG implementations. + + Convert an input of shape [N, T, idim] to an output + with shape [N, T', odim], where + T' = ((T-1)//2 - 1)//2, which approximates T' = T//4 + """ + + def __init__(self, idim: int, odim: int) -> None: + """Construct a VggSubsampling object. + + This uses 2 VGG blocks with 2 Conv2d layers each, + subsampling its input by a factor of 4 in the time dimensions. + + Args: + idim: + Input dim. The input shape is [N, T, idim]. + Caution: It requires: T >=7, idim >=7 + odim: + Output dim. The output shape is [N, ((T-1)//2 - 1)//2, odim] + """ + super().__init__() + + cur_channels = 1 + layers = [] + block_dims = [32, 64] + + # The decision to use padding=1 for the 1st convolution, then padding=0 + # for the 2nd and for the max-pooling, and ceil_mode=True, was driven by + # a back-compatibility concern so that the number of frames at the + # output would be equal to: + # (((T-1)//2)-1)//2. + # We can consider changing this by using padding=1 on the + # 2nd convolution, so the num-frames at the output would be T//4. + for block_dim in block_dims: + layers.append( + torch.nn.Conv2d( + in_channels=cur_channels, + out_channels=block_dim, + kernel_size=3, + padding=1, + stride=1, + ) + ) + layers.append(torch.nn.ReLU()) + layers.append( + torch.nn.Conv2d( + in_channels=block_dim, + out_channels=block_dim, + kernel_size=3, + padding=0, + stride=1, + ) + ) + layers.append( + torch.nn.MaxPool2d( + kernel_size=2, stride=2, padding=0, ceil_mode=True + ) + ) + cur_channels = block_dim + + self.layers = nn.Sequential(*layers) + + self.out = nn.Linear( + block_dims[-1] * (((idim - 1) // 2 - 1) // 2), odim + ) + + def forward(self, x: torch.Tensor) -> torch.Tensor: + """Subsample x. + + Args: + x: + Its shape is [N, T, idim]. + + Returns: + Return a tensor of shape [N, ((T-1)//2 - 1)//2, odim] + """ + x = x.unsqueeze(1) + x = self.layers(x) + b, c, t, f = x.size() + x = self.out(x.transpose(1, 2).contiguous().view(b, t, c * f)) + return x diff --git a/egs/aishell/ASR/conformer_ctc/test_subsampling.py b/egs/aishell/ASR/conformer_ctc/test_subsampling.py new file mode 100755 index 000000000..e3361d0c9 --- /dev/null +++ b/egs/aishell/ASR/conformer_ctc/test_subsampling.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 +# Copyright 2021 Xiaomi Corp. (authors: Fangjun Kuang) +# +# See ../../../../LICENSE for clarification regarding multiple authors +# +# 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 subsampling import Conv2dSubsampling +from subsampling import VggSubsampling +import torch + + +def test_conv2d_subsampling(): + N = 3 + odim = 2 + + for T in range(7, 19): + for idim in range(7, 20): + model = Conv2dSubsampling(idim=idim, odim=odim) + x = torch.empty(N, T, idim) + y = model(x) + assert y.shape[0] == N + assert y.shape[1] == ((T - 1) // 2 - 1) // 2 + assert y.shape[2] == odim + + +def test_vgg_subsampling(): + N = 3 + odim = 2 + + for T in range(7, 19): + for idim in range(7, 20): + model = VggSubsampling(idim=idim, odim=odim) + x = torch.empty(N, T, idim) + y = model(x) + assert y.shape[0] == N + assert y.shape[1] == ((T - 1) // 2 - 1) // 2 + assert y.shape[2] == odim diff --git a/egs/aishell/ASR/conformer_ctc/test_transformer.py b/egs/aishell/ASR/conformer_ctc/test_transformer.py new file mode 100644 index 000000000..7c0695683 --- /dev/null +++ b/egs/aishell/ASR/conformer_ctc/test_transformer.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python3 +# Copyright 2021 Xiaomi Corp. (authors: Fangjun Kuang) +# +# See ../../../../LICENSE for clarification regarding multiple authors +# +# 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 torch +from torch.nn.utils.rnn import pad_sequence +from transformer import ( + Transformer, + add_eos, + add_sos, + decoder_padding_mask, + encoder_padding_mask, + generate_square_subsequent_mask, +) + + +def test_encoder_padding_mask(): + supervisions = { + "sequence_idx": torch.tensor([0, 1, 2]), + "start_frame": torch.tensor([0, 0, 0]), + "num_frames": torch.tensor([18, 7, 13]), + } + + max_len = ((18 - 1) // 2 - 1) // 2 + mask = encoder_padding_mask(max_len, supervisions) + expected_mask = torch.tensor( + [ + [False, False, False], # ((18 - 1)//2 - 1)//2 = 3, + [False, True, True], # ((7 - 1)//2 - 1)//2 = 1, + [False, False, True], # ((13 - 1)//2 - 1)//2 = 2, + ] + ) + assert torch.all(torch.eq(mask, expected_mask)) + + +def test_transformer(): + num_features = 40 + num_classes = 87 + model = Transformer(num_features=num_features, num_classes=num_classes) + + N = 31 + + for T in range(7, 30): + x = torch.rand(N, T, num_features) + y, _, _ = model(x) + assert y.shape == (N, (((T - 1) // 2) - 1) // 2, num_classes) + + +def test_generate_square_subsequent_mask(): + s = 5 + mask = generate_square_subsequent_mask(s) + inf = float("inf") + expected_mask = torch.tensor( + [ + [0.0, -inf, -inf, -inf, -inf], + [0.0, 0.0, -inf, -inf, -inf], + [0.0, 0.0, 0.0, -inf, -inf], + [0.0, 0.0, 0.0, 0.0, -inf], + [0.0, 0.0, 0.0, 0.0, 0.0], + ] + ) + assert torch.all(torch.eq(mask, expected_mask)) + + +def test_decoder_padding_mask(): + x = [torch.tensor([1, 2]), torch.tensor([3]), torch.tensor([2, 5, 8])] + y = pad_sequence(x, batch_first=True, padding_value=-1) + mask = decoder_padding_mask(y, ignore_id=-1) + expected_mask = torch.tensor( + [[False, False, True], [False, True, True], [False, False, False]] + ) + assert torch.all(torch.eq(mask, expected_mask)) + + +def test_add_sos(): + x = [[1, 2], [3], [2, 5, 8]] + y = add_sos(x, sos_id=0) + expected_y = [[0, 1, 2], [0, 3], [0, 2, 5, 8]] + assert y == expected_y + + +def test_add_eos(): + x = [[1, 2], [3], [2, 5, 8]] + y = add_eos(x, eos_id=0) + expected_y = [[1, 2, 0], [3, 0], [2, 5, 8, 0]] + assert y == expected_y diff --git a/egs/aishell/ASR/conformer_ctc/train.py b/egs/aishell/ASR/conformer_ctc/train.py new file mode 100755 index 000000000..94367ed4e --- /dev/null +++ b/egs/aishell/ASR/conformer_ctc/train.py @@ -0,0 +1,679 @@ +#!/usr/bin/env python3 +# Copyright 2021 Xiaomi Corp. (authors: Fangjun Kuang +# Wei Kang) +# +# See ../../../../LICENSE for clarification regarding multiple authors +# +# 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 argparse +import logging +from pathlib import Path +from shutil import copyfile +from typing import Optional, Tuple + +import k2 +import torch +import torch.multiprocessing as mp +import torch.nn as nn +from asr_datamodule import AishellAsrDataModule +from conformer import Conformer +from lhotse.utils import fix_random_seed +from torch.nn.parallel import DistributedDataParallel as DDP +from torch.nn.utils import clip_grad_norm_ +from torch.utils.tensorboard import SummaryWriter +from transformer import Noam + +from icefall.char_graph_compiler import CharCtcTrainingGraphCompiler +from icefall.checkpoint import load_checkpoint +from icefall.checkpoint import save_checkpoint as save_checkpoint_impl +from icefall.dist import cleanup_dist, setup_dist +from icefall.lexicon import Lexicon +from icefall.utils import ( + AttributeDict, + MetricsTracker, + encode_supervisions, + get_env_info, + setup_logger, + str2bool, +) + + +def get_parser(): + parser = argparse.ArgumentParser( + formatter_class=argparse.ArgumentDefaultsHelpFormatter + ) + + parser.add_argument( + "--world-size", + type=int, + default=1, + help="Number of GPUs for DDP training.", + ) + + parser.add_argument( + "--master-port", + type=int, + default=12354, + help="Master port to use for DDP training.", + ) + + parser.add_argument( + "--tensorboard", + type=str2bool, + default=True, + help="Should various information be logged in tensorboard.", + ) + + parser.add_argument( + "--num-epochs", + type=int, + default=90, + help="Number of epochs to train.", + ) + + parser.add_argument( + "--start-epoch", + type=int, + default=0, + help="""Resume training from from this epoch. + If it is positive, it will load checkpoint from + conformer_ctc/exp/epoch-{start_epoch-1}.pt + """, + ) + + parser.add_argument( + "--exp-dir", + type=str, + default="conformer_ctc/exp", + help="""The experiment dir. + It specifies the directory where all training related + files, e.g., checkpoints, log, etc, are saved + """, + ) + + parser.add_argument( + "--lang-dir", + type=str, + default="data/lang_char", + help="""The lang dir + It contains language related input files such as + "lexicon.txt" + """, + ) + + parser.add_argument( + "--att-rate", + type=float, + default=0.7, + help="""The attention rate. + The total loss is (1 - att_rate) * ctc_loss + att_rate * att_loss + """, + ) + + return parser + + +def get_params() -> AttributeDict: + """Return a dict containing training parameters. + + All training related parameters that are not passed from the commandline + are saved in the variable `params`. + + Commandline options are merged into `params` after they are parsed, so + you can also access them via `params`. + + Explanation of options saved in `params`: + + - best_valid_loss: Best validation loss so far. It is used to select + the model that has the lowest validation loss. It is + updated during the training. + + - best_train_epoch: It is the epoch that has the best training loss. + + - best_valid_epoch: It is the epoch that has the best validation loss. + + - batch_idx_train: Used to writing statistics to tensorboard. It + contains number of batches trained so far across + epochs. + + - log_interval: Print training loss if batch_idx % log_interval` is 0 + + - reset_interval: Reset statistics if batch_idx % reset_interval is 0 + + - valid_interval: Run validation if batch_idx % valid_interval is 0 + + - beam_size: It is used in k2.ctc_loss + + - reduction: It is used in k2.ctc_loss + + - use_double_scores: It is used in k2.ctc_loss + + - subsampling_factor: The subsampling factor for the model. + + - feature_dim: The model input dim. It has to match the one used + in computing features. + + - attention_dim: Attention dimension. + + - nhead: Number of heads in multi-head attention. + Must satisfy attention_dim // nhead == 0. + + - num_encoder_layers: Number of attention encoder layers. + + - num_decoder_layers: Number of attention decoder layers. + + - use_feat_batchnorm: Whether to do normalization in the input layer. + + - weight_decay: The weight_decay for the optimizer. + + - lr_factor: The lr_factor for the optimizer. + + - warm_step: The warm_step for the optimizer. + """ + params = AttributeDict( + { + "best_train_loss": float("inf"), + "best_valid_loss": float("inf"), + "best_train_epoch": -1, + "best_valid_epoch": -1, + "batch_idx_train": 0, + "log_interval": 10, + "reset_interval": 200, + "valid_interval": 3000, + # parameters for k2.ctc_loss + "beam_size": 10, + "reduction": "sum", + "use_double_scores": True, + # parameters for conformer + "subsampling_factor": 4, + "feature_dim": 80, + "attention_dim": 512, + "nhead": 4, + "num_encoder_layers": 12, + "num_decoder_layers": 6, + "use_feat_batchnorm": True, + # parameters for Noam + "weight_decay": 1e-5, + "lr_factor": 5.0, + "warm_step": 36000, + "env_info": get_env_info(), + } + ) + + return params + + +def load_checkpoint_if_available( + params: AttributeDict, + model: nn.Module, + optimizer: Optional[torch.optim.Optimizer] = None, + scheduler: Optional[torch.optim.lr_scheduler._LRScheduler] = None, +) -> None: + """Load checkpoint from file. + + If params.start_epoch is positive, it will load the checkpoint from + `params.start_epoch - 1`. Otherwise, this function does nothing. + + Apart from loading state dict for `model`, `optimizer` and `scheduler`, + it also updates `best_train_epoch`, `best_train_loss`, `best_valid_epoch`, + and `best_valid_loss` in `params`. + + Args: + params: + The return value of :func:`get_params`. + model: + The training model. + optimizer: + The optimizer that we are using. + scheduler: + The learning rate scheduler we are using. + Returns: + Return None. + """ + if params.start_epoch <= 0: + return + + filename = params.exp_dir / f"epoch-{params.start_epoch-1}.pt" + saved_params = load_checkpoint( + filename, + model=model, + optimizer=optimizer, + scheduler=scheduler, + ) + + keys = [ + "best_train_epoch", + "best_valid_epoch", + "batch_idx_train", + "best_train_loss", + "best_valid_loss", + ] + for k in keys: + params[k] = saved_params[k] + + return saved_params + + +def save_checkpoint( + params: AttributeDict, + model: nn.Module, + optimizer: Optional[torch.optim.Optimizer] = None, + scheduler: Optional[torch.optim.lr_scheduler._LRScheduler] = None, + rank: int = 0, +) -> None: + """Save model, optimizer, scheduler and training stats to file. + + Args: + params: + It is returned by :func:`get_params`. + model: + The training model. + """ + if rank != 0: + return + filename = params.exp_dir / f"epoch-{params.cur_epoch}.pt" + save_checkpoint_impl( + filename=filename, + model=model, + params=params, + optimizer=optimizer, + scheduler=scheduler, + rank=rank, + ) + + if params.best_train_epoch == params.cur_epoch: + best_train_filename = params.exp_dir / "best-train-loss.pt" + copyfile(src=filename, dst=best_train_filename) + + if params.best_valid_epoch == params.cur_epoch: + best_valid_filename = params.exp_dir / "best-valid-loss.pt" + copyfile(src=filename, dst=best_valid_filename) + + +def compute_loss( + params: AttributeDict, + model: nn.Module, + batch: dict, + graph_compiler: CharCtcTrainingGraphCompiler, + is_training: bool, +) -> Tuple[torch.Tensor, MetricsTracker]: + """ + Compute CTC loss given the model and its inputs. + + Args: + params: + Parameters for training. See :func:`get_params`. + model: + The model for training. It is an instance of Conformer in our case. + batch: + A batch of data. See `lhotse.dataset.K2SpeechRecognitionDataset()` + for the content in it. + graph_compiler: + It is used to build a decoding graph from a ctc topo and training + transcript. The training transcript is contained in the given `batch`, + while the ctc topo is built when this compiler is instantiated. + is_training: + True for training. False for validation. When it is True, this + function enables autograd during computation; when it is False, it + disables autograd. + """ + device = graph_compiler.device + feature = batch["inputs"] + # at entry, feature is (N, T, C) + assert feature.ndim == 3 + feature = feature.to(device) + + supervisions = batch["supervisions"] + with torch.set_grad_enabled(is_training): + nnet_output, encoder_memory, memory_mask = model(feature, supervisions) + # nnet_output is (N, T, C) + + # NOTE: We need `encode_supervisions` to sort sequences with + # different duration in decreasing order, required by + # `k2.intersect_dense` called in `k2.ctc_loss` + supervision_segments, texts = encode_supervisions( + supervisions, subsampling_factor=params.subsampling_factor + ) + + token_ids = graph_compiler.texts_to_ids(texts) + + decoding_graph = graph_compiler.compile(token_ids) + + dense_fsa_vec = k2.DenseFsaVec( + nnet_output, + supervision_segments, + allow_truncate=params.subsampling_factor - 1, + ) + + ctc_loss = k2.ctc_loss( + decoding_graph=decoding_graph, + dense_fsa_vec=dense_fsa_vec, + output_beam=params.beam_size, + reduction=params.reduction, + use_double_scores=params.use_double_scores, + ) + + if params.att_rate != 0.0: + with torch.set_grad_enabled(is_training): + mmodel = model.module if hasattr(model, "module") else model + # Note: We need to generate an unsorted version of token_ids + # `encode_supervisions()` called above sorts text, but + # encoder_memory and memory_mask are not sorted, so we + # use an unsorted version `supervisions["text"]` to regenerate + # the token_ids + # + # See https://github.com/k2-fsa/icefall/issues/97 + # for more details + unsorted_token_ids = graph_compiler.texts_to_ids( + supervisions["text"] + ) + att_loss = mmodel.decoder_forward( + encoder_memory, + memory_mask, + token_ids=unsorted_token_ids, + sos_id=graph_compiler.sos_id, + eos_id=graph_compiler.eos_id, + ) + loss = (1.0 - params.att_rate) * ctc_loss + params.att_rate * att_loss + else: + loss = ctc_loss + att_loss = torch.tensor([0]) + + assert loss.requires_grad == is_training + + info = MetricsTracker() + info["frames"] = supervision_segments[:, 2].sum().item() + info["ctc_loss"] = ctc_loss.detach().cpu().item() + if params.att_rate != 0.0: + info["att_loss"] = att_loss.detach().cpu().item() + + info["loss"] = loss.detach().cpu().item() + + return loss, info + + +def compute_validation_loss( + params: AttributeDict, + model: nn.Module, + graph_compiler: CharCtcTrainingGraphCompiler, + valid_dl: torch.utils.data.DataLoader, + world_size: int = 1, +) -> MetricsTracker: + """Run the validation process. The validation loss + is saved in `params.valid_loss`. + """ + model.eval() + + tot_loss = MetricsTracker() + + for batch_idx, batch in enumerate(valid_dl): + loss, loss_info = compute_loss( + params=params, + model=model, + batch=batch, + graph_compiler=graph_compiler, + is_training=False, + ) + assert loss.requires_grad is False + tot_loss = tot_loss + loss_info + + if world_size > 1: + tot_loss.reduce(loss.device) + + loss_value = tot_loss["loss"] / tot_loss["frames"] + if loss_value < params.best_valid_loss: + params.best_valid_epoch = params.cur_epoch + params.best_valid_loss = loss_value + + return tot_loss + + +def train_one_epoch( + params: AttributeDict, + model: nn.Module, + optimizer: torch.optim.Optimizer, + graph_compiler: CharCtcTrainingGraphCompiler, + train_dl: torch.utils.data.DataLoader, + valid_dl: torch.utils.data.DataLoader, + tb_writer: Optional[SummaryWriter] = None, + world_size: int = 1, +) -> None: + """Train the model for one epoch. + + The training loss from the mean of all frames is saved in + `params.train_loss`. It runs the validation process every + `params.valid_interval` batches. + + Args: + params: + It is returned by :func:`get_params`. + model: + The model for training. + optimizer: + The optimizer we are using. + graph_compiler: + It is used to convert transcripts to FSAs. + train_dl: + Dataloader for the training dataset. + valid_dl: + Dataloader for the validation dataset. + tb_writer: + Writer to write log messages to tensorboard. + world_size: + Number of nodes in DDP training. If it is 1, DDP is disabled. + """ + model.train() + + tot_loss = MetricsTracker() + + for batch_idx, batch in enumerate(train_dl): + params.batch_idx_train += 1 + batch_size = len(batch["supervisions"]["text"]) + + loss, loss_info = compute_loss( + params=params, + model=model, + batch=batch, + graph_compiler=graph_compiler, + is_training=True, + ) + + # summary stats + tot_loss = (tot_loss * (1 - 1 / params.reset_interval)) + loss_info + + # NOTE: We use reduction==sum and loss is computed over utterances + # in the batch and there is no normalization to it so far. + + optimizer.zero_grad() + loss.backward() + clip_grad_norm_(model.parameters(), 5.0, 2.0) + optimizer.step() + + if batch_idx % params.log_interval == 0: + logging.info( + f"Epoch {params.cur_epoch}, " + f"batch {batch_idx}, loss[{loss_info}], " + f"tot_loss[{tot_loss}], batch size: {batch_size}" + ) + + if batch_idx % params.log_interval == 0: + + if tb_writer is not None: + loss_info.write_summary( + tb_writer, "train/current_", params.batch_idx_train + ) + tot_loss.write_summary( + tb_writer, "train/tot_", params.batch_idx_train + ) + + if batch_idx > 0 and batch_idx % params.valid_interval == 0: + logging.info("Computing validation loss") + valid_info = compute_validation_loss( + params=params, + model=model, + graph_compiler=graph_compiler, + valid_dl=valid_dl, + world_size=world_size, + ) + model.train() + logging.info(f"Epoch {params.cur_epoch}, validation: {valid_info}") + if tb_writer is not None: + valid_info.write_summary( + tb_writer, "train/valid_", params.batch_idx_train + ) + + loss_value = tot_loss["loss"] / tot_loss["frames"] + params.train_loss = loss_value + if params.train_loss < params.best_train_loss: + params.best_train_epoch = params.cur_epoch + params.best_train_loss = params.train_loss + + +def run(rank, world_size, args): + """ + Args: + rank: + It is a value between 0 and `world_size-1`, which is + passed automatically by `mp.spawn()` in :func:`main`. + The node with rank 0 is responsible for saving checkpoint. + world_size: + Number of GPUs for DDP training. + args: + The return value of get_parser().parse_args() + """ + params = get_params() + params.update(vars(args)) + + fix_random_seed(42) + if world_size > 1: + setup_dist(rank, world_size, params.master_port) + + setup_logger(f"{params.exp_dir}/log/log-train") + logging.info("Training started") + logging.info(params) + + if args.tensorboard and rank == 0: + tb_writer = SummaryWriter(log_dir=f"{params.exp_dir}/tensorboard") + else: + tb_writer = None + + lexicon = Lexicon(params.lang_dir) + max_token_id = max(lexicon.tokens) + num_classes = max_token_id + 1 # +1 for the blank + + device = torch.device("cpu") + if torch.cuda.is_available(): + device = torch.device("cuda", rank) + + graph_compiler = CharCtcTrainingGraphCompiler( + lexicon=lexicon, + device=device, + sos_token="", + eos_token="", + ) + + logging.info("About to create model") + model = Conformer( + num_features=params.feature_dim, + nhead=params.nhead, + d_model=params.attention_dim, + num_classes=num_classes, + subsampling_factor=params.subsampling_factor, + num_encoder_layers=params.num_encoder_layers, + num_decoder_layers=params.num_decoder_layers, + vgg_frontend=False, + use_feat_batchnorm=params.use_feat_batchnorm, + ) + + checkpoints = load_checkpoint_if_available(params=params, model=model) + + model.to(device) + if world_size > 1: + model = DDP(model, device_ids=[rank]) + + optimizer = Noam( + model.parameters(), + model_size=params.attention_dim, + factor=params.lr_factor, + warm_step=params.warm_step, + weight_decay=params.weight_decay, + ) + + if checkpoints: + optimizer.load_state_dict(checkpoints["optimizer"]) + + aishell = AishellAsrDataModule(args) + train_dl = aishell.train_dataloaders() + valid_dl = aishell.valid_dataloaders() + + for epoch in range(params.start_epoch, params.num_epochs): + train_dl.sampler.set_epoch(epoch) + + cur_lr = optimizer._rate + if tb_writer is not None: + tb_writer.add_scalar( + "train/learning_rate", cur_lr, params.batch_idx_train + ) + tb_writer.add_scalar("train/epoch", epoch, params.batch_idx_train) + + if rank == 0: + logging.info("epoch {}, learning rate {}".format(epoch, cur_lr)) + + params.cur_epoch = epoch + + train_one_epoch( + params=params, + model=model, + optimizer=optimizer, + graph_compiler=graph_compiler, + train_dl=train_dl, + valid_dl=valid_dl, + tb_writer=tb_writer, + world_size=world_size, + ) + + save_checkpoint( + params=params, + model=model, + optimizer=optimizer, + rank=rank, + ) + + logging.info("Done!") + + if world_size > 1: + torch.distributed.barrier() + cleanup_dist() + + +def main(): + parser = get_parser() + AishellAsrDataModule.add_arguments(parser) + args = parser.parse_args() + args.exp_dir = Path(args.exp_dir) + args.lang_dir = Path(args.lang_dir) + + world_size = args.world_size + assert world_size >= 1 + if world_size > 1: + mp.spawn(run, args=(world_size, args), nprocs=world_size, join=True) + else: + run(rank=0, world_size=1, args=args) + + +torch.set_num_threads(1) +torch.set_num_interop_threads(1) + +if __name__ == "__main__": + main() diff --git a/egs/aishell/ASR/conformer_ctc/transformer.py b/egs/aishell/ASR/conformer_ctc/transformer.py new file mode 100644 index 000000000..88b10b23d --- /dev/null +++ b/egs/aishell/ASR/conformer_ctc/transformer.py @@ -0,0 +1,998 @@ +# Copyright 2021 University of Chinese Academy of Sciences (author: Han Zhu) +# +# See ../../../../LICENSE for clarification regarding multiple authors +# +# 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 math +from typing import Dict, List, Optional, Tuple + +import torch +import torch.nn as nn +from subsampling import Conv2dSubsampling, VggSubsampling +from torch.nn.utils.rnn import pad_sequence + +# Note: TorchScript requires Dict/List/etc. to be fully typed. +Supervisions = Dict[str, torch.Tensor] + + +class Transformer(nn.Module): + def __init__( + self, + num_features: int, + num_classes: int, + subsampling_factor: int = 4, + d_model: int = 256, + nhead: int = 4, + dim_feedforward: int = 2048, + num_encoder_layers: int = 12, + num_decoder_layers: int = 6, + dropout: float = 0.1, + normalize_before: bool = True, + vgg_frontend: bool = False, + use_feat_batchnorm: bool = False, + ) -> None: + """ + Args: + num_features: + The input dimension of the model. + num_classes: + The output dimension of the model. + subsampling_factor: + Number of output frames is num_in_frames // subsampling_factor. + Currently, subsampling_factor MUST be 4. + d_model: + Attention dimension. + nhead: + Number of heads in multi-head attention. + Must satisfy d_model // nhead == 0. + dim_feedforward: + The output dimension of the feedforward layers in encoder/decoder. + num_encoder_layers: + Number of encoder layers. + num_decoder_layers: + Number of decoder layers. + dropout: + Dropout in encoder/decoder. + normalize_before: + If True, use pre-layer norm; False to use post-layer norm. + vgg_frontend: + True to use vgg style frontend for subsampling. + use_feat_batchnorm: + True to use batchnorm for the input layer. + """ + super().__init__() + self.use_feat_batchnorm = use_feat_batchnorm + if use_feat_batchnorm: + self.feat_batchnorm = nn.BatchNorm1d(num_features) + + self.num_features = num_features + self.num_classes = num_classes + self.subsampling_factor = subsampling_factor + if subsampling_factor != 4: + raise NotImplementedError("Support only 'subsampling_factor=4'.") + + # self.encoder_embed converts the input of shape [N, T, num_classes] + # to the shape [N, T//subsampling_factor, d_model]. + # That is, it does two things simultaneously: + # (1) subsampling: T -> T//subsampling_factor + # (2) embedding: num_classes -> d_model + if vgg_frontend: + self.encoder_embed = VggSubsampling(num_features, d_model) + else: + self.encoder_embed = Conv2dSubsampling(num_features, d_model) + + self.encoder_pos = PositionalEncoding(d_model, dropout) + + encoder_layer = TransformerEncoderLayer( + d_model=d_model, + nhead=nhead, + dim_feedforward=dim_feedforward, + dropout=dropout, + normalize_before=normalize_before, + ) + + if normalize_before: + encoder_norm = nn.LayerNorm(d_model) + else: + encoder_norm = None + + self.encoder = nn.TransformerEncoder( + encoder_layer=encoder_layer, + num_layers=num_encoder_layers, + norm=encoder_norm, + ) + + # TODO(fangjun): remove dropout + self.encoder_output_layer = nn.Sequential( + nn.Dropout(p=dropout), nn.Linear(d_model, num_classes) + ) + + if num_decoder_layers > 0: + self.decoder_num_class = ( + self.num_classes + ) # bpe model already has sos/eos symbol + + self.decoder_embed = nn.Embedding( + num_embeddings=self.decoder_num_class, embedding_dim=d_model + ) + self.decoder_pos = PositionalEncoding(d_model, dropout) + + decoder_layer = TransformerDecoderLayer( + d_model=d_model, + nhead=nhead, + dim_feedforward=dim_feedforward, + dropout=dropout, + normalize_before=normalize_before, + ) + + if normalize_before: + decoder_norm = nn.LayerNorm(d_model) + else: + decoder_norm = None + + self.decoder = nn.TransformerDecoder( + decoder_layer=decoder_layer, + num_layers=num_decoder_layers, + norm=decoder_norm, + ) + + self.decoder_output_layer = torch.nn.Linear( + d_model, self.decoder_num_class + ) + + self.decoder_criterion = LabelSmoothingLoss(self.decoder_num_class) + else: + self.decoder_criterion = None + + def forward( + self, x: torch.Tensor, supervision: Optional[Supervisions] = None + ) -> Tuple[torch.Tensor, torch.Tensor, Optional[torch.Tensor]]: + """ + Args: + x: + The input tensor. Its shape is [N, T, C]. + supervision: + Supervision in lhotse format. + See https://github.com/lhotse-speech/lhotse/blob/master/lhotse/dataset/speech_recognition.py#L32 # noqa + (CAUTION: It contains length information, i.e., start and number of + frames, before subsampling) + + Returns: + Return a tuple containing 3 tensors: + - CTC output for ctc decoding. Its shape is [N, T, C] + - Encoder output with shape [T, N, C]. It can be used as key and + value for the decoder. + - Encoder output padding mask. It can be used as + memory_key_padding_mask for the decoder. Its shape is [N, T]. + It is None if `supervision` is None. + """ + if self.use_feat_batchnorm: + x = x.permute(0, 2, 1) # [N, T, C] -> [N, C, T] + x = self.feat_batchnorm(x) + x = x.permute(0, 2, 1) # [N, C, T] -> [N, T, C] + encoder_memory, memory_key_padding_mask = self.run_encoder( + x, supervision + ) + x = self.ctc_output(encoder_memory) + return x, encoder_memory, memory_key_padding_mask + + def run_encoder( + self, x: torch.Tensor, supervisions: Optional[Supervisions] = None + ) -> Tuple[torch.Tensor, Optional[torch.Tensor]]: + """Run the transformer encoder. + + Args: + x: + The model input. Its shape is [N, T, C]. + supervisions: + Supervision in lhotse format. + See https://github.com/lhotse-speech/lhotse/blob/master/lhotse/dataset/speech_recognition.py#L32 # noqa + CAUTION: It contains length information, i.e., start and number of + frames, before subsampling + It is read directly from the batch, without any sorting. It is used + to compute the encoder padding mask, which is used as memory key + padding mask for the decoder. + Returns: + Return a tuple with two tensors: + - The encoder output, with shape [T, N, C] + - encoder padding mask, with shape [N, T]. + The mask is None if `supervisions` is None. + It is used as memory key padding mask in the decoder. + """ + x = self.encoder_embed(x) + x = self.encoder_pos(x) + x = x.permute(1, 0, 2) # (N, T, C) -> (T, N, C) + mask = encoder_padding_mask(x.size(0), supervisions) + mask = mask.to(x.device) if mask is not None else None + x = self.encoder(x, src_key_padding_mask=mask) # (T, N, C) + + return x, mask + + def ctc_output(self, x: torch.Tensor) -> torch.Tensor: + """ + Args: + x: + The output tensor from the transformer encoder. + Its shape is [T, N, C] + + Returns: + Return a tensor that can be used for CTC decoding. + Its shape is [N, T, C] + """ + x = self.encoder_output_layer(x) + x = x.permute(1, 0, 2) # (T, N, C) ->(N, T, C) + x = nn.functional.log_softmax(x, dim=-1) # (N, T, C) + return x + + def decoder_forward( + self, + memory: torch.Tensor, + memory_key_padding_mask: torch.Tensor, + token_ids: List[List[int]], + sos_id: int, + eos_id: int, + ) -> torch.Tensor: + """ + Args: + memory: + It's the output of the encoder with shape [T, N, C] + memory_key_padding_mask: + The padding mask from the encoder. + token_ids: + A list-of-list IDs. Each sublist contains IDs for an utterance. + The IDs can be either phone IDs or word piece IDs. + sos_id: + sos token id + eos_id: + eos token id + + Returns: + A scalar, the **sum** of label smoothing loss over utterances + in the batch without any normalization. + """ + ys_in = add_sos(token_ids, sos_id=sos_id) + ys_in = [torch.tensor(y) for y in ys_in] + ys_in_pad = pad_sequence(ys_in, batch_first=True, padding_value=eos_id) + + ys_out = add_eos(token_ids, eos_id=eos_id) + ys_out = [torch.tensor(y) for y in ys_out] + ys_out_pad = pad_sequence(ys_out, batch_first=True, padding_value=-1) + + device = memory.device + ys_in_pad = ys_in_pad.to(device) + ys_out_pad = ys_out_pad.to(device) + + tgt_mask = generate_square_subsequent_mask(ys_in_pad.shape[-1]).to( + device + ) + + tgt_key_padding_mask = decoder_padding_mask(ys_in_pad, ignore_id=eos_id) + # TODO: Use length information to create the decoder padding mask + # We set the first column to False since the first column in ys_in_pad + # contains sos_id, which is the same as eos_id in our current setting. + tgt_key_padding_mask[:, 0] = False + + tgt = self.decoder_embed(ys_in_pad) # (N, T) -> (N, T, C) + tgt = self.decoder_pos(tgt) + tgt = tgt.permute(1, 0, 2) # (N, T, C) -> (T, N, C) + pred_pad = self.decoder( + tgt=tgt, + memory=memory, + tgt_mask=tgt_mask, + tgt_key_padding_mask=tgt_key_padding_mask, + memory_key_padding_mask=memory_key_padding_mask, + ) # (T, N, C) + pred_pad = pred_pad.permute(1, 0, 2) # (T, N, C) -> (N, T, C) + pred_pad = self.decoder_output_layer(pred_pad) # (N, T, C) + + decoder_loss = self.decoder_criterion(pred_pad, ys_out_pad) + + return decoder_loss + + def decoder_nll( + self, + memory: torch.Tensor, + memory_key_padding_mask: torch.Tensor, + token_ids: List[List[int]], + sos_id: int, + eos_id: int, + ) -> torch.Tensor: + """ + Args: + memory: + It's the output of the encoder with shape [T, N, C] + memory_key_padding_mask: + The padding mask from the encoder. + token_ids: + A list-of-list IDs (e.g., word piece IDs). + Each sublist represents an utterance. + sos_id: + The token ID for SOS. + eos_id: + The token ID for EOS. + Returns: + A 2-D tensor of shape (len(token_ids), max_token_length) + representing the cross entropy loss (i.e., negative log-likelihood). + """ + # The common part between this function and decoder_forward could be + # extracted as a separate function. + + ys_in = add_sos(token_ids, sos_id=sos_id) + ys_in = [torch.tensor(y) for y in ys_in] + ys_in_pad = pad_sequence(ys_in, batch_first=True, padding_value=eos_id) + + ys_out = add_eos(token_ids, eos_id=eos_id) + ys_out = [torch.tensor(y) for y in ys_out] + ys_out_pad = pad_sequence(ys_out, batch_first=True, padding_value=-1) + + device = memory.device + ys_in_pad = ys_in_pad.to(device, dtype=torch.int64) + ys_out_pad = ys_out_pad.to(device, dtype=torch.int64) + + tgt_mask = generate_square_subsequent_mask(ys_in_pad.shape[-1]).to( + device + ) + + tgt_key_padding_mask = decoder_padding_mask(ys_in_pad, ignore_id=eos_id) + # TODO: Use length information to create the decoder padding mask + # We set the first column to False since the first column in ys_in_pad + # contains sos_id, which is the same as eos_id in our current setting. + tgt_key_padding_mask[:, 0] = False + + tgt = self.decoder_embed(ys_in_pad) # (B, T) -> (B, T, F) + tgt = self.decoder_pos(tgt) + tgt = tgt.permute(1, 0, 2) # (B, T, F) -> (T, B, F) + pred_pad = self.decoder( + tgt=tgt, + memory=memory, + tgt_mask=tgt_mask, + tgt_key_padding_mask=tgt_key_padding_mask, + memory_key_padding_mask=memory_key_padding_mask, + ) # (T, B, F) + pred_pad = pred_pad.permute(1, 0, 2) # (T, B, F) -> (B, T, F) + pred_pad = self.decoder_output_layer(pred_pad) # (B, T, F) + # nll: negative log-likelihood + nll = torch.nn.functional.cross_entropy( + pred_pad.view(-1, self.decoder_num_class), + ys_out_pad.view(-1), + ignore_index=-1, + reduction="none", + ) + + nll = nll.view(pred_pad.shape[0], -1) + + return nll + + +class TransformerEncoderLayer(nn.Module): + """ + Modified from torch.nn.TransformerEncoderLayer. + Add support of normalize_before, + i.e., use layer_norm before the first block. + + Args: + d_model: + the number of expected features in the input (required). + nhead: + the number of heads in the multiheadattention models (required). + dim_feedforward: + the dimension of the feedforward network model (default=2048). + dropout: + the dropout value (default=0.1). + activation: + the activation function of intermediate layer, relu or + gelu (default=relu). + normalize_before: + whether to use layer_norm before the first block. + + Examples:: + >>> encoder_layer = TransformerEncoderLayer(d_model=512, nhead=8) + >>> src = torch.rand(10, 32, 512) + >>> out = encoder_layer(src) + """ + + def __init__( + self, + d_model: int, + nhead: int, + dim_feedforward: int = 2048, + dropout: float = 0.1, + activation: str = "relu", + normalize_before: bool = True, + ) -> None: + super(TransformerEncoderLayer, self).__init__() + self.self_attn = nn.MultiheadAttention(d_model, nhead, dropout=0.0) + # Implementation of Feedforward model + self.linear1 = nn.Linear(d_model, dim_feedforward) + self.dropout = nn.Dropout(dropout) + self.linear2 = nn.Linear(dim_feedforward, d_model) + + self.norm1 = nn.LayerNorm(d_model) + self.norm2 = nn.LayerNorm(d_model) + self.dropout1 = nn.Dropout(dropout) + self.dropout2 = nn.Dropout(dropout) + + self.activation = _get_activation_fn(activation) + + self.normalize_before = normalize_before + + def __setstate__(self, state): + if "activation" not in state: + state["activation"] = nn.functional.relu + super(TransformerEncoderLayer, self).__setstate__(state) + + def forward( + self, + src: torch.Tensor, + src_mask: Optional[torch.Tensor] = None, + src_key_padding_mask: Optional[torch.Tensor] = None, + ) -> torch.Tensor: + """ + Pass the input through the encoder layer. + + Args: + src: the sequence to the encoder layer (required). + src_mask: the mask for the src sequence (optional). + src_key_padding_mask: the mask for the src keys per batch (optional) + + Shape: + src: (S, N, E). + src_mask: (S, S). + src_key_padding_mask: (N, S). + S is the source sequence length, T is the target sequence length, + N is the batch size, E is the feature number + """ + residual = src + if self.normalize_before: + src = self.norm1(src) + src2 = self.self_attn( + src, + src, + src, + attn_mask=src_mask, + key_padding_mask=src_key_padding_mask, + )[0] + src = residual + self.dropout1(src2) + if not self.normalize_before: + src = self.norm1(src) + + residual = src + if self.normalize_before: + src = self.norm2(src) + src2 = self.linear2(self.dropout(self.activation(self.linear1(src)))) + src = residual + self.dropout2(src2) + if not self.normalize_before: + src = self.norm2(src) + return src + + +class TransformerDecoderLayer(nn.Module): + """ + Modified from torch.nn.TransformerDecoderLayer. + Add support of normalize_before, + i.e., use layer_norm before the first block. + + Args: + d_model: + the number of expected features in the input (required). + nhead: + the number of heads in the multiheadattention models (required). + dim_feedforward: + the dimension of the feedforward network model (default=2048). + dropout: + the dropout value (default=0.1). + activation: + the activation function of intermediate layer, relu or + gelu (default=relu). + + Examples:: + >>> decoder_layer = nn.TransformerDecoderLayer(d_model=512, nhead=8) + >>> memory = torch.rand(10, 32, 512) + >>> tgt = torch.rand(20, 32, 512) + >>> out = decoder_layer(tgt, memory) + """ + + def __init__( + self, + d_model: int, + nhead: int, + dim_feedforward: int = 2048, + dropout: float = 0.1, + activation: str = "relu", + normalize_before: bool = True, + ) -> None: + super(TransformerDecoderLayer, self).__init__() + self.self_attn = nn.MultiheadAttention(d_model, nhead, dropout=0.0) + self.src_attn = nn.MultiheadAttention(d_model, nhead, dropout=0.0) + # Implementation of Feedforward model + self.linear1 = nn.Linear(d_model, dim_feedforward) + self.dropout = nn.Dropout(dropout) + self.linear2 = nn.Linear(dim_feedforward, d_model) + + self.norm1 = nn.LayerNorm(d_model) + self.norm2 = nn.LayerNorm(d_model) + self.norm3 = nn.LayerNorm(d_model) + self.dropout1 = nn.Dropout(dropout) + self.dropout2 = nn.Dropout(dropout) + self.dropout3 = nn.Dropout(dropout) + + self.activation = _get_activation_fn(activation) + + self.normalize_before = normalize_before + + def __setstate__(self, state): + if "activation" not in state: + state["activation"] = nn.functional.relu + super(TransformerDecoderLayer, self).__setstate__(state) + + def forward( + self, + tgt: torch.Tensor, + memory: torch.Tensor, + tgt_mask: Optional[torch.Tensor] = None, + memory_mask: Optional[torch.Tensor] = None, + tgt_key_padding_mask: Optional[torch.Tensor] = None, + memory_key_padding_mask: Optional[torch.Tensor] = None, + ) -> torch.Tensor: + """Pass the inputs (and mask) through the decoder layer. + + Args: + tgt: + the sequence to the decoder layer (required). + memory: + the sequence from the last layer of the encoder (required). + tgt_mask: + the mask for the tgt sequence (optional). + memory_mask: + the mask for the memory sequence (optional). + tgt_key_padding_mask: + the mask for the tgt keys per batch (optional). + memory_key_padding_mask: + the mask for the memory keys per batch (optional). + + Shape: + tgt: (T, N, E). + memory: (S, N, E). + tgt_mask: (T, T). + memory_mask: (T, S). + tgt_key_padding_mask: (N, T). + memory_key_padding_mask: (N, S). + S is the source sequence length, T is the target sequence length, + N is the batch size, E is the feature number + """ + residual = tgt + if self.normalize_before: + tgt = self.norm1(tgt) + tgt2 = self.self_attn( + tgt, + tgt, + tgt, + attn_mask=tgt_mask, + key_padding_mask=tgt_key_padding_mask, + )[0] + tgt = residual + self.dropout1(tgt2) + if not self.normalize_before: + tgt = self.norm1(tgt) + + residual = tgt + if self.normalize_before: + tgt = self.norm2(tgt) + tgt2 = self.src_attn( + tgt, + memory, + memory, + attn_mask=memory_mask, + key_padding_mask=memory_key_padding_mask, + )[0] + tgt = residual + self.dropout2(tgt2) + if not self.normalize_before: + tgt = self.norm2(tgt) + + residual = tgt + if self.normalize_before: + tgt = self.norm3(tgt) + tgt2 = self.linear2(self.dropout(self.activation(self.linear1(tgt)))) + tgt = residual + self.dropout3(tgt2) + if not self.normalize_before: + tgt = self.norm3(tgt) + return tgt + + +def _get_activation_fn(activation: str): + if activation == "relu": + return nn.functional.relu + elif activation == "gelu": + return nn.functional.gelu + + raise RuntimeError( + "activation should be relu/gelu, not {}".format(activation) + ) + + +class PositionalEncoding(nn.Module): + """This class implements the positional encoding + proposed in the following paper: + + - Attention Is All You Need: https://arxiv.org/pdf/1706.03762.pdf + + PE(pos, 2i) = sin(pos / (10000^(2i/d_modle)) + PE(pos, 2i+1) = cos(pos / (10000^(2i/d_modle)) + + Note:: + + 1 / (10000^(2i/d_model)) = exp(-log(10000^(2i/d_model))) + = exp(-1* 2i / d_model * log(100000)) + = exp(2i * -(log(10000) / d_model)) + """ + + def __init__(self, d_model: int, dropout: float = 0.1) -> None: + """ + Args: + d_model: + Embedding dimension. + dropout: + Dropout probability to be applied to the output of this module. + """ + super().__init__() + self.d_model = d_model + self.xscale = math.sqrt(self.d_model) + self.dropout = nn.Dropout(p=dropout) + self.pe = None + + def extend_pe(self, x: torch.Tensor) -> None: + """Extend the time t in the positional encoding if required. + + The shape of `self.pe` is [1, T1, d_model]. The shape of the input x + is [N, T, d_model]. If T > T1, then we change the shape of self.pe + to [N, T, d_model]. Otherwise, nothing is done. + + Args: + x: + It is a tensor of shape [N, T, C]. + Returns: + Return None. + """ + if self.pe is not None: + if self.pe.size(1) >= x.size(1): + if self.pe.dtype != x.dtype or self.pe.device != x.device: + self.pe = self.pe.to(dtype=x.dtype, device=x.device) + return + pe = torch.zeros(x.size(1), self.d_model, dtype=torch.float32) + position = torch.arange(0, x.size(1), dtype=torch.float32).unsqueeze(1) + div_term = torch.exp( + torch.arange(0, self.d_model, 2, dtype=torch.float32) + * -(math.log(10000.0) / self.d_model) + ) + pe[:, 0::2] = torch.sin(position * div_term) + pe[:, 1::2] = torch.cos(position * div_term) + pe = pe.unsqueeze(0) + # Now pe is of shape [1, T, d_model], where T is x.size(1) + self.pe = pe.to(device=x.device, dtype=x.dtype) + + def forward(self, x: torch.Tensor) -> torch.Tensor: + """ + Add positional encoding. + + Args: + x: + Its shape is [N, T, C] + + Returns: + Return a tensor of shape [N, T, C] + """ + self.extend_pe(x) + x = x * self.xscale + self.pe[:, : x.size(1), :] + return self.dropout(x) + + +class Noam(object): + """ + Implements Noam optimizer. + + Proposed in + "Attention Is All You Need", https://arxiv.org/pdf/1706.03762.pdf + + Modified from + https://github.com/espnet/espnet/blob/master/espnet/nets/pytorch_backend/transformer/optimizer.py # noqa + + Args: + params: + iterable of parameters to optimize or dicts defining parameter groups + model_size: + attention dimension of the transformer model + factor: + learning rate factor + warm_step: + warmup steps + """ + + def __init__( + self, + params, + model_size: int = 256, + factor: float = 10.0, + warm_step: int = 25000, + weight_decay=0, + ) -> None: + """Construct an Noam object.""" + self.optimizer = torch.optim.Adam( + params, lr=0, betas=(0.9, 0.98), eps=1e-9, weight_decay=weight_decay + ) + self._step = 0 + self.warmup = warm_step + self.factor = factor + self.model_size = model_size + self._rate = 0 + + @property + def param_groups(self): + """Return param_groups.""" + return self.optimizer.param_groups + + def step(self): + """Update parameters and rate.""" + self._step += 1 + rate = self.rate() + for p in self.optimizer.param_groups: + p["lr"] = rate + self._rate = rate + self.optimizer.step() + + def rate(self, step=None): + """Implement `lrate` above.""" + if step is None: + step = self._step + return ( + self.factor + * self.model_size ** (-0.5) + * min(step ** (-0.5), step * self.warmup ** (-1.5)) + ) + + def zero_grad(self): + """Reset gradient.""" + self.optimizer.zero_grad() + + def state_dict(self): + """Return state_dict.""" + return { + "_step": self._step, + "warmup": self.warmup, + "factor": self.factor, + "model_size": self.model_size, + "_rate": self._rate, + "optimizer": self.optimizer.state_dict(), + } + + def load_state_dict(self, state_dict): + """Load state_dict.""" + for key, value in state_dict.items(): + if key == "optimizer": + self.optimizer.load_state_dict(state_dict["optimizer"]) + else: + setattr(self, key, value) + + +class LabelSmoothingLoss(nn.Module): + """ + Label-smoothing loss. KL-divergence between + q_{smoothed ground truth prob.}(w) + and p_{prob. computed by model}(w) is minimized. + Modified from + https://github.com/espnet/espnet/blob/master/espnet/nets/pytorch_backend/transformer/label_smoothing_loss.py # noqa + + Args: + size: the number of class + padding_idx: padding_idx: ignored class id + smoothing: smoothing rate (0.0 means the conventional CE) + normalize_length: normalize loss by sequence length if True + criterion: loss function to be smoothed + """ + + def __init__( + self, + size: int, + padding_idx: int = -1, + smoothing: float = 0.1, + normalize_length: bool = False, + criterion: nn.Module = nn.KLDivLoss(reduction="none"), + ) -> None: + """Construct an LabelSmoothingLoss object.""" + super(LabelSmoothingLoss, self).__init__() + self.criterion = criterion + self.padding_idx = padding_idx + assert 0.0 < smoothing <= 1.0 + self.confidence = 1.0 - smoothing + self.smoothing = smoothing + self.size = size + self.true_dist = None + self.normalize_length = normalize_length + + def forward(self, x: torch.Tensor, target: torch.Tensor) -> torch.Tensor: + """ + Compute loss between x and target. + + Args: + x: + prediction of dimension + (batch_size, input_length, number_of_classes). + target: + target masked with self.padding_id of + dimension (batch_size, input_length). + + Returns: + A scalar tensor containing the loss without normalization. + """ + assert x.size(2) == self.size + # batch_size = x.size(0) + x = x.view(-1, self.size) + target = target.view(-1) + with torch.no_grad(): + true_dist = x.clone() + true_dist.fill_(self.smoothing / (self.size - 1)) + ignore = target == self.padding_idx # (B,) + total = len(target) - ignore.sum().item() + target = target.masked_fill(ignore, 0) # avoid -1 index + true_dist.scatter_(1, target.unsqueeze(1), self.confidence) + kl = self.criterion(torch.log_softmax(x, dim=1), true_dist) + # denom = total if self.normalize_length else batch_size + denom = total if self.normalize_length else 1 + return kl.masked_fill(ignore.unsqueeze(1), 0).sum() / denom + + +def encoder_padding_mask( + max_len: int, supervisions: Optional[Supervisions] = None +) -> Optional[torch.Tensor]: + """Make mask tensor containing indexes of padded part. + + TODO:: + This function **assumes** that the model uses + a subsampling factor of 4. We should remove that + assumption later. + + Args: + max_len: + Maximum length of input features. + CAUTION: It is the length after subsampling. + supervisions: + Supervision in lhotse format. + See https://github.com/lhotse-speech/lhotse/blob/master/lhotse/dataset/speech_recognition.py#L32 # noqa + (CAUTION: It contains length information, i.e., start and number of + frames, before subsampling) + + Returns: + Tensor: Mask tensor of dimension (batch_size, input_length), + True denote the masked indices. + """ + if supervisions is None: + return None + + supervision_segments = torch.stack( + ( + supervisions["sequence_idx"], + supervisions["start_frame"], + supervisions["num_frames"], + ), + 1, + ).to(torch.int32) + + lengths = [ + 0 for _ in range(int(supervision_segments[:, 0].max().item()) + 1) + ] + for idx in range(supervision_segments.size(0)): + # Note: TorchScript doesn't allow to unpack tensors as tuples + sequence_idx = supervision_segments[idx, 0].item() + start_frame = supervision_segments[idx, 1].item() + num_frames = supervision_segments[idx, 2].item() + lengths[sequence_idx] = start_frame + num_frames + + lengths = [((i - 1) // 2 - 1) // 2 for i in lengths] + bs = int(len(lengths)) + seq_range = torch.arange(0, max_len, dtype=torch.int64) + seq_range_expand = seq_range.unsqueeze(0).expand(bs, max_len) + # Note: TorchScript doesn't implement Tensor.new() + seq_length_expand = torch.tensor( + lengths, device=seq_range_expand.device, dtype=seq_range_expand.dtype + ).unsqueeze(-1) + mask = seq_range_expand >= seq_length_expand + + return mask + + +def decoder_padding_mask( + ys_pad: torch.Tensor, ignore_id: int = -1 +) -> torch.Tensor: + """Generate a length mask for input. + + The masked position are filled with True, + Unmasked positions are filled with False. + + Args: + ys_pad: + padded tensor of dimension (batch_size, input_length). + ignore_id: + the ignored number (the padding number) in ys_pad + + Returns: + Tensor: + a bool tensor of the same shape as the input tensor. + """ + ys_mask = ys_pad == ignore_id + return ys_mask + + +def generate_square_subsequent_mask(sz: int) -> torch.Tensor: + """Generate a square mask for the sequence. The masked positions are + filled with float('-inf'). Unmasked positions are filled with float(0.0). + The mask can be used for masked self-attention. + + For instance, if sz is 3, it returns:: + + tensor([[0., -inf, -inf], + [0., 0., -inf], + [0., 0., 0]]) + + Args: + sz: mask size + + Returns: + A square mask of dimension (sz, sz) + """ + mask = (torch.triu(torch.ones(sz, sz)) == 1).transpose(0, 1) + mask = ( + mask.float() + .masked_fill(mask == 0, float("-inf")) + .masked_fill(mask == 1, float(0.0)) + ) + return mask + + +def add_sos(token_ids: List[List[int]], sos_id: int) -> List[List[int]]: + """Prepend sos_id to each utterance. + + Args: + token_ids: + A list-of-list of token IDs. Each sublist contains + token IDs (e.g., word piece IDs) of an utterance. + sos_id: + The ID of the SOS token. + + Return: + Return a new list-of-list, where each sublist starts + with SOS ID. + """ + ans = [] + for utt in token_ids: + ans.append([sos_id] + utt) + return ans + + +def add_eos(token_ids: List[List[int]], eos_id: int) -> List[List[int]]: + """Append eos_id to each utterance. + + Args: + token_ids: + A list-of-list of token IDs. Each sublist contains + token IDs (e.g., word piece IDs) of an utterance. + eos_id: + The ID of the EOS token. + + Return: + Return a new list-of-list, where each sublist ends + with EOS ID. + """ + ans = [] + for utt in token_ids: + ans.append(utt + [eos_id]) + return ans diff --git a/egs/aishell/ASR/local/__init__.py b/egs/aishell/ASR/local/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/egs/aishell/ASR/local/compile_hlg.py b/egs/aishell/ASR/local/compile_hlg.py new file mode 100755 index 000000000..407fb7d88 --- /dev/null +++ b/egs/aishell/ASR/local/compile_hlg.py @@ -0,0 +1,156 @@ +#!/usr/bin/env python3 +# Copyright 2021 Xiaomi Corp. (authors: Fangjun Kuang) +# +# See ../../../../LICENSE for clarification regarding multiple authors +# +# 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. + + +""" +This script takes as input lang_dir and generates HLG from + + - H, the ctc topology, built from tokens contained in lang_dir/lexicon.txt + - L, the lexicon, built from lang_dir/L_disambig.pt + + Caution: We use a lexicon that contains disambiguation symbols + + - G, the LM, built from data/lm/G_3_gram.fst.txt + +The generated HLG is saved in $lang_dir/HLG.pt +""" +import argparse +import logging +from pathlib import Path + +import k2 +import torch + +from icefall.lexicon import Lexicon + + +def get_args(): + parser = argparse.ArgumentParser() + parser.add_argument( + "--lang-dir", + type=str, + help="""Input and output directory. + """, + ) + + return parser.parse_args() + + +def compile_HLG(lang_dir: str) -> k2.Fsa: + """ + Args: + lang_dir: + The language directory, e.g., data/lang_phone or data/lang_bpe_5000. + + Return: + An FSA representing HLG. + """ + lexicon = Lexicon(lang_dir) + max_token_id = max(lexicon.tokens) + logging.info(f"Building ctc_topo. max_token_id: {max_token_id}") + H = k2.ctc_topo(max_token_id) + L = k2.Fsa.from_dict(torch.load(f"{lang_dir}/L_disambig.pt")) + + if Path("data/lm/G_3_gram.pt").is_file(): + logging.info("Loading pre-compiled G_3_gram") + d = torch.load("data/lm/G_3_gram.pt") + G = k2.Fsa.from_dict(d) + else: + logging.info("Loading G_3_gram.fst.txt") + with open("data/lm/G_3_gram.fst.txt") as f: + G = k2.Fsa.from_openfst(f.read(), acceptor=False) + torch.save(G.as_dict(), "data/lm/G_3_gram.pt") + + first_token_disambig_id = lexicon.token_table["#0"] + first_word_disambig_id = lexicon.word_table["#0"] + + L = k2.arc_sort(L) + G = k2.arc_sort(G) + + logging.info("Intersecting L and G") + LG = k2.compose(L, G) + logging.info(f"LG shape: {LG.shape}") + + logging.info("Connecting LG") + LG = k2.connect(LG) + logging.info(f"LG shape after k2.connect: {LG.shape}") + + logging.info(type(LG.aux_labels)) + logging.info("Determinizing LG") + + LG = k2.determinize(LG) + logging.info(type(LG.aux_labels)) + + logging.info("Connecting LG after k2.determinize") + LG = k2.connect(LG) + + logging.info("Removing disambiguation symbols on LG") + + LG.labels[LG.labels >= first_token_disambig_id] = 0 + + assert isinstance(LG.aux_labels, k2.RaggedTensor) + LG.aux_labels.data[LG.aux_labels.data >= first_word_disambig_id] = 0 + + LG = k2.remove_epsilon(LG) + logging.info(f"LG shape after k2.remove_epsilon: {LG.shape}") + + LG = k2.connect(LG) + LG.aux_labels = LG.aux_labels.remove_values_eq(0) + + logging.info("Arc sorting LG") + LG = k2.arc_sort(LG) + + logging.info("Composing H and LG") + # CAUTION: The name of the inner_labels is fixed + # to `tokens`. If you want to change it, please + # also change other places in icefall that are using + # it. + HLG = k2.compose(H, LG, inner_labels="tokens") + + logging.info("Connecting LG") + HLG = k2.connect(HLG) + + logging.info("Arc sorting LG") + HLG = k2.arc_sort(HLG) + logging.info(f"HLG.shape: {HLG.shape}") + + return HLG + + +def main(): + args = get_args() + lang_dir = Path(args.lang_dir) + + if (lang_dir / "HLG.pt").is_file(): + logging.info(f"{lang_dir}/HLG.pt already exists - skipping") + return + + logging.info(f"Processing {lang_dir}") + + HLG = compile_HLG(lang_dir) + logging.info(f"Saving HLG.pt to {lang_dir}") + torch.save(HLG.as_dict(), f"{lang_dir}/HLG.pt") + + +if __name__ == "__main__": + formatter = ( + "%(asctime)s %(levelname)s [%(filename)s:%(lineno)d] %(message)s" + ) + + logging.basicConfig(format=formatter, level=logging.INFO) + + main() diff --git a/egs/aishell/ASR/local/compute_fbank_aishell.py b/egs/aishell/ASR/local/compute_fbank_aishell.py new file mode 100755 index 000000000..b3b9e7681 --- /dev/null +++ b/egs/aishell/ASR/local/compute_fbank_aishell.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python3 +# Copyright 2021 Xiaomi Corp. (authors: Fangjun Kuang) +# +# See ../../../../LICENSE for clarification regarding multiple authors +# +# 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. + + +""" +This file computes fbank features of the aishell dataset. +It looks for manifests in the directory data/manifests. + +The generated fbank features are saved in data/fbank. +""" + +import argparse +import logging +import os +from pathlib import Path + +import torch +from lhotse import CutSet, Fbank, FbankConfig, LilcomHdf5Writer +from lhotse.recipes.utils import read_manifests_if_cached + +from icefall.utils import get_executor + +# Torch's multithreaded behavior needs to be disabled or +# it wastes a lot of CPU and slow things down. +# Do this outside of main() in case it needs to take effect +# even when we are not invoking the main (e.g. when spawning subprocesses). +torch.set_num_threads(1) +torch.set_num_interop_threads(1) + + +def compute_fbank_aishell(num_mel_bins: int = 80): + src_dir = Path("data/manifests") + output_dir = Path("data/fbank") + num_jobs = min(15, os.cpu_count()) + + dataset_parts = ( + "train", + "dev", + "test", + ) + manifests = read_manifests_if_cached( + dataset_parts=dataset_parts, output_dir=src_dir + ) + assert manifests is not None + + extractor = Fbank(FbankConfig(num_mel_bins=num_mel_bins)) + + with get_executor() as ex: # Initialize the executor only once. + for partition, m in manifests.items(): + if (output_dir / f"cuts_{partition}.json.gz").is_file(): + logging.info(f"{partition} already exists - skipping.") + continue + logging.info(f"Processing {partition}") + cut_set = CutSet.from_manifests( + recordings=m["recordings"], + supervisions=m["supervisions"], + ) + if "train" in partition: + cut_set = ( + cut_set + + cut_set.perturb_speed(0.9) + + cut_set.perturb_speed(1.1) + ) + cut_set = cut_set.compute_and_store_features( + extractor=extractor, + storage_path=f"{output_dir}/feats_{partition}", + # when an executor is specified, make more partitions + num_jobs=num_jobs if ex is None else 80, + executor=ex, + storage_type=LilcomHdf5Writer, + ) + cut_set.to_json(output_dir / f"cuts_{partition}.json.gz") + + +def get_args(): + parser = argparse.ArgumentParser() + parser.add_argument( + "--num-mel-bins", + type=int, + default=80, + help="""The number of mel bins for Fbank""", + ) + + return parser.parse_args() + + +if __name__ == "__main__": + formatter = ( + "%(asctime)s %(levelname)s [%(filename)s:%(lineno)d] %(message)s" + ) + + logging.basicConfig(format=formatter, level=logging.INFO) + + args = get_args() + compute_fbank_aishell(num_mel_bins=args.num_mel_bins) diff --git a/egs/aishell/ASR/local/compute_fbank_musan.py b/egs/aishell/ASR/local/compute_fbank_musan.py new file mode 100755 index 000000000..e79bdafb1 --- /dev/null +++ b/egs/aishell/ASR/local/compute_fbank_musan.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python3 +# Copyright 2021 Xiaomi Corp. (authors: Fangjun Kuang) +# +# See ../../../../LICENSE for clarification regarding multiple authors +# +# 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. + + +""" +This file computes fbank features of the musan dataset. +It looks for manifests in the directory data/manifests. + +The generated fbank features are saved in data/fbank. +""" + +import argparse +import logging +import os +from pathlib import Path + +import torch +from lhotse import CutSet, Fbank, FbankConfig, LilcomHdf5Writer, combine +from lhotse.recipes.utils import read_manifests_if_cached + +from icefall.utils import get_executor + +# Torch's multithreaded behavior needs to be disabled or +# it wastes a lot of CPU and slow things down. +# Do this outside of main() in case it needs to take effect +# even when we are not invoking the main (e.g. when spawning subprocesses). +torch.set_num_threads(1) +torch.set_num_interop_threads(1) + + +def compute_fbank_musan(num_mel_bins: int = 80): + src_dir = Path("data/manifests") + output_dir = Path("data/fbank") + num_jobs = min(15, os.cpu_count()) + + dataset_parts = ( + "music", + "speech", + "noise", + ) + manifests = read_manifests_if_cached( + dataset_parts=dataset_parts, output_dir=src_dir + ) + assert manifests is not None + + musan_cuts_path = output_dir / "cuts_musan.json.gz" + + if musan_cuts_path.is_file(): + logging.info(f"{musan_cuts_path} already exists - skipping") + return + + logging.info("Extracting features for Musan") + + extractor = Fbank(FbankConfig(num_mel_bins=num_mel_bins)) + + with get_executor() as ex: # Initialize the executor only once. + # create chunks of Musan with duration 5 - 10 seconds + musan_cuts = ( + CutSet.from_manifests( + recordings=combine( + part["recordings"] for part in manifests.values() + ) + ) + .cut_into_windows(10.0) + .filter(lambda c: c.duration > 5) + .compute_and_store_features( + extractor=extractor, + storage_path=f"{output_dir}/feats_musan", + num_jobs=num_jobs if ex is None else 80, + executor=ex, + storage_type=LilcomHdf5Writer, + ) + ) + musan_cuts.to_json(musan_cuts_path) + + +def get_args(): + parser = argparse.ArgumentParser() + parser.add_argument( + "--num-mel-bins", + type=int, + default=80, + help="""The number of mel bins for Fbank""", + ) + + return parser.parse_args() + + +if __name__ == "__main__": + formatter = ( + "%(asctime)s %(levelname)s [%(filename)s:%(lineno)d] %(message)s" + ) + + logging.basicConfig(format=formatter, level=logging.INFO) + args = get_args() + compute_fbank_musan(num_mel_bins=args.num_mel_bins) diff --git a/egs/aishell/ASR/local/prepare_char.py b/egs/aishell/ASR/local/prepare_char.py new file mode 100755 index 000000000..d9e47d17a --- /dev/null +++ b/egs/aishell/ASR/local/prepare_char.py @@ -0,0 +1,248 @@ +#!/usr/bin/env python3 +# Copyright 2021 Xiaomi Corp. (authors: Fangjun Kuang, +# Wei Kang) +# +# See ../../../../LICENSE for clarification regarding multiple authors +# +# 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. + + +""" + +This script takes as input `lang_dir`, which should contain:: + + - lang_dir/text, + - lang_dir/words.txt + +and generates the following files in the directory `lang_dir`: + + - lexicon.txt + - lexicon_disambig.txt + - L.pt + - L_disambig.pt + - tokens.txt +""" + +import re +from pathlib import Path +from typing import Dict, List + +import k2 +import torch +from prepare_lang import ( + Lexicon, + add_disambig_symbols, + add_self_loops, + write_lexicon, + write_mapping, +) + + +def lexicon_to_fst_no_sil( + lexicon: Lexicon, + token2id: Dict[str, int], + word2id: Dict[str, int], + need_self_loops: bool = False, +) -> k2.Fsa: + """Convert a lexicon to an FST (in k2 format). + + Args: + lexicon: + The input lexicon. See also :func:`read_lexicon` + token2id: + A dict mapping tokens to IDs. + word2id: + A dict mapping words to IDs. + need_self_loops: + If True, add self-loop to states with non-epsilon output symbols + on at least one arc out of the state. The input label for this + self loop is `token2id["#0"]` and the output label is `word2id["#0"]`. + Returns: + Return an instance of `k2.Fsa` representing the given lexicon. + """ + loop_state = 0 # words enter and leave from here + next_state = 1 # the next un-allocated state, will be incremented as we go + + arcs = [] + + # The blank symbol is defined in local/train_bpe_model.py + assert token2id[""] == 0 + assert word2id[""] == 0 + + eps = 0 + + for word, pieces in lexicon: + assert len(pieces) > 0, f"{word} has no pronunciations" + cur_state = loop_state + + word = word2id[word] + pieces = [ + token2id[i] if i in token2id else token2id[""] for i in pieces + ] + + for i in range(len(pieces) - 1): + w = word if i == 0 else eps + arcs.append([cur_state, next_state, pieces[i], w, 0]) + + cur_state = next_state + next_state += 1 + + # now for the last piece of this word + i = len(pieces) - 1 + w = word if i == 0 else eps + arcs.append([cur_state, loop_state, pieces[i], w, 0]) + + if need_self_loops: + disambig_token = token2id["#0"] + disambig_word = word2id["#0"] + arcs = add_self_loops( + arcs, + disambig_token=disambig_token, + disambig_word=disambig_word, + ) + + final_state = next_state + arcs.append([loop_state, final_state, -1, -1, 0]) + arcs.append([final_state]) + + arcs = sorted(arcs, key=lambda arc: arc[0]) + arcs = [[str(i) for i in arc] for arc in arcs] + arcs = [" ".join(arc) for arc in arcs] + arcs = "\n".join(arcs) + + fsa = k2.Fsa.from_str(arcs, acceptor=False) + return fsa + + +def contain_oov(token_sym_table: Dict[str, int], tokens: List[str]) -> bool: + """Check if all the given tokens are in token symbol table. + + Args: + token_sym_table: + Token symbol table that contains all the valid tokens. + tokens: + A list of tokens. + Returns: + Return True if there is any token not in the token_sym_table, + otherwise False. + """ + for tok in tokens: + if tok not in token_sym_table: + return True + return False + + +def generate_lexicon( + token_sym_table: Dict[str, int], words: List[str] +) -> Lexicon: + """Generate a lexicon from a word list and token_sym_table. + + Args: + token_sym_table: + Token symbol table that mapping token to token ids. + words: + A list of strings representing words. + Returns: + Return a dict whose keys are words and values are the corresponding + tokens. + """ + lexicon = [] + for word in words: + chars = list(word.strip(" \t")) + if contain_oov(token_sym_table, chars): + continue + lexicon.append((word, chars)) + + # The OOV word is + lexicon.append(("", [""])) + return lexicon + + +def generate_tokens(text_file: str) -> Dict[str, int]: + """Generate tokens from the given text file. + + Args: + text_file: + A file that contains text lines to generate tokens. + Returns: + Return a dict whose keys are tokens and values are token ids ranged + from 0 to len(keys) - 1. + """ + tokens: Dict[str, int] = dict() + tokens[""] = 0 + tokens[""] = 1 + tokens[""] = 2 + whitespace = re.compile(r"([ \t\r\n]+)") + with open(text_file, "r", encoding="utf-8") as f: + for line in f: + line = re.sub(whitespace, "", line) + chars = list(line) + for char in chars: + if char not in tokens: + tokens[char] = len(tokens) + return tokens + + +def main(): + lang_dir = Path("data/lang_char") + text_file = lang_dir / "text" + + word_sym_table = k2.SymbolTable.from_file(lang_dir / "words.txt") + + words = word_sym_table.symbols + + excluded = ["", "!SIL", "", "", "#0", "", ""] + for w in excluded: + if w in words: + words.remove(w) + + token_sym_table = generate_tokens(text_file) + + lexicon = generate_lexicon(token_sym_table, words) + + lexicon_disambig, max_disambig = add_disambig_symbols(lexicon) + + next_token_id = max(token_sym_table.values()) + 1 + for i in range(max_disambig + 1): + disambig = f"#{i}" + assert disambig not in token_sym_table + token_sym_table[disambig] = next_token_id + next_token_id += 1 + + word_sym_table.add("#0") + word_sym_table.add("") + word_sym_table.add("") + + write_mapping(lang_dir / "tokens.txt", token_sym_table) + + write_lexicon(lang_dir / "lexicon.txt", lexicon) + write_lexicon(lang_dir / "lexicon_disambig.txt", lexicon_disambig) + + L = lexicon_to_fst_no_sil( + lexicon, + token2id=token_sym_table, + word2id=word_sym_table, + ) + + L_disambig = lexicon_to_fst_no_sil( + lexicon_disambig, + token2id=token_sym_table, + word2id=word_sym_table, + need_self_loops=True, + ) + torch.save(L.as_dict(), lang_dir / "L.pt") + torch.save(L_disambig.as_dict(), lang_dir / "L_disambig.pt") + + +if __name__ == "__main__": + main() diff --git a/egs/aishell/ASR/local/prepare_lang.py b/egs/aishell/ASR/local/prepare_lang.py new file mode 100755 index 000000000..0880019b3 --- /dev/null +++ b/egs/aishell/ASR/local/prepare_lang.py @@ -0,0 +1,381 @@ +#!/usr/bin/env python3 +# Copyright 2021 Xiaomi Corp. (authors: Fangjun Kuang) +# +# See ../../../../LICENSE for clarification regarding multiple authors +# +# 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. + + +""" +This script takes as input a lexicon file "data/lang_phone/lexicon.txt" +consisting of words and tokens (i.e., phones) and does the following: + +1. Add disambiguation symbols to the lexicon and generate lexicon_disambig.txt + +2. Generate tokens.txt, the token table mapping a token to a unique integer. + +3. Generate words.txt, the word table mapping a word to a unique integer. + +4. Generate L.pt, in k2 format. It can be loaded by + + d = torch.load("L.pt") + lexicon = k2.Fsa.from_dict(d) + +5. Generate L_disambig.pt, in k2 format. +""" +import math +from collections import defaultdict +from pathlib import Path +from typing import Any, Dict, List, Tuple + +import k2 +import torch + +from icefall.lexicon import read_lexicon, write_lexicon + +Lexicon = List[Tuple[str, List[str]]] + + +def write_mapping(filename: str, sym2id: Dict[str, int]) -> None: + """Write a symbol to ID mapping to a file. + + Note: + No need to implement `read_mapping` as it can be done + through :func:`k2.SymbolTable.from_file`. + + Args: + filename: + Filename to save the mapping. + sym2id: + A dict mapping symbols to IDs. + Returns: + Return None. + """ + with open(filename, "w", encoding="utf-8") as f: + for sym, i in sym2id.items(): + f.write(f"{sym} {i}\n") + + +def get_tokens(lexicon: Lexicon) -> List[str]: + """Get tokens from a lexicon. + + Args: + lexicon: + It is the return value of :func:`read_lexicon`. + Returns: + Return a list of unique tokens. + """ + ans = set() + for _, tokens in lexicon: + ans.update(tokens) + sorted_ans = sorted(list(ans)) + return sorted_ans + + +def get_words(lexicon: Lexicon) -> List[str]: + """Get words from a lexicon. + + Args: + lexicon: + It is the return value of :func:`read_lexicon`. + Returns: + Return a list of unique words. + """ + ans = set() + for word, _ in lexicon: + ans.add(word) + sorted_ans = sorted(list(ans)) + return sorted_ans + + +def add_disambig_symbols(lexicon: Lexicon) -> Tuple[Lexicon, int]: + """It adds pseudo-token disambiguation symbols #1, #2 and so on + at the ends of tokens to ensure that all pronunciations are different, + and that none is a prefix of another. + + See also add_lex_disambig.pl from kaldi. + + Args: + lexicon: + It is returned by :func:`read_lexicon`. + Returns: + Return a tuple with two elements: + + - The output lexicon with disambiguation symbols + - The ID of the max disambiguation symbol that appears + in the lexicon + """ + + # (1) Work out the count of each token-sequence in the + # lexicon. + count = defaultdict(int) + for _, tokens in lexicon: + count[" ".join(tokens)] += 1 + + # (2) For each left sub-sequence of each token-sequence, note down + # that it exists (for identifying prefixes of longer strings). + issubseq = defaultdict(int) + for _, tokens in lexicon: + tokens = tokens.copy() + tokens.pop() + while tokens: + issubseq[" ".join(tokens)] = 1 + tokens.pop() + + # (3) For each entry in the lexicon: + # if the token sequence is unique and is not a + # prefix of another word, no disambig symbol. + # Else output #1, or #2, #3, ... if the same token-seq + # has already been assigned a disambig symbol. + ans = [] + + # We start with #1 since #0 has its own purpose + first_allowed_disambig = 1 + max_disambig = first_allowed_disambig - 1 + last_used_disambig_symbol_of = defaultdict(int) + + for word, tokens in lexicon: + tokenseq = " ".join(tokens) + assert tokenseq != "" + if issubseq[tokenseq] == 0 and count[tokenseq] == 1: + ans.append((word, tokens)) + continue + + cur_disambig = last_used_disambig_symbol_of[tokenseq] + if cur_disambig == 0: + cur_disambig = first_allowed_disambig + else: + cur_disambig += 1 + + if cur_disambig > max_disambig: + max_disambig = cur_disambig + last_used_disambig_symbol_of[tokenseq] = cur_disambig + tokenseq += f" #{cur_disambig}" + ans.append((word, tokenseq.split())) + return ans, max_disambig + + +def generate_id_map(symbols: List[str]) -> Dict[str, int]: + """Generate ID maps, i.e., map a symbol to a unique ID. + + Args: + symbols: + A list of unique symbols. + Returns: + A dict containing the mapping between symbols and IDs. + """ + return {sym: i for i, sym in enumerate(symbols)} + + +def add_self_loops( + arcs: List[List[Any]], disambig_token: int, disambig_word: int +) -> List[List[Any]]: + """Adds self-loops to states of an FST to propagate disambiguation symbols + through it. They are added on each state with non-epsilon output symbols + on at least one arc out of the state. + + See also fstaddselfloops.pl from Kaldi. One difference is that + Kaldi uses OpenFst style FSTs and it has multiple final states. + This function uses k2 style FSTs and it does not need to add self-loops + to the final state. + + The input label of a self-loop is `disambig_token`, while the output + label is `disambig_word`. + + Args: + arcs: + A list-of-list. The sublist contains + `[src_state, dest_state, label, aux_label, score]` + disambig_token: + It is the token ID of the symbol `#0`. + disambig_word: + It is the word ID of the symbol `#0`. + + Return: + Return new `arcs` containing self-loops. + """ + states_needs_self_loops = set() + for arc in arcs: + src, dst, ilabel, olabel, score = arc + if olabel != 0: + states_needs_self_loops.add(src) + + ans = [] + for s in states_needs_self_loops: + ans.append([s, s, disambig_token, disambig_word, 0]) + + return arcs + ans + + +def lexicon_to_fst( + lexicon: Lexicon, + token2id: Dict[str, int], + word2id: Dict[str, int], + sil_token: str = "SIL", + sil_prob: float = 0.5, + need_self_loops: bool = False, +) -> k2.Fsa: + """Convert a lexicon to an FST (in k2 format) with optional silence at + the beginning and end of each word. + + Args: + lexicon: + The input lexicon. See also :func:`read_lexicon` + token2id: + A dict mapping tokens to IDs. + word2id: + A dict mapping words to IDs. + sil_token: + The silence token. + sil_prob: + The probability for adding a silence at the beginning and end + of the word. + need_self_loops: + If True, add self-loop to states with non-epsilon output symbols + on at least one arc out of the state. The input label for this + self loop is `token2id["#0"]` and the output label is `word2id["#0"]`. + Returns: + Return an instance of `k2.Fsa` representing the given lexicon. + """ + assert sil_prob > 0.0 and sil_prob < 1.0 + # CAUTION: we use score, i.e, negative cost. + sil_score = math.log(sil_prob) + no_sil_score = math.log(1.0 - sil_prob) + + start_state = 0 + loop_state = 1 # words enter and leave from here + sil_state = 2 # words terminate here when followed by silence; this state + # has a silence transition to loop_state. + next_state = 3 # the next un-allocated state, will be incremented as we go. + arcs = [] + + assert token2id[""] == 0 + assert word2id[""] == 0 + + eps = 0 + + sil_token = token2id[sil_token] + + arcs.append([start_state, loop_state, eps, eps, no_sil_score]) + arcs.append([start_state, sil_state, eps, eps, sil_score]) + arcs.append([sil_state, loop_state, sil_token, eps, 0]) + + for word, tokens in lexicon: + assert len(tokens) > 0, f"{word} has no pronunciations" + cur_state = loop_state + + word = word2id[word] + tokens = [token2id[i] for i in tokens] + + for i in range(len(tokens) - 1): + w = word if i == 0 else eps + arcs.append([cur_state, next_state, tokens[i], w, 0]) + + cur_state = next_state + next_state += 1 + + # now for the last token of this word + # It has two out-going arcs, one to the loop state, + # the other one to the sil_state. + i = len(tokens) - 1 + w = word if i == 0 else eps + arcs.append([cur_state, loop_state, tokens[i], w, no_sil_score]) + arcs.append([cur_state, sil_state, tokens[i], w, sil_score]) + + if need_self_loops: + disambig_token = token2id["#0"] + disambig_word = word2id["#0"] + arcs = add_self_loops( + arcs, + disambig_token=disambig_token, + disambig_word=disambig_word, + ) + + final_state = next_state + arcs.append([loop_state, final_state, -1, -1, 0]) + arcs.append([final_state]) + + arcs = sorted(arcs, key=lambda arc: arc[0]) + arcs = [[str(i) for i in arc] for arc in arcs] + arcs = [" ".join(arc) for arc in arcs] + arcs = "\n".join(arcs) + + fsa = k2.Fsa.from_str(arcs, acceptor=False) + return fsa + + +def main(): + out_dir = Path("data/lang_phone") + lexicon_filename = out_dir / "lexicon.txt" + sil_token = "SIL" + sil_prob = 0.5 + + lexicon = read_lexicon(lexicon_filename) + tokens = get_tokens(lexicon) + words = get_words(lexicon) + + lexicon_disambig, max_disambig = add_disambig_symbols(lexicon) + + for i in range(max_disambig + 1): + disambig = f"#{i}" + assert disambig not in tokens + tokens.append(f"#{i}") + + assert "" not in tokens + tokens = [""] + tokens + + assert "" not in words + assert "#0" not in words + assert "" not in words + assert "" not in words + + words = [""] + words + ["#0", "", ""] + + token2id = generate_id_map(tokens) + word2id = generate_id_map(words) + + write_mapping(out_dir / "tokens.txt", token2id) + write_mapping(out_dir / "words.txt", word2id) + write_lexicon(out_dir / "lexicon_disambig.txt", lexicon_disambig) + + L = lexicon_to_fst( + lexicon, + token2id=token2id, + word2id=word2id, + sil_token=sil_token, + sil_prob=sil_prob, + ) + + L_disambig = lexicon_to_fst( + lexicon_disambig, + token2id=token2id, + word2id=word2id, + sil_token=sil_token, + sil_prob=sil_prob, + need_self_loops=True, + ) + torch.save(L.as_dict(), out_dir / "L.pt") + torch.save(L_disambig.as_dict(), out_dir / "L_disambig.pt") + + if False: + # Just for debugging, will remove it + L.labels_sym = k2.SymbolTable.from_file(out_dir / "tokens.txt") + L.aux_labels_sym = k2.SymbolTable.from_file(out_dir / "words.txt") + L_disambig.labels_sym = L.labels_sym + L_disambig.aux_labels_sym = L.aux_labels_sym + L.draw(out_dir / "L.png", title="L") + L_disambig.draw(out_dir / "L_disambig.png", title="L_disambig") + + +if __name__ == "__main__": + main() diff --git a/egs/aishell/ASR/local/test_prepare_lang.py b/egs/aishell/ASR/local/test_prepare_lang.py new file mode 100755 index 000000000..d4cf62bba --- /dev/null +++ b/egs/aishell/ASR/local/test_prepare_lang.py @@ -0,0 +1,106 @@ +#!/usr/bin/env python3 +# Copyright 2021 Xiaomi Corp. (authors: Fangjun Kuang) +# +# See ../../../../LICENSE for clarification regarding multiple authors +# +# 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. + + +# Copyright (c) 2021 Xiaomi Corporation (authors: Fangjun Kuang) + +import os +import tempfile + +import k2 +from prepare_lang import ( + add_disambig_symbols, + generate_id_map, + get_phones, + get_words, + lexicon_to_fst, + read_lexicon, + write_lexicon, + write_mapping, +) + + +def generate_lexicon_file() -> str: + fd, filename = tempfile.mkstemp() + os.close(fd) + s = """ + !SIL SIL + SPN + SPN + f f + a a + foo f o o + bar b a r + bark b a r k + food f o o d + food2 f o o d + fo f o + """.strip() + with open(filename, "w") as f: + f.write(s) + return filename + + +def test_read_lexicon(filename: str): + lexicon = read_lexicon(filename) + phones = get_phones(lexicon) + words = get_words(lexicon) + print(lexicon) + print(phones) + print(words) + lexicon_disambig, max_disambig = add_disambig_symbols(lexicon) + print(lexicon_disambig) + print("max disambig:", f"#{max_disambig}") + + phones = ["", "SIL", "SPN"] + phones + for i in range(max_disambig + 1): + phones.append(f"#{i}") + words = [""] + words + + phone2id = generate_id_map(phones) + word2id = generate_id_map(words) + + print(phone2id) + print(word2id) + + write_mapping("phones.txt", phone2id) + write_mapping("words.txt", word2id) + + write_lexicon("a.txt", lexicon) + write_lexicon("a_disambig.txt", lexicon_disambig) + + fsa = lexicon_to_fst(lexicon, phone2id=phone2id, word2id=word2id) + fsa.labels_sym = k2.SymbolTable.from_file("phones.txt") + fsa.aux_labels_sym = k2.SymbolTable.from_file("words.txt") + fsa.draw("L.pdf", title="L") + + fsa_disambig = lexicon_to_fst( + lexicon_disambig, phone2id=phone2id, word2id=word2id + ) + fsa_disambig.labels_sym = k2.SymbolTable.from_file("phones.txt") + fsa_disambig.aux_labels_sym = k2.SymbolTable.from_file("words.txt") + fsa_disambig.draw("L_disambig.pdf", title="L_disambig") + + +def main(): + filename = generate_lexicon_file() + test_read_lexicon(filename) + os.remove(filename) + + +if __name__ == "__main__": + main() diff --git a/egs/aishell/ASR/prepare.sh b/egs/aishell/ASR/prepare.sh new file mode 100755 index 000000000..584e50cb0 --- /dev/null +++ b/egs/aishell/ASR/prepare.sh @@ -0,0 +1,162 @@ +#!/usr/bin/env bash + +set -eou pipefail + +nj=15 +stage=-1 +stop_stage=10 + +# We assume dl_dir (download dir) contains the following +# directories and files. If not, they will be downloaded +# by this script automatically. +# +# - $dl_dir/aishell +# You can find data_aishell, resource_aishell inside it. +# You can download them from https://www.openslr.org/33 +# +# - $dl_dir/lm +# This directory contains the language model downloaded from +# https://huggingface.co/pkufool/aishell_lm +# +# - 3-gram.unpruned.apra +# +# - $dl_dir/musan +# This directory contains the following directories downloaded from +# http://www.openslr.org/17/ +# +# - music +# - noise +# - speech + +dl_dir=$PWD/download + +. shared/parse_options.sh || exit 1 + +# All files generated by this script are saved in "data". +# You can safely remove "data" and rerun this script to regenerate it. +mkdir -p data + +log() { + # This function is from espnet + local fname=${BASH_SOURCE[1]##*/} + echo -e "$(date '+%Y-%m-%d %H:%M:%S') (${fname}:${BASH_LINENO[0]}:${FUNCNAME[1]}) $*" +} + +log "dl_dir: $dl_dir" + +if [ $stage -le -1 ] && [ $stop_stage -ge -1 ]; then + log "stage -1: Download LM" + # We assume that you have installed the git-lfs, if not, you could install it + # using: `sudo apt-get install git-lfs && git-lfs install` + [ ! -e $dl_dir/lm ] && mkdir -p $dl_dir/lm + git clone https://huggingface.co/pkufool/aishell_lm $dl_dir/lm +fi + +if [ $stage -le 0 ] && [ $stop_stage -ge 0 ]; then + log "stage 0: Download data" + + # If you have pre-downloaded it to /path/to/aishell, + # you can create a symlink + # + # ln -sfv /path/to/aishell $dl_dir/aishell + # + # The directory structure is + # aishell/ + # |-- data_aishell + # | |-- transcript + # | `-- wav + # `-- resource_aishell + # |-- lexicon.txt + # `-- speaker.info + + if [ ! -d $dl_dir/aishell/data_aishell/wav ]; then + lhotse download aishell $dl_dir + fi + + # If you have pre-downloaded it to /path/to/musan, + # you can create a symlink + # + # ln -sfv /path/to/musan $dl_dir/musan + # + if [ ! -d $dl_dir/musan ]; then + lhotse download musan $dl_dir + fi +fi + +if [ $stage -le 1 ] && [ $stop_stage -ge 1 ]; then + log "Stage 1: Prepare aishell manifest" + # We assume that you have downloaded the aishell corpus + # to $dl_dir/aishell + mkdir -p data/manifests + lhotse prepare aishell -j $nj $dl_dir/aishell data/manifests +fi + +if [ $stage -le 2 ] && [ $stop_stage -ge 2 ]; then + log "Stage 2: Prepare musan manifest" + # We assume that you have downloaded the musan corpus + # to data/musan + mkdir -p data/manifests + lhotse prepare musan $dl_dir/musan data/manifests +fi + +if [ $stage -le 3 ] && [ $stop_stage -ge 3 ]; then + log "Stage 3: Compute fbank for aishell" + mkdir -p data/fbank + ./local/compute_fbank_aishell.py +fi + +if [ $stage -le 4 ] && [ $stop_stage -ge 4 ]; then + log "Stage 4: Compute fbank for musan" + mkdir -p data/fbank + ./local/compute_fbank_musan.py +fi + +if [ $stage -le 5 ] && [ $stop_stage -ge 5 ]; then + log "Stage 5: Prepare phone based lang" + mkdir -p data/lang_phone + + (echo '!SIL SIL'; echo ' SPN'; echo ' SPN'; ) | + cat - $dl_dir/aishell/resource_aishell/lexicon.txt | + sort | uniq > data/lang_phone/lexicon.txt + + if [ ! -f data/lang_phone/L_disambig.pt ]; then + ./local/prepare_lang.py + fi +fi + +if [ $stage -le 6 ] && [ $stop_stage -ge 6 ]; then + log "Stage 6: Prepare char based lang" + mkdir -p data/lang_char + # We reuse words.txt from phone based lexicon + # so that the two can share G.pt later. + cp data/lang_phone/words.txt data/lang_char + + cat $dl_dir/aishell/data_aishell/transcript/aishell_transcript_v0.8.txt | + cut -d " " -f 2- | sed -e 's/[ \t\r\n]*//g' > data/lang_char/text + + if [ ! -f data/lang_char/L_disambig.pt ]; then + ./local/prepare_char.py + fi +fi + +if [ $stage -le 7 ] && [ $stop_stage -ge 7 ]; then + log "Stage 7: Prepare G" + # We assume you have install kaldilm, if not, please install + # it using: pip install kaldilm + + mkdir -p data/lm + if [ ! -f data/lm/G_3_gram.fst.txt ]; then + # It is used in building HLG + python3 -m kaldilm \ + --read-symbol-table="data/lang_phone/words.txt" \ + --disambig-symbol='#0' \ + --max-order=3 \ + $dl_dir/lm/3-gram.unpruned.arpa > data/lm/G_3_gram.fst.txt + fi +fi + +if [ $stage -le 8 ] && [ $stop_stage -ge 8 ]; then + log "Stage 8: Compile HLG" + ./local/compile_hlg.py --lang-dir data/lang_phone + ./local/compile_hlg.py --lang-dir data/lang_char +fi diff --git a/egs/aishell/ASR/shared b/egs/aishell/ASR/shared new file mode 120000 index 000000000..4c5e91438 --- /dev/null +++ b/egs/aishell/ASR/shared @@ -0,0 +1 @@ +../../../icefall/shared/ \ No newline at end of file diff --git a/egs/aishell/ASR/tdnn_lstm_ctc/README.md b/egs/aishell/ASR/tdnn_lstm_ctc/README.md new file mode 100644 index 000000000..a2d80a785 --- /dev/null +++ b/egs/aishell/ASR/tdnn_lstm_ctc/README.md @@ -0,0 +1,4 @@ + +Please visit + +for how to run this recipe. diff --git a/egs/aishell/ASR/tdnn_lstm_ctc/__init__.py b/egs/aishell/ASR/tdnn_lstm_ctc/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/egs/aishell/ASR/tdnn_lstm_ctc/asr_datamodule.py b/egs/aishell/ASR/tdnn_lstm_ctc/asr_datamodule.py new file mode 100644 index 000000000..9075ecb7e --- /dev/null +++ b/egs/aishell/ASR/tdnn_lstm_ctc/asr_datamodule.py @@ -0,0 +1,331 @@ +# Copyright 2021 Piotr Żelasko +# +# See ../../../../LICENSE for clarification regarding multiple authors +# +# 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 argparse +import logging +from functools import lru_cache +from pathlib import Path +from typing import List, Union + +from lhotse import CutSet, Fbank, FbankConfig, load_manifest +from lhotse.dataset import ( + BucketingSampler, + CutConcatenate, + CutMix, + K2SpeechRecognitionDataset, + PrecomputedFeatures, + SingleCutSampler, + SpecAugment, +) +from lhotse.dataset.input_strategies import OnTheFlyFeatures +from torch.utils.data import DataLoader + +from icefall.dataset.datamodule import DataModule +from icefall.utils import str2bool + + +class AishellAsrDataModule(DataModule): + """ + DataModule for k2 ASR experiments. + It assumes there is always one train and valid dataloader, + but there can be multiple test dataloaders (e.g. LibriSpeech test-clean + and test-other). + + It contains all the common data pipeline modules used in ASR + experiments, e.g.: + - dynamic batch size, + - bucketing samplers, + - cut concatenation, + - augmentation, + - on-the-fly feature extraction + """ + + @classmethod + def add_arguments(cls, parser: argparse.ArgumentParser): + super().add_arguments(parser) + group = parser.add_argument_group( + title="ASR data related options", + description="These options are used for the preparation of " + "PyTorch DataLoaders from Lhotse CutSet's -- they control the " + "effective batch sizes, sampling strategies, applied data " + "augmentations, etc.", + ) + group.add_argument( + "--feature-dir", + type=Path, + default=Path("data/fbank"), + help="Path to directory with train/valid/test cuts.", + ) + group.add_argument( + "--max-duration", + type=int, + default=200.0, + help="Maximum pooled recordings duration (seconds) in a " + "single batch. You can reduce it if it causes CUDA OOM.", + ) + group.add_argument( + "--bucketing-sampler", + type=str2bool, + default=True, + help="When enabled, the batches will come from buckets of " + "similar duration (saves padding frames).", + ) + group.add_argument( + "--num-buckets", + type=int, + default=30, + help="The number of buckets for the BucketingSampler" + "(you might want to increase it for larger datasets).", + ) + group.add_argument( + "--concatenate-cuts", + type=str2bool, + default=False, + help="When enabled, utterances (cuts) will be concatenated " + "to minimize the amount of padding.", + ) + group.add_argument( + "--duration-factor", + type=float, + default=1.0, + help="Determines the maximum duration of a concatenated cut " + "relative to the duration of the longest cut in a batch.", + ) + group.add_argument( + "--gap", + type=float, + default=1.0, + help="The amount of padding (in seconds) inserted between " + "concatenated cuts. This padding is filled with noise when " + "noise augmentation is used.", + ) + group.add_argument( + "--on-the-fly-feats", + type=str2bool, + default=False, + help="When enabled, use on-the-fly cut mixing and feature " + "extraction. Will drop existing precomputed feature manifests " + "if available.", + ) + group.add_argument( + "--shuffle", + type=str2bool, + default=True, + help="When enabled (=default), the examples will be " + "shuffled for each epoch.", + ) + group.add_argument( + "--return-cuts", + type=str2bool, + default=True, + help="When enabled, each batch will have the " + "field: batch['supervisions']['cut'] with the cuts that " + "were used to construct it.", + ) + + group.add_argument( + "--num-workers", + type=int, + default=2, + help="The number of training dataloader workers that " + "collect the batches.", + ) + + def train_dataloaders(self) -> DataLoader: + logging.info("About to get train cuts") + cuts_train = self.train_cuts() + + logging.info("About to get Musan cuts") + cuts_musan = load_manifest(self.args.feature_dir / "cuts_musan.json.gz") + + logging.info("About to create train dataset") + transforms = [CutMix(cuts=cuts_musan, prob=0.5, snr=(10, 20))] + if self.args.concatenate_cuts: + logging.info( + f"Using cut concatenation with duration factor " + f"{self.args.duration_factor} and gap {self.args.gap}." + ) + # Cut concatenation should be the first transform in the list, + # so that if we e.g. mix noise in, it will fill the gaps between + # different utterances. + transforms = [ + CutConcatenate( + duration_factor=self.args.duration_factor, gap=self.args.gap + ) + ] + transforms + + input_transforms = [ + SpecAugment( + num_frame_masks=2, + features_mask_size=27, + num_feature_masks=2, + frames_mask_size=100, + ) + ] + + train = K2SpeechRecognitionDataset( + cut_transforms=transforms, + input_transforms=input_transforms, + return_cuts=self.args.return_cuts, + ) + + if self.args.on_the_fly_feats: + # NOTE: the PerturbSpeed transform should be added only if we + # remove it from data prep stage. + # Add on-the-fly speed perturbation; since originally it would + # have increased epoch size by 3, we will apply prob 2/3 and use + # 3x more epochs. + # Speed perturbation probably should come first before + # concatenation, but in principle the transforms order doesn't have + # to be strict (e.g. could be randomized) + # transforms = [PerturbSpeed(factors=[0.9, 1.1], p=2/3)] + transforms # noqa + # Drop feats to be on the safe side. + train = K2SpeechRecognitionDataset( + cut_transforms=transforms, + input_strategy=OnTheFlyFeatures( + Fbank(FbankConfig(num_mel_bins=80)) + ), + input_transforms=input_transforms, + return_cuts=self.args.return_cuts, + ) + + if self.args.bucketing_sampler: + logging.info("Using BucketingSampler.") + train_sampler = BucketingSampler( + cuts_train, + max_duration=self.args.max_duration, + shuffle=self.args.shuffle, + num_buckets=self.args.num_buckets, + bucket_method="equal_duration", + drop_last=True, + ) + else: + logging.info("Using SingleCutSampler.") + train_sampler = SingleCutSampler( + cuts_train, + max_duration=self.args.max_duration, + shuffle=self.args.shuffle, + ) + logging.info("About to create train dataloader") + + train_dl = DataLoader( + train, + sampler=train_sampler, + batch_size=None, + num_workers=self.args.num_workers, + persistent_workers=False, + ) + + return train_dl + + def valid_dataloaders(self) -> DataLoader: + logging.info("About to get dev cuts") + cuts_valid = self.valid_cuts() + + transforms = [] + if self.args.concatenate_cuts: + transforms = [ + CutConcatenate( + duration_factor=self.args.duration_factor, gap=self.args.gap + ) + ] + transforms + + logging.info("About to create dev dataset") + if self.args.on_the_fly_feats: + validate = K2SpeechRecognitionDataset( + cut_transforms=transforms, + input_strategy=OnTheFlyFeatures( + Fbank(FbankConfig(num_mel_bins=80)) + ), + return_cuts=self.args.return_cuts, + ) + else: + validate = K2SpeechRecognitionDataset( + cut_transforms=transforms, + return_cuts=self.args.return_cuts, + ) + valid_sampler = SingleCutSampler( + cuts_valid, + max_duration=self.args.max_duration, + shuffle=False, + ) + logging.info("About to create dev dataloader") + valid_dl = DataLoader( + validate, + sampler=valid_sampler, + batch_size=None, + num_workers=2, + persistent_workers=False, + ) + + return valid_dl + + def test_dataloaders(self) -> Union[DataLoader, List[DataLoader]]: + cuts = self.test_cuts() + is_list = isinstance(cuts, list) + test_loaders = [] + if not is_list: + cuts = [cuts] + + for cuts_test in cuts: + logging.debug("About to create test dataset") + test = K2SpeechRecognitionDataset( + input_strategy=OnTheFlyFeatures( + Fbank(FbankConfig(num_mel_bins=80)) + ) + if self.args.on_the_fly_feats + else PrecomputedFeatures(), + return_cuts=self.args.return_cuts, + ) + sampler = SingleCutSampler( + cuts_test, max_duration=self.args.max_duration + ) + logging.debug("About to create test dataloader") + test_dl = DataLoader( + test, batch_size=None, sampler=sampler, num_workers=1 + ) + test_loaders.append(test_dl) + + if is_list: + return test_loaders + else: + return test_loaders[0] + + @lru_cache() + def train_cuts(self) -> CutSet: + logging.info("About to get train cuts") + cuts_train = load_manifest(self.args.feature_dir / "cuts_train.json.gz") + return cuts_train + + @lru_cache() + def valid_cuts(self) -> CutSet: + logging.info("About to get dev cuts") + cuts_valid = load_manifest(self.args.feature_dir / "cuts_dev.json.gz") + return cuts_valid + + @lru_cache() + def test_cuts(self) -> List[CutSet]: + test_sets = ["test"] + cuts = [] + for test_set in test_sets: + logging.debug("About to get test cuts") + cuts.append( + load_manifest( + self.args.feature_dir / f"cuts_{test_set}.json.gz" + ) + ) + return cuts diff --git a/egs/aishell/ASR/tdnn_lstm_ctc/decode.py b/egs/aishell/ASR/tdnn_lstm_ctc/decode.py new file mode 100755 index 000000000..851264be7 --- /dev/null +++ b/egs/aishell/ASR/tdnn_lstm_ctc/decode.py @@ -0,0 +1,394 @@ +#!/usr/bin/env python3 +# Copyright 2021 Xiaomi Corp. (authors: Fangjun Kuang) +# +# See ../../../../LICENSE for clarification regarding multiple authors +# +# 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 argparse +import logging +from collections import defaultdict +from pathlib import Path +from typing import Dict, List, Tuple + +import k2 +import torch +import torch.nn as nn +from asr_datamodule import AishellAsrDataModule +from model import TdnnLstm + +from icefall.checkpoint import average_checkpoints, load_checkpoint +from icefall.decode import get_lattice, nbest_decoding, one_best_decoding +from icefall.lexicon import Lexicon +from icefall.utils import ( + AttributeDict, + get_texts, + setup_logger, + store_transcripts, + str2bool, + write_error_stats, +) + + +def get_parser(): + parser = argparse.ArgumentParser( + formatter_class=argparse.ArgumentDefaultsHelpFormatter + ) + + parser.add_argument( + "--epoch", + type=int, + default=19, + help="It specifies the checkpoint to use for decoding." + "Note: Epoch counts from 0.", + ) + parser.add_argument( + "--avg", + type=int, + default=5, + help="Number of checkpoints to average. Automatically select " + "consecutive checkpoints before the checkpoint specified by " + "'--epoch'. ", + ) + parser.add_argument( + "--method", + type=str, + default="1best", + help="""Decoding method. + Supported values are: + - (1) 1best. Extract the best path from the decoding lattice as the + decoding result. + - (2) nbest. Extract n paths from the decoding lattice; the path + with the highest score is the decoding result. + """, + ) + parser.add_argument( + "--num-paths", + type=int, + default=30, + help="""Number of paths for n-best based decoding method. + Used only when "method" is nbest. + """, + ) + parser.add_argument( + "--export", + type=str2bool, + default=False, + help="""When enabled, the averaged model is saved to + tdnn/exp/pretrained.pt. Note: only model.state_dict() is saved. + pretrained.pt contains a dict {"model": model.state_dict()}, + which can be loaded by `icefall.checkpoint.load_checkpoint()`. + """, + ) + return parser + + +def get_params() -> AttributeDict: + params = AttributeDict( + { + "exp_dir": Path("tdnn_lstm_ctc/exp/"), + "lang_dir": Path("data/lang_phone"), + "lm_dir": Path("data/lm"), + # parameters for tdnn_lstm_ctc + "subsampling_factor": 3, + "feature_dim": 80, + # parameters for decoding + "search_beam": 20, + "output_beam": 7, + "min_active_states": 30, + "max_active_states": 10000, + "use_double_scores": True, + } + ) + return params + + +def decode_one_batch( + params: AttributeDict, + model: nn.Module, + HLG: k2.Fsa, + batch: dict, + lexicon: Lexicon, +) -> Dict[str, List[List[int]]]: + """Decode one batch and return the result in a dict. The dict has the + following format: + + - key: It indicates the setting used for decoding. For example, + if the decoding method is 1best, the key is the string + `no_rescore`. If the decoding method is nbest, the key is the + string `no_rescore-xxx`, xxx is the num_paths. + + - value: It contains the decoding result. `len(value)` equals to + batch size. `value[i]` is the decoding result for the i-th + utterance in the given batch. + Args: + params: + It's the return value of :func:`get_params`. + + - params.method is "1best", it uses 1best decoding without LM rescoring. + - params.method is "nbest", it uses nbest decoding without LM rescoring. + + model: + The neural model. + HLG: + The decoding graph. + batch: + It is the return value from iterating + `lhotse.dataset.K2SpeechRecognitionDataset`. See its documentation + for the format of the `batch`. + lexicon: + It contains word symbol table. + Returns: + Return the decoding result. See above description for the format of + the returned dict. + """ + device = HLG.device + feature = batch["inputs"] + assert feature.ndim == 3 + feature = feature.to(device) + # at entry, feature is [N, T, C] + + feature = feature.permute(0, 2, 1) # now feature is [N, C, T] + + nnet_output = model(feature) + # nnet_output is [N, T, C] + + supervisions = batch["supervisions"] + + supervision_segments = torch.stack( + ( + supervisions["sequence_idx"], + supervisions["start_frame"] // params.subsampling_factor, + supervisions["num_frames"] // params.subsampling_factor, + ), + 1, + ).to(torch.int32) + + lattice = get_lattice( + nnet_output=nnet_output, + HLG=HLG, + supervision_segments=supervision_segments, + search_beam=params.search_beam, + output_beam=params.output_beam, + min_active_states=params.min_active_states, + max_active_states=params.max_active_states, + ) + + assert params.method in ["1best", "nbest"] + if params.method == "1best": + best_path = one_best_decoding( + lattice=lattice, use_double_scores=params.use_double_scores + ) + key = "no_rescore" + else: + best_path = nbest_decoding( + lattice=lattice, + num_paths=params.num_paths, + use_double_scores=params.use_double_scores, + ) + key = f"no_rescore-{params.num_paths}" + hyps = get_texts(best_path) + hyps = [[lexicon.word_table[i] for i in ids] for ids in hyps] + return {key: hyps} + + +def decode_dataset( + dl: torch.utils.data.DataLoader, + params: AttributeDict, + model: nn.Module, + HLG: k2.Fsa, + lexicon: Lexicon, +) -> Dict[str, List[Tuple[List[int], List[int]]]]: + """Decode dataset. + + Args: + dl: + PyTorch's dataloader containing the dataset to decode. + params: + It is returned by :func:`get_params`. + model: + The neural model. + HLG: + The decoding graph. + lexicon: + It contains word symbol table. + Returns: + Return a dict, whose key may be "no-rescore" if decoding method is 1best, + or it may be "no-rescoer-100" if decoding method is nbest. + Its value is a list of tuples. Each tuple contains two elements: + The first is the reference transcript, and the second is the + predicted result. + """ + results = [] + + num_cuts = 0 + + try: + num_batches = len(dl) + except TypeError: + num_batches = "?" + + results = defaultdict(list) + for batch_idx, batch in enumerate(dl): + texts = batch["supervisions"]["text"] + + hyps_dict = decode_one_batch( + params=params, + model=model, + HLG=HLG, + batch=batch, + lexicon=lexicon, + ) + + for lm_scale, hyps in hyps_dict.items(): + this_batch = [] + assert len(hyps) == len(texts) + for hyp_words, ref_text in zip(hyps, texts): + ref_words = ref_text.split() + this_batch.append((ref_words, hyp_words)) + + results[lm_scale].extend(this_batch) + + num_cuts += len(batch["supervisions"]["text"]) + + if batch_idx % 100 == 0: + batch_str = f"{batch_idx}/{num_batches}" + + logging.info( + f"batch {batch_str}, cuts processed until now is {num_cuts}" + ) + return results + + +def save_results( + params: AttributeDict, + test_set_name: str, + results_dict: Dict[str, List[Tuple[List[int], List[int]]]], +): + test_set_wers = dict() + for key, results in results_dict.items(): + recog_path = params.exp_dir / f"recogs-{test_set_name}-{key}.txt" + store_transcripts(filename=recog_path, texts=results) + logging.info(f"The transcripts are stored in {recog_path}") + + # The following prints out WERs, per-word error statistics and aligned + # ref/hyp pairs. + errs_filename = params.exp_dir / f"errs-{test_set_name}-{key}.txt" + # We compute CER for aishell dataset. + results_char = [] + for res in results: + results_char.append((list("".join(res[0])), list("".join(res[1])))) + with open(errs_filename, "w") as f: + wer = write_error_stats(f, f"{test_set_name}-{key}", results_char) + test_set_wers[key] = wer + + logging.info("Wrote detailed error stats to {}".format(errs_filename)) + + test_set_wers = sorted(test_set_wers.items(), key=lambda x: x[1]) + errs_info = params.exp_dir / f"cer-summary-{test_set_name}.txt" + with open(errs_info, "w") as f: + print("settings\tCER", file=f) + for key, val in test_set_wers: + print("{}\t{}".format(key, val), file=f) + + s = "\nFor {}, CER of different settings are:\n".format(test_set_name) + note = "\tbest for {}".format(test_set_name) + for key, val in test_set_wers: + s += "{}\t{}{}\n".format(key, val, note) + note = "" + logging.info(s) + + +@torch.no_grad() +def main(): + parser = get_parser() + AishellAsrDataModule.add_arguments(parser) + args = parser.parse_args() + + params = get_params() + params.update(vars(args)) + + setup_logger(f"{params.exp_dir}/log/log-decode") + logging.info("Decoding started") + logging.info(params) + + lexicon = Lexicon(params.lang_dir) + max_phone_id = max(lexicon.tokens) + + device = torch.device("cpu") + if torch.cuda.is_available(): + device = torch.device("cuda", 0) + + logging.info(f"device: {device}") + + HLG = k2.Fsa.from_dict( + torch.load(f"{params.lang_dir}/HLG.pt", map_location="cpu") + ) + HLG = HLG.to(device) + assert HLG.requires_grad is False + + if not hasattr(HLG, "lm_scores"): + HLG.lm_scores = HLG.scores.clone() + + model = TdnnLstm( + num_features=params.feature_dim, + num_classes=max_phone_id + 1, # +1 for the blank symbol + subsampling_factor=params.subsampling_factor, + ) + if params.avg == 1: + load_checkpoint(f"{params.exp_dir}/epoch-{params.epoch}.pt", model) + else: + start = params.epoch - params.avg + 1 + filenames = [] + for i in range(start, params.epoch + 1): + if start >= 0: + filenames.append(f"{params.exp_dir}/epoch-{i}.pt") + logging.info(f"averaging {filenames}") + model.load_state_dict(average_checkpoints(filenames)) + + if params.export: + logging.info(f"Export averaged model to {params.exp_dir}/pretrained.pt") + torch.save( + {"model": model.state_dict()}, f"{params.exp_dir}/pretrained.pt" + ) + + model.to(device) + model.eval() + + aishell = AishellAsrDataModule(args) + # CAUTION: `test_sets` is for displaying only. + # If you want to skip test-clean, you have to skip + # it inside the for loop. That is, use + # + # if test_set == 'test-clean': continue + # + test_sets = ["test"] + for test_set, test_dl in zip(test_sets, aishell.test_dataloaders()): + results_dict = decode_dataset( + dl=test_dl, + params=params, + model=model, + HLG=HLG, + lexicon=lexicon, + ) + + save_results( + params=params, test_set_name=test_set, results_dict=results_dict + ) + + logging.info("Done!") + + +if __name__ == "__main__": + main() diff --git a/egs/aishell/ASR/tdnn_lstm_ctc/model.py b/egs/aishell/ASR/tdnn_lstm_ctc/model.py new file mode 100644 index 000000000..5e04c11b4 --- /dev/null +++ b/egs/aishell/ASR/tdnn_lstm_ctc/model.py @@ -0,0 +1,103 @@ +# Copyright 2021 Xiaomi Corp. (authors: Fangjun Kuang) +# +# See ../../../../LICENSE for clarification regarding multiple authors +# +# 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 torch +import torch.nn as nn + + +class TdnnLstm(nn.Module): + def __init__( + self, num_features: int, num_classes: int, subsampling_factor: int = 3 + ) -> None: + """ + Args: + num_features: + The input dimension of the model. + num_classes: + The output dimension of the model. + subsampling_factor: + It reduces the number of output frames by this factor. + """ + super().__init__() + self.num_features = num_features + self.num_classes = num_classes + self.subsampling_factor = subsampling_factor + self.tdnn = nn.Sequential( + nn.Conv1d( + in_channels=num_features, + out_channels=500, + kernel_size=3, + stride=1, + padding=1, + ), + nn.ReLU(inplace=True), + nn.BatchNorm1d(num_features=500, affine=False), + nn.Conv1d( + in_channels=500, + out_channels=500, + kernel_size=3, + stride=1, + padding=1, + ), + nn.ReLU(inplace=True), + nn.BatchNorm1d(num_features=500, affine=False), + nn.Conv1d( + in_channels=500, + out_channels=500, + kernel_size=3, + stride=self.subsampling_factor, # stride: subsampling_factor! + padding=1, + ), + nn.ReLU(inplace=True), + nn.BatchNorm1d(num_features=500, affine=False), + ) + self.lstms = nn.ModuleList( + [ + nn.LSTM(input_size=500, hidden_size=500, num_layers=1) + for _ in range(5) + ] + ) + self.lstm_bnorms = nn.ModuleList( + [nn.BatchNorm1d(num_features=500, affine=False) for _ in range(5)] + ) + self.dropout = nn.Dropout(0.2) + self.linear = nn.Linear(in_features=500, out_features=self.num_classes) + + def forward(self, x: torch.Tensor) -> torch.Tensor: + """ + Args: + x: + Its shape is [N, C, T] + + Returns: + The output tensor has shape [N, T, C] + """ + x = self.tdnn(x) + x = x.permute(2, 0, 1) # (N, C, T) -> (T, N, C) -> how LSTM expects it + for lstm, bnorm in zip(self.lstms, self.lstm_bnorms): + x_new, _ = lstm(x) + x_new = bnorm(x_new.permute(1, 2, 0)).permute( + 2, 0, 1 + ) # (T, N, C) -> (N, C, T) -> (T, N, C) + x_new = self.dropout(x_new) + x = x_new + x # skip connections + x = x.transpose( + 1, 0 + ) # (T, N, C) -> (N, T, C) -> linear expects "features" in the last dim + x = self.linear(x) + x = nn.functional.log_softmax(x, dim=-1) + return x diff --git a/egs/aishell/ASR/tdnn_lstm_ctc/pretrained.py b/egs/aishell/ASR/tdnn_lstm_ctc/pretrained.py new file mode 100644 index 000000000..b68221d08 --- /dev/null +++ b/egs/aishell/ASR/tdnn_lstm_ctc/pretrained.py @@ -0,0 +1,228 @@ +#!/usr/bin/env python3 +# Copyright 2021 Xiaomi Corp. (authors: Fangjun Kuang, +# Wei Kang) +# +# See ../../../../LICENSE for clarification regarding multiple authors +# +# 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 argparse +import logging +import math +from typing import List + +import k2 +import kaldifeat +import torch +import torchaudio +from model import TdnnLstm +from torch.nn.utils.rnn import pad_sequence + +from icefall.decode import get_lattice, one_best_decoding +from icefall.utils import AttributeDict, get_texts + + +def get_parser(): + parser = argparse.ArgumentParser( + formatter_class=argparse.ArgumentDefaultsHelpFormatter + ) + + parser.add_argument( + "--checkpoint", + type=str, + required=True, + help="Path to the checkpoint. " + "The checkpoint is assumed to be saved by " + "icefall.checkpoint.save_checkpoint().", + ) + + parser.add_argument( + "--words-file", + type=str, + required=True, + help="Path to words.txt", + ) + + parser.add_argument( + "--HLG", type=str, required=True, help="Path to HLG.pt." + ) + + parser.add_argument( + "--method", + type=str, + default="1best", + help="""Decoding method. + Use the best path as decoding output. Only the transformer encoder + output is used for decoding. We call it HLG decoding. + """, + ) + + parser.add_argument( + "sound_files", + type=str, + nargs="+", + help="The input sound file(s) to transcribe. " + "Supported formats are those supported by torchaudio.load(). " + "For example, wav and flac are supported. " + "The sample rate has to be 16kHz.", + ) + + return parser + + +def get_params() -> AttributeDict: + params = AttributeDict( + { + "feature_dim": 80, + "subsampling_factor": 3, + "num_classes": 220, + "sample_rate": 16000, + "search_beam": 20, + "output_beam": 7, + "min_active_states": 30, + "max_active_states": 10000, + "use_double_scores": True, + } + ) + return params + + +def read_sound_files( + filenames: List[str], expected_sample_rate: float +) -> List[torch.Tensor]: + """Read a list of sound files into a list 1-D float32 torch tensors. + Args: + filenames: + A list of sound filenames. + expected_sample_rate: + The expected sample rate of the sound files. + Returns: + Return a list of 1-D float32 torch tensors. + """ + ans = [] + for f in filenames: + wave, sample_rate = torchaudio.load(f) + assert sample_rate == expected_sample_rate, ( + f"expected sample rate: {expected_sample_rate}. " + f"Given: {sample_rate}" + ) + # We use only the first channel + ans.append(wave[0]) + return ans + + +def main(): + parser = get_parser() + args = parser.parse_args() + + params = get_params() + params.update(vars(args)) + logging.info(f"{params}") + + device = torch.device("cpu") + if torch.cuda.is_available(): + device = torch.device("cuda", 0) + + logging.info(f"device: {device}") + + logging.info("Creating model") + model = TdnnLstm( + num_features=params.feature_dim, + num_classes=params.num_classes, + subsampling_factor=params.subsampling_factor, + ) + + checkpoint = torch.load(args.checkpoint, map_location="cpu") + model.load_state_dict(checkpoint["model"]) + model.to(device) + model.eval() + + logging.info(f"Loading HLG from {params.HLG}") + HLG = k2.Fsa.from_dict(torch.load(params.HLG, map_location="cpu")) + HLG = HLG.to(device) + if not hasattr(HLG, "lm_scores"): + # For whole-lattice-rescoring and attention-decoder + HLG.lm_scores = HLG.scores.clone() + + logging.info("Constructing Fbank computer") + opts = kaldifeat.FbankOptions() + opts.device = device + opts.frame_opts.dither = 0 + opts.frame_opts.snip_edges = False + opts.frame_opts.samp_freq = params.sample_rate + opts.mel_opts.num_bins = params.feature_dim + + fbank = kaldifeat.Fbank(opts) + + logging.info(f"Reading sound files: {params.sound_files}") + waves = read_sound_files( + filenames=params.sound_files, expected_sample_rate=params.sample_rate + ) + waves = [w.to(device) for w in waves] + + logging.info("Decoding started") + features = fbank(waves) + + features = pad_sequence( + features, batch_first=True, padding_value=math.log(1e-10) + ) + features = features.permute(0, 2, 1) # now features is [N, C, T] + + with torch.no_grad(): + nnet_output = model(features) + # nnet_output is [N, T, C] + + batch_size = nnet_output.shape[0] + supervision_segments = torch.tensor( + [[i, 0, nnet_output.shape[1]] for i in range(batch_size)], + dtype=torch.int32, + ) + + lattice = get_lattice( + nnet_output=nnet_output, + HLG=HLG, + supervision_segments=supervision_segments, + search_beam=params.search_beam, + output_beam=params.output_beam, + min_active_states=params.min_active_states, + max_active_states=params.max_active_states, + subsampling_factor=params.subsampling_factor, + ) + + assert params.method == "1best" + logging.info("Use HLG decoding") + best_path = one_best_decoding( + lattice=lattice, use_double_scores=params.use_double_scores + ) + + hyps = get_texts(best_path) + word_sym_table = k2.SymbolTable.from_file(params.words_file) + hyps = [[word_sym_table[i] for i in ids] for ids in hyps] + + s = "\n" + for filename, hyp in zip(params.sound_files, hyps): + words = " ".join(hyp) + s += f"{filename}:\n{words}\n\n" + logging.info(s) + + logging.info("Decoding Done") + + +if __name__ == "__main__": + formatter = ( + "%(asctime)s %(levelname)s [%(filename)s:%(lineno)d] %(message)s" + ) + + logging.basicConfig(format=formatter, level=logging.INFO) + main() diff --git a/egs/aishell/ASR/tdnn_lstm_ctc/train.py b/egs/aishell/ASR/tdnn_lstm_ctc/train.py new file mode 100755 index 000000000..410f07c53 --- /dev/null +++ b/egs/aishell/ASR/tdnn_lstm_ctc/train.py @@ -0,0 +1,616 @@ +#!/usr/bin/env python3 +# Copyright 2021 Xiaomi Corp. (authors: Fangjun Kuang) +# +# See ../../../../LICENSE for clarification regarding multiple authors +# +# 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 argparse +import logging +from pathlib import Path +from shutil import copyfile +from typing import Optional + +import k2 +import torch +import torch.distributed as dist +import torch.multiprocessing as mp +import torch.nn as nn +import torch.optim as optim +from asr_datamodule import AishellAsrDataModule +from lhotse.utils import fix_random_seed +from model import TdnnLstm +from torch.nn.parallel import DistributedDataParallel as DDP +from torch.nn.utils import clip_grad_norm_ +from torch.optim.lr_scheduler import StepLR +from torch.utils.tensorboard import SummaryWriter + +from icefall.checkpoint import load_checkpoint +from icefall.checkpoint import save_checkpoint as save_checkpoint_impl +from icefall.dist import cleanup_dist, setup_dist +from icefall.graph_compiler import CtcTrainingGraphCompiler +from icefall.lexicon import Lexicon +from icefall.utils import ( + AttributeDict, + encode_supervisions, + setup_logger, + str2bool, +) + + +def get_parser(): + parser = argparse.ArgumentParser( + formatter_class=argparse.ArgumentDefaultsHelpFormatter + ) + + parser.add_argument( + "--world-size", + type=int, + default=1, + help="Number of GPUs for DDP training.", + ) + + parser.add_argument( + "--master-port", + type=int, + default=12354, + help="Master port to use for DDP training.", + ) + + parser.add_argument( + "--tensorboard", + type=str2bool, + default=True, + help="Should various information be logged in tensorboard.", + ) + + parser.add_argument( + "--num-epochs", + type=int, + default=20, + help="Number of epochs to train.", + ) + + parser.add_argument( + "--start-epoch", + type=int, + default=0, + help="""Resume training from from this epoch. + If it is positive, it will load checkpoint from + tdnn_lstm_ctc/exp/epoch-{start_epoch-1}.pt + """, + ) + + return parser + + +def get_params() -> AttributeDict: + """Return a dict containing training parameters. + + All training related parameters that are not passed from the commandline + is saved in the variable `params`. + + Commandline options are merged into `params` after they are parsed, so + you can also access them via `params`. + + Explanation of options saved in `params`: + + - exp_dir: It specifies the directory where all training related + files, e.g., checkpoints, log, etc, are saved + + - lang_dir: It contains language related input files such as + "lexicon.txt" + + - lr: It specifies the initial learning rate + + - feature_dim: The model input dim. It has to match the one used + in computing features. + + - weight_decay: The weight_decay for the optimizer. + + - subsampling_factor: The subsampling factor for the model. + + - best_train_loss: Best training loss so far. It is used to select + the model that has the lowest training loss. It is + updated during the training. + + - best_valid_loss: Best validation loss so far. It is used to select + the model that has the lowest validation loss. It is + updated during the training. + + - best_train_epoch: It is the epoch that has the best training loss. + + - best_valid_epoch: It is the epoch that has the best validation loss. + + - batch_idx_train: Used to writing statistics to tensorboard. It + contains number of batches trained so far across + epochs. + + - log_interval: Print training loss if batch_idx % log_interval` is 0 + + - reset_interval: Reset statistics if batch_idx % reset_interval is 0 + + - valid_interval: Run validation if batch_idx % valid_interval` is 0 + + - beam_size: It is used in k2.ctc_loss + + - reduction: It is used in k2.ctc_loss + + - use_double_scores: It is used in k2.ctc_loss + """ + params = AttributeDict( + { + "exp_dir": Path("tdnn_lstm_ctc/exp_lr1e-4"), + "lang_dir": Path("data/lang_phone"), + "lr": 1e-4, + "feature_dim": 80, + "weight_decay": 5e-4, + "subsampling_factor": 3, + "best_train_loss": float("inf"), + "best_valid_loss": float("inf"), + "best_train_epoch": -1, + "best_valid_epoch": -1, + "batch_idx_train": 0, + "log_interval": 10, + "reset_interval": 200, + "valid_interval": 1000, + "beam_size": 10, + "reduction": "sum", + "use_double_scores": True, + } + ) + + return params + + +def load_checkpoint_if_available( + params: AttributeDict, + model: nn.Module, + optimizer: Optional[torch.optim.Optimizer] = None, + scheduler: Optional[torch.optim.lr_scheduler._LRScheduler] = None, +) -> None: + """Load checkpoint from file. + + If params.start_epoch is positive, it will load the checkpoint from + `params.start_epoch - 1`. Otherwise, this function does nothing. + + Apart from loading state dict for `model`, `optimizer` and `scheduler`, + it also updates `best_train_epoch`, `best_train_loss`, `best_valid_epoch`, + and `best_valid_loss` in `params`. + + Args: + params: + The return value of :func:`get_params`. + model: + The training model. + optimizer: + The optimizer that we are using. + scheduler: + The learning rate scheduler we are using. + Returns: + Return None. + """ + if params.start_epoch <= 0: + return + + filename = params.exp_dir / f"epoch-{params.start_epoch-1}.pt" + saved_params = load_checkpoint( + filename, + model=model, + optimizer=optimizer, + scheduler=scheduler, + ) + + keys = [ + "best_train_epoch", + "best_valid_epoch", + "batch_idx_train", + "best_train_loss", + "best_valid_loss", + ] + for k in keys: + params[k] = saved_params[k] + + return saved_params + + +def save_checkpoint( + params: AttributeDict, + model: nn.Module, + optimizer: torch.optim.Optimizer, + scheduler: torch.optim.lr_scheduler._LRScheduler, + rank: int = 0, +) -> None: + """Save model, optimizer, scheduler and training stats to file. + + Args: + params: + It is returned by :func:`get_params`. + model: + The training model. + """ + if rank != 0: + return + filename = params.exp_dir / f"epoch-{params.cur_epoch}.pt" + save_checkpoint_impl( + filename=filename, + model=model, + params=params, + optimizer=optimizer, + scheduler=scheduler, + rank=rank, + ) + + if params.best_train_epoch == params.cur_epoch: + best_train_filename = params.exp_dir / "best-train-loss.pt" + copyfile(src=filename, dst=best_train_filename) + + if params.best_valid_epoch == params.cur_epoch: + best_valid_filename = params.exp_dir / "best-valid-loss.pt" + copyfile(src=filename, dst=best_valid_filename) + + +def compute_loss( + params: AttributeDict, + model: nn.Module, + batch: dict, + graph_compiler: CtcTrainingGraphCompiler, + is_training: bool, +): + """ + Compute CTC loss given the model and its inputs. + + Args: + params: + Parameters for training. See :func:`get_params`. + model: + The model for training. It is an instance of TdnnLstm in our case. + batch: + A batch of data. See `lhotse.dataset.K2SpeechRecognitionDataset()` + for the content in it. + graph_compiler: + It is used to build a decoding graph from a ctc topo and training + transcript. The training transcript is contained in the given `batch`, + while the ctc topo is built when this compiler is instantiated. + is_training: + True for training. False for validation. When it is True, this + function enables autograd during computation; when it is False, it + disables autograd. + """ + device = graph_compiler.device + feature = batch["inputs"] + # at entry, feature is [N, T, C] + feature = feature.permute(0, 2, 1) # now feature is [N, C, T] + assert feature.ndim == 3 + feature = feature.to(device) + + with torch.set_grad_enabled(is_training): + nnet_output = model(feature) + # nnet_output is [N, T, C] + + # NOTE: We need `encode_supervisions` to sort sequences with + # different duration in decreasing order, required by + # `k2.intersect_dense` called in `k2.ctc_loss` + supervisions = batch["supervisions"] + supervision_segments, texts = encode_supervisions( + supervisions, subsampling_factor=params.subsampling_factor + ) + decoding_graph = graph_compiler.compile(texts) + + dense_fsa_vec = k2.DenseFsaVec( + nnet_output, + supervision_segments, + allow_truncate=params.subsampling_factor - 1, + ) + + loss = k2.ctc_loss( + decoding_graph=decoding_graph, + dense_fsa_vec=dense_fsa_vec, + output_beam=params.beam_size, + reduction=params.reduction, + use_double_scores=params.use_double_scores, + ) + + assert loss.requires_grad == is_training + + # train_frames and valid_frames are used for printing. + if is_training: + params.train_frames = supervision_segments[:, 2].sum().item() + else: + params.valid_frames = supervision_segments[:, 2].sum().item() + + return loss + + +def compute_validation_loss( + params: AttributeDict, + model: nn.Module, + graph_compiler: CtcTrainingGraphCompiler, + valid_dl: torch.utils.data.DataLoader, + world_size: int = 1, +) -> None: + """Run the validation process. The validation loss + is saved in `params.valid_loss`. + """ + model.eval() + + tot_loss = 0.0 + tot_frames = 0.0 + for batch_idx, batch in enumerate(valid_dl): + loss = compute_loss( + params=params, + model=model, + batch=batch, + graph_compiler=graph_compiler, + is_training=False, + ) + assert loss.requires_grad is False + + loss_cpu = loss.detach().cpu().item() + tot_loss += loss_cpu + tot_frames += params.valid_frames + + if world_size > 1: + s = torch.tensor([tot_loss, tot_frames], device=loss.device) + dist.all_reduce(s, op=dist.ReduceOp.SUM) + s = s.cpu().tolist() + tot_loss = s[0] + tot_frames = s[1] + + params.valid_loss = tot_loss / tot_frames + + if params.valid_loss < params.best_valid_loss: + params.best_valid_epoch = params.cur_epoch + params.best_valid_loss = params.valid_loss + + +def train_one_epoch( + params: AttributeDict, + model: nn.Module, + optimizer: torch.optim.Optimizer, + graph_compiler: CtcTrainingGraphCompiler, + train_dl: torch.utils.data.DataLoader, + valid_dl: torch.utils.data.DataLoader, + tb_writer: Optional[SummaryWriter] = None, + world_size: int = 1, +) -> None: + """Train the model for one epoch. + + The training loss from the mean of all frames is saved in + `params.train_loss`. It runs the validation process every + `params.valid_interval` batches. + + Args: + params: + It is returned by :func:`get_params`. + model: + The model for training. + optimizer: + The optimizer we are using. + graph_compiler: + It is used to convert transcripts to FSAs. + train_dl: + Dataloader for the training dataset. + valid_dl: + Dataloader for the validation dataset. + tb_writer: + Writer to write log messages to tensorboard. + world_size: + Number of nodes in DDP training. If it is 1, DDP is disabled. + """ + model.train() + + tot_loss = 0.0 # reset after params.reset_interval of batches + tot_frames = 0.0 # reset after params.reset_interval of batches + + params.tot_loss = 0.0 + params.tot_frames = 0.0 + + for batch_idx, batch in enumerate(train_dl): + params.batch_idx_train += 1 + batch_size = len(batch["supervisions"]["text"]) + + loss = compute_loss( + params=params, + model=model, + batch=batch, + graph_compiler=graph_compiler, + is_training=True, + ) + + # NOTE: We use reduction==sum and loss is computed over utterances + # in the batch and there is no normalization to it so far. + + optimizer.zero_grad() + loss.backward() + clip_grad_norm_(model.parameters(), 5.0, 2.0) + optimizer.step() + + loss_cpu = loss.detach().cpu().item() + + tot_frames += params.train_frames + tot_loss += loss_cpu + tot_avg_loss = tot_loss / tot_frames + + params.tot_frames += params.train_frames + params.tot_loss += loss_cpu + + if batch_idx % params.log_interval == 0: + logging.info( + f"Epoch {params.cur_epoch}, batch {batch_idx}, " + f"batch avg loss {loss_cpu/params.train_frames:.4f}, " + f"total avg loss: {tot_avg_loss:.4f}, " + f"batch size: {batch_size}" + ) + if tb_writer is not None: + tb_writer.add_scalar( + "train/current_loss", + loss_cpu / params.train_frames, + params.batch_idx_train, + ) + + tb_writer.add_scalar( + "train/tot_avg_loss", + tot_avg_loss, + params.batch_idx_train, + ) + + if batch_idx > 0 and batch_idx % params.reset_interval == 0: + tot_loss = 0 + tot_frames = 0 + + if batch_idx > 0 and batch_idx % params.valid_interval == 0: + compute_validation_loss( + params=params, + model=model, + graph_compiler=graph_compiler, + valid_dl=valid_dl, + world_size=world_size, + ) + model.train() + logging.info( + f"Epoch {params.cur_epoch}, valid loss {params.valid_loss:.4f}," + f" best valid loss: {params.best_valid_loss:.4f} " + f"best valid epoch: {params.best_valid_epoch}" + ) + + params.train_loss = params.tot_loss / params.tot_frames + + if params.train_loss < params.best_train_loss: + params.best_train_epoch = params.cur_epoch + params.best_train_loss = params.train_loss + + +def run(rank, world_size, args): + """ + Args: + rank: + It is a value between 0 and `world_size-1`, which is + passed automatically by `mp.spawn()` in :func:`main`. + The node with rank 0 is responsible for saving checkpoint. + world_size: + Number of GPUs for DDP training. + args: + The return value of get_parser().parse_args() + """ + params = get_params() + params.update(vars(args)) + + fix_random_seed(42) + if world_size > 1: + setup_dist(rank, world_size, params.master_port) + + setup_logger(f"{params.exp_dir}/log/log-train") + logging.info("Training started") + logging.info(params) + + if args.tensorboard and rank == 0: + tb_writer = SummaryWriter(log_dir=f"{params.exp_dir}/tensorboard") + else: + tb_writer = None + + lexicon = Lexicon(params.lang_dir) + max_phone_id = max(lexicon.tokens) + + device = torch.device("cpu") + if torch.cuda.is_available(): + device = torch.device("cuda", rank) + + graph_compiler = CtcTrainingGraphCompiler(lexicon=lexicon, device=device) + + model = TdnnLstm( + num_features=params.feature_dim, + num_classes=max_phone_id + 1, # +1 for the blank symbol + subsampling_factor=params.subsampling_factor, + ) + + checkpoints = load_checkpoint_if_available(params=params, model=model) + + model.to(device) + if world_size > 1: + model = DDP(model, device_ids=[rank]) + + optimizer = optim.AdamW( + model.parameters(), + lr=params.lr, + weight_decay=params.weight_decay, + ) + scheduler = StepLR(optimizer, step_size=8, gamma=0.1) + + if checkpoints: + optimizer.load_state_dict(checkpoints["optimizer"]) + scheduler.load_state_dict(checkpoints["scheduler"]) + + aishell = AishellAsrDataModule(args) + train_dl = aishell.train_dataloaders() + valid_dl = aishell.valid_dataloaders() + + for epoch in range(params.start_epoch, params.num_epochs): + train_dl.sampler.set_epoch(epoch) + + if epoch > params.start_epoch: + logging.info(f"epoch {epoch}, lr: {scheduler.get_last_lr()[0]}") + + if tb_writer is not None: + tb_writer.add_scalar( + "train/lr", + scheduler.get_last_lr()[0], + params.batch_idx_train, + ) + tb_writer.add_scalar("train/epoch", epoch, params.batch_idx_train) + + params.cur_epoch = epoch + + train_one_epoch( + params=params, + model=model, + optimizer=optimizer, + graph_compiler=graph_compiler, + train_dl=train_dl, + valid_dl=valid_dl, + tb_writer=tb_writer, + world_size=world_size, + ) + + scheduler.step() + + save_checkpoint( + params=params, + model=model, + optimizer=optimizer, + scheduler=scheduler, + rank=rank, + ) + + logging.info("Done!") + if world_size > 1: + torch.distributed.barrier() + cleanup_dist() + + +def main(): + parser = get_parser() + AishellAsrDataModule.add_arguments(parser) + args = parser.parse_args() + + world_size = args.world_size + assert world_size >= 1 + if world_size > 1: + mp.spawn(run, args=(world_size, args), nprocs=world_size, join=True) + else: + run(rank=0, world_size=1, args=args) + + +if __name__ == "__main__": + main() diff --git a/icefall/char_graph_compiler.py b/icefall/char_graph_compiler.py new file mode 100644 index 000000000..4a79a300a --- /dev/null +++ b/icefall/char_graph_compiler.py @@ -0,0 +1,99 @@ +# Copyright 2021 Xiaomi Corp. (authors: Fangjun Kuang, +# Wei Kang) +# +# See ../../LICENSE for clarification regarding multiple authors +# +# 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 re +from typing import List + +import k2 +import torch + +from icefall.lexicon import Lexicon + + +class CharCtcTrainingGraphCompiler(object): + def __init__( + self, + lexicon: Lexicon, + device: torch.device, + sos_token: str = "", + eos_token: str = "", + oov: str = "", + ): + """ + Args: + lexicon: + It is built from `data/lang/lexicon.txt`. + device: + The device to use for operations compiling transcripts to FSAs. + oov: + Out of vocabulary token. When a word(token) in the transcript + does not exist in the token list, it is replaced with `oov`. + """ + + assert oov in lexicon.token_table + + self.oov_id = lexicon.token_table[oov] + self.token_table = lexicon.token_table + + self.device = device + + self.sos_id = self.token_table[sos_token] + self.eos_id = self.token_table[eos_token] + + def texts_to_ids(self, texts: List[str]) -> List[List[int]]: + """Convert a list of texts to a list-of-list of token IDs. + + Args: + texts: + It is a list of strings. + An example containing two strings is given below: + + ['你好中国', '北京欢迎您'] + Returns: + Return a list-of-list of token IDs. + """ + ids: List[List[int]] = [] + whitespace = re.compile(r"([ \t])") + for text in texts: + text = re.sub(whitespace, "", text) + sub_ids = [ + self.token_table[txt] + if txt in self.token_table + else self.oov_id + for txt in text + ] + ids.append(sub_ids) + return ids + + def compile( + self, + token_ids: List[List[int]], + modified: bool = False, + ) -> k2.Fsa: + """Build a ctc graph from a list-of-list token IDs. + + Args: + piece_ids: + It is a list-of-list integer IDs. + modified: + See :func:`k2.ctc_graph` for its meaning. + Return: + Return an FsaVec, which is the result of composing a + CTC topology with linear FSAs constructed from the given + piece IDs. + """ + return k2.ctc_graph(token_ids, modified=modified, device=self.device) diff --git a/icefall/utils.py b/icefall/utils.py index 287b917c5..1d4aabd72 100644 --- a/icefall/utils.py +++ b/icefall/utils.py @@ -104,7 +104,6 @@ def setup_logger( """ now = datetime.now() date_time = now.strftime("%Y-%m-%d-%H-%M-%S") - if dist.is_available() and dist.is_initialized(): world_size = dist.get_world_size() rank = dist.get_rank()