示例#1
0
def test_mnist():
    '''
    Tests load_mnist().

    Checks test & train sets' formats and sizes, but not content.
    '''
    train_set, test_set = load_mnist()

    for mnist, expected_size in safe_izip((train_set, test_set),
                                          (60000, 10000)):
        assert_equal(mnist.num_examples(), expected_size)

    expected_formats = [DenseFormat(shape=[-1, 28, 28],
                                    axes=['b', '0', '1'],
                                    dtype='uint8'),
                        DenseFormat(shape=[-1],
                                    axes=['b'],
                                    dtype='uint8')]
    expected_names = [u'images', u'labels']
    expected_sizes = [60000, 10000]

    for dataset, expected_size in safe_izip((train_set, test_set),
                                            expected_sizes):
        assert_all_equal(dataset.names, expected_names)
        assert_all_equal(dataset.formats, expected_formats)

        for tensor, fmt in safe_izip(dataset.tensors, dataset.formats):
            fmt.check(tensor)
            assert_equal(tensor.shape[0], expected_size)

        labels = dataset.tensors[dataset.names.index('labels')]
        assert_true(numpy.logical_and(labels[...] >= 0,
                                      labels[...] < 10).all())
示例#2
0
    def num_examples(self):
        '''
        The number of examples contained in this Dataset.

        Throws a RuntimeException if this Dataset contains no tensors.
        '''
        if len(self.tensors) == 0:
            raise RuntimeError("This dataset has no tensors, so its "
                               "'size' is undefined.")

        sizes = [t.shape[f.axes.index('b')]
                 for t, f in safe_izip(self.tensors, self.formats)]
        assert_all_equal(sizes)
        return sizes[0]
示例#3
0
def build_conv_classifier(input_node,
                          filter_shapes,
                          filter_counts,
                          filter_init_uniform_ranges,
                          pool_shapes,
                          pool_strides,
                          affine_output_sizes,
                          affine_init_stddevs,
                          dropout_include_rates,
                          conv_pads,
                          rng,
                          theano_rng):
    '''
    Builds a classification convnet on top of input_node.

    Returns
    -------
    rval: tuple
      (conv_nodes, affine_nodes, output_node), where:
         conv_nodes is a list of the Conv2d nodes.
         affine_nodes is a list of the AffineNodes.
         output_node is the final node, a Softmax.
    '''

    assert_is_instance(input_node, Lcn)

    conv_shape_args = (filter_shapes,
                       pool_shapes,
                       pool_strides)

    for conv_shapes in conv_shape_args:
        for conv_shape in conv_shapes:
            assert_all_integer(conv_shape)
            assert_all_greater(conv_shape, 0)

    conv_args = conv_shape_args + (filter_counts, filter_init_uniform_ranges)
    assert_all_equal([len(c) for c in conv_args])

    assert_equal(len(affine_output_sizes), len(affine_init_stddevs))

    assert_equal(len(dropout_include_rates),
                 len(filter_shapes) + len(affine_output_sizes))

    assert_equal(affine_output_sizes[-1], 10)  # for MNIST

    #assert_equal(input_node.output_format.axes, ('b', '0', '1'))

    #
    # Done sanity-checking args.
    #

    input_shape = input_node.output_format.shape

    # Converts from MNIST's ('b', '0', '1') to ('b', 'c', '0', '1')
    last_node = input_node

    conv_dropout_include_rates = \
        dropout_include_rates[:len(filter_shapes)]

    # Adds a dropout-conv-bias-relu-maxpool stack for each element in
    # filter_XXXX

    conv_layers = []

    def uniform_init(rng, params, init_range):
        '''
        Fills params with values uniformly sampled from
        [-init_range, init_range]
        '''

        assert_floating(init_range)
        assert_greater_equal(init_range, 0)

        values = params.get_value()
        values[...] = rng.uniform(low=-init_range,
                                  high=init_range,
                                  size=values.shape)
        params.set_value(values)

    for (filter_shape,
         filter_count,
         filter_init_range,
         pool_shape,
         pool_stride,
         conv_dropout_include_rate,
         conv_pads)                 in safe_izip(filter_shapes,
                                                 filter_counts,
                                                 filter_init_uniform_ranges,
                                                 pool_shapes,
                                                 pool_strides,
                                                 conv_dropout_include_rates,
                                                 conv_pads):
        if conv_dropout_include_rate != 1.0:
            last_node = Dropout(last_node,
                                conv_dropout_include_rate,
                                theano_rng)

        last_node = Conv2dLayer(last_node,
                                filter_shape,
                                filter_count,
                                conv_pads=conv_pads,
                                pool_window_shape=pool_shape,
                                pool_strides=pool_stride,
                                pool_pads='pylearn2')
        conv_layers.append(last_node)

        uniform_init(rng, last_node.conv2d_node.filters, filter_init_range)

    affine_dropout_include_rates = dropout_include_rates[len(filter_shapes):]

    affine_layers = []

    def normal_distribution_init(rng, params, stddev):
        '''
        Fills params with values uniformly sampled from
        [-init_range, init_range]
        '''

        assert_floating(stddev)
        assert_greater_equal(stddev, 0)

        values = params.get_value()
        values[...] = rng.standard_normal(values.shape) * stddev
        params.set_value(values)

    #
    # Adds a dropout-affine-relu stack for each element in affine_XXXX,
    # except for the last one, where it omits the dropout.
    #

    # Add a fully connected layer here:
    output_format = DenseFormat(axes=('b', 'f'),
                                    shape=(-1, 500),
                                    dtype=None)

    if affine_dropout_include_rates < 1.0:
        last_node = Dropout(last_node,
                            affine_dropout_include_rates,
                            theano_rng)

    last_node = AffineLayer(last_node, output_format, input_to_bf_map={('0', '1', 'c'): 'f'})
    affine_layers.append(last_node)
    normal_distribution_init(rng,
                         last_node.affine_node.linear_node.params,
                         0.05)
 

    for (affine_size,
         affine_init_stddev,
         affine_dropout_include_rate) in \
        safe_izip(affine_output_sizes,
                  affine_init_stddevs,
                  affine_dropout_include_rates):

        '''
        if affine_dropout_include_rate < 1.0:
            last_node = Dropout(last_node,
                                affine_dropout_include_rate,
                                theano_rng)
        '''
        # No need to supply an axis map for the first affine transform.
        # By default, it collapses all non-'b' axes into a feature vector,
        # which is what we want.

        # remap from bc01 to b01c before flattening to bf, as pylearn2 does,
        # just so that they do identical things.
        last_node = SoftmaxLayer(last_node,
                                 DenseFormat(axes=('b', 'f'),
                                             shape=(-1, affine_size),
                                             dtype=None))
                                 #input_to_bf_map={('0', '1', 'c'): 'f'})
        normal_distribution_init(rng,
                                 last_node.affine_node.linear_node.params,
                                 affine_init_stddev)
        # stddev_init(rng, last_node.bias_node.params, affine_init_stddev)
        affine_layers.append(last_node)

    return conv_layers, affine_layers, last_node
def build_conv_classifier(input_node,
                          filter_shapes,
                          filter_counts,
                          filter_init_uniform_ranges,
                          pool_shapes,
                          pool_strides,
                          affine_output_sizes,
                          affine_init_stddevs,
                          dropout_include_rates,
                          conv_pads,
                          rng,
                          theano_rng):
    '''
    Builds a classification convnet on top of input_node.

    Returns
    -------
    rval: tuple
      (conv_nodes, affine_nodes, output_node), where:
         conv_nodes is a list of the Conv2d nodes.
         affine_nodes is a list of the AffineNodes.
         output_node is the final node, a Softmax.
    '''

    assert_is_instance(input_node, Lcn)

    conv_shape_args = (filter_shapes,
                       pool_shapes,
                       pool_strides)

    for conv_shapes in conv_shape_args:
        for conv_shape in conv_shapes:
            assert_all_integer(conv_shape)
            assert_all_greater(conv_shape, 0)

    conv_args = conv_shape_args + (filter_counts, filter_init_uniform_ranges)
    assert_all_equal([len(c) for c in conv_args])

    assert_equal(len(affine_output_sizes), len(affine_init_stddevs))

    assert_equal(len(dropout_include_rates),
                 len(filter_shapes) + len(affine_output_sizes))

    assert_equal(affine_output_sizes[-1], 10)  # for MNIST

    #assert_equal(input_node.output_format.axes, ('b', '0', '1'))

    #
    # Done sanity-checking args.
    #

    input_shape = input_node.output_format.shape

    # Converts from MNIST's ('b', '0', '1') to ('b', 'c', '0', '1')
    last_node = input_node

    conv_dropout_include_rates = \
        dropout_include_rates[:len(filter_shapes)]

    # Adds a dropout-conv-bias-relu-maxpool stack for each element in
    # filter_XXXX

    conv_layers = []

    def uniform_init(rng, params, init_range):
        '''
        Fills params with values uniformly sampled from
        [-init_range, init_range]
        '''

        assert_floating(init_range)
        assert_greater_equal(init_range, 0)

        values = params.get_value()
        values[...] = rng.uniform(low=-init_range,
                                  high=init_range,
                                  size=values.shape)
        params.set_value(values)

    for (filter_shape,
         filter_count,
         filter_init_range,
         pool_shape,
         pool_stride,
         conv_dropout_include_rate,
         conv_pad)                 in safe_izip(filter_shapes,
                                                 filter_counts,
                                                 filter_init_uniform_ranges,
                                                 pool_shapes,
                                                 pool_strides,
                                                 conv_dropout_include_rates,
                                                 conv_pads):
        if conv_dropout_include_rate != 1.0:
            last_node = Dropout(last_node,
                                conv_dropout_include_rate,
                                theano_rng)

        last_node = Conv2dLayer(last_node,
                                filter_shape,
                                filter_count,
                                conv_pads=conv_pad,
                                pool_window_shape=pool_shape,
                                pool_strides=pool_stride,
                                pool_pads='pylearn2')
        conv_layers.append(last_node)

        uniform_init(rng, last_node.conv2d_node.filters, filter_init_range)

    affine_dropout_include_rates = dropout_include_rates[len(filter_shapes):]

    affine_layers = []

    def normal_distribution_init(rng, params, stddev):
        '''
        Fills params with values uniformly sampled from
        [-init_range, init_range]
        '''

        assert_floating(stddev)
        assert_greater_equal(stddev, 0)

        values = params.get_value()
        values[...] = rng.standard_normal(values.shape) * stddev
        params.set_value(values)

    #
    # Adds a dropout-affine-relu stack for each element in affine_XXXX,
    # except for the last one, where it omits the dropout.
    #

    # Add a fully connected layer here:
    output_format = DenseFormat(axes=('b', 'f'),
                                    shape=(-1, 500),
                                    dtype=None)

    if affine_dropout_include_rates < 1.0:
        last_node = Dropout(last_node,
                            affine_dropout_include_rates,
                            theano_rng)

    last_node = AffineLayer(last_node, output_format, input_to_bf_map={('0', '1', 'c'): 'f'})
    affine_layers.append(last_node)
    normal_distribution_init(rng,
                         last_node.affine_node.linear_node.params,
                         0.05)


    for (affine_size,
         affine_init_stddev,
         affine_dropout_include_rate) in \
        safe_izip(affine_output_sizes,
                  affine_init_stddevs,
                  affine_dropout_include_rates):

        '''
        if affine_dropout_include_rate < 1.0:
            last_node = Dropout(last_node,
                                affine_dropout_include_rate,
                                theano_rng)
        '''
        # No need to supply an axis map for the first affine transform.
        # By default, it collapses all non-'b' axes into a feature vector,
        # which is what we want.

        # remap from bc01 to b01c before flattening to bf, as pylearn2 does,
        # just so that they do identical things.
        last_node = SoftmaxLayer(last_node,
                                 DenseFormat(axes=('b', 'f'),
                                             shape=(-1, affine_size),
                                             dtype=None))
                                 #input_to_bf_map={('0', '1', 'c'): 'f'})
        normal_distribution_init(rng,
                                 last_node.affine_node.linear_node.params,
                                 affine_init_stddev)
        # stddev_init(rng, last_node.bias_node.params, affine_init_stddev)
        affine_layers.append(last_node)

    #################################################################################################
    ### BUILD THE SECOND NETWORK WITH FLAT PARAMETERS (given the dimensions of the first) ###########
    #################################################################################################

    rng = numpy.random.RandomState(281934)
    std_deviation = .05

    # Fetch all parameters and shapes
    parameters = []
    for conv_layer in conv_layers:
        filters = conv_layer.conv2d_node.filters
        parameters.append(filters)

        bias = conv_layer.bias_node.params
        parameters.append(bias)

    for affine_layer in affine_layers:
        weights = affine_layer.affine_node.linear_node.params
        parameters.append(weights)

        biases = affine_layer.affine_node.bias_node.params
        parameters.append(biases)

    '''
    print(len(parameters))
    for parameter in parameters:
        print(parameter.get_value().shape)

    shapes = []
    params_flat_values = numpy.asarray([], dtype=theano.config.floatX)
    counter = 0
    for parameter in parameters:
        shape = parameter.get_value().shape
        if counter%2 == 0 and len(shape)==4:
            vector_param = numpy.asarray(numpy.ndarray.flatten(parameter.get_value()), dtype=theano.config.floatX)
            vector_param[...] = rng.standard_normal(vector_param.shape) * std_deviation
            col_length = shape[2]
            index_from = 0

            ###
            #for _ in range(shape[0]*shape[1]*shape[3]):
            #    index_to = index_from + col_length
            #    vector_param[index_from:index_to] = vector_param[index_from:index_to]/numpy.linalg.norm(vector_param[index_from:index_to])
            #    index_from = index_to
            ####

        elif counter%2==0:
            vector_param = numpy.asarray(numpy.ndarray.flatten(parameter.get_value()), dtype=theano.config.floatX)
            vector_param[...] = rng.standard_normal(vector_param.shape) * std_deviation
        else:
            vector_param = numpy.asarray(numpy.ndarray.flatten(parameter.get_value()), dtype=theano.config.floatX)

        params_flat_values = numpy.append(params_flat_values, vector_param)
        shapes.append(shape)
    '''
    params_flat_values = numpy.asarray([], dtype=theano.config.floatX)
    shapes = []

    for parameter in parameters:
        parameter_value = parameter.get_value()
        shapes.append(parameter_value.shape)
        vector_param = numpy.asarray(numpy.ndarray.flatten(parameter_value))
        params_flat_values = numpy.append(params_flat_values, vector_param)
        print(parameter.get_value().shape)

    print(params_flat_values)
    print(params_flat_values.shape)

    params_flat = theano.shared(params_flat_values)
    params_old_flat = theano.shared(params_flat_values)

    '''
    Builds a classification convnet on top of input_node.

    Returns
    -------
    rval: tuple
      (conv_nodes, affine_nodes, output_node), where:
         conv_nodes is a list of the Conv2d nodes.
         affine_nodes is a list of the AffineNodes.
         output_node is the final node, a Softmax.
    '''

    assert_is_instance(input_node, Lcn)

    conv_shape_args = (filter_shapes,
                       pool_shapes,
                       pool_strides)

    for conv_shapes in conv_shape_args:
        for conv_shape in conv_shapes:
            assert_all_integer(conv_shape)
            assert_all_greater(conv_shape, 0)

    conv_args = conv_shape_args + (filter_counts, filter_init_uniform_ranges)
    assert_all_equal([len(c) for c in conv_args])

    assert_equal(len(affine_output_sizes), len(affine_init_stddevs))

    assert_equal(len(dropout_include_rates),
                 len(filter_shapes) + len(affine_output_sizes))

    assert_equal(affine_output_sizes[-1], 10)  # for MNIST

    #assert_equal(input_node.output_format.axes, ('b', '0', '1'))

    #
    # Done sanity-checking args.
    #

    input_shape = input_node.output_format.shape

    # Converts from MNIST's ('b', '0', '1') to ('b', 'c', '0', '1')
    last_node = input_node

    conv_dropout_include_rates = \
        dropout_include_rates[:len(filter_shapes)]

    # Adds a dropout-conv-bias-relu-maxpool stack for each element in
    # filter_XXXX

    conv_layers = []
    counter = 0
    index_from = 0

    for (filter_shape,
         filter_count,
         filter_init_range,
         pool_shape,
         pool_stride,
         conv_dropout_include_rate,
         conv_pad)                 in safe_izip(filter_shapes,
                                                 filter_counts,
                                                 filter_init_uniform_ranges,
                                                 pool_shapes,
                                                 pool_strides,
                                                 conv_dropout_include_rates,
                                                 conv_pads):
        if conv_dropout_include_rate != 1.0:
            last_node = Dropout(last_node,
                                conv_dropout_include_rate,
                                theano_rng)

        print(shapes)

        shape1 = shapes[counter]
        shape2 = shapes[counter+1]
        size1= numpy.prod(numpy.asarray(shape1))
        size2= numpy.prod(numpy.asarray(shape2))
        index_to = index_from + size1
        #filters_ = theano.tensor.transpose(params_flat[index_from:index_to].reshape(shape1), axes=[0,1,3,2])
        filters_ = params_flat[index_from:index_to].reshape(shape1)
        index_from = index_to
        index_to = index_from + size2
        bias_ = params_flat[index_from:index_to].reshape(shape2)
        index_from = index_to

        last_node = Conv2dLayer(last_node,
                                filter_shape,
                                filter_count,
                                conv_pads=conv_pad,
                                pool_window_shape=pool_shape,
                                pool_strides=pool_stride,
                                pool_pads='pylearn2',
                                filters=filters_,
                                bias=bias_)
        conv_layers.append(last_node)

        counter = counter + 2


    affine_dropout_include_rates = dropout_include_rates[len(filter_shapes):]

    affine_layers = []

    #
    # Adds a dropout-affine-relu stack for each element in affine_XXXX,
    # except for the last one, where it omits the dropout.
    #

    # Add a fully connected layer here:

    shape1 = shapes[counter]
    #shape1 = (shape1[1], shape1[0])
    shape2 = shapes[counter+1]
    size1= numpy.prod(numpy.asarray(shape1))
    size2= numpy.prod(numpy.asarray(shape2))
    index_to = index_from + size1
    weights_ = params_flat[index_from:index_to].reshape(shape1)
    index_from = index_to
    index_to = index_from + size2
    bias_ = params_flat[index_from:index_to].reshape(shape2)
    index_from = index_to

    output_format = DenseFormat(axes=('b', 'f'),
                                    shape=(-1, 500),
                                    dtype=None)

    if affine_dropout_include_rates < 1.0:
        last_node = Dropout(last_node,
                            affine_dropout_include_rates,
                            theano_rng)

    last_node = AffineLayer(last_node, output_format, weights=weights_, bias=bias_, input_to_bf_map={('0', '1', 'c'): 'f'})
    affine_layers.append(last_node)

    counter += 2

    for (affine_size,
         affine_init_stddev,
         affine_dropout_include_rate) in \
        safe_izip(affine_output_sizes,
                  affine_init_stddevs,
                  affine_dropout_include_rates):

        if affine_dropout_include_rate < 1.0:
            last_node = Dropout(last_node,
                                affine_dropout_include_rate,
                                theano_rng)

        # No need to supply an axis map for the first affine transform.
        # By default, it collapses all non-'b' axes into a feature vector,
        # which is what we want.

        shape1 = shapes[counter]
        #shape1 = (shape1[1], shape1[0])
        shape2 = shapes[counter+1]
        size1= numpy.prod(numpy.asarray(shape1))
        size2= numpy.prod(numpy.asarray(shape2))
        index_to = index_from + size1
        weights_ = params_flat[index_from:index_to].reshape(shape1)
        index_from = index_to
        index_to = index_from + size2
        bias_ = params_flat[index_from:index_to].reshape(shape2)
        index_from = index_to
        # remap from bc01 to b01c before flattening to bf, as pylearn2 does,
        # just so that they do identical things.
        last_node = SoftmaxLayer(last_node,
                                 DenseFormat(axes=('b', 'f'),
                                             shape=(-1, affine_size),
                                             dtype=None),
                                 weights=weights_,
                                 bias=bias_)
                                 #input_to_bf_map={('0', '1', 'c'): 'f'})

        # stddev_init(rng, last_node.bias_node.params, affine_init_stddev)
        affine_layers.append(last_node)

        counter += 2


    return conv_layers, affine_layers, last_node, params_flat, params_old_flat, shapes
def make_instance_dataset(norb_name,
                          a_norb,
                          b_norb,
                          test_elevation_stride,
                          test_azimuth_stride,
                          objects=None):
    '''
    Creates instance recognition datasets from category recognition datasets.

    Merges two category recognition datasets (with disjoint object instances),
    and re-partitions them into instance recognition datasets (with disjoint
    camera views).

    The instance recognition dataset consists of a train and test set.

    All objects not selected by <objects> are ignored.

    Of the remaining images, he test set consists of all images that satisfy
    both the test_elevation_stride and test_azimuth_stride. The other
    images are used for the training set.

    If the category datset is in stereo, only the left stereo images are used.

    Parameters
    ----------
    norb_name: str
      The name of the category recognition dataset (e.g. 'big_norb'). Used to
      build the name of the instance recognition dataset. Alphanumeric
      characters and '_' only.

    a_norb: NORB Dataset
      One of the category recognition datasets (i.e. training set).

    b_norb: NORB Dataset
      The other category recognition dataset (i.e. testing set).

    test_elevation_stride: int
      Use every M'th elevation as a test image.

    test_azimuth_stride: int
      Use every N'th azimuth as a test image.

    objects: Sequence
      [(c0, i0), (c1, i1), ..., (cN, iN)]
      Each (cx, ix) pair specifies an object to include, by their
      class and instance labels cx and ix.

    Returns
    -------
    rval: str
      The path to the newly created .h5 file.
    '''

    assert_is_instance(norb_name, basestring)
    assert_all_true(c.isalnum() or c == '_' for c in norb_name)

    assert_is_instance(a_norb, Dataset)
    assert_is_instance(b_norb, Dataset)
    assert_all_equal(a_norb.names, b_norb.names)
    assert_all_equal(a_norb.formats, b_norb.formats)

    assert_integer(test_elevation_stride)
    assert_greater(test_elevation_stride, 0)

    assert_integer(test_azimuth_stride)
    assert_greater(test_azimuth_stride, 0)

    if objects is not None:
        assert_is_instance(objects, Sequence)
        for id_pair in objects:
            assert_equal(len(id_pair), 2)
            assert_all_integer(id_pair)
            assert_all_greater_equal(id_pair, 0)

    #
    # Done sanity-checking args
    #

    (category_index,
     instance_index,
     azimuth_index,
     elevation_index) = range(4)  # no need for lighting_index (= 4)

    def get_row_indices(labels,
                        test_elevation_stride,
                        test_azimuth_stride,
                        objects):
        '''
        Returns row indices or training and testing sets.
        '''

        logical_and = numpy.logical_and

        if objects is not None:
            objects = numpy.asarray(objects)
            obj_cols = (category_index, instance_index)
            object_mask = (labels[:, obj_cols] == objects).all(axis=1)
        else:
            object_mask = numpy.ones(labels.shape[0], dtype=bool)

        test_mask = logical_and(
            object_mask,
            (labels[:, elevation_index] % test_elevation_stride) == 0)

        test_mask = logical_and(
            test_mask,
            (labels[:, azimuth_index] % (test_azimuth_stride * 2)) == 0)

        train_mask = logical_and(object_mask, numpy.logical_not(test_mask))

        return tuple(numpy.nonzero(m)[0] for m in (train_mask, test_mask))

    a_train_indices, a_test_indices = get_row_indices(a_norb.tensors[1],
                                                      test_elevation_stride,
                                                      test_azimuth_stride,
                                                      objects)

    b_train_indices, b_test_indices = get_row_indices(b_norb.tensors[1],
                                                      test_elevation_stride,
                                                      test_azimuth_stride,
                                                      objects)

    def create_h5_filepath(norb_name,
                           test_elevation_stride,
                           test_azimuth_stride,
                           objects):
        '''
        Creates an hdf filepath based on the args.

        For which-norb: "big_norb", elevation_stride: 2, azimuth_stride: 1:
          <data_dir>/big_norb_instance/e2_a1_all.h5

        For same as above, but with objects: [[1, 2], [3, 7], [4, 1]]
          <data_dir>/big_norb_instance/e2_a1_1-2_3-7_4-1.h5
        '''
        output_dir = os.path.join(simplelearn.data.data_path,
                                  '{}_instance'.format(norb_name))

        if not os.path.isdir(output_dir):
            os.mkdir(output_dir)

        filename = "e{:02d}_a{:02d}_o_".format(test_elevation_stride,
                                               test_azimuth_stride)

        if objects is None:
            filename = filename + 'all'
        else:
            for id_pair in objects:
                filename = filename + "%d-%d" % tuple(id_pair)

        filename = filename + '.h5'

        return os.path.join(output_dir, filename)

    h5_path = create_h5_filepath(norb_name,
                                 test_elevation_stride,
                                 test_azimuth_stride,
                                 objects)

    def get_mono_format(input_image_format):
        axes = input_image_format.axes
        shape = input_image_format.shape

        if 's' in axes:
            s_index = axes.index('s')
            axes = list(axes)
            del axes[s_index]

            shape = list(shape)
            del shape[s_index]

        return DenseFormat(axes=axes,
                           shape=shape,
                           dtype=input_image_format.dtype)

    mono_image_format = get_mono_format(a_norb.formats[0])
    label_format = a_norb.formats[1]
    partition_names = ['train', 'test']
    partition_sizes = [len(a_train_indices) + len(b_train_indices),
                       len(a_test_indices) + len(b_test_indices)]
    train_indices = (a_train_indices, b_train_indices)
    test_indices = (a_test_indices, b_test_indices)

    # Creates a .h5 file and copies repartitioned data into it.
    with make_h5_file(h5_path,
                      partition_names,
                      partition_sizes,
                      a_norb.names,
                      [mono_image_format, label_format]) as h5_file:
        partitions = h5_file['partitions']

        for partition_name, (a_indices, b_indices) \
            in safe_izip(partition_names, [train_indices, test_indices]):

            partition = partitions[partition_name]

            a_images = a_norb.tensors[0]
            b_images = b_norb.tensors[0]
            out_images = partition['images']

            print("Copying {} partition.".format(partition_name))

            if 's' in a_norb.formats[0].axes:
                assert_equal(a_norb.formats[0].axes.index('s'), 1)

                out_images[:len(a_indices), ...] = a_images[a_indices, 0, ...]
                out_images[len(a_indices):, ...] = b_images[b_indices, 0, ...]
            else:
                out_images[:len(a_indices), ...] = a_images[a_indices, ...]
                out_images[len(a_indices):, ...] = b_images[b_indices, ...]

            a_labels = a_norb.tensors[1]
            b_labels = b_norb.tensors[1]
            out_labels = partition['labels']

            out_labels[:len(a_indices), :] = a_labels[a_indices, :]
            out_labels[len(a_indices):, :] = b_labels[b_indices, :]

            # Don't shuffle the data; that's the iterator's job.

    return h5_path