Skip to content

Commit

Permalink
Merge pull request #196 from mldiego/master
Browse files Browse the repository at this point in the history
AISOLA 2023 - mnist and mednist code
  • Loading branch information
mldiego authored Oct 17, 2023
2 parents eba0c6f + a63a58d commit cca95e5
Show file tree
Hide file tree
Showing 59,329 changed files with 4,474 additions and 72 deletions.
The diff you're trying to view is too large. We only load the first 3000 changed files.
8 changes: 6 additions & 2 deletions code/nnv/engine/nn/NN.m
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,9 @@
% Parse the inputs

% Ensure input set is a valid type
if ~ isa(inputSet,"Star") && ~ isa(inputSet,"ImageStar") && ~ isa(inputSet,"ImageZono") && ~ isa(inputSet,"Zono")
error('Wrong input set type. Input set must be of type "Star", "ImageStar", "ImageZono", or "Zono"')
if ~isa(inputSet,"Star") && ~isa(inputSet,"ImageStar") && ~isa(inputSet, "VolumeStar")...
&& ~isa(inputSet,"ImageZono") && ~isa(inputSet,"Zono")
error('Wrong input set type. Input set must be of type "Star", "ImageStar", "VolumeStar", "ImageZono", or "Zono"')
end

% Check validity of reachability method
Expand Down Expand Up @@ -1217,6 +1218,9 @@ function start_pool(obj)
exec_len = length(obj.reachSet);
% ensure layer has not been eexcuted yet
if exec_len >= source_indx && isempty(obj.reachSet{source_indx})
if strcmp(obj.dis_opt, 'display')
fprintf('\nPerforming analysis for Layer %d (%s)...', i-1, source);
end
t = tic;
if isequal(class(obj.Layers{1,1}), 'SequenceInputLayer')
outSet = obj.Layers{source_indx}.reachSequence(inSet, obj.reachMethod, obj.reachOption, obj.relaxFactor, obj.dis_opt, obj.lp_solver);
Expand Down
4 changes: 2 additions & 2 deletions code/nnv/engine/nn/layers/AveragePooling3DLayer.m
Original file line number Diff line number Diff line change
Expand Up @@ -200,9 +200,9 @@ function set_padding(obj, padding)
%
% @y: high-dimensional array (output volume), depth of output = number of filters

x = dlarray(input, "SSSC");
x = dlarray(input, "SSSCB");
y = avgpool(x, obj.PoolSize, 'Stride', obj.Stride, 'Padding', obj.PaddingSize);
y = extractdata(x);
y = extractdata(y);

end

Expand Down
86 changes: 69 additions & 17 deletions code/nnv/engine/nn/layers/BatchNormalizationLayer.m
Original file line number Diff line number Diff line change
Expand Up @@ -103,24 +103,46 @@
obj.NumChannels = 1;
end

if ~isempty(obj.TrainedMean) && ~isempty(obj.TrainedVariance) && ~isempty(obj.Epsilon) && ~isempty(obj.Offset) && ~isempty(obj.Scale)
y = input - obj.TrainedMean;
for i=1:obj.NumChannels
y(:,:,i) = y(:,:,i)./(sqrt(obj.TrainedVariance(:,:,i) + obj.Epsilon));
y(:,:,i) = obj.Scale(:, :, i).*y(:,:,i) + obj.Offset(:,:,i);
end

elseif ~isempty(obj.Scale) && ~isempty(obj.Offset) && isempty(obj.TrainedVariance) && isempty(obj.TrainedMean)
y = input;
if obj.NumChannels == 1
y = obj.Scale.*y + obj.Offset;
% input -> 3d image / volume
if length(size(input)) == 4 || (length(size(input)) == 3 && obj.NumChannels == 1)
if ~isempty(obj.TrainedMean) && ~isempty(obj.TrainedVariance) && ~isempty(obj.Epsilon) && ~isempty(obj.Offset) && ~isempty(obj.Scale)
y = input - obj.TrainedMean;
for i=1:obj.NumChannels
y(:,:,:,i) = y(:,:,:,i)./(sqrt(obj.TrainedVariance(:,:,:,i) + obj.Epsilon));
y(:,:,:,i) = obj.Scale(:,:,:,i).*y(:,:,:,i) + obj.Offset(:,:,:,i);
end
elseif ~isempty(obj.Scale) && ~isempty(obj.Offset) && isempty(obj.TrainedVariance) && isempty(obj.TrainedMean)
y = input;
if obj.NumChannels == 1
y = obj.Scale.*y + obj.Offset;
else
for i=1:obj.NumChannels
y(:,:,:,i) = obj.Scale(:,:,:,i).*y(:,:,:,i) + obj.Offset(:,:,:,i);
end
end
else
y = input;
end
% input => image or feature vector
else
if ~isempty(obj.TrainedMean) && ~isempty(obj.TrainedVariance) && ~isempty(obj.Epsilon) && ~isempty(obj.Offset) && ~isempty(obj.Scale)
y = input - obj.TrainedMean;
for i=1:obj.NumChannels
y(:,:,i) = y(:,:,i)./(sqrt(obj.TrainedVariance(:,:,i) + obj.Epsilon));
y(:,:,i) = obj.Scale(:, :, i).*y(:,:,i) + obj.Offset(:,:,i);
end
elseif ~isempty(obj.Scale) && ~isempty(obj.Offset) && isempty(obj.TrainedVariance) && isempty(obj.TrainedMean)
y = input;
if obj.NumChannels == 1
y = obj.Scale.*y + obj.Offset;
else
for i=1:obj.NumChannels
y(:,:,i) = obj.Scale(:, :, i).*y(:,:,i) + obj.Offset(:,:,i);
end
end
else
y = input;
end
else
y = input;
end

end
Expand All @@ -146,14 +168,42 @@
% @in_image: an input imagestar
% @image: output set

if ~isa(in_image, 'ImageStar') && ~isa(in_image, 'Star') % input may be Star or ImageStar
error('Input is not a Star or ImageStar');
if ~isa(in_image, 'ImageStar') && ~isa(in_image, 'Star') && ~isa(in_image, 'VolumeStar') % input may be Star or ImageStar
error('Input is not a Star, ImageStar or VolumeStar');
end

% make copy of input set
image = in_image;

if isa(image, 'VolumeStar')

% Begin reachability analysis
x = in_image;

% If mean and variance exist
if ~isempty(obj.TrainedMean) && ~isempty(obj.TrainedVariance) && ~isempty(obj.Epsilon) && ~isempty(obj.Offset) && ~isempty(obj.Scale)
% 1) Normalized all elements of x (for each channel independently)
% 1a) substract mean from elements of x per channel
for i=1:obj.NumChannels
x.V(:,:,:,i,1) = x.V(:,:,:,i,1) - obj.TrainedMean(:,:,:,i);
end
% 1b) Divide by sqrt(variance + epsilon)
for i=1:obj.NumChannels
x.V(:,:,:,i,:) = x.V(:,:,:,i,:) .* 1/sqrt(obj.TrainedVariance(:,:,:,i) + obj.Epsilon);
end
% 2) Batch normalization operation further shifts and scales the activations using Scale and Offset values
% 2a) Scale values
for i=1:obj.NumChannels
x.V(:,:,:,i,:) = x.V(:,:,:,i,:) .* obj.Scale(:,:,:,i);
end
% 2b) Apply offset
for i=1:obj.NumChannels
x.V(:,:,:,i,1) = x.V(:,:,:,i,1) + obj.Offset(:,:,:,i);
end
image = x;
end

if isa(image, 'ImageStar')
elseif isa(image, 'ImageStar')
% Get parameters to the right shape
if(length(size(obj.TrainedMean)) == 2) && size(image.V, 1) == 1 && size(image.V, 2) == 1 && length(size(image.V)) == 4
obj.TrainedMean = reshape(obj.TrainedMean, [1 1 size(obj.TrainedMean, 1)]);
Expand Down Expand Up @@ -245,7 +295,9 @@
% date: 1/7/2020

n = length(in_images);
if isa(in_images(n), 'ImageStar')
if isa(in_images(n), 'VolumeStar')
images(n) = VolumeStar;
elseif isa(in_images(n), 'ImageStar')
images(n) = ImageStar;
else
images(n) = Star;
Expand Down
6 changes: 3 additions & 3 deletions code/nnv/engine/nn/layers/Conv3DLayer.m
Original file line number Diff line number Diff line change
Expand Up @@ -406,8 +406,8 @@ function set_name(obj, name)

% compute output sets
c = dlconv(dlarray(input.V(:,:,:,:,1), "SSSC"), obj.Weights, obj.Bias, 'Stride', obj.Stride, 'Padding', obj.PaddingSize, 'DilationFactor', obj.DilationFactor);
V = dlconv(dlarray(input.V(:,:,:,2:input.numPred + 1)), "SSSCB", obj.Weights, [], 'Stride', obj.Stride, 'Padding', obj.PaddingSize, 'DilationFactor', obj.DilationFactor);
Y = cat(4, extractdata(c), extractdata(V));
V = dlconv(dlarray(input.V(:,:,:,:,2:input.numPred + 1), "SSSCB"), obj.Weights, 0, 'Stride', obj.Stride, 'Padding', obj.PaddingSize, 'DilationFactor', obj.DilationFactor);
Y = cat(5, extractdata(c), extractdata(V));
S = VolumeStar(Y, input.C, input.d, input.pred_lb, input.pred_ub);

end
Expand All @@ -419,7 +419,7 @@ function set_name(obj, name)
% @volumes: an array of VolumeStars output set

n = length(in_volumes);
volumes(n) = IVolumeStar;
volumes(n) = VolumeStar;

if strcmp(option, 'parallel')
parfor i=1:n
Expand Down
6 changes: 3 additions & 3 deletions code/nnv/engine/nn/layers/FlattenLayer.m
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@
elseif length(n) == 3
flatten_im = reshape(image, [1 1 n(1)*n(2)*n(3)]);
elseif length(n) == 4
flatten_im = reshape(image, [1 1 n(1)*n(2)*n(3)*n(4)]);
flatten_im = reshape(image, [1 1 1 n(1)*n(2)*n(3)*n(4)]);
else
error('Invalid input.');
end
Expand Down Expand Up @@ -158,7 +158,7 @@
% author: Dung Tran
% date: 6/9/2020

if isa(in_set, 'ImageStar') || ~isa(in_set, 'ImageZono')
if isa(in_set, 'ImageStar') || isa(in_set, 'ImageZono')
N = in_set.height*in_set.width*in_set.numChannel;
n = in_set.numPred;
V(1, 1, :, in_set.numPred + 1) = zeros(N, 1);
Expand Down Expand Up @@ -196,7 +196,7 @@
elseif isa(inputs(1), 'ImageZono')
S(n) = ImageZono;
elseif isa(inputs(1), 'VolumeStar')
S(n) = VolumeStar;
S(n) = Star; % convert to Star as we move to a 2D set
else
error('Unknown input data set');
end
Expand Down
7 changes: 5 additions & 2 deletions code/nnv/engine/nn/layers/FullyConnectedLayer.m
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,12 @@
x = reshape(x, [n(1)*n(2) 1]);
elseif length(n) == 3
x = reshape(x, [n(1)*n(2)*n(3) 1]);
elseif length(n) == 4
x = reshape(x, [n(1)*n(2)*n(3)*n(4) 1]);
else
error('Invalid input image');
error('Invalid input');
end

if size(x, 1) ~= size(obj.Weights, 2)
error('Inconsistent input vector')
end
Expand All @@ -127,7 +130,7 @@
% author: Neelanjana Pal
% date: 1/6/2023

y = double(obj.Weights)*input + double(obj.Bias);
y = obj.Weights*input + obj.Bias;
end

% main reachability analysis function
Expand Down
6 changes: 3 additions & 3 deletions code/nnv/engine/nn/layers/Image3DInputLayer.m
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@
% @in_image: an input ImageStar
% @image: an output ImageStar

if ~isa(in_image, 'ImageStar')
error('Input is not an ImageStar');
if ~isa(in_image, 'VolumeStar')
error('Input is not an VolumeStar');
end

% Compute normalization
Expand All @@ -95,7 +95,7 @@
% or a single ImageStar set

n = length(in_images);
images(n) = ImageStar;
images(n) = VolumeStar;

if strcmp(option, 'parallel')
parfor i=1:n
Expand Down
36 changes: 24 additions & 12 deletions code/nnv/engine/nn/layers/ReluLayer.m
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@

end

% evaluation method
methods

methods % evaluation methods

function y = evaluate(~, input)
% @input: 2 or 3-dimensional array, for example, input(:, :, :),
Expand All @@ -41,18 +41,17 @@
% date: 6/26/2019

% @y: high-dimensional array (output volume)

n = size(input);
N = 1;
for i=1:length(n)
N = N*n(i);
end
N = prod(n);

I = reshape(input, [N 1]);
y = PosLin.evaluate(I);
y = reshape(y, n);

end


function y = evaluateSequence(~, input)
% @input: 2 or 3-dimensional array, for example, input(:, :, :),
% @y: 2 or 3-dimensional array, for example, y(:, :, :)
Expand Down Expand Up @@ -84,11 +83,24 @@
% update: 7/15/2020: add display option
% update 7/16/2020: add lp_solver option

if ~isa(in_image, 'ImageStar') && ~isa(in_image, 'Star')
error('input is not an ImageStar or Star');
if ~isa(in_image, 'VolumeStar') && ~isa(in_image, 'ImageStar') && ~isa(in_image, 'Star')
error('input is not an ImageStar, Star or VolumeStar');
end

if isa(in_image, 'ImageStar')
if isa(in_image, 'VolumeStar')
% get dimensions of VolumeStar
h = in_image.height;
w = in_image.width;
dp = in_image.depth;
c = in_image.numChannel;
% transform to star and compute relu reachability
Y = PosLin.reach(in_image.toStar, method, [], relaxFactor); % reachable set computation with ReLU
n = length(Y);
% transform back to VolumeStar
images(n) = VolumeStar;
for i=1:n
images(i) = Y(i).toVolumeStar(h,w,dp, c);
end
elseif isa(in_image, 'ImageStar')
h = in_image.height;
w = in_image.width;
c = in_image.numChannel;
Expand Down
Loading

0 comments on commit cca95e5

Please sign in to comment.