Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Open In Colab   Open in Kaggle

Tutorial 1: Generalization and representational geometry

Week 1, Day 3: Comparing artificial and biological neural networks

By Neuromatch Academy

Content creators: JohnMark Taylor & Zhuofan Josh Ying

Content reviewers: Samuele Bolotta, Yizhou Chen, RyeongKyung Yoon, Ruiyi Zhang, Lily Chamakura, Patrick Mineault, Hlib Solodzhuk, Alex Murphy

Production editors: Konstantine Tsafatinos, Ella Batty, Spiros Chavlis, Samuele Bolotta, Hlib Solodzhuk, Patrick Mineault, Alex Murphy


Tutorial Objectives

Estimated timing of tutorial: 40 minutes

Welcome to Tutorial 1 on Generalization and Representational Geometry. Building on the Intro Lecture, this tutorial aims to help you get your feet wet and characterize representations in terms of their geometry, as captured by the distances among inputs at different stages of processing. The key point of this tutorial is that the way machine learning models generalize depends on how they represent their inputs and, in particular, on how similar a new input is to other inputs in the internal representations. We focus on linear models, where the close relationship between similarity and generalization can be most easily understood from an intuitive and mathematical perspective.

By the end of this tutorial, you will:

  • Understand the concept of representational geometry and the representational dissimilarity matrix.

  • Understand the connection between generalization and representational similarity in the linear case.

  • Understand how the analytic solution for linear regression can be seen as a weighted sum of training values, weighted by the test inputs’ similarity to the training inputs.

Exercises include:

  1. Question on comparing RDMs.

  2. Question on the relationship between RDMs and model performances.

  3. Interactive exercise on how similarity structure affects predictions.

This tutorial includes an interactive widget that plays only locally or in Colab, but not in Kaggle.


Setup (Please Read)

This tutorial involves an interactive component as the final element, which depends on some tools that have undergone a change since the last time this course was run (2024). Therefore, if you’re running this on Google Colab, you need to:

  • uncomment the cell below

  • run the cell

This will initially cause the notebook to restart after a few moments, but then you can run all the cells below (in Google Colab: Runtime -> Run Cell and Below) as necessary and the intended functionally will exist. As of the time of writing, this issue has not been corrected and this workaround is required. Please wait until you see the notification of the notebook having restarted before selecting the ‘Run all and below’ menu option.

Additionally, this tutorial uses Graphviz for additional visualizations. For proper execution of the functions, you should install it locally. Please visit this link to get the instructions depending on your local OS configurations (if you are running this notebook on Google Colab, just skip it).

Install dependencies

Source
Requirement already satisfied: rsatoolbox==0.1.5 in /opt/hostedtoolcache/Python/3.10.22/x64/lib/python3.10/site-packages (0.1.5)
Requirement already satisfied: numpy>=1.21.2 in /opt/hostedtoolcache/Python/3.10.22/x64/lib/python3.10/site-packages (from rsatoolbox==0.1.5) (1.26.4)
Requirement already satisfied: scipy in /opt/hostedtoolcache/Python/3.10.22/x64/lib/python3.10/site-packages (from rsatoolbox==0.1.5) (1.12.0)
Requirement already satisfied: scikit-learn in /opt/hostedtoolcache/Python/3.10.22/x64/lib/python3.10/site-packages (from rsatoolbox==0.1.5) (1.4.1.post1)
Requirement already satisfied: scikit-image in /opt/hostedtoolcache/Python/3.10.22/x64/lib/python3.10/site-packages (from rsatoolbox==0.1.5) (0.19.2)
Requirement already satisfied: pandas in /opt/hostedtoolcache/Python/3.10.22/x64/lib/python3.10/site-packages (from rsatoolbox==0.1.5) (2.3.3)
Requirement already satisfied: matplotlib in /opt/hostedtoolcache/Python/3.10.22/x64/lib/python3.10/site-packages (from rsatoolbox==0.1.5) (3.8.3)
Requirement already satisfied: h5py in /opt/hostedtoolcache/Python/3.10.22/x64/lib/python3.10/site-packages (from rsatoolbox==0.1.5) (3.16.0)
Requirement already satisfied: tqdm in /opt/hostedtoolcache/Python/3.10.22/x64/lib/python3.10/site-packages (from rsatoolbox==0.1.5) (4.66.2)
Requirement already satisfied: joblib in /opt/hostedtoolcache/Python/3.10.22/x64/lib/python3.10/site-packages (from rsatoolbox==0.1.5) (1.6.0)
Requirement already satisfied: cloudpickle>=3.0 in /opt/hostedtoolcache/Python/3.10.22/x64/lib/python3.10/site-packages (from joblib->rsatoolbox==0.1.5) (3.1.2)
Requirement already satisfied: contourpy>=1.0.1 in /opt/hostedtoolcache/Python/3.10.22/x64/lib/python3.10/site-packages (from matplotlib->rsatoolbox==0.1.5) (1.3.2)
Requirement already satisfied: cycler>=0.10 in /opt/hostedtoolcache/Python/3.10.22/x64/lib/python3.10/site-packages (from matplotlib->rsatoolbox==0.1.5) (0.12.1)
Requirement already satisfied: fonttools>=4.22.0 in /opt/hostedtoolcache/Python/3.10.22/x64/lib/python3.10/site-packages (from matplotlib->rsatoolbox==0.1.5) (4.65.0)
Requirement already satisfied: kiwisolver>=1.3.1 in /opt/hostedtoolcache/Python/3.10.22/x64/lib/python3.10/site-packages (from matplotlib->rsatoolbox==0.1.5) (1.5.1)
Requirement already satisfied: packaging>=20.0 in /opt/hostedtoolcache/Python/3.10.22/x64/lib/python3.10/site-packages (from matplotlib->rsatoolbox==0.1.5) (26.3)
Requirement already satisfied: pillow>=8 in /opt/hostedtoolcache/Python/3.10.22/x64/lib/python3.10/site-packages (from matplotlib->rsatoolbox==0.1.5) (10.2.0)
Requirement already satisfied: pyparsing>=2.3.1 in /opt/hostedtoolcache/Python/3.10.22/x64/lib/python3.10/site-packages (from matplotlib->rsatoolbox==0.1.5) (3.3.3)
Requirement already satisfied: python-dateutil>=2.7 in /opt/hostedtoolcache/Python/3.10.22/x64/lib/python3.10/site-packages (from matplotlib->rsatoolbox==0.1.5) (3.0.0)
Requirement already satisfied: six>=1.6 in /opt/hostedtoolcache/Python/3.10.22/x64/lib/python3.10/site-packages (from python-dateutil>=2.7->matplotlib->rsatoolbox==0.1.5) (1.17.0)
Requirement already satisfied: tzdata in /opt/hostedtoolcache/Python/3.10.22/x64/lib/python3.10/site-packages (from python-dateutil>=2.7->matplotlib->rsatoolbox==0.1.5) (2026.6)
Requirement already satisfied: pytz>=2020.1 in /opt/hostedtoolcache/Python/3.10.22/x64/lib/python3.10/site-packages (from pandas->rsatoolbox==0.1.5) (2026.6)
Requirement already satisfied: networkx>=2.2 in /opt/hostedtoolcache/Python/3.10.22/x64/lib/python3.10/site-packages (from scikit-image->rsatoolbox==0.1.5) (3.2.1)
Requirement already satisfied: imageio>=2.4.1 in /opt/hostedtoolcache/Python/3.10.22/x64/lib/python3.10/site-packages (from scikit-image->rsatoolbox==0.1.5) (2.38.0)
Requirement already satisfied: tifffile>=2019.7.26 in /opt/hostedtoolcache/Python/3.10.22/x64/lib/python3.10/site-packages (from scikit-image->rsatoolbox==0.1.5) (2025.5.10)
Requirement already satisfied: PyWavelets>=1.1.1 in /opt/hostedtoolcache/Python/3.10.22/x64/lib/python3.10/site-packages (from scikit-image->rsatoolbox==0.1.5) (1.8.0)
Requirement already satisfied: threadpoolctl>=2.0.0 in /opt/hostedtoolcache/Python/3.10.22/x64/lib/python3.10/site-packages (from scikit-learn->rsatoolbox==0.1.5) (3.8.0)

Install and import feedback gadget

Source

Import dependencies

Source

Figure settings

Source

Plotting functions

Source

Helper functions

Source

Data retrieval

Source

Set random seed

Source

Set device (GPU or CPU)

Source
GPU is not enabled in this notebook. 
If you want to enable it, in the menu under `Runtime` -> 
`Hardware accelerator.` and select `GPU` from the dropdown menu

Video 1: Tutorial Introduction

Youtube
Bilibili

Section 1: MNIST DNN Comparisons

In this section, we are going to take a look at the MNIST Dataset and its adversarial version.

In this activity, you will use linear regression on representations of two neural networks trained on MNIST, one with adversarial training and one without. The objective is to observe:

  • How predictions for clean images of numbers are similar between networks for a deep layer

  • The close alignment of the predictions with the category structure

  • How the dissimilarity matrix reflects a category structure

  • How dissimilarity matrices from the two networks compare

  • The significant differences in predictions and dissimilarity matrices when applying adversarial examples

Understanding the MNIST DNNs

We start by defining two models on the MNIST dataset: a standard model and an adversarially robust model. The training process for the adversarially robust model includes a step where adversarial examples are generated and used to train the robust model.

You are already provided with the trained models to save time. Still, you are free to explore the training code being included in the tutorial.

Defining the MNIST Model

First, we define a neural network model that will be trained on the MNIST dataset. The MNIST dataset consists of 28x28 pixel images of handwritten digits (0 through 9). Our model, based on the LeNet architecture, includes two convolutional layers followed by dropout layers to reduce overfitting and, finally, fully connected layers to perform classification.

MNIST Model

Source

Training the Standard Model

Once the model is defined, we would normally proceed to train it on the MNIST dataset. Training involves feeding batches of images and their corresponding labels to the model and adjusting the model’s weights based on the loss computed from its predictions and the actual labels through backpropagation and gradient descent. This process is iterated over multiple epochs to improve the model’s accuracy.

The training code is copied here for reference in a commented block. We ran this code offline and saved a checkpoint. In the interest of time, we’ll skip ahead to loading this checkpoint into the model.

Build and train the model

Source

Grab a pretrained model

Source
  0%|          | 0/9912422 [00:00<?, ?it/s]
100%|██████████| 9912422/9912422 [00:00<00:00, 99325603.81it/s]

  0%|          | 0/28881 [00:00<?, ?it/s]
100%|██████████| 28881/28881 [00:00<00:00, 21562067.25it/s]

  0%|          | 0/1648877 [00:00<?, ?it/s]
100%|██████████| 1648877/1648877 [00:00<00:00, 65529248.87it/s]

  0%|          | 0/4542 [00:00<?, ?it/s]
100%|██████████| 4542/4542 [00:00<00:00, 1548697.57it/s]

Adversarial Attack & Model Robustness

Generating Adversarial Examples

Adversarial examples are inputs to machine learning models that an attacker has intentionally designed to cause the model to make a mistake. They are often indistinguishable from real data by humans but result in incorrect predictions by the model. Generating these examples and using them in training can improve a model’s robustness against such attacks.

Grab 5 test images from each category and visualize them

Source
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).
<Figure size 800x600 with 1 Axes>

Here, we generate adversarial images using the Fast Gradient Sign Method (FGSM). This is a popular and straightforward adversarial attack technique designed to test the robustness of neural networks. Developed by Ian Goodfellow and his colleagues in 2014, FGSM backprops through the neural network to create perturbed inputs that maximize the loss:

perturbed image=image+ϵ⋅sign(∇imageJ(image,true label))\text{perturbed image} = \text{image} + \epsilon \cdot \text{sign}(\nabla_{\text{image}} J(\text{image}, \text{true label}))

where:

  • perturbed image\text{perturbed image} is the adversarial image

  • image\text{image} is the original input image

  • ϵ\epsilon is the magnitude of the perturbation

  • ∇imageJ(image,true label)\nabla_{\text{image}} J(\text{image}, \text{true label}) is the gradient of the loss with respect to the input image

  • sign(⋅)\text{sign}(\cdot) returns the sign of the argument (either 1 or -1)

Generate adversarial images for the standard model

Source
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).
(-0.5, 139.5, 279.5, -0.5)
<Figure size 800x600 with 1 Axes>

As you can see, the black background from the clean and original images has changed a bit to include intricate patterns that do not affect our interpretation of what digit is being represented overall (because humans focus on the white pixels that make up the MNIST digit). However, this new fluctuating pattern in the background of each image will demonstrate that the models can be tricked into perceiving different digits based on this background pattern. This is the issue we want to solve when training an adversarially robust model.

Training the Adversarially Robust Model

With adversarial examples at hand, we now train a model designed to be robust against such examples. The idea is to include adversarial examples in the training process, enabling the model to learn from and defend against them.

Again, we’ve included the training code in a commented section, and you are presented with an already adversarially trained network.

Train adversirially robust model

Source

Grab an adversarially pretrained model

Source

Generate adversarial images for the adversarially trained model

Source
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).
(-0.5, 139.5, 279.5, -0.5)
<Figure size 800x600 with 1 Axes>

Evaluating Model Robustness

Now that we have a trained model, we evaluate its resistance to adversarial attacks. We do this by testing the models on both standard and adversarial images and comparing their accuracies.

While these adversarially generated images are visually indistinguishable from the original ones, they cause dramatic decreases in the standard model, while the adversarially trained model is robust to this kind of attack.

Test model

Source
For standard model trained without adversarial examples (eps=0.2):
adversarial test accuracy = 30 / 50 = 0.6
For adversrially trained model (eps=0.2):
adversarial test accuracy = 49 / 50 = 0.98

You should observe that the adversarially trained model has much higher accuracy on the adversarial images (98%) than the standard model does (60%) on the same images.

Extracting Model Features and Analyzing Representations

With the models trained and adversarial images generated, we proceed to extract features from different layers of our networks using torchlens, a package for extracting neural network activations and visualizing their computational graph. This will allow us to peer into the data representations at different layers of the models in normal and adversarial conditions.

Extract model features with torchlens

Source
/tmp/ipykernel_5815/794751295.py:348: DeprecationWarning: torchlens.log_forward_pass is deprecated; use torchlens.trace instead. The old paper-era name remains available as a compatibility shim.
  model_history = tl.log_forward_pass(model, imgs, layers_to_save='all', vis_opt=plot)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[20], line 4
      1 # @title Extract model features with torchlens
      3 return_layers = ['input_1', 'conv1', 'conv2', 'fc1', 'fc2']
----> 4 features_model_imgs = extract_features(model, imgs, return_layers, plot = 'rolled') #comment this line if Graphviz installation was unsuccessful for you
      6 features_model_advimgs = extract_features(model, adv_imgs, return_layers)
      7 features_advmodel_imgs = extract_features(model_robust, imgs, return_layers)

Cell In[7], line 348, in extract_features(model, imgs, return_layers, plot)
    335 def extract_features(model, imgs, return_layers, plot='none'):
    336     """
    337     Extracts features from specified layers of the model.
    338 
   (...)
    346     - model_features (dict): A dictionary with layer names as keys and extracted features as values.
    347     """
--> 348     model_history = tl.log_forward_pass(model, imgs, layers_to_save='all', vis_opt=plot)
    349     model_features = {}
    350     for layer in return_layers:

File /opt/hostedtoolcache/Python/3.10.22/x64/lib/python3.10/site-packages/torchlens/__init__.py:424, in _legacy_trace_alias.<locals>._shim(*args, **kwargs)
    422 _warn_legacy_api_name(name, replacement)
    423 if name == "log_forward_pass":
--> 424     return _resolve_top_level("_trace")(*args, **_translate_legacy_trace_kwargs(kwargs))
    425 if name == "validate_model_activations":
    426     kwargs.setdefault("scope", "forward")

TypeError: trace() got an unexpected keyword argument 'vis_opt'

Section 2: Creating and Comparing Representation Dissimilarity Matrices

Estimated timing to here from start of tutorial: 15 minutes

Using the Representational Similarity Analysis (RSA) toolbox, you will create representational dissimilarity matrices (RDMs) for each model and condition (standard and adversarial). These matrices provide a visual representation of how inputs are represented within the network, offering insights into the models’ generalization capabilities and the effects of adversarial training.

What is an RDM?

Before diving into the practical applications, let’s clarify what an RDM is. An RDM is a tool used to measure and visualize the dissimilarities in the responses of a neural system to different inputs. It is represented as a matrix MM where each element MijM_{ij} measures how dissimilar the response patterns in some layer of a neural network are to the ii-th and jj-th input. Let’s consider a particular estimator of representational dissimilarity:

Mij=1−r(xi,xj)M_{ij} = 1 - r(x_i, x_j)

Here r(xi,xj)r(x_i, x_j) is the Pearson correlation coefficient between the representations of the ii-th and jj-th inputs. 1−r(xi,xj)1 - r(x_i, x_j) is also known as the correlation distance, which quantifies the dissimilarity between two inputs.

RDMs help us understand how well a model differentiates between various types of inputs, which is a key aspect of generalization. They are particularly useful in deep learning as they help illustrate the level at which different layers of a network or different networks recognize and differentiate between input categories. A well-performing model will show clear patterns of dissimilarity corresponding to different input categories, especially in deeper layers.

Visualizing RDMs

We first visualize the category structure by computing the RDM of the labels. To see clear blocks in RDMs—where blocks indicate that inputs of the same class are represented similarly—we need to ensure that input images are organized and grouped by their class labels before calculating the RDM. Here, we have 10 classes (numbers 0-9), each class with 5 samples, which sums up to 50 input images. Recall that each element of the RDM MijM_{ij} refers to the dissimilarity between the representations of the ii-th and jj-th inputs. Make sure you understand the figure of RDM of the labels below.

RDMs for the labels (see the category structures)

Source
<Figure size 600x400 with 2 Axes>

Is it clear to you that the block associated with indices 20-25 in the figure above represent similarity of the 5th class label (the digit ‘4’)? If not, go back and re-read the paragraphs above and take care to relate the block structure to the 5 samples per image class.

Now we compute and visualize the RDMs for standard images for both the standard model and the adversarially trained model.

For standard model + standard images

Source
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[22], line 2
      1 # @title For standard model + standard images
----> 2 rdms, rdms_dict = calc_rdms(features_model_imgs)
      3 plot_maps(rdms_dict, "Standard Model with Standard Images")

NameError: name 'features_model_imgs' is not defined

For adversarially trained model + standard images

Source
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[23], line 2
      1 # @title For adversarially trained model + standard images
----> 2 rdms, rdms_dict = calc_rdms(features_advmodel_imgs)
      3 plot_maps(rdms_dict, "Adversarial Trained Model with Standard Images")

NameError: name 'features_advmodel_imgs' is not defined

Think!

  1. For the standard clean images, how do the RDMs change across the model layers, how do they compare to the category structure, and why?

RDMs of the standard model and the adversarially trained model are very similar for clean images.

Now we compute and visualize the RDMs for adversarial images for both the standard model and the adversarially trained model.

For standard model + adversarial images

Source
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[24], line 2
      1 # @title For standard model + adversarial images
----> 2 rdms, rdms_dict = calc_rdms(features_model_advimgs)
      3 plot_maps(rdms_dict, "Standard Model with Adversarial Images")

NameError: name 'features_model_advimgs' is not defined

For adversarially trained model + adversarial images

Source
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[25], line 2
      1 # @title For adversarially trained model + adversarial images
----> 2 rdms, rdms_dict = calc_rdms(features_advmodel_advimgs)
      3 plot_maps(rdms_dict, "Adversarial Trained Model with Adversarial Images")

NameError: name 'features_advmodel_advimgs' is not defined

Think!

  1. For adversarial images, how do the RDMs change when comparing representations from the standard model to the adversarially trained model?

Think!

  1. How do the RDMs relate to the performances of the standard and the adversarially trained models on clean and adversarial images?


Section 3: Interactive Exploration with Widgets

Estimated timing to here from start of tutorial: 30 minutes

In Sections 1 & 2, we saw that networks generalize better when their test stimuli are “similar” to their training stimuli: the network trained only on normal MNIST images generalized poorly to adversarially generated images since they were not part of its training diet, whereas the network trained with adversarial images generalized more effectively to new adversarial images. It turns out that we can sometimes be mathematically precise about how the similarity of training and test examples affects generalization performance. In this interactive example, you will explore the connection between similarity and generalization in the case of linear regression.

The manner in which a readout function generalizes to new inputs depends closely on the similarity of the new inputs to training stimuli--in other words, the more similar a test stimulus is to a training stimulus, the more similar the output of the readout will be. But what do we mean by “similar”? The relevant way to measure “similarity” in each case will depend on the readout function in question. In the case of linear regression, the relevant similarity metric is the kernel (dot product) similarity of the inputs. To see this, you can inspect the matrix form of the least squares solution for regression below:

ypred=Xpred(XtrainTXtrain)−1XtrainTytrainy_{pred} = X_{pred} \left( X_{train}^T X_{train} \right)^{-1} X_{train}^T y_{train}

Note that the predicted outputs for the test stimuli are a weighted combination of the outputs for training stimuli, where the weights depend on the inner products of the training and test stimuli. Thus, the more similar a training stimulus is to a given test stimulus, the more strongly the output for that training stimulus will contribute to the output for that test stimulus. To give another example, in the case of a radial basis function readout, the relevant notion of similarity would be the Euclidean distance between the inputs.

Interactive exercise

In this interactive exercise, you will explore how the similarity between training and test stimuli predicts how the network generalizes. The task is to use linear regression on activations from our MNIST network from above in order to predict how “left-leaning” or “right-leaning” a particular digit image is. You play the role of the human rater providing the outputs for the training data and will rate the leaning direction of each individual training image from 1-10 using the provided sliders (on the left), where a 1 is leaning strongly left, a 10 is leaning strongly right, and a 5 is perfectly upright, with no leaning. Based on these provided ratings, ridge regression is trained under the hood to predict those ratings using the activations from the selected layer of the neural network, and the resulting regression model is then applied to new images, yielding predicted leaning ratings for these images (red numbers at the bottom).

The color-coded matrix shows the dot product similarity between activations for the training images (rows) and test images (columns)--yellow means that the two images are highly similar based on the dot product of the activations for those images, and dark blue means the two images are highly dissimilar. The goal of this exercise is to explore how the predicted leaning direction of the test stimuli is determined by your leaning ratings of the training stimuli, and the similarity of the training and test stimuli.

  1. Using the matrix, find training and test images that are highly similar and play around with the rating of the training image. How much does the predicted leaning rating for the test image change? Try this for a few different pairs.

  2. Now find a highly dissimilar pair and play with the rating. How much does the predicted leaning of the test image change? Try this for a few different pairs.

  3. Using the dropdown menu, you can choose a different layer of the neural network to predict the leaning direction of the images, reflecting different stages of processing in the network. Try a few different layers.

/tmp/ipykernel_5815/2545937697.py:16: DeprecationWarning: torchlens.log_forward_pass is deprecated; use torchlens.trace instead. The old paper-era name remains available as a compatibility shim.
  train_patterns = tl.log_forward_pass(model, train_data)
/opt/hostedtoolcache/Python/3.10.22/x64/lib/python3.10/site-packages/torchlens/backends/torch/wrappers.py:256: UserWarning: TorchLens torch capability HAS_FUNCTORCH_LEVEL_API is unavailable; functorch transform-boundary detection is disabled
  maybe_current_level = get_functorch_maybe_current_level()
/tmp/ipykernel_5815/2545937697.py:17: DeprecationWarning: torchlens.log_forward_pass is deprecated; use torchlens.trace instead. The old paper-era name remains available as a compatibility shim.
  test_patterns = tl.log_forward_pass(model, test_data)

Execute to see the widget!

Source
Could not switch to interactive backend. Please see Setup instructions at the top of the notebook.
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
File /opt/hostedtoolcache/Python/3.10.22/x64/lib/python3.10/site-packages/ipywidgets/widgets/interaction.py:240, in interactive.update(self, *args)
    238     value = widget.get_interact_value()
    239     self.kwargs[widget._kwarg] = value
--> 240 self.result = self.f(**self.kwargs)
    241 show_inline_matplotlib_plots()
    242 if self.auto_display and self.result is not None:

Cell In[28], line 20, in update_and_visualize(layer, rating1, rating2, rating3, rating4, rating5, rating6, rating7, rating8, rating9, rating10)
     18 def update_and_visualize(layer, rating1, rating2, rating3, rating4, rating5,
     19                          rating6, rating7, rating8, rating9, rating10):
---> 20     X_train = train_patterns[layer].tensor_contents.flatten(start_dim=1).detach().cpu().numpy()
     21     X_test = test_patterns[layer].tensor_contents.flatten(start_dim=1).detach().cpu().numpy()
     22     Y_train = [rating1, rating2, rating3, rating4, rating5,
     23                rating6, rating7, rating8, rating9, rating10]

File /opt/hostedtoolcache/Python/3.10.22/x64/lib/python3.10/site-packages/torchlens/data_classes/op.py:1431, in Op.__getattribute__(self, name, _getattribute, _lazy_fields)
   1428 """Materialize lazy grads, copy shared groups, reject unsaved predicate outs."""
   1430 if name not in _lazy_fields:
-> 1431     return _getattribute(self, name)
   1432 if name == "equivalent_ops":
   1433     # One canonical set object backs every Op of an equivalence class;
   1434     # hand out a private copy so no holder can alias-corrupt the group.
   1435     # Non-set legacy/loaded values (e.g. a list) pass through untouched.
   1436     value = _getattribute(self, name)

AttributeError: 'Op' object has no attribute 'tensor_contents'

The Big Picture

Estimated timing of tutorial: 40 minutes

In this tutorial, we explored a foundational issue in artificial intelligence: how can we understand how a system generalizes to new inputs that it wasn’t trained on? We did this through the lens of representational similarity analysis (RSA), the characterization of a system based on the pattern of dissimilarities among a set of stimuli. This tutorial has two parts:

  • In part 1, you used RSA to understand how networks trained in different ways handle adversarial stimuli designed to fool the network.

  • In part 2, you used an interactive widget to understand how a network’s response to a new stimulus depends on its similarity to training stimuli.

The theme of today is tying together similarity measures with generalization. If you’ve struggled in any part with the material so far, the key message to take away from this tutorial is that it makes sense that a system which is trained on a specific distribution has an easier time to generalize to new inputs that look very similar to what was seen during training. If you had a cat-dog classifier and later input images that were dissimilar to the images used in training, this would be more difficult for the model to generalize to. It’s a conceptually simple idea, but until now resisted a comprehensive set of methods to quantify and demonstrate this mathematically.

With that said - Let’s move on to Tutorial 2!