Menu

New directions to OpenHTM implementation

2013-05-31
2013-07-04
  • David Ragazzi

    David Ragazzi - 2013-05-31

    Hi all,

    As you know, last days I reviewed the CLA white paper for convert the pseudo-code to OO approach and include UML diagrams in order to it easier to understand. However in meantime I had some ideas for our project.

    First of all, I realized that our CLA implementation became complex enough to 'newbies' take a long time to understand our imlementation and finally contribute. I understand that several changes were necessary but much others we could avoid.

    I believe we should simplify it and leave it closer to CLA white paper. When I converted pseudocode to OO approach, I noted several code of our current implementation either is redudant or is not fully useful (statistics, for example) or its naming is different from white paper. White paper is not difficult to understand (mainly when the pseudocode is object oriented). So if we leave our implementation closer to original pseudocode, several people could contribute and the learning curve would decrease once the documentation will be the same. For example, properties like 'IsActive', 'IsActiveWasLearning' or methods like 'ProcessSegments', and many others I found, performs redudant actions that instead from help to understand let us with the sensation that the code is more complex and bigger than it seems.

    With this in mind, I decided implement my own CLA implementation from scratch using the same naming and structure from white paper in order to test if we could have a simpler and smaller code. Yesterday I finished spatial pooler. I would say that the code is very small and clean (as closer to original as possible, including the exact white paper descriptions and some code borrowed from our current). So, one interesting thing is we refactored the code having the White paper as model.

    Please, don't consider this:
    The other thing is that maybe is the time to we already have CLA in a language like C++. The claims for comunity members are fully valid and so we will have more people working it (softnhard, for example). I also know that many of us like Michael, Barry, also has C++ implementations and keeping working them. So the idea is the CLA being a static library in native code (keeping Visual Studio as IDE but automatically compiling it with GCC or other compiler from own VS through compilation params). I believe that all us here won't have problems with C++ and even I could perform this conversion. From I tested, we can have this static library without need use explicit pointers and others, so the code will keep nice and clean like C# (I made some experiments and visually implementations in C# and C++ are very similar).

    Having this said I would like know your opinions about it (developer team and members).

    Best, David
    PS: I attached the reviewed white paper and my implementation (without temporal pooler) in this message

     

    Last edit: David Ragazzi 2013-07-04
    • Nick

      Nick - 2013-05-31

      Hi David,
      When talking about converting you must remember such things as interaction with other parts (how should we visualize data from C++ objects?), code maintenance (will there be just one current version/language?), multithreading and the problems we had with 2 pure C# CLA versions like saving/loading via XML and visualization I've already mentioned.
      Yes, there are some redundant code parts but as for me, we must integrate existing codebase more, starting with implementing long existing tickets.
      And, of course, we might be more careful in face of NuPic release.

       
      • David Ragazzi

        David Ragazzi - 2013-06-01

        Hi Nick,

        When talking about converting you must remember such things as interaction with other parts (how should we visualize data from C++ objects?), code maintenance (will there be just one current version/language?), multithreading and the problems we had with 2 pure C# CLA versions like saving/loading via XML and visualization I've already mentioned.

        If we use C++(11) with VS2012 we can choose either compile to pure/native code or then keep using the own CLR (common language runtime), i.e. the virtual machine. If the latter is choosen, the code will have the same behavior that any other .Net managed language has (like C#, VB.net, etc). So we could create a preprocessor directive that allow choose if we want use virtual machine (and keep using runtime integration with UI, XML, etc) or native code. Note that only the CLA would be C++ while IDE and others will keep in C#.

        Yes, there are some redundant code parts but as for me, we must integrate existing codebase more, starting with implementing long existing tickets.
        And, of course, we might be more careful in face of NuPic release.

        I can guarante that the code is tiny and closer to Numenta pseudo-code structure. For example, code to get column neighbors in spatial pooler are repeated twice in or current implementation while that pseudocode (and now my implementation) this is performed by GetNeighbors() function. Please, take a look in it. I'm taking advantage from the Barry's code (and probally from Michael) when I have doubts.

        When I finish my implementation, I will communicate to you. If all like it, an idea would be I upload it and then move only the code from our implementation that we consider really important or then refactor the entire CLA to complain with the white paper.

        Before Grok (former Numenta) release NuPIC, it is very important we have similar structure in order to us can sincronize both implementations. C++ conversion could be done after this refactoring/moving, no need to rush.

        David

         
        • Barry Matt

          Barry Matt - 2013-06-01

          David,
          I do not feel our code is so complex that we need to strip down to a more basic version just so others can maybe better understand. I do not propose we replace what we have with this simple version, namely because we have added lots of changes that have improved results.

          In addition, several differences were designed for optimizing performance. For example ProcessSegment method was added to precalculate the activity states of all segments up front because my profiling was finding that segments were repeatedly being recalculated during pooling and this was significantly slowing performance. Similarly the column inhibition is much faster via IsWithinKthScore by avoiding GetNeighbors entirely thus no new list allocations and no list sorting.

          However with that said, I do like the idea of your simple implementation being made available as part of a tutorial package. Perhaps as the default implementation included alongside the whitepaper as you have been doing so far. For that purpose what you have done so far is a great help.

          I think our biggest complaint is not necessarily that the code itself is too complicated but rather simply that we do not really have any high-level documentation on the project site. People want to read about how best to get started. How to install easy, how to run simple examples easy, and what options they have for reading in other data and seeing results. They should have sufficient web documentation to not even have to look at the code itself at all. If we had these getting started documents then I think a lot of the questions will go away. From there people can jump into the code details if they want once they realize what is going on in the big picture overall.

          As for C++, it is nicer for better performance and better portability (recompile on Linux without mono for example). So if those are goals we feel are important than this may be worthwhile. However I don't think this is necessarily a high priority right away.

          Finally I know some work has slowed around here, and I believe this is because we are all waiting to see the open sourced Grok code before moving to far. I think we will want to synchronize on everything Grok has done so far before moving on. It is likely Grok has added lots of options and solved several issues that we have not done yet. If so it makes sense to wait until we see their code and from there integrate all the latest changes. Then we will know for sure what is lacking and thus can focus on what needs improving. Until then we might be trying to solve something that Grok already has solved.

          Barry

           
          • David Ragazzi

            David Ragazzi - 2013-06-04

            Hi Barry

            I'm not asking to discard our implementation not. I'm just saying we should leave it closer to the CLA white paper as possible. And one of the reasons is that the white paper itself would be the main developer documentation (without extra documentation to explain details of our code).

            As I said in the previous post, many things that were done were REALLY NEEDED. However, the problem is how the code is organized. There are many code encapsulations and hacks that makes it a little difficult to read. For example, the approach to handle "time steps" is a bit tricky to understand at first. If we used only a state machine having T as a marker of context (as is used in the white paper), the reading would be easier (avoiding using "previousXXXX" variables, maxPredictionSteps, etc.) because they would have fewer variables to developer trying to understand or even remember. I left a sample of state machine I'm deploying in the end of this post.

            In most part of my implementation, I took advantage of your code, but organized in a more direct way that was easy to read, avoiding many methods to create small routines. In some parts I was struck by the way that you optimized some routines, and so I preserved the logic. In other ones, I preferred a more direct approach to the problem, even if it slightly decreased performance.

            Thus, one suggestion is to have this implementation as a model for refactoring the current implementation (not replace it) where possible. In addition, it is very succinct and documented.

            Regarding C++, we can postpone it. I saw Numenta released the CLA in C++, but it seems that the implementation needs a lot of refactoring yet, so a difference for OpenHTM will be providing a simple, robust solution in a managed language like C#. I strongly believe that OpenHTM will be the best starting point to those who wish study CLA for general purposes given its beautiful code and its great tools.

            Machine state sample:

            class Global
            {                
              // Current (and maximum) time step of the context.
              // Classes usually have state vectors that use T as initial context reference.
              // A state vector works like a context 'queue' with the difference that we can access directly its elements through an index (between 0 and T).
              // This means that all state machines have their vectors with fixed lenght = T.
              // For example, if T=4 (i.e. 5 time steps assumming that array base is 0) then methods only can handle states up to the 'T-4' time step:
              //   State[T-4] => State[0] => state at 5 time steps ago
              //   State[T-3] => State[1]
              //   State[T-2] => State[2]
              //   State[T-1] => State[3]
              //   State[T]   => State[4] => current state
              public static readonly int T = 4; 
            
              ...
            }
            
            class Column
            { 
              public List<bool> ActivateState = new List<bool> ();
              public List<bool> PredictiveState = new List<bool> ();
            
              // Constructor
              public Column()
              {
                // Initialize state vectors with fixed lenght = T
                for (int t = 0; t <= Global.T; t++)
                {
                  ActivateState.Add(false);
                  PredictiveState.Add(false);
                }
              }
            
              // Perfoms actions related to time step progression.
              public void NextTimeStep()
              { 
                // Remove the element in first position in order to the state vector always have lenght = T
                ActivateState.RemoveAt(0);
                PredictiveState.RemoveAt(0);
            
                // Add a new element to represent the state at current time step
                ActivateState.Add(false);
                PredictiveState.Add(false);
              }
            
              public void SomeMethod()
              {
                // Example of handling states
                if (PredictiveState[Global.T - 1])
                {
                  ActivateState[Global.T] = true;
                }
              }
            }
            
             

            Last edit: David Ragazzi 2013-06-04
  • David Ragazzi

    David Ragazzi - 2013-05-31

    Hi HoaNam,

    HoaNam wrote:
    Dear David,

    I find your idea to port the current version or at least the CORE of CLA into C++ or ANSI C and clean it as more as possible is very good.
    It will be better for newbies to understand und test it in his framework/application.
    But othercodes in the implementation like visualisation, statistics etc are not really useful for the final applications, but they are very usefull for understanding how CLA works, also for further development.
    For this reason, I would like to recommend to let those codes in our implemenation, but we should have possibilities to turn them on/off by compiling.
    To motivate more people to work with our openHTM we need to write more codes for
    1. decoding common data inputs (at least 1D-data, 2D-Data like images) into sparse binary description
    2. convert the openHTM data format back into the user data format
    What do you think?
    Regards
    Hoa Nam

    For this reason, I would like to recommend to let those codes in our implemenation, but we should have possibilities to turn them on/off by compiling.

    I think CLA project is only for CLA. Once it could be ported to embbeded systems, for example, the less code the better. Visualization and Statistics aren't part of the core, they are projects apart (Statistics still not but should).

    1. decoding common data inputs (at least 1D-data, 2D-Data like images) into sparse binary description.
    2. convert the openHTM data format back into the user data format

    This is really necessary. However before this being possible, we have to ensure that reconstruction is ok. For reconstruction is ok we should implement methods that know how reconstruct an input taking account the synapses "InputSource" (more details in white paper), i.e. which position in the input a synapse represents. I see a code implemented by Itay, but I still couldn't analyse in detail.

    David

     
  • David Ragazzi

    David Ragazzi - 2013-06-16

    Hi guys,

    I've attached to this message my implementation which is very small and closer to white paper.

    You will note the following:

    • There are not 'previous' or 'current' variables, everything is managed by state machines (T, T-1, T-n) like in white paper (which I also think is easier to analyse context in several time steps ago).
    • I didn't use locality radius and others that arent in white paper because since that synapses closer to column center are choosen there's not strong motivation to limit radius to potential proximal synapses. Probally the gains arent worth the enough to increase complexity (if they are then I implement again).
    • An interface IChild was created. Its function is allow that developers inherits it and so CLA has abstration to read inputs from a region or sensor. Sensor examples are: FileSensor, NetworkSensor. All these childs use NextTimeStep() method but their internal implementation is different for each one.
    • Hierarchy is created when we specify in the own child element (region or sensor) which is its parent. For example, if we specify that the parent of a region V1 is V2, in V1 constructor we add it to V2 ChildRegions list: ParentRegion.ChildRegions.Add(this);

    Please take a look and give feedback. Note that I still dont test it, it's just a framework practically finished. But it is enough to give an idea.

    David

     
  • David Ragazzi

    David Ragazzi - 2013-07-04

    In order to all know what was made in last commits, here it's a brief summary:

    IDE:

    • It was implemented a dock control in Main form that leave the IDE with customizable layout. This dock control is very similar to MS Visual Studio IDE which user can customize his layout according to his preference.
    • It was implemented a tree control to handle directly regions hierarchy. When HTM is simulating, users can select node to view states in State Information form (advanced visualized made by Itay). When HTM is not simulating (i.e. only configuration), users can add/remove/configure nodes (region or sensors).

    CLA:

    • The poolers methods were grouped by phases (SpatialPoolerPhase1(), TemporalPoolerPhase2(), etc) similar to CLA white paper.
    • Properties to indicate state (IsActive, WasActive, IsActiveAndLearning, etc) were replaced by state machines. IsActive became ActiveState[T] and WasActive became ActiveState[T-1] exactly like in CLA white paper. State machines allow we have information of several time steps, reduces the number of additional code to handle it, and leave CLA easer to follow for those that read white paper.
    • Input size of an higher region is computed by sum the size of its lower nodes (region or sensors). So if a region has 2 child regions where each one has 20x20 sizes, the input size to the region will be 2*(20x20), i.e. a 40x40 vector. (Locality radius could be a problem to columns create proximal synapses to one or more lower regions once that limit the scope?).
    • Before a region perform SP and TP pooling (in NextTimeStep() method), it first makes child regions RECURSIVELY perform their poolings in order to these child´s outputs become parent´s input.

    Although early I say that would remove features like Statistics and MaxPredictionSteps, I didn't it. Thus, I didn't change the current features of the project because we need discuss them before.

    David

     

Log in to post a comment.

MongoDB Logo MongoDB