Рубрики
Без рубрики

Предварительная обработка для глубокого обучения: от матрицы ковариации к улучшению изображения

Автор оригинала: FreeCodeCapm Team.

Адриен

Целью этого поста является переход от основ предварительной обработки данных к современным методам, используемым в глубоком обучении. Моя точка зрения в том, что мы можем использовать код (например, python/numpy), чтобы лучше понять абстрактные математические представления. Думать, кодируя! ?

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

Предварительная обработка Относится ко всем преобразованиям на необработанные данные, прежде чем он подается в изучение машины или алгоритма глубокого обучения. Например, обучение сверточной нейронной сети на необработанных изображениях, вероятно, приведет к плохой классификации спектаклей ( Pal & Sudeep, 2016 ). Предварительная обработка также важно ускорить обучение (например, методы центрирования и масштабирования, см. Lecun et al., 2012; см. 4.3 ).

Вот учебник этого урока:

1. Фон: В первой части мы получим некоторые напоминания о дисперсии и ковариации. Мы увидим, как генерировать и построить поддельные данные, чтобы лучше понять эти концепции.

2. Препроцессия: Во второй части мы увидим основы некоторых методов предварительной обработки, которые могут быть применены к любым видам данных – средняя нормализация , Стандартизация и Отбеливание Отказ

3. Отбеливание изображений: В третьей части мы будем использовать инструменты и концепции, полученные в 1. и 2. сделать особый вид отбеливания под названием Анализ нуля компонента (Zca). Его можно использовать для предварительной обработки изображений для глубокого обучения. Эта часть будет очень практичной и веселой ☃️!

Не стесняйтесь вилкой ноутбук, связанный с этим постом ! Например, проверьте фигуры матриц каждый раз, когда у вас возникнут сомнение.

1. История

А. Дисперсия и ковариация

Дисперсия переменной описывает, сколько значения распространяются. Ковариация – это мера, которая рассказывает количество зависимости между двумя переменными.

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

Ковариационная стоимость зависит от масштаба переменной, поэтому его трудно проанализировать. Можно использовать коэффициент корреляции, который легче интерпретировать. Коэффициент корреляции – это просто нормализованная ковариация.

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

Давайте просто проверим с формулой дисперсии:

с N Длина вектора, а среднее значение вектора. Например, дисперсия первого столбца вектора А является:

Это первая клетка нашей ковариационной матрицы. Второй элемент на диагонали соответствует дисперсии второго вектора столбца от А и так далее.

Примечание : векторы, извлеченные из матрицы А соответствовать столбцам А Отказ

Другие клетки соответствуют ковариации между двумя векторами столбец от А Отказ Например, ковариация между первым и третьим столбцом расположена в ковариационной матрице в качестве столбца 1 и строки 3 (или столбец 3 и строки 1).

Давайте проверим, что ковариация между первым и третьим колоннельным вектором А равно -2,67. Формула ковариации между двумя переменными Х и Y является:

Переменные Х и Y Первые и третий столбец векторы в последнем примере. Давайте разделим эту формулу, чтобы быть уверенным, что она Crystal Clear:

  1. Символ суммы ( σ ) означает, что мы будем инаправлять на элементах векторов. Начнем с первого элемента ( i = 1 ) и рассчитайте первый элемент Х минус среднее значение вектора Х Отказ

2. Умножьте результат с первым элементом Y минус среднее значение вектора Y Отказ

3. Повторяйте процесс для каждого элемента векторов и рассчитайте сумму всех результатов.

4. Разделите количество элементов в векторе.

Пример 1.

Давайте начнем с матрицы А :

Мы рассчитаем ковариацию между первым и третьим векторами столбец:

а также

X̄ = 3 , ȳ = 4 и n = 3 Итак, у нас есть:

Ок, отлично! Это ценность ковариационной матрицы.

Теперь простой способ Отказ С Numpy, ковариационная матрица может быть рассчитана с помощью функции NP.cov Отказ

Стоит отметить Что если вы хотите Numpy использовать столбцы в качестве векторов, параметр Rowvar = false должен быть использован. Также смещение = правда делится на N а не по N-1 Отказ

Давайте сначала создадим массив:

array([[1, 3, 5],       [5, 4, 1],       [3, 8, 6]])

Теперь мы рассчитаем ковариацию с помощью функции numpy:

array([[ 2.66666667, 0.66666667, -2.66666667],       [ 0.66666667, 4.66666667, 2.33333333],       [-2.66666667, 2.33333333, 4.66666667]])

Выглядит неплохо!

Нахождение ковариационной матрицы с точечным продуктом

Есть еще один способ вычислить ковариационную матрицу А Отказ Вы можете центрировать А Около 0. Среднее значение вектора вычтено из каждого элемента вектора, чтобы иметь вектор со средним значением 0. Он умножается со своим собственным транспонированием и делится на количество наблюдений.

Давайте начнем с реализации, а затем мы попытаемся понять связь с предыдущим уравнением:

Давайте проверим это на нашей матрице А :

array([[ 2.66666667, 0.66666667, -2.66666667],       [ 0.66666667, 4.66666667, 2.33333333],       [-2.66666667, 2.33333333, 4.66666667]])

Мы в конечном итоге с тем же результатом, что и раньше.

Объяснение просто. Точечный продукт между двумя векторами можно выразить:

Это верно, это сумма продуктов каждого элемента векторов:

Если N это количество элементов в наших векторах, и что мы делимся по N :

Вы можете отметить, что это не слишком далеко от формулы ковариации, которую мы видели ранее:

Единственное отличие состоит в том, что в формуле ковариации мы вычитаем среднее значение вектора от каждого из его элементов. Вот почему нам нужно центрировать данные, прежде чем делать точечный продукт.

Теперь, если у нас есть матрица А точечный продукт между А И его транспонирование даст вам новую матрицу:

Это ковариация матрицы!

B. Визуализируйте данные и ковариационные матрицы

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

Эта функция рассчитает ковариационную матрицу, как мы видели выше. Он создаст два подлома – один для ковариационной матрицы и один для данных. HeatMap () Функция из Морской Используется для создания градиентов цвета – небольшие значения будут окрашены в светло-зеленых и больших значениях в темно-синем. Мы выбрали одну из наших цветов палитры, но вы можете предпочесть другие цвета. Данные представлены в виде ScatterPlot.

C. Имитация данных

Неисправные данные

Теперь, когда у нас есть функция сюжета, мы создадим некоторые случайные данные для визуализации того, что может сказать нам ковариационную матрицу. Начнем с некоторых данных, нарисованных из обычного распространения с функцией Numpy NP.RANDOM.NOMMAL () Отказ

Эта функция нуждается в среднем, стандартное отклонение и количество наблюдений распределения в качестве ввода. Мы создадим две случайные переменные 300 наблюдений со стандартным отклонением 1. Первым будет иметь среднее значение 1 и второе среднее значение 2. Если мы случайным образом рисовали два набора 300 наблюдений от нормального распределения, оба вектора будут некоррелирован.

(300, 2)

Примечание 1 : Мы транспонируем данные с .T Потому что оригинальная форма – (2, 300) И мы хотим количества наблюдений, как строки (так с формой (300, 2) ).

Примечание 2 : Мы используем np.random.seed Функция для воспроизводимости. Такое же случайное число будет использоваться в следующий раз, когда мы запускаем ячейку.

Давайте проверим, как выглядит данные:

array([[ 2.47143516, 1.52704645],       [ 0.80902431, 1.7111124 ],       [ 3.43270697, 0.78245452],       [ 1.6873481 , 3.63779121],       [ 1.27941127, -0.74213763],       [ 2.88716294, 0.90556519],       [ 2.85958841, 2.43118375],       [ 1.3634765 , 1.59275845],       [ 2.01569637, 1.1702969 ],       [-0.24268495, -0.75170595]])

Приятно, у нас есть два колоночных вектора.

Теперь мы можем проверить, что распределения являются нормальными:

Выглядит неплохо!

Мы видим, что распределения имеют эквивалентные стандартные отклонения, а разные средства (1 и 2). Так что именно то, о чем мы просили.

Теперь мы можем построить наш набор данных и его ковариационную матрицу с нашей функцией:

Covariance matrix:[[ 0.95171641 -0.0447816 ] [-0.0447816 0.87959853]]

Мы видим на рассеянном рассеянии, что два размера некоррелированы. Обратите внимание, что у нас есть одно измерение со средним значением 1 (оси Y), а другая со средним количеством 2 (ось X).

Кроме того, ковариационная матрица показывает, что дисперсия каждой переменной очень большой (около 1), а ковариация колонн 1 и 2 очень маленькая (около 0). Поскольку мы гарантировали, что два вектора независимы, это согласовано. Противоположное не обязательно верно: ковариация 0 не гарантирует независимость (см. здесь ).

Коррелированные данные

Теперь давайте построим зависимые данные, указав один столбец с другой.

Covariance matrix:[[ 0.95171641 0.92932561] [ 0.92932561 1.12683445]]

Корреляция между двумя размерами видна на графике разброса. Мы видим, что линия может быть нарисована и используется для прогнозирования y от х и наоборот. Ковариационная матрица не диагональна (вне нулевых клеток вне диагонали). Это означает, что ковариация между размерами ненулена.

Замечательно! Теперь у нас есть все инструменты, чтобы увидеть различные методы предварительной обработки.

2. Предварительная обработка

А. Средняя нормализация

Средняя нормализация просто удаляет среднее из каждого наблюдения.

где X ‘ Является ли нормализованный набор данных Х это оригинальный набор данных, а это среднее значение Х Отказ

Средняя нормализация имеет влияние центрирования данных вокруг 0. Мы создадим функцию Центр () сделать это:

Давайте попробуем с матрицей B Мы создали ранее:

Before:
Covariance matrix:[[ 0.95171641 0.92932561] [ 0.92932561 1.12683445]]
After:
Covariance matrix:[[ 0.95171641 0.92932561] [ 0.92932561 1.12683445]]

Первый участок показывает снова оригинальные данные B И второй сюжет показывает центрированные данные (посмотрите на масштаб).

B. Стандартизация или нормализация

Стандартизация используется для размещения всех функций в одинаковом масштабе. Каждое измерение с нулевым центром разделена на его стандартное отклонение.

где X ‘ это стандартизированный набор данных, Х Оригинальный набор данных это среднее значение Х , и Σ это стандартное отклонение Х Отказ

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

Covariance matrix:[[ 0.95171641 0.83976242] [ 0.83976242 6.22529922]]

Мы видим, что масштабы х и y разные. Обратите внимание, что корреляция кажется меньше из-за различий в масштабах. Теперь давайте стандартизируем это:

Covariance matrix:[[ 1.          0.34500274] [ 0.34500274  1.        ]]

Выглядит неплохо. Вы можете видеть, что масштабы одинаковы, и что набор данных сосредоточен в соответствии с обеими осями.

Теперь посмотрите на ковариационную матрицу. Вы можете видеть, что дисперсия каждой координаты – верхняя левая ячейка и нижняя правая клетка – равна 1.

Эта новая ковариационная матрица на самом деле является корреляционной матрицей. Коэффициент корреляции Пирсона между двумя переменными ( C1 и C2 ) составляет 0,54220151.

C. Отбеливание

Отбеливание, или сферирование, данные означает, что мы хотим преобразовать его, чтобы иметь ковариационную матрицу, которая является матрицей идентификатора – 1 в диагонали и 0 для других ячеек. Это называется отбеливание в отношении белого шума.

Вот более подробную информацию о матрице личности.

Отбеливание немного сложнее, чем другая предварительная обработка, но теперь у нас есть все инструменты, которые нам нужно сделать это. Это включает в себя следующие шаги:

  • Нулевой центр данных
  • Декорреляция данных
  • Rescale данные

Давайте снова возьмем C и попробуйте сделать эти шаги.

  1. Нулевое центрирование

Это относится к нормализации ( 2. A ). Проверьте для получения подробной информации о Центр () функция.

Covariance matrix:[[ 0.95171641  0.83976242] [ 0.83976242  6.22529922]]

2. декоррелита

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

Левый участок показывает коррелированные данные. Например, если вы возьмете точку данных с большой х ценность, шансы состоят в том, что связанные y Также будет довольно большой.

Теперь возьмите все точки данных и выполните вращение (возможно, примерно на 45 градусов против часовой стрелки. Новые данные, нанесенные справа, больше не коррелируются. Вы можете видеть, что большие и маленькие y y значения связаны с тем же типом x ценности.

Вопрос в том, как мы можем найти правильное вращение, чтобы получить некоррелированные данные?

На самом деле, именно то, что делают собственные векторы ковариационной матрицы. Они указывают на направление, где распространение данных на его максимуме:

Собственные векторы ковариационной матрицы дают вам направление, которое максимизирует дисперсию. Направление зеленый Линия – это то, где дисперсия максимальная. Просто посмотрите на самую маленькую и крупнейшую точку, проецируемую на этой строке – распространение большой. Сравните это с проекцией на Оранжевый Линия – распространение очень мало.

Для получения более подробной информации о eigendecomposition, см. Это пост Отказ

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

  • Рассчитайте ковариационную матрицу
  • Рассчитайте собственные векторы ковариационной матрицы
  • Примените матрицу собственных векторов к данным – это применит вращение Давайте упаковывать это в функцию:

Давайте попробуем декоррелировать нашу нулевую матрицу C Чтобы увидеть это в действии:

Covariance matrix:[[ 0.95171641 0.83976242] [ 0.83976242 6.22529922]]
Covariance matrix:[[ 5.96126981e-01 -1.48029737e-16] [ -1.48029737e-16 3.15205774e+00]]

Хороший! Это работает.

Мы можем видеть, что корреляция больше не здесь. Ковариационная матрица, теперь диагональная матрица, подтверждает, что ковариация между двумя измерениями равна 0.

3. Ссылка данных

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

Примечание : Мы добавляем небольшое значение (здесь 10 ^ -5), чтобы избежать разделения на 0.

Covariance matrix:[[ 9.99983225e-01 -1.06581410e-16] [ -1.06581410e-16 9.99996827e-01]]

Ура! Мы видим, что с ковариационной матрицей, что это все хорошо. У нас есть то, что выглядит как матрица личности – 1 по диагонали и 0 в других местах.

3. Отбеливание изображений

Мы увидим, как отбеливание может быть применено для предварительной обработки набора данных изображения. Для этого мы будем использовать статью Pal & Sudeep (2016) где они дают некоторые подробности о процессе. Эта методика предварительной обработки называется нулевой компонентной анализом (ZCA).

Проверьте газету, но вот тот результат, который они получили. Оригинальные изображения (слева) и изображения после ZCA (справа) отображаются.

Первые вещи в первую очередь. Мы загрузим изображения из CIFAR DataSet. Этот набор данных доступен из KERAS, и вы также можете скачать его здесь Отказ

(50000, 32, 32, 3)

Набор тренировок CIFAR10 DataSet содержит 50000 изображений. Форма X_train это (50000, 32, 32, 3) Отказ Каждое изображение составляет 32 пиксель на 32 пикселя, и каждый пиксель содержит 3 размера (R, G, B). Каждое значение является яркость соответствующего цвета от 0 до 255.

Мы начнем с выбора только подмножества изображений, скажем, 1000:

(1000, 32, 32, 3)

Так-то лучше. Теперь мы изменим массив, чтобы иметь плоские данные изображения с одним изображением на строку. Каждое изображение будет (1, 3072) потому что 32 х 32 х. Таким образом, массив, содержащий все изображения, будет (1000, 3072) :

(1000, 3072)

Следующим шагом является возможность увидеть изображения. Функция imshow () От MatPlotlib ( DOC ) можно использовать для отображения изображений. Это нужны изображения с формой (m x n x 3), поэтому давайте создадим функцию, чтобы изменить изображения и иметь возможность визуализировать их из формы (1, 3072) Отказ

Например, давайте построим один из изображений, которые мы загрузили:

Милый!

Теперь мы можем реализовать отбеливание изображений. Pal & Sudeep (2016) Опишите процесс:

1. Первым шагом является расписание изображений для получения диапазона [0, 1] путем разделения на 255 (максимальное значение пикселей).

Напомним, что формула для получения диапазона [0, 1]:

Но, здесь минимальное значение равно 0, так что это приводит к:

X.min() 0.0X.max() 1.0

Среднее вычитание: per-pixel или per – изображение?

Хорошо, круто, диапазон наших ценностей пикселей составляет от 0 до 1. Следующий шаг:

2. Вычтите среднее от всех изображений.

Будьте осторожны здесь.

Один из способов сделать это – взять каждое изображение и удалить среднее значение этого изображения из каждого пикселя ( jarrett et al., 2009 ). Интуиция этого процесса состоит в том, что он центрирует пиксели каждого изображения около 0.

Еще один способ сделать это – взять каждый из 3072 пикселей, которые у нас есть (32 на 32 пикселя для R, G и B) для каждого изображения и вычтите среднее значение этого пикселя по всем изображениям. Это называется средним вычитанием Per-Pixel. На этот раз каждый пиксель будет сосредоточен вокруг 0 Согласно всем изображениям Отказ Когда вы будете кормить свою сеть с изображениями, каждый пиксель считается другой особенностью. С помощью среднего вычитания PER-PIXEL мы сосредоточили каждую функцию (пиксель) около 0. Этот метод обычно используется (например, wan et al., 2013 ).

Теперь мы сделаем среднее вычитание Per-Pixel с наших 1000 изображений. Наши данные организованы с этими размерами (изображения, пиксели) Отказ Это было (1000, 3072) Поскольку есть 1000 изображений с 32 х 32-х пикселями. Таким образом, средний пиксель может быть получен из первой оси:

(3072,)

Это дает 3072 значения, которые являются количеством средств – один на пиксель. Давайте посмотрим, какие значения у нас есть:

array([ 0.5234 , 0.54323137, 0.5274 , …, 0.50369804, 0.50011765, 0.45227451])

Это около 0,5, потому что мы уже нормализовались до диапазона [0, 1]. Тем не менее, нам все еще нужно удалить среднее из каждого пикселя:

Просто чтобы убедить себя, что это сработало, мы вычислим среднее значение первого пикселя. Будем надеяться, что это 0.

array([ -5.30575583e-16, -5.98021632e-16, -4.23439062e-16, …, -1.81965554e-16, -2.49800181e-16, 3.98570066e-17])

Это не совсем 0, но достаточно маленькое, что мы можем считать, что это сработало!

Теперь мы хотим рассчитать ковариационную матрицу с нулевыми центрированными данными. Как мы видели выше, мы можем рассчитать его с NP.cov () Функция от Numpy.

Пожалуйста, обратите внимание на Что наши переменные являются нашими разными изображениями. Это подразумевает, что переменные являются рядами матрицы Х Отказ Просто чтобы быть понятным, мы расскажем эту информацию о Numpy с параметром Rowvar = True Даже если это Правда По умолчанию (см. DOC ):

Теперь волшебная часть – Мы рассчитаем особые значения и векторы ковариационной матрицы и используем их, чтобы повернуть наш набор данных. Посмотрите на Мой пост О сингулярном разложении ценностей (SVD), если вам нужно больше деталей.

Примечание : Это может занять немного времени с большим количеством изображений, и поэтому мы используем только 1000. В статье они использовали 10000 изображений. Не стесняйтесь сравнивать результаты в соответствии с тем, сколько изображений вы используете:

В статье они использовали следующее уравнение:

с U левые сингулярные векторы и S Особое значения ковариации первоначального нормализованного набора данных изображений и Х Нормализованный набор данных. ε это гиперпараметр, называемый коэффициентом отбеливания. Diag (а) Соответствует матрицу с вектором А как диагональ и 0 во всех других клетках.

Мы постараемся реализовать это уравнение. Давайте начнем с проверки размеров SVD:

(1000, 1000) (1000,)

S это вектор, содержащий 1000 элементов (сингулярные значения). Diag (ы) Таким образом, будет иметь форму (1000, 1000) с S Как диагональ:

[[ 8.15846654e+00 0.00000000e+00 0.00000000e+00 …, 0.00000000e+00 0.00000000e+00 0.00000000e+00] [ 0.00000000e+00 4.68234845e+00 0.00000000e+00 …, 0.00000000e+00 0.00000000e+00 0.00000000e+00] [ 0.00000000e+00 0.00000000e+00 2.41075267e+00 …, 0.00000000e+00 0.00000000e+00 0.00000000e+00] …,  [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 …, 3.92727365e-05 0.00000000e+00 0.00000000e+00] [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 …, 0.00000000e+00 3.52614473e-05 0.00000000e+00] [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 …, 0.00000000e+00 0.00000000e+00 1.35907202e-15]]
shape: (1000, 1000)

Проверьте эту часть:

Это также форма (1000, 1000) а также U и U ^ T Отказ Мы также видели, что Х имеет форму (1000, 3072) Отказ Форма X_ZCA Таким образом:

который соответствует форме исходного набора данных. Хороший.

У нас есть:

Неожиданно! Если вы посмотрите на бумагу, это не тот результат, который они показывают. На самом деле, это потому, что мы не перекаливали пиксели, и есть отрицательные значения. Для этого мы можем вернуть его в диапазон [0, 1] с той же техникой, что и выше:

min: 0.0max: 1.0

Ура! Замечательно! Похоже на изображение из бумаги. Как упоминалось ранее, они использовали 10000 изображений, а не 1000, как мы.

Чтобы увидеть различия в результатах в соответствии с количеством используемых изображений и эффект Hyper-Parameter ε Вот результаты для разных ценностей:

Результат отбеливания отличается в зависимости от количества изображений, которые мы используем, и значение Hyper-Parameter ε Отказ Изображение слева – это исходное изображение. В статье Pal & Sudeep (2016) Используются 10000 изображений и. Это соответствует нижнему левому изображению.

Это все!

Я надеюсь, что вы нашли что-то интересное в этой статье, вы можете прочитать его на моем Блог с латексным для математики вместе с другими статьями.

Вы также можете вилить ноутбук Jupyter на Github здесь Отказ

Рекомендации

К. Джарретт, К. Кавуккууглу, М. Ранзато и Ю. Лекун: «Какова лучшая многоэтапная архитектура для признания объекта?», «В 2009 году 12-я Международная конференция по компьютерному видению, 2009, с. 2146-2153.

А. Крижевский, «Обучение нескольких слоев особенностей от крошечных изображений», «Магистерский тезис, Университет Торонто, 2009».

Ю. А. Лекун, Л. Боттау, Г. Б. Орр и К.-р. Müller, “Эффективное backprop” в нейронных сетях: трюки торговли, Спрингер, Берлин, Гейдельберг, 2012, с. 9-48.

К. К. Пэл и К. С. Судип, “Предварительная обработка классификации изображений со стороны сверточных нейронных сетей”, в 2016 году Международная конференция IEEE о последних тенденциях в электронике, технологии информационных коммуникаций (RTEICT), 2016, с. 1778-1781.

L.

Отличные ресурсы и Qa

Wikipedia – отбеливание преобразования

CS231 – сверточные нейронные сети для визуального распознавания

Дастин Стансбери – умная машина

Некоторые подробности о ковариационной матрице

Итак – изображение отбеливания в Python

Средняя нормализация на изображение или от всего набора данных

Среднее вычитание – все изображения или на изображение?

Почему центрирование важно – см. Раздел 4.3

Kaggle Kernel на ZCA

Как ZCA реализован в KERAS