Сигмоидальный вывод для класса обнаружения возвращает неверную производительность

Резюме моей проблемы: у меня есть обнаружение (двоичная классификация, несбалансированная проблема). Я использую сигмоид для классификации образцов. Представленные f-оценка, точность и отзыв, похоже, учитывают оба класса, например, истинные положительные значения представляют собой общее количество правильно классифицированных образцов, а не общее количество образцов, принадлежащих к классу "1", которые классифицированы правильно.

Более длинное объяснение: в моем эксперименте у меня есть демографические данные о людях, и я должен предсказать, купили ли они продукт или нет. Я использовал PCA, чтобы уменьшить первоначальные функции до 4 функций, и данные хранятся в файле CSV (первый столбец содержит метки классов, "0" и "1"). Обратите внимание, что большинство людей не покупали, и тогда эти два класса очень несбалансированы. Я использую класс CSVDataset, чтобы прочитать его:

dataset: &train !obj:pylearn2.datasets.csv_dataset.CSVDataset {
        path: 'input.csv',
        task: 'classification'
}

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

model: !obj:pylearn2.models.mlp.MLP {
        layers: [
                 !obj:pylearn2.models.mlp.Sigmoid {
                     layer_name: 'y',
                     dim: 2,
                     irange: .005
                 }
                ],
        nvis: 4,
    }

Моя первоначальная идея состояла в том, чтобы установить dim в 1 (правило принятия решения было бы таково: если output > 0.5, выберите класс '1', если < 0.5, выберите класс '0'). Тем не менее, я получил ошибку ValueError: Невозможно преобразовать в VectorSpace из dim 1. Ожидается, что dim=2 (объединенные одноточечные) или 2 (объединенные одноточечные), а затем я решил установить dim равным 2 (правило принятия решения будет быть: если out1 > out0 выберите "1", если out1

В моем train.yaml я более или менее следую примеру тетради softmax, приведенному в документации. Например, я использую алгоритм BGD и задаю batch_size как общее количество примеров в обучающем наборе (74164 примера, небольшой набор данных!), Чтобы избежать путаницы при проверке производительности вручную.

Модель была обучена с помощью прилагаемого скрипта train.py, и все выглядело хорошо, пока я не посмотрел на результаты. Как упоминалось ранее, это проблема обнаружения, когда класс для обнаружения ('1') происходит очень редко. Поэтому я был очень удивлен, увидев высокие значения для сообщенного train_y_f1 (лучший результат составляет около 94% после одной эпохи).

Чтобы проверить это, я вычислил f-показатель вручную, используя предоставленный сценарий Предикат_csv.py, а затем загрузил прогнозы. Я видел, что на самом деле были только промахи (все "1" были классифицированы как "0"), поэтому точность, отзыв и f-оценка должны быть равны нулю. Почему монитор обнаружения сообщает о более высоких значениях?

После некоторого исследования я обнаружил, что MLP имеет выходные данные для каждого класса, и я проверил (вычислил его вручную и получил те же числа), что истинные положительные и ложные положительные значения, определенные в get_detection_channels_from_state(), фактически относятся к обоим классам, '1' и "0", например, истинные положительные значения - это число векторов, принадлежащих "1", классифицированных как "1", суммированных с количеством векторов, принадлежащих "0", классифицированных как "0". Таким образом, MLP классифицирует все как "0", и, поскольку почти все векторы принадлежат "0", производительность хорошая. Это известная проблема для несбалансированных проблем обнаружения, где правильная скорость классификации не является подходящей мерой, и это причина, почему у нас есть меры, такие как f-оценка или AUC. Однако, если tp и fp в get_detection_channels_from_state() учитывают оба класса, то сообщаемое f-оценка не является полезным (по крайней мере, для меня).

Я могу представить, что это известно разработчику класса Sigmoid, поэтому я могу только предположить, что я делаю что-то не так. Надеюсь, кто-нибудь может дать мне подсказку:)

Примечание: я отправил этот вопрос в список рассылки пользователя pylearn2. Если я получу ответ, я скопирую его здесь...

1 ответ

Монитор Pylearn вычисляет оценку f1, % misclass и т. Д. Для каждой партии, а не для всей эпохи. Когда он генерирует отчет, оценка f1 является средним значением f1 для всех партий в эпоху. Отчет о среднем по всем партиям прекрасно работает, когда вы смотрите на количества, похожие на неправильный класс:

misclass [n] - оценка для n-й партии
misclass_epoch = mean(misclass[0] + misclass[1] +.. misclass[n])

тем не менее, вы не можете построить то же самое утверждение для оценки f1:
f1_epoch! = среднее (f1[0] + f1[1] +.. f1[n])
где f1[n] = 2* точность [n]* отзыв [n]/(точность [n] + отзыв [n])

В демонстрационных целях попробуйте установить размер пакета равным размеру набора данных (вы можете избежать этого в примере с mnist). Тогда оценка f1 будет правильной.

Поэтому лучший совет - следить за количествами в мониторе, например, за неправильным классом, где среднее значение по партиям совпадает со значением для эпохи. После того, как вы обучите nn, вы сможете делать прогнозы для всего набора валидации и рассчитывать оценку f1 в этой точке.

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