基于精度或召回而不是损失,keras中是否有优化器?

问题描述 投票:3回答:2

我正在开发一个只有两个类的分段神经网络,0和1(0是背景,1是我想在图像上找到的对象)。在每个图像上,大约有80%的1和20%的0.正如您所看到的,数据集是不平衡的,它会导致结果错误。我的准确率是85%而我的损失很低,但这只是因为我的模型擅长找到背景!

我想将优化器基于另一个度量,如精度或召回,在这种情况下更有用。

有谁知道如何实现这个?

machine-learning keras metrics
2个回答
5
投票

由于我们的评论不够明确,让我给你一些代码来跟踪你的需求。您不使用精度或召回进行优化。您只需将它们作为有效分数进行跟踪即可获得最佳权重。不要混合损失,优化程序,指标等。它们并不意味着同样的事情。

def precision(y_true, y_pred, threshold_shift=0.5-THRESHOLD):
    beta = 1

    # just in case of hipster activation at the final layer
    y_pred = K.clip(y_pred, 0, 1)

    # shifting the prediction threshold from .5 if needed
    y_pred_bin = K.round(y_pred + threshold_shift)

    tp = K.sum(K.round(y_true * y_pred_bin)) + K.epsilon()
    fp = K.sum(K.round(K.clip(y_pred_bin - y_true, 0, 1)))
    fn = K.sum(K.round(K.clip(y_true - y_pred, 0, 1)))

    precision = tp / (tp + fp)
    return precision


def recall(y_true, y_pred, threshold_shift=0.5-THRESHOLD):
    beta = 1

    # just in case of hipster activation at the final layer
    y_pred = K.clip(y_pred, 0, 1)

    # shifting the prediction threshold from .5 if needed
    y_pred_bin = K.round(y_pred + threshold_shift)

    tp = K.sum(K.round(y_true * y_pred_bin)) + K.epsilon()
    fp = K.sum(K.round(K.clip(y_pred_bin - y_true, 0, 1)))
    fn = K.sum(K.round(K.clip(y_true - y_pred_bin, 0, 1)))

    recall = tp / (tp + fn)
    return recall


def fbeta(y_true, y_pred, threshold_shift=0.5-THRESHOLD):
    beta = 2

    # just in case of hipster activation at the final layer
    y_pred = K.clip(y_pred, 0, 1)

    # shifting the prediction threshold from .5 if needed
    y_pred_bin = K.round(y_pred + threshold_shift)

    tp = K.sum(K.round(y_true * y_pred_bin)) + K.epsilon()
    fp = K.sum(K.round(K.clip(y_pred_bin - y_true, 0, 1)))
    fn = K.sum(K.round(K.clip(y_true - y_pred, 0, 1)))

    precision = tp / (tp + fp)
    recall = tp / (tp + fn)

    beta_squared = beta ** 2
    return (beta_squared + 1) * (precision * recall) / (beta_squared * precision + recall) 


def model_fit(X,y,X_test,y_test):
    class_weight={
    1: 1/(np.sum(y) / len(y)),
    0:1}
    np.random.seed(47)
    model = Sequential()
    model.add(Dense(1000, input_shape=(X.shape[1],)))
    model.add(Activation('relu'))
    model.add(Dropout(0.35))
    model.add(Dense(500))
    model.add(Activation('relu'))
    model.add(Dropout(0.35))
    model.add(Dense(250))
    model.add(Activation('relu'))
    model.add(Dropout(0.35))
    model.add(Dense(1))
    model.add(Activation('sigmoid'))

    model.compile(loss='binary_crossentropy', optimizer='adamax',metrics=[fbeta,precision,recall])
    model.fit(X, y,validation_data=(X_test,y_test), epochs=200, batch_size=50, verbose=2,class_weight = class_weight)
    return model

2
投票

不。要进行“梯度下降”,您需要计算渐变。为此,功能需要以某种方式平滑。精度/召回或精度不是平滑函数,它只有渐变无限的锐边和渐变为零的平坦位置。因此,你不能使用任何一种数值方法来找到这样一个函数的最小值 - 你必须使用某种组合优化,这将是NP难的。

© www.soinside.com 2019 - 2024. All rights reserved.