zondag 24 mei 2015

Vierde deel in "Deep Learning met Python" cursus - Modern netwerk

De gradient-functie (sgd) nadert maar langzaam zijn optimum.

In het vierde deel wordt de netwerk opzet verbeterd:

  • Een 'rectify' functie die in principe alle negatieve waarden naar nul terugbrengt waardoor er steeds met 'schone' waardes wordt gewerkt.
  • Een aangepaste softmax functie. Dit heeft meer een technische reden. De ingebouwde softmax blijkt niet altijd goed te voldoen.
  • De RMSprop functie. Een mooie grafiek (zie hierboven) laat zien dat de eerder gebruikte 'gradient-functie' bij het 'leren' steeds langzamer naar het gewenste optimum toe gaat. De hier gedefinieerde RMSprop functie doet dit veel sneller. Er zijn dus minder leer-loops noodzakelijk om bij het gewenste punt uit te komen.          
  • De dropout functie. Deze wordt gebruikt om bewust, random 'vervuiling' in de invoer en in de verborgen lagen aan te brengen. Hierdoor wordt het leren iets flexibeler. 
  • De tussenlaag is 784x625 en de output laag is 625x10. Het is mij nog niet helemaal duidelijk hoe deze formaten zijn gekozen. Alleen de 784 (28*28) is gelijk aan de input en de 10 is gelijk aan het aantal mogelijke uitkomsten. Het formaat daartussen (625 = 25*25) begrijp ik niet helemaal.

Hier is de betreffende code. Na 100 leerloops wordt er een betrouwbaarheid mee bereikt van 98,77%
Alweer een stapje dichter bij het noodzakelijke niveau van  99,5%. Straks kijken wat een 'convolutional network' gaat brengen!

import theano
from theano import tensor as T
from theano.sandbox.rng_mrg import MRG_RandomStreams as RandomStreams
import numpy as np
import time
from load import mnist

srng = RandomStreams()

def floatX(X):
    return np.asarray(X, dtype=theano.config.floatX)

def init_weights(shape):
    return theano.shared(floatX(np.random.randn(*shape) * 0.01))

def rectify(X):
    return T.maximum(X, 0.)

def softmax(X):
    e_x = T.exp(X - X.max(axis=1).dimshuffle(0'x'))
    return e_x / e_x.sum(axis=1).dimshuffle(0'x')

def RMSprop(cost, params, lr=0.001, rho=0.9, epsilon=1e-6):
    grads = T.grad(cost=cost, wrt=params)
    updates = []
    for p, g in zip(params, grads):
        acc = theano.shared(p.get_value() * 0.)
        acc_new = rho * acc + (1 - rho) * g ** 2
        gradient_scaling = T.sqrt(acc_new + epsilon)
        g = g / gradient_scaling
        updates.append((acc, acc_new))
        updates.append((p, p - lr * g))
    return updates

def dropout(X, p=0.):
    if p > 0:
        retain_prob = 1 - p
        X *= srng.binomial(X.shape, p=retain_prob, dtype=theano.config.floatX)
        X /= retain_prob
    return X

def model(X, w_h, w_h2, w_o, p_drop_input, p_drop_hidden):
    X = dropout(X, p_drop_input)
    h = rectify(T.dot(X, w_h))

    h = dropout(h, p_drop_hidden)
    h2 = rectify(T.dot(h, w_h2))

    h2 = dropout(h2, p_drop_hidden)
    py_x = softmax(T.dot(h2, w_o))
    return h, h2, py_x

trX, teX, trY, teY = mnist(onehot=True)

X = T.fmatrix()
Y = T.fmatrix()

w_h = init_weights((784625))
w_h2 = init_weights((625625))
w_o = init_weights((62510))

noise_h, noise_h2, noise_py_x = model(X, w_h, w_h2, w_o, 0.20.5)
h, h2, py_x = model(X, w_h, w_h2, w_o, 0.0.)
y_x = T.argmax(py_x, axis=1)

cost = T.mean(T.nnet.categorical_crossentropy(noise_py_x, Y))
params = [w_h, w_h2, w_o]
updates = RMSprop(cost, params, lr=0.001)

train = theano.function(inputs=[X, Y], outputs=cost, updates=updates, allow_input_downcast=True)
predict = theano.function(inputs=[X], outputs=y_x, allow_input_downcast=True)
t0 = time.time()
for i in range(100):
    for start, end in zip(range(0, len(trX), 128), range(128, len(trX), 128)):
        cost = train(trX[start:end], trY[start:end])
    print np.mean(np.argmax(teY, axis=1) == predict(teX))

print time.time() - t0, "seconds"

Geen opmerkingen:

Een reactie posten