楼主: ReneeBK
1009 2

K-Nearest Neighbor using JavaScript [推广有奖]

  • 1关注
  • 62粉丝

VIP

已卖:4897份资源

学术权威

14%

还不是VIP/贵宾

-

TA的文库  其他...

R资源总汇

Panel Data Analysis

Experimental Design

威望
1
论坛币
49635 个
通用积分
55.6937
学术水平
370 点
热心指数
273 点
信用等级
335 点
经验
57805 点
帖子
4005
精华
21
在线时间
582 小时
注册时间
2005-5-8
最后登录
2023-11-26

楼主
ReneeBK 发表于 2016-6-27 00:08:16 |AI写论文

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币
K-Nearest neighbor classifier

A General purpose k-nearest neighbor classifier algorithm based on the k-d tree Javascript library develop by Ubilabs:

Methodsnew NaiveBayes()

Constructor that takes no arguments.

Example

var knn = new KNN();
train(trainingSet, predictions)

Train the Naive Bayes model to the given training set, predictions, and some options.

Arguments

  • trainingSet - A matrix of the training set.
  • trainingLabels - An array of value for each case in the training set.
  • options - Object with the options for the training.

Options

  • k - number of nearest neighbor (Default, number of label + 1).
  • distance - distance function for the algorithm, the argument is a function, not an String (by default is euclidean, you can use the functions of this repository distance).

Example

var trainingSet = [[0, 0, 0], [0, 1, 1], [1, 1, 0], [2, 2, 2], [1, 2, 2], [2, 1, 2]];var predictions = [0, 0, 0, 1, 1, 1];knn.train(trainingSet, predictions);
predict(dataset)

Predict the values of the dataset.

Arguments

  • dataset - A matrix that contains the dataset.

Example

var dataset = [[0, 0, 0],               [2, 2, 2]];var ans = knn.predict(dataset);
export()

Exports the actual K-Nearest Neighbor model to an Javascript Object.

load(model)

Returns a new K-Nearest Neighbor Classifier with the given model.

Arguments

  • model - Javascript Object generated from export() function.
AuthorsLicense

MIT

本帖隐藏的内容

knn-master.zip (8.27 KB)



二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

关键词:Javascript script Using scrip Java training library General develop purpose

沙发
ReneeBK 发表于 2016-6-27 00:09:05
  1. 'use strict';

  2. /**
  3. * k-d Tree JavaScript - V 1.01
  4. *
  5. * https://github.com/ubilabs/kd-tree-javascript
  6. *
  7. * @author Mircea Pricop <pricop@ubilabs.net>, 2012
  8. * @author Martin Kleppe <kleppe@ubilabs.net>, 2012
  9. * @author Ubilabs http://ubilabs.net, 2012
  10. * @license MIT License <http://www.opensource.org/licenses/mit-license.php>
  11. */


  12. function Node(obj, dimension, parent) {
  13.     this.obj = obj;
  14.     this.left = null;
  15.     this.right = null;
  16.     this.parent = parent;
  17.     this.dimension = dimension;
  18. }

  19. function kdTree(points, metric, dimensions) {

  20.     var self = this;

  21.     function buildTree(points, depth, parent) {
  22.         var dim = depth % dimensions.length,
  23.             median,
  24.             node;

  25.         if (points.length === 0) {
  26.             return null;
  27.         }
  28.         if (points.length === 1) {
  29.             return new Node(points[0], dim, parent);
  30.         }

  31.         points.sort(function (a, b) {
  32.             return a[dimensions[dim]] - b[dimensions[dim]];
  33.         });

  34.         median = Math.floor(points.length / 2);
  35.         node = new Node(points[median], dim, parent);
  36.         node.left = buildTree(points.slice(0, median), depth + 1, node);
  37.         node.right = buildTree(points.slice(median + 1), depth + 1, node);

  38.         return node;
  39.     }

  40.     // Reloads a serialied tree
  41.     function loadTree (data) {
  42.         // Just need to restore the `parent` parameter
  43.         self.root = data;

  44.         function restoreParent (root) {
  45.             if (root.left) {
  46.                 root.left.parent = root;
  47.                 restoreParent(root.left);
  48.             }

  49.             if (root.right) {
  50.                 root.right.parent = root;
  51.                 restoreParent(root.right);
  52.             }
  53.         }

  54.         restoreParent(self.root);
  55.     }

  56.     // If points is not an array, assume we're loading a pre-built tree
  57.     if (!Array.isArray(points)) loadTree(points, metric, dimensions);
  58.     else this.root = buildTree(points, 0, null);

  59.     // Convert to a JSON serializable structure; this just requires removing
  60.     // the `parent` property
  61.     this.toJSON = function (src) {
  62.         if (!src) src = this.root;
  63.         var dest = new Node(src.obj, src.dimension, null);
  64.         if (src.left) dest.left = self.toJSON(src.left);
  65.         if (src.right) dest.right = self.toJSON(src.right);
  66.         return dest;
  67.     };

  68.     this.insert = function (point) {
  69.         function innerSearch(node, parent) {

  70.             if (node === null) {
  71.                 return parent;
  72.             }

  73.             var dimension = dimensions[node.dimension];
  74.             if (point[dimension] < node.obj[dimension]) {
  75.                 return innerSearch(node.left, node);
  76.             } else {
  77.                 return innerSearch(node.right, node);
  78.             }
  79.         }

  80.         var insertPosition = innerSearch(this.root, null),
  81.             newNode,
  82.             dimension;

  83.         if (insertPosition === null) {
  84.             this.root = new Node(point, 0, null);
  85.             return;
  86.         }

  87.         newNode = new Node(point, (insertPosition.dimension + 1) % dimensions.length, insertPosition);
  88.         dimension = dimensions[insertPosition.dimension];

  89.         if (point[dimension] < insertPosition.obj[dimension]) {
  90.             insertPosition.left = newNode;
  91.         } else {
  92.             insertPosition.right = newNode;
  93.         }
  94.     };

  95.     this.remove = function (point) {
  96.         var node;

  97.         function nodeSearch(node) {
  98.             if (node === null) {
  99.                 return null;
  100.             }

  101.             if (node.obj === point) {
  102.                 return node;
  103.             }

  104.             var dimension = dimensions[node.dimension];

  105.             if (point[dimension] < node.obj[dimension]) {
  106.                 return nodeSearch(node.left, node);
  107.             } else {
  108.                 return nodeSearch(node.right, node);
  109.             }
  110.         }

  111.         function removeNode(node) {
  112.             var nextNode,
  113.                 nextObj,
  114.                 pDimension;

  115.             function findMin(node, dim) {
  116.                 var dimension,
  117.                     own,
  118.                     left,
  119.                     right,
  120.                     min;

  121.                 if (node === null) {
  122.                     return null;
  123.                 }

  124.                 dimension = dimensions[dim];

  125.                 if (node.dimension === dim) {
  126.                     if (node.left !== null) {
  127.                         return findMin(node.left, dim);
  128.                     }
  129.                     return node;
  130.                 }

  131.                 own = node.obj[dimension];
  132.                 left = findMin(node.left, dim);
  133.                 right = findMin(node.right, dim);
  134.                 min = node;

  135.                 if (left !== null && left.obj[dimension] < own) {
  136.                     min = left;
  137.                 }
  138.                 if (right !== null && right.obj[dimension] < min.obj[dimension]) {
  139.                     min = right;
  140.                 }
  141.                 return min;
  142.             }

  143.             if (node.left === null && node.right === null) {
  144.                 if (node.parent === null) {
  145.                     self.root = null;
  146.                     return;
  147.                 }

  148.                 pDimension = dimensions[node.parent.dimension];

  149.                 if (node.obj[pDimension] < node.parent.obj[pDimension]) {
  150.                     node.parent.left = null;
  151.                 } else {
  152.                     node.parent.right = null;
  153.                 }
  154.                 return;
  155.             }

  156.             // If the right subtree is not empty, swap with the minimum element on the
  157.             // node's dimension. If it is empty, we swap the left and right subtrees and
  158.             // do the same.
  159.             if (node.right !== null) {
  160.                 nextNode = findMin(node.right, node.dimension);
  161.                 nextObj = nextNode.obj;
  162.                 removeNode(nextNode);
  163.                 node.obj = nextObj;
  164.             } else {
  165.                 nextNode = findMin(node.left, node.dimension);
  166.                 nextObj = nextNode.obj;
  167.                 removeNode(nextNode);
  168.                 node.right = node.left;
  169.                 node.left = null;
  170.                 node.obj = nextObj;
  171.             }

  172.         }

  173.         node = nodeSearch(self.root);

  174.         if (node === null) { return; }

  175.         removeNode(node);
  176.     };

  177.     this.nearest = function (point, maxNodes, maxDistance) {
  178.         var i,
  179.             result,
  180.             bestNodes;

  181.         bestNodes = new BinaryHeap(
  182.             function (e) { return -e[1]; }
  183.         );

  184.         function nearestSearch(node) {
  185.             var bestChild,
  186.                 dimension = dimensions[node.dimension],
  187.                 ownDistance = metric(point, node.obj),
  188.                 linearPoint = {},
  189.                 linearDistance,
  190.                 otherChild,
  191.                 i;

  192.             function saveNode(node, distance) {
  193.                 bestNodes.push([node, distance]);
  194.                 if (bestNodes.size() > maxNodes) {
  195.                     bestNodes.pop();
  196.                 }
  197.             }

  198.             for (i = 0; i < dimensions.length; i += 1) {
  199.                 if (i === node.dimension) {
  200.                     linearPoint[dimensions[i]] = point[dimensions[i]];
  201.                 } else {
  202.                     linearPoint[dimensions[i]] = node.obj[dimensions[i]];
  203.                 }
  204.             }

  205.             linearDistance = metric(linearPoint, node.obj);

  206.             if (node.right === null && node.left === null) {
  207.                 if (bestNodes.size() < maxNodes || ownDistance < bestNodes.peek()[1]) {
  208.                     saveNode(node, ownDistance);
  209.                 }
  210.                 return;
  211.             }

  212.             if (node.right === null) {
  213.                 bestChild = node.left;
  214.             } else if (node.left === null) {
  215.                 bestChild = node.right;
  216.             } else {
  217.                 if (point[dimension] < node.obj[dimension]) {
  218.                     bestChild = node.left;
  219.                 } else {
  220.                     bestChild = node.right;
  221.                 }
  222.             }

  223.             nearestSearch(bestChild);

  224.             if (bestNodes.size() < maxNodes || ownDistance < bestNodes.peek()[1]) {
  225.                 saveNode(node, ownDistance);
  226.             }

  227.             if (bestNodes.size() < maxNodes || Math.abs(linearDistance) < bestNodes.peek()[1]) {
  228.                 if (bestChild === node.left) {
  229.                     otherChild = node.right;
  230.                 } else {
  231.                     otherChild = node.left;
  232.                 }
  233.                 if (otherChild !== null) {
  234.                     nearestSearch(otherChild);
  235.                 }
  236.             }
  237.         }

  238.         if (maxDistance) {
  239.             for (i = 0; i < maxNodes; i += 1) {
  240.                 bestNodes.push([null, maxDistance]);
  241.             }
  242.         }

  243.         if(self.root)
  244.             nearestSearch(self.root);

  245.         result = [];

  246.         for (i = 0; i < Math.min(maxNodes, bestNodes.content.length); i += 1) {
  247.             if (bestNodes.content[i][0]) {
  248.                 result.push([bestNodes.content[i][0].obj, bestNodes.content[i][1]]);
  249.             }
  250.         }
  251.         return result;
  252.     };

  253.     this.balanceFactor = function () {
  254.         function height(node) {
  255.             if (node === null) {
  256.                 return 0;
  257.             }
  258.             return Math.max(height(node.left), height(node.right)) + 1;
  259.         }

  260.         function count(node) {
  261.             if (node === null) {
  262.                 return 0;
  263.             }
  264.             return count(node.left) + count(node.right) + 1;
  265.         }

  266.         return height(self.root) / (Math.log(count(self.root)) / Math.log(2));
  267.     };
  268. }

  269. // Binary heap implementation from:
  270. // http://eloquentjavascript.net/appendix2.html

  271. function BinaryHeap(scoreFunction){
  272.     this.content = [];
  273.     this.scoreFunction = scoreFunction;
  274. }

  275. BinaryHeap.prototype = {
  276.     push: function(element) {
  277.         // Add the new element to the end of the array.
  278.         this.content.push(element);
  279.         // Allow it to bubble up.
  280.         this.bubbleUp(this.content.length - 1);
  281.     },

  282.     pop: function() {
  283.         // Store the first element so we can return it later.
  284.         var result = this.content[0];
  285.         // Get the element at the end of the array.
  286.         var end = this.content.pop();
  287.         // If there are any elements left, put the end element at the
  288.         // start, and let it sink down.
  289.         if (this.content.length > 0) {
  290.             this.content[0] = end;
  291.             this.sinkDown(0);
  292.         }
  293.         return result;
  294.     },

  295.     peek: function() {
  296.         return this.content[0];
  297.     },

  298.     remove: function(node) {
  299.         var len = this.content.length;
  300.         // To remove a value, we must search through the array to find
  301.         // it.
  302.         for (var i = 0; i < len; i++) {
  303.             if (this.content[i] == node) {
  304.                 // When it is found, the process seen in 'pop' is repeated
  305.                 // to fill up the hole.
  306.                 var end = this.content.pop();
  307.                 if (i != len - 1) {
  308.                     this.content[i] = end;
  309.                     if (this.scoreFunction(end) < this.scoreFunction(node))
  310.                         this.bubbleUp(i);
  311.                     else
  312.                         this.sinkDown(i);
  313.                 }
  314.                 return;
  315.             }
  316.         }
  317.         throw new Error("Node not found.");
  318.     },

  319.     size: function() {
  320.         return this.content.length;
  321.     },

  322.     bubbleUp: function(n) {
  323.         // Fetch the element that has to be moved.
  324.         var element = this.content[n];
  325.         // When at 0, an element can not go up any further.
  326.         while (n > 0) {
  327.             // Compute the parent element's index, and fetch it.
  328.             var parentN = Math.floor((n + 1) / 2) - 1,
  329.                 parent = this.content[parentN];
  330.             // Swap the elements if the parent is greater.
  331.             if (this.scoreFunction(element) < this.scoreFunction(parent)) {
  332.                 this.content[parentN] = element;
  333.                 this.content[n] = parent;
  334.                 // Update 'n' to continue at the new position.
  335.                 n = parentN;
  336.             }
  337.             // Found a parent that is less, no need to move it further.
  338.             else {
  339.                 break;
  340.             }
  341.         }
  342.     },

  343.     sinkDown: function(n) {
  344.         // Look up the target element and its score.
  345.         var length = this.content.length,
  346.             element = this.content[n],
  347.             elemScore = this.scoreFunction(element);

  348.         while(true) {
  349.             // Compute the indices of the child elements.
  350.             var child2N = (n + 1) * 2, child1N = child2N - 1;
  351.             // This is used to store the new position of the element,
  352.             // if any.
  353.             var swap = null;
  354.             // If the first child exists (is inside the array)...
  355.             if (child1N < length) {
  356.                 // Look it up and compute its score.
  357.                 var child1 = this.content[child1N],
  358.                     child1Score = this.scoreFunction(child1);
  359.                 // If the score is less than our element's, we need to swap.
  360.                 if (child1Score < elemScore)
  361.                     swap = child1N;
  362.             }
  363.             // Do the same checks for the other child.
  364.             if (child2N < length) {
  365.                 var child2 = this.content[child2N],
  366.                     child2Score = this.scoreFunction(child2);
  367.                 if (child2Score < (swap == null ? elemScore : child1Score)){
  368.                     swap = child2N;
  369.                 }
  370.             }

  371.             // If the element needs to be moved, swap it, and continue.
  372.             if (swap != null) {
  373.                 this.content[n] = this.content[swap];
  374.                 this.content[swap] = element;
  375.                 n = swap;
  376.             }
  377.             // Otherwise, we are done.
  378.             else {
  379.                 break;
  380.             }
  381.         }
  382.     }
  383. };

  384. this.kdTree = kdTree;

  385. exports.kdTree = kdTree;
  386. exports.BinaryHeap = BinaryHeap;
复制代码

藤椅
ReneeBK 发表于 2016-6-27 00:09:43
  1. 'use strict';

  2. module.exports = KNN;

  3. var KDTree = require('./kdtree').kdTree;
  4. var Distances = require('ml-distance');

  5. /**
  6. * K-Nearest neighboor constructor.
  7. *
  8. * @param reload - loading purposes.
  9. * @param model - loading purposes
  10. * @constructor
  11. */
  12. function KNN(reload, model) {
  13.     if(reload) {
  14.         this.kdtree = model.kdtree;
  15.         this.k = model.k;
  16.         this.classes = model.classes;
  17.     }
  18. }

  19. /**
  20. * Function that trains the KNN with the given trainingSet and trainingLabels.
  21. * The third argument is an object with the following options.
  22. *  * distance: that represent the distance function applied (default: euclidean)
  23. *  * k: the number of neighboors to take in count for classify (default: number of features + 1)
  24. *
  25. * @param trainingSet
  26. * @param trainingLabels
  27. * @param options
  28. */
  29. KNN.prototype.train = function (trainingSet, trainingLabels, options) {
  30.     if(options === undefined) options = {};
  31.     if(options.distance === undefined) options.distance = Distances.distance.euclidean;
  32.     if(options.k === undefined) options.k = trainingSet[0].length + 1;

  33.     var classes = 0;
  34.     var exist = new Array(1000);
  35.     var j = 0;
  36.     for(var i = 0; i < trainingLabels.length; ++i) {
  37.         if(exist.indexOf(trainingLabels[i]) === -1) {
  38.             classes++;
  39.             exist[j] = trainingLabels[i];
  40.             j++;
  41.         }
  42.     }

  43.     // copy dataset
  44.     var points = new Array(trainingSet.length);
  45.     for(i = 0; i < points.length; ++i) {
  46.         points[i] = trainingSet[i].slice();
  47.     }

  48.     this.features = trainingSet[0].length;
  49.     for(i = 0; i < trainingLabels.length; ++i) {
  50.         points[i].push(trainingLabels[i]);
  51.     }

  52.     var dimensions = new Array(trainingSet[0].length);
  53.     for(i = 0; i < dimensions.length; ++i) {
  54.         dimensions[i] = i;
  55.     }

  56.     this.kdtree = new KDTree(points, options.distance, dimensions);
  57.     this.k = options.k;
  58.     this.classes = classes;
  59. };

  60. /**
  61. * Function that returns the predictions given the dataset.
  62. *
  63. * @param dataset
  64. * @returns {Array}
  65. */
  66. KNN.prototype.predict = function (dataset) {
  67.     var predictions = new Array(dataset.length);
  68.     for(var i = 0; i < dataset.length; ++i) {
  69.         predictions[i] = this.getSinglePrediction(dataset[i]);
  70.     }

  71.     return predictions;
  72. };

  73. /**
  74. * function that returns a prediction for a single case.
  75. * @param currentCase
  76. * @returns {number}
  77. */
  78. KNN.prototype.getSinglePrediction = function (currentCase) {
  79.     var nearestPoints = this.kdtree.nearest(currentCase, this.k);
  80.     var pointsPerClass = new Array(this.classes);
  81.     var predictedClass = -1;
  82.     var maxPoints = -1;
  83.     var lastElement = nearestPoints[0][0].length - 1;

  84.     for(var i = 0; i < pointsPerClass.length; ++i) {
  85.         pointsPerClass[i] = 0;
  86.     }

  87.     for(i = 0; i < nearestPoints.length; ++i) {
  88.         var currentClass = nearestPoints[i][0][lastElement];
  89.         var currentPoints = ++pointsPerClass[currentClass];
  90.         if(currentPoints > maxPoints) {
  91.             predictedClass = currentClass;
  92.             maxPoints = currentPoints;
  93.         }
  94.     }

  95.     return predictedClass;
  96. };

  97. /**
  98. * function that returns a KNN classifier with the given model.
  99. *
  100. * @param model
  101. */
  102. KNN.load = function (model) {
  103.     if(model.modelName !== "KNN")
  104.         throw new RangeError("The given model is invalid!");

  105.     return new KNN(true, model);
  106. };

  107. /**
  108. * function that exports the current KNN classifier.
  109. */
  110. KNN.prototype.export = function () {
  111.     return {
  112.         modelName: "KNN",
  113.         kdtree: this.kdtree,
  114.         k: this.k,
  115.         classes: this.classes
  116.     };
  117. };
复制代码

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
jg-xs1
拉您进交流群
GMT+8, 2025-12-21 16:39