В этом примере показано, как применить байесовскую оптимизацию к глубокому обучению и найти оптимальные сетевые гиперпараметры и варианты обучения для сверточных нейронных сетей.
Для обучения глубокой нейронной сети необходимо указать архитектуру нейронной сети, а также варианты алгоритма обучения. Выбор и настройка этих гиперпараметров могут быть затруднены и требуют времени. Байесовская оптимизация - это алгоритм, хорошо подходящий для оптимизации гиперпараметров классификационных и регрессионных моделей. Байесовскую оптимизацию можно использовать для оптимизации недифференцируемых, прерывистых и трудоемких функций. Алгоритм внутренне поддерживает гауссову модель процесса целевой функции и использует оценки целевой функции для обучения этой модели.
В этом примере показано, как:
Загрузите и подготовьте набор CIFAR-10 данных для обучения сети. Этот набор данных является одним из наиболее широко используемых наборов данных для тестирования моделей классификации изображений.
Укажите переменные для оптимизации с помощью байесовской оптимизации. Эти переменные являются опциями обучающего алгоритма, а также параметрами самой архитектуры сети.
Определите целевую функцию, которая принимает значения переменных оптимизации в качестве входных данных, определяет архитектуру сети и варианты обучения, обучает и проверяет работу сети и сохраняет обученную сеть на диск. Целевая функция определяется в конце этого сценария.
Выполните байесовскую оптимизацию, минимизировав ошибку классификации в наборе проверки.
Загрузите лучшую сеть с диска и оцените ее на тестовом наборе.
В качестве альтернативы можно использовать байесовскую оптимизацию для поиска оптимальных вариантов обучения в Диспетчере экспериментов. Дополнительные сведения см. в разделе Настройка гиперпараметров эксперимента с помощью байесовской оптимизации.
Загрузите набор данных CIFAR-10 [1]. Этот набор данных содержит 60 000 изображений, и каждое изображение имеет размер 32 на 32 и три цветовых канала (RGB). Размер всего набора данных составляет 175 МБ. В зависимости от подключения к Интернету процесс загрузки может занять некоторое время.
datadir = tempdir; downloadCIFARData(datadir);
Загрузите набор данных CIFAR-10 как обучающие изображения и метки, а также протестируйте изображения и метки. Чтобы включить проверку сети, используйте 5000 тестовых образов для проверки.
[XTrain,YTrain,XTest,YTest] = loadCIFARData(datadir); idx = randperm(numel(YTest),5000); XValidation = XTest(:,:,:,idx); XTest(:,:,:,idx) = []; YValidation = YTest(idx); YTest(idx) = [];
Образец обучающих изображений можно просмотреть с помощью следующего кода.
figure; idx = randperm(numel(YTrain),20); for i = 1:numel(idx) subplot(4,5,i); imshow(XTrain(:,:,:,idx(i))); end
Выберите переменные для оптимизации с помощью байесовской оптимизации и укажите диапазоны для поиска. Также укажите, являются ли переменные целыми числами и нужно ли искать интервал в логарифмическом пространстве. Оптимизируйте следующие переменные:
Глубина сечения сети. Этот параметр управляет глубиной сети. Сеть имеет три секции, каждая с SectionDepth идентичные сверточные слои. Таким образом, общее количество сверточных слоев составляет 3*SectionDepth. Целевая функция позже в сценарии принимает число сверточных фильтров в каждом слое пропорционально 1/sqrt(SectionDepth). В результате количество параметров и требуемая величина вычисления для каждой итерации примерно одинаковы для различных глубин сечения.
Начальная скорость обучения. Наилучшая скорость обучения может зависеть от ваших данных, а также от сети, которую вы обучаете.
Стохастический градиентный импульс спуска. Импульс добавляет инерцию к обновлениям параметров, поскольку текущее обновление содержит вклад, пропорциональный обновлению в предыдущей итерации. Это приводит к более плавным обновлениям параметров и снижению шума, присущего стохастическому градиентному спуску.
L2 прочности регуляризации. Используйте регуляризацию для предотвращения переоборудования. Поиск пространства силы регуляризации, чтобы найти хорошую ценность. Увеличение объема данных и пакетная нормализация также помогают упорядочить работу сети.
optimVars = [
optimizableVariable('SectionDepth',[1 3],'Type','integer')
optimizableVariable('InitialLearnRate',[1e-2 1],'Transform','log')
optimizableVariable('Momentum',[0.8 0.98])
optimizableVariable('L2Regularization',[1e-10 1e-2],'Transform','log')];Создайте целевую функцию для байесовского оптимизатора, используя данные обучения и проверки в качестве входных данных. Целевая функция обучает сверточную нейронную сеть и возвращает ошибку классификации в наборе проверки. Эта функция определяется в конце этого сценария. Поскольку bayesopt использует частоту ошибок в наборе проверки для выбора лучшей модели, возможно, что окончательная сеть переопределяется в наборе проверки. Окончательная выбранная модель затем тестируется на независимом тестовом наборе для оценки ошибки обобщения.
ObjFcn = makeObjFcn(XTrain,YTrain,XValidation,YValidation);
Выполните байесовскую оптимизацию, минимизировав ошибку классификации в наборе проверки. Укажите общее время оптимизации в секундах. Чтобы наилучшим образом использовать силу байесовской оптимизации, необходимо выполнить не менее 30 объективных оценок функций. Для параллельного обучения сетей на нескольких графических процессорах установите 'UseParallel' значение для true. Если имеется один графический процессор, установите 'UseParallel' значение для trueТогда все работники разделяют этот GPU, и вы не получаете никакой скорости обучения и увеличиваете шансы GPU иссякнуть память.
После того, как каждая сеть закончит обучение, bayesopt распечатывает результаты в окне команд. bayesopt затем функция возвращает имена файлов в BayesObject.UserDataTrace. Целевая функция сохраняет обученные сети на диск и возвращает имена файлов в bayesopt.
BayesObject = bayesopt(ObjFcn,optimVars, ... 'MaxTime',14*60*60, ... 'IsObjectiveDeterministic',false, ... 'UseParallel',false);
|===================================================================================================================================| | Iter | Eval | Objective | Objective | BestSoFar | BestSoFar | SectionDepth | InitialLearn-| Momentum | L2Regulariza-| | | result | | runtime | (observed) | (estim.) | | Rate | | tion | |===================================================================================================================================| | 1 | Best | 0.197 | 955.69 | 0.197 | 0.197 | 3 | 0.61856 | 0.80624 | 0.00035179 |
| 2 | Best | 0.1918 | 790.38 | 0.1918 | 0.19293 | 2 | 0.074118 | 0.91031 | 2.7229e-09 |
| 3 | Accept | 0.2438 | 660.29 | 0.1918 | 0.19344 | 1 | 0.051153 | 0.90911 | 0.00043113 |
| 4 | Accept | 0.208 | 672.81 | 0.1918 | 0.1918 | 1 | 0.70138 | 0.81923 | 3.7783e-08 |
| 5 | Best | 0.1792 | 844.07 | 0.1792 | 0.17921 | 2 | 0.65156 | 0.93783 | 3.3663e-10 |
| 6 | Best | 0.1776 | 851.49 | 0.1776 | 0.17759 | 2 | 0.23619 | 0.91932 | 1.0007e-10 |
| 7 | Accept | 0.2232 | 883.5 | 0.1776 | 0.17759 | 2 | 0.011147 | 0.91526 | 0.0099842 |
| 8 | Accept | 0.2508 | 822.65 | 0.1776 | 0.17762 | 1 | 0.023919 | 0.91048 | 1.0002e-10 |
| 9 | Accept | 0.1974 | 1947.6 | 0.1776 | 0.17761 | 3 | 0.010017 | 0.97683 | 5.4603e-10 |
| 10 | Best | 0.176 | 1938.4 | 0.176 | 0.17608 | 2 | 0.3526 | 0.82381 | 1.4244e-07 |
| 11 | Accept | 0.1914 | 2874.4 | 0.176 | 0.17608 | 3 | 0.079847 | 0.86801 | 9.7335e-07 |
| 12 | Accept | 0.181 | 2578 | 0.176 | 0.17809 | 2 | 0.35141 | 0.80202 | 4.5634e-08 |
| 13 | Accept | 0.1838 | 2410.8 | 0.176 | 0.17946 | 2 | 0.39508 | 0.95968 | 9.3856e-06 |
| 14 | Accept | 0.1786 | 2490.6 | 0.176 | 0.17737 | 2 | 0.44857 | 0.91827 | 1.0939e-10 |
| 15 | Accept | 0.1776 | 2668 | 0.176 | 0.17751 | 2 | 0.95793 | 0.85503 | 1.0222e-05 |
| 16 | Accept | 0.1824 | 3059.8 | 0.176 | 0.17812 | 2 | 0.41142 | 0.86931 | 1.447e-06 |
| 17 | Accept | 0.1894 | 3091.5 | 0.176 | 0.17982 | 2 | 0.97051 | 0.80284 | 1.5836e-10 |
| 18 | Accept | 0.217 | 2794.5 | 0.176 | 0.17989 | 1 | 0.2464 | 0.84428 | 4.4938e-06 |
| 19 | Accept | 0.2358 | 4054.2 | 0.176 | 0.17601 | 3 | 0.22843 | 0.9454 | 0.00098248 |
| 20 | Accept | 0.2216 | 4411.7 | 0.176 | 0.17601 | 3 | 0.010847 | 0.82288 | 2.4756e-08 |
|===================================================================================================================================| | Iter | Eval | Objective | Objective | BestSoFar | BestSoFar | SectionDepth | InitialLearn-| Momentum | L2Regulariza-| | | result | | runtime | (observed) | (estim.) | | Rate | | tion | |===================================================================================================================================| | 21 | Accept | 0.2038 | 3906.4 | 0.176 | 0.17601 | 2 | 0.09885 | 0.81541 | 0.0021184 |
| 22 | Accept | 0.2492 | 4103.4 | 0.176 | 0.17601 | 2 | 0.52313 | 0.83139 | 0.0016269 |
| 23 | Accept | 0.1814 | 4240.5 | 0.176 | 0.17601 | 2 | 0.29506 | 0.84061 | 6.0203e-10 |

__________________________________________________________
Optimization completed.
MaxTime of 50400 seconds reached.
Total function evaluations: 23
Total elapsed time: 53088.5123 seconds
Total objective function evaluation time: 53050.7026
Best observed feasible point:
SectionDepth InitialLearnRate Momentum L2Regularization
____________ ________________ ________ ________________
2 0.3526 0.82381 1.4244e-07
Observed objective function value = 0.176
Estimated objective function value = 0.17601
Function evaluation time = 1938.4483
Best estimated feasible point (according to models):
SectionDepth InitialLearnRate Momentum L2Regularization
____________ ________________ ________ ________________
2 0.3526 0.82381 1.4244e-07
Estimated objective function value = 0.17601
Estimated function evaluation time = 1898.2641
Загрузите лучшую сеть, найденную в оптимизации, и ее точность проверки.
bestIdx = BayesObject.IndexOfMinimumTrace(end);
fileName = BayesObject.UserDataTrace{bestIdx};
savedStruct = load(fileName);
valError = savedStruct.valErrorvalError = 0.1760
Спрогнозировать метки тестового набора и вычислить тестовую ошибку. Отнесите классификацию каждого изображения в тестовом наборе к независимым событиям с определённой вероятностью успеха, что означает, что количество неправильно классифицированных изображений следует биномиальному распределению. Используется для вычисления стандартной ошибки (testErrorSE) и приблизительно 95% доверительный интервал (testError95CI) частоты ошибок обобщения. Этот метод часто называют методом Вальда. bayesopt определяет наилучшую сеть с помощью набора проверки, не подвергая сеть тестовому набору. Тогда возможно, что ошибка теста выше, чем ошибка проверки.
[YPredicted,probs] = classify(savedStruct.trainedNet,XTest); testError = 1 - mean(YPredicted == YTest)
testError = 0.1910
NTest = numel(YTest); testErrorSE = sqrt(testError*(1-testError)/NTest); testError95CI = [testError - 1.96*testErrorSE, testError + 1.96*testErrorSE]
testError95CI = 1×2
0.1801 0.2019
Постройте график матрицы путаницы для тестовых данных. Отображение точности и отзыва для каждого класса с помощью сводок столбцов и строк.
figure('Units','normalized','Position',[0.2 0.2 0.4 0.4]); cm = confusionchart(YTest,YPredicted); cm.Title = 'Confusion Matrix for Test Data'; cm.ColumnSummary = 'column-normalized'; cm.RowSummary = 'row-normalized';

Можно отобразить некоторые тестовые изображения вместе с их прогнозируемыми классами и вероятностями этих классов с помощью следующего кода.
figure idx = randperm(numel(YTest),9); for i = 1:numel(idx) subplot(3,3,i) imshow(XTest(:,:,:,idx(i))); prob = num2str(100*max(probs(idx(i),:)),3); predClass = char(YPredicted(idx(i))); label = [predClass,', ',prob,'%']; title(label) end
Определите целевую функцию для оптимизации. Эта функция выполняет следующие шаги:
Принимает значения переменных оптимизации в качестве входных данных. bayesopt вызывает целевую функцию с текущими значениями переменных оптимизации в таблице с каждым именем столбца, равным имени переменной. Например, текущее значение глубины сечения сети равно optVars.SectionDepth.
Определяет архитектуру сети и параметры обучения.
Осуществляет обучение и валидацию сети.
Сохранение обученной сети, ошибки проверки и параметров обучения на диск.
Возвращает ошибку проверки и имя файла сохраненной сети.
function ObjFcn = makeObjFcn(XTrain,YTrain,XValidation,YValidation) ObjFcn = @valErrorFun; function [valError,cons,fileName] = valErrorFun(optVars)
Определите архитектуру сверточной нейронной сети.
Добавьте заполнение к сверточным слоям, чтобы размер пространственных выходных данных всегда совпадал с размером входных данных.
Каждый раз при понижении пространственных размеров в два раза с использованием максимального количества слоев пула увеличивайте число фильтров в два раза. Это гарантирует, что объем вычислений, требуемых в каждом сверточном уровне, примерно одинаков.
Выберите число фильтров, пропорциональное 1/sqrt(SectionDepth), так что сети разной глубины имеют примерно одинаковое количество параметров и требуют примерно одинакового количества вычислений на одну итерацию. Увеличение количества параметров сети и общей гибкости сети numF. Чтобы обучить еще более глубокие сети, измените диапазон SectionDepth переменная.
Использовать convBlock(filterSize,numFilters,numConvLayers) для создания блока numConvLayers сверточные слои, каждый с указанным filterSize и numFilters фильтры, за каждым из которых следуют уровень нормализации пакета и уровень ReLU. convBlock определяется в конце этого примера.
imageSize = [32 32 3];
numClasses = numel(unique(YTrain));
numF = round(16/sqrt(optVars.SectionDepth));
layers = [
imageInputLayer(imageSize)
% The spatial input and output sizes of these convolutional
% layers are 32-by-32, and the following max pooling layer
% reduces this to 16-by-16.
convBlock(3,numF,optVars.SectionDepth)
maxPooling2dLayer(3,'Stride',2,'Padding','same')
% The spatial input and output sizes of these convolutional
% layers are 16-by-16, and the following max pooling layer
% reduces this to 8-by-8.
convBlock(3,2*numF,optVars.SectionDepth)
maxPooling2dLayer(3,'Stride',2,'Padding','same')
% The spatial input and output sizes of these convolutional
% layers are 8-by-8. The global average pooling layer averages
% over the 8-by-8 inputs, giving an output of size
% 1-by-1-by-4*initialNumFilters. With a global average
% pooling layer, the final classification output is only
% sensitive to the total amount of each feature present in the
% input image, but insensitive to the spatial positions of the
% features.
convBlock(3,4*numF,optVars.SectionDepth)
averagePooling2dLayer(8)
% Add the fully connected layer and the final softmax and
% classification layers.
fullyConnectedLayer(numClasses)
softmaxLayer
classificationLayer];Укажите параметры сетевого обучения. Оптимизируйте начальную скорость обучения, импульс SGD и силу регуляризации L2.
Укажите данные проверки и выберите 'ValidationFrequency' значение такое, что trainNetwork проверяет сеть один раз в эпоху. Тренируйтесь на фиксированное количество эпох и снижайте уровень обучения в 10 раз в течение последних эпох. Это уменьшает шум обновлений параметров и позволяет сетевым параметрам сбалансироваться ближе к минимуму потери функции.
miniBatchSize = 256;
validationFrequency = floor(numel(YTrain)/miniBatchSize);
options = trainingOptions('sgdm', ...
'InitialLearnRate',optVars.InitialLearnRate, ...
'Momentum',optVars.Momentum, ...
'MaxEpochs',60, ...
'LearnRateSchedule','piecewise', ...
'LearnRateDropPeriod',40, ...
'LearnRateDropFactor',0.1, ...
'MiniBatchSize',miniBatchSize, ...
'L2Regularization',optVars.L2Regularization, ...
'Shuffle','every-epoch', ...
'Verbose',false, ...
'Plots','training-progress', ...
'ValidationData',{XValidation,YValidation}, ...
'ValidationFrequency',validationFrequency);Увеличение данных используется для случайного разворота обучающих изображений вдоль вертикальной оси и их случайного перемещения до четырех пикселей по горизонтали и вертикали. Увеличение объема данных помогает предотвратить переоборудование сети и запоминание точных деталей обучающих изображений.
pixelRange = [-4 4];
imageAugmenter = imageDataAugmenter( ...
'RandXReflection',true, ...
'RandXTranslation',pixelRange, ...
'RandYTranslation',pixelRange);
datasource = augmentedImageDatastore(imageSize,XTrain,YTrain,'DataAugmentation',imageAugmenter);Обучение сети и составление графика хода обучения во время обучения. Закройте все обучающие графики после завершения обучения.
trainedNet = trainNetwork(datasource,layers,options);
close(findall(groot,'Tag','NNET_CNN_TRAININGPLOT_UIFIGURE'))
Оцените обученную сеть в наборе проверки, рассчитайте прогнозируемые метки изображения и вычислите частоту ошибок в данных проверки.
YPredicted = classify(trainedNet,XValidation);
valError = 1 - mean(YPredicted == YValidation);Создайте имя файла, содержащее ошибку проверки, и сохраните сеть, ошибку проверки и параметры обучения на диске. Целевая функция возвращает fileName в качестве выходного аргумента и bayesopt возвращает все имена файлов в BayesObject.UserDataTrace. Дополнительный требуемый выходной аргумент cons указывает зависимости между переменными. Нет переменных ограничений.
fileName = num2str(valError) + ".mat"; save(fileName,'trainedNet','valError','options') cons = []; end end
convBlock функция создает блок numConvLayers сверточные слои, каждый с указанным filterSize и numFilters фильтры, за каждым из которых следуют уровень нормализации пакета и уровень ReLU.
function layers = convBlock(filterSize,numFilters,numConvLayers) layers = [ convolution2dLayer(filterSize,numFilters,'Padding','same') batchNormalizationLayer reluLayer]; layers = repmat(layers,numConvLayers,1); end
[1] Крижевский, Алекс. «Изучение нескольких слоев элементов из крошечных изображений». (2009). https://www.cs.toronto.edu/~kriz/learning-features-2009-TR.pdf
Руководитель эксперимента | trainingOptions | trainNetwork | bayesopt (инструментарий статистики и машинного обучения)