<commit_before>.. _data_specs:

Data specifications, spaces, and sources
========================================

Data specifications, often called ``data_specs``, are used as a
specification for requesting and providing data in a certain format
across different parts of a Pylearn2 experiment.

A ``data_specs`` is a ``(space, source)`` pair, where ``source`` is an
identifier or the data source or sources required (for instance, inputs
and targets), and ``space`` is an instance of :class:`.space.Space`
representing the *format* of these data (for instance, a vector, a 3D
tensor representing an RGB image, or a one-hot vector).

The main use of ``data_specs`` is to request data from a
:class:`.datasets.Dataset` object, via an iterator. Various objects can
request data this way: models, costs, monitoring channels, training
algorithms, even some datasets that perform a transformation on data.


The ``Space`` object
====================

A ``Space`` represents a way in which a mini-batch of data can be
formatted. For instance, a batch of RGB images (each of shape ``(rows,
columns)``) can be represented in different ways, for instance:

- as a matrix where each row corresponds to a different image, and is
  of length ``rows * columns * 3``: the corresponding space would be
  a :class:`.space.VectorSpace`, more precisely
  ``VectorSpace(dim=(rows * columns * 3))``;

- as a 4-dimensional tensor, where rows, columns, and channels (here:
  red, green, and blue) are different axes: the corresponding space would
  be a :class:`.space.Conv2DSpace`. Theano convolutions prefer that
  tensor to have shape ``(batch_size, channels, rows, columns)``, which
  corresponds to ``Conv2DSpace(shape=(rows, columns), num_channels=3,
  axes=('b', 'c', 0, 1))``;

- as a 4-dimensional tensors with a different shape: for instance,
  cuda-convnet prefers ``(channels, rows, columns, batch_size)``: the
  space would be ``Conv2DSpace(shape=(rows, columns), num_channels=3,
  axes=('c', 0, 1, 'b'))``.

Spaces can be either elementary, representing one mini-batch from one
source of data, such as ``VectorSpace`` and ``Conv2DSpace`` mentioned
above, or *composite* (:class:`.space.CompositeSpace`), representing
the aggregation of several sources of data (some of these may in
turn be aggregations of sources). A mini-batch for an elementary
space will usually be a NumPy ``ndarray``, whereas a mini-batch for a
``CompositeSpace`` will be a Python tuple of elementary (or composite)
mini-batches.

Notable methods of the :class:`Space` class are:

- :meth:`Space.make_theano_batch`: creates a Theano Variable
  (or tuple of Theano Variable in the case of ``CompositeSpace``)
  representing a *symbolic* mini-batch of data. For instance,
  ``VectorSpace(...).make_theano_batch(...)`` will essentially call
  ``theano.tensor.matrix()``.

- :meth:`Space.validate(batch)` will check that symbolic
  variable ``batch`` can correctly represent a mini-batch
  of data for the corresponding space. For instance,
  ``VectorSpace(...).validate(theano.tensor.matrix())`` will work, but
  ``VectorSpace(...).validate(theano.tensor.vector())`` will raise an
  exception.

- :meth:`Space.np_validate(batch)` (where ``np`` stands for NumPy)
  is similar, but operates on a mini-batch of numeric data, rather than
  on a symbolic variable. This enables more checks to be performed. For
  instance, ``VectorSpace(dim=3).validate(np.zeros((4, 3)))`` will work,
  because it correctly describes a mini-batch of 4 samples of dimension
  3, but ``VectorSpace(dim=4).validate(np.zeros((4, 3)))`` will raise an
  exception.

- :meth:`Space.format_as(batch, space)` and
  :meth:`Space.np_format_as(batch, space)` are the way we can convert
  data from their original space into the destination ``space``.
  ``format_as`` operates on a symbolic ``batch``, and returns a symbolic
  expression of the newly-formatted data, whereas ``np_format_as``
  operates on a numeric batch, and returns numeric data. This formatting
  can happen between different instances of the same ``Space`` class,
  for instance, converting between two instances of ``Conv2DSpace`` with
  different ``axes`` amounts to correctly transpose the ``batch``. It can
  also happen between different subclasses of ``Space``, for instance,
  converting between a ``VectorSpace`` and ``Conv2DSpace`` of compatible
  shape involves reshaping and transposition of the data.


Sources
=======

Sources are simple identifiers that specify *which* data should be
returned, whereas spaces specify *how* that data should be formatted.

An elementary source is identified by a Python string. For instance, the
most used sources are ``'features'`` and ``'targets'``. ``'features'``
usually denotes the part of the data that models will use as input, and
``'targets'``, for labeled datasets, contains the value the model will
try to predict. However, this is only a convention, and some datasets
will declare other sources, that can be used in varying ways by models,
for instance when using multi-modal data.

A composite source is identified by a tuple of sources. For instance,
to request features and targets from a dataset, the `source` would be
``('features', 'targets')``.


Structure of composite specifications
=====================================

When using composite specifications ``data_specs=(space, source)``,
``space`` and ``source`` have to have the same *structure*. This means
that:

- if ``space`` is an elementary space, then ``source`` has to be an
  elementary source, i.e., a string;

- if ``space`` is a composite space, then ``source`` has to be a
  composite source (a tuple), with exactly as many components as the
  number of sub-spaces of ``space``; and the corresponding sub-sources and
  sub-spaces again have to have the same *structure*.


For example, let us define the following spaces:

.. code-block:: python

    input_vecspace = VectorSpace(dim=(32 * 32 * 3))
    input_convspace = Conv2DSpace(shape=(32, 32), num_channels=3, axes=('b', 'c', 0, 1))
    target_space = VectorSpace(dim=10)<commit_msg>Fix miswording in data specs doc.<commit_after>.. _data_specs:

Data specifications, spaces, and sources
========================================

Data specifications, often called ``data_specs``, are used as a
specification for requesting and providing data in a certain format
across different parts of a Pylearn2 experiment.

A ``data_specs`` is a ``(space, source)`` pair, where ``source`` is an
identifier or the data source or sources required (for instance, inputs
and targets), and ``space`` is an instance of :class:`.space.Space`
representing the *format* of these data (for instance, a vector, a 3D
tensor representing an RGB image, or a one-hot vector).

The main use of ``data_specs`` is to request data from a
:class:`.datasets.Dataset` object, via an iterator. Various objects can
request data this way: models, costs, monitoring channels, training
algorithms, even some datasets that perform a transformation on data.


The ``Space`` object
====================

A ``Space`` represents a way in which a mini-batch of data can be
formatted. For instance, a batch of RGB images (each of shape ``(rows,
columns)``) can be represented in different ways, for instance:

- as a matrix where each row corresponds to a different image, and is
  of length ``rows * columns * 3``: the corresponding space would be
  a :class:`.space.VectorSpace`, more precisely
  ``VectorSpace(dim=(rows * columns * 3))``;

- as a 4-dimensional tensor, where rows, columns, and channels (here:
  red, green, and blue) are different axes: the corresponding space would
  be a :class:`.space.Conv2DSpace`. Theano convolutions prefer that
  tensor to have shape ``(batch_size, channels, rows, columns)``, which
  corresponds to ``Conv2DSpace(shape=(rows, columns), num_channels=3,
  axes=('b', 'c', 0, 1))``;

- as a 4-dimensional tensors with a different shape: for instance,
  cuda-convnet prefers ``(channels, rows, columns, batch_size)``: the
  space would be ``Conv2DSpace(shape=(rows, columns), num_channels=3,
  axes=('c', 0, 1, 'b'))``.

Spaces can be either elementary, representing one mini-batch from one
source of data, such as ``VectorSpace`` and ``Conv2DSpace`` mentioned
above, or *composite* (:class:`.space.CompositeSpace`), representing
the aggregation of several sources of data (some of these may in
turn be aggregations of sources). A mini-batch for an elementary
space will usually be a NumPy ``ndarray``, whereas a mini-batch for a
``CompositeSpace`` will be a Python tuple of elementary (or composite)
mini-batches.

Notable methods of the :class:`Space` class are:

- :meth:`Space.make_theano_batch`: creates a Theano Variable
  (or tuple of Theano Variable in the case of ``CompositeSpace``)
  representing a *symbolic* mini-batch of data. For instance,
  ``VectorSpace(...).make_theano_batch(...)`` will essentially call
  ``theano.tensor.matrix()``.

- :meth:`Space.validate(batch)` will check that symbolic
  variable ``batch`` can correctly represent a mini-batch
  of data for the corresponding space. For instance,
  ``VectorSpace(...).validate(theano.tensor.matrix())`` will work, but
  ``VectorSpace(...).validate(theano.tensor.vector())`` will raise an
  exception.

- :meth:`Space.np_validate(batch)` (where ``np`` stands for NumPy)
  is similar, but operates on a mini-batch of numeric data, rather than
  on a symbolic variable. This enables more checks to be performed. For
  instance, ``VectorSpace(dim=3).validate(np.zeros((4, 3)))`` will work,
  because it correctly describes a mini-batch of 4 samples of dimension
  3, but ``VectorSpace(dim=4).validate(np.zeros((4, 3)))`` will raise an
  exception.

- :meth:`Space.format_as(batch, space)` and
  :meth:`Space.np_format_as(batch, space)` are the way we can convert
  data from their original space into the destination ``space``.
  ``format_as`` operates on a symbolic ``batch``, and returns a symbolic
  expression of the newly-formatted data, whereas ``np_format_as``
  operates on a numeric batch, and returns numeric data. This formatting
  can happen between different instances of the same ``Space`` class,
  for instance, converting between two instances of ``Conv2DSpace`` with
  different ``axes`` amounts to correctly transpose the ``batch``. It can
  also happen between different subclasses of ``Space``, for instance,
  converting between a ``VectorSpace`` and ``Conv2DSpace`` of compatible
  shape involves reshaping and transposition of the data.


Sources
=======

Sources are simple identifiers that specify *which* data should be
returned, whereas spaces specify *how* that data should be formatted.

An elementary source is identified by a Python string. For instance, the
most used sources are ``'features'`` and ``'targets'``. ``'features'``
usually denotes the part of the data that models will use as input, and
``'targets'``, for labeled datasets, contains the value the model will
try to predict. However, this is only a convention, and some datasets
will declare other sources, that can be used in varying ways by models,
for instance when using multi-modal data.

A composite source is identified by a tuple of sources. For instance,
to request features and targets from a dataset, the `source` would be
``('features', 'targets')``.


Structure of data specifications
================================

When using data specifications ``data_specs=(space, source)``,
``space`` and ``source`` have to have the same *structure*. This means
that:

- if ``space`` is an elementary space, then ``source`` has to be an
  elementary source, i.e., a string;

- if ``space`` is a composite space, then ``source`` has to be a
  composite source (a tuple), with exactly as many components as the
  number of sub-spaces of ``space``; and the corresponding sub-sources and
  sub-spaces again have to have the same *structure*.


For example, let us define the following spaces:

.. code-block:: python

    input_vecspace = VectorSpace(dim=(32 * 32 * 3))
    input_convspace = Conv2DSpace(shape=(32, 32), num_channels=3, axes=('b', 'c', 0, 1))
    target_space = VectorSpace(dim=10)
{'fraction_non_alphanumeric': 0.12186084808563195, 'fraction_numerical': 0.006751749691230959, 'mean_word_length': 4.893255701115963, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7528282', 'n_tokens_mistral': 3437, 'n_tokens_neox': 3291, 'n_words': 1560}