I’m surprised that no one has ever tried grid cells as location encoders (like to the old GeoSpatial Encoder) for anomaly detection. So it became an experiment I ran for the final project for my ML course.
Here is a screen shot for your viewing pleasure. And letting me to explain things more clearly.
On the left you see a white and red circle revolving in a circle. That is the target. HTM will try to learn lt’s path and generate anomaly signals when even the path is altered.
On the right is an self explanatory window. It shows the input SDR of the current time step, what TemporalMemory predicts at the last time step, what has not been predicted, anomaly history, current anomaly score and a slider and threshold and display to show anomaly.
Grid Cells
If you don’t know what gird cells are. Go watch HTMSchool Epsode 14. You have already watched? Awesome. Numenta’s view of Grid Cell module not as a hexagon but as a parallelogram is ingenious. It simplified the problem from some crazy hexagonal indexing into simple 2D geometry/algebra. Making encoding each module an O(1) process (assuming constant density). (I’m not certain. But the implementation used in HTM School, hex-gcm.js seems not have take advantage of this property. Thus the algorithmic complexity there is O(n), where n is the number of cells in a module)
I have also tried alternative forms of grid cells. Randomlly squashing/extending the x or y axis of each grid cell module, perform random transformation on the coordinate instead of rotating it, add a bias term to the coordinate etc…
Most of them failed, they underperform the grid cell modules purposed by Numenta. However, adding a bias term to shift the coordinates around seems to improve the performance a bit. But it might be random luck.
The Test
To have a base line to compare. I compare how well anomaly detection works when the SDR is encoded using grid cells vs 2 ScalarEncoders encoding the X-Y coordinate of the circle.
The anomalies I test includes:
- Path offset (to up/right/left/down) by 50 pixels
- Path offset (to up/right/left/down) by 5 pixels
- Rotation center moved from (50, 50) to (250, 250)
- Rotation radius increased from 100 to 105
- Reverse the rotation direction
- Fix the circle to (50, 50)
And… Grid cells dominated ScalarEncoder. Some times ScalarEncoders can’t even detect the anomaly. The following table shows the average anomaly score among 2000 steps that HTM generates when encountering different anomalies.
Scalar Encoder | Grid Cells | |
---|---|---|
Normal | 0.00422116 | 0.0645078 |
Shift 5 px | 0.00683655 | 0.379953 |
Shift 50 px | 0.115336 | 0.943195 |
Revolve at (200, 200) | 0.749588 | 0.996648 |
Radius at 105 | 0.0086827 | 0.634852 |
Reverse direction | 0.0170673 | 0.828555 |
Fixed at (50, 50) | 0.0005 | 1 |
Immunity to Catastrophic Forgetting
I don’t see this being discussed much in the forum. HTM is very resistant to catastrophic forgetting.
Catastrophic forgetting is a phenomenon where ML algorithms (mostly Neural Networks today) will totally forget what it had learned when training on new data that does not contain patterns of the previous data.
For amusement I trained HTM on the normal path till a low anomaly score. Than train HTM when the circle revolves around (250, 250) till a low anomaly score. When I set the circle back to it’s original orbit. HTM immediately recognized the pattern. Although giving a anomaly score of ~0.3 instead of ~0.05.
After further training to reduce the anomaly score. I set the circle orbiting around (250, 250) again. This time HTM fully recognized the path and gives a low score of ~0.05. Good job HTM!
Further analysis
I’m curious that weather if HTM is relying on any context (higher order memory) to predict the next state. Since each location has a unique representation, first order memory should be enough to learn all the sequences. So I limited the TM to only have 1 cell in each column.
And… HTM still learns the pattern. Although the SDR density TemporalMemory generated that achieved the same anomaly score increased from 17% to 21%. (Both pretty dense.)
The code
The source is available here on GitHub. Well… the code is very messy for now. I’ll spend some time to clean it up in the future.
HTMPath
is a GUI application with visualizations of the HTM model and other info.
These are the controls.
- w - move orbit up 5 pixels
- a - move orbit left 5 pixels
- s - move orbit down 5 pixels
- d - move orbit right 5 pixels
- up - move orbit up 50 pixels
- down - move orbit left 50 pixels
- left - move orbit down 50 pixels
- right - move orbit right 50 pixels
- o - move orbit center to (250, 250)
- l - set orbit radius from 100 to 105
- f - fast forward
- p - slow motion (limit to 10 FPS)
- c - lock the circle at (50, 50)
- Left Shift - Force learning (Learning is disabled when orbit is altered)
- n - Force disable learning
- t - reverse orbit direction
bench
is a CLI tool for generating test results as fast as possible. Change GridCellEncoder2D
to LocEncoder2D
in bench.cpp to switch between Grid Cells and Scalar Encoders.3
I think that’s enough for today, Hope someone find this helpful.