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 2: Learning with structure

Week 2, Day 2: Neuro-Symbolic Methods

By Neuromatch Academy

Content creators: P. Michael Furlong, Chris Eliasmith

Content reviewers: Hlib Solodzhuk, Patrick Mineault, Aakash Agrawal, Alish Dipani, Hossein Rezaei, Yousef Ghanbari, Mostafa Abdollahi, Alex Murphy

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


Tutorial Objectives

Estimated timing of tutorial: 20 minutes

This tutorial will present you with a couple of play-examples on the usage of basic operations of vector symbolic algebras while generalizing to the new knowledge.


Setup (Colab Users: Please Read)

Note that because this tutorial relies on some special Python packages, these packages have requirements for specific versions of common scientific libraries, such as numpy. If you’re in Google Colab, then as of May 2025, this comes with a later version (2.0.2) pre-installed. We require an older version (we’ll be installing 1.24.4). This causes Colab to force a session restart and then re-running of the installation cells for the new version to take effect. When you run the cell below, you will be prompted to restart the session. This is entirely expected and you haven’t done anything wrong. Simply click ‘Restart’ and then run the cells as normal.

An additional error might sometimes arise where an exception is raised connected to a missing element of NumPy. If this occurs, please restart the session and re-run the cells as normal and this error will go away. Updated versions of the affected libraries are expected out soon, but sadly not in time for the preparation of this material. We thank you for your understanding.

Install dependencies

Source

Install and import feedback gadget

Source

Imports

Source

Figure settings

Source

Plotting functions

Source

Set random seed

Source

Helper functions

Source

Section 1: Wason Card Task

One of the powerful benefits of using these structured representations is being able to generalize to other circumstances. To demonstrate this, we are going to show you this in a simple task.

Video 1: Wason Card Task Intro

Youtube
Bilibili

Coding Exercise 1: Wason Card Task

We are going to test the generalization property on the Wason Card Task, where a person is told a rule of the form “if the card is even, then the back is blue”, they are then presented with a number of cards with either an odd number, an even number, a red back, or a blue back. The participant is asked which cards they have to flip to determine that the rule is true.

In this case, the participant needs to flip only the even card(s), and any card where the back is not blue, as the rule does not state whether or not odd numbers can have blue backs, and a red-backed card with an even number would violate the rule. We can get this from Boolean logic:

even  ⟹  blue\mathrm{even} \implies \mathrm{blue}

which is equal to

¬even∨blue\neg \mathrm{even} \vee \mathrm{blue}

where ¬\neg means a logical not. If we want to find cards that violate the rule, then we negate the rule, providing:

¬(¬even∨blue)=even∧¬blue.\neg (\neg \mathrm{even} \vee \mathrm{blue}) = \mathrm{even} \wedge \neg \mathrm{blue}.

Hence the cards that can violate the rule are even and not blue.

At first, we will define all needed concepts. For all noun concepts we would also like to have not concept presented in the space, please complete missing code parts.

---------------------------------------------------------------------------
NotImplementedError                       Traceback (most recent call last)
Cell In[8], line 10
      6 vocab.populate(';'.join(card_states))
      8 ###################################################################
      9 ## Fill out the following then remove
---> 10 raise NotImplementedError("Student exercise: complete creating `not x` concepts.")
     11 ###################################################################
     13 for a in ['RED','BLUE','ODD','EVEN','GREEN','PRIME']:

NotImplementedError: Student exercise: complete creating `not x` concepts.

Now, we are going to set up a simple perceptron-style learning rule, using the HRR (Holographic Reduced Representations) algebra. We are going to learn a target transformation, TT, such that given a learning rule, A∗=T⊛RA^{*} = T\circledast R, where A∗A^{*} is the antecedant value bundled with not\texttt{not} bound with the consequent value, because we are trying to learn the cards that can violate the rule, described above, and RR is the rule to be learned.

Rules themselves are going to be composed like the data structures representing different countries in the previous section. ant, relation and cons are extra concepts which define the structure and which will bind to the specific instances.

If we have a rule, X  ⟹  YX \implies Y, then we would create the VSA representation:

R=ant⊛X+relation⊛implies+cons⊛YR = \texttt{ant}\circledast X + \texttt{relation}\circledast \text{implies} + \texttt{cons} \circledast Y

,

and the ideal output is:

A∗=X+not⊛YA^{*} = X + \texttt{not}\circledast Y

In the cell below, let us define two rules:

blue  ⟹  even\text{blue} \implies \text{even}
odd  ⟹  green\text{odd} \implies \text{green}
---------------------------------------------------------------------------
NotImplementedError                       Traceback (most recent call last)
Cell In[9], line 3
      1 ###################################################################
      2 ## Fill out the following then remove
----> 3 raise NotImplementedError("Student exercise: complete creating rules as defined above.")
      4 ###################################################################
      6 rules = [
      7     (vocab['ANT'] * vocab['BLUE'] + vocab['RELATION'] * vocab['IMPLIES'] + vocab['CONS'] * vocab[...]).normalized(),
      8     (vocab[...] * vocab[...] + vocab[...] * vocab[...] + vocab[...] * vocab[...]).normalized(),
      9 ]

NotImplementedError: Student exercise: complete creating rules as defined above.

Now, we are ready to derive the transformation! For that, we will iterate through the rules and solutions for specified number of iterations and update it as the following:

ΔT←T−lr∗(A∗⊛∼R)\Delta T \leftarrow T - \text{lr}*(A^{*} \circledast \sim R)

where lr\text{lr} is learning rate constant value. Ultimately, we want A∗=T⊛RA^{*} = T\circledast R, so we unbind RR to recorver the desired transform, and use the learning rule to update our current estimated transform.

We will also compute loss progression over the time and log loss function between perfect similarity (ones only for antecedance value and not consequent one) and the one we obtain between prediciton for current transformation and full action space. Complete missing parts of the code in the next cell to complete training.

---------------------------------------------------------------------------
NotImplementedError                       Traceback (most recent call last)
Cell In[10], line 3
      1 ###################################################################
      2 ## Fill out the following then remove
----> 3 raise NotImplementedError("Student exercise: complete training loop.")
      4 ###################################################################
      6 num_iters = 500

NotImplementedError: Student exercise: complete training loop.
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[11], line 2
      1 plt.figure(figsize=(15,5))
----> 2 plot_training_and_choice(losses, sims, ant_names, cons_names, action_names)

NameError: name 'losses' is not defined
<Figure size 1500x500 with 0 Axes>

Let’s see what happens when we test it on a new rule it hasn’t seen before. This time we will use the rule that red  ⟹  prime\text{red} \implies \text{prime}. Your task is to complete new rule in the cell below and observe the results.

---------------------------------------------------------------------------
NotImplementedError                       Traceback (most recent call last)
Cell In[12], line 3
      1 ###################################################################
      2 ## Fill out the following then remove
----> 3 raise NotImplementedError("Student exercise: complete new rule and predict for it.")
      4 ###################################################################
      6 new_rule = (vocab['ANT'] * vocab[...] + vocab['RELATION'] * ... + vocab['CONS'] * vocab[...]).normalized()

NotImplementedError: Student exercise: complete new rule and predict for it.
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[13], line 2
      1 plt.figure(figsize=(7,5))
----> 2 plot_choice([new_sims], ["RED"], ["PRIME"], action_names)

NameError: name 'new_sims' is not defined
<Figure size 700x500 with 0 Axes>

Let’s compare how a standard MLP that isn’t aware of the structure in the representation performs. Here, features are going to be the rules and output - solutions. Complete the code below.

---------------------------------------------------------------------------
NotImplementedError                       Traceback (most recent call last)
Cell In[14], line 3
      1 ###################################################################
      2 ## Fill out the following then remove
----> 3 raise NotImplementedError("Student exercise: complete MLP training.")
      4 ###################################################################
      5 
      6 #features - rules
      7 X_train = np.array(...).squeeze()

NotImplementedError: Student exercise: complete MLP training.
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[15], line 1
----> 1 plot_choice([mlp_sims], ["RED"], ["PRIME"], action_names)

NameError: name 'mlp_sims' is not defined

As you can see, this model, even though it is a more expressive neural network, simply learns to predict the values it had seen before when presented with a novel stimulus.

Video 2: Wason Card Task Outro

Youtube
Bilibili

The Big Picture

What we saw in this tutorial is the power of generalization at work, that the two top responses were indeed GREEN and NOT PRIME, as Michael outlined in the Outro video. The theme of generalization is the cornerstone of this course and one of the most fundamental aspects we want to convey to you in your NeuroAI journey with us. This tutorial highlights yet another way in which this can be achieved, through the special language of VSA. The MLP does not have access to the structural components and fails to generalize on this task. This is one of the key benefits of the VSA method, where the connection to learning underlying structures allows for generalization to occur.

We have a bonus tutorial today (Tutorial 4) that covers some other cases connected to analogies, which will help to clarify and demonstrate the power of VSAs even more. We really encourage you to check out that material and then maybe revisit this tutorial if you had any trouble following along.