Обучите нейронную сеть ОДУ

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

Нейронное ОДУ [1] является операцией глубокого обучения, которая возвращает решение ОДУ. В частности, учитывая вход, нейронная операция ODE выводит числовое решение ОДУ y=f(t,y,θ) в течение периода времени (t0,t1) и начальное условие y(t0)=y0, где t и y обозначьте входные параметры функции ОДУ и θ набор настраиваемых параметров. Как правило, начальное условие y0 или сетевой вход или, как в случае этого примера, выхода другой операции глубокого обучения.

Увеличенная нейронная операция ODE [2] улучшает стандартное нейронное ОДУ путем увеличения входных данных с дополнительными каналами и затем отбрасывания увеличения после нейронной операции ODE. Опытным путем увеличенные нейронные ОДУ более устойчивы, делают вывод лучше и имеют более низкую вычислительную стоимость, чем нейронные ОДУ.

Этот пример обучает простую сверточную нейронную сеть с увеличенной нейронной операцией ODE.

Функция ОДУ может быть набором операций глубокого обучения. В этом примере модель использует блок свертки-tanh в качестве функции ОДУ:

Пример показывает, как обучить нейронную сеть, чтобы классифицировать изображения цифр с помощью увеличенной нейронной операции ODE.

Загрузите обучающие данные

Загрузите учебные изображения и метки с помощью digitTrain4DArrayData функция.

[XTrain,TTrain] = digitTrain4DArrayData;

Просмотрите количество классов обучающих данных.

classNames = categories(TTrain);
numClasses = numel(classNames)
numClasses = 10

Просмотрите некоторые изображения от обучающих данных.

numObservations = size(XTrain,4);
idx = randperm(numObservations,64);
I = imtile(XTrain(:,:,:,idx));
figure
imshow(I)

Задайте модель глубокого обучения

Задайте следующую сеть, которая классифицирует изображения.

  • Блок свертки-ReLU с 8 3х3 фильтрами шагом 2

  • Шаг увеличения, который конкатенирует массив нулей к входу, таким образом, что количество каналов удвоено

  • Нейронная операция ODE с функцией ОДУ, содержащей свертку-tanh, блокируется с 16 3х3 фильтрами

  • Для классификации выход, полностью операция connect размера 10 (количество классов) и softmax операция

Нейронная операция ODE выводит решение заданной функции ОДУ. В данном примере задайте блок свертки-tanh как функцию ОДУ.

Таким образом, задайте функцию ОДУ, данную y=f(t,y,θ), где f обозначает операцию свертки-tanh, y входные данные, и θ содержит настраиваемые параметры для операции свертки. В этом случае, переменная t не использовано.

Задайте и инициализируйте параметры модели

Задайте настраиваемые параметры для каждой из операций и включайте их в структуру. Используйте формат parameters.OperationName.ParameterName, где parameters структура, OperationName имя операции (например, "conv1"), и ParameterName имя параметра (например, "Веса"). Инициализируйте learnable веса слоя и смещения с помощью initializeGlorot и initializeZeros функции, взятые в качестве примера, соответственно. Функции, взятые в качестве примера, инициализации присоединены к этому примеру как к вспомогательным файлам. Чтобы получить доступ к этим функциям, откройте этот пример как live скрипт. Для получения дополнительной информации об инициализации настраиваемых параметров для функций модели, смотрите, Инициализируют Настраиваемые параметры для Функции Модели.

Инициализируйте структуру параметров.

parameters = struct;

Инициализируйте параметры для первого сверточного слоя. Задайте 8 3х3 фильтров. Если вы изменяете эти размерности, то необходимо вручную вычислить входной размер полностью операция connect для ее инициализации весов Glorot.

filterSize = [3 3];
numFilters = 8;

numChannels = size(XTrain,3);
sz = [filterSize numChannels numFilters];
numOut = prod(filterSize) * numFilters;
numIn = prod(filterSize) * numFilters;

parameters.conv1.Weights = initializeGlorot(sz,numOut,numIn);
parameters.conv1.Bias = initializeZeros([numFilters 1]);

Инициализируйте параметры для операции свертки, используемой в нейронной функции ОДУ. Поскольку шаг увеличения увеличивает входные данные с массивом нулей, количество входных каналов дано numFilters + numExtraChannels, где numExtraChannels количество каналов в увеличении. Точно так же, потому что модель отбрасывает каналы выхода нейронной операции ODE, соответствующей увеличению, операция свертки в нейронном ОДУ должна иметь (numChannels + numExtraChannels) фильтры, где numChannels желаемое количество выходных каналов.

Задайте то же количество фильтров как первый слой свертки и соответствующий размер увеличения.

numChannels = numFilters;
numExtraChannels = numFilters;

numFiltersAugmented = numChannels + numExtraChannels;
sz = [filterSize numFiltersAugmented numFiltersAugmented];

numOut = prod(filterSize) * numFiltersAugmented;
numIn = prod(filterSize) * numFiltersAugmented;

parameters.neuralode.Weights = initializeGlorot(sz,numOut,numIn);
parameters.neuralode.Bias = initializeZeros([numFiltersAugmented 1]);

Инициализируйте параметры для полностью операция connect. Чтобы инициализировать веса полностью операция connect с помощью инициализатора Glorot, сначала вычислите количество входных элементов к операции.

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

  • Первая свертка имеет 8 фильтров с "same" дополнение и шаг 2. Эта операция выходные параметры 14 14 отображает с 8 каналами.

  • Модель затем увеличивает данные с массивом с 8 каналами нулей. Эта операция выходные параметры 14 14 отображает с 16 каналами.

  • Нейронная операция ODE начинает операцию свертки с 16 фильтрами и "same" дополнение. Эта операция выходные параметры 14 14 отображает с 16 каналами.

  • Модель затем отбрасывает каналы, соответствующие увеличению. Эта операция выходные параметры 14 14 отображает с 8 каналами.

Это означает, что количество входных элементов к полностью операции connect 14*14*8=1568.

sz =  [14 14];
inputSize = prod(sz)*numChannels;
outputSize = numClasses;

sz = [outputSize inputSize];
numOut = outputSize;
numIn = inputSize;

parameters.fc1.Weights = initializeGlorot(sz,numOut,numIn);
parameters.fc1.Bias = initializeZeros([outputSize 1]);

Просмотрите структуру параметров.

parameters
parameters = struct with fields:
        conv1: [1×1 struct]
    neuralode: [1×1 struct]
          fc1: [1×1 struct]

Просмотрите параметры для нейронной операции ODE.

parameters.neuralode
ans = struct with fields:
    Weights: [3×3×16×16 dlarray]
       Bias: [16×1 dlarray]

Модель Define параметры Hyper

Задайте гиперпараметры для операций и включайте их в структуру. Используйте формат hyperparameters.OperationName.ParameterName где hyperparameters структура, OperationName имя операции (например, "neuralode") и ParameterName имя гиперпараметра (например, "tspan").

Инициализируйте структуру гиперпараметров.

hyperparameters = struct;

Для нейронного ОДУ задайте интервал интегрирования [0 0.1].

hyperparameters.neuralode.tspan = [0 0.1];

Задайте нейронную функцию ОДУ

Создайте функциональный odeModel, перечисленный в разделе ODE Function примера, который берет в качестве входа, который время ввело (неиспользованный), начальные условия и параметры функции ОДУ. Функция применяет операцию свертки, сопровождаемую tanh операцией к входным данным с помощью весов, и смещает данный параметрами.

Функция модели Define

Создайте функциональный model, перечисленный в разделе Model Function примера, который вычисляет выходные параметры модели глубокого обучения. Функциональный model берет в качестве входа параметры модели и входные данные. Функциональные выходные параметры предсказания для меток.

Функция градиентов модели Define

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

Задайте опции обучения

Задайте опции обучения. Обучайтесь с мини-пакетным размером 64 в течение 30 эпох.

miniBatchSize = 64;
numEpochs = 30;

Обучите модель

Обучите модель с помощью пользовательского учебного цикла.

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

dsXTrain = arrayDatastore(XTrain,IterationDimension=4);
dsTTrain = arrayDatastore(TTrain);
dsTrain = combine(dsXTrain,dsTTrain);

Создайте мини-пакетную очередь. Для каждого мини-пакета:

  • Используйте пользовательский мини-пакет, предварительно обрабатывающий функциональный preprocessMiniBatch, заданный в разделе Mini-Batch Preprocessing Function примера, чтобы преобразовать метки в одногорячие закодированные переменные.

  • Отформатируйте данные изображения с метками размерности "SSCB" (пространственный, пространственный, канал, пакет). По умолчанию, minibatchqueue объект преобразует данные в dlarray объекты с базовым типом single.

  • Отбросьте частичные мини-пакеты.

  • Обучайтесь на графическом процессоре, если вы доступны. По умолчанию, minibatchqueue объект преобразует каждый выход в gpuArray если графический процессор доступен. Используя графический процессор требует Parallel Computing Toolbox™ и поддерживаемого устройства графического процессора. Для получения информации о поддерживаемых устройствах смотрите Поддержку графического процессора Релизом (Parallel Computing Toolbox).

mbq = minibatchqueue(dsTrain, ...
    MiniBatchSize=miniBatchSize, ...
    MiniBatchFcn=@preprocessMiniBatch, ...
    MiniBatchFormat=["SSCB" "CB"]);

Инициализируйте скользящее среднее значение градиентов параметра и поэлементные квадраты градиентов, используемых оптимизатором Адама.

trailingAvg = [];
trailingAvgSq = [];

Инициализируйте учебный график.

figure
C = colororder;
lineLossTrain = animatedline(Color=C(2,:));
ylim([0 inf])
xlabel("Iteration")
ylabel("Loss")
grid on

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

  • Оцените градиенты модели с помощью dlfeval и modelGradients функции.

  • Обновите сетевые параметры с помощью adamupdate функция.

  • Обновите график процесса обучения.

iteration = 0;
start = tic;

% Loop over epochs.
for epoch = 1:numEpochs

    % Shuffle data.
    shuffle(mbq)

    % Loop over mini-batches.
    while hasdata(mbq)

        iteration = iteration + 1;

        [dlX,dlT] = next(mbq);

        % Evaluate the model gradients, state, and loss using dlfeval and the
        % modelGradients function.
        [gradients,loss] = dlfeval(@modelGradients, parameters, dlX, dlT, hyperparameters);

        % Update the network parameters using the Adam optimizer.
        [parameters,trailingAvg,trailingAvgSq] = adamupdate(parameters,gradients, ...
            trailingAvg,trailingAvgSq,iteration);

        % Display the training progress.
        D = duration(0,0,toc(start),Format="hh:mm:ss");
        loss = double(gather(extractdata(loss)));
        addpoints(lineLossTrain,iteration,loss)
        title("Epoch: " + epoch + ", Elapsed: " + string(D))
        drawnow
    end
end

Тестовая модель

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

Загрузите тестовые данные.

[XTest,TTest] = digitTest4DArrayData;

После обучения создание предсказаний на новых данных не требует меток. Создайте minibatchqueue объект, содержащий только предикторы тестовых данных:

  • Определите номер выходных параметров мини-пакетной очереди к 1.

  • Задайте тот же мини-пакетный размер, используемый для обучения.

  • Предварительно обработайте предикторы с помощью preprocessPredictors функция, перечисленная в разделе Mini-Batch Predictors Preprocessing Function примера.

  • Для одного выхода datastore задайте мини-пакетный формат "SSCB" (пространственный, пространственный, канал, пакет).

dsTest = arrayDatastore(XTest,IterationDimension=4);

mbqTest = minibatchqueue(dsTest,1, ...
    MiniBatchSize=miniBatchSize, ...
    MiniBatchFormat="SSCB", ...
    MiniBatchFcn=@preprocessPredictors);

Цикл по мини-пакетам и классифицирует последовательности с помощью modelPredictions функция, перечисленная в разделе Model Predictions Function примера.

YPred = modelPredictions(parameters,hyperparameters,mbqTest,classNames);

Визуализируйте предсказания в матрице беспорядка.

figure
confusionchart(TTest,YPred)

Функция модели

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

Эта схема обрисовывает в общих чертах структуру модели.

Для нейронной операции ODE используйте dlode45 функционируйте и задайте odeModel функция, перечисленная в разделе ODE Function примера. Увеличьте абсолютную и относительную погрешность с помощью AbsoluteTolerance и RelativeTolerance аргументы name-value, соответственно. Чтобы вычислить градиенты путем решения связанной примыкающей системы ОДУ, установите GradientMode опция к "adjoint".

function dlY = model(parameters,dlX,hyperparameters)

% Convolution, ReLU.
weights = parameters.conv1.Weights;
bias = parameters.conv1.Bias;
dlY = dlconv(dlX,weights,bias,Padding="same",Stride=2);

dlY = relu(dlY);

% Augment.
weights = parameters.neuralode.Weights;

numChannels = size(dlY,3);
szAugmented = size(dlY);
szAugmented(3) = size(weights,3) - numChannels;

dlY0 = cat(3, dlY, zeros(szAugmented,"like",dlY));

% Neural ODE.
tspan = hyperparameters.neuralode.tspan;
dlY = dlode45(@odeModel,tspan,dlY0,parameters.neuralode, ...
    GradientMode="adjoint", ...
    AbsoluteTolerance=1e-3, ...
    RelativeTolerance=1e-4);

% Discard augmentation.
dlY(:,:,numChannels+1:end,:) = [];

% Fully connect, softmax.
weights = parameters.fc1.Weights;
bias = parameters.fc1.Bias;
dlY = fullyconnect(dlY,weights,bias);

dlY = softmax(dlY);

end

Функция ОДУ

Нейронная операция ODE состоит из операции свертки, сопровождаемой tanh операцией.

Функция ОДУ odeModel берет в качестве входа входные параметры функции t (неиспользованный) и y и параметры функции ОДУ p содержание весов свертки и смещений, и возвращает выходной параметр блочной операции свертки-tanh.

function z = odeModel(t,y,p)

weights = p.Weights;
bias = p.Bias;

z = dlconv(y,weights,bias,Padding="same");
z = tanh(z);

end

Функция градиентов модели

modelGradients функционируйте берет в качестве входа параметры модели, мини-пакет входных данных dlX с соответствующими целями dlT, и гиперпараметры модели, и возвращают градиенты потери относительно настраиваемых параметров и соответствующей потери. Чтобы вычислить градиенты с помощью автоматического дифференцирования, используйте dlgradient функция.

function [gradients,loss] = modelGradients(parameters,dlX,dlT,hyperparameters)

dlY = model(parameters,dlX,hyperparameters);

loss = crossentropy(dlY,dlT);

gradients = dlgradient(loss,parameters);

end

Функция предсказаний модели

modelPredictions функционируйте берет в качестве входа параметры модели, гиперпараметры модели, minibatchqueue из входных данных mbq, и сетевые классы, и вычисляют предсказания модели путем итерации по всем данным в minibatchqueue объект. Функция использует onehotdecode функционируйте, чтобы найти предсказанные классы с самым высоким счетом.

function predictions = modelPredictions(parameters,hyperparameters,mbq,classNames)

predictions = [];

while hasdata(mbq)
    dlX = next(mbq);
    dlYPred = model(parameters,dlX,hyperparameters);
    YPred = onehotdecode(dlYPred,classNames,1)';
    predictions = [predictions; YPred];
end

end

Функция предварительной обработки мини-пакета

preprocessMiniBatch функция предварительно обрабатывает мини-пакет предикторов и меток с помощью следующих шагов:

  1. Предварительно обработайте изображения с помощью preprocessPredictors функция.

  2. Извлеките данные о метке из массива входящей ячейки и конкатенируйте в категориальный массив вдоль второго измерения.

  3. Одногорячий кодируют категориальные метки в числовые массивы. Кодирование в первую размерность производит закодированный массив, который совпадает с формой сетевого выхода.

function [X,Y] = preprocessMiniBatch(XCell,YCell)

% Preprocess predictors.
X = preprocessPredictors(XCell);

% Extract label data from cell and concatenate.
Y = cat(2,YCell{:});

% One-hot encode labels.
Y = onehotencode(Y,1);

end

Предикторы, предварительно обрабатывающие функцию

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

function X = preprocessPredictors(XCell)

X = cat(4,XCell{:});

end

Библиография

  1. Чен, Рики Т. К., Юлия Рубанова, Джесси Бетанкур и Давид Дювено. “Нейронные Обыкновенные дифференциальные уравнения”. Предварительно распечатайте, представленный 19 июня 2018. https://arxiv.org/abs/1806.07366.

  2. Дюпон, Emilien, Арно Дусэ и Ии Вай Тех. “Увеличенные Нейронные ОДУ”. Предварительно распечатайте, представленный 26 октября 2019. https://arxiv.org/abs/1904.01681.

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

| | | |

Похожие темы