Giter Club home page Giter Club logo

clusters's People

Contributors

nathanepstein avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

clusters's Issues

I am getting [object],[object] on points

[ { centroid: [ 10.5, 11 ], points: [ [Object], [Object] ] }, { centroid: [ -9.5, 10.5 ], points: [ [Object], [Object] ] }, { centroid: [ 0.3333333333333333, 0.3333333333333333 ], points: [ [Object], [Object], [Object] ] } ]
How can I remove this [Object] in the points

Get original index of data?

Hi,

This tool is amazing! Quick question for you. I am using this to cluster groups of students based on their performance. Your tool produces the clusters exactly as I would hope. However, it doesn't seem to output which data indexes are in each cluster, just the data itself. What I'd like is for each cluster output to include an array of the indexes contained, so that I can easily say "Cluster 1 includes students 1, 4, and 8", Cluster 2 includes students 2, 3, and 6", etc.

Is that possible? Or do I have to do a lookup after the fact to reconnect the original data index with the cluster outputs based on the points array?

Thanks,
John

Minor adjustment.

Hey Nathan, not necessarily an issue...but a few amendments to your code. It was quite helpful.

let clusterMaker = {

    data: getterSetter([], (arrayOfArrays) => {
        let n = arrayOfArrays[0].length;
        return (arrayOfArrays.map((array) => {
            return array.length === n;
        }).reduce((boolA, boolB) => {
            return (boolA & boolB)
        }, true));
    }),

    clusters: function () {
        let pointsAndCentroids = kmeans(this.data(), {k: this.k(), iterations: this.iterations()});
        let points = pointsAndCentroids.points;
        let centroids = pointsAndCentroids.centroids;

        let centroidReturnValue =  centroids.map((centroid) => {
            return {
                centroid: centroid.location(),
                points: points.filter((point) => {
                    return point.label() === centroid.label()
                }).map((point) => {
                    return point.location()
                }),
            };
        });

        centroidReturnValue.map((centroid, key) => {
            console.log("Cluster", key ," ", centroid);
        });

        return centroidReturnValue
    },

    k: getterSetter(undefined, (value) => {
        return ((value % 1 === 0) & (value > 0))
    }),

    iterations: getterSetter(Math.pow(10, 3), (value) => {
        return ((value % 1 === 0) & (value > 0))
    }),

};

function kmeans(data, config) {
    // default k
    let k = config.k || Math.round(Math.sqrt(data.length / 2));
    let iterations = config.iterations;

    // initialize point objects with data
    let points = data.map((vector) => {
        return new Point(vector)
    });

    // intialize centroids randomly
    let centroids = [];
    for (let i = 0; i < k; i++) {
        centroids.push(new Centroid(points[i % points.length].location(), i));
    }

    // update labels and centroid locations until convergence
    for (let iter = 0; iter < iterations; iter++) {
        points.forEach((point) => {
            point.updateLabel(centroids)
        });
        centroids.forEach((centroid) => {
            centroid.updateLocation(points)
        });
    }

    // return points and centroids
    return {
        points: points,
        centroids: centroids
    };

}

// objects
function Point(location) {
    let self = this;
    this.location = getterSetter(location);
    this.label = getterSetter();
    this.updateLabel = (centroids) => {
        let distancesSquared = centroids.map((centroid) => {
            return sumOfSquareDiffs(self.location(), centroid.location());
        });
        self.label(mindex(distancesSquared));
    };
}

function Centroid(initialLocation, label) {
    let self = this;
    this.location = getterSetter(initialLocation);
    this.label = getterSetter(label);
    this.updateLocation = (points) => {
        let pointsWithThisCentroid = points.filter((point) => {
            return point.label() === self.label()
        });
        if (pointsWithThisCentroid.length > 0) self.location(averageLocation(pointsWithThisCentroid));
    };
}

// convenience functions
function getterSetter(initialValue, validator) {
    let thingToGetSet = initialValue;
    let isValid = validator || function (val) {
        return true
    };
    return (newValue) => {
        if (typeof newValue === 'undefined') return thingToGetSet;
        if (isValid(newValue)) thingToGetSet = newValue;
    };
}

function sumOfSquareDiffs(oneVector, anotherVector) {
    let squareDiffs = oneVector.map((component, i) => {
        return Math.pow(component - anotherVector[i], 2);
    });
    return squareDiffs.reduce((a, b) => {
        return a + b
    }, 0);
}

function mindex(array) {
    let min = array.reduce((a, b) => {
        return Math.min(a, b);
    });
    return array.indexOf(min);
}

function sumVectors(a, b) {
    return a.map((val, i) => {
        return val + b[i]
    });
}

function averageLocation(points) {
    let zeroVector = points[0].location().map(() => {
        return 0
    });
    let locations = points.map((point) => {
        return point.location()
    });
    let vectorSum = locations.reduce((a, b) => {
        return sumVectors(a, b)
    }, zeroVector);
    return vectorSum.map((val) => {
        return val / points.length
    });
}

//number of clusters, defaults to undefined
clusterMaker.k(3);

//number of iterations (higher number gives more time to converge), defaults to 1000
clusterMaker.iterations(750);

//data from which to identify clusters, defaults to []
clusterMaker.data([[1, 0], [0, 1], [0, 0], [-10, 10], [-9, 11], [10, 10], [11, 12]]);

clusterMaker.clusters();

Return indexes of the points instead

Instead of returning the points of the original matrix, I would like it to return an array of indexes pointing to the original points in the matrix. Here is 1 way you can do it

  clusters: function() {
    var pointsAndCentroids = kmeans(this.data(), {k: this.k(), iterations: this.iterations() });
    var points = pointsAndCentroids.points;
    var centroids = pointsAndCentroids.centroids;
    return centroids.map(function(centroid) {
      return points.reduce(function(acc, point, i) {
          if (point.label() == centroid.label()) {
            acc.push(i);
          }
          return acc;
        }, []);
    });
  },

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.