E2E/Streaming Transformer/Conformer ASR (#578)
* add cmvn and label smoothing loss layer
* add layer for transformer
* add glu and conformer conv
* add torch compatiable hack, mask funcs
* not hack size since it exists
* add test; attention
* add attention, common utils, hack paddle
* add audio utils
* conformer batch padding mask bug fix #223
* fix typo, python infer fix rnn mem opt name error and batchnorm1d, will be available at 2.0.2
* fix ci
* fix ci
* add encoder
* refactor egs
* add decoder
* refactor ctc, add ctc align, refactor ckpt, add warmup lr scheduler, cmvn utils
* refactor docs
* add fix
* fix readme
* fix bugs, refactor collator, add pad_sequence, fix ckpt bugs
* fix docstring
* refactor data feed order
* add u2 model
* refactor cmvn, test
* add utils
* add u2 config
* fix bugs
* fix bugs
* fix autograd maybe has problem when using inplace operation
* refactor data, build vocab; add format data
* fix text featurizer
* refactor build vocab
* add fbank, refactor feature of speech
* refactor audio feat
* refactor data preprare
* refactor data
* model init from config
* add u2 bins
* flake8
* can train
* fix bugs, add coverage, add scripts
* test can run
* fix data
* speed perturb with sox
* add spec aug
* fix for train
* fix train logitc
* fix logger
* log valid loss, time dataset process
* using np for speed perturb, remove some debug log of grad clip
* fix logger
* fix build vocab
* fix logger name
* using module logger as default
* fix
* fix install
* reorder imports
* fix board logger
* fix logger
* kaldi fbank and mfcc
* fix cmvn and print prarams
* fix add_eos_sos and cmvn
* fix cmvn compute
* fix logger and cmvn
* fix subsampling, label smoothing loss, remove useless
* add notebook test
* fix log
* fix tb logger
* multi gpu valid
* fix log
* fix log
* fix config
* fix compute cmvn, need paddle 2.1
* add cmvn notebook
* fix layer tools
* fix compute cmvn
* add rtf
* fix decoding
* fix layer tools
* fix log, add avg script
* more avg and test info
* fix dataset pickle problem; using 2.1 paddle; num_workers can > 0; ckpt save in exp dir;fix setup.sh;
* add vimrc
* refactor tiny script, add transformer and stream conf
* spm demo; librisppech scripts and confs
* fix log
* add librispeech scripts
* refactor data pipe; fix conf; fix u2 default params
* fix bugs
* refactor aishell scripts
* fix test
* fix cmvn
* fix s0 scripts
* fix ds2 scripts and bugs
* fix dev & test dataset filter
* fix dataset filter
* filter dev
* fix ckpt path
* filter test, since librispeech will cause OOM, but all test wer will be worse, since mismatch train with test
* add comment
* add syllable doc
* fix ds2 configs
* add doc
* add pypinyin tools
* fix decoder using blank_id=0
* mmseg with pybind11
* format code
4 years ago
|
|
|
# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.
|
|
|
|
#
|
|
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
# you may not use this file except in compliance with the License.
|
|
|
|
# You may obtain a copy of the License at
|
|
|
|
#
|
|
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
#
|
|
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
# See the License for the specific language governing permissions and
|
|
|
|
# limitations under the License.
|
|
|
|
import getpass
|
|
|
|
import logging
|
|
|
|
import os
|
|
|
|
import socket
|
|
|
|
import sys
|
|
|
|
|
|
|
|
import auto_log
|
|
|
|
from paddle import inference
|
|
|
|
|
E2E/Streaming Transformer/Conformer ASR (#578)
* add cmvn and label smoothing loss layer
* add layer for transformer
* add glu and conformer conv
* add torch compatiable hack, mask funcs
* not hack size since it exists
* add test; attention
* add attention, common utils, hack paddle
* add audio utils
* conformer batch padding mask bug fix #223
* fix typo, python infer fix rnn mem opt name error and batchnorm1d, will be available at 2.0.2
* fix ci
* fix ci
* add encoder
* refactor egs
* add decoder
* refactor ctc, add ctc align, refactor ckpt, add warmup lr scheduler, cmvn utils
* refactor docs
* add fix
* fix readme
* fix bugs, refactor collator, add pad_sequence, fix ckpt bugs
* fix docstring
* refactor data feed order
* add u2 model
* refactor cmvn, test
* add utils
* add u2 config
* fix bugs
* fix bugs
* fix autograd maybe has problem when using inplace operation
* refactor data, build vocab; add format data
* fix text featurizer
* refactor build vocab
* add fbank, refactor feature of speech
* refactor audio feat
* refactor data preprare
* refactor data
* model init from config
* add u2 bins
* flake8
* can train
* fix bugs, add coverage, add scripts
* test can run
* fix data
* speed perturb with sox
* add spec aug
* fix for train
* fix train logitc
* fix logger
* log valid loss, time dataset process
* using np for speed perturb, remove some debug log of grad clip
* fix logger
* fix build vocab
* fix logger name
* using module logger as default
* fix
* fix install
* reorder imports
* fix board logger
* fix logger
* kaldi fbank and mfcc
* fix cmvn and print prarams
* fix add_eos_sos and cmvn
* fix cmvn compute
* fix logger and cmvn
* fix subsampling, label smoothing loss, remove useless
* add notebook test
* fix log
* fix tb logger
* multi gpu valid
* fix log
* fix log
* fix config
* fix compute cmvn, need paddle 2.1
* add cmvn notebook
* fix layer tools
* fix compute cmvn
* add rtf
* fix decoding
* fix layer tools
* fix log, add avg script
* more avg and test info
* fix dataset pickle problem; using 2.1 paddle; num_workers can > 0; ckpt save in exp dir;fix setup.sh;
* add vimrc
* refactor tiny script, add transformer and stream conf
* spm demo; librisppech scripts and confs
* fix log
* add librispeech scripts
* refactor data pipe; fix conf; fix u2 default params
* fix bugs
* refactor aishell scripts
* fix test
* fix cmvn
* fix s0 scripts
* fix ds2 scripts and bugs
* fix dev & test dataset filter
* fix dataset filter
* filter dev
* fix ckpt path
* filter test, since librispeech will cause OOM, but all test wer will be worse, since mismatch train with test
* add comment
* add syllable doc
* fix ds2 configs
* add doc
* add pypinyin tools
* fix decoder using blank_id=0
* mmseg with pybind11
* format code
4 years ago
|
|
|
FORMAT_STR = '[%(levelname)s %(asctime)s %(filename)s:%(lineno)d] %(message)s'
|
|
|
|
DATE_FMT_STR = '%Y/%m/%d %H:%M:%S'
|
|
|
|
|
|
|
|
logging.basicConfig(
|
|
|
|
level=logging.DEBUG, format=FORMAT_STR, datefmt=DATE_FMT_STR)
|
|
|
|
|
|
|
|
|
|
|
|
def find_log_dir(log_dir=None):
|
|
|
|
"""Returns the most suitable directory to put log files into.
|
|
|
|
Args:
|
|
|
|
log_dir: str|None, if specified, the logfile(s) will be created in that
|
|
|
|
directory. Otherwise if the --log_dir command-line flag is provided,
|
|
|
|
the logfile will be created in that directory. Otherwise the logfile
|
|
|
|
will be created in a standard location.
|
|
|
|
Raises:
|
|
|
|
FileNotFoundError: raised when it cannot find a log directory.
|
|
|
|
"""
|
|
|
|
# Get a list of possible log dirs (will try to use them in order).
|
|
|
|
if log_dir:
|
|
|
|
# log_dir was explicitly specified as an arg, so use it and it alone.
|
|
|
|
dirs = [log_dir]
|
|
|
|
else:
|
|
|
|
dirs = ['/tmp/', './']
|
|
|
|
|
|
|
|
# Find the first usable log dir.
|
|
|
|
for d in dirs:
|
|
|
|
if os.path.isdir(d) and os.access(d, os.W_OK):
|
|
|
|
return d
|
|
|
|
raise FileNotFoundError(
|
|
|
|
"Can't find a writable directory for logs, tried %s" % dirs)
|
|
|
|
|
|
|
|
|
|
|
|
def find_log_dir_and_names(program_name=None, log_dir=None):
|
|
|
|
"""Computes the directory and filename prefix for log file.
|
|
|
|
Args:
|
|
|
|
program_name: str|None, the filename part of the path to the program that
|
|
|
|
is running without its extension. e.g: if your program is called
|
|
|
|
'usr/bin/foobar.py' this method should probably be called with
|
|
|
|
program_name='foobar' However, this is just a convention, you can
|
|
|
|
pass in any string you want, and it will be used as part of the
|
|
|
|
log filename. If you don't pass in anything, the default behavior
|
|
|
|
is as described in the example. In python standard logging mode,
|
|
|
|
the program_name will be prepended with py_ if it is the program_name
|
|
|
|
argument is omitted.
|
|
|
|
log_dir: str|None, the desired log directory.
|
|
|
|
Returns:
|
|
|
|
(log_dir, file_prefix, symlink_prefix)
|
|
|
|
Raises:
|
|
|
|
FileNotFoundError: raised in Python 3 when it cannot find a log directory.
|
|
|
|
OSError: raised in Python 2 when it cannot find a log directory.
|
|
|
|
"""
|
|
|
|
if not program_name:
|
|
|
|
# Strip the extension (foobar.par becomes foobar, and
|
|
|
|
# fubar.py becomes fubar). We do this so that the log
|
|
|
|
# file names are similar to C++ log file names.
|
|
|
|
program_name = os.path.splitext(os.path.basename(sys.argv[0]))[0]
|
|
|
|
|
|
|
|
# Prepend py_ to files so that python code gets a unique file, and
|
|
|
|
# so that C++ libraries do not try to write to the same log files as us.
|
|
|
|
program_name = 'py_%s' % program_name
|
|
|
|
|
|
|
|
actual_log_dir = find_log_dir(log_dir=log_dir)
|
|
|
|
|
|
|
|
try:
|
|
|
|
username = getpass.getuser()
|
|
|
|
except KeyError:
|
|
|
|
# This can happen, e.g. when running under docker w/o passwd file.
|
|
|
|
if hasattr(os, 'getuid'):
|
|
|
|
# Windows doesn't have os.getuid
|
|
|
|
username = str(os.getuid())
|
|
|
|
else:
|
|
|
|
username = 'unknown'
|
|
|
|
hostname = socket.gethostname()
|
|
|
|
file_prefix = '%s.%s.%s.log' % (program_name, hostname, username)
|
|
|
|
|
|
|
|
return actual_log_dir, file_prefix, program_name
|
|
|
|
|
|
|
|
|
|
|
|
class Log():
|
|
|
|
|
|
|
|
log_name = None
|
|
|
|
|
|
|
|
def __init__(self, logger=None):
|
|
|
|
self.logger = logging.getLogger(logger)
|
|
|
|
self.logger.setLevel(logging.DEBUG)
|
|
|
|
|
|
|
|
file_dir = os.getcwd() + '/log'
|
|
|
|
if not os.path.exists(file_dir):
|
|
|
|
os.mkdir(file_dir)
|
|
|
|
self.log_dir = file_dir
|
|
|
|
|
|
|
|
actual_log_dir, file_prefix, symlink_prefix = find_log_dir_and_names(
|
|
|
|
program_name=None, log_dir=self.log_dir)
|
|
|
|
|
|
|
|
basename = '%s.DEBUG.%d' % (file_prefix, os.getpid())
|
|
|
|
filename = os.path.join(actual_log_dir, basename)
|
|
|
|
if Log.log_name is None:
|
|
|
|
Log.log_name = filename
|
|
|
|
|
|
|
|
# Create a symlink to the log file with a canonical name.
|
|
|
|
symlink = os.path.join(actual_log_dir, symlink_prefix + '.DEBUG')
|
|
|
|
try:
|
|
|
|
if os.path.islink(symlink):
|
|
|
|
os.unlink(symlink)
|
|
|
|
os.symlink(os.path.basename(Log.log_name), symlink)
|
|
|
|
except EnvironmentError:
|
|
|
|
# If it fails, we're sad but it's no error. Commonly, this
|
|
|
|
# fails because the symlink was created by another user and so
|
|
|
|
# we can't modify it
|
|
|
|
pass
|
|
|
|
|
|
|
|
if not self.logger.hasHandlers():
|
|
|
|
formatter = logging.Formatter(fmt=FORMAT_STR, datefmt=DATE_FMT_STR)
|
|
|
|
fh = logging.FileHandler(Log.log_name)
|
|
|
|
fh.setLevel(logging.DEBUG)
|
|
|
|
fh.setFormatter(formatter)
|
|
|
|
self.logger.addHandler(fh)
|
|
|
|
|
|
|
|
ch = logging.StreamHandler()
|
|
|
|
ch.setLevel(logging.INFO)
|
|
|
|
ch.setFormatter(formatter)
|
|
|
|
self.logger.addHandler(ch)
|
|
|
|
|
|
|
|
# stop propagate for propagating may print
|
|
|
|
# log multiple times
|
|
|
|
self.logger.propagate = False
|
|
|
|
|
|
|
|
def getlog(self):
|
|
|
|
return self.logger
|
|
|
|
|
|
|
|
|
|
|
|
class Autolog:
|
|
|
|
def __init__(self,
|
|
|
|
batch_size,
|
|
|
|
model_name="DeepSpeech",
|
|
|
|
model_precision="fp32"):
|
|
|
|
pid = os.getpid()
|
|
|
|
gpu_id = int(os.environ['CUDA_VISIBLE_DEVICES'].split(',')[0])
|
|
|
|
infer_config = inference.Config()
|
|
|
|
infer_config.enable_use_gpu(100, gpu_id)
|
|
|
|
autolog = auto_log.AutoLogger(
|
|
|
|
model_name=model_name,
|
|
|
|
model_precision=model_precision,
|
|
|
|
batch_size=batch_size,
|
|
|
|
data_shape="dynamic",
|
|
|
|
save_path="./output/auto_log.lpg",
|
|
|
|
inference_config=infer_config,
|
|
|
|
pids=pid,
|
|
|
|
process_name=None,
|
|
|
|
gpu_ids=gpu_id,
|
|
|
|
time_keys=['preprocess_time', 'inference_time', 'postprocess_time'],
|
|
|
|
warmup=0)
|
|
|
|
self.autolog = autolog
|
|
|
|
|
|
|
|
def getlog(self):
|
|
|
|
return self.autolog
|