function [Y,state] = xvecModel(X,parameters,state,nvargs)
% This function is only for use in this example. It may be changed or
% removed in a future release.
arguments
    X
    parameters
    state
    nvargs.DoTraining = false
    nvargs.OutputLayer = 'final'
    nvargs.Dropout = 0.2;
end


% LAYER 1 ----------------------------------------------------------------
Y = dlconv(X,parameters.conv1.Weights,parameters.conv1.Bias,'DilationFactor',1);
if nvargs.DoTraining
    [Y,state.batchnorm1.TrainedMean,state.batchnorm1.TrainedVariance] = ...
        batchnorm(Y, ...
        parameters.batchnorm1.Offset, ...
        parameters.batchnorm1.Scale, ...
        state.batchnorm1.TrainedMean, ...
        state.batchnorm1.TrainedVariance);
    Y(rand(size(Y))<nvargs.Dropout) = 0;
else
    Y = batchnorm(Y, ...
        parameters.batchnorm1.Offset, ...
        parameters.batchnorm1.Scale, ...
        state.batchnorm1.TrainedMean, ...
        state.batchnorm1.TrainedVariance);
end
if nvargs.OutputLayer==1
    return
end
Y = relu(Y);
% -------------------------------------------------------------------------


% LAYER 2 -----------------------------------------------------------------
Y = dlconv(Y,parameters.conv2.Weights,parameters.conv2.Bias,'DilationFactor',2);
if nvargs.DoTraining
    [Y,state.batchnorm2.TrainedMean,state.batchnorm2.TrainedVariance] = ...
        batchnorm(Y, ...
        parameters.batchnorm2.Offset, ...
        parameters.batchnorm2.Scale, ...
        state.batchnorm2.TrainedMean, ...
        state.batchnorm2.TrainedVariance);
    Y(rand(size(Y))<nvargs.Dropout) = 0;
else
    Y = batchnorm(Y, ...
        parameters.batchnorm2.Offset, ...
        parameters.batchnorm2.Scale, ...
        state.batchnorm2.TrainedMean, ...
        state.batchnorm2.TrainedVariance);
end
if nvargs.OutputLayer==2
    return
end
Y = relu(Y);
% -------------------------------------------------------------------------


% LAYER 3 -----------------------------------------------------------------
Y = dlconv(Y,parameters.conv3.Weights,parameters.conv3.Bias,'DilationFactor',3);
if nvargs.DoTraining
    [Y,state.batchnorm3.TrainedMean,state.batchnorm3.TrainedVariance] = ...
        batchnorm(Y, ...
        parameters.batchnorm3.Offset, ...
        parameters.batchnorm3.Scale, ...
        state.batchnorm3.TrainedMean, ...
        state.batchnorm3.TrainedVariance);
    Y(rand(size(Y))<nvargs.Dropout) = 0;
else
    Y = batchnorm(Y, ...
        parameters.batchnorm3.Offset, ...
        parameters.batchnorm3.Scale, ...
        state.batchnorm3.TrainedMean, ...
        state.batchnorm3.TrainedVariance);
end
if nvargs.OutputLayer==3
    return
end
Y = relu(Y);
% -------------------------------------------------------------------------


% LAYER 4 -----------------------------------------------------------------
Y = dlconv(Y,parameters.conv4.Weights,parameters.conv4.Bias,'DilationFactor',1);
if nvargs.DoTraining
    [Y,state.batchnorm4.TrainedMean,state.batchnorm4.TrainedVariance] = ...
        batchnorm(Y, ...
        parameters.batchnorm4.Offset, ...
        parameters.batchnorm4.Scale, ...
        state.batchnorm4.TrainedMean, ...
        state.batchnorm4.TrainedVariance);
    Y(rand(size(Y))<nvargs.Dropout) = 0;
else
    Y = batchnorm(Y, ...
        parameters.batchnorm4.Offset, ...
        parameters.batchnorm4.Scale, ...
        state.batchnorm4.TrainedMean, ...
        state.batchnorm4.TrainedVariance);
end
if nvargs.OutputLayer==4
    return
end
Y = relu(Y);
% -------------------------------------------------------------------------


% LAYER 5 -----------------------------------------------------------------
Y = dlconv(Y,parameters.conv5.Weights,parameters.conv5.Bias,'DilationFactor',1);
if nvargs.DoTraining
    [Y,state.batchnorm5.TrainedMean,state.batchnorm5.TrainedVariance] = ...
        batchnorm(Y, ...
        parameters.batchnorm5.Offset, ...
        parameters.batchnorm5.Scale, ...
        state.batchnorm5.TrainedMean, ...
        state.batchnorm5.TrainedVariance);
    Y(rand(size(Y))<nvargs.Dropout) = 0;
else
    Y = batchnorm(Y, ...
        parameters.batchnorm5.Offset, ...
        parameters.batchnorm5.Scale, ...
        state.batchnorm5.TrainedMean, ...
        state.batchnorm5.TrainedVariance);
end
if nvargs.OutputLayer==5
    return
end
Y = relu(Y);
% -------------------------------------------------------------------------


% Layer 6: Statistical pooling --------------------------------------------
if nvargs.DoTraining
    Y = Y + 0.0001*rand(size(Y));
end
Y = cat(2,mean(Y,1),std(Y,[],1));
if nvargs.OutputLayer==6
    return
end
% -------------------------------------------------------------------------

% LAYER 7 -----------------------------------------------------------------
Y = fullyconnect(Y,parameters.fc7.Weights,parameters.fc7.Bias);
if nvargs.DoTraining
    [Y,state.batchnorm7.TrainedMean,state.batchnorm6.TrainedVariance] = ...
        batchnorm(Y, ...
        parameters.batchnorm7.Offset, ...
        parameters.batchnorm7.Scale, ...
        state.batchnorm7.TrainedMean, ...
        state.batchnorm7.TrainedVariance);
     Y(rand(size(Y))<nvargs.Dropout) = 0;
else
        Y = batchnorm(Y, ...
            parameters.batchnorm7.Offset, ...
            parameters.batchnorm7.Scale, ...
            state.batchnorm7.TrainedMean, ...
            state.batchnorm7.TrainedVariance);
end
if nvargs.OutputLayer==7
    return
end
Y = relu(Y);
% -------------------------------------------------------------------------

% LAYER 8 -----------------------------------------------------------------
Y = fullyconnect(Y,parameters.fc8.Weights,parameters.fc8.Bias);
if nvargs.DoTraining
    [Y,state.batchnorm8.TrainedMean,state.batchnorm8.TrainedVariance] = ...
        batchnorm(Y, ...
        parameters.batchnorm8.Offset, ...
        parameters.batchnorm8.Scale, ...
        state.batchnorm8.TrainedMean, ...
        state.batchnorm8.TrainedVariance);
    Y(rand(size(Y))<nvargs.Dropout) = 0;
else
        Y = batchnorm(Y, ...
            parameters.batchnorm8.Offset, ...
            parameters.batchnorm8.Scale, ...
            state.batchnorm8.TrainedMean, ...
            state.batchnorm8.TrainedVariance);
end
if nvargs.OutputLayer==8
    return
end
Y = relu(Y);
% -------------------------------------------------------------------------

% LAYER 9 (softmax)--------------------------------------------------------
Y = fullyconnect(Y,parameters.fc9.Weights,parameters.fc9.Bias);
if nvargs.OutputLayer==9
    return
end
Y = softmax(Y);
% -------------------------------------------------------------------------
end