%% LSTM Sequence Length Figures

%%
XTrain = japaneseVowelsTrainData;

sequenceLengths = cellfun(@(x) size(x,2),XTrain);
sequenceLengthsSorted = sort(sequenceLengths);
 
dataColor = [0 0.4470 0.7410];
paddingColor = [0.9290 0.6940 0.1250]; 

numSequences = size(XTrain,1);
miniBatchSize = 27;

%% Sort Data by Sequence Length
% The following figures show the sequence lengths of the sorted and
% unsorted data in bar charts. 

f = figure;
f.Position(3) = 1.5*f.Position(3);
f.Position(4) = .6*f.Position(4);

subplot(1,2,1)
barh(sequenceLengths,1,'LineStyle','none')
xlabel("Length")
ylabel("Sequence")
title("Unsorted Data")

subplot(1,2,2)
barh(sequenceLengthsSorted,1,'LineStyle','none')
xlabel("Length")
ylabel("Sequence")
title("Sorted Data")

%% Right-Truncate to Shortest
% The following figures illustrate the effect of setting |'SequenceLength'|
% to |'shortest'|.

f = figure;
f.Position(3) = 1.5*f.Position(3);
f.Position(4) = .6*f.Position(4);
subplot(1,2,1)
for i = 0:9
    idx = i*miniBatchSize+1:(i+1)*miniBatchSize;
    
    miniBatchSequenceLengths = sequenceLengths(idx)';
    minLength = min(miniBatchSequenceLengths);
    
    data = [ ...
        min(miniBatchSequenceLengths,minLength);
        miniBatchSequenceLengths-minLength]';
    
    h = barh(idx,data,1,'stacked', ...
        'LineStyle','none');
    hold on
    
    h(1).FaceColor = dataColor;
    h(2).FaceColor = 'k';
    h(2).FaceAlpha = .25;
    
    plot([minLength minLength],[idx(1) idx(end)],'r')
    
    h(3)=plot([0 minLength],[idx(1)-1 idx(1)-1],'r-');
    
    h(3)=plot([0 minLength],[idx(end) idx(end)],'r-');
end

title("Unsorted Data")
xlabel("Length")
ylabel("Sequence")

subplot(1,2,2)
for i = 0:9
    idx = i*miniBatchSize+1:(i+1)*miniBatchSize;
    
    miniBatchSequenceLengths = sequenceLengthsSorted(idx)';
    minLength = min(miniBatchSequenceLengths);
    
    data = [ ...
        min(miniBatchSequenceLengths,minLength);
        miniBatchSequenceLengths-minLength]';
    
    h = barh(idx,data,1,'stacked', ...
        'LineStyle','none');
    hold on
    
    h(1).FaceColor = dataColor;
    h(2).FaceColor = 'k';
    h(2).FaceAlpha = .25;
    
    plot([minLength minLength],[idx(1) idx(end)],'r')
    
    h(3)=plot([0 minLength],[idx(1)-1 idx(1)-1],'r-');
    
    h(3)=plot([0 minLength],[idx(end) idx(end)],'r-');
end

title("Sorted Data")
xlabel("Length")
ylabel("Sequence")
legend(h,["Sequence Data","Discarded Data","Mini-Batches"], ...
    'Location','southeast')

%% Truncate to Shortest
% The following figures illustrate the effect of setting |'SequenceLength'|
% to |'shortest'|.

xMax = 30;

f = figure;
f.Position(3) = 1.5*f.Position(3);
f.Position(4) = .6*f.Position(4);
subplot(1,2,1)
for i = 0:9
    idx = i*miniBatchSize+1:(i+1)*miniBatchSize;
    
    miniBatchSequenceLengths = sequenceLengths(idx)';
    minLength = min(miniBatchSequenceLengths);
    
    data1 = -(miniBatchSequenceLengths-minLength)';
    data2 = repmat(minLength,[numel(idx),1]);
    
    h(1) = barh(idx,data1,1, ...
        'LineStyle','none');
    hold on
    
    h(2) = barh(idx,data2,1, ...
        'LineStyle','none');

    h(2).FaceColor = dataColor;
    h(1).FaceColor = 'k';
    h(1).FaceAlpha = .25;
    
    plot([minLength minLength],[idx(1) idx(end)],'r')
    
    h(3)=plot([0 minLength],[idx(1)-1 idx(1)-1],'r-');
    
    h(3)=plot([0 minLength],[idx(end) idx(end)],'r-');
end
hold off

xticks(0:5:max(xticks))
title("Unsorted Data")
xlabel("Sequence Length")
ylabel("Sequence")

subplot(1,2,2)
for i = 0:9
    idx = i*miniBatchSize+1:(i+1)*miniBatchSize;
    
    miniBatchSequenceLengths = sequenceLengthsSorted(idx)';
    minLength = min(miniBatchSequenceLengths);
    
    data1 = -(miniBatchSequenceLengths-minLength)';
    data2 = repmat(minLength,[numel(idx),1]);
    
    h(1) = barh(idx,data1,1, ...
        'LineStyle','none');
    hold on
    
    h(2) = barh(idx,data2,1, ...
        'LineStyle','none');
    
    h(2).FaceColor = dataColor;
    h(1).FaceColor = 'k';
    h(1).FaceAlpha = .25;
    
    plot([minLength minLength],[idx(1) idx(end)],'r')
    
    h(3)=plot([0 minLength],[idx(1)-1 idx(1)-1],'r-');
    
    h(3)=plot([0 minLength],[idx(end) idx(end)],'r-');
end

xticks(0:5:max(xticks))
title("Sorted Data")
xlabel("Sequence Length")
ylabel("Sequence")
legend([h(2) h(1) h(3)],["Sequence Data","Discarded Data","Mini-Batches"], ...
    'Location','southeast')

%% Right-Pad to Longest
% The following figures illustrate the effect of setting |'SequenceLength'|
% to |'longest'|.

f = figure;
f.Position(3) = 1.5*f.Position(3);
f.Position(4) = .6*f.Position(4);
subplot(1,2,1)

for i = 0:9
    idx = i*miniBatchSize+1:(i+1)*miniBatchSize;
    miniBatchSequenceLengths = sequenceLengths(idx)';
    maxLength = max(miniBatchSequenceLengths);
    
    data = [ ...
        miniBatchSequenceLengths;
        maxLength-miniBatchSequenceLengths]';
    
    h = barh(idx,data,1,'stacked','LineStyle','none');
    hold on
    
    h(1).FaceColor = dataColor;
    h(2).FaceColor = paddingColor;
    
    plot([maxLength maxLength],[idx(1) idx(end)],'r')
    
    h(3)=plot([0 maxLength],[idx(1)-1 idx(1)-1],'r-');
    
    h(3)=plot([0 maxLength],[idx(end) idx(end)],'r-');
end

title("Unsorted Data")
xlabel("Length")
ylabel("Sequence")

subplot(1,2,2)
for i = 0:9
    idx = i*miniBatchSize+1:(i+1)*miniBatchSize;
    miniBatchSequenceLengths = sequenceLengthsSorted(idx)';
    maxLength = max(miniBatchSequenceLengths);
    
    data = [ ...
        miniBatchSequenceLengths;
        maxLength-miniBatchSequenceLengths]';
    
    h = barh(idx,data,1,'stacked','LineStyle','none');
    hold on
    
    h(1).FaceColor = dataColor;
    h(2).FaceColor = paddingColor;
    
    plot([maxLength maxLength],[idx(1) idx(end)],'r')
    
    h(3)=plot([0 maxLength],[idx(1)-1 idx(1)-1],'r-');
    
    h(3)=plot([0 maxLength],[idx(end) idx(end)],'r-');
end

title("Sorted Data")
xlabel("Length")
ylabel("Sequence")
legend(h,["Sequence Data","Padding","Mini-Batches"], ...
    'Location','southeast')

miniBatchSequenceLengths = sequenceLengths(1:miniBatchSize)';
maxLength = max(miniBatchSequenceLengths);

%% Pad to Longest
% The following figures illustrate the effect of setting |'SequenceLength'|
% to |'longest'|.

f = figure;
f.Position(3) = 1.5*f.Position(3);
f.Position(4) = .6*f.Position(4);
subplot(1,2,1)


for i = 0:9
    idx = i*miniBatchSize+1:(i+1)*miniBatchSize;
    miniBatchSequenceLengths = sequenceLengths(idx)';
    maxLength = max(miniBatchSequenceLengths);
    
    data = [ ...
        maxLength-miniBatchSequenceLengths;
        miniBatchSequenceLengths]';
    
    h = barh(idx,data,1,'stacked','LineStyle','none');
    hold on
    
    h(2).FaceColor = dataColor;
    h(1).FaceColor = paddingColor;
    
    plot([maxLength maxLength],[idx(1) idx(end)],'r')
    
    h(3)=plot([0 maxLength],[idx(1)-1 idx(1)-1],'r-');
    
    h(3)=plot([0 maxLength],[idx(end) idx(end)],'r-');
end

title("Unsorted Data")
xlabel("Sequence Length")
ylabel("Sequence")

subplot(1,2,2)
for i = 0:9
    idx = i*miniBatchSize+1:(i+1)*miniBatchSize;
    miniBatchSequenceLengths = sequenceLengthsSorted(idx)';
    maxLength = max(miniBatchSequenceLengths);
    
    data = [ ...
        maxLength-miniBatchSequenceLengths;
        miniBatchSequenceLengths]';
    
    h = barh(idx,data,1,'stacked','LineStyle','none');
    hold on
    
    h(2).FaceColor = dataColor;
    h(1).FaceColor = paddingColor;
    
    plot([maxLength maxLength],[idx(1) idx(end)],'r')
    
    h(3)=plot([0 maxLength],[idx(1)-1 idx(1)-1],'r-');
    
    h(3)=plot([0 maxLength],[idx(end) idx(end)],'r-');
end

title("Sorted Data")
xlabel("Sequence Length")
ylabel("Sequence")
legend([h(2) h(1) h(3)],["Sequence Data","Padding","Mini-Batches"], ...
    'Location','southeast')

miniBatchSequenceLengths = sequenceLengths(1:miniBatchSize)';
maxLength = max(miniBatchSequenceLengths);

%% Right-Split Sequences
% The following figures illustrate the effect of setting |'SequenceLength'|
% to 5.

f = figure;
f.Position(3) = 1.5*f.Position(3);
f.Position(4) = .6*f.Position(4);

subplot(1,2,1)

sequenceLength = 5;
for i = 1:numSequences/miniBatchSize
    idx = (i-1)*miniBatchSize+1:i*miniBatchSize;
    miniBatchSequenceLengths = sequenceLengths(idx)';
    
    maxLength = ceil(max(miniBatchSequenceLengths)/sequenceLength)*sequenceLength;
    
    data = [...
        miniBatchSequenceLengths;
        maxLength-miniBatchSequenceLengths]';
    
    h=barh(idx,data,1,'stacked', ...
        'LineStyle','none');
    hold on
    
    h(1).FaceColor = dataColor;
    h(2).FaceColor = paddingColor;
    plot([maxLength maxLength],[idx(1) idx(end)],'r')
    
    for j = sequenceLength:sequenceLength:maxLength-1
        h(4) = plot([j j],[idx(1) idx(end)],'r--');
    end
    
    h(3)=plot([0 maxLength],[idx(1)-1 idx(1)-1],'r-');
    
    h(3)=plot([0 maxLength],[idx(end) idx(end)],'r-');
end

title("Unsorted Data")
xlabel("Length")
ylabel("Sequence")

subplot(1,2,2)

sequenceLength = 5;
for i = 1:numSequences/miniBatchSize
    idx = (i-1)*miniBatchSize+1:i*miniBatchSize;
    miniBatchSequenceLengths = sequenceLengthsSorted(idx)';
    
    maxLength = ceil(max(miniBatchSequenceLengths)/sequenceLength)*sequenceLength;
    
    data = [...
        miniBatchSequenceLengths;
        maxLength-miniBatchSequenceLengths]';
    
    h=barh(idx,data,1,'stacked', ...
        'LineStyle','none');
    hold on
    
    h(1).FaceColor = dataColor;
    h(2).FaceColor = paddingColor;
    plot([maxLength maxLength],[idx(1) idx(end)],'r')
    
    for j = sequenceLength:sequenceLength:maxLength-1
        h(4) = plot([j j],[idx(1) idx(end)],'r--');
    end
    
    h(3)=plot([0 maxLength],[idx(1)-1 idx(1)-1],'r-');
    
    h(3)=plot([0 maxLength],[idx(end) idx(end)],'r-');
end

title("Sorted Data")
xlabel("Length")
ylabel("Sequence")

legend([h(1) h(2) h(3) h(4)],["Sequence Data","Padding","Mini-Batches","Splits"], ...
    'Location','southeast')

%% Split Sequences
% The following figures illustrate the effect of setting |'SequenceLength'|
% to 5.

f = figure;
f.Position(3) = 1.5*f.Position(3);
f.Position(4) = .6*f.Position(4);

subplot(1,2,1)

sequenceLength = 5;
for i = 1:numSequences/miniBatchSize
    idx = (i-1)*miniBatchSize+1:i*miniBatchSize;
    miniBatchSequenceLengths = sequenceLengths(idx)';
    
    maxLength = ceil(max(miniBatchSequenceLengths)/sequenceLength)*sequenceLength;
    
    data = [...
        maxLength-miniBatchSequenceLengths;
        miniBatchSequenceLengths]';
    
    h=barh(idx,data,1,'stacked', ...
        'LineStyle','none');
    hold on
    
    h(2).FaceColor = dataColor;
    h(1).FaceColor = paddingColor;
    plot([maxLength maxLength],[idx(1) idx(end)],'r')
    
    for j = sequenceLength:sequenceLength:maxLength-1
        h(4) = plot([j j],[idx(1) idx(end)],'r--');
    end
    
    h(3)=plot([0 maxLength],[idx(1)-1 idx(1)-1],'r-');
    
    h(3)=plot([0 maxLength],[idx(end) idx(end)],'r-');
end

title("Unsorted Data")
xlabel("Sequence Length")
ylabel("Sequence")

subplot(1,2,2)

sequenceLength = 5;
for i = 1:numSequences/miniBatchSize
    idx = (i-1)*miniBatchSize+1:i*miniBatchSize;
    miniBatchSequenceLengths = sequenceLengthsSorted(idx)';
    
    maxLength = ceil(max(miniBatchSequenceLengths)/sequenceLength)*sequenceLength;
    
    data = [...
        maxLength-miniBatchSequenceLengths;
        miniBatchSequenceLengths]';
    
    h=barh(idx,data,1,'stacked', ...
        'LineStyle','none');
    hold on
    
    h(2).FaceColor = dataColor;
    h(1).FaceColor = paddingColor;
    plot([maxLength maxLength],[idx(1) idx(end)],'r')
    
    for j = sequenceLength:sequenceLength:maxLength-1
        h(4) = plot([j j],[idx(1) idx(end)],'r--');
    end
    
    h(3)=plot([0 maxLength],[idx(1)-1 idx(1)-1],'r-');
    
    h(3)=plot([0 maxLength],[idx(end) idx(end)],'r-');
end

title("Sorted Data")
xlabel("Sequence Length");
ylabel("Sequence")

legend([h(2) h(1) h(3) h(4)],["Sequence Data","Padding","Mini-Batches","Splits"], ...
    'Location','southeast')

%% Padding Direction
% The following figures illustrate padding sequence data on the left and
% on the right.

f = figure;
f.Position(3) = 1.5*f.Position(3);
f.Position(4) = .6*f.Position(4);
subplot(1,2,1)

for i = 0:9
    idx = i*miniBatchSize+1:(i+1)*miniBatchSize;
    miniBatchSequenceLengths = sequenceLengthsSorted(idx)';
    maxLength = max(miniBatchSequenceLengths);
    
    data = [ ...
        maxLength-miniBatchSequenceLengths;
        miniBatchSequenceLengths]';
    
    h = barh(idx,data,1,'stacked','LineStyle','none');
    hold on
    
    h(2).FaceColor = dataColor;
    h(1).FaceColor = paddingColor;
    
    plot([maxLength maxLength],[idx(1) idx(end)],'r')
    
    h(3)=plot([0 maxLength],[idx(1)-1 idx(1)-1],'r-');
    
    h(3)=plot([0 maxLength],[idx(end) idx(end)],'r-');
end

title("Left-Padding")
xlabel("Sequence Length")
ylabel("Sequence")

miniBatchSequenceLengths = sequenceLengths(1:miniBatchSize)';
maxLength = max(miniBatchSequenceLengths);

subplot(1,2,2)

for i = 0:9
    idx = i*miniBatchSize+1:(i+1)*miniBatchSize;
    miniBatchSequenceLengths = sequenceLengthsSorted(idx)';
    maxLength = max(miniBatchSequenceLengths);
    
    data = [ ...
        miniBatchSequenceLengths;
        maxLength-miniBatchSequenceLengths]';
    
    h = barh(idx,data,1,'stacked','LineStyle','none');
    hold on
    
    h(1).FaceColor = dataColor;
    h(2).FaceColor = paddingColor;
    
    plot([maxLength maxLength],[idx(1) idx(end)],'r')
    
    h(3)=plot([0 maxLength],[idx(1)-1 idx(1)-1],'r-');
    
    h(3)=plot([0 maxLength],[idx(end) idx(end)],'r-');
end

title("Right-Padding")
xlabel("Sequence Length")
ylabel("Sequence")
legend(h,["Sequence Data","Padding","Mini-Batches"], ...
    'Location','southeast')

miniBatchSequenceLengths = sequenceLengths(1:miniBatchSize)';
maxLength = max(miniBatchSequenceLengths);



%%
%% Truncation Direction
% The following figures illustrate truncating sequence data on the left and
% on the right.

xMax = 30;

f = figure;
f.Position(3) = 1.5*f.Position(3);
f.Position(4) = .6*f.Position(4);
subplot(1,2,1)

for i = 0:9
    idx = i*miniBatchSize+1:(i+1)*miniBatchSize;
    
    miniBatchSequenceLengths = sequenceLengthsSorted(idx)';
    minLength = min(miniBatchSequenceLengths);
    
    data1 = -(miniBatchSequenceLengths-minLength)';
    data2 = repmat(minLength,[numel(idx),1]);
    
    h(1) = barh(idx,data1,1, ...
        'LineStyle','none');
    hold on
    
    h(2) = barh(idx,data2,1, ...
        'LineStyle','none');
    
    h(2).FaceColor = dataColor;
    h(1).FaceColor = 'k';
    h(1).FaceAlpha = .25;
    
    plot([minLength minLength],[idx(1) idx(end)],'r')
    
    h(3)=plot([0 minLength],[idx(1)-1 idx(1)-1],'r-');
    
    h(3)=plot([0 minLength],[idx(end) idx(end)],'r-');
end

xticks(0:5:max(xticks))
title("Left-Truncation")
xlabel("Sequence Length")
ylabel("Sequence")

subplot(1,2,2)
for i = 0:9
    idx = i*miniBatchSize+1:(i+1)*miniBatchSize;
    
    miniBatchSequenceLengths = sequenceLengthsSorted(idx)';
    minLength = min(miniBatchSequenceLengths);
    
    data = [ ...
        min(miniBatchSequenceLengths,minLength);
        miniBatchSequenceLengths-minLength]';
    
    h = barh(idx,data,1,'stacked', ...
        'LineStyle','none');
    hold on
    
    h(1).FaceColor = dataColor;
    h(2).FaceColor = 'k';
    h(2).FaceAlpha = .25;
    
    plot([minLength minLength],[idx(1) idx(end)],'r')
    
    h(3)=plot([0 minLength],[idx(1)-1 idx(1)-1],'r-');
    
    h(3)=plot([0 minLength],[idx(end) idx(end)],'r-');
end

title("Right-Truncation")
xlabel("Length")
ylabel("Sequence")
legend(h,["Sequence Data","Discarded Data","Mini-Batches"], ...
    'Location','southeast')




%% 
% Copyright 2012 The MathWorks, Inc.