在keras模型中创建自定义损失和指标函数时,它假设两种情况都是(y_true, y_pred)
输入:
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行是相同的,并且在两个函数改变之后。是否可以使用Callback
来打印mean_acc
?
答案 0 :(得分:1)
您不需要loss
成为模型的一部分,您可以使模型输出自己的输出,然后应用损失。
这是一个工作代码(可以通过将commom部分添加到模型中来优化它以避免在度量和损失中重复操作)
我的形状有些问题,然后我用任意形状做了。您的原始行已注释。
此代码适用于Keras 2.0.8,Tensorflow 1.3.0。我怀疑你正在使用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