![]() ![]() ![]()
|
1 Bitworm: Getting Started Example
This chapter gets you started with the Numenta Platform for Intelligent Computing (NuPIC) by explaining how you can run a simple example HTM Network and by briefly examining the example scripts.
Topics
The Bitworm Example
This chapter introduces a simple example called Bitworm. The example illustrates how you might structure your input and category input, how to run your HTM Network, and how to interpret the results. Bitworm is not intended to be a realistic problem, instead, it's used as a Hello World example to get you up and running with NuPIC.
What are Bitworms?
Bitworms are 16-bit vectors. There are solid bitworms, which consist of consecutive on-bits, and textured bitworms, which consist of alternating on/off bits. In each case, the part of the vector that's not a bitworm consists of off bits. Here are some examples:
The Bitworm example program trains an HTM Network to model the world of bitworms. After the HTM Network has been trained, you can submit new data and the HTM Network uses the model of the bitworm world to discriminate between solid and textured bitworms.
Bitworm Example Components
The Bitworm example consists of the following files, discussed in more detail below:
Running the Example
This section explains how to run the example and how you can explore what the HTM Network does by changing the example configuration.
The example has been set up so you need to execute only one script.
On Microsoft Windows, open up a command prompt and type:
On OS X and Linux - assuming
$HOME/ntais the location where you installed the software - type the following at the command line:
The example is set up so you always make modifications to theRunOnce.pyscript, then rerun the script so the example goes through each step again.The script performs these tasks:
1. Generates a set of training data by calling
GenerateData.pyusing the parameters set inRunOnce.py. The default is to generate temporally coherent data, that is, sequences of solid and textured bitworms of variable bitworm length. The minimum and maximum length are specified in thetrainingMinLength/testMinLengthandtrainingMaxLength/testMaxLengthparameters.2. Creates the bitworm HTM Network, that is
a. creates a
Networkinstance (from the Python packagenupic.network)b. creates the specified nodes for the network
c. links the inputs and outputs of the nodes
d. saves the untrained HTM Network to a file that describes the HTM Network structure
3. Trains the HTM Network. The example proceeds as follows:
a. The script enables the sensor and bottom-level (level 1) node for training and calls the appropriate methods to perform training at level 1.
During training, the nodes learn, that is, they construct a model of their world.
b. After the bottom-level nodes have been trained, the script enables inference for the bottom-level node and training for the top-level node. While in inference mode, the bottom-level node sends the result of its inference computation to the next level (in this example, the top level). The top level performs learning with those input data.
4. When the top-level node receives input during training, it also receives category information. It assigns the data to categories as part of training.
5.
RunOnce.pycallsrunInferenceto explore how the trained HTM Network handles new data. During inference, the trained HTM Network looks at each input bitworm and determines the probability that the bitworm belongs to one or the other category.6. Finally,
RunOnce.pycallsGenerateReport, which prints the coincidences for each group to a file calledreport.txt.Grouping is an important part of the learning algorithm. You don't need to understand grouping or the learning algorithm for this simple example. See Inside a Learning Node: How Learning and Inference Happen on page 38 in Advanced NuPIC Programming for an overview and the white papers on the Numenta website at http://www.numenta.com/for-developers/education/algorithms.php for more detailed information.
Examining the Report
The
GenerateReportscript that is run as part ofRunOncegenerates a report file namedreport.txtthat includes the following information:------------------------------ General network statistics: Network has 5 nodes. Node names are: Sensor CategorySensor Level1 Level2 FileOutput Node Level1 has 40 coincidences and 7 groups. Node Level2 has 8 coincidences.------------------------------
------------------------------ Performance statistics: Comparing: training_results.txt with training_categories.txt Performance on training set:100.00%, 420 correct out of 420 vectors Comparing: test_results.txt with test_categories.txt Performance on test set: 97.86%, 411 correct out of 420 vectors ------------------------------Note that the Bitworm example gets very good results because this is a toy problem: The assumptions matched those of the current learning algorithm precisely. Achieving the same degree of success for more complex problems can be more challenging.
====> Group = 0 1 0 1 0 1 0 1 0 1 0 1 0 0 0 0 0 0 1 0 1 0 1 0 1 0 1 0 1 0 0 0 0 0 0 1 0 1 0 1 0 1 0 1 0 1 0 0 0 0 0 0 1 0 1 0 1 0 1 0 1 0 1 0 0 0 0 0 0 1 0 1 0 1 0 1 0 1 0 1 0 0 0 0 0 0 1 0 1 0 1 0 1 0 1 0 1 ====> Group = 1 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1This display can be helpful in a simple program, such as bitworms. It's easy to see how clean the groups are. Each group contains a different kind of bitworm. For other programs, using Numenta Visualizer might be better. For a discussion of Numenta Visualizer, see Debugging Your HTM Application.
You can look at theGenerateReport.pyfile to see what Python calls you can use to retrieve information from the network. Comments in the file make it easy to understand your options.Displaying the Report
You can run the
DisplayReport.pyscript to see a visual representation of the groups, as follows:Running the Example with Temporally Incoherent Data
You can change the
useCoherentDataparameter inRunOnce.pyto generate solid and textured bitworms that are not presented in sequence, that is, that have no temporal relationship. Submitting those data to the trained HTM Network illustrates the importance of the temporal aspect of the training data.To run the example with incoherent data:
1. In the
RunOnce.pyscript, change theuseCoherentDataparameter toFalse.2. Execute
RunOnce.pyagain.The example runs with data that include both solid and textured bitworms but don't present sequences of solid bitworms followed by sequences of textured bitworms.
3. Examine the
report.txtfile this run generated. You should see that the HTM system found it difficult to find the groups and to categorize the data.Running the Example with Noisy Data
The data generation script allows you to change the data by introducing some noise and to observe the results. There are two types of noise:
0 0 0 0 1 1 1 1 1 0 0 0 0 0 without noise -.1 0.1 0 1.01 1 1.1 .98 .98 1.05 0 0.05 0.09 0 0.07 with noiseIn the bitworm example, you can introduce noise to the data and see how the noise affects recognition.
To run the example with noisy data:
1. In the
RunOnce.pyscript, return theuseCoherentDataparameter toTrue.2. Change
additiveNoiseTrainingto 0.1. This setting adds uniform random noise in the range [-0.1, 0.1] to the inputs. Note that once you start adding noise to the inputs, it becomes harder for the learning algorithm to detect temporal coherence.3. Execute
RunOnce.py.You get a Python exception with the message
The current parameters generated 400 groups, which exceeds the maximum of 25 groups. This message means you didn't have enough outputs for the number of groups that were found. Although the number of underlying causes has not changed, the noise makes it harder for the algorithm to create a compact set of groups based on temporal coherence.4. Change the following two parameters in
RunOnce.pyand save the revised file:
- Increase
maxGroupsto 50 to avoid the error above.- Set
maxDistanceto 0.1. ThemaxDistanceparameter sets the maximum Euclidean distance at which two input vectors are considered the same during learning. The default for this parameter is 0, so a change usually means better performance if some noise is present. See Affecting Learning Node Behavior With Node Parameters on page 42 in Advanced NuPIC Programming for more information.5. Call
RunOnce.pyagain. The script now runs without generating an exception.6. Examine the
report.txtfile this run generated. You should see that the results are good; however, notice that the number of groups is fairly large compared to the original number. This is an indication that the learning algorithm found it more difficult to find the groups and categorize the data.7. Set
maxDistanceto 0.2, rerunRunOnce.py, and examinereports.txt. This time the HTM gets the same number of groups as it did before you added noise.This example illustrates how a combination of parameters (
maxDistanceandmaxGroups) affects whether the HTM Network works well or does not work at all. If you wish, you can experiment with some of the otherRunOnce.pyparameters. Here are some possibilities:
additiveNoiseTraining- allows you train an HTM Network with additive noise. You could then test the trained HTM Network with noisy data.bitFlipProbabilityTraining- allows you train an HTM Network with bitflip noise. You could then test the trained HTM Network with noisy data.trainingMinLength- Shortest bitworm used for trainingtrainingMaxLength- Longest bitworm used for trainingadditiveNoiseTesting- allows you to test an HTM Network trained with noiseless data using noisy data.bitFlipProbabilityTesting- allows you to test an HTM Network trained with noiseless data using bitflip noise.testMinLength- Shortest bitworm used for testingtestMaxLength- Longest bitworm used for testingUnderstanding the Example Scripts
This section briefly discusses the Bitworm example scripts.
RunOnce.py: Your Entry Point to Bitworms
The
RunOnce.pyscript runs the component scripts of the example in sequence. As a rule, you should always callRunOnce.py, not one of the component scripts.
RunOnceallows you to set the following parameters:
useCoherentData When set to true (the default), theGenerateData.pyscript creates sequences of solid bitworms followed by sequences of textured bitworms.When set to false, theGenerateData.pyscript mixes solid and textured bitworms randomly. In that case, the temporal element is missing from the data.numSequencesPerBitwormType Number of sequences for each bitworm type. For example, you could present ten sequences of textured bitworms and ten sequences of solid bitworms. The sequences are always separated by a row of zeros (0).GenerateData.pyalways generates the same number of sequences of each type.sequenceLength Length of each sequence (e.g 20 bitworm vectors, followed by one vector of zeros). Minimum and maximum length of the generated bitworms.inputSize Size of the input vector. Defaults to 16.additiveNoiseTrainingadditiveNoiseTesting Allows you to add noise in the range [-additiveNoise, additiveNoise] to each input element. Default is 0. You can add noise during testing, during training, or both. See Running the Example with Noisy Data. Probability that a bit will be flipped from 0 to 1 or vice versa, that is, a 0 bit becomes 1 or a 1 bit becomes 0. Can be combined with additiveNoise. Default is 0. See Running the Example with Noisy Data.maxGroups Maximum number of groups that can be learned at level 1.maxGroupSize Specifies how large the groups in the temporal pooler can become. maxDistance Sets the maximum Euclidean distance at which two input vectors are considered the same during learning. See Affecting Learning Node Behavior With Node Parameters. topNeighbors If thetopNeighborsvalue is big, wider grouping and bigger sets result. If the value is small, narrower grouping and smaller sets result. Affecting Learning Node Behavior With Node Parameters on page 42 in Advanced NuPIC Programming.GenerateData.py: An Example of Data Generation
The
GenerateData.pyscript generates a file with training data or testing data, plus an associated category file, using the parameter settings specified inRunOnce.py. Data are generated in sequences: For each sequence, the code generates a bitworm specified bysequenceLengthusing a random length and position (within the current parameter constraints), and then slides the bitworm left or right. At the end of each sequence,GenerateDatainserts a line of zeros to reset the node so that the node does not attempt to learn temporal correlation between two bitworm sequences.The script includes methods to generate data in which no temporal correlation exists. Those methods are called when the
useCoherentDataparameter is set toFalse.Several aspects of this data setup are interesting:
- Each bitworm is not considered a sequence of bits but instead a single unit. The same way, a vision system processes input one "glance" at a time (not one pixel at a time) and compares "glances" over time.
- The data are presented as a set of logical sequences. Each sequence shows a single bitworm moving left or right. Within each sequence, each input pattern is correlated with the next pattern. This temporal coherence is critical for any HTM training data. HTMs (like people) expect a world that does not change drastically from one moment to the next. HTM learning algorithms exploit this property.
- In the data file, each sequence is followed by a row of zeros that separates it from the next sequence. At the start of each new sequence, the data generator decides which type of bitworm it wants to present next. This approach can be compared to viewing the frames of scenes in a movie. You need to see a set of frames to get a coherent picture, and then you could switch to the next scene.
CreateNetwork.py: Creating the Untrained HTM Network File
The
CreateNetwork.pyscript creates theNetworkandNodeinstances, links the nodes, and saves the complete untrained network to an XML file. During training and testing, the Numenta Runtime Engine (NRE) can then load the network file and use the information about the network structure to process the data. See Constructing an HTM Network for a detailed discussion of network creation.Node Hierarchy
Figure 1 shows the hierarchy of nodes in the bitworm example. This is the simplest possible HTM hierarchy.
Figure 1 Nodes in the Bitworm Example
To create this hierarchy, the script goes through these steps:
1. Creates the
Networkinstance, specifying three parameters. See Affecting Learning Node Behavior With Node Parameters on page 42 in Advanced NuPIC Programming for some background information about the parameters.def createNetwork(untrainedNetwork, inputSize = 16, maxDistance = 0.0, topNeighbors = 3, maxGroups = 8):2. Uses the
CreateNode()function to specify each node and its parameters. The bitworm network has a data sensor and a category sensor, one bottom-level node, one top-level node, and one effector.The level 1 learning node is an instance of
Zeta1Node, the level 2 node an instance of andZeta1TopNode. Those two classes encapsulate the learning algorithms used by Numenta HTM Networks:Zeta1TopNodeexpects to get both domain data and category data, whileZeta1Nodeexpects domain data only.3. Adds each node to the network. For example:
sensor = CreateNode("VectorFileSensor", phase=0, dataOut= inputSize) net.addElement("Sensor", sensor)The phase determines when the node is scheduled. You must specify a phase for each node. In many cases, using a phase that corresponds to the level is appropriate. See Scheduling Node Processing on page 79 in Advanced NuPIC Programming for more information on scheduling.
4. Links the nodes using the
Network.link()method. The method expects as input a node and its output and a second node and its input. See Node Inputs, Node Outputs and Links on page 34 in Advanced NuPIC Programming for more information. For example, to link the sensor to the bottom node:net.link("Sensor", "dataOut", "Level1", "bottomUpIn")This call links the
Sensor'sdataOutoutput to theLevel1node'sbottomUpIninput.5. Saves the network to an XML file.
TrainNetwork.py: Training of the HTM Network
During training, each node in the HTM Network builds a model of its world using the available input data.
The
TrainNetwork.pyscript performs training as follows:1. Creates a
RuntimeNetworkobject that contains information about the session and data files to be used. The training file is the data file we created earlier.2. Loads the training and category data for each sensor.
sensor = runtimeNet.getElement("Sensor") categorySensor = runtimeNet.getElement("CategorySensor") sensor.execute("loadFile", trainingFile) categorySensor.execute("loadFile", trainingCategories)These commands extract the
RuntimeNodefor each sensor from theRuntimeNetwork, and then send aloadFilecommand to eachRuntimeNode.3. Runs the
SensorandLevel1nodes to train level 1. That means level 1 is progressively building a model of its world, which will later be used by the next level. Before starting the run, learning is automatically turned on forLevel1. After theLevel1run is complete, the system turns off learning and turns on inference for that level.runtimeNet.run(Zeta1Train("Level1", numVectors), ["Sensor", "Level1"])
Zeta1Trainis a special run policy for trainingZeta1Nodes andZeta1TopNodes. See Advanced NuPIC Programming for more information.4. Resets the sensors before training Level2. The commands use the
RuntimeNodeinstances extracted in Step 2 above.
categorySensor.setParameter("position", "0")5. Runs
Level2.runtimeNet.run(Zeta1Train("Level2", numVectors), exclusion=["FileOutput"])In Step 3, inference was turned on for level 1. While in inference mode, the
Level1node sends its output to the top-level node.6. Finally, saves the trained HTM Network file and cleans up the bundle of temporary files used by the NRE. Session Bundles on page 55 in Advanced NuPIC Programming discusses bundles in some detail.
runtimeNet.cleanupBundleWhenDone()
When the script completes, the NRE stops.
RunInference.py: Running the Trained Network with New Data
The
RunInferencescript allows you to submit new data to the trained HTM Network. This script loads a trained HTM Network, and runs the entire network in inference mode using a given data file. You can run the script on the original training data or on new test data. No category file is specified during inference.The script proceeds as follows:
1. Creates a runtime network and adds data files.
runtimeNet = CreateRuntimeNetwork(trainedNetwork, files=[testFile]) runtimeNet.getElement('Sensor').execute('loadFile', testFile)2. Sets up the effector output so it's stored inside the bundle.
fileOutputEffector = runtimeNet.getElement('FileOutput') fileOutputEffector.execute("setFile", resultsFile) fileOutputEffector.execute("echo", "Numbers show Level 2 node output followed by the sensor output")At this point, each node is in inference mode because the trained HTM Network was saved in that state.
3. Runs through training patterns. During inference, categories are not known, so the
CategorySensoris disabled.runtimeNet.run(numVectors, exclusion=["CategorySensor"])Note that when you submit new data to a trained network,
Zeta1Trainis not used because no enabling and disabling of learning is necessary. All learning nodes have been trained and are in inference mode.4. Retrieves the results file and cleans up. The
flushFilecommand ensures that the inference output file has been fully written to disk and is not partially stored in an operating system file cache.fileOutputEffector.execute("flushFile") runtimeNet.getFiles(resultsFile) runtimeNet.cleanupBundleWhenDone()In most cases, you don't need to be concerned about details regarding bundles. Just retrieve any files you'd like to keep, and then call
cleanupBundleWhenDone(), as in the code fragment above.
|
Numenta www.Numenta.com |
![]() ![]() ![]()
|