Search code examples
pythonneural-networkmnistchainer

Using arrays as labels on MNIST data in chainer


The python module chainer has an introduction where it uses its neural network to recognize handwritten digits from the MNIST database.

Assuming that a particular handwritten digit D.png is labeled as a 3. I'm used to the label appearing as an array as follows:

label = [0, 0, 0, 1, 0, 0, 0, 0, 0, 0]

However, chainer labels with an integer instead:

label = 3

The array-label is more intuitive to me because the output prediction is an array as well. In neural networks that don't deal with images, I want the flexibility to give the label to be a specific array.

I have included code below directly from the chainer introduction. If you parse through train or test dataset, notice that all of the labels are integers and not floats.

How would I run training/test data with arrays as labels instead of integers?

import numpy as np
import chainer
from chainer import cuda, Function, gradient_check, report, training, utils, Variable
from chainer import datasets, iterators, optimizers, serializers
from chainer import Link, Chain, ChainList
import chainer.functions as F
import chainer.links as L
from chainer.training import extensions

class MLP(Chain):
    def __init__(self, n_units, n_out):
        super(MLP, self).__init__()
        with self.init_scope():
            # the size of the inputs to each layer will be inferred
            self.l1 = L.Linear(None, n_units)  # n_in -> n_units
            self.l2 = L.Linear(None, n_units)  # n_units -> n_units
            self.l3 = L.Linear(None, n_out)    # n_units -> n_out

    def __call__(self, x):
        h1 = F.relu(self.l1(x))
        h2 = F.relu(self.l2(h1))
        y = self.l3(h2)
        return y

train, test = datasets.get_mnist()

train_iter = iterators.SerialIterator(train, batch_size=100, shuffle=True)
test_iter = iterators.SerialIterator(test, batch_size=100, repeat=False, shuffle=False)

model = L.Classifier(MLP(100, 10))  # the input size, 784, is inferred
optimizer = optimizers.SGD()
optimizer.setup(model)

updater = training.StandardUpdater(train_iter, optimizer)
trainer = training.Trainer(updater, (20, 'epoch'), out='result')

trainer.extend(extensions.Evaluator(test_iter, model))
trainer.extend(extensions.LogReport())
trainer.extend(extensions.PrintReport(['epoch', 'main/accuracy', 'validation/main/accuracy']))
trainer.extend(extensions.ProgressBar())
trainer.run()

Solution

  • The Classifier accepts a tuple containing image or other data as array(float32) and label as int. This is a convention for chainer and how it works there. If you print your label you will see that you are getting an array with dtype int. Both the image/non-image data and the label will be in arrays but with dtype float and int respectively.

    So to answer your question: your labels are in array format itself with dtype int(as it should be for labels).

    If you want your labels to be 0's and 1's instead of 1 to 10 then use One Hot Encoding(https://blog.cambridgespark.com/robust-one-hot-encoding-in-python-3e29bfcec77e).