2017-09-28 3 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) 

및 메트릭 :

더 speciffically 내 손실이 원하는

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 행은 동일하고 이후입니다 두 가지 기능이 변경됩니다. Callback을 사용하여 mean_acc을 인쇄 할 수 있습니까?

+0

사용자 정의 기능이 y_pred에 종속되지 않습니까? –

+0

나는이 두 함수에서'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에서 작동합니다. 네가 테아 노를 사용하고있는 것 같지, 그렇지?

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 = [embedded _..._ positive, z, embed .._ negatives]'로 변경하면'y_pred'는'embedded _.._ positive'가됩니다. 'y_pred'가 3 텐서 ('z','embed..psotive','embed..negatives')가 될 수 없습니까? –

관련 문제