![]() ![]() ![]()
|
3 Constructing an HTM Network
This chapter explains how you can use the Numenta Python APIs to create an untrained HTM Network and save that network to an HTM Network file.
Topics
HTM Programming Steps Overview
This section briefly discusses the complete development process to help you understand the relationship between your HTM Network's structure (encapsulated by a
Networkinstance) and theRuntimeNetworkthat is used during training and inference.Figure 3 HTM Development Process Overview
Network Instance Creation Tasks
The rest of this chapter explains how you can create an untrained network (the Network object and all associated objects). Here's an overview of the steps:
Understanding HTM Network Components
HTM Networks are data-driven learning systems.
The untrained network has no inherent capability and cannot be used to perform inference. The untrained network is like a scaffold that describes the flow of data and other aspects of analysis at runtime. This scaffold information includes, for example, the number of nodes and levels, characteristics of the nodes, and how the nodes' inputs and outputs are connected.
Figure 5 shows a sample HTM Network, which consists of a number of different nodes. While the sample network shown below is small and highly symmetrical, an HTM Network can actually have an arbitrary number of levels and connections, and it does not need to be symmetrical.
Figure 4 Sample HTM Network
All the elements in Figure 4 together form an HTM Network. The HTM Network consists of nodes, links, and, optionally, regions.
Nodes
A node - sensor, effector, or learning node - is the basic unit of a Numenta HTM Network. Each node is implemented as a Python or C++ plugin to NuPIC. Numenta nodes are usually created and manipulated using classes in the Python NuPIC API, as discussed in Constructing an HTM Network.
The general node categories are:
Each node has a number of attributes:
- Inputs and outputs, which are vectors of floating-point numbers in the nodes that are currently implemented.
- Sensors have no inputs but at least one output.
- Learning nodes have at least one input and output each.
- Effectors have no outputs but at least one input.
See Node Inputs, Node Outputs and Links on page 34 in Advanced NuPIC Programming for more information.
- Links to other nodes. A node can receive input from and send output to nodes to which it is linked.
- Parameters that affect node behavior at runtime. You can find an introduction to parameters in Affecting Learning Node Behavior With Node Parameters on page 42 in Advanced NuPIC Programming.
- Scheduling (phase) information for any node in the HTM Network determines the order in which the nodes are processed. It usually makes sense to assign sensors to phase 0 and other nodes on a per-level basis. The NRE processes each phase in sequence. See Scheduling Node Processing on page 79 in Advanced NuPIC Programming.
- An internal state. Most of the internal state is saved when the HTM Network is saved after training. Some node data, such as the current input and output vectors, are transient and are not saved.
Regions
A region is an array of nodes that have precisely the same parameters, including the same phase. The sample network in Figure 4 does not include a region, but most larger HTM Networks do include regions.
Figure 5 1-D region of four nodes (top) and 2-D region of 2x3 nodes (bottom).
Links
Links determine the flow of information in the HTM Network. You can specify links between individual nodes, or link arrays of nodes at once using a link policy. See Link Policies.
Creating the Network and Node Objects
You use the
Networkclass to create the initial untrained networks. You can create a network and populate it by creating node objects, regions, or both. The untrained HTM Network describes the structure of an HTM Network similar to the way a database schema describes the structure of a database. Creating the untrained network using node objects consists of these steps, discussed with code fragments below:1. Import the nupic.network Python package
3. Create and Configure the Nodes
4. Add the Nodes to the Network Object
After you've completed these steps, you can link the different nodes, as discussed in Linking the Elements of the Network.
1 Import the nupic.network Python package
The
nupic.networkpackage contains all the classes you need for creating your network. For example:Here are some of the classes and functions from
nupic.network:
Network Container class. You can create an instance ofNetwork, and then add the network elements (nodes or regions). Used to create nodes explicitly using the node class and its methods. See NuPIC Node Types on page 32 in Advanced NuPIC Programming for an overview of node types. See Affecting Learning Node Behavior With Node Parameters on page 42 in Advanced NuPIC Programming for an introduction to node parameters. To create arrays of nodes based on a template, you use the Region class. See Creating Regions. In the simplest case, you link nodes by specifying output of the source node and the input of the target node. You can use link policies to link multiple nodes. For example, if you are connecting regions to each other or to nodes, you must specify a link policy.For information about any of the classes, you can use pydoc, as discussed in Getting Node Help.
2 Create an Empty Network
After you've imported the appropriate classes, you can create an empty network to serve as container for network elements and links. For example:
3 Create and Configure the Nodes
The
CreateNode()function allows you to create and configure a node with one call.For each node, you can specify a node type and all node parameters. Some parameters are required, as indicated in the online help. If you make a mistake,
CreateNode()warns you immediately by throwing a Python exception.The following code fragment creates a node using
CreateNode()and specifies its parameters:myNode = CreateNode (nodeType='Zeta1Node', phase=1, spatialPoolerAlgorithm='gaussian', symmetricTime=True, transitionMemory=4, topNeighbors=3, maxGroupSize=50, temporalPoolerAlgorithm='sumProp', maxDistance=0.05, bottomUpOut=8)4 Add the Nodes to the Network Object
After you've created the node(s), you can add them to the network as follows:
Here,
For example:
myNode = CreateNode (nodeType='Zeta1Node', phase=1, spatialPoolerAlgorithm='gaussian', symmetricTime=True, transitionMemory=4, topNeighbors=3, maxGroupSize=50, temporalPoolerAlgorithm='sumProp', bottomUpOut=8, maxDistance=0.05) myNet.addElement ("Level1Node", myNode)
Network.addElement()keeps a copy of the element added. Modifications to the original do not affect the copy inside the HTM Network. You should make all modifications, for example, to phase, output element counts, or parameters, before you calladdElement().Creating Regions
Creating a region involves a few simple steps.
1 Create a Node that Serves as the Template
Use
CreateNode()to create a node template. Set all parameters as part of node creation.2 Create a Region Using the Template and Specifying the Dimensions
You create a 1-D region that consists of four nodes as follows:
You create a 2-D region of six nodes arranged in a grid with two rows and three columns (see Figure 5) as follows:
3 Add the Region to the Network
Adding a region to an HTM Network is identical to adding a node to a network.
After you've completed these steps, you can link the region to other regions or to nodes, as discussed in Linking the Elements of the Network.
Node Names
All the node names for a 1-D region are
<region_name>[<num>]where
<num>is a number between 0 and the number of nodes in the region, minus 1.All the node names for a 2-D region are
<region_name>[num,num]where the two numbers are the indices into the region. Note that there is no space between the two numbers.
You can use node names when setting up more advanced links, or when analyzing individual nodes in a trained network.
Region Example
Figure 6, Regions represented by the Pictures example, shows an example of regions. The code fragment in Example 1, Using regions in the Pictures example, shows how the regions can be created.
Figure 6 Regions represented by the Pictures example
Linking the Elements of the Network
After you've added nodes to a
Network, you must link the nodes together. Each node can have multiple named outputs and named inputs. Links connect from a source node and named output to a destination node and named input. See Links on page 36 in Advanced NuPIC Programming for an introduction to links.You perform the linking in one of two ways.
myNet.link ("<source_node_name>", "<output_name>","<dest_node_name>",\ "<input_name>", )If the nodes have only one input and output, you can omit the input or output name and the system defaults appropriately, as follows:
myNet.link ("<source_node_name>", "<dest_node_name>")myNet.link ("<source_region_name", "<dest_region_name>", <link_policy> ) myNet.link ("<source_node_name", "<dest_node_name>", <link_policy> )Here, you use the constructor for a link policy, e.g.
SimpleFanIn()as the third argument.Link Policies
This section discusses the
SimpleSensorLinkandSimpleFanInlink policies.
- Sensor to region linking:
SimpleSensorLink- When you want to connect a sensor to a region, the goal is usually to divide the sensor output array evenly across all nodes in the region. When you set the link policy toSimpleSensorLink, the system takes care of this automatically for 1-D, 2-D, or 3-D arrays.Figure 7 SimpleSensorLink Link Policy.
For example, if the sensor output is an array of 64 elements, and the region consists of four nodes, the first 16 data values go to the first node, the next 16 data values go to the second node, and so on.
To link a sensor with a 1-D region, use code like the following:
myNet.link ("<source_node_name", "<dest_region_name>", SimpleSensorLink () )To link a sensor with a 2-D region, use code like the following:
myNet.link ("<source_node_name", "<dest_region_name>", SimpleSensorLink (sensor_dimenson) )
sensor_dimensionis a list, e.g. [32, 32] if the sensor outputs 1024 elements that should be treated as a 32x32 array.If necessary, you can specify the additional arguments for the link policy by calling the constructor, which has this prototype:
SimpleSensorLink (list_of_sensor_dimensions, output_name, input_name)Figure 8 SimpleFanIn Link Policy
- When two 2-D regions are linked, the nodes at the bottom level are divided evenly to send their output to the next level. For example, if you have 8x8 (64) nodes at the bottom level, and you have 2x2 (4) nodes at the next level, each higher level node gets input from 16 lower level nodes arranged in a 4x4 grid.
To link two regions, use code like the following:
Overlapping Connections
There are variants of
SimpleSensorLinkandSimpleFaninthat allow overlapping connections.OverlapFanIn
OverlapFanIn allows you to link nodes at two levels using a specified overlap, for example:
The arguments to
OverlapFanInare, in order, the source output name, the overlap as a list, and the destination input name.Figure 9 OverlapFanIn Example
The system calculates the fan-in using the source element (or region) dimension, destination element (or region) dimension, and overlap. The overlap, which is a list to allow for multi-dimensional HTM Networks, specifies the number of source nodes shared by any two adjacent destination nodes.
OverlapSensorLink
OverlapSensorLink allows you to divide a single sensor output array equally across the nodes of the destination region, for example:
Figure 10 OverlapSensorLink Example
In this example, the sensor output array has 18 array elements, which are divided across four nodes. Each node receives the output of six array elements, with adjacent nodes getting the input from two shared elements each.
Creating and Linking Regions: The Pictures Example
The following code fragment comes from the Pictures example. It creates template nodes, regions, and link policies for each level. The
net_constructionexample included with NuPIC contains many example scripts for creating HTM Networks.Example 1 Using regions in the Pictures example# Import modules from Numenta Tools from nupic.network import Network, CreateNode, Region from nupic.network import SimpleFanIn, SimpleSensorLink # Create the Numenta network object net = Network() # Create and add one input sensor to the network sensorNode = CreateNode('VectorFileSensor', phase=0, dataOut=1024) net.addElement("sensor", sensorNode) # Create Level 1 L1Template = CreateNode(nodeType='Zeta1Node', phase=1, spatialPoolerAlgorithm='gaussian', symmetricTime=False, topNeighbors=2, transitionMemory=4, maxGroupSize=50, temporalPoolerAlgorithm='sumProp', bottomUpOut=1024, maxDistance=0.1) net.addElement("level1", Region([8, 8], L1Template)) # Create Level 2 L2Template = CreateNode(nodeType='Zeta1Node', phase=2, spatialPoolerAlgorithm='product', symmetricTime=False, transitionMemory=4, topNeighbors=2, maxGroupSize=50, temporalPoolerAlgorithm='sumProp', bottomUpOut=48) net.addElement("level2", Region([4, 4], L2Template)) # Create Level 3 L3Template = CreateNode('Zeta1TopNode', phase=3, categoriesOut=48, mapperAlgorithm='sumProp') net.addElement("level3", Region(1, L3Template)) # Link all the levels net.link("sensor", "level1", SimpleSensorLink([32,32])) net.link("level1", "level2", SimpleFanIn("bottomUpOut", "bottomUpIn")) net.link("level2", "level3", SimpleFanIn("bottomUpOut", "bottomUpIn")) # Write out the file net.writeXML("SampleNet.xml")
Saving the Network to a File
NuPIC allows you to save untrained and trained HTM Networks.
When you export a network to an HTM Network File on disk, the system creates an XML file that contains information on all the nodes and links in the HTM Network.
When you call
writeXML(), the system saves the HTM Network to an XML file (extension.xml) using custom XML tags and attributes. HTM files can be quite large, so they can be zip-compressed by calling the command as follows:During training, testing, and debugging, the network file is loaded in the NRE, and a trained network file can be saved by the NRE. Trained network files use the same XML file format and can also be used with
RuntimeNetwork. See Using the RuntimeNetwork Object to Perform Training.
|
Numenta www.Numenta.com |
![]() ![]() ![]()
|