ioam / topographica

A general-purpose neural simulator focusing on topographic maps.
topographica.org
BSD 3-Clause "New" or "Revised" License
53 stars 32 forks source link

about the learning function reset #616

Closed kqqun closed 9 years ago

kqqun commented 9 years ago

Dear, now I am trying to test the influence of different learning functions on the GCAL model. But it is confused to me that if I deliberately reset all the weights to zeros, the resutant orientation preferance map is similar to that learned with hebbian , BCM functions et.al. The details is below:

  1. Resetting the learning function: projection.CFProjection.learning_fn=learningfn.optimized.CFPLF_Fold()(which is in the file "topographica/topo/submodel/gcal/py") 2.Definning CFPLF_Fold() in the file "topographica/topo/learningfn/optimized.py" as: class CFPLF_Fold(CFPLF_Plugin): single_cf_fn = param.ClassSelector(LearningFn,default=Fold(),readonly=True) 3.Definning Fold() in the file "topographica/topo/learningfninit.py/" as: class Fold(LearningFn): def call(self,input_activity, unit_activity, weights, single_connection_learning_rate): weights=0; Now I do not know whether I have some misunderstanding or the learning function used to train the model has been resetted elsewhere. Thank you for reply.
jbednar commented 9 years ago

There are several issues here.

  1. It's not a good idea to modify the files in topo/ directly; there should never be a need to do that unless you find a specific bug, in which case of course we would want to see a pull request showing us how to fix that bug, and then once we applied it you could go back to having an unmodified topo/. Apart from that, you never need to edit topo to do something like select a different learning_fn; that can and should always be done in your .ty file without any change to the underlying copy of Topographica.
  2. For what you're trying to do, I recommend starting with examples/gcal_oo_or.ty, not examples/gcal.ty. gcal.ty is the complete model covering all possible options, but because of that it can be very difficult to see how it is put together. If you start by making a copy of gcal_oo_or.ty, you should be able to see precisely how the various components are chosen, and then change them easily in one place. Eventualy, if you came up with a model that you wanted to then expand to the visual dimensions other than orientation (which is all gcal_oo_or.ty supports), then it would be easier to do so from a working copy of gcal_oo_or.ty than by changing topo.submodel directly. And even in that case you can do it by subclassing from topo.submodel's classes, or just by setting their parameters as you instantiate them, never by modifying the code directly. Of course, since it's open source, you can do whatever you like; I'm just saying what I strongly, strongly recommend so that you (a) don't confuse yourself, and (b) don't confuse us when sending us issues like this. :-)
  3. The main use for the "readonly=True" designation for a Parameter is to indicate that the value for it is hard-coded somewhere, and that the user cannot actually ever change it. Where it is used, it usually means that we have C code implementing what that Parameter declares, and changing that declaration isn't actually going to have any effect on the corresponding C code. So if something is marked readonly, then don't change it -- you have to instead supply a different component that's not hardcoded in this way. If you follow the rule of not modifying topo/, you shouldn't have any problem like this, because then Topographica will complain if you attempt to replace a read-only parameter's value. You can go around that by editing topo/, but don't!
  4. One thing that might make your life simpler is removing ".optimized" and "_opt" from your copy of gcal_oo_or.ty. The optimized versions of the indicated functions are much, much faster, but they are limited in certain ways, which is reflected in the readonly parameters. If you use the corresponding non-opt version, you should get very similar results (not precisely, due to floating point issues, but very similar), albeit much more slowly. And you can then swap components as much as you like.
  5. Just doing weights=0 isn't going to achieve anything, for several reasons. First, the optimized C code uses weights stored in a fixed area of memory, and what weights=0 does is change the local variable "weights" to point at the integer zero, without having any effect at all on the underlying data structures in which the weights are stored. When the function is first called, "weights" points to that underlying data structure, and all you are doing is to make that local variable now point to the number zero, which has no lasting effect once you exit this function. Second, even if it did achieve what you wanted, it would have had the effect of turning the entire weights array into the single number zero, which would have broken everything, so you're lucky it actually had no effect! Third, even if you did manage to make the weights array all zeros, the weights are by default normalized to a constant sum of 1, which is impossible with weights that are all zero, so again you're lucky that you did not achieve this! If you really did want the weights to be zero, you could do "weights = 0", which modifies the weights in place, and you would also have to turn off the weight normalization (weights_output_fn). But here you probably really want "weights = 0; weights +=1", to set them all to 1 instead of zero, which can then easily be normalized to 1.

Hope all this make sense, and I hope this advice will make things go more smoothly now!