2017-07-14 2 views
0

Dies ist Teil meines aktuellen Python-Code für NN Training in Python mit CNTK ModulErstellen von benutzerdefinierter Fehlerfunktion in CNTK

batch_axis = C.Axis.default_batch_axis() 
input_seq_axis = C.Axis.default_dynamic_axis() 

input_dynamic_axes = [batch_axis, input_seq_axis] 
input_dynamic_axes2 = [batch_axis, input_seq_axis] 

input = C.input_variable(n_ins, dynamic_axes=input_dynamic_axes, dtype=numpy.float32) 
output = C.input_variable(n_outs, dynamic_axes=input_dynamic_axes2, dtype=numpy.float32) 

dnn_model = cntk_model.create_model(input, hidden_layer_type, hidden_layer_size, n_outs) 

loss = C.squared_error(dnn_model, output) 
error = C.squared_error(dnn_model, output) 

lr_schedule = C.learning_rate_schedule(current_finetune_lr, C.UnitType.minibatch) 
      momentum_schedule = C.momentum_schedule(current_momentum) 

learner = C.adam(dnn_model.parameters, lr_schedule, momentum_schedule, unit_gain = False, l1_regularization_weight=l1_reg, l2_regularization_weight= l2_reg)  

trainer = C.Trainer(dnn_model, (loss, error), [learner]) 

Und hier ist der Code für die Erstellung von NN-Modell

def create_model(features, hidden_layer_type, hidden_layer_size, n_out): 
    logger.debug('Creating cntk model') 
    assert len(hidden_layer_size) == len(hidden_layer_type) 

    n_layers = len(hidden_layer_size) 

    my_layers = list() 
    for i in xrange(n_layers): 
     if(hidden_layer_type[i] == 'TANH'): 
      my_layers.append(C.layers.Dense(hidden_layer_size[i], activation=C.tanh, init=C.layers.glorot_uniform())) 
     elif (hidden_layer_type[i] == 'LSTM'): 
      my_layers.append(C.layers.Recurrence(C.layers.LSTM(hidden_layer_size[i]))) 
     else: 
      raise Exception('Unknown hidden layer type') 

    my_layers.append(C.layers.Dense(n_out, activation=None)) 

    my_model = C.layers.Sequential([my_layers]) 
    my_model = my_model(features) 

    return my_model 

Nun, ich Möchte man eine Backpropagation ändern, so wird beim Berechnen des Fehlers keine direkte Netzwerkausgabe verwendet, sondern die Ausgabe nach einiger zusätzlicher Berechnung. Ich habe versucht, so etwas wie dieses

def create_error_function(self, prediction, target): 

    prediction_denorm = C.element_times(prediction, self.std_vector) 
    prediction_denorm = C.plus(prediction_denorm, self.mean_vector) 
    prediction_denorm_rounded = C.round(C.element_times(prediction_denorm[0:5], C.round(prediction_denorm[5]))) 
    prediction_denorm_rounded = C.element_divide(prediction_denorm_rounded, C.round(prediction_denorm[5])) 

    prediction_norm = C.minus(prediction_denorm_rounded, self.mean_vector[0:5]) 
    prediction_norm = C.element_divide(prediction_norm, self.std_vector[0:5]) 

    first = C.squared_error(prediction_norm, target[0:5]) 
    second = C.minus(C.round(prediction_denorm[5]), self.mean_vector[5]) 
    second = C.element_divide(second, self.std_vector[5]) 

    return C.plus(first, C.squared_error(second, target[5])) 

zu definieren, und es verwenden, anstatt Standard squared_error. Und der Teil für NN Ausbildung

dnn_model = cntk_model.create_model(input, hidden_layer_type, hidden_layer_size, n_outs) 
error_function = cntk_model.ErrorFunction(cmp_mean_vector, cmp_std_vector) 
loss = error_function.create_error_function(dnn_model, output) 
error = error_function.create_error_function(dnn_model, output) 
lr_schedule = C.learning_rate_schedule(current_finetune_lr, C.UnitType.minibatch) 
momentum_schedule = C.momentum_schedule(current_momentum) 

learner = C.adam(dnn_model.parameters, lr_schedule, momentum_schedule, unit_gain = False, l1_regularization_weight=l1_reg, 
           l2_regularization_weight= l2_reg)  

trainer = C.Trainer(dnn_model, (loss, error), [learner]) 
trainer.train_minibatch({input: temp_train_x, output: temp_train_y}) 

Aber nach zwei Epochen beginne ich immer die gleiche durchschnittliche Verlust gettting, wie mein Netzwerk nicht

Antwort

0

Lernen ist jedes Mal wie Backprop Werke ändern möchten, müssen Sie Verwenden Sie stop_gradient. Dies ist die einzige Funktion, deren Gradient sich von dem Gradient der Operation des Vorwärtsdurchlaufs unterscheidet. Im Vorwärtsdurchlauf wirkt stop_gradient als Identität. Im Rückwärtsdurchlauf blockiert es die Ausbreitung des Gradienten.

eine Operation f(x) auf einige x im Vorwärtsdurchlauf zu tun, und so tun, als ob es nie im Rückwärtsdurchlauf passiert man so etwas tun müssen: C.stop_gradient(f(x) - x) + x. In Ihrem Fall, dass

norm_features = C.stop_gradient(features/normalization - features) + features

+0

ich meine Frage aktualisiert wäre. Ich habe es geschafft, ein Beispiel für eine neue Verlustfunktion zu machen, aber es sieht so aus, als ob etwas falsch in meiner Implementierung ist, da ich in allen Epochen denselben Durchschnitt erreiche. Ich bin mir auch nicht sicher, wo die von Ihnen vorgeschlagene Änderung hinzugefügt werden sollte – sinisha

Verwandte Themen