Как вычислить Receiving Operating Characteristic (ROC) и AUC в кератах?
У меня есть бинарная классификационная модель с несколькими выходами (200), которую я написал в керасе.
В этой модели я хочу добавить дополнительные метрики, такие как ROC и AUC, но, насколько мне известно, у keras нет встроенных метрических функций ROC и AUC.
Я пытался импортировать функции ROC, AUC из scikit-learn
from sklearn.metrics import roc_curve, auc
from keras.models import Sequential
from keras.layers import Dense
.
.
.
model.add(Dense(200, activation='relu'))
model.add(Dense(300, activation='relu'))
model.add(Dense(400, activation='relu'))
model.add(Dense(300, activation='relu'))
model.add(Dense(200,init='normal', activation='softmax')) #outputlayer
model.compile(loss='categorical_crossentropy', optimizer='adam',metrics=['accuracy','roc_curve','auc'])
но это дает эту ошибку:
Исключение: неверная метрика: roc_curve
Как добавить ROC, AUC в керас?
6 ответов
Из-за того, что вы не можете рассчитать ROC&AUC по мини-пакетам, вы можете рассчитать его только в конце одной эпохи. Есть решение от jamartinh, я для удобства прошиваю приведенные ниже коды:
from sklearn.metrics import roc_auc_score
from keras.callbacks import Callback
class roc_callback(Callback):
def __init__(self,training_data,validation_data):
self.x = training_data[0]
self.y = training_data[1]
self.x_val = validation_data[0]
self.y_val = validation_data[1]
def on_train_begin(self, logs={}):
return
def on_train_end(self, logs={}):
return
def on_epoch_begin(self, epoch, logs={}):
return
def on_epoch_end(self, epoch, logs={}):
y_pred = self.model.predict(self.x)
roc = roc_auc_score(self.y, y_pred)
y_pred_val = self.model.predict(self.x_val)
roc_val = roc_auc_score(self.y_val, y_pred_val)
print('\rroc-auc: %s - roc-auc_val: %s' % (str(round(roc,4)),str(round(roc_val,4))),end=100*' '+'\n')
return
def on_batch_begin(self, batch, logs={}):
return
def on_batch_end(self, batch, logs={}):
return
model.fit(X_train, y_train, validation_data=(X_test, y_test), callbacks=[roc_callback(training_data=(X_train, y_train),validation_data=(X_test, y_test))])
Более взломанный способ использования tf.contrib.metrics.streaming_auc
:
import numpy as np
import tensorflow as tf
from sklearn.metrics import roc_auc_score
from sklearn.datasets import make_classification
from keras.models import Sequential
from keras.layers import Dense
from keras.utils import np_utils
from keras.callbacks import Callback, EarlyStopping
# define roc_callback, inspired by https://github.com/keras-team/keras/issues/6050#issuecomment-329996505
def auc_roc(y_true, y_pred):
# any tensorflow metric
value, update_op = tf.contrib.metrics.streaming_auc(y_pred, y_true)
# find all variables created for this metric
metric_vars = [i for i in tf.local_variables() if 'auc_roc' in i.name.split('/')[1]]
# Add metric variables to GLOBAL_VARIABLES collection.
# They will be initialized for new session.
for v in metric_vars:
tf.add_to_collection(tf.GraphKeys.GLOBAL_VARIABLES, v)
# force to update metric values
with tf.control_dependencies([update_op]):
value = tf.identity(value)
return value
# generation a small dataset
N_all = 10000
N_tr = int(0.7 * N_all)
N_te = N_all - N_tr
X, y = make_classification(n_samples=N_all, n_features=20, n_classes=2)
y = np_utils.to_categorical(y, num_classes=2)
X_train, X_valid = X[:N_tr, :], X[N_tr:, :]
y_train, y_valid = y[:N_tr, :], y[N_tr:, :]
# model & train
model = Sequential()
model.add(Dense(2, activation="softmax", input_shape=(X.shape[1],)))
model.compile(loss='categorical_crossentropy',
optimizer='adam',
metrics=['accuracy', auc_roc])
my_callbacks = [EarlyStopping(monitor='auc_roc', patience=300, verbose=1, mode='max')]
model.fit(X, y,
validation_split=0.3,
shuffle=True,
batch_size=32, nb_epoch=5, verbose=1,
callbacks=my_callbacks)
# # or use independent valid set
# model.fit(X_train, y_train,
# validation_data=(X_valid, y_valid),
# batch_size=32, nb_epoch=5, verbose=1,
# callbacks=my_callbacks)
Как и вы, я предпочитаю использовать встроенные методы scikit-learn для оценки AUROC. Я считаю, что лучший и самый простой способ сделать это в керасе - это создать собственную метрику. Если тензор потока является вашим бэкэндом, реализация этого может быть осуществлена в несколько строк кода:
import tensorflow as tf
from sklearn.metrics import roc_auc_score
def auroc(y_true, y_pred):
return tf.py_func(roc_auc_score, (y_true, y_pred), tf.double)
# Build Model...
model.compile(loss='categorical_crossentropy', optimizer='adam',metrics=['accuracy', auroc])
Создание пользовательского обратного вызова, как упоминалось в других ответах, не будет работать для вашего случая, так как ваша модель имеет несколько выходов, но это будет работать. Кроме того, этот метод позволяет оценивать метрику как по данным обучения, так и по проверке, тогда как обратный вызов keras не имеет доступа к данным обучения и, таким образом, может использоваться только для оценки эффективности данных обучения.
Следующее решение работало для меня:
import tensorflow as tf
from keras import backend as K
def auc(y_true, y_pred):
auc = tf.metrics.auc(y_true, y_pred)[1]
K.get_session().run(tf.local_variables_initializer())
return auc
model.compile(loss="binary_crossentropy", optimizer='adam', metrics=[auc])
Я решил свою проблему таким образом
Предположим, у вас есть набор данных x_test для функций и y_test для соответствующих целей.
Сначала мы прогнозируем цели из функции, используя нашу обученную модель
y_pred = model.predict_proba(x_test)
затем из sklearn мы импортируем функцию roc_auc_score, а затем просто передаем исходные цели и прогнозируемые цели в функцию.
roc_auc_score(y_test, y_pred)
Вы можете отслеживать AUC во время обучения, предоставляя показатели следующим образом:
METRICS = [
keras.metrics.TruePositives(name='tp'),
keras.metrics.FalsePositives(name='fp'),
keras.metrics.TrueNegatives(name='tn'),
keras.metrics.FalseNegatives(name='fn'),
keras.metrics.BinaryAccuracy(name='accuracy'),
keras.metrics.Precision(name='precision'),
keras.metrics.Recall(name='recall'),
keras.metrics.AUC(name='auc'),
]
model = keras.Sequential([
keras.layers.Dense(16, activation='relu', input_shape=(train_features.shape[-1],)),
keras.layers.Dense(1, activation='sigmoid'),
])
model.compile(
optimizer=keras.optimizers.Adam(lr=1e-3)
loss=keras.losses.BinaryCrossentropy(),
metrics=METRICS)
для более подробного руководства см.:
https://www.tensorflow.org/tutorials/structured_data/imbalanced_data
Вы можете обернуть tf.metrics (например, tf.metrics.auc
) в keras.metrics.
Из моего ответа на Как использовать метрики TensorFlow в Керасе:
def as_keras_metric(method):
import functools
from keras import backend as K
import tensorflow as tf
@functools.wraps(method)
def wrapper(self, args, **kwargs):
""" Wrapper for turning tensorflow metrics into keras metrics """
value, update_op = method(self, args, **kwargs)
K.get_session().run(tf.local_variables_initializer())
with tf.control_dependencies([update_op]):
value = tf.identity(value)
return value
return wrapper
Основное использование:
auc_roc = as_keras_metric(tf.metrics.auc)
recall = as_keras_metric(tf.metrics.recall)
...
Скомпилируйте модель keras:
model.compile(..., metrics=[auc_roc])
'roc_curve','auc' не являются стандартными метриками, вы не можете передавать их таким образом в переменную метрик, это недопустимо. Вы можете передать что-то вроде "fmeasure", которое является стандартным показателем.
Просмотрите доступные метрики здесь: https://keras.io/metrics/ Вы также можете посмотреть на создание своей собственной метрики: https://keras.io/metrics/
Также взгляните на метод generate_results, упомянутый в этом блоге для ROC, AUC... https://vkolachalama.blogspot.in/2016/05/keras-implementation-of-mlp-neural.html
Установите архитектуру модели с помощью tf.keras.metrics.AUC(): прочтите следующий блог Keras: страница Keras
def model_architecture_ann(in_dim,lr=0.0001):
model = Sequential()
model.add(Dense(512, input_dim=X_train_filtered.shape[1], activation='relu'))
model.add(Dense(1, activation='sigmoid'))
opt = keras.optimizers.SGD(learning_rate=0.001)
auc=tf.keras.metrics.AUC()
model.compile(loss='binary_crossentropy', optimizer=opt, metrics=[tf.keras.metrics.AUC(name='auc')])
model.summary()
return model
Добавляя ответы выше, я получил ошибку "ValueError: неправильная форма ввода...", поэтому я определяю вектор вероятностей следующим образом:
y_pred = model.predict_proba(x_test)[:,1]
auc = roc_auc_score(y_test, y_pred)
print(auc)