<NME> feedforward.py
<BEF> # -*- coding: utf-8 -*-

'''This module contains common feedforward network models.'''

import numpy as np
import theano
import warnings

from . import graph
from . import layers
from . import regularizers
from . import util


class Autoencoder(graph.Network):
    r'''An autoencoder network attempts to reproduce its input.

    Examples
    --------

    To create an autoencoder, just create a new model instance. Often you'll
    provide the layer configuration at this time:

    >>> model = theanets.Autoencoder([10, 20, 10])

    If you want to create an autoencoder with tied weights, specify that layer
    type when creating the model:

    >>> model = theanets.Autoencoder([10, 20, (10, 'tied')])

    See :ref:`guide-creating` for more information.

    *Data*

    Training data for an autoencoder takes the form of a two-dimensional array.
    The shape of this array is (num-examples, num-variables): the first axis
    enumerates data points in a batch, and the second enumerates the variables
    in the model.

    For instance, to create a training dataset containing 1000 examples:

    >>> inputs = np.random.randn(1000, 10).astype('f')

    *Training*

    Training the model can be as simple as calling the :func:`train()
    <theanets.graph.Network.train>` method:

    >>> model.train([inputs])

    See :ref:`guide-training` for more information about training.

    *Use*

    A model can be used to :func:`predict() <theanets.graph.Network.predict>`
    the output of some input data points:

    >>> test = np.random.randn(3, 10).astype('f')
    >>> print(model.predict(test))

    Additionally, autoencoders can :func:`encode()
    <theanets.feedforward.Autoencoder.encode>` a set of input data points:

    >>> enc = model.encode(test)
    >>> enc.shape
    (3, 20)

    The model can also :func:`decode()
    <theanets.feedforward.Autoencoder.decode>` a set of encoded data:

    >>> model.decode(enc)

    See :ref:`guide-using` for more information about using models.

    Notes
    -----

    Autoencoder models default to a :class:`MSE
    <theanets.losses.MeanSquaredError>` loss. To use a different loss, provide a
    non-default argument for the ``loss`` keyword argument when constructing
    your model.

    Formally, an autoencoder defines a parametric mapping from a data space to
    the same space:

    .. math::
       F_\theta: \mathcal{S} \to \mathcal{S}

    Often, this mapping can be decomposed into an "encoding" stage
    :math:`f_\alpha(\cdot)` and a corresponding "decoding" stage
    :math:`g_\beta(\cdot)` to and from some latent space :math:`\mathcal{Z} =
    \mathbb{R}^{n_z}`:

    .. math::
       \begin{eqnarray*}
       f_\alpha &:& \mathcal{S} \to \mathcal{Z} \\
       g_\beta &:& \mathcal{Z} \to \mathcal{S}
       \end{eqnarray*}

    Autoencoders form an interesting class of models for several reasons. They:

    - require only "unlabeled" data (which is typically easy to obtain),
    - are generalizations of many popular density estimation techniques, and
    - can be used to model the "manifold" or density of a dataset.

    Many extremely common dimensionality reduction techniques can be expressed
    as autoencoders. For instance, Principal Component Analysis (PCA) can be
    expressed as a model with two tied, linear layers:

    >>> pca = theanets.Autoencoder([10, (5, 'linear'), (10, 'tied')])

    Similarly, Independent Component Analysis (ICA) can be expressed as the same
    model, but trained with a sparsity penalty on the hidden-layer activations:

    >>> ica = pca
    >>> ica.train([inputs], hidden_l1=0.1)

    In this light, "nonlinear PCA" is quite easy to formulate as well!
    '''

    def __init__(self, layers, loss='mse', weighted=False, rng=13):
        super(Autoencoder, self).__init__(layers, rng=rng)
        self.set_loss(form=loss, target=self.inputs[0], weighted=weighted)

    def encode(self, x, layer=None, sample=False, **kwargs):
        '''Encode a dataset using the hidden layer activations of our network.

        Parameters
        ----------
        x : ndarray
            A dataset to encode. Rows of this dataset capture individual data
            points, while columns represent the variables in each data point.

        layer : str, optional
            The name of the hidden layer output to use. By default, we use
            the "middle" hidden layer---for example, for a 4,2,4 or 4,3,2,3,4
            autoencoder, we use the layer with size 2.

        sample : bool, optional
            If True, then draw a sample using the hidden activations as
            independent Bernoulli probabilities for the encoded data. This
            assumes the hidden layer has a logistic sigmoid activation function.

        Returns
        -------
        ndarray :
            The given dataset, encoded by the appropriate hidden layer
            activation.
        '''
        enc = self.feed_forward(x, **kwargs)[self._find_output(layer)]
        if sample:
            return np.random.binomial(n=1, p=enc).astype(np.uint8)
        return enc

    def decode(self, z, layer=None, **kwargs):
        '''Decode an encoded dataset by computing the output layer activation.

        Parameters
        ----------
        z : ndarray
            A matrix containing encoded data from this autoencoder.
        layer : int or str or :class:`Layer <layers.Layer>`, optional
            The index or name of the hidden layer that was used to encode `z`.

        Returns
        -------
        decoded : ndarray
            The decoded dataset.
        '''
        key = self._find_output(layer)
        if key not in self._functions:
            regs = regularizers.from_kwargs(self, **kwargs)
            outputs, updates = self.build_graph(regs)
            self._functions[key] = theano.function(
                [outputs[key]],
                [outputs[self.layers[-1].output_name]],
                updates=updates)
        return self._functions[key](z)[0]

    def _find_output(self, layer):
        '''Find a layer output name for the given layer specifier.

        Parameters
        ----------
            logging.info('output activation: %s', self._output_func.__theanets_name__)

        self.setup_vars()
        self.z, encode_count = self.setup_encoder(**kwargs)
        self.y, decode_count = self.setup_decoder(**kwargs)

        logging.info('%d total network parameters', encode_count + decode_count)
        Returns
        -------
        name : str
            The fully-scoped output name for the desired layer.
        '''
        if layer is None:
            layer = len(self.layers) // 2
        if isinstance(layer, int):
            layer = self.layers[layer]
        if isinstance(layer, util.basestring):
            try:
                layer = [l for l in self.layers if l.name == layer][0]
            except IndexError:
                pass
        if isinstance(layer, layers.Layer):
            layer = layer.output_name
        return layer

    def score(self, x, w=None, **kwargs):
        '''Compute R^2 coefficient of determination for a given input.

        Parameters
        ----------

        Returns
        -------
        z : Theano variable
            A variable representing the state of the topmost hidden layer.
        parameter_count : int
            The number of parameters created in the forward map.
        '''
        sizes = self.check_layer_sizes()
        parameter_count = 0
        z = self._add_noise(
            self.x,
            kwargs.get('input_noise', 0.),
            kwargs.get('input_dropouts', 0.))

class Regressor(graph.Network):
    '''A regressor attempts to produce a target output given some inputs.

    Examples
    --------

            self.weights.append(W)
            self.biases.append(b)
            z = self.hiddens[-1]
        return z, parameter_count

    def setup_decoder(self, **kwargs):
        '''Set up the "decoding" computations from layer activations to output.
    *Data*

    Training data for a regression model takes the form of two two-dimensional
    arrays. The shapes of both of these arrays are (num-examples, num-variables)
    -- the first axis enumerates data points in a batch, and the second
    enumerates the relevant variables (input variables for the input array, and
    output variables for the output array).

    For instance, to create a training dataset containing 1000 examples:

    >>> inputs = np.random.randn(1000, 10).astype('f')
    >>> outputs = np.random.randn(1000, 3).astype('f')

    *Training*

    Training the model can be as simple as calling the :func:`train()
    <theanets.graph.Network.train>` method, with the inputs and target outputs
    as data:

    >>> model.train([inputs, outputs])

    See :ref:`guide-training` for more information.

    *Use*

    A regression model can be used to :func:`predict()
    <theanets.graph.Network.predict>` the output of some input data points:

    >>> test = np.random.randn(3, 10).astype('f')
    >>> print(model.predict(test))

    See :ref:`guide-using` for more information.

    Notes
    -----

    Regressor models default to a :class:`MSE
    <theanets.losses.MeanSquaredError>` loss. To use a different loss, provide a
    non-default argument for the ``loss`` keyword argument when constructing
    your model.
    '''


class Classifier(graph.Network):
    '''A classifier computes a distribution over labels, given an input.

    Examples
    --------

    To create a classification model, just create a new class instance. Often
    you'll provide the layer configuration at this time:

    >>> model = theanets.Classifier([10, (20, 'tanh'), 50])

    See :ref:`guide-creating` for more information.

    *Data*

    Training data for a classification model takes the form of a two-dimensional
    array of input data and a one-dimensional vector of target labels. The input
    array has a shape (num-examples, num-variables): the first axis enumerates
    data points in a batch, and the second enumerates the input variables in the
    model.

    The second array provides the target class labels for the inputs. Its shape
    is (num-examples, ), and each integer value in the array gives the class
    label for the corresponding input example.

    For instance, to create a training dataset containing 1000 examples:

    >>> inputs = np.random.randn(1000, 10).astype('f')
    >>> outputs = np.random.randint(50, size=1000).astype('i')

    *Training*

    Training the model can be as simple as calling the :func:`train()
    <theanets.graph.Network.train>` method, giving the inputs and target outputs
    as a dataset:

    >>> model.train([inputs, outputs])

    See :ref:`guide-training` for more information.

    *Use*

    A classification model can be used to :func:`predict()
    <theanets.graph.Network.predict>` the output of some input data points:

    >>> test = np.random.randn(3, 10).astype('f')
    >>> print(model.predict(test))

    This method returns a vector containing the most likely class for each input
    example.

    To retrieve the probabilities of the classes for each example, use
    :func:`predict_proba() <theanets.feedforward.Classifier.predict_proba>`:

    >>> model.predict_proba(test).shape
    (3, 50)

    See also :ref:`guide-using` for more information.

    Notes
    -----

    Classifier models default to a :class:`cross-entropy
    <theanets.losses.CrossEntropy>` loss. To use a different loss, provide a
    non-default argument for the ``loss`` keyword argument when constructing
    your model.
    '''

    DEFAULT_OUTPUT_ACTIVATION = 'softmax'
    '''Default activation for the output layer.'''

    OUTPUT_NDIM = 1
    '''Number of dimensions for holding output data arrays.'''

    def __init__(self, layers, loss='xe', weighted=False, rng=13):
        super(Classifier, self).__init__(layers, loss=loss, weighted=weighted, rng=rng)

    def monitors(self, **kwargs):
        '''Return expressions that should be computed to monitor training.

        Returns
        -------
        monitors : list of (name, expression) pairs
            A list of named monitor expressions to compute for this network.
        '''
        monitors = super(Classifier, self).monitors(**kwargs)
        regs = regularizers.from_kwargs(self, **kwargs)
        outputs, _ = self.build_graph(regs)
        return monitors + [('acc', self.losses[0].accuracy(outputs))]

    def predict(self, x, **kwargs):
        '''Compute a greedy classification for the given set of data.

        Parameters
        ----------
        x : ndarray (num-examples, num-variables)
            An array containing examples to classify. Examples are given as the
            rows in this array.

        Returns
        -------
        k : ndarray (num-examples, )
            A vector of class index values, one per row of input data.
        '''
        outputs = self.feed_forward(x, **kwargs)
        return outputs[self.layers[-1].output_name].argmax(axis=-1)

    def classify(self, x, **kwargs):
        warnings.warn('please use predict() instead of classify()',
                      DeprecationWarning)
        return self.predict(x, **kwargs)

    def predict_proba(self, x, **kwargs):
        '''Compute class posterior probabilities for the given set of data.

        Parameters
        ----------
        x : ndarray (num-examples, num-variables)
            An array containing examples to predict. Examples are given as the
            rows in this array.

        Returns
        -------
        p : ndarray (num-examples, num-classes)
            An array of class posterior probability values, one per row of input
            data.
        '''
        return self.feed_forward(x, **kwargs)[self.layers[-1].output_name]

    def predict_logit(self, x, **kwargs):
        '''Compute the logit values that underlie the softmax output.

        Parameters
        ----------
        x : ndarray (num-examples, num-variables)
            An array containing examples to classify. Examples are given as the
            rows in this array.

        Returns
        -------
        l : ndarray (num-examples, num-classes)
            An array of posterior class logit values, one row of logit values
            per row of input data.
        '''
        return self.feed_forward(x, **kwargs)[self.layers[-1].full_name('pre')]

    def score(self, x, y, w=None, **kwargs):
        '''Compute the mean accuracy on a set of labeled data.

        Parameters
        ----------
        x : ndarray (num-examples, num-variables)
            An array containing examples to classify. Examples are given as the
            rows in this array.
        y : ndarray (num-examples, )
            A vector of integer class labels, one for each row of input data.
        w : ndarray (num-examples, )
            A vector of weights, one for each row of input data.

        Returns
        -------
        score : float
            The (possibly weighted) mean accuracy of the model on the data.
        '''
        eq = y == self.predict(x, **kwargs)
        if w is not None:
            return (w * eq).sum() / w.sum()
        return eq.mean()

<MSG> Change default encoder to return noisy input variable, not topmost hidden layer.

<DFF> @@ -185,7 +185,7 @@ class Network(object):
             logging.info('output activation: %s', self._output_func.__theanets_name__)
 
         self.setup_vars()
-        self.z, encode_count = self.setup_encoder(**kwargs)
+        _, encode_count = self.setup_encoder(**kwargs)
         self.y, decode_count = self.setup_decoder(**kwargs)
 
         logging.info('%d total network parameters', encode_count + decode_count)
@@ -215,14 +215,14 @@ class Network(object):
 
         Returns
         -------
-        z : Theano variable
-            A variable representing the state of the topmost hidden layer.
+        x : Theano variable
+            A variable representing the (possibly noisy) input vector.
         parameter_count : int
             The number of parameters created in the forward map.
         '''
         sizes = self.check_layer_sizes()
         parameter_count = 0
-        z = self._add_noise(
+        x = z = self._add_noise(
             self.x,
             kwargs.get('input_noise', 0.),
             kwargs.get('input_dropouts', 0.))
@@ -236,7 +236,7 @@ class Network(object):
             self.weights.append(W)
             self.biases.append(b)
             z = self.hiddens[-1]
-        return z, parameter_count
+        return x, parameter_count
 
     def setup_decoder(self, **kwargs):
         '''Set up the "decoding" computations from layer activations to output.

{'commit': 'diff --git a/theanets/feedforward.py b/theanets/feedforward.py\nindex c159a39..97ba12c 100644\n--- a/theanets/feedforward.py\n+++ b/theanets/feedforward.py\n@@ -185,7 +185,7 @@ class Network(object):\n             logging.info(\'output activation: %s\', self._output_func.__theanets_name__)\n \n         self.setup_vars()\n-        self.z, encode_count = self.setup_encoder(**kwargs)\n+        _, encode_count = self.setup_encoder(**kwargs)\n         self.y, decode_count = self.setup_decoder(**kwargs)\n \n         logging.info(\'%d total network parameters\', encode_count + decode_count)\n@@ -215,14 +215,14 @@ class Network(object):\n \n         Returns\n         -------\n-        z : Theano variable\n-            A variable representing the state of the topmost hidden layer.\n+        x : Theano variable\n+            A variable representing the (possibly noisy) input vector.\n         parameter_count : int\n             The number of parameters created in the forward map.\n         \'\'\'\n         sizes = self.check_layer_sizes()\n         parameter_count = 0\n-        z = self._add_noise(\n+        x = z = self._add_noise(\n             self.x,\n             kwargs.get(\'input_noise\', 0.),\n             kwargs.get(\'input_dropouts\', 0.))\n@@ -236,7 +236,7 @@ class Network(object):\n             self.weights.append(W)\n             self.biases.append(b)\n             z = self.hiddens[-1]\n-        return z, parameter_count\n+        return x, parameter_count\n \n     def setup_decoder(self, **kwargs):\n         \'\'\'Set up the "decoding" computations from layer activations to output.\n', 'commit_subject': 'Change default encoder to return noisy input variable, not topmost hidden layer.', 'repo_name': 'lmjohns3/theanets', 'committer': {'name': 'Leif Johnson', 'email': 'c37e4453350f6d87af4666f6d6fa751c6b8ff4cd@leifjohnson.net', 'time_sec': '1410813682', 'tz_offset': '-300', 'date': {'seconds': '1410813682'}}, 'commit_tree': 'b343bf7cbae89b88dd9e4890e59baa85bb82bb9f', 'commit_message': 'Change default encoder to return noisy input variable, not topmost hidden layer.\n', 'language_name': 'Python', 'license': 'mit', 'hunks': '@@ -185,7 +185,7 @@ class Network(object):\n             logging.info(\'output activation: %s\', self._output_func.__theanets_name__)\n \n         self.setup_vars()\n-        self.z, encode_count = self.setup_encoder(**kwargs)\n+        _, encode_count = self.setup_encoder(**kwargs)\n         self.y, decode_count = self.setup_decoder(**kwargs)\n \n         logging.info(\'%d total network parameters\', encode_count + decode_count)\n@@ -215,14 +215,14 @@ class Network(object):\n \n         Returns\n         -------\n-        z : Theano variable\n-            A variable representing the state of the topmost hidden layer.\n+        x : Theano variable\n+            A variable representing the (possibly noisy) input vector.\n         parameter_count : int\n             The number of parameters created in the forward map.\n         \'\'\'\n         sizes = self.check_layer_sizes()\n         parameter_count = 0\n-        z = self._add_noise(\n+        x = z = self._add_noise(\n             self.x,\n             kwargs.get(\'input_noise\', 0.),\n             kwargs.get(\'input_dropouts\', 0.))\n@@ -236,7 +236,7 @@ class Network(object):\n             self.weights.append(W)\n             self.biases.append(b)\n             z = self.hiddens[-1]\n-        return z, parameter_count\n+        return x, parameter_count\n \n     def setup_decoder(self, **kwargs):\n         \'\'\'Set up the "decoding" computations from layer activations to output.\n', 'addition_count': 5, 'deletion_count': 5, 'src_file': 'a/theanets/feedforward.py', 'tgt_file': 'b/theanets/feedforward.py', 'file_extension': '.py', 'before_file': '# -*- coding: utf-8 -*-\n\n\'\'\'This module contains common feedforward network models.\'\'\'\n\nimport numpy as np\nimport theano\nimport warnings\n\nfrom . import graph\nfrom . import layers\nfrom . import regularizers\nfrom . import util\n\n\nclass Autoencoder(graph.Network):\n    r\'\'\'An autoencoder network attempts to reproduce its input.\n\n    Examples\n    --------\n\n    To create an autoencoder, just create a new model instance. Often you\'ll\n    provide the layer configuration at this time:\n\n    >>> model = theanets.Autoencoder([10, 20, 10])\n\n    If you want to create an autoencoder with tied weights, specify that layer\n    type when creating the model:\n\n    >>> model = theanets.Autoencoder([10, 20, (10, \'tied\')])\n\n    See :ref:`guide-creating` for more information.\n\n    *Data*\n\n    Training data for an autoencoder takes the form of a two-dimensional array.\n    The shape of this array is (num-examples, num-variables): the first axis\n    enumerates data points in a batch, and the second enumerates the variables\n    in the model.\n\n    For instance, to create a training dataset containing 1000 examples:\n\n    >>> inputs = np.random.randn(1000, 10).astype(\'f\')\n\n    *Training*\n\n    Training the model can be as simple as calling the :func:`train()\n    <theanets.graph.Network.train>` method:\n\n    >>> model.train([inputs])\n\n    See :ref:`guide-training` for more information about training.\n\n    *Use*\n\n    A model can be used to :func:`predict() <theanets.graph.Network.predict>`\n    the output of some input data points:\n\n    >>> test = np.random.randn(3, 10).astype(\'f\')\n    >>> print(model.predict(test))\n\n    Additionally, autoencoders can :func:`encode()\n    <theanets.feedforward.Autoencoder.encode>` a set of input data points:\n\n    >>> enc = model.encode(test)\n    >>> enc.shape\n    (3, 20)\n\n    The model can also :func:`decode()\n    <theanets.feedforward.Autoencoder.decode>` a set of encoded data:\n\n    >>> model.decode(enc)\n\n    See :ref:`guide-using` for more information about using models.\n\n    Notes\n    -----\n\n    Autoencoder models default to a :class:`MSE\n    <theanets.losses.MeanSquaredError>` loss. To use a different loss, provide a\n    non-default argument for the ``loss`` keyword argument when constructing\n    your model.\n\n    Formally, an autoencoder defines a parametric mapping from a data space to\n    the same space:\n\n    .. math::\n       F_\\theta: \\mathcal{S} \\to \\mathcal{S}\n\n    Often, this mapping can be decomposed into an "encoding" stage\n    :math:`f_\\alpha(\\cdot)` and a corresponding "decoding" stage\n    :math:`g_\\beta(\\cdot)` to and from some latent space :math:`\\mathcal{Z} =\n    \\mathbb{R}^{n_z}`:\n\n    .. math::\n       \\begin{eqnarray*}\n       f_\\alpha &:& \\mathcal{S} \\to \\mathcal{Z} \\\\\n       g_\\beta &:& \\mathcal{Z} \\to \\mathcal{S}\n       \\end{eqnarray*}\n\n    Autoencoders form an interesting class of models for several reasons. They:\n\n    - require only "unlabeled" data (which is typically easy to obtain),\n    - are generalizations of many popular density estimation techniques, and\n    - can be used to model the "manifold" or density of a dataset.\n\n    Many extremely common dimensionality reduction techniques can be expressed\n    as autoencoders. For instance, Principal Component Analysis (PCA) can be\n    expressed as a model with two tied, linear layers:\n\n    >>> pca = theanets.Autoencoder([10, (5, \'linear\'), (10, \'tied\')])\n\n    Similarly, Independent Component Analysis (ICA) can be expressed as the same\n    model, but trained with a sparsity penalty on the hidden-layer activations:\n\n    >>> ica = pca\n    >>> ica.train([inputs], hidden_l1=0.1)\n\n    In this light, "nonlinear PCA" is quite easy to formulate as well!\n    \'\'\'\n\n    def __init__(self, layers, loss=\'mse\', weighted=False, rng=13):\n        super(Autoencoder, self).__init__(layers, rng=rng)\n        self.set_loss(form=loss, target=self.inputs[0], weighted=weighted)\n\n    def encode(self, x, layer=None, sample=False, **kwargs):\n        \'\'\'Encode a dataset using the hidden layer activations of our network.\n\n        Parameters\n        ----------\n        x : ndarray\n            A dataset to encode. Rows of this dataset capture individual data\n            points, while columns represent the variables in each data point.\n\n        layer : str, optional\n            The name of the hidden layer output to use. By default, we use\n            the "middle" hidden layer---for example, for a 4,2,4 or 4,3,2,3,4\n            autoencoder, we use the layer with size 2.\n\n        sample : bool, optional\n            If True, then draw a sample using the hidden activations as\n            independent Bernoulli probabilities for the encoded data. This\n            assumes the hidden layer has a logistic sigmoid activation function.\n\n        Returns\n        -------\n        ndarray :\n            The given dataset, encoded by the appropriate hidden layer\n            activation.\n        \'\'\'\n        enc = self.feed_forward(x, **kwargs)[self._find_output(layer)]\n        if sample:\n            return np.random.binomial(n=1, p=enc).astype(np.uint8)\n        return enc\n\n    def decode(self, z, layer=None, **kwargs):\n        \'\'\'Decode an encoded dataset by computing the output layer activation.\n\n        Parameters\n        ----------\n        z : ndarray\n            A matrix containing encoded data from this autoencoder.\n        layer : int or str or :class:`Layer <layers.Layer>`, optional\n            The index or name of the hidden layer that was used to encode `z`.\n\n        Returns\n        -------\n        decoded : ndarray\n            The decoded dataset.\n        \'\'\'\n        key = self._find_output(layer)\n        if key not in self._functions:\n            regs = regularizers.from_kwargs(self, **kwargs)\n            outputs, updates = self.build_graph(regs)\n            self._functions[key] = theano.function(\n                [outputs[key]],\n                [outputs[self.layers[-1].output_name]],\n                updates=updates)\n        return self._functions[key](z)[0]\n\n    def _find_output(self, layer):\n        \'\'\'Find a layer output name for the given layer specifier.\n\n        Parameters\n        ----------\n            logging.info(\'output activation: %s\', self._output_func.__theanets_name__)\n\n        self.setup_vars()\n        self.z, encode_count = self.setup_encoder(**kwargs)\n        self.y, decode_count = self.setup_decoder(**kwargs)\n\n        logging.info(\'%d total network parameters\', encode_count + decode_count)\n        Returns\n        -------\n        name : str\n            The fully-scoped output name for the desired layer.\n        \'\'\'\n        if layer is None:\n            layer = len(self.layers) // 2\n        if isinstance(layer, int):\n            layer = self.layers[layer]\n        if isinstance(layer, util.basestring):\n            try:\n                layer = [l for l in self.layers if l.name == layer][0]\n            except IndexError:\n                pass\n        if isinstance(layer, layers.Layer):\n            layer = layer.output_name\n        return layer\n\n    def score(self, x, w=None, **kwargs):\n        \'\'\'Compute R^2 coefficient of determination for a given input.\n\n        Parameters\n        ----------\n\n        Returns\n        -------\n        z : Theano variable\n            A variable representing the state of the topmost hidden layer.\n        parameter_count : int\n            The number of parameters created in the forward map.\n        \'\'\'\n        sizes = self.check_layer_sizes()\n        parameter_count = 0\n        z = self._add_noise(\n            self.x,\n            kwargs.get(\'input_noise\', 0.),\n            kwargs.get(\'input_dropouts\', 0.))\n\nclass Regressor(graph.Network):\n    \'\'\'A regressor attempts to produce a target output given some inputs.\n\n    Examples\n    --------\n\n            self.weights.append(W)\n            self.biases.append(b)\n            z = self.hiddens[-1]\n        return z, parameter_count\n\n    def setup_decoder(self, **kwargs):\n        \'\'\'Set up the "decoding" computations from layer activations to output.\n    *Data*\n\n    Training data for a regression model takes the form of two two-dimensional\n    arrays. The shapes of both of these arrays are (num-examples, num-variables)\n    -- the first axis enumerates data points in a batch, and the second\n    enumerates the relevant variables (input variables for the input array, and\n    output variables for the output array).\n\n    For instance, to create a training dataset containing 1000 examples:\n\n    >>> inputs = np.random.randn(1000, 10).astype(\'f\')\n    >>> outputs = np.random.randn(1000, 3).astype(\'f\')\n\n    *Training*\n\n    Training the model can be as simple as calling the :func:`train()\n    <theanets.graph.Network.train>` method, with the inputs and target outputs\n    as data:\n\n    >>> model.train([inputs, outputs])\n\n    See :ref:`guide-training` for more information.\n\n    *Use*\n\n    A regression model can be used to :func:`predict()\n    <theanets.graph.Network.predict>` the output of some input data points:\n\n    >>> test = np.random.randn(3, 10).astype(\'f\')\n    >>> print(model.predict(test))\n\n    See :ref:`guide-using` for more information.\n\n    Notes\n    -----\n\n    Regressor models default to a :class:`MSE\n    <theanets.losses.MeanSquaredError>` loss. To use a different loss, provide a\n    non-default argument for the ``loss`` keyword argument when constructing\n    your model.\n    \'\'\'\n\n\nclass Classifier(graph.Network):\n    \'\'\'A classifier computes a distribution over labels, given an input.\n\n    Examples\n    --------\n\n    To create a classification model, just create a new class instance. Often\n    you\'ll provide the layer configuration at this time:\n\n    >>> model = theanets.Classifier([10, (20, \'tanh\'), 50])\n\n    See :ref:`guide-creating` for more information.\n\n    *Data*\n\n    Training data for a classification model takes the form of a two-dimensional\n    array of input data and a one-dimensional vector of target labels. The input\n    array has a shape (num-examples, num-variables): the first axis enumerates\n    data points in a batch, and the second enumerates the input variables in the\n    model.\n\n    The second array provides the target class labels for the inputs. Its shape\n    is (num-examples, ), and each integer value in the array gives the class\n    label for the corresponding input example.\n\n    For instance, to create a training dataset containing 1000 examples:\n\n    >>> inputs = np.random.randn(1000, 10).astype(\'f\')\n    >>> outputs = np.random.randint(50, size=1000).astype(\'i\')\n\n    *Training*\n\n    Training the model can be as simple as calling the :func:`train()\n    <theanets.graph.Network.train>` method, giving the inputs and target outputs\n    as a dataset:\n\n    >>> model.train([inputs, outputs])\n\n    See :ref:`guide-training` for more information.\n\n    *Use*\n\n    A classification model can be used to :func:`predict()\n    <theanets.graph.Network.predict>` the output of some input data points:\n\n    >>> test = np.random.randn(3, 10).astype(\'f\')\n    >>> print(model.predict(test))\n\n    This method returns a vector containing the most likely class for each input\n    example.\n\n    To retrieve the probabilities of the classes for each example, use\n    :func:`predict_proba() <theanets.feedforward.Classifier.predict_proba>`:\n\n    >>> model.predict_proba(test).shape\n    (3, 50)\n\n    See also :ref:`guide-using` for more information.\n\n    Notes\n    -----\n\n    Classifier models default to a :class:`cross-entropy\n    <theanets.losses.CrossEntropy>` loss. To use a different loss, provide a\n    non-default argument for the ``loss`` keyword argument when constructing\n    your model.\n    \'\'\'\n\n    DEFAULT_OUTPUT_ACTIVATION = \'softmax\'\n    \'\'\'Default activation for the output layer.\'\'\'\n\n    OUTPUT_NDIM = 1\n    \'\'\'Number of dimensions for holding output data arrays.\'\'\'\n\n    def __init__(self, layers, loss=\'xe\', weighted=False, rng=13):\n        super(Classifier, self).__init__(layers, loss=loss, weighted=weighted, rng=rng)\n\n    def monitors(self, **kwargs):\n        \'\'\'Return expressions that should be computed to monitor training.\n\n        Returns\n        -------\n        monitors : list of (name, expression) pairs\n            A list of named monitor expressions to compute for this network.\n        \'\'\'\n        monitors = super(Classifier, self).monitors(**kwargs)\n        regs = regularizers.from_kwargs(self, **kwargs)\n        outputs, _ = self.build_graph(regs)\n        return monitors + [(\'acc\', self.losses[0].accuracy(outputs))]\n\n    def predict(self, x, **kwargs):\n        \'\'\'Compute a greedy classification for the given set of data.\n\n        Parameters\n        ----------\n        x : ndarray (num-examples, num-variables)\n            An array containing examples to classify. Examples are given as the\n            rows in this array.\n\n        Returns\n        -------\n        k : ndarray (num-examples, )\n            A vector of class index values, one per row of input data.\n        \'\'\'\n        outputs = self.feed_forward(x, **kwargs)\n        return outputs[self.layers[-1].output_name].argmax(axis=-1)\n\n    def classify(self, x, **kwargs):\n        warnings.warn(\'please use predict() instead of classify()\',\n                      DeprecationWarning)\n        return self.predict(x, **kwargs)\n\n    def predict_proba(self, x, **kwargs):\n        \'\'\'Compute class posterior probabilities for the given set of data.\n\n        Parameters\n        ----------\n        x : ndarray (num-examples, num-variables)\n            An array containing examples to predict. Examples are given as the\n            rows in this array.\n\n        Returns\n        -------\n        p : ndarray (num-examples, num-classes)\n            An array of class posterior probability values, one per row of input\n            data.\n        \'\'\'\n        return self.feed_forward(x, **kwargs)[self.layers[-1].output_name]\n\n    def predict_logit(self, x, **kwargs):\n        \'\'\'Compute the logit values that underlie the softmax output.\n\n        Parameters\n        ----------\n        x : ndarray (num-examples, num-variables)\n            An array containing examples to classify. Examples are given as the\n            rows in this array.\n\n        Returns\n        -------\n        l : ndarray (num-examples, num-classes)\n            An array of posterior class logit values, one row of logit values\n            per row of input data.\n        \'\'\'\n        return self.feed_forward(x, **kwargs)[self.layers[-1].full_name(\'pre\')]\n\n    def score(self, x, y, w=None, **kwargs):\n        \'\'\'Compute the mean accuracy on a set of labeled data.\n\n        Parameters\n        ----------\n        x : ndarray (num-examples, num-variables)\n            An array containing examples to classify. Examples are given as the\n            rows in this array.\n        y : ndarray (num-examples, )\n            A vector of integer class labels, one for each row of input data.\n        w : ndarray (num-examples, )\n            A vector of weights, one for each row of input data.\n\n        Returns\n        -------\n        score : float\n            The (possibly weighted) mean accuracy of the model on the data.\n        \'\'\'\n        eq = y == self.predict(x, **kwargs)\n        if w is not None:\n            return (w * eq).sum() / w.sum()\n        return eq.mean()\n', 'message': 'Change default encoder to return noisy input variable, not topmost hidden layer.\n', 'author_name': 'Leif Johnson', 'lang': 'py'}