def svd_affine(x, n_outputs, cr): W = get_parameter('affine/W') if W is None: UV = None else: UV = W.d b = get_parameter('affine/b') # compute rank (size of intermediate activations) # to obtained desired reduction inshape = np.prod(x.shape[1:]) outshape = np.prod(n_outputs) rank = int( np.floor((1 - cr) * inshape * outshape / (inshape + outshape))) # Initialize bias to existing b in affine if exists if b is not None: b_new = get_parameter_or_create('svd_affine/b', b.d.shape, need_grad=b.need_grad) b_new.d = b.d.copy() logger.info( "SVD affine created: input_shape = {}; output_shape = {}; compression = {}; rank = {};" .format(inshape, outshape, cr, rank)) # create svd_affine initialized from W in current context if it exists return PF.svd_affine(x, n_outputs, rank, uv_init=UV)
def svd_convolution(x, n_outputs, kernel, pad, with_bias, cr): W = get_parameter('conv/W') if W is None: UV = None else: UV = W.d b = get_parameter('conv/b') # compute rank (size of intermediate activations) # to obtained desired reduction inmaps = x.shape[1] outmaps = n_outputs Ksize = np.prod(kernel) rank = int( np.floor((1 - cr) * inmaps * outmaps * Ksize / (inmaps * Ksize + inmaps * outmaps))) # Initialize bias to existing b in affine if exists if b is not None: b_new = get_parameter_or_create('svd_conv/b', b.d.shape, need_grad=b.need_grad) b_new.d = b.d.copy() logger.info( "SVD convolution created: inmaps = {}; outmaps = {}; compression = {}; rank = {};" .format(inmaps, outmaps, cr, rank)) # create svd_convolution initialized from W in current context if it exists return PF.svd_convolution(x, n_outputs, kernel=kernel, r=rank, pad=pad, with_bias=with_bias, uv_init=UV)
def test_get_set_pop_parameter(): import nnabla as nn from nnabla.parameter import set_parameter, pop_parameter, get_parameter nn.clear_parameters() x = nn.Variable((2, 3, 4, 5)) key = 'a/b/c' set_parameter(key, x) x2 = get_parameter(key) assert x is x2 x3 = pop_parameter(key) assert x is x3 x4 = get_parameter(key) assert x4 is None
def _get_variable_or_create(self, name, shape, var_type): # The variable is a parameter, then get from parameter registry. if var_type == 'Parameter': try: param = get_parameter(name) assert param is not None, \ "A parameter `{}` is not found.".format(name) except: import sys import traceback raise ValueError( 'An error occurs during creation of a variable `{}` as a' ' parameter variable. The error was:\n----\n{}\n----\n' 'The parameters registered was {}'.format( name, traceback.format_exc(), '\n'.join( list(nn.get_parameters(grad_only=False).keys())))) assert shape == param.shape return param # Returns if variable is already created. try: var, count = self.vseen[name] count[0] += 1 except: # Create a new one and returns. var = nn.Variable(shape) self.vseen[name] = (var, [1]) return var # Found already created variable. assert var.shape == shape return var
def _get_variable_or_create(self, v, callback, current_scope): if v.variable is not None: return v.variable v = callback._apply_generate_variable(v) if v.variable is not None: return v.variable pvar = v.proto name = pvar.name shape = list(pvar.shape.dim) if shape[0] < 0: shape[0] = self.batch_size shape = tuple(shape) assert np.all(np.array(shape) > 0 ), "Shape must be positive. Given {}.".format(shape) if pvar.type != 'Parameter': # Create a new variable and returns. var = nn.Variable(shape) v.variable = var var.name = name return var # Trying to load the parameter from .nnp file. callback.verbose('Loading parameter `{}` from .nnp.'.format(name)) try: param = get_parameter(name) if param is None: logger.info( 'Parameter `{}` is not found. Initializing.'.format(name)) tmp = _create_variable(pvar, name, shape, self.rng) param = tmp.variable_instance set_parameter(name, param) # Always copy param to current scope even if it already exists. with nn.parameter_scope('', current_scope): set_parameter(name, param) except: import sys import traceback raise ValueError( 'An error occurs during creation of a variable `{}` as a' ' parameter variable. The error was:\n----\n{}\n----\n' 'The parameters registered was {}'.format( name, traceback.format_exc(), '\n'.join( list(nn.get_parameters(grad_only=False).keys())))) assert shape == param.shape param = param.get_unlinked_variable(need_grad=v.need_grad) v.variable = param param.name = name return param
def _get_variable_or_create(self, name, shape): # Returns if name found in parameter. param = get_parameter(name) if param is not None: assert shape == param.shape return param # Returns if variable is already created. try: var, count = self.vseen[name] count[0] += 1 except: # Create a new one and returns. var = nn.Variable(shape) self.vseen[name] = (var, [1]) return var # Found already created variable. assert var.shape == shape return var
def istft(y_r, y_i, window_size, stride, fft_size, window_type='hanning', center=True): '''Workaround wrapper of ISTFT for fixing a bug in nnabla<=1.15.0 ''' from utils import get_nnabla_version_integer if get_nnabla_version_integer() > 11500: return F.istft(**locals()) import numpy as np from nnabla.parameter import get_parameter, get_parameter_or_create conv_cos = get_parameter('conv_cos') conv_sin = get_parameter('conv_sin') if conv_cos is None or conv_sin is None: if window_type == 'hanning': window_func = np.hanning(window_size + 1)[:-1] elif window_type == 'hamming': window_func = np.hamming(window_size + 1)[:-1] elif window_type == 'rectangular' or window_type is None: window_func = np.ones(window_size) else: raise ValueError("Unknown window type {}.".format(window_type)) # pad window if `fft_size > window_size` if fft_size > window_size: diff = fft_size - window_size window_func = np.pad(window_func, (diff // 2, diff - diff // 2), mode='constant') elif fft_size < window_size: raise ValueError( "FFT size has to be as least as large as window size.") # compute inverse STFT filter coefficients if fft_size % stride != 0: raise ValueError("FFT size needs to be a multiple of stride.") inv_window_func = np.zeros_like(window_func) for s in range(0, fft_size, stride): inv_window_func += np.roll(np.square(window_func), s) mat_cos = np.zeros((fft_size // 2 + 1, 1, fft_size)) mat_sin = np.zeros((fft_size // 2 + 1, 1, fft_size)) for w in range(fft_size // 2 + 1): alpha = 1.0 if w == 0 or w == fft_size // 2 else 2.0 alpha /= fft_size for t in range(fft_size): mat_cos[w, 0, t] = alpha * \ np.cos(2. * np.pi * w * t / fft_size) mat_sin[w, 0, t] = alpha * \ np.sin(2. * np.pi * w * t / fft_size) mat_cos = mat_cos * window_func / inv_window_func mat_sin = mat_sin * window_func / inv_window_func conv_cos = get_parameter_or_create('conv_cos', initializer=mat_cos, need_grad=False) conv_sin = get_parameter_or_create('conv_sin', initializer=mat_sin, need_grad=False) # compute inverse STFT x_cos = F.deconvolution(y_r, conv_cos, stride=(stride, )) x_sin = F.deconvolution(y_i, conv_sin, stride=(stride, )) x = F.reshape(x_cos - x_sin, (x_cos.shape[0], x_cos.shape[2])) if center: x = x[:, fft_size // 2:-fft_size // 2] return x
def istft(y_r, y_i, window_size, stride, fft_size, window_type='hanning', center=True): """Computes the inverse shoft-time Fourier transform Note: We use a constant square inverse window for the reconstruction of the time-domain signal, therefore, the first and last `window_size - stride` are not perfectly reconstructed. Args: y_r (~nnabla.Variable): Real part of STFT of size `batch_size x fft_size//2 + 1 x frame_size`. y_i (~nnabla.Variable): Imaginary part of STFT of size `batch_size x fft_size//2 + 1 x frame_size`. window_size (int): Size of STFT analysis window. stride (int): Number of samples that we shift the window, also called `hop size`. fft_size (int): Size of the FFT, (STFT has `fft_size // 2 + 1` frequency bins). window_type (str): Analysis window, can be either `hanning`, `hamming` or `rectangular`. For convenience, also `window_type=None` is supported which is equivalent to `window_type='rectangular'`. center (bool): If `True`, then it is assumed that the time-domain signal has centered frames. Returns: ~nnabla.Variable: Time domain sequence of size `batch_size x sample_size`. """ from nnabla.parameter import get_parameter, get_parameter_or_create conv_cos = get_parameter('conv_cos') conv_sin = get_parameter('conv_sin') if conv_cos is None or conv_sin is None: if window_type == 'hanning': window_func = np.hanning(window_size + 1)[:-1] elif window_type == 'hamming': window_func = np.hamming(window_size + 1)[:-1] elif window_type == 'rectangular' or window_type is None: window_func = np.ones(window_size) else: raise ValueError("Unknown window type {}.".format(window_type)) # pad window if `fft_size > window_size` if fft_size > window_size: diff = fft_size - window_size window_func = np.pad(window_func, (diff // 2, diff - diff // 2), mode='constant') elif fft_size < window_size: raise ValueError( "FFT size has to be as least as large as window size.") # compute inverse STFT filter coefficients if fft_size % stride != 0: raise ValueError("FFT size needs to be a multiple of stride.") inv_window_func = np.zeros_like(window_func) for s in range(0, fft_size, stride): inv_window_func += np.roll(np.square(window_func), s) mat_cos = np.zeros((fft_size // 2 + 1, 1, fft_size)) mat_sin = np.zeros((fft_size // 2 + 1, 1, fft_size)) for w in range(fft_size // 2 + 1): alpha = 1.0 if w == 0 or w == fft_size // 2 else 2.0 alpha /= fft_size for t in range(fft_size): mat_cos[w, 0, t] = alpha * \ np.cos(2. * np.pi * w * t / fft_size) mat_sin[w, 0, t] = alpha * \ np.sin(2. * np.pi * w * t / fft_size) mat_cos = mat_cos * window_func / inv_window_func mat_sin = mat_sin * window_func / inv_window_func conv_cos = get_parameter_or_create('conv_sin', initializer=mat_cos, need_grad=False) conv_sin = get_parameter_or_create('conv_cos', initializer=mat_sin, need_grad=False) # compute inverse STFT x_cos = deconvolution(y_r, conv_cos, stride=(stride, )) x_sin = deconvolution(y_i, conv_sin, stride=(stride, )) x = reshape(x_cos - x_sin, (x_cos.shape[0], x_cos.shape[2])) if center: x = x[:, fft_size // 2:-fft_size // 2] return x
def stft(x, window_size, stride, fft_size, window_type='hanning', center=True, pad_mode='reflect'): """Computes the short-time Fourier transform Args: x (~nnabla.Variable): Time domain sequence of size `batch_size x sample_size`. window_size (int): Size of STFT analysis window. stride (int): Number of samples that we shift the window, also called `hop size`. fft_size (int): Size of the FFT, the output will have `fft_size // 2+ 1` frequency bins. window_type (str): Analysis window, can be either `hanning`, `hamming` or `rectangular`. For convenience, also `window_type=None` is supported which is equivalent to `window_type='rectangular'`. center (bool): If `True`, then the signal `x` is padded by half the FFT size using reflection padding. pad_mode (str): Padding mode, which can be `'constant'` or `'reflect'`. `'constant'` pads with `0`. Returns: Returns real and imaginary parts of STFT result. * :obj:`~nnabla.Variable`: Real part of STFT of size `batch_size x fft_size//2 + 1 x frame_size`. * :obj:`~nnabla.Variable`: Imaginary part of STFT of size `batch x fft_size//2 + 1 x frame_size`. """ from nnabla.parameter import get_parameter, get_parameter_or_create conv_r = get_parameter('conv_r') conv_i = get_parameter('conv_i') if conv_r is None or conv_i is None: if window_type == 'hanning': window_func = np.hanning(window_size + 1)[:-1] elif window_type == 'hamming': window_func = np.hamming(window_size + 1)[:-1] elif window_type == 'rectangular' or window_type is None: window_func = np.ones(window_size) else: raise ValueError("Unknown window type {}.".format(window_type)) # pad window if `fft_size > window_size` if fft_size > window_size: diff = fft_size - window_size window_func = np.pad(window_func, (diff // 2, diff - diff // 2), mode='constant') elif fft_size < window_size: raise ValueError( "FFT size has to be as least as large as window size.") # compute STFT filter coefficients mat_r = np.zeros((fft_size // 2 + 1, 1, fft_size)) mat_i = np.zeros((fft_size // 2 + 1, 1, fft_size)) for w in range(fft_size // 2 + 1): for t in range(fft_size): mat_r[w, 0, t] = np.cos(2. * np.pi * w * t / fft_size) mat_i[w, 0, t] = -np.sin(2. * np.pi * w * t / fft_size) mat_r = mat_r * window_func mat_i = mat_i * window_func conv_r = get_parameter_or_create('conv_r', initializer=mat_r, need_grad=False) conv_i = get_parameter_or_create('conv_i', initializer=mat_i, need_grad=False) if center: # pad at begin/end (per default this is a reflection padding) x = pad(x, (fft_size // 2, fft_size // 2), mode=pad_mode) # add channel dimension x = reshape(x, (x.shape[0], 1, x.shape[1]), inplace=False) # compute STFT y_r = convolution(x, conv_r, stride=(stride, )) y_i = convolution(x, conv_i, stride=(stride, )) return y_r, y_i