JavaScript >> Javascript 文檔 >  >> JavaScript

帶有 Brain.js 的 JavaScript 中的神經網絡

簡介

尤其是在過去的幾年裡,神經網絡 (NNs) 已經真正成為一種實用且有效的方法來解決算法無法輕易解決的問題,例如人臉檢測、語音識別和醫學診斷。這在很大程度上要歸功於最近關於如何更好地訓練和調整網絡的發現,以及計算機速度的提高。

就在最近,倫敦帝國理工學院的一名學生創建了一個名為 Giraffe 的神經網絡,只需 72 小時即可完成與 FIDE 國際大師級水平的國際象棋訓練。在這個級別下棋的計算機並不是真正的新事物,但是這個程序的創建方式 新的。這些程序通常需要數年時間才能構建並在真正的大師的幫助下進行調整,而另一方面,Giraffe 是簡單地使用深度神經網絡、一些創造力和大量國際象棋遊戲數據集構建的。這是最近展示的 Promise 神經網絡的又一個例子,而且它們只會不斷改進。

大腦.js

神經網絡和一般人工智能的缺點是該領域非常依賴數學,這往往會在人們開始之前就將其嚇跑。 NN 的高度技術性以及隨之而來的所有行話使得外行很難利用。這就是 Brain.js 發揮作用的地方。 Brain.js 通過利用 JavaScript 的易用性並將 API 限制為僅幾個方法調用和選項,在簡化創建和訓練 NN 的過程方面做得很好。

不要誤會我的意思,您仍然需要了解 NN 背後的一些概念,但這種簡化使其不那麼令人生畏。

例如,要訓練一個網絡來逼近 XOR 函數(這是標準的 NN 示例之一),您只需要:

var brain = require('brain');

var net = new brain.NeuralNetwork();

net.train([{input: [0, 0], output: [0]},
           {input: [0, 1], output: [1]},
           {input: [1, 0], output: [1]},
           {input: [1, 1], output: [0]}]);

var output = net.run([1, 0]);  // [0.933]

這段代碼只是創建了一個新的網絡(net ), train s 網絡使用示例數組,然後是 run s 輸入為 [1, 0] 的網絡 ,正確地導致 [0.933] (又名 1 )。

雖然 Brain.js 沒有大量選項可讓您自定義網絡,但 API 接受了足夠的參數以使其對簡單的應用程序有用。您可以設置隱藏層的數量和大小、錯誤閾值、學習率等:

var net = new brain.NeuralNetwork({
	hiddenLayers: [128,64]
});

net.train({
	errorThresh: 0.005,  // error threshold to reach before completion
	iterations: 20000,   // maximum training iterations 
	log: true,           // console.log() progress periodically 
	logPeriod: 10,       // number of iterations between logging 
	learningRate: 0.3    // learning rate 
});

有關選項的完整列表,請參閱文檔。

雖然您可以構建的網絡類型有限,但這並不意味著您無法做出任何有意義的事情。以這個項目為例。作者為他的數據集收集了一堆驗證碼圖像,使用一些簡單的圖像處理對圖像進行預處理,然後使用 Brain.js 創建一個識別每個單獨字符的神經網絡。

優勢

正如我已經提到的,Brain.js 非常適合使用高級語言快速創建簡單的 NN,您可以在其中利用大量開源庫。有了一個好的數據集和幾行代碼,你就可以創建一些非常有趣的功能。

像這樣用 JavaScript 編寫的高度科學/計算庫往往會受到嚴厲批評,但我個人認為 Brain.js 在 JS 中佔有一席之地,只要你有正確的期望和應用程序。例如,JS 是在瀏覽器中運行客戶端的主要(唯一?)語言,那麼為什麼不利用這個庫來處理諸如瀏覽器內游戲、廣告展示(我知道很無聊)或字符識別之類的事情呢?

缺點

雖然我們絕對可以從這樣的庫中獲得一些價值,但它並不完美。正如我所提到的,該庫將您的網絡架構限制在您只能執行簡單應用程序的程度。 softmax 層或其他結構的可能性不大。至少可以選擇對架構進行更多自定義,而不是對您隱藏所有內容。

可能我最大的抱怨是該庫是用 pure 編寫的 JavaScript。訓練 NN 是一個緩慢的過程,可能需要數千次迭代(意味著數百萬或數十億次操作)才能在數百萬個數據點上進行訓練。 JavaScript 無論如何都不是一種快速的語言,並且確實應該有這樣的插件來加速訓練時的計算。上面的驗證碼破解器的訓練時間驚人地低,只有 20 分鐘,但只需要更多的輸入和更多的數據就可以將訓練時間增加幾個小時甚至幾天,正如您將在下面的示例中看到的那樣。

不幸的是,這個庫已經被它的作者放棄了(Github 描述前面帶有“[UNMAINTAINED]”)。雖然我知道很難跟上流行的開源庫的需求,但看到它仍然令人失望,我們只能希望有人合格 可以填補空白。我確信已經有一個好的分叉正在開發中,但可能需要一些搜索才能找到它。

示例

在這裡,我將向您展示如何使用 Brain 的一個稍微複雜的示例。在此示例中,我創建了一個可以識別單個手寫數字 (0-9) 的 NN。我使用的數據集是流行的 MNIST 數據集,其中包含超過 50,000 個手寫數字樣本。這類問題被稱為光學字符識別(OCR),是神經網絡的熱門應用。

識別的工作原理是獲取手寫數字的 28x28 灰度圖像,並輸出網絡認為它“看到”的數字。這意味著我們將有 784 個輸入(每個像素一個),值在 0-255 之間,並且將有 10 個輸出(每個數字一個)。每個輸出將具有 0-1 的值,基本上充當該特定數字是正確答案的置信水平。那麼最高的置信度值就是我們的答案。

上代碼:

var brain = require('brain');
var fs = require('fs');

var getMnistData = function(content) {
	var lines = content.toString().split('\n');

	var data = [];
	for (var i = 0; i < lines.length; i++) {
		var input = lines[i].split(',').map(Number);

		var output = Array.apply(null, Array(10)).map(Number.prototype.valueOf, 0);
		output[input.shift()] = 1;

		data.push({
			input: input,
			output: output
		});
	}

	return data;
};

fs.readFile(__dirname + '/train.csv', function (err, trainContent) {
	if (err) {
		console.log('Error:', err);
	}

	var trainData = getMnistData(trainContent);

	console.log('Got ' + trainData.length + ' samples');

	var net = new brain.NeuralNetwork({hiddenLayers: [784, 392, 196]});

	net.train(trainData, {
		errorThresh: 0.025,
		log: true,
		logPeriod: 1,
		learningRate: 0.1
	});
});

train.csv 文件只是一個 CSV,每行一個圖像。第一個值是圖像中顯示的數字,接下來的 784 個值是像素數據。

免費電子書:Git Essentials

查看我們的 Git 學習實踐指南,其中包含最佳實踐、行業認可的標準以及隨附的備忘單。停止谷歌搜索 Git 命令並真正學習 它!

我選擇的層數和節點數有點隨意,對於這個 OCR 應用程序來說可能是不必要的高。但是,當您無法利用 softmax 或池化之類的東西時,增加層數和節點數可能會更好。

培訓輕鬆地花費了一個多小時來獲得一些不錯的結果。雖然這是意料之中的,但我仍然有點失望,因為必須等待這麼長時間才能測試新的網絡結構或新的學習參數。像這樣一個簡單的應用程序不應該花費這麼長時間,但這就是您為全 JavaScript 實現所付出的代價。

為了測試網絡,我加載了另一個文件 test.csv ,並將其用作比較網絡的基準。這樣我們就可以更好地了解性能,因為我們正在測試網絡尚未訓練過的輸入。

以下是我測試網絡的方法(我只展示了相關部分):

// Require packages...

fs.readFile(__dirname + '/test.csv', function (err, testContent) {
	if (err) {
		console.log('Error:', err);
	}

	// Load training data...

	// Train network...

	// Test it out
	var testData = getMnistData(testContent);

	var numRight = 0;

	console.log('Neural Network tests:');
	for (i = 0; i < testData.length; i++) {
		var resultArr = net.run(testData[i].input);
		var result = resultArr.indexOf(Math.max.apply(Math, resultArr));
		var actual = testData[i].output.indexOf(Math.max.apply(Math, testData[i].output));

		var str = '(' + i + ') GOT: ' + result + ', ACTUAL: ' + actual;
		str += result === actual ? '' : ' -- WRONG!';

		numRight += result === actual ? 1 : 0;

		console.log(str);
	}

	console.log('Got', numRight, 'out of 350, or ' + String(100*(numRight/350)) + '%');
});

結論

雖然有一些缺點,但總的來說,我認為 Brain.js 非常有用,可以為 JavaScript/Node 應用程序增加很多價值。它的易用性應該讓幾乎任何人都可以開始使用神經網絡。

如果您想要更靈活的東西,或者您對缺乏對 Brain.js 的支持感到困擾,請查看 Synaptic,它允許對您的網絡架構進行更多自定義。它不像 Brain 那樣受歡迎/受關注,但它似乎是 JavaScript 中神經網絡的下一個最佳選擇。

您對 Brain.js 的體驗如何?您還有其他推薦的 AI 軟件包嗎?請在評論中告訴我們!


Tutorial JavaScript 教程
  1. 用動物群寫作 - 呼叫 JAMstack 愛好者!

  2. jQuery函數從數組中獲取所有唯一元素?

  3. 使用 GraphQL SDL 為 GraphQL API 創建靜態文檔

  4. 像專業人士一樣使用 Flex

  5. Angular 9 入門

  6. 從一個函數組件到另一個 const 組件的單擊按鈕上設置值 React

  7. Twitter 自動轉推和點贊機器人(使用 JavaScript)

  1. 🚀 使用 puppeteer 在 Node.js 中使用 JavaScript 測量網頁的性能

  2. 我希望早點知道的 4 個靜態對象方法

  3. V8 發布 v6.1

  4. 您可以通過管道進入 Node.js

  5. 使用內置 DOM 方法或 Prototype 從 HTML 字符串創建新的 DOM 元素

  6. 如何將 Typescript 與 ASP.NET Core 2.x React 項目模板一起使用

  7. JavaScript 類擴展 |代碼

  1. #100DaysOfCode 第 1 天:使用 CSS 網格和媒體查詢設計購物車模板佈局

  2. 從頭開始創建 Netflix 克隆:JavaScript PHP + MySQL 第 66 天

  3. 為 React Native 初學者提供簡單易懂的 State &Props 解釋

  4. 在 Web 開發中平衡信息密度