%% Fix Errors in Network Architecture
% Create a simple convolutional network with shortcut connections. Create the main branch of the network as an array of layers and create a layer graph from the layer array. layerGraph connects all the layers in layers sequentially.

layers = [
    imageInputLayer([32 32 3],'Name','input')
    
    convolution2dLayer(5,16,'Padding','same','Name','conv_1')
    reluLayer('Name','relu_1')
    
    convolution2dLayer(3,16,'Padding','same','Stride',2,'Name','conv_2')
    reluLayer('Name','relu_2') 
    additionLayer(2,'Name','add1')
    
    convolution2dLayer(3,16,'Padding','same','Stride',2,'Name','conv_3')
    reluLayer('Name','relu_3') 
    additionLayer(3,'Name','add2')
    
    fullyConnectedLayer(10,'Name','fc')
    classificationLayer('Name','output')];

lgraph = layerGraph(layers);

%
% Create the shortcut connections. One of the shortcut connections contains a single 1-by-1 convolutional layer skipConv.

skipConv = convolution2dLayer(1,16,'Stride',2,'Name','skipConv');
lgraph = addLayers(lgraph,skipConv);
lgraph = connectLayers(lgraph,'relu_1','add1/in2');
lgraph = connectLayers(lgraph,'add1','add2/in2');

%
% Analyze the network architecture. analyzeNetwork finds four errors in the network.

analyzeNetwork(lgraph)

%
% Investigate and fix the errors in the network. In this example, the following issues cause the errors:
% A softmax layer, which outputs class probabilities, must precede the classification layer. To fix the error in the output classification layer, add a softmax layer before the classification layer.
% The skipConv layer is not connected to the rest of the network. It should be a part of the shortcut connection between the add1 and add2 layers. To fix this error, connect add1 to skipConv and skipConv to add2.
% The add2 layer is specified to have three inputs, but the layers only has two inputs. To fix the error, specify the number of inputs as 2.
% All the inputs to an addition layer must have the same size, but the add1 layer has two inputs with different sizes. Because the conv_2 layer has a 'Stride' value of 2, this layer downsamples the activations by a factor of two in the first two dimensions (the spatial dimensions). To resize the input from the relu2 layer so that it has the same size as the input from relu1, remove the downsampling by setting the 'Stride' value of the conv_2 layer to 1.
% Apply these modifications to the layer graph construction from the beginning of this example and create a new layer graph.

layers = [
    imageInputLayer([32 32 3],'Name','input')
    
    convolution2dLayer(5,16,'Padding','same','Name','conv_1')
    reluLayer('Name','relu_1')
    
    convolution2dLayer(3,16,'Padding','same','Stride',1,'Name','conv_2')
    reluLayer('Name','relu_2') 
    additionLayer(2,'Name','add1')
    
    convolution2dLayer(3,16,'Padding','same','Stride',2,'Name','conv_3')
    reluLayer('Name','relu_3') 
    additionLayer(2,'Name','add2')
    
    fullyConnectedLayer(10,'Name','fc')
    softmaxLayer('Name','softmax');
    classificationLayer('Name','output')];

lgraph = layerGraph(layers);

skipConv = convolution2dLayer(1,16,'Stride',2,'Name','skipConv');
lgraph = addLayers(lgraph,skipConv);
lgraph = connectLayers(lgraph,'relu_1','add1/in2');
lgraph = connectLayers(lgraph,'add1','skipConv');
lgraph = connectLayers(lgraph,'skipConv','add2/in2');

%
% Analyze the new architecture. The new network does not contain any errors and is ready to be trained.

analyzeNetwork(lgraph)

%
% Copyright 2018 The MathWorks, Inc.