使用JavaScript實現機器學習和神經學網絡

歡迎你們前往雲+社區,獲取更多騰訊海量技術實踐乾貨哦~javascript

基本介紹

在本文中,你會對如何使用JavaScript實現機器學習這個話題有一些基本的瞭解。我會使用Encon(一個先進的神經網絡和機器學習框架)這個框架,並向大家展現如何用這個框架來實現光學字符辨識模擬退火法遺傳算法和神經網絡。Encog同時包括了幾個GUI窗體小部件,這些小部件能夠更方便地顯示出通常機器學習任務的輸出。java

運行環境

Encog是一個面向Java,C#,JavaScript和C/C++的高級機器學習平臺。除此以外,Encog還能夠爲www.heatonresearch.com/wiki/Meta_T…的實際案例生成對應代碼,本文將重點介紹如何使用支持JavaScript的Encog框架,該框架容許你建立利用人工智能實現的交互式web應用程序。訪問如下網址獲取有關Encog的更多信息。git

www.heatonresearch.com/encog程序員

代碼調用

本文介紹的全部示例代碼均可以在附帶的下載中找到。github

這段代碼同時被託管在下面的GitHub庫中。web

github.com/encog/encog…算法

你能夠看到本文討論的全部示例都運行在下面的URL中:編程

www.heatonresearch.com/fun數組

Encog框架包含在兩個JavaScript文件中。第一個JavaScript文件包含了全部核心的機器學習函數。這個JavaScript文件被命名爲encog-js-x.js。第二個文件包含了全部的GUI窗體小組件,並被命名爲encog-widget.js。你能夠在下面的引用路徑中閱讀這兩個文件。bash

<script src=" encog-js-1.0.js"></script>
<script src="encog-widget-1.0.js"></script>複製代碼

歐氏距離

咱們從歐氏距離開始談起,歐氏距離是一個很是簡單的概念,適用於不一樣的機器學習技術。歐氏距離提供的結果是一個數字,該數字決定了相同長度的兩個數組之間的類似性。思考下面三個數組:

Array 1: [ 1, 2, 3]
Array 2: [ 1, 3, 2]
Array 3: [ 3, 2, 1]複製代碼

咱們能夠計算出上面任意兩個數組之間的歐氏距離,這對於肯定數組之間的類似度是很是有用的。思考一下,假如咱們想要肯定一下數組2或者數組3哪一個距離數組1更近。爲了作到這一點,咱們須要計算數組1和數組2之間的歐氏距離。而後再計算數組1和數組3之間的歐氏距離。兩相比較,最短的就是最類似的。

從數學角度來說,歐氏距離由如下方程式進行計算。

圖 1: 歐氏距離

使用這個公式,咱們如今能夠計算上文中的歐氏距離

複製代碼
d(a1,a2) = sqrt( (a2[0]-a1[0])^2 + (a2[1]-a1[1])^2 +  (a2[1]-a1[1])^2  )
d(a1,a2) = sqrt( (1-1)^2 + (3-2)^2 + (2-3)^2 )
d(a1,a2) = sqrt( 0+1+1 )
d(a1,a2) = sqrt(2) = 1.4
d(a1,a3) = sqrt( (a3[0]-a1[0])^2 + (a3[1]-a1[1])^2 +  (a3[1]-a1[1])^2  )
d(a1,a3) = sqrt( (3-1)^2 + (2-2)^2 + (1-3)^2 )
d(a1,a3) = sqrt( 4+0+4 )
d(a1,a3) = sqrt(8) = 2.3複製代碼
複製代碼

從結果中咱們能夠看出數組2比數組1更爲接近數組3。

下面的JavaScript代碼實現了歐氏距離的計算。

複製代碼
ENCOG.MathUtil.euclideanDistance = function (a1, a2, startIndex, len) {
    'use strict';
    var result = 0, i, diff;
    for (i = startIndex; i < (startIndex + len); i += 1) {
        diff = a1[i] - a2[i];
        result += diff * diff;
    }
    return Math.sqrt(result);
};複製代碼
複製代碼

歐氏距離能夠被用來建立一個簡單的光學字符辨識實例。你能夠在下圖中看到應用程序運行實例:

圖 2: JavaScript光學字符辨識

你能夠在下面這個URL中查看程序的運行實例:

www.heatonresearch.com/fun/ocr

HTML5(啓用觸控設備)的JavaScript應用程序能夠經過簡單的歐氏距離來實現基本的光學字符辨識。爲了使用這個示例,須要在下面這個大的矩形中繪製一個數字,而後點擊「Recognize」(識別)按鈕,程序會嘗試猜想你畫的這個數字。雖然準確性並非特別高,但它作的確實已經很不錯了。

該程序已經經過了數據訓練,你能夠移除這些數字條目中的任何一個,或者建立你本身的條目。若是須要訓練一個新字符的OCR,只要簡單繪出那個字符,而後點擊「Teach」(教學)按鈕。則該字符就會被增長到已知的字符列表中。

你會發現,你所繪製的任何東西都是先剪裁而後向下採樣的。程序會對你所繪製的高分辨率字符向下採樣並將採樣點分配到5×8網格中。而後將這個經過向下採樣獲得的網格與每一個數字的向下採樣網格進行比較。若是要查看程序中經訓練後獲得的網格,須要在字符列表中單擊你但願看到的字符。而後程序會將這個網格轉換成一個一維數組,而一個5×8的網格會有40個數組元素。

如下JavaScript代碼執行了這個搜索,而且實現了一個歐氏距離的計算

複製代碼
var c, data, sum, i, delta;
for(c in charData )
{
 data = charData[c];
// 如今咱們將會識別出這個畫出來的字母.
// 爲此,咱們須要利用歐氏距離來計算
// http://www.heatonresearch.com/wiki/Euclidean_Distance (這是歐氏距離運行實例的URL)
 sum = 0;
 for(var i = 0; i&lt;data.length; i++ )
 {
 delta = data[i] - downSampleData[i];
 sum = sum + (delta*delta);
 }
 sum = Math.sqrt(sum);
// 最基本的,咱們須要計算的是歐氏距離
// 咱們畫上去的字母,咱們學習的每個樣本
// 程序將會返回歐氏距離最小的那個字符
if( sum&lt;bestScore || bestChar=='??' )
{
 bestScore = sum;
 bestChar = c;
}
}複製代碼
複製代碼

蜂擁算法

這個例子展現一個名爲flocking(蜂擁)的迷人的簡單算法。此處的粒子是成羣存在的。起初的時候,它們各自隨機出如今某個位置,然而,這些粒子會很快地填充成各類形式的組,並以看似複雜的模式路線飛行。或者你也能夠手動點擊(或者觸摸)一個位置,這些粒子會排斥並遠離你的接觸點。

圖3:flocking(蜂擁算法)

你能夠在線運行如下URL的實例程序:

www.heatonresearch.com/fun/flock

這個實例可能須要一分鐘(大約),才能讓成熟的蜂擁集羣出現。即便這些集羣出現了,它們也常常會再次分裂和重組。重啓時點擊「Clear」(清除),或者也能夠點擊「Big Bang」(大爆炸模式),該模式不會使用任何隨機的初始化,而是將粒子統一放置在面板中央,而且以粒子設定的「複雜模式」迅速向外移動。

克雷格·雷諾茲在1986年首次用他的模擬程序Boids在計算機上成功模擬出了蜂擁算法。蜂擁集羣是一種很是複雜的行爲。他在不一樣種類的動物中有各自表現形式,各自使用了不少不一樣的名字。好比一羣小鳥,一羣昆蟲,一個學校的魚羣,一羣牛等等。其實就是用不一樣的名字來描述本質相同的行爲。

初看上去,蜂擁算法可能看似複雜。由於咱們須要建立一個對象來處理集羣中的個體、須要定義一個蜂擁對象來容納集羣成員、須要爲肯定蜂擁集羣應該向哪一個方向移動而制定常規行爲。咱們還必須肯定如何將蜂擁集羣分紅兩羣或者更多的羣。那麼問題是什麼樣的標準能夠決定某個羣體能夠獲得成員數量?新成員如何被確認是屬於哪個集羣?你能夠在下面內容中看到一些真實的蜂擁集羣例子。

蜂擁算法其實很簡單,它只有三條規則:

  • 分離 :遠離擁擠的鄰居(短距離相互排斥)
  • 對齊 :趨近於鄰居的平均方向
  • 內聚 :轉向鄰居的平均距離位置(長距離相互吸引)

這三個基本規則是必需的。蜂擁算法其實就是「簡單的複雜」的典型例子。

我但願這個例子可以儘量的簡單,可是仍然表現出看似複雜的行爲方式。其實這些粒子都是以恆定的速度運行的,每一個粒子都有一個角度屬性來定義粒子運動的方向。因此這些粒子不能夠加速或者減速,惟一能夠作到是轉向。

上述的三種規則實際上是分別爲粒子的運動設定好了一個「理想的角度」,遵照這三種規則的指望被特定的百分比屬性所抑制。這些抑制因子是你在底部看到的三個數字。你能夠嘗試填入一些數字,看看它們是如何影響集羣粒子的運動軌跡的。其實有不少的數字組合不會產生集羣的行爲,而我在實例中填入的默認值是比較合適的。

若是你想單獨查看這三種規則中單獨一條生效時的結果,那麼能夠將該規則設置爲1.0,其它的規則設置爲0.0。例如當內聚的規則單獨生效時,你會全部的粒子會彙集在面板區域中少數的幾個位置。

在這個區域中不存在任何隨機性。除了粒子最初出現的位置是隨機的以外,不會產生更多的隨機數。你甚至能夠點擊「Big Bang」(大爆炸模式)按鈕,來消除系統中全部的隨機性。若是你點擊了「Big Bang」按鈕,則全部的粒子都會被放置到區域的中心位置,並以一樣的方向運動。如此一來,要造成一幅複雜的運動模式並不會花費很長時間。因此對於用很是簡單的規則來實現很是複雜的系統來講,蜂擁算法是一個很是典型的例子。

理解歐氏距離對於例子很重要。由於每一個粒子都有兩個維度,分別是x座標和y座標。利用歐氏距離的計算方法,咱們就能夠很快找到最近的鄰居。由此即引入了另外一種重要的機器學習算法,即「K-鄰近算法」。這個K就是你但願找到的鄰居的數量。

這三種規則能夠很容易的用JavaScript實現。首先,咱們計算出理想的分離角度。

複製代碼
// 1. 隔離-避免擁擠的鄰居
(短距離的排斥力) 
separation = 0;
if (nearest.length > 0) {
  meanX = ENCOG.ArrayUtil.arrayMean(nearest, 0);
  meanY = ENCOG.ArrayUtil.arrayMean(nearest, 1);
  dx = meanX - this.agentsi;
  dy = meanY - this.agentsi;
  separation = (Math.atan2(dx, dy) \* 180 / Math.PI) - this.agentsi;
  separation += 180;
}複製代碼
複製代碼

首先,咱們須要計算出全部鄰居粒子的x座標的平均值和y座標的平均值,這個平均座標點就是鄰近集羣的中心點。而後,借用一些三角函數中的知識,計算出咱們和鄰近集羣中心點之間的夾角值。對這個夾角值加上180,由於咱們是但願遠離這個鄰近的鄰居的(進而咱們就不會撞到它們)。這個纔是咱們應該努力爭取的理想分離角度。

緊接着,咱們會計算出理想的對齊角度。以下代碼所示。

// 2. 對齊-轉向鄰居的平均方向
alignment = 0;
if (neighbors.length > 0) {
  alignment = ENCOG.ArrayUtil.arrayMean(neighbors, 2) - this.agents[i][2];
}複製代碼

對齊很是簡單,其實就是全部鄰居的平均角度。

接下來咱們計算內聚力。爲此咱們再來看看鄰居,不過這回考慮的是一個更大的集合,幾乎包括了全部的粒子。

複製代碼
// 3. 內聚-轉向鄰居的平均位置(長距離的吸引力)
cohesion = 0;
if (neighbors.length > 0) {
  meanX 
= ENCOG.ArrayUtil.arrayMean(this.agents, 0); 
  meanY = ENCOG.ArrayUtil.arrayMean(this.agents, 1);
  dx = meanX - this.agents[i][0];
  dy = meanY - this.agents[i][1];
  cohesion = (Math.atan2(dx, dy) * 180 / Math.PI) - this.agents[i][2];
}複製代碼
複製代碼

如今咱們從這個規則中獲得了理想的角度,那麼必需要開始轉動粒子(或者說是代理)了。

// 執行轉向操做
// 這三種規則的參數應用值是能夠配置的
// 我提供的這三個默認值比例的運行表現很好
turnAmount = (cohesion * this.constCohesion) + (alignment * this.constAlignment) + (separation * this.constSeparation);
this.agents[i][2] += turnAmount;複製代碼

到目前爲止,咱們研究的技術並非隨機性的,而是能夠被認定爲決定性的。也就是說獲得的結果老是能夠預測的。對於本文的內容的排版,咱們會作出180度的調整,剩下的技術都是研究隨機性的。也就是用隨機性來解決問題。

旅行推銷員問題(TSP問題)

旅行推銷員問題(TSP)意爲存在一名「推銷員」,他必須通過必定數量的城市,而這條最短的旅行路線就是咱們尋找的目標。其中容許推銷員從任意一個城市開始或者結束。惟一的要求是「推銷員」必須通過每個城市而且只能通過一次。

若是用通常的迭代程序實現,這彷佛是一個簡單的任務。思考一下隨着城市數量的增長,可能的排列組合數量會增長多少。若是隻有一兩個城市,那隻須要一步迭代就夠了。若是是三個城市呢,迭代步驟就變成了6步。表格8-1列舉出了迭代步驟的增加速度。

表1:用常規程序解決TSP問題的步驟數目

表格中的計算公式就是階乘。步驟數目n的數量就是用階乘符號!計算的。任意n值的階乘計算方式是n×(n−1) ×(n−2).......3×2×1

由這個公式不難看出當一個程序必須使用「暴力」方式進行搜索時,這些數值會變得很是大。在下一節的討論中,咱們使用的示例程序會在幾分鐘內找到一個能解決50個城市問題的解決方案,這個程序用到是模擬退火法的思路,而不是使用普通的暴力搜索。

模擬退火法

模擬退火法是一種模擬退火的物理過程的編程方法,退火是指將某種材料(好比鋼鐵或者玻璃)加熱後再冷卻的方法,一般用來軟化材料以及下降材料硬度。由此可知,模擬退火法就是將一個「解決方案」暴露在「熱處理」的環境中,而後進行冷卻處理進而產生一個更好的解決方案。你能夠在下面的URL中運行模擬退火法的示例程序。

www.heatonresearch.com/fun/tsp/ann…

模擬退火法是經過從起始溫度到結束溫度的屢次迭代進行實現的。循環計數容許你指定溫度降低的粒度。溫度越高,系統引入的隨機性就越高。你能夠配置這三個參數的值。

下面的JavaScript代碼實現了模擬退火法

複製代碼
anneal.randomize = function(path, temperature) {
 var length = path.length - 1;
 // 調整路徑上城市的次序(即模擬退火)
 for (var i = 0; i < temperature; i++) {
 var index1 = Math.floor(length * Math.random());
 var index2 = Math.floor(length * Math.random());
 var d = universe.pathDistance(path, index1, index1 + 1)
 + universe.pathDistance(path, index2, index2 + 1)
 - universe.pathDistance(path, index1, index2)
 - universe.pathDistance(path, index1 + 1, index2 + 1);
 if (d > 0) {
 // 若是須要的話對index1 和 index2進行排序
 if (index2 < index1) {
 var temp = index1;
 index1 = index2;
 index2 = temp;
 }
 for (; index2 > index1; index2--) {
 var temp = path[index1 + 1];
 path[index1 + 1] = path[index2];
 path[index2] = temp;
 index1++;
 }
 }
 }
}複製代碼
複製代碼

上面的隨機化函數是專門爲TSP問題定義的。在Encog框架中模擬退火法是通用的,相對於TSP獨立。因此你必須爲你但願解決的問題提供一個隨機函數。

基原本說,隨機化函數會根據溫度對城市的旅行路線進行修正。上面的函數只是簡單地根據溫度將旅行路線中的路線上通過城市次序進行對換。溫度越高,對換的次數越多。

隨機城市

這個程序的常見用法是將隨機幾個城市放置地圖上,這些城市出如今地圖上的隨機的幾個位置。隨機城市問題的排列組合相比於其餘的固定城市組合要更困難一些。在下圖中你能夠看到包含了50個隨機的城市的地圖。

圖 4:隨機城市

一旦解決了這組隨機城市TSP問題,結果就以下圖所示。

圖 5:可能的解決方案

你可能想要經過改變參數來評估模擬退火法的實際效果,爲此須要從新運行該程序,而且你應該隨機化旅行路線。這樣你就能夠用相同的城市配置從新開始。

城市圈

你能夠將城市位置以橢圓的形狀進行排列,這樣就更容易理解模擬退火法是如何演化出最佳解決方案的。圍繞一個橢圓的最優路徑與它的周長形狀相似。在這裏你能夠利用模擬退火法,找到一條几乎就是最優的路徑。

圖 6:城市圈

遺傳算法

利用遺傳算法(GA)能夠獲得TSP問題的潛在解決方案。GA是經過簡單的進化操做來建立一個可以不斷改進的解決方案。這整個過程就至關於生物遺傳進化的精簡版。進化其實就是經過交叉和突變實現的,因此當兩個解決方案「交配」併產生後代時,就至關於發生了交叉。而當單一的解決方案稍微有所改變時就至關於引起了突變。

相似於模擬退火法,GA(遺傳算法)也是隨機的。在交叉過程當中會由隨機性來決定父本和母本會遺產什麼樣的特徵給子代。

你能夠在下面的URL中在線查看TSP(旅行推銷員問題)的遺傳算法應用程序:

www.heatonresearch.com/fun/tsp/gen…

爲了使用Encog框架中自帶的遺傳算法,你必須定義變異和交叉這兩個操做,它們的實現取決於你正在尋找的解決方案的類型。

下面的代碼定義了TSP問題的突變操做。

複製代碼
genetic.mutate = function performMutation(data)
{
  var iswap1 = Math.floor(Math.random() * data.length);
  var iswap2 = Math.floor(Math.random() * data.length);
  // 不相等時
  if (iswap1 == iswap2)
  {
    // 繼續下一步
    // 可是,不要出界
    if (iswap1 > 0)
    {
      iswap1--;
    } else {
      iswap1++;
    }
  }
  var t = data[iswap1];
  data[iswap1] = data[iswap2];
  data[iswap2] = t;
}複製代碼
複製代碼

這段代碼與模擬退火法的隨機化操做很是相似。本質上,程序對列表中的兩個城市進行了交換操做。因此咱們必須保證這兩個隨機城市是不相同的,由於一旦相同,這兩個城市就不會發生交換。

交叉操做比較複雜。下面的代碼實現了交叉函數。

複製代碼
genetic.crossover = function performCrossover(motherArray, fatherArray, child1Array, child2Array)
{
  // 染色體(此處泛指遺傳特性)必須在兩個位置被切割,並肯定他們。
  var cutLength = motherArray.length / 5;
  var cutpoint1 = Math.floor(Math.random() * (motherArray.length - cutLength));
  var cutpoint2 = cutpoint1 + cutLength;
  // 記錄這兩個子代中每個染色體中所帶的基因,默認爲false
  var taken1 = {};
  var taken2 = {};
  // 處理削減的染色體部分
  for (var i = 0; i < motherArray.length; i++)
  {
    if (!((i < cutpoint1) || (i > cutpoint2)))
    {
      child1Array[i] = fatherArray[i];
      child2Array[i] = motherArray[i];
      taken1[fatherArray[i]] = true;
      taken2[motherArray[i]] = true;
    }
  }
  // 處理外部的染色體部分
  for (var i = 0; i < motherArray.length; i++)
  {
    if ((i < cutpoint1) || (i > cutpoint2))
    {
      child1Array[i] = getNotTaken(motherArray,taken1);
      child2Array[i] = getNotTaken(fatherArray,taken2);
    }
  }
};複製代碼
複製代碼

上面代碼的原理以下:在城市的道路上取兩個「切點」,這就意味着把父本和母本的特性都各自分割成了三份,父本和母本有着相同的切點。這些切割的規模是隨機的,而後經過交換父輩的三份來建立兩個子代。例如,觀察下面的父本和母本。

[m1, m2, m3 ,m4, m5, m6, m7, m8, m9, m10]
[f1, f2, f3 ,f4, f5, f6, f7, f8, f9, f10]複製代碼

如今咱們將這些切點加進去。

[m1, m2] [m3 ,m4, m5, m6] [m7, m8, m9, m10]
[f1, f2] [f3 ,f4, f5, f6] [f7, f8, f9, f10]複製代碼

如此會產生下面兩個子代。

[m1, m2] [f3 ,f4, f5, f6] [m7, m8, m9, m10]
[f1, f2] [m3 ,m4, m5, m6] [f7, f8, f9, f10]複製代碼

根據另外一個隨機事件,每一個解決方案均可能會發生突變。突變就是將「新產生的信息」添加到種羣遺傳的過程。不然就是簡單的傳遞已經存在的遺傳特徵。

XOR神經網絡

神經網絡是另一種基於生物學的機器學習方法,它很是鬆散地創建在人腦的基礎上。神經網絡是由神經突觸鏈接的神經元組成的,每個突觸自己都具備權重,衆多突觸的權重構成了神經網絡的記憶。以下所示的神經網絡示意圖。

圖 7:一個神經網絡

如圖所示的結構,其實就是咱們下一節要建立的神經網絡,你能夠在上面的神經網絡中看到有一個輸入層和一個輸出層。神經網絡接收來自輸入層的刺激,並交由輸出層進行相應輸出。神經網絡內部也可能存在隱藏層,該層中一樣包含有神經元。隱藏層也有助於信息的處理。XOR神經網絡(異或神經網絡),有兩個輸入和一個輸出。兩個輸入端接收布爾值(0或者1),輸出神經元也輸出布爾值。其目的就是讓神經網絡實現和XOR(異或運算)操做符相同的功能。

0 XOR 0 = 0
1 XOR 0 = 1
0 XOR 1 = 1
1 XOR 1 = 0複製代碼

當兩個輸入不一致時,異或XOR操做符的輸出必爲1。

你能夠在下面看到異或XOR的示例輸出。

複製代碼
Training XOR with Resilient Propagation (RPROP)
Training Iteration #1, Error: 0.266564333804989
Training Iteration #2, Error: 0.2525674154011323
Training Iteration #3, Error: 0.2510141208338126
Training Iteration #4, Error: 0.2501895607116004
Training Iteration #5, Error: 0.24604660296617512
Training Iteration #6, Error: 0.24363697465430123
Training Iteration #7, Error: 0.24007542622000883
Training Iteration #8, Error: 0.23594361591893737
Training Iteration #9, Error: 0.23110199069041137
Training Iteration #10, Error: 0.22402031408256806
...
Training Iteration #41, Error: 0.0169149539750981
Training Iteration #42, Error: 0.012983289628979862
Training Iteration #43, Error: 0.010217909135985562
Training Iteration #44, Error: 0.007442433731742264
Testing neural network
Input: 0 ; 0   Output: 0.000005296759326400659   Ideal: 0
Input: 1 ; 0   Output: 0.9176637562838892   Ideal: 1
Input: 0 ; 1   Output: 0.9249242746585553   Ideal: 1
Input: 1 ; 1   Output: 0.036556423402042126   Ideal: 0複製代碼
複製代碼

正如上文所示,它用了44個迭代訓練來教神經網絡執行XOR操做,神經網絡的初始化權重是從隨機數字開始的。數據訓練的過程當中會逐漸調整權重,以產生指望的輸出。神經網絡的隨機部分是權重的初始化量值。除了這些,神經網絡是決定性的。給定相同的權重和輸入,神經網絡始終會產生相同的輸出。

在上面的輸出中,你可能會注意到輸出的結果並非很是精確的。由於神經網絡永遠不會爲1的輸出精確到1.0。因爲開始的權重是隨機的,因此你不可能從這個神經網絡中獲得兩個相同的結果。另外,因爲一些隨機的初始化權重量值是徹底不可訓練的,正因如此,有時你會看到XOR神經網絡達到了5000的最大訓練值,然而就仍是放棄了。

你能夠在下面URL中看到這個案例的運行實例。

www.heatonresearch.com/fun/ann/xor

咱們如今來觀察這個程序是如何構建的。首先,咱們建立輸入和理想輸出。

複製代碼
var XOR_INPUT = [
  [0,0],
  [1,0],
  [0,1],
  [1,1]
];
var XOR_IDEAL = [
  [0],
  [1],
  [1],
  [0]
];複製代碼
複製代碼

上面的兩個數組分別包含了輸入和理想輸出。這個「真相表」將被用來訓練神經網絡。

接着咱們來建立一個三層神經網絡。輸入層有兩個神經元,隱藏的神經元有三個,輸出層有一個神經元。

var network = ENCOG.BasicNetwork.create( [
  ENCOG.BasicLayer.create(ENCOG.ActivationSigmoid.create(),2,1),
  ENCOG.BasicLayer.create(ENCOG.ActivationSigmoid.create(),3,1),
  ENCOG.BasicLayer.create(ENCOG.ActivationSigmoid.create(),1,0)] );
network.randomize();複製代碼

建立和隨機化神經網絡的時候,將會調用隨機化函數將權重填充爲隨機值。

訓練神經網絡有不少不一樣方法,對於本例,咱們會採用RPROP(一種基於彈性反向傳播的神經網絡算法原理)來實現。

var train = ENCOG.PropagationTrainer.create(network,XOR_INPUT,XOR_IDEAL,"RPROP",0,0);複製代碼

如今,咱們將經過迭代訓練進行循環處理,直到出錯率降到能夠接受的水平線如下爲止。

複製代碼
var iteration = 1;
do
{
  train.iteration();
  var str = "Training Iteration #" + iteration + ", Error: " + train.error;
con.writeLine(str); 
  iteration++;
} while( iteration<1000 && train.error>0.01);複製代碼
複製代碼

如今神經網絡的訓練已完成,咱們將對輸入數組進行循環處理,並將其提交給神經網絡。神經網絡會顯示出對應輸出。

複製代碼
var input = [0,0];
var output = [];
con.writeLine("Testing neural network");
for(var i=0;i<XOR_INPUT.length;i++)
{
  network.compute(XOR_INPUT[i],output);
  var str = "Input: " + String(XOR_INPUT[i][0])
    + " ; " + String(XOR_INPUT[i][1])
    + " Output: " + String(output[0])
    + " Ideal: " + String(XOR_IDEAL[i][0]);
  con.writeLine(str);
}複製代碼
複製代碼

這是對神經網絡的一個很是簡單的介紹,我還作了一個關於Java和C#神經網絡內容,你若是隻對神經網絡感興趣,下面的內容應該會有所幫助。

  • <ahref="http:>Introduction to Neural Networks for Java
  • <ahref="http:>Introduction to Neural Networks for C# </ahref="http:>

此外,若是你想了解神經網絡的基本介紹,下面的文章可能會對你有用。

www.heatonresearch.com/content/non…

神經網絡分類

如今咱們來看一個稍微複雜些的神經網絡分類,這個神經網絡將會學習如何進行分類。咱們會學到神經網絡是如何經過訓練數據集來學習對數據點進行分類,而且可以對訓練數據集中不存在的數據點進行分類。

你能夠在下面的URL中在線運行這個示例代碼:

www.heatonresearch.com/ann/classif…

本案例將利用前饋神經網絡原理進行分類。爲了充分利用這個程序,咱們在畫圖區域繪製了幾個彩色點。必須保證你至少有兩個彩色點,不然程序就沒法進行分類。一旦你開始畫點而且點擊begin(開始),則神經網絡也就開始訓練了。你將看到你提供的數據點附近的其餘區域是如何進行分類的。

上一個神經網絡案例有是兩個輸入神經元和三個輸出神經元的。隱藏層的結構是由drop列表決定的。舉例來講,若是你選擇了2:10:10:3,你將會獲得一個與如下圖像類似的網絡,這個網絡有兩個隱藏層,每層有10個神經元。

輸入神經元表明一個點的x座標和y座標。爲了繪出上面的圖像,該程序在x座標和y座標的網格上進行循環處理。每一個網格組件都會對神經網絡進行查詢。左上角的細胞是[0,0],右下角的細胞座標是[1,1]。對於具備sigmoid(經常使用的非線性激活函數)激活函數的神經網絡數據,一般能夠在0到1之間的範圍內接受輸入,所以這個範圍的表現良好。中心點是[0.5,0.5]。

神經網絡的輸出即正方形中像素點的RGB顏色值。[0,0,0]表示黑色,[1,1,1]表示白色。當你在繪圖區域畫點時,就等同於在提供訓練數據。輸入神經元將會根據你輸入的數據訓練出放置x座標和y座標的方式。指望或者理想中的輸出應該是與你在該位置選擇的顏色近似一致。

讓咱們來看一個簡單的案例。若是你只畫出兩個數據點,那麼這個區域就會被分割成兩部分。以下圖所示,你能夠看到一個紅色的數據點和一個藍色的數據點。

圖 8:兩個數據點的分類

該算法爲了讓應用程序獲得的錯誤評級比較低,它僅須要保證藍色數據點位於藍色區域,而紅色數據點位於紅色區域。其餘全部像素點都是基於已知像素點的「猜想」。但因爲這樣已知的數據很是少,因此神經網絡很難真正猜到這兩個區域之間的邊界到底在哪裏。

若是你提供了更多的訓練數據,那你會獲得一個更加複雜的形狀。若是你選擇建立一個雙色的隨機圖像,那你會獲得與下圖相似的數據點。

圖 9:多個數據點的分類

在此圖中,神經網絡建立了一種更加複雜的模式試圖來適應全部的數據點。

你還能夠選擇建立一個複雜的多顏色模式。下面的案例中爲數據點隨機生成了顏色值。神經網絡甚至會將顏色進行混合,試圖作出妥協,以此來儘量地下降偏差。

圖 10:多顏色數據點分類

此算法甚至有可能學習複雜的相互螺旋的形狀,以下圖所示。

圖 11:螺旋數據點的分類

延伸閱讀

本文介紹了JavaScript中的機器學習,若是想了解更多關於機器學習的知識,那麼你可能會對下面的連接感興趣。

歷史

2012年10月16日的第一個版本,引用文件版本 Encog JS v1.0

翻譯人:白加黑大人,該成員來自雲+社區翻譯社

原文連接:https://www.codeproject.com/Articles/477689/JavaScript-Machine-Learning-and-Neural-Networks-wi

原文做者:JeffHeaton

原文譯題:經過JS庫Encog實現JavaScript機器學習和神經學網絡

相關閱讀

Python中Keras深度學習庫的迴歸教程

從程序員的角度設計一個Java的神經網絡

如何使用 scikit-learn 爲機器學習準備文本數據

此文已由做者受權雲加社區發佈,轉載請註明文章出處

相關文章
相關標籤/搜索