%% Use VGGish Embeddings for Deep Learning
% Download and unzip the air compressor data set. This data set consists of recordings from air compressors in a healthy state or in one of seven faulty states.

url = 'https://www.mathworks.com/supportfiles/audio/AirCompressorDataset/AirCompressorDataset.zip';
downloadFolder = fullfile(tempdir,'aircompressordataset');
datasetLocation = tempdir;

if ~exist(fullfile(tempdir,'AirCompressorDataSet'),'dir')
    loc = websave(downloadFolder,url);
    unzip(loc,fullfile(tempdir,'AirCompressorDataSet'))
end

%
% Create an audioDatastore object to manage the data and split it into training and validation sets.

ads = audioDatastore(downloadFolder,'IncludeSubfolders',true,'LabelSource','foldernames');

[adsTrain,adsValidation] = splitEachLabel(ads,0.8,0.2);

%
% Read an audio file from the datastore and save the sample rate for later use. Reset the datastore to return the read pointer to the beginning of the data set. Listen to the audio signal and plot the signal in the time domain.

[x,fileInfo] = read(adsTrain);
fs = fileInfo.SampleRate;

reset(adsTrain)

sound(x,fs)

figure
t = (0:size(x,1)-1)/fs;
plot(t,x)
xlabel('Time (s)')
title('State = ' + string(fileInfo.Label))
axis tight

%
% Extract VGGish features from the training and validation sets. Transpose the features so that time is along rows.

trainFeatures = cell(1,numel(adsTrain.Files));
for idx = 1:numel(adsTrain.Files)
    [audioIn,fileInfo] = read(adsTrain);
    features = vggishFeatures(audioIn,fileInfo.SampleRate);
    trainFeatures{idx} = features';
end

validationFeatures = cell(1,numel(adsValidation.Files));
for idx = 1:numel(adsValidation.Files)
    [audioIn,fileInfo] = read(adsValidation);
    features = vggishFeatures(audioIn,fileInfo.SampleRate);
    validationFeatures{idx} = features';
end

%
% Define a Long Short-Term Memory network.

layers = [
    sequenceInputLayer(128)
    lstmLayer(100,'OutputMode','last')
    fullyConnectedLayer(8)
    softmaxLayer
    classificationLayer];

%
% To define training options, use trainingOptions.

miniBatchSize = 64;
validationFrequency = 5*floor(numel(trainFeatures)/miniBatchSize);
options = trainingOptions("adam", ...
    "MaxEpochs",12, ...
    "MiniBatchSize",miniBatchSize, ...
    "Plots","training-progress", ...
    "Shuffle","every-epoch", ...
    "LearnRateSchedule","piecewise", ...
    "LearnRateDropPeriod",6, ...
    "LearnRateDropFactor",0.1, ...
    "ValidationData",{validationFeatures,adsValidation.Labels}, ...
    "ValidationFrequency",validationFrequency, ...
    'Verbose',false);

%
% To train the network, use trainNetwork.

net = trainNetwork(trainFeatures,adsTrain.Labels,layers,options)

%
% Visualize the confusion matrix for the validation set.

predictedClass = classify(net,validationFeatures);
confusionchart(adsValidation.Labels,predictedClass)

% Copyright 2020 The MathWorks, Inc.