Использование перекрестной проверки для выбора оптимального порога: двоичная классификация в Керасе - PullRequest
2 голосов
/ 22 апреля 2019

У меня есть модель Keras, которая принимает преобразованный вектор x в качестве входных данных и выводит вероятности того, что каждое входное значение равно 1.

Я бы хотел взять прогнозы из этой модели и найти оптимальный порог. То есть, возможно, значение отсечения для «это значение равно 1» должно быть 0,23, или, возможно, оно должно быть 0,78, или что-то еще. Я знаю, что перекрестная проверка - хороший инструмент для этого.

Мой вопрос: как это отработать на тренировке? Например, скажем, у меня есть следующая модель (взято из здесь ):

def create_baseline():
    # create model
    model = Sequential()
    model.add(Dense(60, input_dim=60, kernel_initializer='normal', activation='relu'))
    model.add(Dense(1, kernel_initializer='normal', activation='sigmoid'))
    # Compile model
    model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
    return model

Я обучаю модель и получаю некоторые выходные вероятности:

model.fit(train_x, train_y)
predictions = model.predict(train_y)

Теперь я хочу узнать пороговое значение для каждой записи в predictions, которое, например, дало бы наилучшую точность. Как я могу узнать этот параметр вместо того, чтобы просто выбрать его после завершения обучения?

РЕДАКТИРОВАТЬ: Например, скажем, у меня есть это:

def fake_model(self):

    #Model that returns probability that each of 10 values is 1
    a_input = Input(shape=(2, 10), name='a_input')
    dense_1 = Dense(5)(a_input)
    outputs = Dense(10, activation='sigmoid')(dense_1)

    def hamming_loss(y_true, y_pred):
        return tf.to_float(tf.reduce_sum(abs(y_true - y_pred))) /tf.to_float(tf.size(y_pred))

    fakemodel = Model(a_input, outputs)

    #Use the outputs of the model; find the threshold value that minimizes the Hamming loss
    #Record the final confusion matrix.

Как я могу тренировать такую ​​модель, как эта?

Ответы [ 4 ]

0 голосов
/ 30 апреля 2019

Для многих популярных метрик качества классификации (точность, точность, отзыв и т. Д.) Вы просто не можете узнать оптимальный порог при обучении вашей нейронной сети.

Это потому, что эти метрики не дифференцируемы - поэтому обновления градиента не смогут правильно установить порог (или любой другой параметр). Таким образом, вы вынуждены оптимизировать приятные сглаженные потери (например, отрицательное логарифмическое правдоподобие) во время обучения большинства параметров, а затем настроить порог с помощью поиска в сетке.

Конечно, вы можете придумать сглаженную версию вашей метрики и оптимизировать ее (и иногда люди делают это). Но в большинстве случаев можно оптимизировать логарифмическую вероятность, получить хороший вероятностный классификатор и настроить пороги поверх него. Например. если вы хотите оптимизировать точность, то сначала вы должны как можно точнее оценить вероятности классов (чтобы приблизиться к идеальному байесовскому классификатору), а затем просто выбрать их argmax.

0 голосов
/ 25 апреля 2019

Первая идея, которая у меня есть, - это грубая сила. Вы вычисляете в тестовом наборе метрику отдельно для каждого из ваших входных данных и соответствующих прогнозируемых выходных данных.
Затем для каждого из них итерируйте значения для порога между 0 и 1, пока метрика не будет оптимизирована для данной пары ввода / прогнозирования.

0 голосов
/ 28 апреля 2019

Если кривая ROC - это не то, что вы ищете, вы можете создать собственный слой Keras, который принимает выходные данные вашей исходной модели и пытается выучить оптимальный порог, учитывая истинные выходные данные и прогнозируемые вероятности.

Этот уровень вычитает порог из предсказанной вероятности, умножает на относительно большую константу (в данном случае 100) и затем применяет сигмовидную функцию. Вот график, который показывает функцию на трех разных пороговых значениях (.3, .5, .7).

enter image description here

Ниже приведен код для определения этого слоя и создания модели, состоящей исключительно из него, после подгонки вашей исходной модели, передачи ее выходных вероятностей в эту модель и начала обучения для достижения оптимального порога.

class ThresholdLayer(keras.layers.Layer):
    def __init__(self, **kwargs):
        super(ThresholdLayer, self).__init__(**kwargs)

    def build(self, input_shape):
        self.kernel = self.add_weight(name="threshold", shape=(1,), initializer="uniform",
                                      trainable=True)
        super(ThresholdLayer, self).build(input_shape)

    def call(self, x):
        return keras.backend.sigmoid(100*(x-self.kernel))

    def compute_output_shape(self, input_shape):
        return input_shape

out = ThresholdLayer()(input_layer)
threshold_model = keras.Model(inputs=input_layer, outputs=out)
threshold_model.compile(optimizer="sgd", loss="mse")
0 голосов
/ 24 апреля 2019

Во-первых, вот прямой ответ на ваш вопрос.Вы думаете о кривой ROC .Например, если предположить, что некоторые данные X_test и y_test:

from matplotlib import pyplot as plt
from sklearn.metrics import roc_curve
from sklearn.metrics import auc

y_pred = model.predict(X_test).ravel()

fpr, tpr, thresholds = roc_curve(y_test, y_pred)

my_auc = auc(fpr, tpr)

plt.figure(1)
plt.plot([0, 1], [0, 1], 'k--')
plt.plot(fpr, tpr, label='Model_name (area = {:.3f})'.format(my_auc))
plt.xlabel('False positive rate')
plt.ylabel('True positive rate')
plt.title('ROC curve')
plt.legend(loc='best')
plt.show()

plt.figure(2)
plt.xlim(0, 0.2)
plt.ylim(0.8, 1)
plt.plot([0, 1], [0, 1], 'k--')
plt.plot(fpr, tpr, label='Model_name (area = {:.3f})'.format(my_auc))
plt.xlabel('False positive rate')
plt.ylabel('True positive rate')
plt.title('ROC curve close-up')
plt.legend(loc='best')
plt.show()

Во-вторых, что касается моего комментария, вот пример одной попытки. Это можно сделать в Керасе, илиTF или где угодно, хотя он делает это с XGBoost.

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...