matlabmachine-learningtime-seriesconv-neural-network

How do you properly format data for CNN classification?


I'm trying to use LeNet to classify univariate time series data with 300 time steps.

num_channels = 1;
num_classes = 3;
filterSize = 5;
numFilters = 32;
num_of_features = size(X_train(1, :), 2);
assert(num_of_features==300);

net = dlnetwork;

LeNeT = [
    % featureInputLayer(num_of_features, "Name", "input")
    sequenceInputLayer(num_of_features, "Name", "input", "MinLength", num_of_features)
    convolution1dLayer( 5, 6,"Name","conv1")
    tanhLayer("Name","tanh1")
    averagePooling1dLayer( 2, "Name","pool1","Stride", 2)
    tanhLayer("Name","tanh2")
    convolution1dLayer( 5, 16,"Name","conv2")
    tanhLayer("Name","tanh3")
    averagePooling1dLayer( 2,"Name","pool2","Stride", 2)
    tanhLayer("Name","tanh4")
    convolution1dLayer( 5, 120,"Name","conv3")
    tanhLayer("Name","tanh5")
    fullyConnectedLayer( 84, "Name","fc1")
    tanhLayer("Name","tanh6")
    fullyConnectedLayer( num_classes, "Name","new_fc")
    softmaxLayer("Name","prob")];

net = addLayers(net,LeNeT);
net = initialize(net);

train_opts = trainingOptions("adam", ...
    MaxEpochs=20, ...
    MiniBatchSize=128, ... 
    InitialLearnRate=0.01, ...
    Shuffle="once", ...
    ValidationData={X_val,Y_val}, ...
    Plots="none", ...
    Metrics="accuracy", ...
    Verbose=true);

%% Train the network.

net = trainnet(X_train, Y_train, net, "crossentropy", train_opts);

%% Test the network.

accuracy = testnet(net, X_test, Y_test, "accuracy");
scores = minibatchpredict(net, X_test);
predicted_labels = scores2label(scores, categories(Y));
figure
confusionchart(Y_test, predicted_labels)

The dimension of the predictors (X) and targets (Y):

Running the code above results in this error message:

Training stopped: Error occurred
Error using trainnet (line 54)
Error evaluating loss function.

Error in main (line 158)
net = trainnet(X_train, Y_train, net, "crossentropy", train_opts);
      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Caused by:
    Error using validateTrueValues (line 54)
    Size of predictions and targets must match.
    Size of predictions:
        3(C) × 1(B) × 2940(T)
    Size of targets:
        3(C) × 1(B) × 11788(T)
 
>> 

The problem is most likely the way I formatted the data, but I just can't figure out exactly what the issue is. To be honest, I'm not sure about the difference between a 'channel' and a 'feature,' so maybe the source of the problem lies in me setting the inputSize parameter of the sequenceInputLayer to num_of_features. However, according to the MATLAB documentation, 'For vector sequence input, inputSize is a scalar corresponding to the number of features.'

Originally, I formatted the data into a cell array (with dimension 11788 x 1 cell), where each predictor cell (each sample) held a 300 step long vector (300 x 1 double). The target formatting was the same. For this approach, I followed the example from this link, so my data was formatted very similarly to the data used in this example, but I encountered a similar error message described above.


Solution

  • With a convolutional network, "features" are the output of its filters, and "channels" are the inputs you give it. For example, a 2D conv network might either have 3 colour channels, or 1 greyscale one. The layer can output the results of perhaps 10, 100 or 1000 different features from "convoluting" a "filter" over the data - it's up to us how many filters we want to use in each layer. It is common practice to make the size of the "filter" (eg 7x7, or in your case, just 7) decrease and number of features increase per each layer deep into the network. https://ieeexplore.ieee.org/abstract/document/9142089

    I think the issue you have is that your sequence input layer might be reshaping the input. Perhaps this layer is squashing together the samples into an RNN format, and then when it goes through your network it gives the wrong dimensions at the output. If you are learning on a bunch of 300-length inputs, you might be better using an input layer https://uk.mathworks.com/help/deeplearning/ref/nnet.cnn.layer.inputlayer.html

    I recommend printing out the dimension of each layer when debugging to help catch these sorts of bugs - you should persist with the same samples that you start with as what you end with.