摘要:是的縮寫,它是一種監督學習算法。每一個機器學習算法都需要數據,這次我將使用數據集。其數據集包含了個樣本,都屬于鳶尾屬下的三個亞屬,分別是山鳶尾變色鳶尾和維吉尼亞鳶尾。四個特征被用作樣本的定量分析,它們分別是花萼和花瓣的長度和寬度。
譯者按: 機器學習原來很簡單啊,不妨動手試試!
原文: 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參考鏈接
K NEAREST NEIGHBOR 算法
安德森鳶尾花卉數據集
歡迎加入我們Fundebug的全棧BUG監控交流群: 622902485。
版權聲明:
轉載時請注明作者Fundebug以及本文地址:
https://blog.fundebug.com/2017/07/10/javascript-machine-learning-knn/
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/84018.html
摘要:近鄰算法通過測量不同特征值之間的距離方法進行分類。對于近鄰算法來說,它是一個特殊的沒有模型的算法,但是我們將其訓練數據集看作是模型。算法優缺點近鄰算法是一個比較簡單的算法,有其優點但也有缺點。 k-近鄰算法通過測量不同特征值之間的距離方法進行分類。 k-近鄰算法原理 對于一個存在標簽的訓練樣本集,輸入沒有標簽的新數據后,將新數據的每個特征與樣本集中數據對應的特征進行比較,根據算法選擇樣...
摘要:還提供了,將多項式特征數據歸一化和線性回歸組合在了一起,大大方便的編程的過程。在機器學習算法中,主要的挑戰來自方差,解決的方法主要有降低模型復雜度降維增加樣本數使用驗證集模型正則化。 多項式回歸 多項式回歸使用線性回歸的基本思路 非線性曲線如圖: showImg(https://segmentfault.com/img/bVbkn4q?w=372&h=252); 假設曲線表達式為:$y...
閱讀 1575·2021-11-23 10:01
閱讀 2969·2021-11-19 09:40
閱讀 3214·2021-10-18 13:24
閱讀 3464·2019-08-29 14:20
閱讀 2980·2019-08-26 13:39
閱讀 1276·2019-08-26 11:56
閱讀 2662·2019-08-23 18:03
閱讀 373·2019-08-23 15:35