javascript - Why I am getting NaN when I toggle the loop? -


i'm trying write k-means function in javascript. , here code.

function kmeans(arraytoprocess,cluster_n){     var pointdimension = arraytoprocess[0].length;     var clusterresult = new array();     var clustercenter = new array();     var oldclustercenter = new array();     var changed=false;     for(var = 0;i<cluster_n;i++)         clustercenter.push(arraytoprocess[randomint(arraytoprocess.length-1)]);      console.log(clustercenter);      // do{     for(var k=0;k<50;k++){//loop         for(var = 0; i<cluster_n; i++){             clusterresult[i] = new array();         }         for(var = 0; i<arraytoprocess.length; i++){             //for every point element             var olddistance=-1;             var newclusternumber = 0;             for(var j = 0; j<cluster_n; j++){                 //for every cluster                 var distance = math.abs(computedistancebetween(arraytoprocess[i], clustercenter[j]));                    if (olddistance == -1){                     olddistance = distance;                     newclusternumber = j;                 }else if ( distance <= olddistance ){                     newclusternumber = j;                     olddistance = distance;                 }             }             clusterresult[newclusternumber].push(arraytoprocess[i]);         }         oldclustercenter = clustercenter;         //compute new centroid         for(var = 0; i<cluster_n; i++){             newcentroid = pinit(pointdimension);             for(var j = 0; j<clusterresult[i].length; j++){                 newcentroid = padd(clusterresult[i][j], newcentroid);             }             clustercenter[i] = pdivide(newcentroid, clusterresult[i].length);         }          changed=false;         for(var = 0; i<cluster_n; i++){             if(!pequal(clustercenter[i],oldclustercenter[i]))                 changed = true;         }     }//while (changed == true);      return clusterresult; }   function computedistancebetween(a,b){     var result = 0;     for(var = 0; i<a.length;i++) result += a[i] * b[i];     return result; }  function pinit(n){     var result = new array(n);     for(var i=0;i<n;i++) result[i] = 0;     return result; }  function padd(a,b){     var result = new array(a.length);     for(var = 0; i<a.length;i++) result[i] = a[i] + b[i];     return result; }  function pdivide(a,d){     var result = new array(a.length);     for(var = 0; i<a.length;i++) result[i] = a[i] / d;     return result; }  function pequal(a,b){     for(var = 0; i<a.length;i++)          if(a[i] != b[i]) return false;     return true; }  function randomint(max){     return randomintbetween(0,max); }  function randomintbetween(min,max){     return math.floor(math.random() * (max - min + 1)) + min; } 

if stop for-loop(k<0), console gives right answer. if start for-loop(k<1),the array clustercenter has nan items. how dose nan appear?

edit: further explanation: if for-loop in 14th line has been executed, clustercenter above give nan items.why?

example input

var testarray = new array(); for(var i=0; i<100; i++) testarray.push([randomint(-150,150),randomint(-150,150)]); kmeans(testarray,4); 

the clustercenter above give nan items.why?

because you're diving 0 zero, not number. happen every empty cluster in clusterresult - create clustercenter[i] = pdivide(pinit(pointdimension), 0);.

how deal empty clusters? possible strategies think of make 0/0 = 0, choose new random cluster center, or drop cluster alltogether (cluster_n--).

but why many empty clusters in first place? because computedistancebetween function flawed. every (non-0|0) point distant itself. choose more reasonable distance function, euclidian distance. should return positive number, rendering math.abs in loop superflouos.


some other points:

  • newcentroid misses var statement , leaks global scope
  • your changed flawed. when setting oldclustercenter = clustercenter, both variables hold same array mutated. not pequal(clustercenter[i],oldclustercenter[i]) true, clustercenter[i]===oldclustercenter[i] because of oldclustercenter === clustercenter.

    to fix this, either make oldclustercenter = clustercenter.slice() or introduce clustercenter = new array(cluster_n); after assignment.

  • your code computing nearest cluster simplified to

    var newclusternumber = 0,     olddistance = computedistancebetween(arraytoprocess[i], clustercenter[0])); (var j=1; j<cluster_n; j++) {     var distance = computedistancebetween(arraytoprocess[i], clustercenter[j]);     if (distance <= olddistance) {         newclusternumber = j;         olddistance = distance;     } } 

    or

    var onewclusternumber, lddistance=infinity; (var j=0; j<cluster_n; j++) {     var distance = computedistancebetween(arraytoprocess[i], clustercenter[j]);     if (distance <= olddistance) {         newclusternumber = j;         olddistance = distance;     } } 

Comments

Popular posts from this blog

how to proxy from https to http with lighttpd -

android - Automated my builds -

python - Flask migration error -