Committed by
GitHub
Provide models for mobile-only platforms by fixing batch size to 1 (#1276)
正在显示
6 个修改的文件
包含
287 行增加
和
0 行删除
.github/workflows/mobile-asr-models.yaml
0 → 100644
| 1 | +name: mobile-asr-models | ||
| 2 | + | ||
| 3 | +on: | ||
| 4 | + push: | ||
| 5 | + branches: | ||
| 6 | + - asr-mobile | ||
| 7 | + | ||
| 8 | + workflow_dispatch: | ||
| 9 | + | ||
| 10 | + | ||
| 11 | +concurrency: | ||
| 12 | + group: mobile-asr-models-${{ github.ref }} | ||
| 13 | + cancel-in-progress: true | ||
| 14 | + | ||
| 15 | +jobs: | ||
| 16 | + mobile-asr-models: | ||
| 17 | + if: github.repository_owner == 'k2-fsa' || github.repository_owner == 'csukuangfj' || github.repository_owner == 'csu-fangjun' | ||
| 18 | + runs-on: ${{ matrix.os }} | ||
| 19 | + strategy: | ||
| 20 | + fail-fast: false | ||
| 21 | + matrix: | ||
| 22 | + os: [ubuntu-latest] | ||
| 23 | + python-version: ["3.8"] | ||
| 24 | + | ||
| 25 | + steps: | ||
| 26 | + - uses: actions/checkout@v4 | ||
| 27 | + | ||
| 28 | + - name: Setup Python ${{ matrix.python-version }} | ||
| 29 | + uses: actions/setup-python@v5 | ||
| 30 | + with: | ||
| 31 | + python-version: ${{ matrix.python-version }} | ||
| 32 | + | ||
| 33 | + - name: Install dependencies | ||
| 34 | + shell: bash | ||
| 35 | + run: | | ||
| 36 | + python3 -m pip install onnxruntime==1.16.3 onnx==1.15.0 | ||
| 37 | + | ||
| 38 | + - name: Run | ||
| 39 | + shell: bash | ||
| 40 | + run: | | ||
| 41 | + cd scripts/mobile-asr-models | ||
| 42 | + ./run.sh | ||
| 43 | + | ||
| 44 | + - name: Release | ||
| 45 | + uses: svenstaro/upload-release-action@v2 | ||
| 46 | + with: | ||
| 47 | + file_glob: true | ||
| 48 | + file: ./*.tar.bz2 | ||
| 49 | + overwrite: true | ||
| 50 | + repo_name: k2-fsa/sherpa-onnx | ||
| 51 | + repo_token: ${{ secrets.UPLOAD_GH_SHERPA_ONNX_TOKEN }} | ||
| 52 | + tag: asr-models |
scripts/mobile-asr-models/README.md
0 → 100644
| 1 | +# Introduction | ||
| 2 | + | ||
| 3 | +This folder contains scripts to convert ASR models for mobile platforms | ||
| 4 | +supporting only batch size equal to 1. | ||
| 5 | + | ||
| 6 | +The advantage of fixing the batch size to 1 is that it provides more | ||
| 7 | +opportunities for model optimization and quantization. | ||
| 8 | + | ||
| 9 | +To give you a concrete example, for the following model | ||
| 10 | +https://k2-fsa.github.io/sherpa/onnx/pretrained_models/online-transducer/zipformer-transducer-models.html#csukuangfj-sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20-bilingual-chinese-english | ||
| 11 | + | ||
| 12 | +| | encoder-epoch-99-avg-1.onnx | encoder-epoch-99-avg-1.int8.onnx| | ||
| 13 | +|---|---|---| | ||
| 14 | +|Dynamic batch size| 315 MB| 174 MB| | ||
| 15 | +|Batch size fixed to 1| 242 MB | 100 MB | | ||
| 16 | + | ||
| 17 | +The following [colab notebook](https://colab.research.google.com/drive/1RsVZbsxbPjazeGrNNbZNjXCYbEG2F2DU?usp=sharing) | ||
| 18 | +provides examples to use the above two models. |
| 1 | +#!/usr/bin/env python3 | ||
| 2 | +import argparse | ||
| 3 | + | ||
| 4 | +from onnxruntime.quantization import QuantType, quantize_dynamic | ||
| 5 | + | ||
| 6 | + | ||
| 7 | +def get_args(): | ||
| 8 | + parser = argparse.ArgumentParser() | ||
| 9 | + parser.add_argument( | ||
| 10 | + "--input", | ||
| 11 | + type=str, | ||
| 12 | + required=True, | ||
| 13 | + help="Input onnx model", | ||
| 14 | + ) | ||
| 15 | + | ||
| 16 | + parser.add_argument( | ||
| 17 | + "--output", | ||
| 18 | + type=str, | ||
| 19 | + required=True, | ||
| 20 | + help="Output onnx model", | ||
| 21 | + ) | ||
| 22 | + return parser.parse_args() | ||
| 23 | + | ||
| 24 | + | ||
| 25 | +def main(): | ||
| 26 | + args = get_args() | ||
| 27 | + print(vars(args)) | ||
| 28 | + | ||
| 29 | + quantize_dynamic( | ||
| 30 | + model_input=args.input, | ||
| 31 | + model_output=args.output, | ||
| 32 | + op_types_to_quantize=["MatMul"], | ||
| 33 | + weight_type=QuantType.QInt8, | ||
| 34 | + ) | ||
| 35 | + | ||
| 36 | + | ||
| 37 | +if __name__ == "__main__": | ||
| 38 | + main() |
scripts/mobile-asr-models/parse_options.sh
0 → 100755
| 1 | +#!/usr/bin/env bash | ||
| 2 | + | ||
| 3 | +# Copyright 2012 Johns Hopkins University (Author: Daniel Povey); | ||
| 4 | +# Arnab Ghoshal, Karel Vesely | ||
| 5 | + | ||
| 6 | +# Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 7 | +# you may not use this file except in compliance with the License. | ||
| 8 | +# You may obtain a copy of the License at | ||
| 9 | +# | ||
| 10 | +# http://www.apache.org/licenses/LICENSE-2.0 | ||
| 11 | +# | ||
| 12 | +# THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| 13 | +# KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED | ||
| 14 | +# WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, | ||
| 15 | +# MERCHANTABLITY OR NON-INFRINGEMENT. | ||
| 16 | +# See the Apache 2 License for the specific language governing permissions and | ||
| 17 | +# limitations under the License. | ||
| 18 | + | ||
| 19 | + | ||
| 20 | +# Parse command-line options. | ||
| 21 | +# To be sourced by another script (as in ". parse_options.sh"). | ||
| 22 | +# Option format is: --option-name arg | ||
| 23 | +# and shell variable "option_name" gets set to value "arg." | ||
| 24 | +# The exception is --help, which takes no arguments, but prints the | ||
| 25 | +# $help_message variable (if defined). | ||
| 26 | + | ||
| 27 | + | ||
| 28 | +### | ||
| 29 | +### The --config file options have lower priority to command line | ||
| 30 | +### options, so we need to import them first... | ||
| 31 | +### | ||
| 32 | + | ||
| 33 | +# Now import all the configs specified by command-line, in left-to-right order | ||
| 34 | +for ((argpos=1; argpos<$#; argpos++)); do | ||
| 35 | + if [ "${!argpos}" == "--config" ]; then | ||
| 36 | + argpos_plus1=$((argpos+1)) | ||
| 37 | + config=${!argpos_plus1} | ||
| 38 | + [ ! -r $config ] && echo "$0: missing config '$config'" && exit 1 | ||
| 39 | + . $config # source the config file. | ||
| 40 | + fi | ||
| 41 | +done | ||
| 42 | + | ||
| 43 | + | ||
| 44 | +### | ||
| 45 | +### Now we process the command line options | ||
| 46 | +### | ||
| 47 | +while true; do | ||
| 48 | + [ -z "${1:-}" ] && break; # break if there are no arguments | ||
| 49 | + case "$1" in | ||
| 50 | + # If the enclosing script is called with --help option, print the help | ||
| 51 | + # message and exit. Scripts should put help messages in $help_message | ||
| 52 | + --help|-h) if [ -z "$help_message" ]; then echo "No help found." 1>&2; | ||
| 53 | + else printf "$help_message\n" 1>&2 ; fi; | ||
| 54 | + exit 0 ;; | ||
| 55 | + --*=*) echo "$0: options to scripts must be of the form --name value, got '$1'" | ||
| 56 | + exit 1 ;; | ||
| 57 | + # If the first command-line argument begins with "--" (e.g. --foo-bar), | ||
| 58 | + # then work out the variable name as $name, which will equal "foo_bar". | ||
| 59 | + --*) name=`echo "$1" | sed s/^--// | sed s/-/_/g`; | ||
| 60 | + # Next we test whether the variable in question is undefned-- if so it's | ||
| 61 | + # an invalid option and we die. Note: $0 evaluates to the name of the | ||
| 62 | + # enclosing script. | ||
| 63 | + # The test [ -z ${foo_bar+xxx} ] will return true if the variable foo_bar | ||
| 64 | + # is undefined. We then have to wrap this test inside "eval" because | ||
| 65 | + # foo_bar is itself inside a variable ($name). | ||
| 66 | + eval '[ -z "${'$name'+xxx}" ]' && echo "$0: invalid option $1" 1>&2 && exit 1; | ||
| 67 | + | ||
| 68 | + oldval="`eval echo \\$$name`"; | ||
| 69 | + # Work out whether we seem to be expecting a Boolean argument. | ||
| 70 | + if [ "$oldval" == "true" ] || [ "$oldval" == "false" ]; then | ||
| 71 | + was_bool=true; | ||
| 72 | + else | ||
| 73 | + was_bool=false; | ||
| 74 | + fi | ||
| 75 | + | ||
| 76 | + # Set the variable to the right value-- the escaped quotes make it work if | ||
| 77 | + # the option had spaces, like --cmd "queue.pl -sync y" | ||
| 78 | + eval $name=\"$2\"; | ||
| 79 | + | ||
| 80 | + # Check that Boolean-valued arguments are really Boolean. | ||
| 81 | + if $was_bool && [[ "$2" != "true" && "$2" != "false" ]]; then | ||
| 82 | + echo "$0: expected \"true\" or \"false\": $1 $2" 1>&2 | ||
| 83 | + exit 1; | ||
| 84 | + fi | ||
| 85 | + shift 2; | ||
| 86 | + ;; | ||
| 87 | + *) break; | ||
| 88 | + esac | ||
| 89 | +done | ||
| 90 | + | ||
| 91 | + | ||
| 92 | +# Check for an empty argument to the --cmd option, which can easily occur as a | ||
| 93 | +# result of scripting errors. | ||
| 94 | +[ ! -z "${cmd+xxx}" ] && [ -z "$cmd" ] && echo "$0: empty argument to --cmd option" 1>&2 && exit 1; | ||
| 95 | + | ||
| 96 | + | ||
| 97 | +true; # so this script returns exit code 0. |
scripts/mobile-asr-models/run-impl.sh
0 → 100755
| 1 | +#!/usr/bin/env bash | ||
| 2 | +# | ||
| 3 | +# usage of this file: | ||
| 4 | +# ./run.sh --input in.onnx --output1 out1.onnx --output2 out2.onnx | ||
| 5 | +# where out1.onnx is a float32 model with batch size fixed to 1 | ||
| 6 | +# and out2.onnx is an int8 quantized version of out1.onnx | ||
| 7 | + | ||
| 8 | +set -ex | ||
| 9 | + | ||
| 10 | +input= | ||
| 11 | +output1= | ||
| 12 | +output2= | ||
| 13 | +batch_dim=N | ||
| 14 | +source ./parse_options.sh | ||
| 15 | + | ||
| 16 | +if [ -z $input ]; then | ||
| 17 | + echo 'Please provide input model filename' | ||
| 18 | + exit 1 | ||
| 19 | +fi | ||
| 20 | + | ||
| 21 | +if [ -z $output1 ]; then | ||
| 22 | + echo 'Please provide output1 model filename' | ||
| 23 | + exit 1 | ||
| 24 | +fi | ||
| 25 | + | ||
| 26 | +if [ -z $output2 ]; then | ||
| 27 | + echo 'Please provide output2 model filename' | ||
| 28 | + exit 1 | ||
| 29 | +fi | ||
| 30 | + | ||
| 31 | + | ||
| 32 | +echo "input: $input" | ||
| 33 | +echo "output1: $output1" | ||
| 34 | +echo "output2: $output2" | ||
| 35 | + | ||
| 36 | +python3 -m onnxruntime.tools.make_dynamic_shape_fixed --dim_param $batch_dim --dim_value 1 $input tmp.fixed.onnx | ||
| 37 | +python3 -m onnxruntime.quantization.preprocess --input tmp.fixed.onnx --output $output1 | ||
| 38 | +python3 ./dynamic_quantization.py --input $output1 --output $output2 | ||
| 39 | + | ||
| 40 | +ls -lh $input tmp.fixed.onnx $output1 $output2 | ||
| 41 | + | ||
| 42 | +rm tmp.fixed.onnx |
scripts/mobile-asr-models/run.sh
0 → 100755
| 1 | +#!/usr/bin/env bash | ||
| 2 | + | ||
| 3 | +set -ex | ||
| 4 | + | ||
| 5 | +curl -SL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20.tar.bz2 | ||
| 6 | +tar xvf sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20.tar.bz2 | ||
| 7 | +rm sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20.tar.bz2 | ||
| 8 | + | ||
| 9 | +src=sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20 | ||
| 10 | +dst=$src-mobile | ||
| 11 | + | ||
| 12 | +mkdir -p $dst | ||
| 13 | + | ||
| 14 | +./run-impl.sh \ | ||
| 15 | + --input $src/encoder-epoch-99-avg-1.onnx \ | ||
| 16 | + --output1 $dst/encoder-epoch-99-avg-1.onnx \ | ||
| 17 | + --output2 $dst/encoder-epoch-99-avg-1.int8.onnx | ||
| 18 | + | ||
| 19 | +cp -v $src/README.md $dst/ | ||
| 20 | +cp -v $src/tokens.txt $dst/ | ||
| 21 | +cp -av $src/test_wavs $dst/ | ||
| 22 | +cp -v $src/decoder-epoch-99-avg-1.onnx $dst/ | ||
| 23 | +cp -v $src/joiner-epoch-99-avg-1.int8.onnx $dst/ | ||
| 24 | + | ||
| 25 | +cat > $dst/notes.md <<EOF | ||
| 26 | +# Introduction | ||
| 27 | +This model is converted from | ||
| 28 | +https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/$src.tar.bz2 | ||
| 29 | +and it supports only batch size equal to 1. | ||
| 30 | +EOF | ||
| 31 | + | ||
| 32 | +echo "---$src---" | ||
| 33 | +ls -lh $src | ||
| 34 | +echo "---$dst---" | ||
| 35 | +ls -lh $dst | ||
| 36 | +rm -rf $src | ||
| 37 | + | ||
| 38 | +tar cjfv $dst.tar.bz2 $dst | ||
| 39 | +mv *.tar.bz2 ../../ | ||
| 40 | +rm -rf $dst |
-
请 注册 或 登录 后发表评论