Merge pull request #1868 from JRMeyer/data-augmentation-cleaning

Add logging and clean up some augmentation code
This commit is contained in:
Josh Meyer 2021-05-18 07:05:12 -04:00 committed by GitHub
commit ac2bbd6a79
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 42 additions and 21 deletions

View File

@ -1,4 +1,3 @@
import os
import re
import math
@ -10,6 +9,7 @@ from multiprocessing import Queue, Process
from .audio import gain_db_to_ratio, max_dbfs, normalize_audio, AUDIO_TYPE_NP, AUDIO_TYPE_PCM, AUDIO_TYPE_OPUS
from .helpers import LimitingPool, int_range, float_range, pick_value_from_range, tf_pick_value_from_range, MEGABYTE
from .sample_collections import samples_from_source, unpack_maybe
from .logging import log_info
BUFFER_SIZE = 1 * MEGABYTE
SPEC_PARSER = re.compile(r'^(?P<cls>[a-z_]+)(\[(?P<params>.*)\])?$')
@ -90,6 +90,7 @@ def parse_augmentation(augmentation_spec):
kwargs[pair[0]] = pair[1]
else:
raise ValueError('Unable to parse augmentation value assignment')
log_info('Processed augmentation type: [{}] with parameter settings: {}'.format(augmentation_cls.__name__, kwargs))
return augmentation_cls(*args, **kwargs)
@ -106,7 +107,7 @@ def parse_augmentations(augmentation_specs):
-------
List of augmentation class instances from util.augmentations.*.
"""
return [] if augmentation_specs is None else list(map(parse_augmentation, augmentation_specs))
return list(map(parse_augmentation, augmentation_specs or []))
def apply_graph_augmentations(domain, tensor, augmentations, transcript=None, clock=0.0):

View File

@ -163,27 +163,41 @@ def remember_exception(iterable, exception_box=None):
def get_value_range(value, target_type):
"""
This function converts all possible supplied values for augmentation
into the [start,end,r] ValueRange type. The expected inputs are of the form:
<number>
<number>~<number>
<number>:<number>~<number>
Any "missing" values are filled so that ValueRange always includes [start,end,r].
"""
if isinstance(value, str):
r = target_type(0)
parts = value.split('~')
if len(parts) == 2:
if '~' in value:
parts = value.split('~')
if len(parts) != 2:
raise ValueError('Cannot parse value range')
value = parts[0]
r = target_type(parts[1])
elif len(parts) > 2:
raise ValueError('Cannot parse value range')
r = parts[1]
else:
r = 0 # if no <r> supplied, use 0
parts = value.split(':')
if len(parts) == 1:
parts.append(parts[0])
elif len(parts) > 2:
parts.append(parts[0]) # only one <value> given, so double it
if len(parts) != 2:
raise ValueError('Cannot parse value range')
return ValueRange(target_type(parts[0]), target_type(parts[1]), r)
return ValueRange(target_type(parts[0]), target_type(parts[1]), target_type(r))
if isinstance(value, tuple):
if len(value) == 2:
return ValueRange(target_type(value[0]), target_type(value[1]), 0)
return ValueRange(target_type(value[0]), target_type(value[1]), target_type(0))
if len(value) == 3:
return ValueRange(target_type(value[0]), target_type(value[1]), target_type(value[2]))
raise ValueError('Cannot convert to ValueRange: Wrong tuple size')
return ValueRange(target_type(value), target_type(value), 0)
else:
raise ValueError('Cannot convert to ValueRange: Wrong tuple size')
if isinstance(value, int) or isinstance(value, float):
return ValueRange(target_type(value), target_type(value), target_type(0))
raise ValueError('Cannot convert to ValueRange: Wrong tuple size')
def int_range(value):
@ -203,14 +217,20 @@ def pick_value_from_range(value_range, clock=None):
def tf_pick_value_from_range(value_range, clock=None, double_precision=False):
import tensorflow as tf # pylint: disable=import-outside-toplevel
clock = (tf.random.stateless_uniform([], seed=(-1, 1), dtype=tf.float64) if clock is None
else tf.maximum(tf.constant(0.0, dtype=tf.float64), tf.minimum(tf.constant(1.0, dtype=tf.float64), clock)))
if clock is None:
clock = tf.random.stateless_uniform([], seed=(-1, 1), dtype=tf.float64)
else:
clock = tf.maximum(tf.constant(0.0, dtype=tf.float64),
tf.minimum(tf.constant(1.0, dtype=tf.float64), clock))
value = value_range.start + clock * (value_range.end - value_range.start)
value = tf.random.stateless_uniform([],
minval=value - value_range.r,
maxval=value + value_range.r,
seed=(clock * tf.int32.min, clock * tf.int32.max),
dtype=tf.float64)
if value_range.r:
# if the option <r> (<value>~<r>, randomization radius) is supplied,
# sample the value from a uniform distribution with "radius" <r>
value = tf.random.stateless_uniform([],
minval=value - value_range.r,
maxval=value + value_range.r,
seed=(clock * tf.int32.min, clock * tf.int32.max),
dtype=tf.float64)
if isinstance(value_range.start, int):
return tf.cast(tf.math.round(value), tf.int64 if double_precision else tf.int32)
return tf.cast(value, tf.float64 if double_precision else tf.float32)