Предобработка — это общий термин для всех манипуляций, производимых с данными перед передачей их модели, включая центрирование, нормализацию, сдвиг, вращение, обрезку и т. п. Как правило, предобработка требуется в двух случаях.
Рассмотрим некоторые возможные методы трансформации при предобработке и их реализацию через Keras.
![](https://habrastorage.org/webt/l-/qv/i5/l-qvi5bbsdqfjdcfheqqzjhrpzu.jpeg)
В этой и следующих статьях будет использован набор данных для анализа эмоциональной окраски изображений. Он содержит 1500 примеров изображений, разделенных на два класса — положительные и отрицательные. Рассмотрим некоторые примеры.
![](https://habrastorage.org/webt/mu/rf/_g/murf_geogu_lj6a9q4xoa4pn3si.jpeg)
Отрицательные примеры
![](https://habrastorage.org/webt/nn/1_/vt/nn1_vtdtnxjci9mlhxxh25f4c5a.jpeg)
Положительные примеры
Теперь рассмотрим набор возможных трансформаций, обычно применяемых для очистки данных, их внедрение и влияние на изображения.
Все фрагменты кода можно найти в книге Preprocessing.ipynb.
Изображения, как правило, хранятся в формате RGB (Red Green Blue). В этом формате изображение представлено трехмерным (или трехканальным) массивом.
![](https://habrastorage.org/webt/gk/bw/4w/gkbw4wlsomht08_atrneom6ugru.jpeg)
RGB-разложение изображения. Диаграмма взята с Wikiwand
Одно измерение используется для каналов (красного, зеленого и синего цветов), два других представляют местоположение. Таким образом, каждый пиксель кодируется тремя числами. Каждое число обычно хранится в виде 8-битового беззнакового целого типа (от 0 до 255).
Перемасштабирование — это операция, изменяющая числовой диапазон данных простым делением на заранее определенную константу. В глубоких нейронных сетях может потребоваться ограничить входные данные диапазоном от 0 до 1 из-за возможного переполнения, вопросов оптимизации, стабильности и т. п.
Например, перемасштабируем наши данные с диапазона [0; 255] в диапазон [0; 1]. Здесь и далее будем использовать класс Keras ImageDataGenerator, позволяющий выполнять все трансформации «на лету».
Создадим два экземпляра этого класса: один для трансформированных данных, другой для исходных:
![](https://habrastorage.org/webt/pf/0_/hv/pf0_hvqdqdqsqtwwaqw5nznhrhc.png)
(или для данных по умолчанию). Необходимо лишь указать константу масштабирования. Более того, класс ImageDataGenerator позволяет направлять данные потоком напрямую из папки на жестком диске, используя метод flow_from_directory.
Все параметры можно найти в документации, но основными параметрами являются: путь к потоку и целевой размер изображения (если изображение не соответствует целевому размеру, генератор его просто обрезает или наращивает). Наконец, получим образец из генератора и рассмотрим результаты.
Визуально оба изображения идентичны, но причина этого в том, что инструменты Python* автоматически перемасштабируют изображения
![](https://habrastorage.org/webt/5s/o6/9o/5so69otm8hi5utmf09himqmoigm.jpeg)
в диапазон по умолчанию, чтобы их можно было отображать на экране. Рассмотрим сырые данные (массивы). Как видно, сырые массивы отличаются ровно в 255 раз.
Еще один вид трансформации, который может оказаться полезным — это перевод в оттенки серого, который переводит цветное RGB-изображение в изображение, в котором все цвета представлены оттенками серого. Обычная обработка изображений может использовать перевод в оттенки серого в комбинации с последующим заданием порога. Эта пара трансформаций может отбрасывать шумные пиксели и определять формы на изображении. Сегодня все эти операции выполняются сверточными нейронными сетями (Convolutional Neural Network, CNN), но перевод в оттенки серого как этап предобработки по-прежнему может быть полезным. Запустим этот шаг в Keras с тем же классом генератора.
![](https://habrastorage.org/webt/uh/ay/li/uhaylivvkd5aznb1k-l9hzeeabw.jpeg)
Здесь мы создаем только один экземпляр класса и берем из него два разных генератора. Второй генератор устанавливает параметр color_mode в “grayscale” (значение по умолчанию “RGB”).
Мы уже видели, что значения необработанных данных находятся в диапазоне от 0 до 255. Таким образом, один образец представляет собой трехмерный массив чисел от 0 до 255. В свете принципов стабильности оптимизации (избавляться от проблемы исчезающих или насыщающих значений) может потребоваться нормализовать набор данных таким образом, чтобы среднее значение каждого образца данных равнялось 0.
![](https://habrastorage.org/webt/eh/6s/jg/eh6sjgccinzuviy9vrzklcbzqas.jpeg)
Для этого необходимо рассчитать среднее значение по всему образцу и вычесть его из каждого числа в данном образце.
В Keras это делается при помощи параметра samplewise_center.
Данный этап предобработки основан на той же идее, что и центрирование образцов, но вместо установки среднего в 0 от устанавливает значение среднеквадратичного отклонения в 1.
![](https://habrastorage.org/webt/_e/aq/4k/_eaq4kpjy1ox6l70homarb0tlxe.png)
Нормализация СКО управляется параметром samplewise_std_normalization. Следует отметить, что эти два способа нормализации образцов часто используются совместно.
Данная трансформация может применяться в моделях глубокого обучения для повышения стабильности оптимизации путем снижения влияния проблемы взрывающихся градиентов.
В двух предыдущих разделах использовалась техника нормализации, рассматривающая каждый отдельный образец данных. Существует альтернативный подход к процедуре нормализации. Рассмотрим каждое число в массиве изображения как признак. Тогда каждое изображение представляет собой вектор признаков. В наборе данных много таких векторов; следовательно, мы можем рассматривать их в виде некоторого неизвестного распределения. Это распределение является многопараметрическим, и размерность его будет равна количеству признаков, т. е. ширина ? высота ? 3. Хотя истинное распределение данных неизвестно, можно попытаться нормализовать его путем вычитания среднего значения распределения. Следует отметить, что среднее значение представляет собой вектор той же размерности, то есть, тоже является изображением. Другими словами, мы усредняем по всему набору данных, а не по одному образцу.
Существует специальный параметр Keras под названием featurewise_centering, но, к сожалению, по состоянию на август 2017 года в его реализации была ошибка; поэтому реализуем его самостоятельно. Сначала считаем весь набор данных в память (мы можем себе это позволить, так как имеем дело с небольшим набором данных). Мы сделали это, установив размер пакета равным размеру набора данных. Затем рассчитаем среднее изображение по всему набору данных и, наконец вычтем его из тестового изображения.
![](https://habrastorage.org/webt/sm/wn/of/smwnofa7izsr-kyhn2r8mwab-dw.jpeg)
Идея нормализации среднеквадратичного отклонения в точности та же, что и идея центрирования. Единственная разница состоит в том, что вместо вычитания среднего значения мы производим деление на значение среднеквадратичного отклонения. Визуально результат не сильно отличается. То же происходило
![](https://habrastorage.org/webt/im/j-/ge/imj-gegeoxxc_1dsd6km4vshs9e.png)
при перемасштабировании, поскольку нормализация СКО есть не что иное как перемасштабирование с определенным образом рассчитанной константой, а при простом перемасштабировании константа указывается вручную. Заметим, что аналогичная идея нормализации пакетов данных лежит в основе современной техники глубокого обучения, называемой BatchNormalization.
В данном разделе мы рассмотрим несколько трансформаций, зависимых от данных, явным образом использующих графическую природу данных. Эти типы трансформации часто используются в процедурах дополнения данных.
Этот вид трансформации вращает изображение в определенном направлении (по или против часовой стрелки).
Параметр, позволяющий осуществлять вращение, называется rotation_range. Он указывает на диапазон в градусах, из которого случайным образом с равномерным распределением выбирается угол поворота. Следует отметить, что при вращении размер изображения не меняется. Таким образом, некоторые участки изображения могут быть обрезаны, а некоторые заполнены.
![](https://habrastorage.org/webt/vh/d8/s-/vhd8s-j4ojpyqrcat9rc3jzegm4.png)
Режим заполнения устанавливается при помощи параметра fill_mode. Он поддерживает различные способы заполнения, но здесь мы в качестве примера используем метод constant.
![](https://habrastorage.org/webt/t3/bo/4f/t3bo4fjn4tm96ergzw_ucahbouq.jpeg)
Этот вид трансформации сдвигает изображение в определенном направлении по горизонтальной оси (влево или вправо).
![](https://habrastorage.org/webt/gw/j9/bh/gwj9bh9j8viw1eif_x1vpkpbh_s.png)
Размер сдвига может определяться при помощи параметра width_shift_range и измеряется как часть полной ширины изображения.
![](https://habrastorage.org/webt/re/pe/65/repe65wt5ekksezxikypdtglpyc.jpeg)
Сдвигает изображение по вертикальной оси (вверх или вниз). Параметр, управляющий диапазоном сдвига называется генератором height_shift и также измеряется как часть полной высоты изображения.
Преобразование обрезки или обрезка смещает каждую точку в вертикальном направлении на величину, пропорциональную расстоянию от этой точки до края изображения. Отметим, что в общем случае направление не обязано быть вертикальным и является произвольным.
![](https://habrastorage.org/webt/mc/9w/0-/mc9w0-6flw4ewwlqyrs9gczpzlg.jpeg)
Параметр, управляющий смещением, называется shear_range и соответствует углу отклонения (в радианах) между горизонтальной линией на исходном изображении и изображением (в математическом смысле) этой линии на трансформированном изображении.
![](https://habrastorage.org/webt/bd/ut/i6/bduti6xglamlgqkaiv2ck2ef5he.png)
Этот вид трансформации осуществляет приближение или удаление исходного изображения. Параметр zoom_range управляет коэффициентом приближения.
![](https://habrastorage.org/webt/ij/nj/4l/ijnj4ln-l8raqleq-lbmwkumewc.jpeg)
Например, если zoom_range равен 0,5, то коэффициент приближения будет выбран из диапазона [0,5, 1,5].
![](https://habrastorage.org/webt/wn/vd/zo/wnvdzog-l-clsbupmziwcszoh9o.jpeg)
![](https://habrastorage.org/webt/qj/xr/r9/qjxrr9l5ktaubq2t_9cagdp7es0.png)
Переворачивает изображение относительно вертикальной оси. Его можно включить или выключить при помощи параметра horizontal_flip.
![](https://habrastorage.org/webt/fb/im/g1/fbimg1quzp5t83brbi8ztfv42jk.jpeg)
Переворачивает изображение относительно горизонтальной оси. Параметр vertical_flip (типа Boolean) управляет наличием или отсутствием данной трансформации.
Применим все описанные виды трансформаций дополнения одновременно и посмотрим, что из этого получится. Напомним, что параметры для всех трансформаций выбираются случайным образом из определенного диапазона; таким образом, мы должны получить набор образцов со значительной степенью разнообразия.
Инициируем ImageDataGenerator со всеми доступными параметрами и проверим на изображении красного гидранта.
![](https://habrastorage.org/webt/05/tg/el/05tgelnzqacfl5gkwkpgzrrr8qe.jpeg)
Заметим, что режим наполнения constant использовался лишь для лучшей визуализации. Теперь будем использовать более продвинутый режим заполнения, называемый nearest; этот режим назначает пустому пикселю цвет ближайшего к нему существующего пикселя.
![](https://habrastorage.org/webt/l-/qv/i5/l-qvi5bbsdqfjdcfheqqzjhrpzu.jpeg)
В данной статье представлен обзор основных техник предобработки изображений, таких как: масштабирование, нормализация, вращение, сдвиг и обрезка. Также продемонстрирована реализация этих техник трансформации при помощи Keras и внедрение их в процесс глубокого обучения как технически (класс ImageDataGenerator), так и идеологически (дополнение данных).
- Очистка данных. Предположим, что на изображениях присутствуют некоторые артефакты. Чтобы облегчить обучение модели, артефакты необходимо удалить на этапе предобработки.
- Дополнение данных. Иногда небольших наборов данных недостаточно для качественного глубокого обучения модели. Подход с дополнением данных весьма полезен при решении этой проблемы. Это процесс трансформации каждого образца данных различными способами и добавления к набору данных таких измененных образцов. Таким образом можно повысить эффективный размер набора данных.
Рассмотрим некоторые возможные методы трансформации при предобработке и их реализацию через Keras.
![](https://habrastorage.org/webt/l-/qv/i5/l-qvi5bbsdqfjdcfheqqzjhrpzu.jpeg)
Данные
В этой и следующих статьях будет использован набор данных для анализа эмоциональной окраски изображений. Он содержит 1500 примеров изображений, разделенных на два класса — положительные и отрицательные. Рассмотрим некоторые примеры.
![](https://habrastorage.org/webt/mu/rf/_g/murf_geogu_lj6a9q4xoa4pn3si.jpeg)
Отрицательные примеры
![](https://habrastorage.org/webt/nn/1_/vt/nn1_vtdtnxjci9mlhxxh25f4c5a.jpeg)
Положительные примеры
Трансформации по очистке
Теперь рассмотрим набор возможных трансформаций, обычно применяемых для очистки данных, их внедрение и влияние на изображения.
Все фрагменты кода можно найти в книге Preprocessing.ipynb.
Перемасштабирование
Изображения, как правило, хранятся в формате RGB (Red Green Blue). В этом формате изображение представлено трехмерным (или трехканальным) массивом.
![](https://habrastorage.org/webt/gk/bw/4w/gkbw4wlsomht08_atrneom6ugru.jpeg)
RGB-разложение изображения. Диаграмма взята с Wikiwand
Одно измерение используется для каналов (красного, зеленого и синего цветов), два других представляют местоположение. Таким образом, каждый пиксель кодируется тремя числами. Каждое число обычно хранится в виде 8-битового беззнакового целого типа (от 0 до 255).
Перемасштабирование — это операция, изменяющая числовой диапазон данных простым делением на заранее определенную константу. В глубоких нейронных сетях может потребоваться ограничить входные данные диапазоном от 0 до 1 из-за возможного переполнения, вопросов оптимизации, стабильности и т. п.
Например, перемасштабируем наши данные с диапазона [0; 255] в диапазон [0; 1]. Здесь и далее будем использовать класс Keras ImageDataGenerator, позволяющий выполнять все трансформации «на лету».
Создадим два экземпляра этого класса: один для трансформированных данных, другой для исходных:
![](https://habrastorage.org/webt/pf/0_/hv/pf0_hvqdqdqsqtwwaqw5nznhrhc.png)
(или для данных по умолчанию). Необходимо лишь указать константу масштабирования. Более того, класс ImageDataGenerator позволяет направлять данные потоком напрямую из папки на жестком диске, используя метод flow_from_directory.
Все параметры можно найти в документации, но основными параметрами являются: путь к потоку и целевой размер изображения (если изображение не соответствует целевому размеру, генератор его просто обрезает или наращивает). Наконец, получим образец из генератора и рассмотрим результаты.
Визуально оба изображения идентичны, но причина этого в том, что инструменты Python* автоматически перемасштабируют изображения
![](https://habrastorage.org/webt/5s/o6/9o/5so69otm8hi5utmf09himqmoigm.jpeg)
в диапазон по умолчанию, чтобы их можно было отображать на экране. Рассмотрим сырые данные (массивы). Как видно, сырые массивы отличаются ровно в 255 раз.
Перевод в оттенки серого
Еще один вид трансформации, который может оказаться полезным — это перевод в оттенки серого, который переводит цветное RGB-изображение в изображение, в котором все цвета представлены оттенками серого. Обычная обработка изображений может использовать перевод в оттенки серого в комбинации с последующим заданием порога. Эта пара трансформаций может отбрасывать шумные пиксели и определять формы на изображении. Сегодня все эти операции выполняются сверточными нейронными сетями (Convolutional Neural Network, CNN), но перевод в оттенки серого как этап предобработки по-прежнему может быть полезным. Запустим этот шаг в Keras с тем же классом генератора.
![](https://habrastorage.org/webt/uh/ay/li/uhaylivvkd5aznb1k-l9hzeeabw.jpeg)
Здесь мы создаем только один экземпляр класса и берем из него два разных генератора. Второй генератор устанавливает параметр color_mode в “grayscale” (значение по умолчанию “RGB”).
Центрирование образцов
Мы уже видели, что значения необработанных данных находятся в диапазоне от 0 до 255. Таким образом, один образец представляет собой трехмерный массив чисел от 0 до 255. В свете принципов стабильности оптимизации (избавляться от проблемы исчезающих или насыщающих значений) может потребоваться нормализовать набор данных таким образом, чтобы среднее значение каждого образца данных равнялось 0.
![](https://habrastorage.org/webt/eh/6s/jg/eh6sjgccinzuviy9vrzklcbzqas.jpeg)
Для этого необходимо рассчитать среднее значение по всему образцу и вычесть его из каждого числа в данном образце.
В Keras это делается при помощи параметра samplewise_center.
Нормализация СКО образцов
Данный этап предобработки основан на той же идее, что и центрирование образцов, но вместо установки среднего в 0 от устанавливает значение среднеквадратичного отклонения в 1.
![](https://habrastorage.org/webt/_e/aq/4k/_eaq4kpjy1ox6l70homarb0tlxe.png)
Нормализация СКО управляется параметром samplewise_std_normalization. Следует отметить, что эти два способа нормализации образцов часто используются совместно.
Данная трансформация может применяться в моделях глубокого обучения для повышения стабильности оптимизации путем снижения влияния проблемы взрывающихся градиентов.
Центрирование признаков
В двух предыдущих разделах использовалась техника нормализации, рассматривающая каждый отдельный образец данных. Существует альтернативный подход к процедуре нормализации. Рассмотрим каждое число в массиве изображения как признак. Тогда каждое изображение представляет собой вектор признаков. В наборе данных много таких векторов; следовательно, мы можем рассматривать их в виде некоторого неизвестного распределения. Это распределение является многопараметрическим, и размерность его будет равна количеству признаков, т. е. ширина ? высота ? 3. Хотя истинное распределение данных неизвестно, можно попытаться нормализовать его путем вычитания среднего значения распределения. Следует отметить, что среднее значение представляет собой вектор той же размерности, то есть, тоже является изображением. Другими словами, мы усредняем по всему набору данных, а не по одному образцу.
Существует специальный параметр Keras под названием featurewise_centering, но, к сожалению, по состоянию на август 2017 года в его реализации была ошибка; поэтому реализуем его самостоятельно. Сначала считаем весь набор данных в память (мы можем себе это позволить, так как имеем дело с небольшим набором данных). Мы сделали это, установив размер пакета равным размеру набора данных. Затем рассчитаем среднее изображение по всему набору данных и, наконец вычтем его из тестового изображения.
![](https://habrastorage.org/webt/sm/wn/of/smwnofa7izsr-kyhn2r8mwab-dw.jpeg)
Нормализация СКО признаков
Идея нормализации среднеквадратичного отклонения в точности та же, что и идея центрирования. Единственная разница состоит в том, что вместо вычитания среднего значения мы производим деление на значение среднеквадратичного отклонения. Визуально результат не сильно отличается. То же происходило
![](https://habrastorage.org/webt/im/j-/ge/imj-gegeoxxc_1dsd6km4vshs9e.png)
при перемасштабировании, поскольку нормализация СКО есть не что иное как перемасштабирование с определенным образом рассчитанной константой, а при простом перемасштабировании константа указывается вручную. Заметим, что аналогичная идея нормализации пакетов данных лежит в основе современной техники глубокого обучения, называемой BatchNormalization.
![](https://habrastorage.org/webt/lf/lc/rg/lflcrgjs6a42y7u1vvtna5nz8jy.jpeg)
Трансформации с дополнением
В данном разделе мы рассмотрим несколько трансформаций, зависимых от данных, явным образом использующих графическую природу данных. Эти типы трансформации часто используются в процедурах дополнения данных.
Вращение
Этот вид трансформации вращает изображение в определенном направлении (по или против часовой стрелки).
Параметр, позволяющий осуществлять вращение, называется rotation_range. Он указывает на диапазон в градусах, из которого случайным образом с равномерным распределением выбирается угол поворота. Следует отметить, что при вращении размер изображения не меняется. Таким образом, некоторые участки изображения могут быть обрезаны, а некоторые заполнены.
![](https://habrastorage.org/webt/vh/d8/s-/vhd8s-j4ojpyqrcat9rc3jzegm4.png)
Режим заполнения устанавливается при помощи параметра fill_mode. Он поддерживает различные способы заполнения, но здесь мы в качестве примера используем метод constant.
![](https://habrastorage.org/webt/t3/bo/4f/t3bo4fjn4tm96ergzw_ucahbouq.jpeg)
Горизонтальный сдвиг
Этот вид трансформации сдвигает изображение в определенном направлении по горизонтальной оси (влево или вправо).
![](https://habrastorage.org/webt/gw/j9/bh/gwj9bh9j8viw1eif_x1vpkpbh_s.png)
Размер сдвига может определяться при помощи параметра width_shift_range и измеряется как часть полной ширины изображения.
Вертикальный сдвиг
![](https://habrastorage.org/webt/re/pe/65/repe65wt5ekksezxikypdtglpyc.jpeg)
Сдвигает изображение по вертикальной оси (вверх или вниз). Параметр, управляющий диапазоном сдвига называется генератором height_shift и также измеряется как часть полной высоты изображения.
Обрезка
Преобразование обрезки или обрезка смещает каждую точку в вертикальном направлении на величину, пропорциональную расстоянию от этой точки до края изображения. Отметим, что в общем случае направление не обязано быть вертикальным и является произвольным.
![](https://habrastorage.org/webt/mc/9w/0-/mc9w0-6flw4ewwlqyrs9gczpzlg.jpeg)
Параметр, управляющий смещением, называется shear_range и соответствует углу отклонения (в радианах) между горизонтальной линией на исходном изображении и изображением (в математическом смысле) этой линии на трансформированном изображении.
Приближение/удаление
![](https://habrastorage.org/webt/bd/ut/i6/bduti6xglamlgqkaiv2ck2ef5he.png)
Этот вид трансформации осуществляет приближение или удаление исходного изображения. Параметр zoom_range управляет коэффициентом приближения.
![](https://habrastorage.org/webt/ij/nj/4l/ijnj4ln-l8raqleq-lbmwkumewc.jpeg)
Например, если zoom_range равен 0,5, то коэффициент приближения будет выбран из диапазона [0,5, 1,5].
![](https://habrastorage.org/webt/wn/vd/zo/wnvdzog-l-clsbupmziwcszoh9o.jpeg)
Горизонтальный переворот
![](https://habrastorage.org/webt/qj/xr/r9/qjxrr9l5ktaubq2t_9cagdp7es0.png)
Переворачивает изображение относительно вертикальной оси. Его можно включить или выключить при помощи параметра horizontal_flip.
Вертикальный переворот
![](https://habrastorage.org/webt/fb/im/g1/fbimg1quzp5t83brbi8ztfv42jk.jpeg)
Переворачивает изображение относительно горизонтальной оси. Параметр vertical_flip (типа Boolean) управляет наличием или отсутствием данной трансформации.
Комбинация
Применим все описанные виды трансформаций дополнения одновременно и посмотрим, что из этого получится. Напомним, что параметры для всех трансформаций выбираются случайным образом из определенного диапазона; таким образом, мы должны получить набор образцов со значительной степенью разнообразия.
Инициируем ImageDataGenerator со всеми доступными параметрами и проверим на изображении красного гидранта.
![](https://habrastorage.org/webt/05/tg/el/05tgelnzqacfl5gkwkpgzrrr8qe.jpeg)
Заметим, что режим наполнения constant использовался лишь для лучшей визуализации. Теперь будем использовать более продвинутый режим заполнения, называемый nearest; этот режим назначает пустому пикселю цвет ближайшего к нему существующего пикселя.
![](https://habrastorage.org/webt/l-/qv/i5/l-qvi5bbsdqfjdcfheqqzjhrpzu.jpeg)
Заключение
В данной статье представлен обзор основных техник предобработки изображений, таких как: масштабирование, нормализация, вращение, сдвиг и обрезка. Также продемонстрирована реализация этих техник трансформации при помощи Keras и внедрение их в процесс глубокого обучения как технически (класс ImageDataGenerator), так и идеологически (дополнение данных).