nagasgura
nagasgura

Reputation: 53

Get probable input based on a given output in a neural network

I'm starting to learn neural networks, and I just made a program that learned how to recognize handwritten digits with pretty good accuracy (trained with backpropagation). Now I want to be able to see what the network thinks a perfect number looks like (essentially getting a pixel array which produces a desired number but is not from the dataset). My research has come up empty, but I posted on another site and was suggested to look at backpropagating to the input. I don't have much of a math background, so could someone point me in the right direction on how to implement that (or any other method of achieving my goal)?

Upvotes: 5

Views: 2331

Answers (1)

lmjohns3
lmjohns3

Reputation: 7592

You can get some idea of an "ideal" input for each of the classes in a multi-class classifier neural network (NN) by inverting the model and visualizing the weights for the output layer, as projected onto the pixels at the input layer.

Suppose you had a simple linear classifier NN that had 784 inputs (the number of pixels in an MNIST digit image) and 10 outputs (the number of digit classes) -- with no hidden layer. The activation z of the output layer given an input image x (a 784-element column vector) is given by z = f(x) = Wx + b where W is the 10 x 784 weight matrix and b is the 10-element bias vector.

You can do some algebra and invert this model easily, to compute x given z: x = f^-1(z) = W^-1 (z - b). Now let's say you wanted to see the optimal input for the 4 class. The target output for this class would be z = [0 0 0 0 1 0 0 0 0 0]^T; if we ignore the bias for the moment, then you would just need to compute the 4th column (starting with 0) of the inverse of W, a 784-element column vector, rearrange it back into a 28 x 28 image, and view it. This is the optimal input because the output layer activation is proportional to the dot product of the input and the weight vector for that class, so an input vector that's identical to the weight vector for class 4 will maximally activate that class at the output layer.

Things get more complicated if you add more layers and nonlinearities to the model, but the general approach remains the same. You want some way to compute an optimal input x* given a target output z* for the model, but you only know the (possibly complicated) forward map z = f(x) from inputs to targets. You can treat this as an optimization problem: you're trying to compute x* = f^-1(z*) and you know f and z*. If your knowledge of f allows you to compute a symbolic inverse in closed form, then you can just plug z* in and get x*. If you can't do this, you can always use an iterative optimization procedure to compute successively better approximations x1, x2, ..., xn given a starting guess of x0. Here's some Python pseudocode for doing this using scipy.optimize:

import numpy as np
import scipy.optimize

# our forward model, paired layers of already-trained
# weights and biases.
weights = [np.array(...) ...]
biases = [np.array(...) ...]
def f(x):
    for W, b in zip(weights, biases):
        # relu activation.
        x = np.clip(np.dot(W, x) + b, 0, np.inf)
    return x

# set our sights on class #4.
zstar = np.array([0, 0, 0, 0, 1, 0, 0, 0, 0, 0])

# the loss we want to optimize: minimize difference
# between zstar and f(x).
def loss(x):
    return abs(f(x) - zstar).sum()

x0 = np.zeros(784)
result = scipy.optimize.minimize(loss, x0)

Incidentally, this process is basically at the core of the recent "Inceptionism" images from Google -- the optimization process is attempting to determine the input pixels that replicate the state of a particular hidden layer in a complicated network. It's more complicated in this case because of the convolutions etc. but the idea is similar.

Upvotes: 3

Related Questions