Делаем нейронную сеть: как не сломать мозг |
||
МЕНЮ Искусственный интеллект Поиск Регистрация на сайте Помощь проекту ТЕМЫ Новости ИИ Искусственный интеллект Разработка ИИГолосовой помощник Городские сумасшедшие ИИ в медицине ИИ проекты Искусственные нейросети Слежка за людьми Угроза ИИ ИИ теория Внедрение ИИКомпьютерные науки Машинное обуч. (Ошибки) Машинное обучение Машинный перевод Реализация ИИ Реализация нейросетей Создание беспилотных авто Трезво про ИИ Философия ИИ Big data Работа разума и сознаниеМодель мозгаРобототехника, БПЛАТрансгуманизмОбработка текстаТеория эволюцииДополненная реальностьЖелезоКиберугрозыНаучный мирИТ индустрияРазработка ПОТеория информацииМатематикаЦифровая экономика
Генетические алгоритмы Капсульные нейросети Основы нейронных сетей Распознавание лиц Распознавание образов Распознавание речи Техническое зрение Чат-боты Авторизация |
2019-02-13 04:58 В этой небольшой заметке расскажу о двух подводных камнях, с которыми как легко столкнуться, так и легко о них разбиться.
Пытаемся учить… но ничего не выходит. И вот в этом месте можно устраивать танцы с бубном и потерять много времени.
Предсказалось 49, что совсем далеко не 65. Но стоит нам немного переделать генератор, как все начинает сразу работать.
И видно, что уже буквально на третьей эпохе сеть сходится.
Основное отличие в том, что в первом случае у нас объект x_mean каждый раз создается в памяти, а во втором он появляется при создании генератора и дальше только переиспользуется. Разбираемся дальше, все ли верно в этом генераторе. Оказывается, что не совсем. Следующий пример показывает, что что-то идет не так.
(array([[44., 2.]]), array([10.])) (array([[44., 2.]]), array([23.])) Среднее значение в первом вызове итератора не совпадает с числами, на основе которых оно посчитано. На самом деле среднее значение было посчитано правильно, но т.к. массив был передан по ссылке, то при втором вызове итератора значения в массиве перезаписались, и функция print() выдала, что и было в массиве, а не то, что мы ожидали. Есть два способо это исправить. Оба затратные, но корректные. 1. Перенести создание переменной x внутрь цикла while, чтобы массив при каждом yield создавался новый.
(array([[82., 4.]]), array([43.])) (array([[77., 34.]]), array([55.5])) 2. Возвращать копию массива.
(array([[63., 31.]]), array([47.])) (array([[94., 25.]]), array([59.5])) Теперь все отлично. Идем дальше. Нужно ли делать expand_dims? Попробуем убрать эту строку и новый код будет такой:
Все прекрасно учится, хотя возвращаемые данные имеют другой shape. Например, было [[49.]], а стало [49.], но внутри Keras это, видимо, корректно приводится к нужной размерности. Итак, мы знаем, как должен выглядеть правильный генератор данных, теперь поиграемся с lambda функцией, и посмотрим на поведение expand_dims там. Ничего предсказывать не будем, просто считаем внитри lambda правильное значение. Код следующий:
Запускаем и видим, что все прекрасно:
Попробуем теперь немного изменить нашу lambda функцию и убрать expand_dims.
При компиляции модели никаких ошибок на размерность не появилось, но результат уже другой, лосс считается непонятно как. Таким образом, здесь expand_dims нужно делать, ничего автоматически не произойдет.
И если посмотреть на возвращаемый результат predict(), то видно, что размерность неправильная, выход равен [46.], а ожидается [[46.]]. Как-то так. Спасибо всем, кто дочитал. И будьте внимательны в мелочах, эффект от них может быть существенным. Источник: habr.com Комментарии: |
|