mars0i / popco2

Cultural transmission with analogy biases.
GNU General Public License v3.0
3 stars 0 forks source link

Represent zero-weight links as links in proposition net #6

Closed mars0i closed 10 years ago

mars0i commented 10 years ago

At present, there is no distinction between a zero-weight link and a non-link in the proposition net. (In the analogy net, there are no zero-weight links.) This may not matter for routine operation, but it's a disaster for diagnostic display of network structure such as in graphical representations.

mars0i commented 10 years ago

When this is fixed, also fix format-nn-for-gephi to reflect the change.

mars0i commented 10 years ago

Added links function to NNMat protocol, definitions of it to AnalogyNet and PropnNet, :link-mat field to PropnNet record, and initialization of it with a core.matrix matrix in make-propn-net.

Still have to cause this matrix to be updated when things are done to the propn net.

Propn nets get links from:

  1. Links to SALIENT to rep persistent activation input. These come from:
    1. Receipt of utterances, which always adds a (pos or neg) bump to the link from SALIENT.
    2. Initial perceived propns. e.g. in crime3/grouptest1.clj, this is stored in crime-perception-ifs, which is then passed as the value of the sem-ifs parameter of make-propn-net in the definition of crime-perc-pnet. These are then passed to new-linger-wt-mat in make-propn-net.
  2. semantic-if(f)s between propositions. These come from the original proposition definition file. e.g. in crime3/propns.clj, these are in semantic-iffs.
  3. Links resulting from activations in propn-map-nodes in the analogy net.

Note that the preceding can be broken up into two categories: Links created during initialization, and links created during runtime. The latter come only from the utterance bump, and from analogy net map nodes.

However, the analogy net map nodes create their links very early on, even if maybe they don't acquire nonzero values on tick 1. We might as well set those to be links during initialization. NO. That is wrong. If a person doesn't have all propositions initially, then some map nodes, including propn map nodes, will be masked until all appropriate propns have been received. The links in the proposition network corresponding to propn map node activations should not exist until those map nodes are unmasked.

Caveat: If programmer manipulates the propn net by removing e.g. semantic links then we might have to also do something to the link mat.

Some places to consider making changes:

  1. popco.nn.propn/new-linger-wt-mat. This currently creates and returns a new linger-wt-mat, but here I'm considering returning also a link mat. But at this stage, maybe there are no zero-weight links, really. That would mean you would be passing semantic-ifs or -iffs that were zero weight. So an option would be to create the link mat from the new linger wt mat immediately after the latter is created.
  2. popco.communic.listen/update-propn-net-from-utterances: maybe after add-from-feeder-node! call.
  3. Somewhere in popco.nn.update/update-propn-wts-from-analogy-activns or in something it calls. Maybe in update-propn-wts-from-analogy-activns after calling propn-wts-from-analogy-activns? It looks like the right place to do it, theoretically, would be in propn-wts-from-analogy-activns, since that's where there's a loop through the new changes. But this is currently returning a core.matrix mat, and what's needed would be to be passed the old link mat and return that, as well.

Or could I just use the linger-wt-mat as the link matrix? Well can it have zero wt links?

Consider replacing "low-level" core.matrix link-making wrappers with wrappers that operate on NNMats and update the link mat when the NNMat is a PropnNet, but does nothing when it's an AnalogyNet. Well, you have to work with both linger-wt-mat and the activation mat, in the case of the propn net.

Well that last idea of polymorphic functions on NNMats is a nice idea, but it's probably a bad idea because for the sake of efficiency it's good to be able to control when you create a fresh matrix to write into, within a function, so that externally the function appears purely functional. e.g. update-propn-net-from-utterances, called by receive-utterances, creates a fresh linger-wt-mat before looping through writes to it. Of course we could add functions that performed that fresh-mat-creation on NNMats, but that may be going down the Java-ish wrapping-everything verbosity route more than I like.

mars0i commented 10 years ago

When will linger-wt-mat have zero-weight links (rather than non-links)?

  1. When positive bumps from utterances or perceptions are exactly counteracted by negative bumps, or vice versa. If that's just due to utterances, maybe it would be fine for the link to disappear in that situation. But if perception is involved, don't you want to retain the information that there's a link there?
  2. Suppose you have a link controlled by a propn map node that has activation zero. Maybe you don't care about that link, but it still is controlled by the map node. If you can't see the link, then it's impossible to determine that. Also, suppose that you have a semantic-iff, and it's counteracted by the propn-map-node-controlled activation to produce a zero-weight link. I definitely want to be able to see that link.

Here's another issue: If you have graphical layout routines being reapplied, and they're sensitive to the existence of links (which they always are), then you could have the layout jumping around unnecessarily as links come and go due to getting zeroed out or unzeroed.

Conclusion: linger-wt-mat can't do double-duty as a link mat.

mars0i commented 10 years ago

Note: The link mat should not just be a lower triangle or something like that. You want to be able to see whether you've got a one-way or a two-way link.

mars0i commented 10 years ago

If I modify link-mat, then I have to copy it first. So maybe I need to check on each iteration e.g. in update-propn-wts-from-analogy-activns to see if link-mat needs updating, and then copy it only if at least one update is needed.

mars0i commented 10 years ago

Or maybe I could check for new links globally at the end of a tick, by checking for nonzero weights where there are zeros in the old link mat. If so, those are the new links. This would ignore any new zero-weight links, but I'm willing to not care about them until they at least have a nonzero weight once. (Is that a good idea??)

_Well suppose that a proposition is added due to communication, and this causes a new propn map node to be unmasked, but this propn map node has activn zero. (This is unlikely, but it could occur.) Suppose that this map node never gets a nonzero activation. Then in the system just mentioned, there would never be a corresponding link in the proposition network. Wouldn't that be confusing? It could look like a bug--i.e. that the proposition network is not getting updated from proposition map nodes in only this one case. And then I might spend time chasing down what's not actually a bug in the underlying process--only in how it's represented to network display software. Even more confusing, suppose that because of low-activation transmission across the network, it takes many ticks before this zero-activation map node gets a nonzero activation. Then suddenly, many ticks after the map node came into existence (i.e. was unmasked), the link in the proposition network seems to spring into existence. How much time would I spend trying to figure out _that?

e.g. use a Kronecker delta function (is there a core.matrix built-in now?) to clamp a copy of the propn-net to 1 iff weight is nonzero. Then subtract the old wt mat from that. Nonzero elements are new links. (If an element is -1, that's OK. That's an existing link that has gone to zero, maybe only temporarily.) So e.g. do that and then posify and then add with the old link-mat.

Or maybe create an inverse image of the link mat by subtracting it from the all-ones matrix. Then element-wise multiply that times the propn-net wt-mat. The result would be nonzero only where there was a zero in the link mat and a nonzero in the wt-mat. Then either poke 1's into a fresh link-mat where those nonzero resulting values are, or Kronecker-delta-ify them and add them into the old link-mat to create the new link-mat.

The assumption here is that links never go away once they arrive. Note this might fail if programmer engages in direct manipulation of links during a run. In that case, something might have to be done to get the link mat back in sync.

mars0i commented 10 years ago

Note that if, in the future, I were to allow one-way inference links (ifs) to be inferred, i.e. calculated somehow, this might require additional work.

mars0i commented 10 years ago

There's an additional thing to think about if I want to avoid missing propn net links from zero-activn propn map nodes in analogy net, by updating a link mat in update/propn-wts-from-analogy-activns: As #23 explains, that function pays no attention to what is and isn't masked. i.e. I would have to modify the loop in order for it to distinguish between links and non-links.

mars0i commented 10 years ago

There are two general strategies listed in previous comments:

  1. Modify propn net's link-mat during whatever internal processes happen to add links to propn net.
  2. Wait until the end of each tick, and do a somewhat kludgey calculation to identify new links in propn net. Then add those to link-mat. (But if a link subsequently goes to zero, don't remove it.)

With strategy 2, why should I perform this calculation on every tick, no matter what? I only need it for output to network display procedures. So why not calculate it only when those are operating? And only for those persons whose propn nets will be displayed?

Well, if part of the point is to prevent links from that go to zero from disappearing, this won't have that effect if, say, I start displaying the network at tick 500, and a link that wasn't zero is zero at that point.

And there would need to be some way to pass something like the link-mat from generation to generation. I suppose I could still store it in the population, but just only calculate it on an as-needed basis.

mars0i commented 10 years ago

I'm starting to think that the whole link-mat strategy of preserving zero-weight propn net links is not worth the trouble. There was no extra work required in popco1, but here I'm having to rethink internal processes for this sake.

After all, most of the time, this won't happen, and when it does, if you know that links can disappear, then it won't be that hard to figure it out.

Note that the persistence of zero-wt links could even be effected in the network output routines. e.g. maybe when constructing a new tick's state for Gephi, if the link was there last time, don't let it go away; just update it to have zero weight.

I like that. Preserving link information is not the responsibility of the internal processes. They are designed to be efficient.

On the other hand: What is the point of the internal processes, if not to ultimately generate output? One kind of output is network structure.

Yeah, but that's really about the process. It's worth monitoring, sometimes, but the effect to be studied is really degrees of belief. Or possibly analogy net activations. The weights are the means. (Anyway, that's a line you could take.)

On the third hand, a general drawback with moving to matrix representations is that it makes it more difficult to observe what's going on in the processes. This is one more dimension of this. Allowing reliable observation of link structure would counteract this trend.

mars0i commented 10 years ago

Well, the main thing I need to do to keep track of network links, beyond what's already provided by the weight matrices, is to track when a propn net link starts at a nonzero value and then goes to zero. That's not perfect, since an analogy net propn map node could cause what should be conceived of as a initially zero-weight link, but I am willing to ignore that. And it could be fixed by monitoring unmasked analogy net propn nodes. (Actually, that's not a bad idea: If unmask a propn map node, then add a propn net link.)

But the main idea can be implemented with the comparison-at-end-of-tick-procedure. And that could be an additional map-on (add on done with map) that fills what is otherwise a dummy slot in the person.

mars0i commented 10 years ago

I've decided to retain the link-mat field in Propn, and the links function in the NNMats protocol, but now they don't really do anything unless I write an extra program that will apply to a population (e.g. using map) and update the link-mats of propn-nets of one or more persons. i.e. if you want accurate tracking of zero-weight links in your external network program, then add a function that will keep track of that by filling the link-mat field in one or more of the persons. You can map it over populations. Or rather, you will have to interpose it in the iterate sequence. i.e. you can't use many-times directly if you want to maintain this information in each link-mat field. (i.e. once is a function from a population to a population, and many-times applies it iteratively to generate a sequence of populations. To add maintenance of the link-mat, you'd need to do (iterate (comp link-updater once) initial-population).