Глубокое обучение Используя байесовую оптимизацию

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

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

Этот пример показывает как:

  • Загрузите и подготовьте набор данных 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

Выберите Variables to Optimize

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

  • Сетевая глубина раздела. Этот параметр управляет глубиной сети. Сеть имеет три раздела, каждого с 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, то все рабочие совместно используют тот графический процессор, и вы не получаете учебного ускорения и увеличиваете возможности графического процессора, исчерпывающего память.

После того, как каждая сеть закончила обучение, 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.19 |        2201 |        0.19 |        0.19 |            3 |     0.012114 |       0.8354 |    0.0010624 |
|    2 | Accept |      0.3224 |      1734.1 |        0.19 |     0.19636 |            1 |     0.066481 |      0.88231 |    0.0026626 |
|    3 | Accept |      0.2076 |      1688.7 |        0.19 |     0.19374 |            2 |     0.022346 |      0.91149 |    8.242e-10 |
|    4 | Accept |      0.1908 |      2167.2 |        0.19 |      0.1904 |            3 |      0.97586 |      0.83613 |   4.5143e-08 |
|    5 | Accept |      0.1972 |      2157.4 |        0.19 |     0.19274 |            3 |      0.21193 |      0.97995 |   1.4691e-05 |
|    6 | Accept |      0.2594 |      2152.8 |        0.19 |        0.19 |            3 |      0.98723 |      0.97931 |   2.4847e-10 |
|    7 | Best   |      0.1882 |      2257.5 |      0.1882 |     0.18819 |            3 |       0.1722 |       0.8019 |   4.2149e-06 |
|    8 | Accept |      0.8116 |      1989.7 |      0.1882 |     0.18818 |            3 |      0.42085 |      0.95355 |    0.0092026 |
|    9 | Accept |      0.1986 |        1836 |      0.1882 |     0.18821 |            2 |     0.030291 |      0.94711 |   2.5062e-05 |
|   10 | Accept |      0.2146 |      1909.4 |      0.1882 |     0.18816 |            2 |     0.013379 |       0.8785 |   7.6354e-09 |
|   11 | Accept |      0.2194 |        1562 |      0.1882 |     0.18815 |            1 |      0.14682 |      0.86272 |   8.6242e-09 |
|   12 | Accept |      0.2246 |      1591.2 |      0.1882 |     0.18813 |            1 |      0.70438 |      0.82809 |   1.0102e-06 |
|   13 | Accept |      0.2648 |      1621.8 |      0.1882 |     0.18824 |            1 |     0.010109 |      0.89989 |   1.0481e-10 |
|   14 | Accept |      0.2222 |        1562 |      0.1882 |     0.18812 |            1 |      0.11058 |      0.97432 |   2.4101e-07 |
|   15 | Accept |      0.2364 |      1625.7 |      0.1882 |     0.18813 |            1 |     0.079381 |       0.8292 |   2.6722e-05 |
|   16 | Accept |        0.26 |      1706.2 |      0.1882 |     0.18815 |            1 |     0.010041 |      0.96229 |   1.1066e-05 |
|   17 | Accept |      0.1986 |      2188.3 |      0.1882 |     0.18635 |            3 |      0.35949 |      0.97824 |    3.153e-07 |
|   18 | Accept |      0.1938 |      2169.6 |      0.1882 |     0.18817 |            3 |     0.024365 |      0.88464 |   0.00024507 |
|   19 | Accept |      0.3588 |      1713.7 |      0.1882 |     0.18216 |            1 |     0.010177 |      0.89427 |    0.0090342 |
|   20 | Accept |      0.2224 |      1721.4 |      0.1882 |     0.18193 |            1 |      0.09804 |      0.97947 |   1.0727e-10 |
|===================================================================================================================================|
| Iter | Eval   | Objective   | Objective   | BestSoFar   | BestSoFar   | SectionDepth | InitialLearn-|     Momentum | L2Regulariza-|
|      | result |             | runtime     | (observed)  | (estim.)    |              | Rate         |              | tion         |
|===================================================================================================================================|
|   21 | Accept |      0.1904 |      2184.7 |      0.1882 |     0.18498 |            3 |     0.017697 |      0.95057 |   0.00022247 |
|   22 | Accept |      0.1928 |      2184.4 |      0.1882 |     0.18527 |            3 |      0.06813 |       0.9027 |   1.3521e-09 |
|   23 | Accept |      0.1934 |      2183.6 |      0.1882 |      0.1882 |            3 |     0.018269 |      0.90432 |    0.0003573 |
|   24 | Accept |       0.303 |      1707.9 |      0.1882 |     0.18809 |            1 |     0.010157 |      0.88226 |   0.00088737 |
|   25 | Accept |       0.194 |      2189.1 |      0.1882 |     0.18808 |            3 |     0.019354 |      0.94156 |   9.6197e-07 |
|   26 | Accept |      0.2192 |      1752.2 |      0.1882 |     0.18809 |            1 |      0.99324 |      0.91165 |   1.1521e-08 |
|   27 | Accept |      0.1918 |        2185 |      0.1882 |     0.18813 |            3 |      0.05292 |       0.8689 |   1.2449e-05 |

__________________________________________________________
Optimization completed.
MaxTime of 50400 seconds reached.
Total function evaluations: 27
Total elapsed time: 51962.3666 seconds.
Total objective function evaluation time: 51942.8833

Best observed feasible point:
    SectionDepth    InitialLearnRate    Momentum    L2Regularization
    ____________    ________________    ________    ________________

         3               0.1722          0.8019        4.2149e-06   

Observed objective function value = 0.1882
Estimated objective function value = 0.18813
Function evaluation time = 2257.4627

Best estimated feasible point (according to models):
    SectionDepth    InitialLearnRate    Momentum    L2Regularization
    ____________    ________________    ________    ________________

         3               0.1722          0.8019        4.2149e-06   

Estimated objective function value = 0.18813
Estimated function evaluation time = 2166.2402

Оцените итоговую сеть

Загрузите лучшую сеть, найденную в оптимизации и ее точности валидации.

bestIdx = BayesObject.IndexOfMinimumTrace(end);
fileName = BayesObject.UserDataTrace{bestIdx};
savedStruct = load(fileName);
valError = savedStruct.valError
valError = 0.1882

Предскажите метки набора тестов и вычислите тестовую ошибку. Обработайте классификацию каждого изображения в наборе тестов как независимые события с определенной вероятностью успеха, что означает, что количество неправильно классифицированных изображений следует за биномиальным распределением. Используйте это, чтобы вычислить стандартную погрешность (testErrorSE) и аппроксимированный 95%-й доверительный интервал (testError95CI) коэффициента ошибок обобщения. Этот метод часто называется Вальдовым методом. bayesopt определяет лучшую сеть с помощью набора валидации, не подвергая сеть набору тестов. Затем возможно, что тестовая ошибка выше, чем ошибка валидации.

[YPredicted,probs] = classify(savedStruct.trainedNet,XTest);
testError = 1 - mean(YPredicted == YTest)
testError = 0.1864
NTest = numel(YTest);
testErrorSE = sqrt(testError*(1-testError)/NTest);
testError95CI = [testError - 1.96*testErrorSE, testError + 1.96*testErrorSE]
testError95CI = 1×2

    0.1756    0.1972

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

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

Целевая функция для оптимизации

Задайте целевую функцию для оптимизации. Эта функция выполняет следующие шаги:

  1. Принимает значения переменных оптимизации как входные параметры. bayesopt вызывает целевую функцию с текущими значениями переменных оптимизации в таблице с каждым именем столбца, равным имени переменной. Например, текущим значением сетевой глубины раздела является optVars.SectionDepth.

  2. Задает сетевую архитектуру и опции обучения.

  3. Train и подтверждает сеть.

  4. Сохраняет обучивший сеть, ошибку валидации и опции обучения к диску.

  5. Возвращает ошибку валидации и имя файла сохраненной сети.

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_FIGURE'))

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

        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] Krizhevsky, Алекс. "Изучая несколько слоев функций от крошечных изображений". (2009). https://www.cs.toronto.edu/~kriz/learning-features-2009-TR.pdf

Смотрите также

| |

Похожие темы