译者按: 机械进修本来很简朴啊,无妨着手尝尝!
原文: Machine Learning with JavaScript : Part 2
译者: Fundebug
为了保证可读性,本文采纳意译而非直译。别的,本文版权归原作者一切,翻译仅用于进修。别的,我们修改了原文代码中的毛病
上图运用plot.ly所画。
上次我们用JavaScript完成了线性规划,此次我们来聊聊KNN算法。
KNN是k-Nearest-Neighbours的缩写,它是一种监视进修算法。KNN算法能够用来做分类,也能够用来处置惩罚回归题目。
GitHub堆栈: machine-learning-with-js
KNN算法简介
简朴地说,KNN算法由那离本身近来的K个点来投票决议待分类数据归为哪一类。
假如待分类的数据有这些相近数据,NY: 7, NJ: 0, IN: 4,即它有7个NY邻人,0个NJ邻人,4个IN邻人,则这个数据应当归类为NY。
假定你在邮局事情,你的使命是为邮递员分派函件,目的是最小化到各个社区的投递路程。无妨假定一共有7个街区。这就是一个现实的分类题目。你须要将这些函件分类,决议它属于哪一个社区,比方上东城、曼哈顿下城等。
最坏的计划是随便分派函件分派给邮递员,如许每一个邮递员会拿到各个社区的函件。
最好的计划是依据函件地点举行分类,如许每一个邮递员只须要担任相近社区的函件。
或许你是如许想的:”将相近3个街区的函件分派给同一个邮递员”。这时候,相近街区的个数就是k。你能够不停增添k,直到取得最好的分派计划。这个k就是分类题目的最好值。
KNN代码完成
像上次一样,我们将运用mljs的KNN模块ml-knn来完成。
每一个机械进修算法都须要数据,此次我将运用IRIS数据集。其数据集包含了150个样本,都属于鸢尾属下的三个亚属,分别是山鸢尾、变色鸢尾和维吉尼亚鸢尾。四个特性被用作样本的定量分析,它们分别是花萼和花瓣的长度和宽度。
1. 装置模块
$ npm install ml-knn@2.0.0 csvtojson prompt
ml-knn: k-Nearest-Neighbours模块,差别版本的接口能够差别,这篇博客运用了2.0.0
csvtojson: 用于将CSV数据转换为JSON
prompt: 在控制台输入输出数据
2. 初始化并导入数据
IRIS数据集由加州大学欧文分校供应。
curl https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data > iris.csv
假定你已初始化了一个NPM项目,请在index.js中输入以下内容:
const KNN = require('ml-knn');
const csv = require('csvtojson');
const prompt = require('prompt');
var knn;
const csvFilePath = 'iris.csv'; // 数据集
const names = ['sepalLength', 'sepalWidth', 'petalLength', 'petalWidth', 'type'];
let seperationSize; // 支解练习和测试数据
let data = [],
X = [],
y = [];
let trainingSetX = [],
trainingSetY = [],
testSetX = [],
testSetY = [];
seperationSize用于支解数据和测试数据
运用csvtojson模块的fromFile要领加载数据:
csv(
{
noheader: true,
headers: names
})
.fromFile(csvFilePath)
.on('json', (jsonObj) =>
{
data.push(jsonObj); // 将数据集转换为JS对象数组
})
.on('done', (error) =>
{
seperationSize = 0.7 * data.length;
data = shuffleArray(data);
dressData();
});
我们将seperationSize设为样本数量的0.7倍。注重,假如练习数据集太小的话,分类效果将变差。
因为数据集是依据品种排序的,所以须要运用shuffleArray函数对数据举行殽杂,如许才轻易支解出练习数据。这个函数的定义请参考StackOverflow的发问How to randomize (shuffle) a JavaScript array?:
function shuffleArray(array)
{
for (var i = array.length - 1; i > 0; i--)
{
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}
3. 转换数据
数据集合每一条数据能够转换为一个JS对象:
{
sepalLength: ‘5.1’,
sepalWidth: ‘3.5’,
petalLength: ‘1.4’,
petalWidth: ‘0.2’,
type: ‘Iris-setosa’
}
在运用KNN算法练习数据之前,须要对数据举行这些处置惩罚:
将属性(sepalLength, sepalWidth,petalLength,petalWidth)由字符串转换为浮点数. (parseFloat)
将分类 (type)用数字示意
function dressData()
{
let types = new Set();
data.forEach((row) =>
{
types.add(row.type);
});
let typesArray = [...types];
data.forEach((row) =>
{
let rowArray, typeNumber;
rowArray = Object.keys(row).map(key => parseFloat(row[key])).slice(0, 4);
typeNumber = typesArray.indexOf(row.type); // Convert type(String) to type(Number)
X.push(rowArray);
y.push(typeNumber);
});
trainingSetX = X.slice(0, seperationSize);
trainingSetY = y.slice(0, seperationSize);
testSetX = X.slice(seperationSize);
testSetY = y.slice(seperationSize);
train();
}
4. 练习数据并测试
function train()
{
knn = new KNN(trainingSetX, trainingSetY,
{
k: 7
});
test();
}
train要领须要2个必需的参数: 输入数据,即花萼和花瓣的长度和宽度;现实分类,即山鸢尾、变色鸢尾和维吉尼亚鸢尾。别的,第三个参数是可选的,用于供应调解KNN算法的内部参数。我将k参数设为7,其默认值为5。
练习好模子以后,就能够运用测试数据来搜检准确性了。我们主要对展望失足的个数比较感兴趣。
function test()
{
const result = knn.predict(testSetX);
const testSetLength = testSetX.length;
const predictionError = error(result, testSetY);
console.log(`Test Set Size = ${testSetLength} and number of Misclassifications = ${predictionError}`);
predict();
}
比较展望值与实在值,就能够获得失足个数:
function error(predicted, expected)
{
let misclassifications = 0;
for (var index = 0; index < predicted.length; index++)
{
if (predicted[index] !== expected[index])
{
misclassifications++;
}
}
return misclassifications;
}
5. 举行展望(可选)
恣意输入属性值,就能够获得展望值
function predict()
{
let temp = [];
prompt.start();
prompt.get(['Sepal Length', 'Sepal Width', 'Petal Length', 'Petal Width'], function(err, result)
{
if (!err)
{
for (var key in result)
{
temp.push(parseFloat(result[key]));
}
console.log(`With ${temp} -- type = ${knn.predict(temp)}`);
}
});
}
6. 完全递次
完全的递次index.js是如许的:
const KNN = require('ml-knn');
const csv = require('csvtojson');
const prompt = require('prompt');
var knn;
const csvFilePath = 'iris.csv'; // 数据集
const names = ['sepalLength', 'sepalWidth', 'petalLength', 'petalWidth', 'type'];
let seperationSize; // 支解练习和测试数据
let data = [],
X = [],
y = [];
let trainingSetX = [],
trainingSetY = [],
testSetX = [],
testSetY = [];
csv(
{
noheader: true,
headers: names
})
.fromFile(csvFilePath)
.on('json', (jsonObj) =>
{
data.push(jsonObj); // 将数据集转换为JS对象数组
})
.on('done', (error) =>
{
seperationSize = 0.7 * data.length;
data = shuffleArray(data);
dressData();
});
function dressData()
{
let types = new Set();
data.forEach((row) =>
{
types.add(row.type);
});
let typesArray = [...types];
data.forEach((row) =>
{
let rowArray, typeNumber;
rowArray = Object.keys(row).map(key => parseFloat(row[key])).slice(0, 4);
typeNumber = typesArray.indexOf(row.type); // Convert type(String) to type(Number)
X.push(rowArray);
y.push(typeNumber);
});
trainingSetX = X.slice(0, seperationSize);
trainingSetY = y.slice(0, seperationSize);
testSetX = X.slice(seperationSize);
testSetY = y.slice(seperationSize);
train();
}
// 运用KNN算法练习数据
function train()
{
knn = new KNN(trainingSetX, trainingSetY,
{
k: 7
});
test();
}
// 测试练习的模子
function test()
{
const result = knn.predict(testSetX);
const testSetLength = testSetX.length;
const predictionError = error(result, testSetY);
console.log(`Test Set Size = ${testSetLength} and number of Misclassifications = ${predictionError}`);
predict();
}
// 盘算失足个数
function error(predicted, expected)
{
let misclassifications = 0;
for (var index = 0; index < predicted.length; index++)
{
if (predicted[index] !== expected[index])
{
misclassifications++;
}
}
return misclassifications;
}
// 依据输入展望效果
function predict()
{
let temp = [];
prompt.start();
prompt.get(['Sepal Length', 'Sepal Width', 'Petal Length', 'Petal Width'], function(err, result)
{
if (!err)
{
for (var key in result)
{
temp.push(parseFloat(result[key]));
}
console.log(`With ${temp} -- type = ${knn.predict(temp)}`);
}
});
}
// 殽杂数据集的递次
function shuffleArray(array)
{
for (var i = array.length - 1; i > 0; i--)
{
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}
在控制台实行node index.js
$ node index.js
输出以下:
Test Set Size = 45 and number of Misclassifications = 2
prompt: Sepal Length: 1.7
prompt: Sepal Width: 2.5
prompt: Petal Length: 0.5
prompt: Petal Width: 3.4
With 1.7,2.5,0.5,3.4 -- type = 2
参考链接
迎接到场我们Fundebug的全栈BUG监控交换群: 622902485。
版权声明:
转载时请说明作者Fundebug以及本文地点:
https://blog.fundebug.com/2017/07/10/javascript-machine-learning-knn/