如何使用JavaScript構(gòu)建機(jī)器學(xué)習(xí)模型
目前,機(jī)器學(xué)習(xí)領(lǐng)域建模的主要語言是 Python 和 R,前不久騰訊推出的機(jī)器學(xué)習(xí)框架 Angel 則支持 Java 和 Scala。本文作者 Abhishek Soni 則用行動(dòng)告訴我們,開發(fā)機(jī)器學(xué)習(xí)模型,JavaScript 也可以。
JavaScript?我不是應(yīng)該使用 Python 嗎?甚至 Scikit-learn 在 JavaScript 上都不工作。
這是可能的,實(shí)際上,連我自己都驚訝于開發(fā)者對(duì)此忽視的態(tài)度。就 Scikit-learn 而言,Javascript 的開發(fā)者事實(shí)上已經(jīng)推出了適用的庫(kù),它會(huì)在本文中有所提及。那么,讓我們看看 Javascript 在機(jī)器學(xué)習(xí)上能夠做什么吧。
根據(jù)人工智能先驅(qū) Arthur Samuel 的說法,機(jī)器學(xué)習(xí)為計(jì)算機(jī)提供了無需明確編程的學(xué)習(xí)能力。換句話說,它使得計(jì)算機(jī)能夠自我學(xué)習(xí)并執(zhí)行正確的指令,無需人類提供全部指導(dǎo)。
谷歌已經(jīng)把自己移動(dòng)優(yōu)先的策略轉(zhuǎn)換到人工智能優(yōu)先很久了。
為什么 JavaScript 在機(jī)器學(xué)習(xí)界未被提及過?
- 慢(真的假的?)
- 矩陣操作很困難(這里有庫(kù),比如 math.js)
- 僅用于 Web 開發(fā)(然而這里還有 Node.js)
- 機(jī)器學(xué)習(xí)庫(kù)通常是在 Python 上的(還好,JS 的開發(fā)者人數(shù)也不少)
在 JavaScript 中有一些可供使用的預(yù)制庫(kù),其中包含一些機(jī)器學(xué)習(xí)算法,如線性回歸、SVM、樸素貝葉斯等等,以下是其中的一部分。
- brain.js(神經(jīng)網(wǎng)絡(luò))
- Synaptic(神經(jīng)網(wǎng)絡(luò))
- Natural(自然語言處理)
- ConvNetJS(卷積神經(jīng)網(wǎng)絡(luò))
- mljs(一組具有多種功能的子庫(kù))
首先,我們將使用 mljs 回歸庫(kù)來進(jìn)行一些線性回歸操作。
參考代碼:https://github.com/abhisheksoni27/machine-learning-with-js
1. 安裝庫(kù)
$ npm install ml-regression csvtojson
$ yarn add ml-regression csvtojson
ml-regression 正如其名,負(fù)責(zé)機(jī)器學(xué)習(xí)的線性回歸。
csvtojson 是一個(gè)用于 node.js 的快速 CSV 解析器,它允許加載 CSV 數(shù)據(jù)文件并將其轉(zhuǎn)換為 JSON。
2. 初始化并加載數(shù)據(jù)
下載數(shù)據(jù)文件(.csv),并將其加入你的項(xiàng)目。
鏈接:http://www-bcf.usc.edu/~gareth/ISL/Advertising.csv
如果你已經(jīng)初始化了一個(gè)空的 npm 項(xiàng)目,打開 index.js,輸入以下代碼。
const ml = require('ml-regression'); const csv = require('csvtojson'); const SLR = ml.SLR; // Simple Linear Regression const csvFilePath = 'advertising.csv'; // Data let csvData = [], // parsed Data X = [], // Input y = []; // Output let regressionModel;
我把文件放在了項(xiàng)目的根目錄下,如果你想放在其他地方,請(qǐng)記得更新 csvFilePath。
現(xiàn)在我們使用 csvtojson 的 fromFile 方法加載數(shù)據(jù)文件:
csv() .fromFile(csvFilePath) .on('json', (jsonObj) => { csvData.push(jsonObj); }) .on('done', () => { dressData(); // To get data points from JSON Objects performRegression(); });
3. 打包數(shù)據(jù),準(zhǔn)備執(zhí)行
JSON 對(duì)象被存儲(chǔ)在 csvData 中,我們還需要輸入數(shù)據(jù)點(diǎn)數(shù)組和輸出數(shù)據(jù)點(diǎn)。我們通過一個(gè)填充 X 和 Y 變量的 dressData 函數(shù)來運(yùn)行數(shù)據(jù)。
function dressData() { /** * One row of the data object looks like: * { * TV: "10", * Radio: "100", * Newspaper: "20", * "Sales": "1000" * } * * Hence, while adding the data points, * we need to parse the String value as a Float. */ csvData.forEach((row) => { X.push(f(row.Radio)); y.push(f(row.Sales)); }); } function f(s) { return parseFloat(s); }
4. 訓(xùn)練模型開始預(yù)測(cè)
數(shù)據(jù)已經(jīng)打包完畢,是時(shí)候訓(xùn)練我們的模型了。
為此,我們需要寫一個(gè) performRegression 函數(shù):
function performRegression() { regressionModel = new SLR(X, y); // Train the model on training data console.log(regressionModel.toString(3)); predictOutput(); }
performRegression 函數(shù)有一個(gè)方法 toString,它為浮點(diǎn)輸出獲取一個(gè)名為 precision 的參數(shù)。predictOutput 函數(shù)能讓你輸入數(shù)值,然后將模型的輸出傳到控制臺(tái)。它是這樣的(注意,我使用的是 Node.js 的 readline 工具):
function predictOutput() { rl.question('Enter input X for prediction (Press CTRL+C to exit) : ', (answer) => { console.log(`At X = ${answer}, y = ${regressionModel.predict(parseFloat(answer))}`); predictOutput(); }); }
以下是為了增加閱讀用戶的代碼
const readline = require('readline'); // For user prompt to allow predictions const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
5. 大功告成!
遵循以上步驟,你的 index.js 應(yīng)該是這樣:
const ml = require('ml-regression'); const csv = require('csvtojson'); const SLR = ml.SLR; // Simple Linear Regression const csvFilePath = 'advertising.csv'; // Data let csvData = [], // parsed Data X = [], // Input y = []; // Output let regressionModel; const readline = require('readline'); // For user prompt to allow predictions const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); csv() .fromFile(csvFilePath) .on('json', (jsonObj) => { csvData.push(jsonObj); }) .on('done', () => { dressData(); // To get data points from JSON Objects performRegression(); }); function performRegression() { regressionModel = new SLR(X, y); // Train the model on training data console.log(regressionModel.toString(3)); predictOutput(); } function dressData() { /** * One row of the data object looks like: * { * TV: "10", * Radio: "100", * Newspaper: "20", * "Sales": "1000" * } * * Hence, while adding the data points, * we need to parse the String value as a Float. */ csvData.forEach((row) => { X.push(f(row.Radio)); y.push(f(row.Sales)); }); } function f(s) { return parseFloat(s); } function predictOutput() { rl.question('Enter input X for prediction (Press CTRL+C to exit) : ', (answer) => { console.log(`At X = ${answer}, y = ${regressionModel.predict(parseFloat(answer))}`); predictOutput(); }); }
到你的終端上運(yùn)行 node index.js,得到的輸出會(huì)是這樣:
$ node index.js f(x) = 0.202 * x + 9.31 Enter input X for prediction (Press CTRL+C to exit) : 151.***t X = 151.5, y = 39.98974927911285 Enter input X for prediction (Press CTRL+C to exit) :
恭喜!你剛剛在 JavaScript 中訓(xùn)練了***個(gè)線性回歸模型。(PS. 你注意到速度了嗎?)