# This trains a Self-Organizing Map (Kohonen network) on the digits data.

set cols 10
set rows 10
addNet "digits: SOM"

# no bias connections
deleteGroups bias

addGroup input 64 INPUT
addGroup map [expr $rows * $cols] DISTANCE KOHONEN
connectGroups input map

# This group is necessary because the example set has targets.  
# It isn't functional, otherwise.
addGroup junk 10 OUTPUT -CROSS_ENTROPY

setObj map.numColumns   $cols
setObj randMean         0.5
setObj randRange        0.5
setObj input.numColumns 8
setObj batchSize        100
setObj numUpdates       2000
setObj momentum         0.0
resetNet

# shuffle the order of examples within each epoch during training (PERMUTED)
loadExamples digits-recog.train_ex.txt -s train-rec -exmode PERMUTED
loadExamples digits-recog.test_ex.txt  -s test-rec

# just to make sure everyone starts with exactly the same conditions
loadWeights digits-SOM.init.wt

resetPlot $cols
plotAll map
plotRow 1
plotRow 8 n input 8
drawUnits

viewUnits

proc setNeighborhood {} {
  set updates [getObj totalUpdates]
  if {$updates % 50} return
  if {$updates == 0} {
    setObj map.neighborhood 6
  } else {
    setObj map.neighborhood [expr 0.9 * [getObj map.neighborhood] + 0.1]
  }	
  puts "Neighborhood = [getObj map.neighborhood]"
}

setObj preEpochProc setNeighborhood
#setObj map.neighborhood 1.0
