用于在 keras 中召回的自定义宏
Custom macro for recall in keras
我正在尝试为 recall = (recall of class1 + recall of class2)/2
创建自定义宏。我想出了以下代码,但我不确定如何计算 class 0.
的真阳性
def unweightedRecall():
def recall(y_true, y_pred):
# recall of class 1
true_positives1 = K.sum(K.round(K.clip(y_pred * y_true, 0, 1)))
possible_positives1 = K.sum(K.round(K.clip(y_true, 0, 1)))
recall1 = true_positives1 / (possible_positives1 + K.epsilon())
# --- get true positive of class 0 in true_positives0 here ---
# Also, is there a cleaner way to get possible_positives0
possible_positives0 = K.int_shape(y_true)[0] - possible_positives1
recall0 = true_positives0 / (possible_positives0 + K.epsilon())
return (recall0 + recall1)/2
return recall
看来我必须使用 Keras.backend.equal(x, y)
,但我如何创建一个具有形状 K.int_shape(y_true)[0]
和所有值的张量,比如说 x?
编辑 1
根据 Marcin 的评论,我想在 keras 中创建一个基于回调的自定义指标。在 browsing issues in Keras 时,我遇到了以下 f1 指标代码:
class Metrics(keras.callbacks.Callback):
def on_epoch_end(self, batch, logs={}):
predict = np.asarray(self.model.predict(self.validation_data[0]))
targ = self.validation_data[1]
self.f1s=f1(targ, predict)
return
metrics = Metrics()
model.fit(X_train, y_train, epochs=epochs, batch_size=batch_size, validation_data=[X_test,y_test],
verbose=1, callbacks=[metrics])
但是回调是如何返回准确度的?我想实现 unweighted recall = (recall class1 + recall class2)/2
。我可以想到以下代码,但希望能帮助我完成它
from sklearn.metrics import recall_score
class Metrics(keras.callbacks.Callback):
def on_epoch_end(self, batch, logs={}):
predict = np.asarray(self.model.predict(self.validation_data[0]))
targ = self.validation_data[1]
# --- what to store the result in?? ---
self.XXXX=recall_score(targ, predict, average='macro')
# we really dont need to return anything ??
return
metrics = Metrics()
model.fit(X_train, y_train, epochs=epochs, batch_size=batch_size, validation_data=[X_test,y_test],
verbose=1, callbacks=[metrics])
编辑 2:型号:
def createModelHelper(numNeurons=40, optimizer='adam'):
inputLayer = Input(shape=(data.shape[1],))
denseLayer1 = Dense(numNeurons)(inputLayer)
outputLayer = Dense(1, activation='sigmoid')(denseLayer1)
model = Model(input=inputLayer, output=outputLayer)
model.compile(loss=unweightedRecall, optimizer=optimizer)
return model
keras版本(有均值问题)。
你的两个类实际上只有一维输出(0或1)吗?
如果是:
def recall(y_true, y_pred):
# recall of class 1
#do not use "round" here if you're going to use this as a loss function
true_positives = K.sum(K.round(y_pred) * y_true)
possible_positives = K.sum(y_true)
return true_positives / (possible_positives + K.epsilon())
def unweightedRecall(y_true, y_pred):
return (recall(y_true,y_pred) + recall(1-y_true,1-y_pred))/2.
现在,如果你的两个 类 实际上是一个 2 元素输出:
def unweightedRecall(y_true, y_pred):
return (recall(y_true[:,0],y_pred[:,0]) + recall(y_true[:,1],y_pred[:,1]))/2.
回调版本:
对于回调,你可以使用一个LambdaCallback
,你手动打印或存储结果:
myCallBack = LambdaCallback(on_epoch_end=unweightedRecall)
stored_metrics = []
def unweightedRecall(epoch,logs):
predict = model.predict(self.validation_data[0])
targ = self.validation_data[1]
result = (recall(targ,predict) + recall(1-targ,1-predict))/2.
print("recall for epoch " + str(epoch) + ": " + str(result))
stored_metrics.append(result)
其中 recall
是使用 np
而不是 K
的函数。和 epsilon = np.finfo(float).eps
或 epsilon = np.finfo(np.float32).eps)
我正在尝试为 recall = (recall of class1 + recall of class2)/2
创建自定义宏。我想出了以下代码,但我不确定如何计算 class 0.
def unweightedRecall():
def recall(y_true, y_pred):
# recall of class 1
true_positives1 = K.sum(K.round(K.clip(y_pred * y_true, 0, 1)))
possible_positives1 = K.sum(K.round(K.clip(y_true, 0, 1)))
recall1 = true_positives1 / (possible_positives1 + K.epsilon())
# --- get true positive of class 0 in true_positives0 here ---
# Also, is there a cleaner way to get possible_positives0
possible_positives0 = K.int_shape(y_true)[0] - possible_positives1
recall0 = true_positives0 / (possible_positives0 + K.epsilon())
return (recall0 + recall1)/2
return recall
看来我必须使用 Keras.backend.equal(x, y)
,但我如何创建一个具有形状 K.int_shape(y_true)[0]
和所有值的张量,比如说 x?
编辑 1
根据 Marcin 的评论,我想在 keras 中创建一个基于回调的自定义指标。在 browsing issues in Keras 时,我遇到了以下 f1 指标代码:
class Metrics(keras.callbacks.Callback):
def on_epoch_end(self, batch, logs={}):
predict = np.asarray(self.model.predict(self.validation_data[0]))
targ = self.validation_data[1]
self.f1s=f1(targ, predict)
return
metrics = Metrics()
model.fit(X_train, y_train, epochs=epochs, batch_size=batch_size, validation_data=[X_test,y_test],
verbose=1, callbacks=[metrics])
但是回调是如何返回准确度的?我想实现 unweighted recall = (recall class1 + recall class2)/2
。我可以想到以下代码,但希望能帮助我完成它
from sklearn.metrics import recall_score
class Metrics(keras.callbacks.Callback):
def on_epoch_end(self, batch, logs={}):
predict = np.asarray(self.model.predict(self.validation_data[0]))
targ = self.validation_data[1]
# --- what to store the result in?? ---
self.XXXX=recall_score(targ, predict, average='macro')
# we really dont need to return anything ??
return
metrics = Metrics()
model.fit(X_train, y_train, epochs=epochs, batch_size=batch_size, validation_data=[X_test,y_test],
verbose=1, callbacks=[metrics])
编辑 2:型号:
def createModelHelper(numNeurons=40, optimizer='adam'):
inputLayer = Input(shape=(data.shape[1],))
denseLayer1 = Dense(numNeurons)(inputLayer)
outputLayer = Dense(1, activation='sigmoid')(denseLayer1)
model = Model(input=inputLayer, output=outputLayer)
model.compile(loss=unweightedRecall, optimizer=optimizer)
return model
keras版本(有均值问题)。
你的两个类实际上只有一维输出(0或1)吗?
如果是:
def recall(y_true, y_pred):
# recall of class 1
#do not use "round" here if you're going to use this as a loss function
true_positives = K.sum(K.round(y_pred) * y_true)
possible_positives = K.sum(y_true)
return true_positives / (possible_positives + K.epsilon())
def unweightedRecall(y_true, y_pred):
return (recall(y_true,y_pred) + recall(1-y_true,1-y_pred))/2.
现在,如果你的两个 类 实际上是一个 2 元素输出:
def unweightedRecall(y_true, y_pred):
return (recall(y_true[:,0],y_pred[:,0]) + recall(y_true[:,1],y_pred[:,1]))/2.
回调版本:
对于回调,你可以使用一个LambdaCallback
,你手动打印或存储结果:
myCallBack = LambdaCallback(on_epoch_end=unweightedRecall)
stored_metrics = []
def unweightedRecall(epoch,logs):
predict = model.predict(self.validation_data[0])
targ = self.validation_data[1]
result = (recall(targ,predict) + recall(1-targ,1-predict))/2.
print("recall for epoch " + str(epoch) + ": " + str(result))
stored_metrics.append(result)
其中 recall
是使用 np
而不是 K
的函数。和 epsilon = np.finfo(float).eps
或 epsilon = np.finfo(np.float32).eps)