Хотя концепция искусственной нейронной сети существует с 1950-х годов, только недавно у нас появилось оборудование, способное претворить теорию в жизнь. Предполагается, что нейронные сети способны имитировать любую непрерывную функцию. Но часто мы сталкиваемся с тем, что сети не работают на должном уровне, или требуется много времени, чтобы получить достойные результаты. К проблеме следует подходить статистически, а не интуитивно относиться к изменениям, которые должны быть внесены в архитектуру сети. Одним из первых шагов должна быть правильная предварительная обработка данных. Помимо средней нормализации и масштабирования, Анализ главных компонентов может быть полезен для ускорения обучения. Если размер данных уменьшен до такой степени, что все еще сохраняется надлежащая величина дисперсии, можно сэкономить место без значительного ущерба для качества данных. Кроме того, нейронные сети можно обучать быстрее, когда им предоставляется меньше данных.

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

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

Реализация Octave PCA будет:

function [U, S] = pca(X)
  [m, n] = size(X);
  U = zeros(n);
  S = zeros(n);
  Sigma=(1/m)*(X' * X);
  [U, S, V] =svd(Sigma);
end
function Z = projectData(X, U, K)
  Z = zeros(size(X, 1), K);
  U_reduce = U(:, 1:K);
  Z = X*U_reduce;
end
load ('<data>');                     % Loads the dataset into
                                     % variable X
[X_norm, mu, sigma] = Normalise(X);  % Performs normalisation
[U, S] = pca(X_norm);                % Performs PCA
K = input("Enter reduced dimension");
Z = projectData(X_norm, U, K);

Можно использовать PCA для визуализации данных, уменьшив их до 3D или 2D. Но более рекомендуемым методом было бы использование t-распределенного стохастического встраивания соседей, которое, в отличие от PCA, основано на распределении вероятностей. t-SNE пытается минимизировать разницу между условной вероятностью в высшем и уменьшенном измерениях.

Условная вероятность высока для точек, расположенных близко друг к другу (измеряемых их евклидовым расстоянием), и низка для единожды, которые находятся далеко друг от друга. Очки сгруппированы согласно полученному распределению. Дисперсия выбирается таким образом, чтобы точки в плотных областях имели меньшую дисперсию по сравнению с точками в разреженных областях.

Хотя в 1989 году Георгий Цибенко доказал, что нейронные сети даже с одним скрытым слоем могут аппроксимировать любую непрерывную функцию, может быть желательно ввести в сеть полиномиальные признаки более высокой степени, чтобы получить лучшие предсказания. Можно подумать об увеличении количества скрытых слоев. Фактически, количество слоев сети равно наивысшей степени полинома, который она должна быть способна представить. Хотя это также может быть достигнуто путем увеличения количества нейронов в существующих слоях, это потребует гораздо большего количества нейронов (и, следовательно, увеличения вычислительного времени) по сравнению с добавлением скрытых слоев в сеть, для аппроксимации функции с аналогичным количеством ошибка. С другой стороны, создание «глубоких» нейронных сетей приводит к нестабильным градиентам. Это можно разделить на две части, а именно: проблемы исчезающего и взрывающегося градиента.

Веса нейронной сети обычно инициализируются случайными значениями, имеющими среднее значение 0 и стандартное отклонение 1, которые примерно соответствуют распределению Гаусса. Это гарантирует, что большая часть весов находится между -1 и 1. Сигмоидальная функция дает нам максимальную производную 0,25 (когда вход равен нулю). Это, в сочетании с тем фактом, что веса принадлежат ограниченному диапазону, помогает гарантировать, что абсолютное значение их продукта также меньше 0,25. Градиент перцептрона состоит из множества таких членов, каждое из которых меньше 0,25. Чем глубже мы углубимся в слои, тем больше будет таких терминов, что приведет к проблеме исчезающего градиента.

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

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

Хотя сигмоид является популярным выбором, поскольку он сжимает входные данные между нулем и единицей, а также для его производной можно записать как функцию самой сигмоиды, нейронные сети, использующие ее, могут страдать от нестабильных градиентов. Более того, сигмовидные выходы не центрированы по нулю, все они положительны. Это означает, что все градиенты будут либо положительными, либо отрицательными, в зависимости от градиента единиц на следующем слое.

Наиболее рекомендуемая функция активации - Maxout. Maxout поддерживает два набора параметров. Используется тот, который дает более высокое значение, которое будет представлено в качестве входных данных для функции активации. Кроме того, веса могут варьироваться в соответствии с определенными входными условиями. Одна из таких попыток приводит к появлению дырявых выпрямленных линейных единиц. В этом особом случае градиент остается равным 1, когда входной сигнал больше 0, и получает небольшой отрицательный наклон, когда он меньше 0, пропорциональный входному значению.

Еще одна проблема, с которой сталкиваются нейронные сети, особенно когда они глубокие, - это внутренний ковариативный сдвиг. Статистическое распределение входных данных постоянно меняется по мере обучения. Это может вызвать значительные изменения в предметной области и, следовательно, снизить эффективность обучения. Решение проблемы - выполнять нормализацию для каждой мини-партии. Мы вычисляем среднее значение и дисперсию для всех таких пакетов, а не для всех данных. Входные данные нормализуются перед подачей почти на каждый скрытый слой. Этот процесс широко известен как пакетная нормализация. Применение пакетной нормализации также может помочь решить проблему исчезающих градиентов.

Регуляризацию можно улучшить, реализовав отсев. Часто определенные узлы в сети случайным образом отключаются от некоторых или всех уровней нейронной сети. Следовательно, на каждой итерации мы получаем новую сеть, а результирующая сеть (полученная в конце обучения) представляет собой их комбинацию. Это также помогает решить проблему переобучения.

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

Определенная диагностика может быть выполнена по параметрам, чтобы получить лучшую статистику. Здесь двумя важными факторами являются графики смещения и дисперсии. Их можно определить, построив кривые с выходными данными функции потерь (без регуляризации) для наборов данных обучения и перекрестной проверки в зависимости от количества примеров обучения.

На рисунке выше красная кривая представляет данные перекрестной проверки, а синий цвет был использован для обозначения набора обучающих данных. Первая цифра - это примерно та цифра, которую можно получить, когда архитектура страдает от сильного смещения. Это означает, что архитектура плохая, поэтому она дает довольно высокие ошибки даже на обучающем наборе данных. Добавление дополнительных функций в сеть (например, добавление большего количества скрытых слоев и, следовательно, введение полиномиальных функций) может быть полезным. Если он страдает от высокой дисперсии, это означает, что обученные параметры хорошо подходят для обучающего набора, но плохо работают при тестировании на «невидимых» данных (обучающий или проверочный набор). Это может быть связано с тем, что модель «слишком подходит» для обучающих данных. Получение большего количества данных могло бы сработать. В этом случае также может оказаться полезным уменьшение количества скрытых слоев в сети. Также может помочь игра с параметром регуляризации. Увеличение его значения может исправить высокую дисперсию, тогда как уменьшение должно помочь исправить высокую систематическую ошибку.

Реализация Octave построения диагностических кривых будет следующей:

function [error_train, error_val] = ...
    learningCurve(X, y, Xval, yval, lambda)

  m = size(X, 1);
  error_train = zeros(m, 1);
  error_val   = zeros(m, 1);

  for i = 1:m
    X_here = X(1:i,:);
    y_here = y(1:i);

    theta = train(X_here, y_here, lambda);
	    
    error_train(i) = LossFunction(X_here,y_here,theta,0);   
    error_val(i) = LossFunction(Xval,yval,theta,0);
   end;

end
lambda = input("Enter regularisation parameter");
[theta] = train(X_poly, y, lambda);
graphics_toolkit "gnuplot";
figure(1);
[error_train, error_val] = ...                               
    learningCurve(X_poly, y, X_poly_val, yval, lambda);                       plot(1:m, error_train, 1:m, error_val);
xlabel('Number of training examples');                    ylabel('Error');
legend('Train', 'Cross Validation');

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

Ссылки:
*
Машинное обучение, Стэнфордский университет
* Сверточные нейронные сети для визуального распознавания, Стэнфордский университет
* Майкл А. Нильсен,« Нейронные Сети и глубокое обучение , Determination Press, 2015»
* Пакетная нормализация - какого черта? (Автор Карл Н.)
* Резюме статьи → Сверточные сети на уровне символов для классификации текста (автор Нишант Нихил)
Репозиторий кода: https://github.com/americast/ML_ANg