Почему нейросеть выдаёт мусор (например, среднее всех результатов или у неё реально слабая точность)? С чего начать проверку?
Сеть может не обучаться по ряду причин. По итогу многих отладочных сессий я заметил, что часто делаю одни и те же проверки. Здесь я собрал в удобный список свой опыт вместе с лучшими идеями коллег. Надеюсь, этот список будет полезен и вам.
Содержание
0. Как использовать это руководство?
I. Проблемы с набором данных
II. Нормализация данных/Проблемы аугментации
III. Проблемы реализации
IV. Проблемы обучения
0. Как использовать это руководство?
Многое может пойти не так. Но некоторые проблемы встречаются чаще, чем другие. Я обычно начинаю с этого маленького списка как набора экстренной помощи:
- Начните с простой модели, которая точно правильно работает для этого типа данных (например, VGG для изображений). Используйте стандартную функцию потерь, если возможно.
- Отключите все финтифлюшки, например, регуляризацию и аугментацию данных.
- В случае тонкой настройки модели дважды проверьте препроцессинг, чтобы он соответствовал обучению первоначальной модели.
- Удостоверьтесь в правильности входных данных.
- Начните с действительно маленького набора данных (2-20 образцов). Затем расширяйте его, постепенно добавляя новые данные.
- Начните постепенно добавлять обратно все фрагменты, которые были опущены: аугментация/регуляризация, кастомные функции потерь, пробуйте более сложные модели.
Если ничего не помогло, то приступайте к чтению этого длинного списка и проверяйте каждый пункт.
I. Проблемы с набором данных
![](https://habrastorage.org/getpro/habr/post_images/ef6/032/8ff/ef60328ff5f505334860490ca248270c.png)
Источник: http://dilbert.com/strip/2014-05-07
1. Проверьте входные данные
Проверьте, что входные данные имеют смысл. Например, я не раз смешивал в кучу высоту и ширину изображений. Иногда по ошибке отдавал в нейросеть все нули. Или использовал одну и ту же партию снова и снова. Так что напечатайте/посмотрите пару партий входных данных и плановых выходных данных — убедитесь, что всё в порядке.
2. Попробуйте случайные входные значения
Попробуйте передать случайные числа вместо реальных данных и посмотрите, останется ли та же ошибка. Если так, то это верный знак, что ваша сеть на каком-то этапе превращает данные в мусор. Попробуйте отладку слой за слоем (операция за операцией) и посмотрите, где происходит сбой.
3. Проверьте загрузчик данных
С данными всё может быть в порядке, а ошибка в коде, который передаёт входные данные нейросети. Распечатайте и проверьте входные данные первого слоя перед началом его операций.
4. Убедитесь, что вход соединяется с выходом
Проверьте, что несколько образцов входных данных снабжены правильными метками. Также проверьте, что смена местами входных образцов так же отражается на выходных метках.
5. Взаимоотношение между входом и выходом слишком случайно?
Может быть, неслучайные части взаимоотношения между входом и выходом слишком малы по сравнению со случайной частью (кто-то может сказать, что таковы котировки на бирже). То есть вход недостаточно связан с выходом. Тут нет универсального метода, потому что мера случайности зависит от типа данных.
6. Слишком много шума в наборе данных?
Однажды это случилось со мной, когда я стянул набор изображений продуктов питания с сайта. Там было так много плохих меток, что сеть не могла обучаться. Вручную проверьте ряд образцов входных значений и посмотрите, что все метки на месте.
Данный пункт достоин отдельного разговора, потому что эта работа показывает точность выше 50% на базе MNIST при 50% повреждённых меток.
7. Перемешайте набор данных
Если ваши данные не перемешаны и располагаются в определённом порядке (отсортированы по меткам), это может отрицательно отразиться на обучении. Перемешайте набор данных: убедитесь, что перемешиваете вместе и входные данные, и метки.
8. Снизьте несбалансированность классов
Может, в наборе данных тысяча изображений класса А на одно изображение класса Б? Тогда вам может понадобиться сбалансировать функцию потерь или попробовать другие подходы устранения несбалансированности.
9. Достаточно ли образцов для обучения?
Если вы обучаете сеть с нуля (то есть не настраиваете её), то может понадобиться очень много данных. Например, для классификации изображений, говорят, нужна тысяча изображений на каждый класс, а то и больше.
10. Убедитесь в отсутствии партий с единственной меткой
Такое случается в отсортированном наборе данных (то есть первые 10 тыс. образцов содержат одинаковый класс). Легко исправляется перемешиванием набора данных.
11. Уменьшите размер партий
Эта работа указывает, что слишком большие партии могут понизить у модели способность к обобщению.
Дополнение 1. Используйте стандартный набор данных (например, mnist, cifar10)
Спасибо hengcherkeng за это:
При тестировании новой сетевой архитектуры или написании нового кода сначала используйте стандартные наборы данных вместо своих. Потому что для них уже есть много результатов и они гарантированно «разрешимые». Там не будет проблем с шумом в метках, разницей в распределении обучение/тестирование, слишком большой сложностью набора данных и т.д.
II. Нормализация данных/Проблемы аугментации
![](https://habrastorage.org/getpro/habr/post_images/a37/7f1/71d/a377f171d5b6bdc0a01822ed42952033.png)
12. Откалибруйте признаки
Вы откалибровали входные данные на нулевое среднее и единичную дисперсию?
13. Слишком сильная аугментация данных?
Аугментация имеет регуляризующий эффект. Если она слишком сильная, то это вкупе с другими формами регуляризации (L2-регуляризация, dropout и др.) может привести к недообучению нейросети.
14. Проверьте предобработку предварительно обученной модели
Если вы используете уже подготовленную модель, то убедитесь, что используются та же нормализация и предобработка, что и в модели, которую вы обучаете. Например, должен пиксель быть в диапазоне [0, 1], [-1, 1] или [0, 255]?
15. Проверьте предварительную обработку для набора обучение/валидация/тестирование
CS231n указал на типичную ловушку:
«… любую статистику предобработки (например, среднее данных) нужно вычислять на данных для обучения, а потом применять на данных валидации/тестирования. Например, будет ошибкой вычисление среднего и вычитание его из каждого изображения во всём наборе данных, а затем разделение данных на фрагменты для обучения/валидации/тестирования».
Также проверьте на предмет наличия различающейся предварительной обработки каждого образца и партии.
III. Проблемы реализации
![](https://habrastorage.org/getpro/habr/post_images/a3c/00e/878/a3c00e878e007200b1f3501115b65066.png)
Источник: https://xkcd.com/1838/
16. Попробуйте решить более простой вариант задачи
Это поможет определить, где проблема. Например, если целевая выдача — это класс объекта и координаты, попробуйте ограничить предсказание только классом объекта.
17. Поищите правильную функцию потерь «по вероятности»
Снова из бесподобного CS231n: Инициализируйте с небольшими параметрами, без регуляризации. Например, если у нас 10 классов, то «по вероятности» означает, что правильный класс определится в 10% случаев, а функция потерь Softmax — это обратный логарифм к вероятности правильного класса, то есть получается
После этого попробуйте увеличить силу регуляризации, что должно увеличить функцию потерь.
18. Проверьте функцию потерь
Если вы реализовали свою собственную, проверьте её на баги и добавьте юнит-тесты. У меня часто бывало, что слегка неправильная функция потерь тонко вредила производительности сети.
19. Проверьте входные данные функции потерь
Если вы используете функцию потерь из фреймворка, то убедитесь, что передаёте ей то что нужно. Например, в PyTorch я бы смешал NLLLoss и CrossEntropyLoss, потому что первая требует входных данных softmax, а вторая — нет.
20. Отрегулируйте веса функции потерь
Если ваша функция потерь состоит из нескольких функций, проверьте их соотношение относительно друг друга. Для этого может понадобиться тестирование в разных вариантах соотношений.
21. Отслеживайте другие показатели
Иногда функция потерь — не лучший предиктор того, насколько правильно обучается ваша нейросеть. Если возможно, используйте другие показатели, такие как точность.
22. Проверьте каждый кастомный слой
Вы самостоятельно реализовали какие-то из слоёв сети? Дважды проверьте, что они работают как полагается.
23. Проверьте отсутствие «зависших» слоёв или переменных
Посмотрите, может вы неумышленно отключили обновления градиента каких-то слоёв/переменных.
24. Увеличьте размер сети
Может, выразительной мощности сети недостаточно для усвоения целевой функции. Попробуйте добавить слоёв или больше скрытых юнитов в полностью соединённые слои.
25. Поищите скрытые ошибки измерений
Если ваши входные данные выглядят как , то легко пропустить ошибку, связанную с неправильными измерениями. Используйте необычные числа для измерений входных данных (например, разные простые числа для каждого измерения) и посмотрите, как они распространяются по сети.
26. Исследуйте Gradient Checking
Если вы самостоятельно реализовали Gradient Descent, то с помощью Gradient Checking можно убедиться в корректной обратной связи. Дополнительная информация: 1, 2, 3.
IV. Проблемы обучения
![](https://habrastorage.org/getpro/habr/post_images/1f6/298/603/1f6298603efa05d69690060e56aa7178.png)
Источник: http://carlvondrick.com/ihog/
27. Решите задачу для действительно маленького набора данных
Переобучите сеть на маленьком наборе данных и убедитесь в её работе. Например, обучите её всего с 1-2 примерами и посмотрите, способна ли сеть различать объекты. Переходите к большему количеству образцов для каждого класса.
28. Проверьте инициализацию весов
Если не уверены, используйте инициализацию Ксавьера или Хе. К тому же, ваша инициализация может вывести на плохой локальный минимум, так что испытайте другую инициализацию, может поможет.
29. Измените гиперпараметры
Может вы используете плохой набор гиперпараметров. Если возможно, попробуйте grid search.
30. Уменьшите регуляризацию
Из-за слишком сильной регуляризации сеть может конкретно недообучиться. Уменьшите регуляризацию, такую как dropout, batch norm, L2-регуляризацию weight/bias и др. В отличном курсе «Практическое глубинное обучение для программистов» Джереми Говард рекомендует в первую очередь избавиться от недообучения. То есть нужно достаточно переообучить сеть на исходных данных, и только затем бороться с переобучением.
31. Дайте время
Может сети нужно больше времени на обучение, прежде чем она начнёт делать осмысленные предсказания. Если функция потерь стабильно уменьшается, дайте ей обучиться чуть подольше.
32. Переходите от режима обучения в режим тестирования
В некоторых фреймворках слои Batch Norm, Dropout и другие ведут себя по-разному во время обучения и тестирования. Переключение в подходящий режим может помочь вашей сети начать делать правильные прогнозы.
33. Визуализируйте обучение
- Отслеживайте активации, веса и обновления для каждого слоя. Убедитесь, что отношения их величин совпадают. Например, отношение величины обновлений к параметрам (весам и смещениям) должно равняться 1e-3.
- Рассмотрите библиотеки визуализации вроде Tensorboard и Crayon. В крайнем случае, можно просто печатать значения весов/сдвигов/активаций.
- Будьте осторожны с активациями сетей со средним намного больше нуля. Попробуйте Batch Norm или ELU.
- Deeplearning4j указал, на что смотреть в гистограммах весов и сдвигов:
«Для весов эти гистограммы должны иметь примерно гауссово (нормальное) распределение, спустя какое-то время. Гистограммы сдвигов обычно начинаются с нуля и обычно заканчиваются на уровне примерно гауссова распределения (единственное исключение — LSTM). Следите за параметрами, которые отклоняются на плюс/минус бесконечность. Следите за сдвигами, которые становятся слишком большими. Иногда такое случается в выходном слое для классификации, если распределение классов слишком несбалансировано».
- Проверяйте обновления слоёв, они должны иметь нормальное распределение.
34. Попробуйте иной оптимизатор
Ваш выбор оптимизатора не должен мешать нейросети обучаться, если только вы не выбрали конкретно плохие гиперпараметры. Но правильный оптимизатор для задачи может помочь получить наилучшее обучение за кратчайшее время. Научная статья с описанием того алгоритма, который вы используете, должна упомянуть и оптимизатор. Если нет, я предпочитаю использовать Adam или простой SGD.
Прочтите отличную статью Себастьяна Рудера, чтобы узнать больше об оптимизаторах градиентного спуска.
35. Взрыв/исчезновение градиентов
- Проверьте обновления слоя, поскольку очень большие значения могут указывать на взрывы градиентов. Может помочь клиппинг градиента.
- Проверьте активации слоя. Deeplearning4j даёт отличный совет: «Хорошее стандартное отклонение для активаций находится в районе от 0,5 до 2,0. Значительный выход за эти рамки может указывать на взрыв или исчезновение активаций».
36. Ускорьте/замедлите обучение
Низкая скорость обучения приведёт к очень медленному схождению модели.
Высокая скорость обучения сначала быстро уменьшит функцию потерь, а потом вам будет трудно найти хорошее решение.
Поэкспериментируйте со скоростью обучению, ускоряя либо замедляя её в 10 раз.
37. Устранение состояний NaN
Состояния NaN (Non-a-Number) гораздо чаще встречаются при обучении RNN (насколько я слышал). Некоторые способы их устранения:
- Уменьшите скорость обучения, особенно если NaN появляются в первые 100 итераций.
- Нечисла могут возникнуть из-за деления на ноль, взятия натурального логарифма нуля или отрицательного числа.
- Рассел Стюарт предлагает хорошие советы, что делать в случае появления NaN.
- Попробуйте оценить сеть слой за слоем и посмотреть, где появляются NaN.
russellsstewart.com/notes/0.html
stackoverflow.com/questions/41488279/neural-network-always-predicts-the-same-class
deeplearning4j.org/visualization
www.reddit.com/r/MachineLearning/comments/46b8dz/what_does_debugging_a_deep_net_look_like
www.researchgate.net/post/why_the_prediction_or_the_output_of_neural_network_does_not_change_during_the_test_phase
book.caltech.edu/bookforum/showthread.php?t=4113
gab41.lab41.org/some-tips-for-debugging-deep-learning-3f69e56ea134
www.quora.com/How-do-I-debug-an-artificial-neural-network-algorithm
Комментарии (11)
slonopotamus
05.08.2017 23:58Карго-культ и танцы с бубном. Почти все пункты подразумевают что нейросеть — черный ящик. Но можно же взять и посмотреть что происходит внутри нее.
masai
06.08.2017 00:31+4Не всегда понятно, на что смотреть. Скажем, приспособили вы ResNet из двух десятков слоев для сегментации котиков. А она не обучается. Куда именно внутрь сети смотреть?
Sirion
06.08.2017 02:45Иногда люблю читать статьи про области, в которых не понимаю ничего, чтобы понять, что именно я не понимаю. Ваш перевод помог, благодарю.
uploadfor
06.08.2017 11:0838. Убедитесь в том, что то, что у вас есть — действительно «нейро», и действительно «сеть».
grossws
06.08.2017 16:17+242. Убедитесь, что нейросеть вам вообще нужна. Возможно, хватит логрега или ансамбля решающих деревьев.
dklein
07.08.2017 10:38Я правильно понимаю, что в конечном счёте всё упирается в данные, на которых данная сеть обучается? И, что, если найти программера, который напишет код, ещё как-то возможно, но найти, например, 1.000.000 уникальных изображений автомобильных знаков или фотографий, например, собак, — просто нереально сложно?
RomanSt
07.08.2017 11:56Найти готовый датасет под уникальную задачу в 99% случаев невозможно. Создать свой вполне реально, хоть и трудоемко. Если говорить о ваших примерах, то автомобильные знаки, собак найти можно, хоть и не 1кк экземпляров. Нужно 1кк? Запустите краудсорсинг по фотографированию знаков/собачек. Если ваши объекты, менее популярны, например, кофе-машины или заколки, то придется запустить датамайнинг или краудсорсинг.
vesper-bot
07.08.2017 11:03-134. Убедитесь, что ваша нейросеть не занимается любовью с оборудованием вместо обучения.
nckma
У меня знакомый есть, специалист по нейросетям. Он говорит, что нейросети — отличная вещь — когда передаешь ее заказчику и она не работает, то всегда можно сказать, что «вы обучали ее на неправильных данных».
Hardcoin
А заказчик разве платит не за обученную сеть? Странный заказчик, видимо )
Nixhibrid
Видимо заказчик жмет бюджет