• Github
Table of Contents
0.16.1.0
  • Welcome to PsyNeuLink
  • Basics and Primer
  • Quick Reference
  • Core
  • Library
  • Contributors Guide
  • Docs >
  • Library >
  • Components >
  • Mechanisms >
  • Processing Mechanisms >
  • IntegratorMechanisms >
  • EpisodicMemoryMechanism
Shortcuts

EpisodicMemoryMechanism¶

Contents¶

  • Overview

  • Creating an EpisodicMemoryMechanism
    • InputPorts, Entries and Memory Fields

    • Function Parameters

    • OutputPorts

  • Structure
    • Memory Fields

    • Input

    • Function

    • Output

  • Execution

  • Examples
    • Formatting entries in memory

    • Initializing memory

    • Naming InputPorts and OutputPorts

  • Class Reference

Overview¶

An EpisodicMemoryMechanism is a ProcessingMechanism that can store and retrieve items from a content addressable memory; that is, on each execution it can store an item presented to it as input, and use that to retrieve an item from its memory based on the content of the input. The MemoryFunction assigned as its function determines how items are stored and retrieved. Each memory is a list or array composed of items referred to as memory fields, each of which is a list or array. Memories can have an arbitrary number of fields, and each of those can be of arbitrary shape, however all memories for a given instance of an EpisodicMemoryMechanism must have the same shape (number of fields, and shapes of corresponding fields). Each InputPort of an EpisodicMemoryMechanism provides the input for a corresponding field of a memory to be stored and used for retrieval. By default, each OutputPort contains the value of a field of the last retrieved memory although, as with any Mechanism, OutputPorts can be configured in other ways. The full set of stored memories can be accessed from the Mechanism’s memory attribute, which references its function's memory Parameter. Other Parameters of its function (e.g., that regulate the probability of storage and/or retrieval – see ContentAddressableMemory) can be accessed and/or modulated in the standard way for a Mechanism’s function.

At present, EpisodicMemoryMechanism supports the following two MemoryFunctions:

  • ContentAddressableMemory – a general form of memory, that stores and retrieves memories as described above; any (weighted) combination of its fields can be used for retrieval.

  • DictionaryMemory – a more specific form of memory, that has only two fields, for keys and values, that stores these as pairs; retrieval is based on similarity to the key; this implements a format commonly used by applications that use dictionaries as a form of external memory.

Creating an EpisodicMemoryMechanism¶

InputPorts, Entries and Memory Fields¶

An EpisodicMemoryMechanism is created by calling its constructor with specifications used to implement its MemoryFunction and the shape of entries stored in memory. The latter is determined by the number of fields and shape of each in an entry. These can be specified using any of the following arguments:

  • default_variable or input_shapes – these are specified in the standard way that the variable is specified for any Component (see default_variable, input_shapes, respectively); the specified value is passed to the constructor for the EpisodicMemoryMechanism’s function), which determines the shape of an entry in memory; the memory itself remains empty until the Mechanism is executed and an item is stored.

    Hint

    Use default_variable rather than memory to specify the shape of memory but keep it empty until the first entry is stored; note, however, that since retrieval is executed before storage (see Execution), the first execution will return an entry of zeros.

  • memory – specifies a set of entries to be stored in memory; it is passed to the constructor for the EpisodicMemoryMechanism’s function) as its initializer argument (see initializer for an example).

  • function – this can be used to specify a constructor for the function, in which the default_variable or initializer arguments are used to specify the shape of entries in memory. If default variable is used, memory remains empty until the Mechanism is executed and an item is stored. If initializer is used, the items specified are stored in memory and are available for retrieval in the first execution of the Mechanism (see initializer for an example).

The above specifications are also used to create the input_ports for the Mechanism in the same way that the variable is used for any Mechanism (see Mechanism Variable for additional information), with the number of InputPorts created equal to the number of fields in an entry of memory. Each input_port provides the value assigned to a corresponding field of the entry stored in memory, and used to retrieve one similar to it. By default, input_port are named FIELD_n_INPUT, where “n” is replaced by the index of each field; however, they can be named explicitly by specifying a list of strings in the input_ports argument of the constructor; the number of these must equal the number of fields specified in default_variable or input_shapes.

Function Parameters¶

Parameters that govern the storage and retrieval process are specified as arguments to the MemoryFunction specified in the function of the constructor (for example, see ContentAddressableMemory for parameters of the default function).

OutputPorts¶

By default, a number of OutputPorts is created equal to the number of InputPorts, each named either RETRIEVED_FIELD_n or RETRIEVED_<user specified InputPort name>, that receive the values of the corresponding fields of a retrieved memory. OutputPort names can be specified explicitly, by assigning a list of strings to the output_ports argument of the Mechanism’s constructor; however, in that case, or if any other forms of OutputPort specification are assigned to output_ports, then only the number of OutputPorts specified are created, which may not match the number of fields of a retrieved memory.

Structure¶

Memory Fields¶

Entries in the memory of an EpisodicMemoryMechanism are comprised of fields: lists or 1d arrays within the outer list or array that comprise each entry. An entry can have an arbitrary number of fields, and fields can be of arbitrary length. However, all entries must have the same form (i.e., number of fields and shape of corresponding fields across entries). One InputPort of the EpisodicMemoryMechanism is assigned to each field. Thus, fields can be used to store different types of information in each field, and to retrieve entries from memory based on all fields, or a weighted combination of them (as determined by the MemoryFunction assigned to function; for example, this can be used to configure the default function, ContentAddressableMemory, as a form of key-value dictionary).

The shape of an entry in memory is determined by the shape of the Mechanism’s variable. specified in the default_variable or input_shapes arguments of its constructor (see Creating an EpisodicMemoryMechanism). Each item of variable corresponds to a field. Both memory and all entries are stored in the EpisodicMemoryMechanism’s function as np.ndarrays, the dimensionality of which is determined by the shape of an entry and its fields. Fields are always stored as 1d arrays; if all fields have the same length (regular), then entries are 2d arrays and memory is a 3d array. However, if fields have different lengths (ragged) then, although each field is 1d, an entry is also 1d (with dtype=’object’), and memory is 2d (with dtype=’object’).

Input¶

An EpisodicMemoryMechanism has one or more input_ports that receive the entry to be stored and that is used to retrieve an existing entry from its memory. If the Mechanism is assigned ContentAddressableMemory as its function, then it can have an arbitrary number of InputPorts, the input to which is assigned to the corresponding memory field of that function. By default InputPorts are named FIELD_n_INPUT (see Creating an EpisodicMemoryMechanism). If the Mechanism is assigned DictionaryMemory as its function, then it is assigned at least one InputPort (named KEY_INPUT by default), and optionally a second (named VALUE_INPUT) if default_variable or input_shapes specifies two items; any additional fields are ignored.

Function¶

The default function is ContentAddressableMemory that can store entries with an arbitrary number of fields and shapes, and retrieve them based on a weighted similarity to any combination of those fields. This can be configured as a key-value dictionary, or a more specific function dedicated to that purpose – DictionaryMemory – can be assigned, in which entries are restricted to be key-value pairs, and retrieved based on similarity only to the key. A custom function can also be specified, so long as it meets the following requirements:

  • it must accept a list or array as its first argument, the items of which are lists or arrays;

  • it must return a list or array of the same size and shape as the input;

  • it must implement a memory attribute, that can be accessed by the EpisodicMemoryMechanism’s memory attribute.

if the function is classed, and has a classmethod _enforce_memory_shape(), this is used to ensure that any specification of the memory argument in the EpisodicMemoryMechanism’s constructor conforms to the format required for the memory attribute of the function.

Output¶

By default, an EpisodicMemoryMechanism has a number of OutputPorts equal to its number of InputPorts, each of which is assigned the value of a corresponding field of the entry retrieved from memory (see Creating an EpisodicMemoryMechanism for naming). However, if OutputPorts were specified in the constructor, then there may be a different number of OutputPorts than InputPorts and memory fields, and thus some of the latter may not be reflected in any of the Mechanism’s output_ports. If the function is a DictionaryMemory, then it will have at least one OutputPort, named KEY_OUTPUT, that is assigned the key (first field) of the entry retrieved from memory and, if two fields are specified in default_variable or sze, the Mechanism will have a second OutputPort named VALUE_OUTPUT that is assigned the value (second field) of the entry retrieved from memory; any additional ones are ignored and no other OutputPorts are created.

Execution¶

When an EpisodicMemoryMechanism is executed, its function carries out the following operations:

  • retrieve an item from memory based on the value of its input_ports; if no retrieval is made, then an appropriately shaped zero-valued array is returned.

  • store the value of its input_ports as an entry in memory.

  • assign the value of the entry retrieved to its output_ports, based on how the latter are configured (see OutputPorts).

Note

In general, retrieval is executed before storage, so that the current items is not also retrieved; however, the order of storage and retrieval is determined by the EpisodicMemoryMechanism’s function.

Examples

(See ContentAddressableMemory for additional examples of how to use that Function, including how it can be configured to implement a key-value dictionary.)

Default EpisodicMemoryMechanism¶

The following example creates a default EpisodicMemoryMechanism (with no initial memory):

>>> my_em = EpisodicMemoryMechanism()
>>> my_em.execute([[1,2]])
array([[0, 0]])
>>> my_em.execute([[2,5]])
array([[1., 2.]])

The default_variable for an EpisodicMemoryMechanism is [[0,0]], so the format of an entry in memory is a single field with two elements. Note that, since it was not assigned any initial memory, the first execution returns an entry comprised of zeros. However, the input to the Mechanism in that execution ([[1,2]]) is stored as an entry in memory, and on the second execution, since that is now the only entry in memory, that is what is returned.

Format entries using default_variable¶

In this example, the default_variable argument is used to format the entries of memory to have two fields, one with two elements and the other with three:

>>> my_em = EpisodicMemoryMechanism(default_variable=[[0,0],[0,0,0]])
>>> my_em.execute([[1,2],[3,4,5]])
array([array([0, 0]), array([0, 0, 0])], dtype=object)

As in the previous example, the first execution returns zeros since memory as not been initialized; however, notice that in this case they are formated as specified in default_variable. Note also that even though a list is specified for default_variable, the entry returned is an array; memory and all of its entries are always formated as arrays.

Format entries using input_shapes¶

The input_shapes argument can also be used to format entries:

>>> my_em = EpisodicMemoryMechanism(input_shapes=[2,3])
>>> my_em.execute([[1,2],[3,4,5]])
array([array([0, 0]), array([0, 0, 0])], dtype=object)

Note that each element of input_shapes specifies the length of a field (see EpisodicMemoryMechanism_Creation_Default_Variable_and_Size for additional details).

Initialize memory¶

The memory argument of an EpisodicMemoryMechanism’s constructor can be used to initialize its memory:

>>> my_em = EpisodicMemoryMechanism(memory=[[[1,2],[3,4,5]],
...                                         [[10,9],[8,7,6]]])
>>> my_em.execute([[1,2],[3,4,6]])
array([array([1., 2.]), array([3., 4., 5.])], dtype=object)
>>> my_em.execute([[1,2],[3,4,6]])
array([array([1., 2.]), array([3., 4., 6.])], dtype=object)

Note that there was no need to use default_variable or input_shapes to format entries here, since that is determined by the entries in the memory argument. If default_variable or input_shapes is specified, its shape must be the same as the entries specified in memory. In this example, since memory was initialized, the first execution returns the closest value to the input, which is used as the retrieval cue. In the second execution, the input from the first execution is returned, since it was stored after the first retrieval. The current contents of memory can be inspected using the memory attribute:

>>> my_em.memory
array([[array([1., 2.]), array([3., 4., 5.])],
       [array([10.,  9.]), array([8., 7., 6.])],
       [array([1., 2.]), array([3., 4., 6.])]], dtype=object)

Notice that there is only one entry for [array([1., 2.]), array([3., 4., 6.])], even though it was provided as input to execute twice. This is because the default function is ContentAddressableMemory, and the default value of its duplicate_entries_allowed attribute is False. Notice also that that the dtype of the memory array is object, since its entries are ragged arrays (i.e., ones with fields of different sizes).

Initialize memory in function¶

The contents of memory can also be initialized using the initializer argument in the constructor for the EpisodicMemoryMechanism’s function:

>>> my_em = EpisodicMemoryMechanism(
...                        function=ContentAddressableMemory(initializer=[[[1,2],[3,4,5]],
...                                                                      [[10,9],[8,7,6]]]))
>>> my_em.function.memory
array([[array([1., 2.]), array([3., 4., 5.])],
       [array([10.,  9.]), array([8., 7., 6.])]], dtype=object)
>>> my_em.memory
array([[array([1., 2.]), array([3., 4., 5.])],
       [array([10.,  9.]), array([8., 7., 6.])]], dtype=object)

Notice memory actually refers to the contents of the function’s memory attribute.

The input_ports of an EpisodicMemoryMechanims correspond to fields of entries in memory (see Input), that by default are named FIELD_n_INPUT:

>>> my_em.input_ports.names
['FIELD_0_INPUT', 'FIELD_1_INPUT']

By default, an EpisodicMemoryMechanims also has the same number of output_ports as input_ports, named correspondingly RETRIEVED_FIELD_n:

>>> my_em.output_ports.names
['RETRIEVED_FIELD_0', 'RETRIEVED_FIELD_1']

These are assigned the values of the fields of the entry retrieved from memory.

The names of input_ports can be customized by specifying a list of names in the input_ports argument of the Mechanism’s constructor:

>>> my_em = EpisodicMemoryMechanism(input_shapes=[2,2,2],
...                                 input_ports=['KEY', 'VALUE', 'LABEL'])
>>> my_em.input_ports.names
['KEY', 'VALUE', 'LABEL']

The number of names must be equal to the number of fields in an entry (in this case, 3). Similarly, the output_ports can be named in the output_ports argument of the constructor. In this case, there can be fewer items specified, in which case the number of fields assigned to OutputPorts will be limited by the number of OutputPorts specified in the argument:

>>> my_em = EpisodicMemoryMechanism(memory=[[[1,2],[3,4,5],[6,7]],
...                                         [[7,6],[5,4,3],[2,1]]],
...                                 input_ports=['KEY', 'VALUE', 'LABEL'],
...                                 output_ports=['VALUE_RETRIEVED', 'LABEL_RETRIEVED'])
>>> my_em.execute([[1,2],[3,4,5],[6,7]])
array([array([1., 2.]), array([3., 4., 5.]), array([6., 7.])],
      dtype=object)
>>> my_em.output_ports
[(OutputPort VALUE_RETRIEVED), (OutputPort LABEL_RETRIEVED)]
>>> my_em.output_ports.values
[array([1., 2.]), array([3., 4., 5.])]

Notice that the first two fields of the retrieved entry are assigned to the two OutputPorts, and the third is not assigned to an OutputPort (see Custom OutputPorts for additional information about customizing OutputPorts).

Class Reference¶

class psyneulink.library.components.mechanisms.processing.integrator.episodicmemorymechanism.EpisodicMemoryMechanism(default_variable=None, input_shapes=None, memory=None, function=None, params=None, name=None, prefs=None, **kwargs)¶

Subclass of ProcessingMechanism that implements a content addressable dictionary. See Mechanism for arguments and attributes.

Parameters
  • _EpisodicMemoryMechanism_Default_Variable (.) –

  • default_variable (list or ndarray) – specifies the format used for entries in memory.

  • memory (list or ndarray) – initial set of entries for memory. It should be either a 3d regular array or a 2d ragged array if the fields of an entry have different lengths; assigned as the initializer argument of the constructor for the MemoryFunction specified in function (see initializer for default assignment).

input_ports¶

a list of the Mechanism’s InputPorts, the number of which is equal to the number of memory fields in an entry of the Mechanism’s memory, and that are named FIELD_n_INPUT by default (see Input and Mechanism input_ports for additional information).

Type

ContentAddressableList[str, InputPort]

function¶

takes the Mechanism’s variable and uses it as a cue to retrieve an entry from memory based on its distance from existing entries, and then stores variable in memory (see Function and Mechanism function for additional information).

Type

MemoryFunction

memory¶

contains entries stored in the functions memory attribute (for example, memory).

Type

3d array

output_ports¶

a list of the Mechanism’s OutputPorts, the number of which is, by default, equal to the number of memory fields in an entry of the Mechanism’s memory, and each of which is assigned the value of the corresponding field of the last entry retrieved from memory. However, as with any Mechanism, the number and value of OutputPorts can be customized (see Output and Mechanism output_ports for additional information).

Type

ContentAddressableList[str, OutputPort]

_handle_default_variable(default_variable=None, input_shapes=None, input_ports=None, function=None, params=None)¶
Override to initialize or validate default_variable based on _memory_init or function.memory
  • if memory argument for Mechanism is specified and default_variable is not, use former to specify latter;

  • if both are specified, validate that they are the same shape;

  • if function.memory is specified and default_variable is not, use former to specify latter;

  • if both are specified, validate that they are the same shape;

  • if default_variable is specified and neither memory arg of Mechanism nor function.memory is specified,

    use default_variable to specify function.memory.

Note: handling this here insures that input_ports are specified/validated using correct default_variable

_instantiate_input_ports(context=None)¶

Override to assign default names to input_ports

_instantiate_function(function, function_params, context)¶

Assign memory to function if specified in Mechanism’s constructor

_instantiate_output_ports(context=None)¶

Generate OutputPorts with names specified and values with shapes equal to corresponding InputPorts

If OutputPorts have not been specified, use InputPort names with prefix replaced and suffix removed.

If any OutputPorts are specified as strings, those are used as names and are the only OutputPorts instantiated

(even if the number is less than the number of InputPorts)

If any OutputPorts are specified in a form other than a string, then this method is ignored and OutputPorts

are instantiated in call to super().instantiate_output_ports; note: in that case, the shapes of the value are as specified and may not necessarily correspond to the

shapes of the corresponding Inputs (i.e., memory fields).

_parse_function_variable(variable, context=None)¶

Parses the variable passed in to a Component into a function_variable that can be used with the Function associated with this Component

property memory¶

Return function’s memory attribute

Next Previous

© Copyright 2016, Jonathan D. Cohen.

Built with Sphinx using a theme provided by Read the Docs.
  • EpisodicMemoryMechanism
    • Contents
    • Overview
    • Creating an EpisodicMemoryMechanism
      • InputPorts, Entries and Memory Fields
      • Function Parameters
      • OutputPorts
    • Structure
      • Memory Fields
      • Input
      • Function
      • Output
    • Execution
      • Default EpisodicMemoryMechanism
      • Format entries using default_variable
      • Format entries using input_shapes
      • Initialize memory
      • Initialize memory in function
    • Class Reference
  • Github