Skip to content

Changes for MNIST MLP experiment#287

Merged
ttj merged 8 commits intoverivital:masterfrom
cirens-utd:master
Dec 2, 2025
Merged

Changes for MNIST MLP experiment#287
ttj merged 8 commits intoverivital:masterfrom
cirens-utd:master

Conversation

@m-usama-z
Copy link
Contributor

Hello Professor @ttj and @sammsaski,

Fortunately, I was able to finish making changes for the FC layer quickly. I maintained the entirety of changes in FullyConnectedLayer.m including the multi-layer case, but these are primarily two changes: an object variable weightPerturb and the weight perturbation addition to the reachability analysis code which runs only when weightPerturb is non-empty. I added the required helper functions in a utility file utils/WPutils.m as static functions, and modified the experiment conv_expt_any_layer.m accordingly. The instructions for launching the experiment remain the same as described in the original PR.

Unless I am fogetting something, the only additional change required to match up to the description in the paper would be the update to Conv2DLayer.m, which I can go ahead and try if it is desirable simultaneously, but that is not needed for the MNIST MLP experiment. That would be a change similar to FullyConnectedLayer.m, i.e., it uses a weightPerturb object variable and reachability code that runs only when that variable is non-empty. Please feel free to take a look at the changes in Conv2DLayer.m in the original pull request and let me know if it is desirable at the moment.

@sammsaski
Copy link
Contributor

Hi Usama,

Thanks so much! I've just skimmed over the changes and this looks great! It doesn't look like it will affect any of the other existing code in NNV.

I have also just looked over the Conv2DLayer.m changes from your other PR and I believe they shouldn't affect any of the existing code in NNV either, so I think safe to include as well.

As far as I can tell, for both FullyConnectedLayer.m and Conv2DLayer.m, you have added some additional properties weightPerturb = 0 and methods that do not impact other methods already implemented. Additionally, all of the logic of doing the reachability is hidden behind a conditional statement if ~isempty(obj.weightPerturb), which should only be true when our specification is defined with weight perturbations, correct? If so, then this will not affect any of the existing code either and will instead be skipped.

If my understanding is accurate, then I think it's safe to merge. Thanks again, Usama!

@m-usama-z
Copy link
Contributor Author

@sammsaski, you're right; weightPerturb is initialized to [] and the ifcondition ensures that this code will not interfere with the existing analysis if no weight perturbations are specified. I have added the changes in Conv2DLayer.m and also the corresponding test in tests/weightPerturb. I also added the collins RUL tutorial, but that required a little change in NN/verify_vnnlib but this change is still based on options only, so it does not interfere with existing analysis. Although, I can remove this tutorial or adjust the modification to the NN/verify_vnnlib function as needed. Please feel free to ask for any help in adding the experiment to the paper, or if any problem still arises after merging (although there shouldn't be any, the changes are isolated and simple). As for the refactoring of this PR's code as well as integration of any other desirable features, we can discuss those after about two weeks or so; I have to finish work on another deadline at the moment.

Professor @ttj, please feel free to take a quick look and kindly proceed with the merge if everything looks ok.

Thank you all for your time and coordination.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements weight perturbation functionality for neural network layers to support the MNIST MLP experiment, enabling robustness analysis under weight uncertainty. The changes focus primarily on FullyConnectedLayer.m and Conv2DLayer.m, with supporting utilities in WPutils.m and experimental infrastructure.

Key changes:

  • Added weightPerturb property and reachability analysis logic to FullyConnectedLayer and Conv2DLayer for handling weight perturbations
  • Implemented WPutils static utility class with helper functions for weight perturbation analysis, sampling, and system resource monitoring
  • Modified NN.verify_vnnlib to support input reshaping and single average input options

Reviewed changes

Copilot reviewed 14 out of 17 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
code/nnv/engine/nn/layers/FullyConnectedLayer.m Added weightPerturb property and ImageStar-based reachability logic for weight perturbations
code/nnv/engine/nn/layers/Conv2DLayer.m Added weightPerturb property, GPU memory management, and parallel processing for weight perturbations
code/nnv/engine/utils/WPutils.m New utility class with static methods for weight perturbation, sampling, verification, and system monitoring
code/nnv/engine/nn/NN.m Enhanced verify_vnnlib with input reshaping and added get_layer_indices helper method
code/nnv/engine/utils/matlab2nnv.m Added matlabnet property assignment to NN objects
code/nnv/examples/Tutorial/NN/MNIST/weightPerturb/single_layer/conv_expt_any_layer.m Main experiment script for running weight perturbation experiments
code/nnv/examples/Tutorial/NN/MNIST/weightPerturb/single_layer/EXPT.m Experiment configuration management class with YAML persistence and plotting
code/nnv/tests/weightPerturb/test_fc_layer_perturbation.m Test for FC layer weight perturbation with sampling validation
code/nnv/tests/weightPerturb/test_conv_layer_perturbation.m Test for Conv2D layer weight perturbation with sampling validation
code/nnv/examples/Tutorial/NN/Collins_RUL/collins_RUL_tutorial.m Tutorial demonstrating weight perturbation on Collins RUL CNN
code/nnv/examples/Tutorial/NN/MNIST/weightPerturb/single_layer/results/*.yaml YAML configuration files for experiment specifications
.gitignore Added *.asv to ignore MATLAB autosave files

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.


% specify a symmetric perturbation to be applied to the whole layer
% as a fraction of the range of the weights in the layer
function pert_whole_layer_given_fraction_of_weights_range_call_fromLayer(layer, frac)
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function name contains a typo: "pert_whole_layer_given_fraction_of_weights_range_call_fromLayer" should be "pert_whole_layer_given_fraction_of_weights_range_call_from_layer" (missing underscore before "Layer"). This is inconsistent with the naming pattern of other similar functions like "add_pert_call_this_function_from_layer" and "perturb_whole_layer_call_this_function_from_layer".

Suggested change
function pert_whole_layer_given_fraction_of_weights_range_call_fromLayer(layer, frac)
function pert_whole_layer_given_fraction_of_weights_range_call_from_layer(layer, frac)

Copilot uses AI. Check for mistakes.
% @frac: fraction of the weights' range to be applied as
% perturbation to the whole layer

WPutils.pert_whole_layer_given_fraction_of_weights_range_call_fromLayer(obj, frac);
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function name has an inconsistent naming pattern: "pert_whole_layer_given_fraction_of_weights_range_call_fromLayer" uses a capital "L" in "fromLayer" while other functions in this class use all lowercase with underscores (e.g., "call_this_function_from_layer"). This is also called from FullyConnectedLayer and Conv2DLayer, so fixing it would require updating those files as well.

Suggested change
WPutils.pert_whole_layer_given_fraction_of_weights_range_call_fromLayer(obj, frac);
WPutils.pert_whole_layer_given_fraction_of_weights_range_call_from_layer(obj, frac);

Copilot uses AI. Check for mistakes.
% @frac: fraction of the weights' range to be applied as
% perturbation to the whole layer

WPutils.pert_whole_layer_given_fraction_of_weights_range_call_fromLayer(obj, frac);
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function name has an inconsistent naming pattern: "pert_whole_layer_given_fraction_of_weights_range_call_fromLayer" uses a capital "L" in "fromLayer" while other functions in this class use all lowercase with underscores (e.g., "call_this_function_from_layer"). This is also called from FullyConnectedLayer, so fixing it would require updating that file as well.

Suggested change
WPutils.pert_whole_layer_given_fraction_of_weights_range_call_fromLayer(obj, frac);
WPutils.pert_whole_layer_given_fraction_of_weights_range_call_from_layer(obj, frac);

Copilot uses AI. Check for mistakes.
Comment on lines +30 to +33
if strcmp(nn_name, "MNIST_MLP")
folder = [nnvroot(), filesep, 'code', filesep, 'nnv', filesep, 'examples', filesep, 'Tutorial', filesep, 'NN', filesep, 'MNIST', filesep, 'weightPerturb', filesep];
mnist_model = load([folder 'mnist_model_fc.mat']);
end
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant condition: The outer switch statement already filters for nn_name == "MNIST_MLP" at line 29, so the inner if strcmp(nn_name, "MNIST_MLP") check at line 30 is redundant and will always be true. This condition can be removed.

Suggested change
if strcmp(nn_name, "MNIST_MLP")
folder = [nnvroot(), filesep, 'code', filesep, 'nnv', filesep, 'examples', filesep, 'Tutorial', filesep, 'NN', filesep, 'MNIST', filesep, 'weightPerturb', filesep];
mnist_model = load([folder 'mnist_model_fc.mat']);
end
folder = [nnvroot(), filesep, 'code', filesep, 'nnv', filesep, 'examples', filesep, 'Tutorial', filesep, 'NN', filesep, 'MNIST', filesep, 'weightPerturb', filesep];
mnist_model = load([folder 'mnist_model_fc.mat']);

Copilot uses AI. Check for mistakes.
end
end

if needReshape > 0.1
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Unclear conditional check: Using needReshape > 0.1 is an unusual way to check if reshaping is needed. Since needReshape has a default value of 0 and can be 1 or 2, it would be clearer to use needReshape > 0 or needReshape ~= 0 instead of > 0.1. The current threshold of 0.1 seems arbitrary and could be confusing.

Suggested change
if needReshape > 0.1
if needReshape > 0

Copilot uses AI. Check for mistakes.
m-usama-z and others added 4 commits December 1, 2025 18:07
Fixed error message

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@m-usama-z
Copy link
Contributor Author

Thank you for the Copilot review, Professor @ttj. I integrated some of the refinements; there were no logical issues (there was a string + number concatenation issue in an error call, which would have errored anyways). I did not fix the function name pert_whole_layer_given_fraction_of_weights_range_call_fromLayer as I was trying to keep the function names descriptive and in the process, hit the MATLAB function name length limit for this function. Please feel free to suggest modifications if necessary.

@ttj
Copy link
Contributor

ttj commented Dec 2, 2025

Thanks Usama! I am going to merge this now, please don't make further edits

@ttj ttj marked this pull request as ready for review December 2, 2025 01:17
@ttj ttj merged commit 4776821 into verivital:master Dec 2, 2025
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@m-usama-z

after merging, I tried to run this test, and got the following error. is this load_images function somewhere?

please make a new pull request with it if some files were missed

Running test_conv_layer_perturbation

================================================================================
Error occurred in test_conv_layer_perturbation/test_conv_layer_perturbation and it did not run to completion.
    ---------
    Error ID:
    ---------
    'MATLAB:UndefinedFunction'
    --------------
    Error Details:
    --------------
    Undefined function 'load_images' for input arguments of type
    'SeriesNetwork'.
    
    Error in test_conv_layer_perturbation (line 33)
    [images, labels] = load_images(database = "mnist", ...
================================================================================
.
Done test_conv_layer_perturbation
__________

Failure Summary:

     Name                                                       Failed  Incomplete  Reason(s)
    ==========================================================================================
     test_conv_layer_perturbation/test_conv_layer_perturbation    X         X       Errored.

ans = 
  TestResult with properties:

          Name: 'test_conv_layer_perturbation/test_conv_layer_perturbation'
        Passed: 0
        Failed: 1
    Incomplete: 1
      Duration: 1.9026
       Details: [1×1 struct]

Totals:
   0 Passed, 1 Failed, 1 Incomplete.
   1.9026 seconds testing time.

@m-usama-z
Copy link
Contributor Author

My apologies, it appears that my MATLAB was using this function from the path of another copy of NNV on the machine. I will create another PR with this function in the utils.

@m-usama-z
Copy link
Contributor Author

Professor @ttj, could you please let me know whether I should go ahead and add a description of the MNIST MLP experiment, along with corresponding plots? Once I add it, @sammsaski can revise or adjust it as needed. I wasn’t entirely sure whether you preferred that I draft the initial description or that @sammsaski do so.

@sammsaski
Copy link
Contributor

I think I can speak for @ttj here. Please feel free to add an initial description of the experiment along with the corresponding plots!

@m-usama-z
Copy link
Contributor Author

Sure, I'll do so tomorrow then, while limiting the experiment to the last 3 layers of the MLP and using 100 images as in the code provided.

@ttj
Copy link
Contributor

ttj commented Dec 2, 2025

yes, thanks Usama, also please make sure to add yourselves as co-authors given the contribution, thanks for the updates too! I think everything ran fine, so I think will be great to include, thanks for all the hard work

@m-usama-z
Copy link
Contributor Author

Sure, Professor. Just one more thing I thought I'd clarify: while my instance of MATLAB was using load_images from the path of another copy of NNV, those paths were superseded by the paths of the copy of NNV I was working on for the PR, so there should be no versioning conflicts. There could only have been missing file issues, which appear to have been resolved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants