摘要:我會(huì)使用一個(gè)先進(jìn)的神經(jīng)網(wǎng)絡(luò)和機(jī)器學(xué)習(xí)框架這個(gè)框架,并向你們展示如何用這個(gè)框架來實(shí)現(xiàn)光學(xué)字符辨識(shí),模擬退火法,遺傳算法和神經(jīng)網(wǎng)絡(luò)。歐氏距離我們從歐氏距離開始談起,歐氏距離是一個(gè)非常簡(jiǎn)單的概念,適用于不同的機(jī)器學(xué)習(xí)技術(shù)。
歡迎大家前往云+社區(qū),獲取更多騰訊海量技術(shù)實(shí)踐干貨哦~
下載 heaton-javascript-ml.zip - 45.1 KB
基本介紹在本文中,你會(huì)對(duì)如何使用JavaScript實(shí)現(xiàn)機(jī)器學(xué)習(xí)這個(gè)話題有一些基本的了解。我會(huì)使用Encon(一個(gè)先進(jìn)的神經(jīng)網(wǎng)絡(luò)和機(jī)器學(xué)習(xí)框架)這個(gè)框架,并向你們展示如何用這個(gè)框架來實(shí)現(xiàn)光學(xué)字符辨識(shí),模擬退火法,遺傳算法和神經(jīng)網(wǎng)絡(luò)。Encog同時(shí)包括了幾個(gè)GUI窗體小部件,這些小部件可以更方便地顯示出一般機(jī)器學(xué)習(xí)任務(wù)的輸出。
運(yùn)行環(huán)境Encog是一個(gè)面向Java,C#,JavaScript和C/C++的高級(jí)機(jī)器學(xué)習(xí)平臺(tái)。除此之外,Encog還可以為http://www.heatonresearch.com...的實(shí)際案例生成對(duì)應(yīng)代碼,本文將重點(diǎn)介紹如何使用支持JavaScript的Encog框架,該框架允許你創(chuàng)建利用人工智能實(shí)現(xiàn)的交互式web應(yīng)用程序。訪問以下網(wǎng)址獲取有關(guān)Encog的更多信息。
http://www.heatonresearch.com...
代碼調(diào)用本文介紹的所有示例代碼都可以在附帶的下載中找到。
這段代碼同時(shí)被托管在下面的GitHub庫中。
https://github.com/encog/enco...
你可以看到本文討論的所有示例都運(yùn)行在下面的URL中:
http://www.heatonresearch.com...
Encog框架包含在兩個(gè)JavaScript文件中。第一個(gè)JavaScript文件包含了所有核心的機(jī)器學(xué)習(xí)函數(shù)。這個(gè)JavaScript文件被命名為encog-js-x.js。第二個(gè)文件包含了所有的GUI窗體小組件,并被命名為encog-widget.js。你可以在下面的引用路徑中閱讀這兩個(gè)文件。
歐氏距離
我們從歐氏距離開始談起,歐氏距離是一個(gè)非常簡(jiǎn)單的概念,適用于不同的機(jī)器學(xué)習(xí)技術(shù)。歐氏距離提供的結(jié)果是一個(gè)數(shù)字,該數(shù)字決定了相同長(zhǎng)度的兩個(gè)數(shù)組之間的相似性。思考下面三個(gè)數(shù)組:
Array 1: [ 1, 2, 3] Array 2: [ 1, 3, 2] Array 3: [ 3, 2, 1]
我們可以計(jì)算出上面任意兩個(gè)數(shù)組之間的歐氏距離,這對(duì)于確定數(shù)組之間的相似度是非常有用的。思考一下,假如我們想要確定一下數(shù)組2或者數(shù)組3哪個(gè)距離數(shù)組1更近。為了做到這一點(diǎn),我們需要計(jì)算數(shù)組1和數(shù)組2之間的歐氏距離。然后再計(jì)算數(shù)組1和數(shù)組3之間的歐氏距離。兩相比較,最短的就是最相似的。
從數(shù)學(xué)角度來講,歐氏距離由以下方程式進(jìn)行計(jì)算。
圖 1: 歐氏距離使用這個(gè)公式,我們現(xiàn)在可以計(jì)算上文中的歐氏距離
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
從結(jié)果中我們可以看出數(shù)組2比數(shù)組1更為接近數(shù)組3。
下面的JavaScript代碼實(shí)現(xiàn)了歐氏距離的計(jì)算。
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); };
歐氏距離可以被用來創(chuàng)建一個(gè)簡(jiǎn)單的光學(xué)字符辨識(shí)實(shí)例。你可以在下圖中看到應(yīng)用程序運(yùn)行實(shí)例:
圖 2: JavaScript光學(xué)字符辨識(shí)你可以在下面這個(gè)URL中查看程序的運(yùn)行實(shí)例:
http://www.heatonresearch.com...
HTML5(啟用觸控設(shè)備)的JavaScript應(yīng)用程序可以通過簡(jiǎn)單的歐氏距離來實(shí)現(xiàn)基本的光學(xué)字符辨識(shí)。為了使用這個(gè)示例,需要在下面這個(gè)大的矩形中繪制一個(gè)數(shù)字,然后點(diǎn)擊“Recognize”(識(shí)別)按鈕,程序會(huì)嘗試猜測(cè)你畫的這個(gè)數(shù)字。雖然準(zhǔn)確性并不是特別高,但它做的確實(shí)已經(jīng)很不錯(cuò)了。
該程序已經(jīng)通過了數(shù)據(jù)訓(xùn)練,你可以移除這些數(shù)字條目中的任何一個(gè),或者創(chuàng)建你自己的條目。如果需要訓(xùn)練一個(gè)新字符的OCR,只要簡(jiǎn)單繪出那個(gè)字符,然后點(diǎn)擊“Teach”(教學(xué))按鈕。則該字符就會(huì)被增加到已知的字符列表中。
你會(huì)發(fā)現(xiàn),你所繪制的任何東西都是先剪裁然后向下采樣的。程序會(huì)對(duì)你所繪制的高分辨率字符向下采樣并將采樣點(diǎn)分配到5×8網(wǎng)格中。然后將這個(gè)通過向下采樣得到的網(wǎng)格與每個(gè)數(shù)字的向下采樣網(wǎng)格進(jìn)行比較。如果要查看程序中經(jīng)訓(xùn)練后得到的網(wǎng)格,需要在字符列表中單擊你希望看到的字符。然后程序會(huì)將這個(gè)網(wǎng)格轉(zhuǎn)換成一個(gè)一維數(shù)組,而一個(gè)5×8的網(wǎng)格會(huì)有40個(gè)數(shù)組元素。
以下JavaScript代碼執(zhí)行了這個(gè)搜索,并且實(shí)現(xiàn)了一個(gè)歐氏距離的計(jì)算
var c, data, sum, i, delta; for(c in charData ) { data = charData[c]; // 現(xiàn)在我們將會(huì)識(shí)別出這個(gè)畫出來的字母. // 為此,我們需要利用歐氏距離來計(jì)算 // http://www.heatonresearch.com/wiki/Euclidean_Distance (這是歐氏距離運(yùn)行實(shí)例的URL) sum = 0; for(var i = 0; i蜂擁算法 這個(gè)例子展示一個(gè)名為flocking(蜂擁)的迷人的簡(jiǎn)單算法。此處的粒子是成群存在的。起初的時(shí)候,它們各自隨機(jī)出現(xiàn)在某個(gè)位置,然而,這些粒子會(huì)很快地填充成各種形式的組,并以看似復(fù)雜的模式路線飛行?;蛘吣阋部梢允謩?dòng)點(diǎn)擊(或者觸摸)一個(gè)位置,這些粒子會(huì)排斥并遠(yuǎn)離你的接觸點(diǎn)。
圖3:flocking(蜂擁算法)你可以在線運(yùn)行以下URL的實(shí)例程序:
http://www.heatonresearch.com...
這個(gè)實(shí)例可能需要一分鐘(大約),才能讓成熟的蜂擁集群出現(xiàn)。即使這些集群出現(xiàn)了,它們也經(jīng)常會(huì)再次分裂和重組。重啟時(shí)點(diǎn)擊“Clear”(清除),或者也可以點(diǎn)擊“Big Bang”(大爆炸模式),該模式不會(huì)使用任何隨機(jī)的初始化,而是將粒子統(tǒng)一放置在面板中央,并且以粒子設(shè)定的“復(fù)雜模式”迅速向外移動(dòng)。
克雷格·雷諾茲在1986年首次用他的模擬程序Boids在計(jì)算機(jī)上成功模擬出了蜂擁算法。蜂擁集群是一種非常復(fù)雜的行為。他在不同種類的動(dòng)物中有各自表現(xiàn)形式,各自使用了很多不同的名字。比如一群小鳥,一群昆蟲,一個(gè)學(xué)校的魚群,一群牛等等。其實(shí)就是用不同的名字來描述本質(zhì)相同的行為。
初看上去,蜂擁算法可能看似復(fù)雜。因?yàn)槲覀冃枰獎(jiǎng)?chuàng)建一個(gè)對(duì)象來處理集群中的個(gè)體、需要定義一個(gè)蜂擁對(duì)象來容納集群成員、需要為確定蜂擁集群應(yīng)該向哪個(gè)方向移動(dòng)而制定常規(guī)行為。我們還必須確定如何將蜂擁集群分成兩群或者更多的群。那么問題是什么樣的標(biāo)準(zhǔn)可以決定某個(gè)群體可以得到成員數(shù)量?新成員如何被確認(rèn)是屬于哪一個(gè)集群?你可以在下面內(nèi)容中看到一些真實(shí)的蜂擁集群例子。
蜂擁算法其實(shí)很簡(jiǎn)單,它只有三條規(guī)則:
分離 :遠(yuǎn)離擁擠的鄰居(短距離相互排斥)
對(duì)齊 :趨近于鄰居的平均方向
內(nèi)聚 :轉(zhuǎn)向鄰居的平均距離位置(長(zhǎng)距離相互吸引)
這三個(gè)基本規(guī)則是必需的。蜂擁算法其實(shí)就是“簡(jiǎn)單的復(fù)雜”的典型例子。
我希望這個(gè)例子能夠盡可能的簡(jiǎn)單,但是仍然表現(xiàn)出看似復(fù)雜的行為方式。其實(shí)這些粒子都是以恒定的速度運(yùn)行的,每個(gè)粒子都有一個(gè)角度屬性來定義粒子運(yùn)動(dòng)的方向。所以這些粒子不可以加速或者減速,唯一可以做到是轉(zhuǎn)向。
上述的三種規(guī)則其實(shí)是分別為粒子的運(yùn)動(dòng)設(shè)定好了一個(gè)“理想的角度”,遵守這三種規(guī)則的期望被特定的百分比屬性所抑制。這些抑制因子是你在底部看到的三個(gè)數(shù)字。你可以嘗試填入一些數(shù)字,看看它們是如何影響集群粒子的運(yùn)動(dòng)軌跡的。其實(shí)有很多的數(shù)字組合不會(huì)產(chǎn)生集群的行為,而我在實(shí)例中填入的默認(rèn)值是比較合適的。
如果你想多帶帶查看這三種規(guī)則中多帶帶一條生效時(shí)的結(jié)果,那么可以將該規(guī)則設(shè)置為1.0,其它的規(guī)則設(shè)置為0.0。例如當(dāng)內(nèi)聚的規(guī)則多帶帶生效時(shí),你會(huì)所有的粒子會(huì)聚集在面板區(qū)域中少數(shù)的幾個(gè)位置。
在這個(gè)區(qū)域中不存在任何隨機(jī)性。除了粒子最初出現(xiàn)的位置是隨機(jī)的之外,不會(huì)產(chǎn)生更多的隨機(jī)數(shù)。你甚至可以點(diǎn)擊“Big Bang”(大爆炸模式)按鈕,來消除系統(tǒng)中所有的隨機(jī)性。如果你點(diǎn)擊了“Big Bang”按鈕,則所有的粒子都會(huì)被放置到區(qū)域的中心位置,并以同樣的方向運(yùn)動(dòng)。如此一來,要形成一幅復(fù)雜的運(yùn)動(dòng)模式并不會(huì)花費(fèi)很長(zhǎng)時(shí)間。所以對(duì)于用非常簡(jiǎn)單的規(guī)則來實(shí)現(xiàn)非常復(fù)雜的系統(tǒng)來說,蜂擁算法是一個(gè)非常典型的例子。
理解歐氏距離對(duì)于例子很重要。因?yàn)槊總€(gè)粒子都有兩個(gè)維度,分別是x坐標(biāo)和y坐標(biāo)。利用歐氏距離的計(jì)算方法,我們就可以很快找到最近的鄰居。由此即引入了另一種重要的機(jī)器學(xué)習(xí)算法,即“K-鄰近算法”。這個(gè)K就是你希望找到的鄰居的數(shù)量。
這三種規(guī)則可以很容易的用JavaScript實(shí)現(xiàn)。首先,我們計(jì)算出理想的分離角度。
// 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; }首先,我們需要計(jì)算出所有鄰居粒子的x坐標(biāo)的平均值和y坐標(biāo)的平均值,這個(gè)平均坐標(biāo)點(diǎn)就是鄰近集群的中心點(diǎn)。然后,借用一些三角函數(shù)中的知識(shí),計(jì)算出我們和鄰近集群中心點(diǎn)之間的夾角值。對(duì)這個(gè)夾角值加上180,因?yàn)槲覀兪窍Mh(yuǎn)離這個(gè)鄰近的鄰居的(進(jìn)而我們就不會(huì)撞到它們)。這個(gè)才是我們應(yīng)該努力爭(zhēng)取的理想分離角度。
緊接著,我們會(huì)計(jì)算出理想的對(duì)齊角度。如下代碼所示。
// 2. 對(duì)齊-轉(zhuǎn)向鄰居的平均方向 alignment = 0; if (neighbors.length > 0) { alignment = ENCOG.ArrayUtil.arrayMean(neighbors, 2) - this.agents[i][7]; }對(duì)齊非常簡(jiǎn)單,其實(shí)就是所有鄰居的平均角度。
接下來我們計(jì)算內(nèi)聚力。為此我們?cè)賮砜纯脆従樱贿^這回考慮的是一個(gè)更大的集合,幾乎包括了所有的粒子。
// 3. 內(nèi)聚-轉(zhuǎn)向鄰居的平均位置(長(zhǎng)距離的吸引力) 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][8]; cohesion = (Math.atan2(dx, dy) * 180 / Math.PI) - this.agents[i][9]; }現(xiàn)在我們從這個(gè)規(guī)則中得到了理想的角度,那么必須要開始轉(zhuǎn)動(dòng)粒子(或者說是代理)了。
// 執(zhí)行轉(zhuǎn)向操作 // 這三種規(guī)則的參數(shù)應(yīng)用值是可以配置的 // 我提供的這三個(gè)默認(rèn)值比例的運(yùn)行表現(xiàn)很好 turnAmount = (cohesion * this.constCohesion) + (alignment * this.constAlignment) + (separation * this.constSeparation); this.agents[i][10] += turnAmount;到目前為止,我們研究的技術(shù)并不是隨機(jī)性的,而是可以被認(rèn)定為決定性的。也就是說得到的結(jié)果總是可以預(yù)測(cè)的。對(duì)于本文的內(nèi)容的排版,我們會(huì)做出180度的調(diào)整,剩下的技術(shù)都是研究隨機(jī)性的。也就是用隨機(jī)性來解決問題。
旅行推銷員問題(TSP問題)旅行推銷員問題(TSP)意為存在一名“推銷員”,他必須經(jīng)過一定數(shù)量的城市,而這條最短的旅行路線就是我們尋找的目標(biāo)。其中允許推銷員從任意一個(gè)城市開始或者結(jié)束。唯一的要求是“推銷員”必須經(jīng)過每一個(gè)城市并且只能經(jīng)過一次。
如果用一般的迭代程序?qū)崿F(xiàn),這似乎是一個(gè)簡(jiǎn)單的任務(wù)。思考一下隨著城市數(shù)量的增加,可能的排列組合數(shù)量會(huì)增加多少。如果只有一兩個(gè)城市,那只需要一步迭代就夠了。如果是三個(gè)城市呢,迭代步驟就變成了6步。表格8-1列舉出了迭代步驟的增長(zhǎng)速度。
表1:用常規(guī)程序解決TSP問題的步驟數(shù)目表格中的計(jì)算公式就是階乘。步驟數(shù)目n的數(shù)量就是用階乘符號(hào)!計(jì)算的。任意n值的階乘計(jì)算方式是n×(n?1) ×(n?2).......3×2×1
由這個(gè)公式不難看出當(dāng)一個(gè)程序必須使用“暴力”方式進(jìn)行搜索時(shí),這些數(shù)值會(huì)變得非常大。在下一節(jié)的討論中,我們使用的示例程序會(huì)在幾分鐘內(nèi)找到一個(gè)能解決50個(gè)城市問題的解決方案,這個(gè)程序用到是模擬退火法的思路,而不是使用普通的暴力搜索。
模擬退火法模擬退火法是一種模擬退火的物理過程的編程方法,退火是指將某種材料(比如鋼鐵或者玻璃)加熱后再冷卻的方法,通常用來軟化材料以及降低材料硬度。由此可知,模擬退火法就是將一個(gè)“解決方案”暴露在“熱處理”的環(huán)境中,然后進(jìn)行冷卻處理進(jìn)而產(chǎn)生一個(gè)更好的解決方案。你可以在下面的URL中運(yùn)行模擬退火法的示例程序。
http://www.heatonresearch.com...
模擬退火法是通過從起始溫度到結(jié)束溫度的多次迭代進(jìn)行實(shí)現(xiàn)的。循環(huán)計(jì)數(shù)允許你指定溫度下降的粒度。溫度越高,系統(tǒng)引入的隨機(jī)性就越高。你可以配置這三個(gè)參數(shù)的值。
下面的JavaScript代碼實(shí)現(xiàn)了模擬退火法
anneal.randomize = function(path, temperature) { var length = path.length - 1; // 調(diào)整路徑上城市的次序(即模擬退火) 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) { // 如果需要的話對(duì)index1 和 index2進(jìn)行排序 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++; } } } }上面的隨機(jī)化函數(shù)是專門為TSP問題定義的。在Encog框架中模擬退火法是通用的,相對(duì)于TSP獨(dú)立。所以你必須為你希望解決的問題提供一個(gè)隨機(jī)函數(shù)。
基本來說,隨機(jī)化函數(shù)會(huì)根據(jù)溫度對(duì)城市的旅行路線進(jìn)行修正。上面的函數(shù)只是簡(jiǎn)單地根據(jù)溫度將旅行路線中的路線上經(jīng)過城市次序進(jìn)行對(duì)換。溫度越高,對(duì)換的次數(shù)越多。
隨機(jī)城市這個(gè)程序的常見用法是將隨機(jī)幾個(gè)城市放置地圖上,這些城市出現(xiàn)在地圖上的隨機(jī)的幾個(gè)位置。隨機(jī)城市問題的排列組合相比于其他的固定城市組合要更困難一些。在下圖中你可以看到包含了50個(gè)隨機(jī)的城市的地圖。
圖 4:隨機(jī)城市一旦解決了這組隨機(jī)城市TSP問題,結(jié)果就如下圖所示。
圖 5:可能的解決方案你可能想要通過改變參數(shù)來評(píng)估模擬退火法的實(shí)際效果,為此需要重新運(yùn)行該程序,并且你應(yīng)該隨機(jī)化旅行路線。這樣你就可以用相同的城市配置重新開始。
城市圈你可以將城市位置以橢圓的形狀進(jìn)行排列,這樣就更容易理解模擬退火法是如何演化出最佳解決方案的。圍繞一個(gè)橢圓的最優(yōu)路徑與它的周長(zhǎng)形狀類似。在這里你可以利用模擬退火法,找到一條幾乎就是最優(yōu)的路徑。
圖6:城市圈 遺傳算法利用遺傳算法(GA)可以得到TSP問題的潛在解決方案。GA是通過簡(jiǎn)單的進(jìn)化操作來創(chuàng)建一個(gè)能夠不斷改進(jìn)的解決方案。這整個(gè)過程就相當(dāng)于生物遺傳進(jìn)化的精簡(jiǎn)版。進(jìn)化其實(shí)就是通過交叉和突變實(shí)現(xiàn)的,所以當(dāng)兩個(gè)解決方案“交配”并產(chǎn)生后代時(shí),就相當(dāng)于發(fā)生了交叉。而當(dāng)單一的解決方案稍微有所改變時(shí)就相當(dāng)于引發(fā)了突變。
類似于模擬退火法,GA(遺傳算法)也是隨機(jī)的。在交叉過程中會(huì)由隨機(jī)性來決定父本和母本會(huì)遺產(chǎn)什么樣的特征給子代。
你可以在下面的URL中在線查看TSP(旅行推銷員問題)的遺傳算法應(yīng)用程序:
http://www.heatonresearch.com...
為了使用Encog框架中自帶的遺傳算法,你必須定義變異和交叉這兩個(gè)操作,它們的實(shí)現(xiàn)取決于你正在尋找的解決方案的類型。
下面的代碼定義了TSP問題的突變操作。
genetic.mutate = function performMutation(data) { var iswap1 = Math.floor(Math.random() * data.length); var iswap2 = Math.floor(Math.random() * data.length); // 不相等時(shí) if (iswap1 == iswap2) { // 繼續(xù)下一步 // 但是,不要出界 if (iswap1 > 0) { iswap1--; } else { iswap1++; } } var t = data[iswap1]; data[iswap1] = data[iswap2]; data[iswap2] = t; }這段代碼與模擬退火法的隨機(jī)化操作非常類似。本質(zhì)上,程序?qū)α斜碇械膬蓚€(gè)城市進(jìn)行了交換操作。所以我們必須保證這兩個(gè)隨機(jī)城市是不相同的,因?yàn)橐坏┫嗤?,這兩個(gè)城市就不會(huì)發(fā)生交換。
交叉操作比較復(fù)雜。下面的代碼實(shí)現(xiàn)了交叉函數(shù)。
genetic.crossover = function performCrossover(motherArray, fatherArray, child1Array, child2Array) { // 染色體(此處泛指遺傳特性)必須在兩個(gè)位置被切割,并確定他們。 var cutLength = motherArray.length / 5; var cutpoint1 = Math.floor(Math.random() * (motherArray.length - cutLength)); var cutpoint2 = cutpoint1 + cutLength; // 記錄這兩個(gè)子代中每一個(gè)染色體中所帶的基因,默認(rèn)為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); } } };上面代碼的原理如下:在城市的道路上取兩個(gè)“切點(diǎn)”,這就意味著把父本和母本的特性都各自分割成了三份,父本和母本有著相同的切點(diǎn)。這些切割的規(guī)模是隨機(jī)的,然后通過交換父輩的三份來創(chuàng)建兩個(gè)子代。例如,觀察下面的父本和母本。
[m1, m2, m3 ,m4, m5, m6, m7, m8, m9, m10] [f1, f2, f3 ,f4, f5, f6, f7, f8, f9, f10]現(xiàn)在我們將這些切點(diǎn)加進(jìn)去。
[m1, m2] [m3 ,m4, m5, m6] [m7, m8, m9, m10] [f1, f2] [f3 ,f4, f5, f6] [f7, f8, f9, f10]如此會(huì)產(chǎn)生下面兩個(gè)子代。
[m1, m2] [f3 ,f4, f5, f6] [m7, m8, m9, m10] [f1, f2] [m3 ,m4, m5, m6] [f7, f8, f9, f10]根據(jù)另一個(gè)隨機(jī)事件,每個(gè)解決方案都可能會(huì)發(fā)生突變。突變就是將“新產(chǎn)生的信息”添加到種群遺傳的過程。否則就是簡(jiǎn)單的傳遞已經(jīng)存在的遺傳特征。
XOR神經(jīng)網(wǎng)絡(luò)神經(jīng)網(wǎng)絡(luò)是另外一種基于生物學(xué)的機(jī)器學(xué)習(xí)方法,它非常松散地建立在人腦的基礎(chǔ)上。神經(jīng)網(wǎng)絡(luò)是由神經(jīng)突觸連接的神經(jīng)元組成的,每一個(gè)突觸本身都具有權(quán)重,眾多突觸的權(quán)重構(gòu)成了神經(jīng)網(wǎng)絡(luò)的記憶。如下所示的神經(jīng)網(wǎng)絡(luò)示意圖。
圖 7:一個(gè)神經(jīng)網(wǎng)絡(luò)如圖所示的結(jié)構(gòu),其實(shí)就是我們下一節(jié)要?jiǎng)?chuàng)建的神經(jīng)網(wǎng)絡(luò),你可以在上面的神經(jīng)網(wǎng)絡(luò)中看到有一個(gè)輸入層和一個(gè)輸出層。神經(jīng)網(wǎng)絡(luò)接收來自輸入層的刺激,并交由輸出層進(jìn)行相應(yīng)輸出。神經(jīng)網(wǎng)絡(luò)內(nèi)部也可能存在隱藏層,該層中同樣包含有神經(jīng)元。隱藏層也有助于信息的處理。XOR神經(jīng)網(wǎng)絡(luò)(異或神經(jīng)網(wǎng)絡(luò)),有兩個(gè)輸入和一個(gè)輸出。兩個(gè)輸入端接收布爾值(0或者1),輸出神經(jīng)元也輸出布爾值。其目的就是讓神經(jīng)網(wǎng)絡(luò)實(shí)現(xiàn)和XOR(異或運(yùn)算)操作符相同的功能。
0 XOR 0 = 0 1 XOR 0 = 1 0 XOR 1 = 1 1 XOR 1 = 0當(dāng)兩個(gè)輸入不一致時(shí),異或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個(gè)迭代訓(xùn)練來教神經(jīng)網(wǎng)絡(luò)執(zhí)行XOR操作,神經(jīng)網(wǎng)絡(luò)的初始化權(quán)重是從隨機(jī)數(shù)字開始的。數(shù)據(jù)訓(xùn)練的過程中會(huì)逐漸調(diào)整權(quán)重,以產(chǎn)生期望的輸出。神經(jīng)網(wǎng)絡(luò)的隨機(jī)部分是權(quán)重的初始化量值。除了這些,神經(jīng)網(wǎng)絡(luò)是決定性的。給定相同的權(quán)重和輸入,神經(jīng)網(wǎng)絡(luò)始終會(huì)產(chǎn)生相同的輸出。
在上面的輸出中,你可能會(huì)注意到輸出的結(jié)果并不是非常精確的。因?yàn)樯窠?jīng)網(wǎng)絡(luò)永遠(yuǎn)不會(huì)為1的輸出精確到1.0。由于開始的權(quán)重是隨機(jī)的,所以你不可能從這個(gè)神經(jīng)網(wǎng)絡(luò)中得到兩個(gè)相同的結(jié)果。另外,由于一些隨機(jī)的初始化權(quán)重量值是完全不可訓(xùn)練的,正因如此,有時(shí)你會(huì)看到XOR神經(jīng)網(wǎng)絡(luò)達(dá)到了5000的最大訓(xùn)練值,然而就還是放棄了。
你可以在下面URL中看到這個(gè)案例的運(yùn)行實(shí)例。
http://www.heatonresearch.com...
我們現(xiàn)在來觀察這個(gè)程序是如何構(gòu)建的。首先,我們創(chuàng)建輸入和理想輸出。
var XOR_INPUT = [ [0,0], [1,0], [0,1], [1,1] ]; var XOR_IDEAL = [ [0], [1], [1], [0] ];上面的兩個(gè)數(shù)組分別包含了輸入和理想輸出。這個(gè)“真相表”將被用來訓(xùn)練神經(jīng)網(wǎng)絡(luò)。
接著我們來創(chuàng)建一個(gè)三層神經(jīng)網(wǎng)絡(luò)。輸入層有兩個(gè)神經(jīng)元,隱藏的神經(jīng)元有三個(gè),輸出層有一個(gè)神經(jīng)元。
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();創(chuàng)建和隨機(jī)化神經(jīng)網(wǎng)絡(luò)的時(shí)候,將會(huì)調(diào)用隨機(jī)化函數(shù)將權(quán)重填充為隨機(jī)值。
訓(xùn)練神經(jīng)網(wǎng)絡(luò)有很多不同方法,對(duì)于本例,我們會(huì)采用RPROP(一種基于彈性反向傳播的神經(jīng)網(wǎng)絡(luò)算法原理)來實(shí)現(xiàn)。
var train = ENCOG.PropagationTrainer.create(network,XOR_INPUT,XOR_IDEAL,"RPROP",0,0);現(xiàn)在,我們將通過迭代訓(xùn)練進(jìn)行循環(huán)處理,直到出錯(cuò)率降到可以接受的水平線以下為止。
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);現(xiàn)在神經(jīng)網(wǎng)絡(luò)的訓(xùn)練已完成,我們將對(duì)輸入數(shù)組進(jìn)行循環(huán)處理,并將其提交給神經(jīng)網(wǎng)絡(luò)。神經(jīng)網(wǎng)絡(luò)會(huì)顯示出對(duì)應(yīng)輸出。
var input = [0,0]; var output = []; con.writeLine("Testing neural network"); for(var i=0;i這是對(duì)神經(jīng)網(wǎng)絡(luò)的一個(gè)非常簡(jiǎn)單的介紹,我還做了一個(gè)關(guān)于Java和C#神經(jīng)網(wǎng)絡(luò)內(nèi)容,你如果只對(duì)神經(jīng)網(wǎng)絡(luò)感興趣,下面的內(nèi)容應(yīng)該會(huì)有所幫助。
Introduction to Neural Networks for Java Introduction to Neural Networks for C# 此外,如果你想了解神經(jīng)網(wǎng)絡(luò)的基本介紹,下面的文章可能會(huì)對(duì)你有用。
http://www.heatonresearch.com...
神經(jīng)網(wǎng)絡(luò)分類現(xiàn)在我們來看一個(gè)稍微復(fù)雜些的神經(jīng)網(wǎng)絡(luò)分類,這個(gè)神經(jīng)網(wǎng)絡(luò)將會(huì)學(xué)習(xí)如何進(jìn)行分類。我們會(huì)學(xué)到神經(jīng)網(wǎng)絡(luò)是如何通過訓(xùn)練數(shù)據(jù)集來學(xué)習(xí)對(duì)數(shù)據(jù)點(diǎn)進(jìn)行分類,并且能夠?qū)τ?xùn)練數(shù)據(jù)集中不存在的數(shù)據(jù)點(diǎn)進(jìn)行分類。
你可以在下面的URL中在線運(yùn)行這個(gè)示例代碼:
http://www.heatonresearch.com...
本案例將利用前饋神經(jīng)網(wǎng)絡(luò)原理進(jìn)行分類。為了充分利用這個(gè)程序,我們?cè)诋媹D區(qū)域繪制了幾個(gè)彩色點(diǎn)。必須保證你至少有兩個(gè)彩色點(diǎn),否則程序就無法進(jìn)行分類。一旦你開始畫點(diǎn)并且點(diǎn)擊begin(開始),則神經(jīng)網(wǎng)絡(luò)也就開始訓(xùn)練了。你將看到你提供的數(shù)據(jù)點(diǎn)附近的其他區(qū)域是如何進(jìn)行分類的。
上一個(gè)神經(jīng)網(wǎng)絡(luò)案例有是兩個(gè)輸入神經(jīng)元和三個(gè)輸出神經(jīng)元的。隱藏層的結(jié)構(gòu)是由drop列表決定的。舉例來說,如果你選擇了2:10:10:3,你將會(huì)得到一個(gè)與以下圖像相似的網(wǎng)絡(luò),這個(gè)網(wǎng)絡(luò)有兩個(gè)隱藏層,每層有10個(gè)神經(jīng)元。
輸入神經(jīng)元代表一個(gè)點(diǎn)的x坐標(biāo)和y坐標(biāo)。為了繪出上面的圖像,該程序在x坐標(biāo)和y坐標(biāo)的網(wǎng)格上進(jìn)行循環(huán)處理。每個(gè)網(wǎng)格組件都會(huì)對(duì)神經(jīng)網(wǎng)絡(luò)進(jìn)行查詢。左上角的細(xì)胞是[0,0],右下角的細(xì)胞坐標(biāo)是[1,1]。對(duì)于具有sigmoid(常用的非線性激活函數(shù))激活函數(shù)的神經(jīng)網(wǎng)絡(luò)數(shù)據(jù),通??梢栽?到1之間的范圍內(nèi)接受輸入,因此這個(gè)范圍的表現(xiàn)良好。中心點(diǎn)是[0.5,0.5]。
神經(jīng)網(wǎng)絡(luò)的輸出即正方形中像素點(diǎn)的RGB顏色值。[0,0,0]表示黑色,[1,1,1]表示白色。當(dāng)你在繪圖區(qū)域畫點(diǎn)時(shí),就等同于在提供訓(xùn)練數(shù)據(jù)。輸入神經(jīng)元將會(huì)根據(jù)你輸入的數(shù)據(jù)訓(xùn)練出放置x坐標(biāo)和y坐標(biāo)的方式。期望或者理想中的輸出應(yīng)該是與你在該位置選擇的顏色近似一致。
讓我們來看一個(gè)簡(jiǎn)單的案例。如果你只畫出兩個(gè)數(shù)據(jù)點(diǎn),那么這個(gè)區(qū)域就會(huì)被分割成兩部分。如下圖所示,你可以看到一個(gè)紅色的數(shù)據(jù)點(diǎn)和一個(gè)藍(lán)色的數(shù)據(jù)點(diǎn)。
圖8:兩個(gè)數(shù)據(jù)點(diǎn)的分類該算法為了讓應(yīng)用程序得到的錯(cuò)誤評(píng)級(jí)比較低,它僅需要保證藍(lán)色數(shù)據(jù)點(diǎn)位于藍(lán)色區(qū)域,而紅色數(shù)據(jù)點(diǎn)位于紅色區(qū)域。其他所有像素點(diǎn)都是基于已知像素點(diǎn)的“猜測(cè)”。但由于這樣已知的數(shù)據(jù)非常少,所以神經(jīng)網(wǎng)絡(luò)很難真正猜到這兩個(gè)區(qū)域之間的邊界到底在哪里。
如果你提供了更多的訓(xùn)練數(shù)據(jù),那你會(huì)得到一個(gè)更加復(fù)雜的形狀。如果你選擇創(chuàng)建一個(gè)雙色的隨機(jī)圖像,那你會(huì)得到與下圖類似的數(shù)據(jù)點(diǎn)。
圖9:多個(gè)數(shù)據(jù)點(diǎn)的分類在此圖中,神經(jīng)網(wǎng)絡(luò)創(chuàng)建了一種更加復(fù)雜的模式試圖來適應(yīng)所有的數(shù)據(jù)點(diǎn)。
你還可以選擇創(chuàng)建一個(gè)復(fù)雜的多顏色模式。下面的案例中為數(shù)據(jù)點(diǎn)隨機(jī)生成了顏色值。神經(jīng)網(wǎng)絡(luò)甚至?xí)㈩伾M(jìn)行混合,試圖做出妥協(xié),以此來盡可能地降低誤差。
圖10:多顏色數(shù)據(jù)點(diǎn)分類此算法甚至有可能學(xué)習(xí)復(fù)雜的相互螺旋的形狀,如下圖所示。
圖11:螺旋數(shù)據(jù)點(diǎn)的分類 延伸閱讀本文介紹了JavaScript中的機(jī)器學(xué)習(xí),如果想了解更多關(guān)于機(jī)器學(xué)習(xí)的知識(shí),那么你可能會(huì)對(duì)下面的鏈接感興趣。
Encog 項(xiàng)目
Encog 維基百科
關(guān)于Encog的更多信息
Facebook上關(guān)于Encog的內(nèi)容
歷史2012年10月16日的第一個(gè)版本,引用文件版本 Encog JS v1.0
翻譯人:白加黑大人,該成員來自云+社區(qū)翻譯社相關(guān)閱讀
原文鏈接:https://www.codeproject.com/A...
原文作者:JeffHeaton
原文譯題:通過JS庫Encog實(shí)現(xiàn)JavaScript機(jī)器學(xué)習(xí)和神經(jīng)學(xué)網(wǎng)絡(luò)Python中Keras深度學(xué)習(xí)庫的回歸教程
從程序員的角度設(shè)計(jì)一個(gè)Java的神經(jīng)網(wǎng)絡(luò)
如何使用 scikit-learn 為機(jī)器學(xué)習(xí)準(zhǔn)備文本數(shù)據(jù)
此文已由作者授權(quán)云加社區(qū)發(fā)布,轉(zhuǎn)載請(qǐng)注明文章出處
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/107363.html
摘要:不能用于機(jī)器學(xué)習(xí)太慢幻覺矩陣操作太難有函數(shù)庫啊,比如只能用于前端開發(fā)開發(fā)者笑了機(jī)器學(xué)習(xí)庫都是開發(fā)者機(jī)器學(xué)習(xí)庫神經(jīng)網(wǎng)絡(luò)神經(jīng)網(wǎng)絡(luò)自然語言處理卷積神經(jīng)網(wǎng)絡(luò)一系列庫神經(jīng)網(wǎng)絡(luò)深度學(xué)習(xí)我們將使用來實(shí)現(xiàn)線性回歸,源代碼在倉庫。 譯者按: AI時(shí)代,不會(huì)機(jī)器學(xué)習(xí)的JavaScript開發(fā)者不是好的前端工程師。 原文: Machine Learning with JavaScript : Part 1 ...
摘要:隨后深度學(xué)習(xí)的研究大放異彩,廣泛應(yīng)用在了圖像處理和語音識(shí)別領(lǐng)域。比如的學(xué)生就用深度學(xué)習(xí)算法贏得年的。深度學(xué)習(xí)和人工智能的春天離人工智能最近的互聯(lián)網(wǎng)公司敏銳嗅到了這一機(jī)遇。 多倫多大學(xué)計(jì)算機(jī)系教授Geoffrey Hinton是Deep Learning的開山鼻祖,我們來講講他的故事。他有個(gè)傳奇的姑姑不過先來說說他姑姑吧,他姑姑Joan Hinton是一個(gè)與中國有關(guān)的具有傳奇經(jīng)歷的人物,中文名...
摘要:接下來,是很關(guān)鍵的一步,如何讓機(jī)器學(xué)習(xí)提升它的準(zhǔn)確率。機(jī)器學(xué)習(xí)的內(nèi)容是用來每一次的數(shù)據(jù),逐步提升神經(jīng)網(wǎng)絡(luò)的預(yù)測(cè)準(zhǔn)確性。每步我們輸出一下機(jī)器學(xué)習(xí)的誤差。 經(jīng)過前期的學(xué)習(xí),這一節(jié)來學(xué)習(xí)稍微綜合一點(diǎn)的,建造一個(gè)完整的神經(jīng)網(wǎng)絡(luò),包括添加神經(jīng)層,計(jì)算誤差,訓(xùn)練步驟,判斷是否在學(xué)習(xí)。 添加層 構(gòu)造添加一個(gè)神經(jīng)層的函數(shù)。 def add_layer(inputs, in_size, out_size...
閱讀 2048·2021-11-22 15:33
閱讀 3057·2021-11-18 10:02
閱讀 2686·2021-11-08 13:16
閱讀 1703·2021-10-09 09:57
閱讀 1448·2021-09-30 09:47
閱讀 2067·2019-08-29 13:05
閱讀 3125·2019-08-29 12:46
閱讀 1065·2019-08-29 12:19