UNPKG

kohonen-net

Version:

simple implementation of a self organizing map

72 lines (51 loc) 2.13 kB
var num = require('numeric'); var utils = require('./utils.js'); function SelfOrganizingMap(nFeatures, outputLayer, distanceFn, wraparound, learningRate){ this.nFeatures = nFeatures; this.outputLayer = outputLayer; this.learningRate_t0 = learningRate; this.nOutputnodes = outputLayer.reduce((s, p) => s*p, 1); this.neighbourhoodMatrix = utils.neighbourMatrix(outputLayer, distanceFn, wraparound); this.neighbourhoodMean = this.neighbourhoodMatrix.map(v => {return num.sum(v)/v.length}); this.neighbourhoodMatrixNeg = num.neg(num.pow(this.neighbourhoodMatrix, 2)); this.weights = utils.random_tensor([this.nOutputnodes, nFeatures]); this.t = 0; this.lrDecay = Math.pow(2, 20); this.neighbourDecay = Math.pow(2, 14); this.neighbourhoodCutoff = 5; this.trainStep = function(feature){ let fwDiff = this.computeFeatureWeightDifference(feature); let discriminantV = this.computeDiscriminantVector(fwDiff); let winner = utils.argMin(discriminantV); let nf = this.neighbourhoodFactor(winner); let lr = this.learningRate(); let deltaW = fwDiff.map((val, i) => val.map(val=> val*nf[i]*lr)); num.addeq(this.weights, deltaW); this.t++; } this.computeFeatureWeightDifference = function(features){ return this.weights.map(v => num.sub(features, v)); } this.computeDiscriminantVector = function(fwDiff){ return num.abs(fwDiff).map(v=>num.sum(v)); } this.learningRate = function(winner){ return this.learningRate_t0 * Math.exp(-this.t/this.lrDecay); } this.neighbourhoodFactor = function(winner){ let sigma = this.neighbourhoodMean[winner] * Math.exp(-this.t/this.neighbourDecay); ret = num.exp(num.div(this.neighbourhoodMatrixNeg[winner], sigma)); //console.log(ret); return ret; } } data = [[1, 1], [1, 100], [100, 1], [100, 100]]; let som = new SelfOrganizingMap(2, [16], utils.manhattanDistance, true, 0.2); for (let i=0;i<1000;i++){ for (let j=0;j<data.length;j++){ som.trainStep(data[j]); } } console.log(som.weights); module.exports.SelfOrganizingMap = SelfOrganizingMap; module.exports.utils = utils;