%% Train Network with Numeric Features
% If you have a data set of numeric features (for example a collection of numeric data without spatial or time dimensions), then you can train a deep learning network using a feature input layer.
% Read the transmission casing data from the CSV file "transmissionCasingData.csv".

filename = "transmissionCasingData.csv";
tbl = readtable(filename,'TextType','String');

% Convert the labels for prediction to categorical using the convertvars function.

labelName = "GearToothCondition";
tbl = convertvars(tbl,labelName,'categorical');

% To train a network using categorical features, you must first convert the categorical features to numeric. First, convert the categorical predictors to categorical using the convertvars function by specifying a string array containing the names of all the categorical input variables. In this data set, there are two categorical features with names "SensorCondition" and "ShaftCondition".

categoricalInputNames = ["SensorCondition" "ShaftCondition"];
tbl = convertvars(tbl,categoricalInputNames,'categorical');

% Loop over the categorical input variables. For each variable:
% Convert the categorical values to one-hot encoded vectors using the onehotencode function.
% Add the one-hot vectors to the table using the addvars function. Specify to insert the vectors after the column containing the corresponding categorical data.
% Remove the corresponding column containing the categorical data.

for i = 1:numel(categoricalInputNames)
    name = categoricalInputNames(i);
    oh = onehotencode(tbl(:,name));
    tbl = addvars(tbl,oh,'After',name);
    tbl(:,name) = [];
end

% Split the vectors into separate columns using the splitvars function.

tbl = splitvars(tbl);

% View the first few rows of the table. Notice that the categorical predictors have been split into multiple columns with the categorical values as the variable names.

head(tbl)

% View the class names of the data set.

classNames = categories(tbl{:,labelName})

% Next, partition the data set into training and test partitions. Set aside 15% of the data for testing.
% Determine the number of observations for each partition.

numObservations = size(tbl,1);
numObservationsTrain = floor(0.85*numObservations);
numObservationsTest = numObservations - numObservationsTrain;

% Create an array of random indices corresponding to the observations and partition it using the partition sizes.

idx = randperm(numObservations);
idxTrain = idx(1:numObservationsTrain);
idxTest = idx(numObservationsTrain+1:end);

% Partition the table of data into training, validation, and testing partitions using the indices.

tblTrain = tbl(idxTrain,:);
tblTest = tbl(idxTest,:);

% Define a network with a feature input layer and specify the number of features. Also, configure the input layer to normalize the data using Z-score normalization.

numFeatures = size(tbl,2) - 1;
numClasses = numel(classNames);
 
layers = [
    featureInputLayer(numFeatures,'Normalization', 'zscore')
    fullyConnectedLayer(50)
    batchNormalizationLayer
    reluLayer
    fullyConnectedLayer(numClasses)
    softmaxLayer
    classificationLayer];

% Specify the training options.

miniBatchSize = 16;

options = trainingOptions('adam', ...
    'MiniBatchSize',miniBatchSize, ...
    'Shuffle','every-epoch', ...
    'Plots','training-progress', ...
    'Verbose',false);

% Train the network using the architecture defined by layers, the training data, and the training options.

net = trainNetwork(tblTrain,layers,options);

% Predict the labels of the test data using the trained network and calculate the accuracy. The accuracy is the proportion of the labels that the network predicts correctly.

YPred = classify(net,tblTest,'MiniBatchSize',miniBatchSize);
YTest = tblTest{:,labelName};

accuracy = sum(YPred == YTest)/numel(YTest)

% Copyright 2020 The MathWorks, Inc.