2017-09-28 13 views
0

それは入力が(y_true, y_pred)である両方のケースのための前提としていkerasモデルのカスタム損失およびメトリック関数を作成:Keras:メトリックと異なる入力して損失が

def custom_loss(y_true, y_pred): 
    . 
    return loss 

def custom_metric(y_true, y_pred): 
    . 
    return metric 

そしてy_predの入力が出力されますModel。例:

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

この場合、上記の損失とメトリックの両方について、y_predは損失になります。

costum_lossに異なる入力があり、costum_metricが異なる場合はどうなりますか?それを行う方法はありますか?

編集

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) 

とメトリック:

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) 

だから、最初の4行は同じとした後、あるspeciffically私は私の損失になりたい

詳細2つの機能が変わります。 Callbackを使用してmean_accを印刷することは可能でしょうか?

+0

カスタム関数はy_predに依存しませんか? –

+0

これらの2つの関数で 'y_pred'を異なるものにします。この場合、損失出力は実際には予測値ではありません。あなたはすでにコメントしているこの質問https://stackoverflow.com/questions/46447882/weights-of-cnn-model-go-to-really-small-values-and-after-nanで損失を確認することができます。 –

+0

あなたは 'custom_loss'と' custom_metrics'への入力として何をしたいですか? –

答えて

1

モデルの一部としてlossを使用する必要はありません。モデル出力を独自の出力にして後で損失を適用することができます。ここで

は、作業コード(モデルにcommomパーツを追加することで、指標と損失の両方で動作を繰り返すことを避けるために最適化することができる)

である私は、私がそれを作った、あなたの形状のいくつかの問題がありました任意の形状。元の行にはコメントがついています。

このコードは、Tensorflow 1.3.0のKeras 2.0.8で動作します。私はあなたがTheanoを使用していると思われます。

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

答えに感謝します!私は 'keras:2.0.4'と' tf:1.1.0'を使っています。 'y_pred'として入るのは' outputs'の最初の値です。あなたのコードでは 'z'です。ですから、もし順序を 'outputs = [埋め込み_..._陽性、z、埋め込み.._陰性] 'に変更すると、' y_pred'は '埋め込み_.._陽性'になります。 'y_pred'を3テンソル(' z'、 'embed..psotive'、' embed..negatives')にするべきではありませんか? –

関連する問題