СОДЕРЖАНИЕ
1 Практическое задание. 4
2 Основной файл. 12
3 Вычисление градиента сигмоиды.. 12
4 Инициализация весовых коэффициентов случайными величинами 13
5 Функция вычисления качества обучения (значения функции стоимости) и градиентов, для градиентного спуска. 18
6 Результаты работы программы.. 18
Практическое задание
Дана обучающая выборка, состоящая из 5 000 обучающих пар (файл ex4data1.mat). Каждая обучающая пара представляет собой входной вектор и метку класса (желаемый выход нейронной сети). Входным вектором является изображение рукописной цифры, размером 20×20 точек, «вытянутое» в один вектор-столбец размерностью равной 20×20 = 400.
Рисунок 1 – Пример входных данных
Дан также набор файлов, содержащих вспомогательные функции, которые позволят быстро проверить результат
· ex4.m - основной запускаемый файл, который вызывает реализованные вами функции.
· Fmincg.m - функция, реализующая метод градиентного спуска (метод сопряженных градиентов).
|
|
· sigmoid.m - функция, вычисляющая сигмоид (поэлементно для матриц).
· computeNumericalGradient.m - вычисление градиента методом конечных разностей.
· checkNNGradients.m - проверка правильности вычисления градиентов методом обратного распространения ошибки.
· debugInitializeWeights.m - функция задания весовых коэффициентов (для отладки), пояснения в файле.
· predict.m - функция, при помощи которой, вычисляется отклик сети на поданный входной вектор.
И набор файлов, содержащих заготовки функций, которые необходимо реализовать самостоятельно:
· sigmoidGradient.m - функция вычисления градиента сигмоидной функции.
· nnCostFunction.m - функция вычисления качества обучения (значения функции стоимости) и градиентов, для градиентного спуска.
Также дан файл randInitializeWeights.m для ознакомления с принципом инициализации весовых коэффициентов малыми случайными величинами.
Основной файл
%% Задание "Обучение многослойной нейронной сети методом обратного распространения ошибки"
% Инструкции
% ------------
%
% Этот файл, и файлы не перечисленные в списке,
% приведенном ниже, является вспомогательными,
% их редактировать не нужно.
%
% В ходе работы Вам необходимо завершить код
% функций, расположенный в файлах:
%
% sigmoidGradient.m
% randInitializeWeights.m (уже заполнена, разобраться как работает!)
% nnCostFunction.m
%
%% Инициализация
clear; close all; clc
%% Установка параметров, используемых в задании
% Размер изображения одной цифры 20x20, таким образом,
% размерность входного вектора равна 20*20=400.
input_layer_size = 400;
% Количество нейронов скрытого слоя равно 25.
% Устанавливается опытным путем, четкой методики на сегодняшний день нет.
|
|
hidden_layer_size = 25;
% Количество классов. В данном случае 10, по количеству цифр.
num_labels = 10;
% (цифра "0"б в данном задании имеет метку 10).
% (Метки на практике могут назначаться произвольно.)
%% =========== Часть 1. Загрузка и отображение загруженных данных. =============
% Вначале загрузим и отобразим обучающую выборку.
% Выборка представляет собой 5000 изображений рукописных цифр.
% Каждое изображение имеет размер 20 на 20 точек.
% Значения точек центрированы относительно нуля.
fprintf('Загрузка и отображение данных...\n')
% Загрузка данных (обучающих пар) из файла
% После загрузки в окружении появляются:
% X - матрица 5000х400, содержащая входные векторы. (5000 векторов размерности 400)
% y - вектор 5000х1 меток классов. Содержит ответ, к какому классу относится какой вектор.
load('ex4data1.mat');
m = size(X, 1);
% Выбираем 100 случайных входных векторов для отображения.
sel = randperm(size(X, 1));
sel = sel(1:100);
% Выводим их на экран.
displayData(X(sel,:));
fprintf('Программа на паузе. Нажмите клавишу для продолжения.\n');
pause;
%% ================ Часть 2. Загрузка параметров. ================
% В этой части необходимо загрузить заранее вычисленные
% параметры нейронной сети из файла. Эти параметры используются в следующей
% части для проверки правильности реализации вычисления функции стоимости.
fprintf('\nЗагрузка параметров нейронной сети из файла...\n')
% Загружаются матрицы весов Theta1 and Theta2
load('ex4weights.mat');
% "Разворачиваем" их в один вектор.
nn_params = [Theta1(:); Theta2(:)];
%% ================ Часть 3: Вычисление функции стоимости (Прямой проход) ================
% Вначале, Вам необходимо реализовать функцию вычисления стоимости
% для этого используется прямой проход по сети (вычисление выхода по заданным входам).
% Вам необходимо вписать недостающий код в файле nnCostFunction.m который возвращает значение переменной cost.
% После реализации, Вы можете проверить правильность решения, для отладочных параметров, заданных в этом файле,
% она должна быть примерно 0.287629.
%
% Вначале необходимо реализовать вычисление функции стоимости без регуляризации
% Регуляризация вводится в следующей части.
%
fprintf('\nПроверка функции стоимости (без регуляризации)...\n')
% Коэффициент регуляризации (в этой части установлен в ноль).
lambda = 0;
% Запуск на выполнение Вашей реализации функции вычисления стоимости.
J = nnCostFunction(nn_params, input_layer_size, hidden_layer_size,...
num_labels, X, y, lambda);
fprintf(['Значение стоимости (для загруженных ранее из файла ex4weights весовых коэффициентов): %f '...
'\n(это значение должно быть примерно равно 0.287629)\n'], J);
fprintf('\nПрограмма на паузе. Нажмите клавишу для продолжения.\n');
pause;
%% =============== Часть 4. Введение реализации. ===============
% После того, как Вы добились правильной работы функции вычисления стоимости без регуляризации,
% необходимо ввести регуляризацию.
%
fprintf('\nПроверка функции стоимости (с регуляризацией)... \n')
% Значение коэффициента регуляризации (примем равным единице).
% На практике устанавливается методом кроссвалидации или подбором.
lambda = 1;
J = nnCostFunction(nn_params, input_layer_size, hidden_layer_size,...
num_labels, X, y, lambda);
fprintf(['Значение стоимости (для загруженных ранее из файла ex4weights весовых коэффициентов):: %f '...
'\n(это значение должно быть примерно равно 0.383770)\n'], J);
fprintf('Программа на паузе. Нажмите клавишу для продолжения.\n');
pause;
%% ================ Часть 5. Градиент сигмоиды. ================
% Перед началом реализации функции обучения нейронной сети, необходимо
% реализовать функцию вычисления градиента сигмоидальной функции.
% Для этого Вам необходимо реализовать недостающий код в файле sigmoidGradient.m file.
%
fprintf('\nВычисление градиента сигмоиды...\n')
g = sigmoidGradient([1 -0.5 0 0.5 1]);
fprintf('Градиент сигмоиды вычисленный для [1 -0.5 0 0.5 1] должен быть примерно равен (0.196612 0.235004 0.250000 0.235004 0.196612):\n ');
|
|
fprintf('%f ', g);
fprintf('\n\n');
fprintf('Программа на паузе. Нажмите клавишу для продолжения.\n');
pause;
%% ================ Часть 6. Инициализация параметров. ================
% В этой части задания, Иы начнете реализовывать двуслойную нейронную сеть
% для распознавания рукописных цифр. Вам необходимо начать с реализации
% функции инициализации весовых коэффициентов сети малыми случайными
% значениями. (функция находится в файле randInitializeWeights.m)
fprintf('\nИнициализируются весовые коэффициенты нейронной сети...\n')
initial_Theta1 = randInitializeWeights(input_layer_size, hidden_layer_size);
initial_Theta2 = randInitializeWeights(hidden_layer_size, num_labels);
% "Развернем" весовые коэффициенты в один вектор
initial_nn_params = [initial_Theta1(:); initial_Theta2(:)];
%% =============== Часть 7. Реализация обучения сети методом обратного распространения ошибки ===============
% Как только функция вычисления стоимости совпала с нашей, Вам необходимо
% реализовать алгоритм обратного распространения ошибки. Ваи нужно
% дописать недостающий код в файле nnCostFunction.m так, чтобы он
% возвращал значения векторов частных производных (градиенты).
%
fprintf('\nПроверка реализации алгоритма обратного распространения ошибки... \n');
% Проверка правильности вычисления градиентов функцией checkNNGradients
checkNNGradients;
fprintf('\nПрограмма на паузе, нажмите клавишу для продолжения.\n');
pause;
%% =============== Часть 8. Реализация регуляризации. ===============
% Если алгоритм обратного распространения работает правильно, то
% необходимо приступить к реализации этого алгоитма с учетем
% регуляризации.
fprintf('\nПроверка работы алгоритма обратного распространения ошибки (с регуляризацией)... \n')
% Проверка правильности вычисления градиентов checkNNGradients
lambda = 3;
checkNNGradients(lambda);
% Также выведем отладочные значения costFunction
debug_J = nnCostFunction(nn_params, input_layer_size,...
hidden_layer_size, num_labels, X, y, lambda);
fprintf(['\n\nЗначение Cost для отладочных параметров (для lambda = 10): %f '...
'\n(значение должно быть примерно равно 0.576051)\n\n'], debug_J);
fprintf('Программа на паузе, нажмите клавишу для продолжения.\n');
|
|
pause;
%% =================== Часть 8. Обучение нейронной сети. ===================
% Вы реализовали весь необходимый для обучения нейронной сети код
% Для обучения нейронной сети мы будем использовать функцию "fmincg",
% являющуюся аналогом "fminfunc". Эти функции являются функциями
% оптимизации параметров. Эти функции требуют для своей работы функцию стоимости (минимизируемое значений)
% и вектор градиентов. Эти функции являются более эффективными аналогами
% метода градиентного спуска.
%
fprintf('\nTraining Neural Network... \n')
% После завершения задания попробуйте установить MaxIter на большее
% значение, посмотрите как меняется качество обучения сети.
options = optimset('MaxIter', 50);
% Попытайтесь поварьировать коэффициент регуляризации lambda
lambda = 1;
% Создание ссылки для вызова функции вычисления стоимости
costFunction = @(p) nnCostFunction(p,...
input_layer_size,...
hidden_layer_size,...
num_labels, X, y, lambda);
%Теперь, costFunction стал функцией, принимающей только один параметр аргумент
% (весовые коэффициенты).
[nn_params, cost] = fmincg(costFunction, initial_nn_params, options);
% Получим обратно Theta1 и Theta2 из nn_params
Theta1 = reshape(nn_params(1:hidden_layer_size * (input_layer_size + 1)),...
hidden_layer_size, (input_layer_size + 1));
Theta2 = reshape(nn_params((1 + (hidden_layer_size * (input_layer_size + 1))):end),...
num_labels, (hidden_layer_size + 1));
fprintf('Программа на паузе, нажмите любую клавишу.\n');
pause;
%% ================= Часть 9. Отображение весовых коэффициентов скрытого слоя. =================
% Теперь можно визуализировать "знания" нейронной сети
% отобразив скрытый слой мы можем посмотреть какие особенности ухватила сеть из наших данных.
fprintf('\nВизуализация сети... \n')
displayData(Theta1(:, 2:end));
fprintf('\nПрограмма на паузе, нажмите клавишу для продолжения.\n');
pause;
%% ================= Часть 10. Реализация функции получения прогноз сети. =================
% После того, как нейронная сеть обучена, мы можем использовать ее для
% классификации новых данных.
% Вы должны реализовать функцию "predict" (в файле predict.m) для того чтобы использовать
% нейросеть для классификации.
% Это позволит оценить качество обучения сети.
pred = predict(Theta1, Theta2, X);
fprintf('\nТочность классификации на обучающем множестве составляет: %f\n', mean(double(pred == y)) * 100);
Вычисление градиента сигмоиды
Функция этого файла возвращает градиент сигмоидной функции в точке z. Если z – матрица или вектор, тогда функция возвращает градиент для каждого элемента. Математически функция градиента сигмоиды выглядит следующим образом:
,
где – функция сигмоиды.
Программы файла sigmoidGradient.m:
function g = sigmoidGradient(z)
% вычисление производной сигмоиды
g = sigmoid(z).* (1 - sigmoid(z))
end