function [layers,options] = networkLayersAndOptions(augmentedImdsTrain,imdsValidation,dataqueue)
%NETWORKLAYERSANDOPTIONS creates network layers and options for training.
%   networkLayersAndOptions must return a cell array of network layers and
%   an array of training options. These arrays must have the same length.
%   Each network layer and training option corresponds to an experiment.
%   If you want to send training progress during training, set the
%   following name-value pair in each set of training options:
%       'OutputFcn',@(info) send(dataqueue,struct('experimentNumber',m,'info',info))
%   where m is a positive integer that identifies each experiment. These
%   numbers must range from 1 to the number of experiments.
    
    layers{1} = [
        imageInputLayer(augmentedImdsTrain.OutputSize)
        
        convolution2dLayer(5,10)
        reluLayer
        maxPooling2dLayer(2,'Stride',2)
        
        fullyConnectedLayer(10)
        softmaxLayer
        classificationLayer];

    layers{2} = [
        imageInputLayer(augmentedImdsTrain.OutputSize)
    
        convolution2dLayer(3,8,'Padding','same')
        batchNormalizationLayer
        reluLayer   

        maxPooling2dLayer(2,'Stride',2)

        convolution2dLayer(3,16,'Padding','same')
        batchNormalizationLayer
        reluLayer   

        maxPooling2dLayer(2,'Stride',2)

        convolution2dLayer(3,32,'Padding','same')
        batchNormalizationLayer
        reluLayer
        
        averagePooling2dLayer(7)

        fullyConnectedLayer(10)
        softmaxLayer
        classificationLayer];

    layers{3} = layers{1};
    layers{4} = layers{2};

    miniBatchSize = 128;
    
    options(1) = trainingOptions('sgdm', ...
        'MiniBatchSize',miniBatchSize, ...
        'InitialLearnRate',0.1, ...
        'MaxEpochs',10, ...
        'Shuffle','every-epoch', ...
        'ValidationData',imdsValidation, ...
        'ValidationFrequency',floor(augmentedImdsTrain.NumObservations/miniBatchSize), ...
        'OutputFcn',@(info) send(dataqueue,struct('experimentNumber',1,'info',info)));
    
    options(2) = trainingOptions('sgdm', ...
        'MiniBatchSize',miniBatchSize, ...
        'InitialLearnRate',1e-3, ...
        'MaxEpochs',15, ...
        'Shuffle','every-epoch', ...
        'ValidationData',imdsValidation, ...
        'ValidationFrequency',floor(augmentedImdsTrain.NumObservations/miniBatchSize), ...
        'OutputFcn',@(info) send(dataqueue,struct('experimentNumber',2,'info',info)));
    
    options(3) = trainingOptions('sgdm', ...
        'MiniBatchSize',miniBatchSize, ...
        'InitialLearnRate',1e-3, ...
        'MaxEpochs',15, ...
        'Shuffle','every-epoch', ...
        'ValidationData',imdsValidation, ...
        'ValidationFrequency',floor(augmentedImdsTrain.NumObservations/miniBatchSize), ...
        'OutputFcn',@(info) send(dataqueue,struct('experimentNumber',3,'info',info)));
    
    options(4) = trainingOptions('sgdm', ...
        'MiniBatchSize',miniBatchSize, ...
        'InitialLearnRate',0.1, ...
        'MaxEpochs',10, ...
        'Shuffle','every-epoch', ...
        'ValidationData',imdsValidation, ...
        'ValidationFrequency',floor(augmentedImdsTrain.NumObservations/miniBatchSize), ...
        'OutputFcn',@(info) send(dataqueue,struct('experimentNumber',4,'info',info)));

end