Comments (13)
Isn't an Encoder a stateless entity? Why bother serializing it (if you're talking about state)? Seems the only state is configuration variables which should be "packaged" externally so that they are "re-appliable", that way you can just instantiate an encoder at the endpoint and serialize the parameters and just send those - re-applying the parameters locally to the instantiated Encoder?
Notice the above are all questions. I'm testing my logic, not really declaring a "should" :-)
Sent from my iPhone
On Jun 24, 2015, at 2:48 AM, Felix Andrews [email protected] wrote:
Encoders are the only things in Comportex HTM values that are not serializable. We should fix that so that models can be saved or sent over the wire.
Currently they are created using (reify) which makes a closure. But the main problem is how they get their particular data inputs out of the general, amorphous input-value provided to htm-step. That is using pre-transform which applies some arbitrary function to do the extraction.
Proposal:
Shift the task of formatting the data for encoding outside to whatever is creating the input values. An input-value as provided to htm-step would then be a structured value directly providing the data required by each input's encoder. Each input already has a keyword id specified in core/RegionNetwork so these keys could specify the input data for each.
Example. Suppose there are 2 inputs (feeding into one or more regions), called :main-input and :motor. The former is a concatenation of a category and a coordinate encoding. The latter is a single linear number encoding.
The input-value might then look like:
{:motor 42
:main-input [:red {:coord [5.0 10.0], :radius 2.5}]
}
Each input encoder will be passed just its sub value.The various encoder types can be made into Records or Types.
—
Reply to this email directly or view it on GitHub.
from comportex.
Hi David, interesting question.
So the information, as you rightly point out, is
more like configuration than mutable state. It defines which encoders are
used and how they are combined. Then each encoder will have parameters such
as width/onbits/min/max in a linear scalar encoder.
In Clojure, any object, such as an encoder, is just a map with keyword
keys, and tagged with its type, so when you serialize it (which is the same
as printing it) you get something that looks like configuration data.
E.g. in the above example the serialized data for the inputs (as nodes in
an htm network, like regions) might look like
:inputs {
:motor #LinearEncoder {
:width 127, :on-bits 21, :min 0, :max 100
},
:main-input #ConcatEncoder {
:encoders [
#CategoryEncoder {
:width 100, :values [:red :green :blue]
}
#CoordinateEncoder {
:width 180, :on-bits 20
}
}
}
So it kinda is configuration data. I guess an argument for inventing and
handling a separate configuration format is that it would be less tied to
the current implementation details. But a really nice thing about this is
there is no special serialization mechanism at all. You just print out the
whole htm object, and then read it in at the other end like any other value.
I don't have any real experience with serialization so i may also be
missing something!
Cheers
On Wednesday, June 24, 2015, David Ray [email protected] wrote:
Isn't an Encoder a stateless entity? Why bother serializing it (if you're
talking about state)? Seems the only state is configuration variables which
should be "packaged" externally so that they are "re-appliable", that way
you can just instantiate an encoder at the endpoint and serialize the
parameters and just send those - re-applying the parameters locally to the
instantiated Encoder?Notice the above are all questions. I'm testing my logic, not really
declaring a "should" :-)Sent from my iPhone
On Jun 24, 2015, at 2:48 AM, Felix Andrews [email protected]
wrote:Encoders are the only things in Comportex HTM values that are not
serializable. We should fix that so that models can be saved or sent over
the wire.Currently they are created using (reify) which makes a closure. But the
main problem is how they get their particular data inputs out of the
general, amorphous input-value provided to htm-step. That is using
pre-transform which applies some arbitrary function to do the extraction.Proposal:
Shift the task of formatting the data for encoding outside to whatever
is creating the input values. An input-value as provided to htm-step would
then be a structured value directly providing the data required by each
input's encoder. Each input already has a keyword id specified in
core/RegionNetwork so these keys could specify the input data for each.Example. Suppose there are 2 inputs (feeding into one or more regions),
called :main-input and :motor. The former is a concatenation of a category
and a coordinate encoding. The latter is a single linear number encoding.The input-value might then look like:
{:motor 42
:main-input [:red {:coord [5.0 10.0], :radius 2.5}]
}
Each input encoder will be passed just its sub value.The various encoder types can be made into Records or Types.
—
Reply to this email directly or view it on GitHub.—
Reply to this email directly or view it on GitHub
#19 (comment)
.
from comportex.
Encoders should probably be decomplected from the core functioning of a HTM network.
Let's call a network node representing encoded input a Sensor. It doesn't need to know about an encoder, only its resulting bit-set. Sensor nodes in a network could simply be containers holding bit-sets. We could define p/htm-activate-raw
taking bit-sets to assign to each Sensor node, rather than a domain-related input value.
However, we would want to record the original input value, as it is used:
- in visualizing the input data for a model (
world-pane
in ComportexViz) - in labelling or grouping states (state transition diagram in ComportexViz, or assessing classification or temporal pooling). Note this could be extra data beyond the values passed to encoders.
So a network (SensingNetwork?) would store (a) a map of encoders, corresponding to the Sensor nodes and (b) its input value. A function htm-activate
would take a domain input value, use the encoders to generate bit-sets, and pass them to htm-activate-raw
. And record the input value.
Does that sound reasonable?
from comportex.
On second thought, the term "Sensor" wrongly suggests that it does its own encoding. A better name is "Sense".
Another question that arises is: should Senses define in themselves whether they provide proximal or distal inputs (as currently), or alternatively should Regions declare each of their inputs to be either proximal or distal (and Sense outputs be available for either purpose)? In other words, should the Senses or the Regions decide?
This would matter if Senses were used by some regions as proximal input and others as distal input. Or if a region needed to receive the same Sense as both proximal and distal input (as was suggested for Layer 4 at one point). However a work-around would be to make duplicate Sense nodes for proximal vs distal. I think I would prefer this to complicating the network connection definitions. So, staying with the current approach for now.
from comportex.
Just so I'm clear... is the SensingNetwork separate from the RegionNetwork? Would it be something like
(let [[htm sensors] (htm-activate htm sensors input)])
or are the inputs being recorded in an atom somewhere? I suspect I'm not interpreting this correctly.
I like "Sense". That name resonates with me. And removing encoders from the RegionNetwork definitely sounds like a good idea since we'll probably never stop creating encoders via higher-order functions, e.g. with pre-transform
, so they'll never be serializable.
from comportex.
Interesting that you say "we'll probably never stop creating encoders via higher-order functions"... as I was just about to have a go at doing that (as in original description of this issue). Do you see a problem?
My current idea is not to have a SensingNetwork, rather encoders would be stored in a RegionNetwork but treated separately. Like this:
(defprotocol PHTM
(sense [this in-value])
(htm-activate-raw [this in-bits])
(htm-learn [this])
(htm-depolarise [this])
...)
(defn htm-activate
[this in-value]
(-> this
(assoc :input-value in-value)
(htm-activate-raw (sense this in-value))))
A RegionNetwork would gain keys :encoders
and :senses
instead of :inputs
from comportex.
Good call, I should have scrolled up. Ok, so no more passing arbitrary values as inputs. Only those that our defrecord
encoders can handle. I can live with that.
from comportex.
I started implementing the proposal above in the demos but it felt wrong. It makes the representation of the world be twisted into a shape required by particular encoders.
For example, in demo coordinates-2d
the world is represented like
{:x -10
:y -20
:vx 1
:vy 1
:ax 1
:ay 1}
i.e. position, velocity, acceleration. And the world is updated each time step by a function that operates on this in a natural way. But with the new proposal we would need a transformation step before it can be used as an input value:
(fn [world-value]
(let [{:keys [x y]} world-value]
{:input {:coord [x y]
:radii [radius radius]}
:world world-value}))
This feels awkward since
- the
:input-value
stored in the model, used for viz or analysis, is then not the original world value, even if maybe it includes the original value somehow (here a magical key:world
, yuck); - that transformation step needs to know about the names (here
:input
) and types of encoders. So if you wanted to switch from one encoder to another you would have to change not only the encoder passed toregion-network
but also the shape of the input value.
It seems better to have encoders encapsulate how to extract their data from the world, as in pre-transform
... So we are left with the serialization problem.
It turns out that almost all uses of pre-transform
so far are just selecting a value under a particular key. Obviously keywords are serializable so such selector use cases are easy. Even in the coordinates-2d
example above, the world value could just as well be represented with {:coord [-10 20], ...}
such that a selector :coord
could be used; the radius doesn't actually depend on the input value so could instead be a parameter of the CoordinateEncoder. If we wanted to switch from a CoordinateEncoder to a pair of LinearEncoders, they could select paths [:coord 0]
and [:coord 1]
without changing the input value - good.
There may be more complex transformations or selections required in other cases. For example NuPIC's GeospatialEncoder has a radius that varies with input, so it would need to operate on a value like {:coord [x y], :radii [rx ry]}
.
Or imagine a world represented by objects in a space, but encoders need to pull out a visual perspective on those objects from a particular point in space. A complex transformation. In this case it seems reasonable to first transform the world into a sensed / sensible value.
So maybe a good compromise is to attach selectors to encoders, which gives some degree of independence between encoders and the shape of the input value, while relying on the user to handle any more complex transformations required to actually compute the data.
from comportex.
Would the model hold on to the selector and the encoder separately? Or would we use something like a higher-level encoder to get-in
the value?
I'm thinking we should keep them separate. Otherwise using p/decode
within the model would become weird.
So it'd be in the region-network
params, either a sense->path
or maybe making sensory-encoders
use a [sense [path encoder]]
format.
from comportex.
Ah, you mean it would be weird because what you pass to p/encode
would be a different shape to what you get out of p/decode
. Yes I see.
I kind of like having an encoder as a self-contained object though. And you couldn't in general switch an encoder without also changing its selector.
What if the PEncoder
protocol had a method extract
which returns the encodable value from the world value, while its encode
method is passed just that extracted value? That would also leave the door open to other more complex extraction functions beyond get-in
, like a juxt
-alike for example...
I don't know, maybe I am complecting.
from comportex.
Names help. If I think of a sensor as a [selector encoder]
then I'm willing to have them defined in user code and passed as arguments.
Whether the selector
should satisfy a protocol or just be a get-in
path, I'm not sure.
from comportex.
Actually this separation makes it awkward to combine sensors. Say we have {:position 42, :colour "red"}
and we want to concatenate an encoding of the number from :position
and the category from :colour
.
Individually they would be
(def posn-sensor [(e/select :position) (e/linear-encoder 100 20 [0 99])])
(def colr-sensor [(e/select :colour) (e/unique-encoder [100] 20)])
But to concatenate them?
(def both-sensor
[(e/juxt (e/select :position) (e/select :colour))
(e/encat
(e/linear-encoder 100 20 [0 99])
(e/unique-encoder [100] 20))])
Whereas if the selector was encapsulated in an encoder one could write
(def both-encoder
(e/encat
(e/select :position
(e/linear-encoder 100 20 [0 99]))
(e/select :colour
(e/unique-encoder [100] 20))))
That said, I'm not sure there is any reason to concatenate encoders into one sense, rather than treating them as separate senses.
from comportex.
My last complaint can be disregarded. In practice one would want to concatenate sensors, so we can have a function (e/sensor-cat)
which just applies e/juxt
and e/encat
as above.
You've convinced me of the need for a PExtractor
protocol. Thanks!
from comportex.
Related Issues (20)
- Separate REPL code from HTM logic, stop forcing autoload, still make autoload convenient
- Readme out of date... HOT 1
- q_learning_1d demo showing "nth not supported" error in tgt->i arg destructuring HOT 1
- Just getting started - cljc files? HOT 2
- caching in encoders
- lazy-growing synapse graph HOT 5
- better hash / random number generator
- naming things HOT 1
- testing / validation strategy HOT 2
- learning functions more like STDP HOT 5
- random selection of learning cells from bursting columns
- Suggestion to try "substitution" or "context" pooling HOT 22
- select cells consistently, esp. when beginning sequences HOT 54
- allow algorithm alternatives HOT 2
- Rainbow order is incorrect in logo HOT 2
- Please export public API for javascript interop HOT 8
- Better docs please :) HOT 6
- composable layers only; get rid of regions
- Support for Clojure 1.9
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from comportex.