本文中作者為初學(xué)者解釋了如何使用 JavaScript 來(lái)搭建一個(gè)神經(jīng)網(wǎng)絡(luò)。不用擔(dān)心,這不是一份深入介紹隱藏輸入層、激勵(lì)函數(shù)或如何使用 TensorFlow 的復(fù)雜教程,而是一次輕松實(shí)踐。即使你不懂神經(jīng)網(wǎng)絡(luò)背后的深入內(nèi)容,也可以完成這個(gè)簡(jiǎn)單又有趣的實(shí)踐。
前言
機(jī)器學(xué)習(xí)對(duì)我來(lái)說(shuō)是個(gè)特別的存在,讓我一次又一次覺(jué)得,“它實(shí)在太酷了,但我不確定接下來(lái)我是否會(huì)花幾個(gè)月的時(shí)間去學(xué)習(xí)線性代數(shù)和微積分?!?/p>
然而,同許多開(kāi)發(fā)者一樣,我使用 JavaScript 比較得心應(yīng)手,也會(huì)偶爾找一些用 JS 實(shí)現(xiàn)機(jī)器學(xué)習(xí)的例子,但卻看到大量文章和帖子控訴 JS 對(duì)機(jī)器學(xué)習(xí)來(lái)說(shuō)是極其糟糕的語(yǔ)言,這也是不得不承認(rèn)的一個(gè)事實(shí)。
但后來(lái)當(dāng)我發(fā)現(xiàn) Brain.js 時(shí),我被打動(dòng)了。為什么它被人忽略了這么久?!Brain.js 的文檔寫(xiě)得非常清楚,而且易于學(xué)習(xí)。用了30分鐘的入門時(shí)間,然后我就搭建并訓(xùn)練了一個(gè)神經(jīng)網(wǎng)絡(luò)。如果你想直接去 Github 閱讀文檔,我們?cè)谖哪┙o出了地址。
初體驗(yàn)
關(guān)于接下來(lái)工作的主要步驟包括:
創(chuàng)建初始文件
確定你想讓神經(jīng)網(wǎng)絡(luò)做的工作
搭建 Brain.js 并考慮好如何處理訓(xùn)練數(shù)據(jù)和用戶輸入
收集訓(xùn)練數(shù)據(jù)
運(yùn)行神經(jīng)網(wǎng)絡(luò)
評(píng)估結(jié)果
▌1.初始文件
創(chuàng)建一個(gè)新的目錄,然后添加一個(gè) index.html 作為樣板文件。接下來(lái)創(chuàng)建三個(gè) JS 文件:brain.js、training-data.js 和 script.js,當(dāng)然,index.html 文件下面也需要引入這三個(gè)文件。

目前做這么多就足夠了。
現(xiàn)在我們來(lái)看看 Brain.js 的源代碼。將所有代碼復(fù)制并粘貼到你創(chuàng)建的空白 brain.js 文件中,然后點(diǎn)擊保存:4個(gè)文件中的2個(gè)就這樣完成了。
Brain.js 源代碼:
https://raw.githubusercontent.com/harthur-org/brain.js/master/browser.js
▌2. “我的目的是什么?”
接下來(lái)這個(gè)部分很有趣:決定你的機(jī)器要學(xué)習(xí)什么。你可以用這種方式解決不計(jì)其數(shù)的實(shí)際問(wèn)題,如情感分析或圖像識(shí)別。我偶然想到一個(gè)機(jī)器學(xué)習(xí)應(yīng)用,把文本作為輸入信息進(jìn)行處理是很有趣的,因?yàn)槟隳茈S處找到可用作訓(xùn)練的數(shù)據(jù),它們有很多潛在的應(yīng)用場(chǎng)合,所以在這里我們要舉一個(gè)文本分類問(wèn)題的例子:
判斷一條推文的作者是唐納德·特朗普還是金·卡戴珊。
這看起來(lái)可能不是個(gè)用處最廣的應(yīng)用。雖然推文作者識(shí)別器還沒(méi)有強(qiáng)大的吸引點(diǎn),但 Twitter 對(duì)機(jī)器學(xué)習(xí)來(lái)說(shuō)真的是一座寶庫(kù)。一旦進(jìn)行過(guò)訓(xùn)練,我們的神經(jīng)網(wǎng)絡(luò)就可以通過(guò)識(shí)別推文的內(nèi)容模式,來(lái)辨別一條此前從未見(jiàn)過(guò)的推文是出自唐納德·特朗普還是金·卡戴珊。為了實(shí)現(xiàn)這個(gè)目的,我們需要提供盡可能多的訓(xùn)練數(shù)據(jù),把它們復(fù)制并粘貼到我們的 training-data.js 文件中,同時(shí)我們也可以試試自己是否能判斷一些推文的原作者。
▌3.設(shè)置 & 數(shù)據(jù)處理
現(xiàn)在我們還需做的工作就是在 script.js 文件中設(shè)置 Brain.js,并為我們的 training-data.js 文件提供一些訓(xùn)練數(shù)據(jù)。但在此之前,讓我們先來(lái)看看這一切是如何運(yùn)作的。
設(shè)置 Brain.js 是極其簡(jiǎn)單的,我們?cè)谶@里不會(huì)花費(fèi)太多時(shí)間,但關(guān)于如何處理輸入數(shù)據(jù)格式的細(xì)節(jié)仍需要我們優(yōu)先處理。我們先看一下文檔中的例子,很清晰地展示了這一過(guò)程:
1letnet=newbrain.NeuralNetwork(); 2 3 4net.train([ 5 6{ 7 8Input:{r:0.03,g:0.7,b:0.5}, 910Output:{black:1}1112},{1314Input:{r:0.16,g:0.09,b:0.2},1516Output:{black:1}1718},{1920Input:{r:0.5,b:0.5},2122Output:{black:1}2324}2526]);27282930letoutput=net.run({r:1,g:0.4,b:0});
首先,上面的例子是一個(gè)可以正常運(yùn)行的 AI(它會(huì)查看給定的顏色,然后告訴你在該顏色上黑色文本和白色文本哪個(gè)更易于辨認(rèn))。希望可以借此體現(xiàn) Brain.js 有多易于使用。我們只需先將它實(shí)例化,然后進(jìn)行訓(xùn)練,最后運(yùn)行,就是這么簡(jiǎn)單。如果你將訓(xùn)練數(shù)據(jù)嵌入文件內(nèi)部,僅僅需要三行代碼,是不是很酷!
現(xiàn)在我們講一下數(shù)據(jù)的訓(xùn)練。在上面的例子中,除了訓(xùn)練數(shù)據(jù)的整體格式為input: {}, output: {},還有兩點(diǎn)需要注意。
第一,數(shù)據(jù)無(wú)需統(tǒng)一的長(zhǎng)度。如上面代碼中的第11行,只傳入了 R 和 B 的值,而另兩條輸入傳入了 R、G 和 B 的值。同時(shí),雖然上面的例子把對(duì)象作為輸入,值得一提的是你也可以使用數(shù)組。我之所以特別強(qiáng)調(diào)這一點(diǎn),是因?yàn)槲覀儠?huì)在該項(xiàng)目中傳入長(zhǎng)度不等的數(shù)組。
第二,這些都不是有效的 RGB 值。如果你真的采用這些值,每一組都會(huì)呈現(xiàn)出黑色。這是因?yàn)橐胱?Brain.js 正常工作,輸入值必須在0和1之間。因此,為了能使其正常工作,每個(gè)顏色都需要進(jìn)行處理(只需用一個(gè)函數(shù)將它除以255,即 RGB 的最大值)。接下來(lái)我們也需要做類似的工作。
3.1 編碼
因此,如果我們想讓神經(jīng)網(wǎng)絡(luò)把推文(例如:字符串)作為輸入,我們需要用一個(gè)類似的函數(shù)將它們進(jìn)行處理(即下面提到的encode()方法),它會(huì)把每個(gè)字符轉(zhuǎn)化為0和1之間的值,并存入數(shù)組中。幸運(yùn)的是,JavaScript 有一個(gè)原生方法charCodeAt(),它可以將任何字符轉(zhuǎn)化成 ASCII 碼。所以我們會(huì)采取這種方式,把結(jié)果除以 EASCII 的最大值255,該操作可以保證我們得到的值均小于1。
3.2 處理訓(xùn)練數(shù)據(jù)
我們會(huì)將訓(xùn)練數(shù)據(jù)以純文本的形式進(jìn)行存儲(chǔ),而最終喂給 AI 的數(shù)據(jù)是編碼后的數(shù)據(jù)。因此我們需要另一個(gè)函數(shù)(即下面所說(shuō)的processTrainingData()方法),該函數(shù)會(huì)對(duì)我們的訓(xùn)練數(shù)據(jù)執(zhí)行上文提到的編碼處理,有選擇地將文本轉(zhuǎn)化成編碼字符,然后返回可以完美配合 Brain.js 的訓(xùn)練數(shù)據(jù)的數(shù)組。
那么到這兒的代碼如下(這部分代碼都將寫(xiě)入 'script.js' 文件):
1lettrainedNet; 2 3 4 5functionencode(arg){ 6 7returnarg.split('').map(x=>(x.charCodeAt(0)/255)); 8 9}10111213functionprocessTrainingData(data){1415returndata.map(d=>{1617return{1819input:encode(d.input),2021output:d.output2223}2425})2627}28293031functiontrain(data){3233letnet=newbrain.NeuralNetwork();3435net.train(processTrainingData(data));3637trainedNet=net.toFunction();3839console.log('Finishedtraining...');4041};42434445functionexecute(input){4647letresults=trainedNet(encode(input));4849letoutput;5051results.trump>results.kardashian?output='Trump':output='Kardashian';5253returnoutput;5455}56575859train(trainingData);
這里要強(qiáng)調(diào)一個(gè)上述文檔例子中未涉及的函數(shù),那就是train(),該函數(shù)可將訓(xùn)練好的神經(jīng)網(wǎng)絡(luò)存入全局變量trainedNet 中。這一操作便于我們每次使用神經(jīng)網(wǎng)絡(luò)時(shí)無(wú)需重新訓(xùn)練。一旦神經(jīng)網(wǎng)絡(luò)被訓(xùn)練好并存入變量中,我們就可以像調(diào)用函數(shù)一樣直接調(diào)用網(wǎng)絡(luò),并將編碼后的數(shù)據(jù)傳入 AI 中(如上面execute() 函數(shù)中的第 45 行代碼)。
▌4.訓(xùn)練
最后就是有關(guān)我們的訓(xùn)練數(shù)據(jù)了。就像我在上面提到的,我們將推文存儲(chǔ)為文本的形式,然后緊接著把它們編碼成數(shù)值,這一操作可以讓你在復(fù)制粘貼訓(xùn)練數(shù)據(jù)時(shí)方便很多。無(wú)需擔(dān)心格式問(wèn)題,直接在文本中粘貼新的一行就好了。
1consttrainingData=[ 2 3{ 4 5input:"InsideChi'snursery", 6 7output:{kardashian:1} 8 9},{1011input:"WhyIdyedmyhairpink",1213output:{kardashian:1}1415},{1617input:"FeelingBlue(wearing@kkwbeautypowdercontourinmedium&darkcontourkitaseyeshadow,&anewlipcomingsoon)",1819output:{kardashian:1}2021},{2223input:"Iwillbeinterviewedby@JudgeJeanineon@FoxNewsat9:00P.M.Enjoy!",2425output:{trump:1}2627},{2829input:"DemMemo:FBIdidnotdisclosewhotheclientswere-theClintonCampaignandtheDNC.Wow!",3031output:{trump:1}3233},{3435input:"ThankyoutothegreatmenandwomenoftheUnitedStates@SecretServiceforajobwelldone!",3637output:{trump:1}3839}4041]
把這段代碼寫(xiě)進(jìn) 'training-data.js' 文件,我們就大功告成了!
注意:上面的代碼示例中,只展示了每個(gè)人的3條樣本,但實(shí)際上我分別引入了10條;我只是不想占用太多篇幅。當(dāng)然,你提供的訓(xùn)練數(shù)據(jù)量越大,神經(jīng)網(wǎng)絡(luò)的精度也會(huì)越高,所以試著改變引入的數(shù)據(jù)量,來(lái)看看對(duì)結(jié)果有哪些影響吧。
▌5.執(zhí)行
現(xiàn)在,就可以運(yùn)行這個(gè)訓(xùn)練好的神經(jīng)網(wǎng)絡(luò)了。你只需在 'script.js' 文件的最下面加上一行調(diào)用execute() 的代碼,然后傳入一條特朗普或卡戴珊的推文;記得使用 console.log。這里有一則卡戴珊的推文,這條推文不在我的訓(xùn)練數(shù)據(jù)中:
1console.log(execute("Thesearen'treal.KanyewouldneverwriteYeezyontheside"));
接下來(lái)在本地打開(kāi)你的 index.html 頁(yè)面,查看控制臺(tái):

就是這樣,神經(jīng)網(wǎng)絡(luò)正確辨別了一條之前從未見(jiàn)過(guò)的、來(lái)自卡戴珊的推文,確定度達(dá)到了80%.
現(xiàn)在我們?cè)儆靡粭l特朗普的推文試試:
1console.log(execute("WhetherweareRepublicanorDemocrat,wemustnowfocusonstrengtheningBackgroundChecks!"));
結(jié)果如下:

▌6.評(píng)估
現(xiàn)在你已經(jīng)有一個(gè)可以訓(xùn)練任何文本的神經(jīng)網(wǎng)絡(luò)了!你可以使用它輕松辨別一封郵件或公司在線評(píng)價(jià)的情感及態(tài)度,識(shí)別垃圾郵件,將博客文章分類,判別一則消息是否緊急等等,這一點(diǎn)非常有趣,這個(gè)神經(jīng)網(wǎng)絡(luò)可以用在很多類似根據(jù)所寫(xiě)內(nèi)容判斷作者的任務(wù)中。
即使你不想另外創(chuàng)建一個(gè)由機(jī)器學(xué)習(xí)驅(qū)動(dòng)的全新工具,這次實(shí)踐對(duì)你來(lái)說(shuō)也是一份寶貴的開(kāi)發(fā)經(jīng)驗(yàn)。也許什么時(shí)候它將會(huì)派上用場(chǎng),甚至可能在未來(lái)為你開(kāi)拓新的機(jī)遇。
-
神經(jīng)網(wǎng)絡(luò)
+關(guān)注
關(guān)注
42文章
4840瀏覽量
108127 -
javascript
+關(guān)注
關(guān)注
0文章
526瀏覽量
56508 -
機(jī)器學(xué)習(xí)
+關(guān)注
關(guān)注
67文章
8560瀏覽量
137196
原文標(biāo)題:用JavaScript創(chuàng)建神經(jīng)網(wǎng)絡(luò)的有趣教程,一定要讓你知道!
文章出處:【微信號(hào):rgznai100,微信公眾號(hào):rgznai100】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
人工神經(jīng)網(wǎng)絡(luò)原理及下載
【案例分享】ART神經(jīng)網(wǎng)絡(luò)與SOM神經(jīng)網(wǎng)絡(luò)
如何構(gòu)建神經(jīng)網(wǎng)絡(luò)?
基于BP神經(jīng)網(wǎng)絡(luò)的PID控制
如何使用Keras框架搭建一個(gè)小型的神經(jīng)網(wǎng)絡(luò)多層感知器
輕量化神經(jīng)網(wǎng)絡(luò)的相關(guān)資料下載
卷積神經(jīng)網(wǎng)絡(luò)一維卷積的處理過(guò)程
JavaScript 實(shí)現(xiàn)神經(jīng)網(wǎng)絡(luò)應(yīng)用教程
如何使用numpy搭建一個(gè)卷積神經(jīng)網(wǎng)絡(luò)詳細(xì)方法和程序概述
用Python從頭實(shí)現(xiàn)一個(gè)神經(jīng)網(wǎng)絡(luò)來(lái)理解神經(jīng)網(wǎng)絡(luò)的原理1
用Python從頭實(shí)現(xiàn)一個(gè)神經(jīng)網(wǎng)絡(luò)來(lái)理解神經(jīng)網(wǎng)絡(luò)的原理2
用Python從頭實(shí)現(xiàn)一個(gè)神經(jīng)網(wǎng)絡(luò)來(lái)理解神經(jīng)網(wǎng)絡(luò)的原理3
用Python從頭實(shí)現(xiàn)一個(gè)神經(jīng)網(wǎng)絡(luò)來(lái)理解神經(jīng)網(wǎng)絡(luò)的原理4
如何使用JavaScript來(lái)搭建一個(gè)神經(jīng)網(wǎng)絡(luò)
評(píng)論