2015-11-23 15 views
8

Lasagne/Theano çerçevesindeki "Unsupervised Domain Adaptation by Backpropagation" makalesinde önerilen mimariden faydalanmak istiyorum. alt kısmı boyuncaGeri yayılma sırasında Theano gradyanlarını tersine çevirebilir miyim (seçici olarak)?

enter image description here

(oklar:

biraz olağan dışı kılan bu kağıt ile ilgili bir şey, bir 'gradyan ters tabaka', tersine döndüğü geri yayılım sırasında degrade sahip olmasıdır görüntünün, eğimlerini ters çevrilmiş olan geri yayılımlar vardır. Makalede yazarlar, yaklaşımın "herhangi bir derin öğrenme paketi kullanılarak uygulanabileceğini" iddia ediyorlar ve gerçekten de version made in caffe sağlıyorlar. Ancak çeşitli nedenlerden dolayı Lasagne/Theano çerçevesini kullanıyorum.

Lasagne/Theano'da böyle bir degrade ters katman oluşturmak mümkün mü? Özel skaler dönüşümleri bu gibi gradyanlara uygulayabilecek herhangi bir örnek görmedim. Eğer öyleyse, Lasagne'de özel bir katman oluşturarak yapabilir miyim?

cevap

7

Sade Theano kullanarak bir çizim uygulaması. Bu kolayca Lasagne içine entegre edilebilir.

İleri geçişte kimlik işlemi olarak işlev gören ancak geri geçişteki degradeyi tersine çeviren özel bir işlem oluşturmanız gerekir.

Bunun nasıl uygulanabileceğine dair bir öneri. Test edilmiyor ve% 100 emin değilim, her şeyi doğru anladım, ancak gerektiği gibi doğrulayabilir ve düzeltebilirsiniz.

class ReverseGradient(theano.gof.Op): 
    view_map = {0: [0]} 

    __props__ = ('hp_lambda',) 

    def __init__(self, hp_lambda): 
     super(ReverseGradient, self).__init__() 
     self.hp_lambda = hp_lambda 

    def make_node(self, x): 
     return theano.gof.graph.Apply(self, [x], [x.type.make_variable()]) 

    def perform(self, node, inputs, output_storage): 
     xin, = inputs 
     xout, = output_storage 
     xout[0] = xin 

    def grad(self, input, output_gradients): 
     return [-self.hp_lambda * output_gradients[0]] 

kağıt gösterim kullanılarak ve adlandırma kuralları, işte teklif komple genel modelin basit Theano uygulaması var.

import numpy 
import theano 
import theano.tensor as tt 


def g_f(z, theta_f): 
    for w_f, b_f in theta_f: 
     z = tt.tanh(theano.dot(z, w_f) + b_f) 
    return z 


def g_y(z, theta_y): 
    for w_y, b_y in theta_y[:-1]: 
     z = tt.tanh(theano.dot(z, w_y) + b_y) 
    w_y, b_y = theta_y[-1] 
    z = tt.nnet.softmax(theano.dot(z, w_y) + b_y) 
    return z 


def g_d(z, theta_d): 
    for w_d, b_d in theta_d[:-1]: 
     z = tt.tanh(theano.dot(z, w_d) + b_d) 
    w_d, b_d = theta_d[-1] 
    z = tt.nnet.sigmoid(theano.dot(z, w_d) + b_d) 
    return z 


def l_y(z, y): 
    return tt.nnet.categorical_crossentropy(z, y).mean() 


def l_d(z, d): 
    return tt.nnet.binary_crossentropy(z, d).mean() 


def mlp_parameters(input_size, layer_sizes): 
    parameters = [] 
    previous_size = input_size 
    for layer_size in layer_sizes: 
     parameters.append((theano.shared(numpy.random.randn(previous_size, layer_size).astype(theano.config.floatX)), 
          theano.shared(numpy.zeros(layer_size, dtype=theano.config.floatX)))) 
     previous_size = layer_size 
    return parameters, previous_size 


def compile(input_size, f_layer_sizes, y_layer_sizes, d_layer_sizes, hp_lambda, hp_mu): 
    r = ReverseGradient(hp_lambda) 

    theta_f, f_size = mlp_parameters(input_size, f_layer_sizes) 
    theta_y, _ = mlp_parameters(f_size, y_layer_sizes) 
    theta_d, _ = mlp_parameters(f_size, d_layer_sizes) 

    xs = tt.matrix('xs') 
    xs.tag.test_value = numpy.random.randn(9, input_size).astype(theano.config.floatX) 
    xt = tt.matrix('xt') 
    xt.tag.test_value = numpy.random.randn(10, input_size).astype(theano.config.floatX) 
    ys = tt.ivector('ys') 
    ys.tag.test_value = numpy.random.randint(y_layer_sizes[-1], size=9).astype(numpy.int32) 

    fs = g_f(xs, theta_f) 
    e = l_y(g_y(fs, theta_y), ys) + l_d(g_d(r(fs), theta_d), 0) + l_d(g_d(r(g_f(xt, theta_f)), theta_d), 1) 

    updates = [(p, p - hp_mu * theano.grad(e, p)) for theta in theta_f + theta_y + theta_d for p in theta] 
    train = theano.function([xs, xt, ys], outputs=e, updates=updates) 

    return train 


def main(): 
    theano.config.compute_test_value = 'raise' 
    numpy.random.seed(1) 
    compile(input_size=2, f_layer_sizes=[3, 4], y_layer_sizes=[7, 8], d_layer_sizes=[5, 6], hp_lambda=.5, hp_mu=.01) 


main() 

Bu denenmemiş ama şu bu özel op bir Lazanya katmanı olarak kullanılmasına izin verebilir:

Bu çok havalı
class ReverseGradientLayer(lasagne.layers.Layer): 
    def __init__(self, incoming, hp_lambda, **kwargs): 
     super(ReverseGradientLayer, self).__init__(incoming, **kwargs) 
     self.op = ReverseGradient(hp_lambda) 

    def get_output_for(self, input, **kwargs): 
     return self.op(input) 
+0

, en azından benim makinede derlemek gibi görünüyor. Bunu Lasagne formatına uyarlamayı ve içinden bazı verileri çalıştırmayı dönüştüreceğim. Çok teşekkürler! –

+0

Bunu hiç kimse test etti mi? @BillCheatham, senin için çalıştın mı? – pir