2017-09-28 2 views
0

Wenn individuellen Verlust und metrische Funktion in einem Keras Modell für beiden Fälle nehmen schaffen, die Eingänge von (y_true, y_pred):Keras: Metric und Verlust mit unterschiedlichem Eingang

def custom_loss(y_true, y_pred): 
    . 
    return loss 

def custom_metric(y_true, y_pred): 
    . 
    return metric 

und der Eingang der y_pred ist der Ausgang der Model. Beispiel:

model = Model(inputs = [input1,..inputN], outputs=loss) 
model.compile(loss=costum_loss, metrics=costum_metric) 

In diesem Fall oben für sowohl Verlust als auch Metrik ist y_pred der Verlust.

Was ist, wenn ich andere Eingabe in costum_loss und andere in der costum_metric wollen. Gibt es einen Weg, es zu tun?

bearbeiten:

Mehr speciffically möchte ich meinen Verlust sein:

def warp_loss(X): 
    z, positive_entity, negatives_entities = X 
    positiveSim = Lambda(lambda x: similarity(x[0], x[1]), output_shape=(1,), name="positive_sim")([z, positive_entity]) 
    z_reshaped = Reshape((1, z.shape[1].value))(z) 
    negativeSim = Lambda(lambda x: similarity(x[0], x[1]), output_shape=(negatives_titles.shape[1].value, 1,), name="negative_sim")([z_reshaped, negatives_entities]) 
    loss = Lambda(lambda x: max_margin_loss(x[0], x[1]), output_shape=(1,), name="max_margin")([positiveSim, negativeSim]) 
    return loss 

def mean_loss(y_true, y_pred): 
    return K.mean(y_pred - 0 * y_true) 

und die Metrik:

def metric(X): 
    z, positive_entity, negatives_entities = X 
    positiveSim = Lambda(lambda x: similarity(x[0], x[1]), output_shape=(1,), name="positive_sim")([z, positive_entity]) 
    z_reshaped = Reshape((1, z.shape[1].value))(z) 
    negativeSim = Lambda(lambda x: similarity(x[0], x[1]), output_shape=(negatives_titles.shape[1].value, 1,), name="negative_sim")([z_reshaped, negatives_entities]) 
    position = K.sum(K.cast(K.greater(positiveSim, negativeSim), dtype="int32"), axis=1, keepdims=True) 
    accuracy = Lambda(lambda x: x/_NUMBER_OF_NEGATIVE_EXAMPLES)(position) 
    return accuracy 


def mean_acc(y_true, y_pred): 
    return K.mean(y_pred - 0 * y_true) 

So sind die ersten 4 Zeilen gleich sind und nach dem zwei Funktionen ändern sich. Könnte es möglich sein, einen Callback zum Drucken mean_acc zu verwenden?

+0

Funktioniert Ihre benutzerdefinierte Funktion nicht von y_pred? –

+0

Ich möchte 'y_pred' in diesen 2 Funktionen unterschiedlich sein. Die Verlustausgabe ist in diesem Fall keine tatsächliche Vorhersage. Sie können den Verlust in dieser Frage https://stackoverflow.com/questions/46447882/weights-of-cnn-model-go-to-really-small-values-and-after-nan überprüfen, dass Sie bereits kommentiert haben. –

+0

Was möchten Sie als Eingaben für 'custom_loss' und' custom_metrics' verwenden ?. –

Antwort

1

Sie benötigen nicht die loss, um Teil Ihres Modells zu sein, können Sie Ihre Modellausgabe seine eigenen Ausgaben machen und später wenden Sie den Verlust an.

hier ein Arbeitscode ist (es optimiert werden Operationen in beiden Metriken und Verlust Wiederholung zu vermeiden, indem die commom Teil zum Modell hinzugefügt)

ich mit Ihren Formen einige Probleme hatte, dann habe ich es mit beliebige Formen. Ihre ursprünglichen Zeilen sind kommentiert.

Dieser Code funktioniert für Keras 2.0.8, mit Tensorflow 1.3.0. Ich vermute, du benutzt Theano, richtig?

from keras.layers import * 
from keras.models import * 
import keras.backend as K 


def get_divisor(x): 
    return K.sqrt(K.sum(K.square(x), axis=-1)) 


def similarity(a, b): 
    numerator = K.sum(a * b, axis=-1) 
    denominator = get_divisor(a) * get_divisor(b) 
    denominator = K.maximum(denominator, K.epsilon()) 
    return numerator/denominator 


def max_margin_loss(positive, negative): 
    #loss_matrix = K.maximum(0.0, 1.0 + negative - Reshape((1,))(positive)) 
    loss_matrix = K.maximum(0.0, 1.0 + negative - positive) 
    loss = K.sum(loss_matrix, axis=-1, keepdims=True) 
    return loss 


def warp_loss(X): 
    z = X[0] 
    positive_entity = X[1] 
    negative_entities = X[2] 
    positiveSim = similarity(z, positive_entity) 
    #z_reshaped = Reshape((1, z.shape[1].value))(z) 
    z_reshaped = K.expand_dims(z,axis=1) 
    negativeSim = similarity(z_reshaped, negative_entities) 
    #negativeSim = Reshape((negatives_titles.shape[1].value, 1,)) 
    negativeSim = K.expand_dims(negativeSim,axis=-1) 
    loss = max_margin_loss(positiveSim, negativeSim) 
    return loss 


def warp_metricsX(X): 
    z = X[0] 
    positive_entity = X[1] 
    negative_entities = X[2] 
    positiveSim = similarity(z, positive_entity) 
    #z_reshaped = Reshape((1, z.shape[1].value))(z) 
    z_reshaped = K.expand_dims(z,axis=1) 
    negativeSim = similarity(z_reshaped, negative_entities) 
    #Reshape((negatives_titles.shape[1].value, 1,)) 
    negativeSim = K.expand_dims(negativeSim,axis=-1) 

    position = K.sum(K.cast(K.greater(positiveSim, negativeSim), dtype="int32"), axis=1, keepdims=True) 
    #accuracy = position/_NUMBER_OF_NEGATIVE_EXAMPLES 
    accuracy = position/30 
    return accuracy 


def mean_loss(yTrue,yPred): 
    return K.mean(warp_loss(yPred)) 

def warp_metrics(yTrue,yPred): 
    return warp_metricsX(yPred) 


def build_nn_model(): 
    #wl, tl = load_vector_lookups() 
    #embedded_layer_1 = initialize_embedding_matrix(wl) 
    #embedded_layer_2 = initialize_embedding_matrix(tl) 
    embedded_layer_1 = Embedding(200,25) 
    embedded_layer_2 = Embedding(200,25) 

    #sequence_input_1 = Input(shape=(_NUMBER_OF_LENGTH,), dtype='int32',name="text") 
    sequence_input_1 = Input(shape=(30,), dtype='int32',name="text") 
    sequence_input_positive = Input(shape=(1,), dtype='int32', name="positive") 
    sequence_input_negatives = Input(shape=(10,), dtype='int32', name="negatives") 

    embedded_sequences_1 = embedded_layer_1(sequence_input_1) 
    #embedded_sequences_positive = Reshape((tl.shape[1],))(embedded_layer_2(sequence_input_positive)) 
    embedded_sequences_positive = Reshape((25,))(embedded_layer_2(sequence_input_positive)) 
    embedded_sequences_negatives = embedded_layer_2(sequence_input_negatives) 

    conv_step1 = Convolution1D(
     filters=1000, 
     kernel_size=5, 
     activation="tanh", 
     name="conv_layer_mp", 
     padding="valid")(embedded_sequences_1) 

    conv_step2 = GlobalMaxPooling1D(name="max_pool_mp")(conv_step1) 
    conv_step3 = Activation("tanh")(conv_step2) 
    conv_step4 = Dropout(0.2, name="dropout_mp")(conv_step3) 
    #z = Dense(wl.shape[1], name="predicted_vec")(conv_step4) # activation="linear" 
    z = Dense(25, name="predicted_vec")(conv_step4) # activation="linear" 

    model = Model(
      inputs=[sequence_input_1, sequence_input_positive, sequence_input_negatives], 
      outputs = [z,embedded_sequences_positive,embedded_sequences_negatives] 
     ) 


    model.compile(loss=mean_loss, optimizer='adam',metrics=[warp_metrics]) 
    return model 
+0

danke für die Antwort! Ich benutze 'keras: 2.0.4' und' tf: 1.1.0' für jetzt. Es scheint, dass das, was als 'y_pred' eintritt, der erste Wert von 'outputs' ist. In Ihrem Code ist 'z'. Also, wenn ich die Reihenfolge zu "outputs = [eingebettet _... positiv, z, einzubetten .._ negative]' dann "y_pred" ist "eingebettet _.._ positiv". sollte es nicht "y_pred" sein, um 3 Tensoren zu sein ('z',' embed..psotive', 'embed..negatives')? –

Verwandte Themen