Как существенное увеличение потерь может привести к улучшению точности?

Вопрос или проблема

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

https://github.com/udacity/deep-learning/raw/master/language-translation/data

который состоит более чем из 137 тысяч предложений. Моя модель — это LSTM с кодировщиком-декодировщиком и вниманием, реализованным в Keras. И вот мои графики потерь валидации и точности:

введите описание изображения здесь

введите описание изображения здесь

Два показателя точности — это кастомные метрики, разработанные мной. Но они основаны на той же categorical_accuracy из Keras.

Теперь мой вопрос: почему я получаю улучшение точности, в то время как значение потерь ухудшается?

Также, можно ли доверять такой модели?

Проверьте, учитываются ли заполненные значения при вычислении точности, что не должно быть так. Вам следует создать маску для заполненных значений и использовать ее при вычислении точности. Например, когда значение y_true для заполненной области равно 0, и 0 также для y_pred, тогда y_true == y_pred считается правильным предсказанием и влияет на общую точность. Это неправильно, и вместо этого вам следует определить кастомную метрику точности, которая делает следующее:

correct = y_pred == y_true
mask = tf.cast(tf.cast(y_true, tf.bool), tf.int16)
accuracy = tf.reduce_sum(correct * mask)/tf.reduce_sum(mask)

Надеюсь, это даст вам корректную меру.

Я не уверен, является ли это причиной в вашем случае. Но, в общем, большее (хуже) log_loss может соответствовать большему (лучше) accuracy если результирующие вероятности некорректированы:

import numpy as np
import matplotlib.pyplot as plt
from sklearn.metrics import log_loss, accuracy_score

random = np.random.RandomState(41)
y = np.array([0]*50 + [1]*50)

probas1= np.concatenate([[0]*30, random.uniform(size=40), [1]*30])
probas2= np.concatenate([random.normal(loc=0.48, scale=0.01, size=50),
                         random.normal(loc=0.52, scale=0.01, size=50)])

print(log_loss(y, probas1), accuracy_score(y, probas1>0.5))
print(log_loss(y, probas2), accuracy_score(y, probas2>0.5))

>>> 0.31286642799863323 0.83
>>> 0.6536974952243071 0.99

plt.hist(y, label="Истинные классы");
plt.hist(probas1, label="Лучший log_loss, худшая точность")
plt.hist(probas2, label="Худший log_loss, лучшая точность")
plt.legend()

гистограмма

Ответ или решение

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

Причины несоответствия между потерями и точностью

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

Точность, с другой стороны, это бинарная метрика, которая отражает долю правильно предсказанных классов среди всех предсказаний. Это может привести к ситуации, когда модель дает высокую точность при низком качестве вероятностных оценок, что как раз и объясняет, почему, например, при плохих значениях log_loss вы можете видеть высокую метрику точности.

Погрешность в расчете точности

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

correct = y_pred == y_true
mask = tf.cast(tf.cast(y_true, tf.bool), tf.int16)
accuracy = tf.reduce_sum(correct * mask) / tf.reduce_sum(mask)

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

Неоткалиброванные вероятности

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

Пример:

import numpy as np
from sklearn.metrics import log_loss, accuracy_score

random = np.random.RandomState(41)
y = np.array([0]*50 + [1]*50)

probas1 = np.concatenate([[0]*30, random.uniform(size=40), [1]*30])
probas2 = np.concatenate([random.normal(loc=0.48, scale=0.01, size=50),
                          random.normal(loc=0.52, scale=0.01, size=50)])

print(log_loss(y, probas1), accuracy_score(y, probas1 > 0.5))
print(log_loss(y, probas2), accuracy_score(y, probas2 > 0.5))

Доверие к модели

Теперь относительно доверия к вашей модели. Если вы наблюдаете резкое несоответствие между показателями потерь и точности, стоит проявить осторожность. Высокая точность с большими потерями может говорить о переобучении модели или же о проблемах с оценкой метрик. Рекомендуется проводить перекрестную проверку модели и использовать уточненные метрики, такие как F1-score или AUC, которые могут дать вам более полное представление о ее производительности.

Заключение

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

Оцените материал
Добавить комментарий

Капча загружается...