Source code for madmom.ml.nn

# encoding: utf-8
# pylint: disable=no-member
# pylint: disable=invalid-name
# pylint: disable=too-many-arguments
# pylint: disable=too-few-public-methods
"""
Neural Network package.

"""

from __future__ import absolute_import, division, print_function

import numpy as np

from . import layers, activations
from ...processors import Processor, ParallelProcessor, SequentialProcessor


[docs]def average_predictions(predictions): """ Returns the average of all predictions. Parameters ---------- predictions : list Predictions (i.e. NN activation functions). Returns ------- numpy array Averaged prediction. """ # average predictions if needed if len(predictions) > 1: # average the predictions predictions = sum(predictions) / len(predictions) else: # nothing to average since we have only one prediction predictions = predictions[0] # return the (averaged) predictions return predictions
[docs]class NeuralNetwork(Processor): """ Neural Network class. Parameters ---------- layers : list Layers of the Neural Network. Examples -------- Create a NeuralNetwork from the given layers. >>> from madmom.ml.nn.layers import FeedForwardLayer >>> from madmom.ml.nn.activations import tanh, sigmoid >>> l1_weights = np.array([[0.5, -1., -0.3 , -0.2]]) >>> l1_bias = np.array([0.05, 0., 0.8, -0.5]) >>> l1 = FeedForwardLayer(l1_weights, l1_bias, activation_fn=tanh) >>> l2_weights = np.array([-1, 0.9, -0.2 , 0.4]) >>> l2_bias = np.array([0.5]) >>> l2 = FeedForwardLayer(l2_weights, l2_bias, activation_fn=sigmoid) >>> nn = NeuralNetwork([l1, l2]) >>> nn # doctest: +ELLIPSIS <madmom.ml.nn.NeuralNetwork object at 0x...> >>> nn(np.array([[0], [0.5], [1], [0], [1], [2], [0]])) ... # doctest: +NORMALIZE_WHITESPACE array([0.53305, 0.36903, 0.265 , 0.53305, 0.265 , 0.18612, 0.53305]) """ def __init__(self, layers): self.layers = layers
[docs] def process(self, data, reset=True, **kwargs): """ Process the given data with the neural network. Parameters ---------- data : numpy array, shape (num_frames, num_inputs) Activate the network with this data. reset : bool, optional Reset the network to its initial state before activating it. Returns ------- numpy array, shape (num_frames, num_outputs) Network predictions for this data. """ # make data at least 2d (required by NN-layers) if data.ndim < 2: data = np.array(data, subok=True, copy=False, ndmin=2) # loop over all layers for layer in self.layers: # activate the layer and feed the output into the next one data = layer.activate(data, reset=reset) # ravel the predictions if needed if data.ndim == 2 and data.shape[1] == 1: data = data.ravel() return data
[docs] def reset(self): """ Reset the neural network to its initial state. """ for layer in self.layers: layer.reset()
[docs]class NeuralNetworkEnsemble(SequentialProcessor): """ Neural Network ensemble class. Parameters ---------- networks : list List of the Neural Networks. ensemble_fn : function or callable, optional Ensemble function to be applied to the predictions of the neural network ensemble (default: average predictions). num_threads : int, optional Number of parallel working threads. Notes ----- If `ensemble_fn` is set to 'None', the predictions are returned as a list with the same length as the number of networks given. Examples -------- Create a NeuralNetworkEnsemble from the networks. Instead of supplying the neural networks as parameter, they can also be loaded from file: >>> from madmom.models import ONSETS_BRNN_PP >>> nn = NeuralNetworkEnsemble.load(ONSETS_BRNN_PP) >>> nn # doctest: +ELLIPSIS <madmom.ml.nn.NeuralNetworkEnsemble object at 0x...> >>> nn(np.array([[0], [0.5], [1], [0], [1], [2], [0]])) ... # doctest: +NORMALIZE_WHITESPACE array([0.00116, 0.00213, 0.01428, 0.00729, 0.0088 , 0.21965, 0.00532]) """ def __init__(self, networks, ensemble_fn=average_predictions, num_threads=None, **kwargs): networks_processor = ParallelProcessor(networks, num_threads=num_threads) super(NeuralNetworkEnsemble, self).__init__((networks_processor, ensemble_fn))
[docs] @classmethod def load(cls, nn_files, **kwargs): """ Instantiate a new Neural Network ensemble from a list of files. Parameters ---------- nn_files : list List of neural network model file names. kwargs : dict, optional Keyword arguments passed to NeuralNetworkEnsemble. Returns ------- NeuralNetworkEnsemble NeuralNetworkEnsemble instance. """ networks = [NeuralNetwork.load(f) for f in nn_files] return cls(networks, **kwargs)
[docs] @staticmethod def add_arguments(parser, nn_files): """ Add neural network options to an existing parser. Parameters ---------- parser : argparse parser instance Existing argparse parser object. nn_files : list Neural network model files. Returns ------- argparse argument group Neural network argument parser group. """ # pylint: disable=signature-differs from madmom.utils import OverrideDefaultListAction # add neural network options g = parser.add_argument_group('neural network arguments') g.add_argument('--nn_files', action=OverrideDefaultListAction, type=str, default=nn_files, help='average the predictions of these pre-trained ' 'neural networks (multiple files can be given, ' 'one file per argument)') # return the argument group so it can be modified if needed return g