#machine-learning #keras
#машинное обучение #keras
Вопрос:
У меня есть модель 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.
Как я могу обучить такую модель от начала до конца?
Комментарии:
1. Конечно, похоже, что вы хотите реализовать некоторое повышение. Я имею в виду, вы могли бы просто поискать идеальное предельное значение, как вы сказали … или вы могли бы перейти
actual - predicted
к другой модели, пытаясь ее минимизировать. В любом случае вы достигаете аналогичного результата, и с помощью этого метода вы открываете возможность повышения точности. Просто мысль!2. Спасибо @TheLoneDeranger. Есть ли способ обучить всю эту систему от начала до конца?
Ответ №1:
Если кривая ROC — это не то, что вы ищете, вы можете создать пользовательский слой Keras, который принимает выходные данные вашей исходной модели и пытается определить оптимальный порог с учетом истинных выходных данных и прогнозируемых вероятностей.
Этот уровень вычитает пороговое значение из прогнозируемой вероятности, умножает на относительно большую константу (в данном случае 100), а затем применяет сигмоидальную функцию. Вот график, который показывает функцию при трех разных порогах (.3, .5, .7).
Ниже приведен код для определения этого уровня и создания модели, состоящей исключительно из него. После подгонки вашей исходной модели передайте ее выходные вероятности этой модели и начните обучение для достижения оптимального порога.
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")
Комментарии:
1. Привет, Ахмед, спасибо за ваш ответ. Почему необходимо вычитать пороговое значение и умножать на большое число?
2. Это приближение к функции определения порога, допустим, у нас есть вероятность .6 в качестве входных данных и порог .5, вычитая порог, вы получаете положительный результат (.1), умножение его на большую константу, а затем применение softmax просто приведет к 1. Если вероятность ввода была меньше порогового значения, результат будет отрицательным, и умножение его на большую константу с последующим применением softmax приведет к 0. Проверьте графики, которые я прикрепил к моему ответу, для лучшей визуализации функции.
Ответ №2:
Во-первых, вот прямой ответ на ваш вопрос. Вы думаете о кривой 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()
Во-вторых, что касается моего комментария, вот пример одной попытки.Это можно сделать в Keras, или TF, или где угодно, хотя он делает это с помощью XGBoost.
Надеюсь, это поможет!
Комментарии:
1. Я думаю, что я ищу что-то большее в духе keras.io/getting-started/functional-api-guide/#more-examples (Модель общего видения), где я могу использовать одну потерю для обучения первой модели и другую потерю (основанную на точности) для обучения следующей. Возможно ли это?
Ответ №3:
Первая идея, которая у меня есть, — это грубая сила. Вы вычисляете в тестовом наборе метрику отдельно для каждого вашего ввода и соответствующего ему прогнозируемого результата.
Затем для каждого из них перебирайте значения для пороговых значений между 0 и 1, пока метрика не будет оптимизирована для данной пары ввода / прогнозирования.
Ответ №4:
Для многих популярных показателей качества классификации (точность, точность, отзыв и т. Д.) Вы просто не можете узнать оптимальный порог во время обучения вашей нейронной сети.
Это связано с тем, что эти показатели не поддаются дифференцированию — поэтому при обновлении градиента не удастся правильно установить пороговое значение (или любой другой параметр). Поэтому вы вынуждены оптимизировать плавную потерю (например, вероятность отрицательного логарифма) во время обучения большинства параметров, а затем настраивать порог с помощью поиска по сетке.
Конечно, вы можете придумать сглаженную версию своей метрики и оптимизировать ее (и иногда люди делают это). Но в большинстве случаев можно оптимизировать логарифмическую вероятность, получить хороший вероятностный классификатор и настроить пороговые значения поверх него. Например, если вы хотите оптимизировать точность, вам следует сначала как можно точнее оценить вероятности классов (чтобы приблизиться к идеальному байесовскому классификатору), а затем просто выбрать их argmax.
Комментарии:
1. Хм. Я согласен в принципе, но мне интересно, можете ли вы сделать приятный маленький трюк, подобный используемому с автокодерами — если у вас есть дискретный скрытый слой, вы можете использовать непрерывное приближение (которое достаточно близко к исходному дискретному распределению) и дифференцировать через это.