Tensorflow и Keras: построение пользовательской метрики для точности

У меня есть подкласс класса Metric для создания пользовательской метрики точности. Все выглядит хорошо; Я имею в виду, что нет ошибки времени выполнения. Но я подозреваю, что что-то не так, когда я вижу, что оценки точности регистрируются в выходных данных, они всегда показывают одну и ту же оценку в конце каждой эпохи, например, эпоха 0,1000 или 0,9000.

Вот мой код:


(X_train_10, y_train_10), (X_test_10, y_test_10) = keras.datasets.cifar10.load_data()

X_train_10 = X_train_10 / 255.
X_test_10 = X_test_10 / 255.

class PrecisionMetric(keras.metrics.Metric):
    def __init__(self, name = 'precision', **kwargs):
        super(PrecisionMetric, self).__init__(**kwargs)
        self.tp = self.add_weight('tp', initializer = 'zeros')
        self.fp = self.add_weight('fp', initializer = 'zeros')

    def update_state(self, y_true, y_pred):
        y_true = tf.cast(y_true, tf.bool)
        y_pred = tf.cast(y_pred, tf.bool)        
        true_p = tf.logical_and(tf.equal(y_true, True), tf.equal(y_pred, True))
        false_p = tf.logical_and(tf.equal(y_true, False), tf.equal(y_pred, True))
        self.tp.assign_add(tf.reduce_sum(tf.cast(true_p, self.dtype)))
        self.fp.assign_add(tf.reduce_sum(tf.cast(false_p, self.dtype)))
    def reset_states(self):
        self.tp.assign(0)
        self.fp.assign(0)

    def result(self):
        return self.tp / (self.tp + self.fp)


keras.backend.clear_session()
model = keras.models.Sequential()

model.add(keras.layers.Flatten(input_shape = np.array(X_train_10.shape[1: ])))
for _ in range(2):
    model.add(keras.layers.Dense(50, activation = 'elu', kernel_initializer = 'he_normal'))
model.add(keras.layers.Dense(1, activation = 'sigmoid'))

loss = keras.losses.binary_crossentropy
optimizer = keras.optimizers.SGD()

model.compile(loss = loss, optimizer = optimizer, metrics = [PrecisionMetric()])

# To make it binary classification
y_train_5 = (y_train_10 == 5)
y_test_5 = (y_test_10 == 5)

history = model.fit(X_train_10, y_train_5, epochs = 5)

Вывод после запуска 5 эпохи:

Epoch 1/5
1563/1563 [==============================] - 5s 4ms/step - loss: 0.2921 - precision_metric: 0.1000
Epoch 2/5
1563/1563 [==============================] - 4s 2ms/step - loss: 0.2744 - precision_metric: 0.1000
Epoch 3/5
1563/1563 [==============================] - 3s 2ms/step - loss: 0.2682 - precision_metric: 0.1000
Epoch 4/5
1563/1563 [==============================] - 3s 2ms/step - loss: 0.2651 - precision_metric: 0.1000
Epoch 5/5
1563/1563 [==============================] - 4s 3ms/step - loss: 0.2629 - precision_metric: 0.1000

Примечание: даже пробовал с большим числом эпох, например, 100, и по-прежнему выдает ту же самую точность, в то время как потери продолжают сокращаться/становиться меньше.

Udacity Nanodegree Capstone Project: Классификатор пород собак
Udacity Nanodegree Capstone Project: Классификатор пород собак
Вы можете ознакомиться со скриптами проекта и данными на github .
1
0
1 111
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

РЕДАКТИРОВАТЬ

В вашей реализации есть ошибка. Вы не должны приводить y_pred к bool. Это выходы из сигмоиды. Ты должен сделать

y_pred = tf.math.greater(y_pred, 0.5)

когда ваша проблема двоичная (вы получаете вывод из сигмоида). И адаптируйте его для многоклассовой классификации.

Пожалуйста, в result проверьте, не делите ли вы 0/0 через:

    def result(self):
        res =  self.tp / (self.tp + self.fp)
        if tf.math.is_nan(res):
            return 0.0
        else:
            return res

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

Огромное спасибо @Proko, не беспокойтесь, все, что здесь идет, носит образовательный характер, если бы не я, другие могли бы на этом поучиться. Я исправил код, конечно, я совершенно забыл о сигмовидной функции;). Более того, я новичок в StackOverflow; Я удалил свой собственный ответ. Также обновите адаптацию для функции softmax.

Mohammad Kasra Habib 24.12.2020 00:11

Другие вопросы по теме