很少有程序員不對這里或者那里所包含的人工智能編程所吸引,然而,許多對AI感興趣的程序員很快就因其中包含的算法的復(fù)雜性而退卻。在本文中,我們將討論一個能大大簡化這種復(fù)雜性的Java開源工程。 Java面向?qū)ο蟮纳窠?jīng)網(wǎng)絡(luò)(JOONE)是一開源工程,它提供給Java程序員一個高適應(yīng)性的神經(jīng)網(wǎng)絡(luò)。該JOONE工程源代碼由LGPL所保護。簡言之,這意味著源代碼是可自由使用的而且你不需要支付版稅就可以使用JOONE。JOONE可以從http://joone./處下載。 JOONE能允許你輕易地從一個Java程序中創(chuàng)建神經(jīng)網(wǎng)絡(luò)。JOONE支持許多特征,如多線程和分布式處理。這意味著JOONE能利用多處理機計算機和多臺計算機的優(yōu)勢來進行分布式處理。
從圖1中你可以看出,神經(jīng)原由一個內(nèi)核細(xì)胞和幾個長長的稱為觸角的連接器組成。神經(jīng)原之間依靠這些觸角進行連接。無論是生物學(xué)的還是人工的神經(jīng)網(wǎng)絡(luò),都通過觸角把信號從一個神經(jīng)原傳遞到另一個神經(jīng)原來工作。 訓(xùn)練神經(jīng)網(wǎng)絡(luò)
正如你從上表中看到的,XOR運算的結(jié)果是只有當(dāng)X和Y具有不同值時,結(jié)果才為真(1)。其它情況下,XOR運算結(jié)果均為假(0)。默認(rèn)地,JOONE從存儲在你的系統(tǒng)中的文本文件中取得輸入。這些文本文件通過使用一種稱為FileInputSynapse的特殊觸角來讀取。為了訓(xùn)練XOR運算問題,你必須建立一個輸入文件-該文件包含上面顯示的數(shù)據(jù)。該文件顯示在列表1中。 列表1:為解決XOR問題的輸入文件的內(nèi)容 0.0;0.0;0.0 0.0;1.0;1.0 1.0;0.0;1.0 1.0;1.0;0.0 我們現(xiàn)在分析一個簡單的程序,它指導(dǎo)JOONE來識別XOR運算并產(chǎn)生正確的結(jié)果。我們現(xiàn)在分析訓(xùn)練該神經(jīng)網(wǎng)絡(luò)必須被處理的過程。訓(xùn)練過程包括把XOR問題提交給神經(jīng)網(wǎng)絡(luò),然后觀察結(jié)果。如果這個結(jié)果不是所預(yù)期的,該訓(xùn)練算法將調(diào)整存儲在觸角中的重量。在神經(jīng)網(wǎng)絡(luò)的實際輸出和預(yù)料的輸出之間的差距稱為誤差。訓(xùn)練將繼續(xù)到誤差小于一個可接受值為止。這個級別通常是一個百分?jǐn)?shù),如10%。我們現(xiàn)在分析必須用于訓(xùn)練一個神經(jīng)網(wǎng)絡(luò)的代碼。 訓(xùn)練過程通過建立神經(jīng)網(wǎng)絡(luò)開始,同時也必須創(chuàng)建隱蔽的輸入層和輸出層。
每個層被使用JOONE對象SigmoidLayer創(chuàng)建。Sigmoidlayer基于自然對數(shù)生成一個輸出。JOONE還包含另外的層,而不是你可能選擇使用的S形的層類型。 下一步,每一層被賦于一個名字。這些名字將有助于后面在調(diào)試期間識別該層。
現(xiàn)在必須定義每個層。我們將指定在每一層中的"行"號。該"行"號對應(yīng)于這一層中的神經(jīng)原的數(shù)目。
從上面的代碼看出,輸入層有兩個神經(jīng)原,隱蔽層有三個隱蔽神經(jīng)原,輸出層包含一個神經(jīng)原。這對于神經(jīng)網(wǎng)絡(luò)包含兩個輸入神經(jīng)原和一個輸出神經(jīng)原是具有重要意義的,因為XOR運算符接收兩個參數(shù)而產(chǎn)生一個結(jié)果。 為使用該神經(jīng)原層,我們也必須創(chuàng)建觸角。在本例中,我們要使用多個觸角。這些觸角用下面的代碼實現(xiàn)。
就象神經(jīng)原層的情況一樣,觸角也可能命名以有助于程序的調(diào)試。下面的代碼命名新建的觸角。
最后,我們必須把觸角聯(lián)接到適當(dāng)神經(jīng)原層。下面的代碼實現(xiàn)這一點。
現(xiàn)在既然神經(jīng)網(wǎng)絡(luò)已被創(chuàng)建,我們必須創(chuàng)建一個用于調(diào)節(jié)該神經(jīng)網(wǎng)絡(luò)的監(jiān)視器對象。下面的代碼創(chuàng)建監(jiān)視器對象。
學(xué)習(xí)速度和動力作為參數(shù)以用于指定訓(xùn)練的產(chǎn)生方式。JOONE利用backpropagation學(xué)習(xí)算法。要更多了解關(guān)于學(xué)習(xí)速度或者動力的信息,你應(yīng)該參考backpropagation算法。 這個監(jiān)視器對象應(yīng)該被賦值給每一個神經(jīng)原層。下面的代碼實現(xiàn)這一點。
就象許多Java對象本身一樣,JOONE監(jiān)視器允許聽者可以添加到它上面去。隨著訓(xùn)練的進行,JOONE將通知聽者有關(guān)訓(xùn)練進程的信息。在這個簡單的例子中,我們使用:
我們現(xiàn)在必須建立輸入觸角。如前所述,我們將使用一個FileInputSynapse來讀取一個磁盤文件。磁盤文件不是JOONE唯一能夠接受的輸入種類。JOONE對于不同的輸入源具有很強的靈活性。為使JOONE能夠接收其它輸入類型,你只需創(chuàng)建一個新的觸角來接受輸入。在本例中,我們將簡單地使用FileInputSynapse。FileInputSynapse首先被實例化。
然后,必須通知FileInputSynapse要使用哪些列。列表1中顯示的文件使用了輸入數(shù)據(jù)的前兩列。下面代碼建立起前兩列用于輸入到神經(jīng)網(wǎng)絡(luò)。
然后,我們必須提供輸入文件的名字,這個名字直接來源于用戶接口。然后,提供一個編輯控件用于收集輸入文件的名字。下面代碼為FileInputSynapse設(shè)置文件名。
如前所述,一個觸角僅是一個神經(jīng)原層之間的數(shù)據(jù)導(dǎo)管。FileInputSynapse正是這里的數(shù)據(jù)導(dǎo)管,通過它數(shù)據(jù)進入到神經(jīng)網(wǎng)絡(luò)。為了更容易實現(xiàn)這點,我們必須要把FileInputSynapse加到神經(jīng)網(wǎng)絡(luò)的輸入層。這由下面一行實現(xiàn)。
現(xiàn)在既然已經(jīng)建立起神經(jīng)網(wǎng)絡(luò),我們必須創(chuàng)建一個訓(xùn)練員和一個監(jiān)視器。訓(xùn)練員用于訓(xùn)練該神經(jīng)網(wǎng)絡(luò),因為該監(jiān)視器通過一個事先設(shè)置好的訓(xùn)練重復(fù)數(shù)來運行這個神經(jīng)網(wǎng)絡(luò)。對于每一次訓(xùn)練重復(fù),數(shù)據(jù)被提供到神經(jīng)網(wǎng)絡(luò),然后就可以觀察到結(jié)果。該神經(jīng)網(wǎng)絡(luò)的權(quán)重(存儲在穿梭在神經(jīng)原層之間的觸角連接中)將根據(jù)誤差作適當(dāng)調(diào)整。隨著訓(xùn)練的進行,誤差級將下降。下列代碼建立訓(xùn)練員并把它依附到監(jiān)視器。
你會記得列表1中提供的輸入文件包含三個列。到目前為止,我們僅僅使用了第一、二列,它們指定了到神經(jīng)網(wǎng)絡(luò)的輸入。第三列包含當(dāng)提供給神經(jīng)網(wǎng)絡(luò)第一列中的數(shù)字時的期盼的輸出值。我們必須使得訓(xùn)練員能夠存取該列以便能確定誤差。該錯誤是神經(jīng)網(wǎng)絡(luò)的實際輸出和期盼的輸出之間的差距。下列代碼創(chuàng)建另外一個FileInputSynapse并作好準(zhǔn)備以讀取與前面相同的輸入文件。
這時,我們想指向在第三列的FileInputSynapse。下列代碼實現(xiàn)了這一點,然后讓訓(xùn)練員使用這個FileInputSynapse。
最后,訓(xùn)練員被連結(jié)到神經(jīng)網(wǎng)絡(luò)輸出層,這將使訓(xùn)練員接收神經(jīng)網(wǎng)絡(luò)的輸出。
我們現(xiàn)在已為所有的層準(zhǔn)備好后臺線程,包括訓(xùn)練員。
最后,我們?yōu)橛?xùn)練設(shè)置一些參數(shù)。我們指定在輸入文件中共有四行,而且想訓(xùn)練20,000個周期,而且還在不段學(xué)習(xí)。如果你設(shè)置學(xué)習(xí)參數(shù)為false,該神經(jīng)網(wǎng)絡(luò)將簡單地處理輸入并不進行學(xué)習(xí)。我們將在下一節(jié)討論輸入處理。
現(xiàn)在我們已經(jīng)為訓(xùn)練過程作好準(zhǔn)備。調(diào)用監(jiān)視器的Go方法將在后臺啟動訓(xùn)練過程。
神經(jīng)網(wǎng)絡(luò)現(xiàn)在將要被訓(xùn)練20,000個周期。當(dāng)神經(jīng)網(wǎng)絡(luò)訓(xùn)練完成,誤差層應(yīng)該在一個合理的低級別上。一般低于10%的誤差級是可接受的。 訓(xùn)練神經(jīng)網(wǎng)絡(luò)
正如你從上表中看到的,XOR運算的結(jié)果是只有當(dāng)X和Y具有不同值時,結(jié)果才為真(1)。其它情況下,XOR運算結(jié)果均為假(0)。默認(rèn)地,JOONE從存儲在你的系統(tǒng)中的文本文件中取得輸入。這些文本文件通過使用一種稱為FileInputSynapse的特殊觸角來讀取。為了訓(xùn)練XOR運算問題,你必須建立一個輸入文件-該文件包含上面顯示的數(shù)據(jù)。該文件顯示在列表1中。 列表1:為解決XOR問題的輸入文件的內(nèi)容 0.0;0.0;0.0 0.0;1.0;1.0 1.0;0.0;1.0 1.0;1.0;0.0 我們現(xiàn)在分析一個簡單的程序,它指導(dǎo)JOONE來識別XOR運算并產(chǎn)生正確的結(jié)果。我們現(xiàn)在分析訓(xùn)練該神經(jīng)網(wǎng)絡(luò)必須被處理的過程。訓(xùn)練過程包括把XOR問題提交給神經(jīng)網(wǎng)絡(luò),然后觀察結(jié)果。如果這個結(jié)果不是所預(yù)期的,該訓(xùn)練算法將調(diào)整存儲在觸角中的重量。在神經(jīng)網(wǎng)絡(luò)的實際輸出和預(yù)料的輸出之間的差距稱為誤差。訓(xùn)練將繼續(xù)到誤差小于一個可接受值為止。這個級別通常是一個百分?jǐn)?shù),如10%。我們現(xiàn)在分析必須用于訓(xùn)練一個神經(jīng)網(wǎng)絡(luò)的代碼。 訓(xùn)練過程通過建立神經(jīng)網(wǎng)絡(luò)開始,同時也必須創(chuàng)建隱蔽的輸入層和輸出層。
每個層被使用JOONE對象SigmoidLayer創(chuàng)建。Sigmoidlayer基于自然對數(shù)生成一個輸出。JOONE還包含另外的層,而不是你可能選擇使用的S形的層類型。 下一步,每一層被賦于一個名字。這些名字將有助于后面在調(diào)試期間識別該層。
現(xiàn)在必須定義每個層。我們將指定在每一層中的"行"號。該"行"號對應(yīng)于這一層中的神經(jīng)原的數(shù)目。
從上面的代碼看出,輸入層有兩個神經(jīng)原,隱蔽層有三個隱蔽神經(jīng)原,輸出層包含一個神經(jīng)原。這對于神經(jīng)網(wǎng)絡(luò)包含兩個輸入神經(jīng)原和一個輸出神經(jīng)原是具有重要意義的,因為XOR運算符接收兩個參數(shù)而產(chǎn)生一個結(jié)果。 為使用該神經(jīng)原層,我們也必須創(chuàng)建觸角。在本例中,我們要使用多個觸角。這些觸角用下面的代碼實現(xiàn)。
就象神經(jīng)原層的情況一樣,觸角也可能命名以有助于程序的調(diào)試。下面的代碼命名新建的觸角。
最后,我們必須把觸角聯(lián)接到適當(dāng)神經(jīng)原層。下面的代碼實現(xiàn)這一點。
現(xiàn)在既然神經(jīng)網(wǎng)絡(luò)已被創(chuàng)建,我們必須創(chuàng)建一個用于調(diào)節(jié)該神經(jīng)網(wǎng)絡(luò)的監(jiān)視器對象。下面的代碼創(chuàng)建監(jiān)視器對象。
學(xué)習(xí)速度和動力作為參數(shù)以用于指定訓(xùn)練的產(chǎn)生方式。JOONE利用backpropagation學(xué)習(xí)算法。要更多了解關(guān)于學(xué)習(xí)速度或者動力的信息,你應(yīng)該參考backpropagation算法。 這個監(jiān)視器對象應(yīng)該被賦值給每一個神經(jīng)原層。下面的代碼實現(xiàn)這一點。
就象許多Java對象本身一樣,JOONE監(jiān)視器允許聽者可以添加到它上面去。隨著訓(xùn)練的進行,JOONE將通知聽者有關(guān)訓(xùn)練進程的信息。在這個簡單的例子中,我們使用:
我們現(xiàn)在必須建立輸入觸角。如前所述,我們將使用一個FileInputSynapse來讀取一個磁盤文件。磁盤文件不是JOONE唯一能夠接受的輸入種類。JOONE對于不同的輸入源具有很強的靈活性。為使JOONE能夠接收其它輸入類型,你只需創(chuàng)建一個新的觸角來接受輸入。在本例中,我們將簡單地使用FileInputSynapse。FileInputSynapse首先被實例化。
然后,必須通知FileInputSynapse要使用哪些列。列表1中顯示的文件使用了輸入數(shù)據(jù)的前兩列。下面代碼建立起前兩列用于輸入到神經(jīng)網(wǎng)絡(luò)。
然后,我們必須提供輸入文件的名字,這個名字直接來源于用戶接口。然后,提供一個編輯控件用于收集輸入文件的名字。下面代碼為FileInputSynapse設(shè)置文件名。
如前所述,一個觸角僅是一個神經(jīng)原層之間的數(shù)據(jù)導(dǎo)管。FileInputSynapse正是這里的數(shù)據(jù)導(dǎo)管,通過它數(shù)據(jù)進入到神經(jīng)網(wǎng)絡(luò)。為了更容易實現(xiàn)這點,我們必須要把FileInputSynapse加到神經(jīng)網(wǎng)絡(luò)的輸入層。這由下面一行實現(xiàn)。
現(xiàn)在既然已經(jīng)建立起神經(jīng)網(wǎng)絡(luò),我們必須創(chuàng)建一個訓(xùn)練員和一個監(jiān)視器。訓(xùn)練員用于訓(xùn)練該神經(jīng)網(wǎng)絡(luò),因為該監(jiān)視器通過一個事先設(shè)置好的訓(xùn)練重復(fù)數(shù)來運行這個神經(jīng)網(wǎng)絡(luò)。對于每一次訓(xùn)練重復(fù),數(shù)據(jù)被提供到神經(jīng)網(wǎng)絡(luò),然后就可以觀察到結(jié)果。該神經(jīng)網(wǎng)絡(luò)的權(quán)重(存儲在穿梭在神經(jīng)原層之間的觸角連接中)將根據(jù)誤差作適當(dāng)調(diào)整。隨著訓(xùn)練的進行,誤差級將下降。下列代碼建立訓(xùn)練員并把它依附到監(jiān)視器。
你會記得列表1中提供的輸入文件包含三個列。到目前為止,我們僅僅使用了第一、二列,它們指定了到神經(jīng)網(wǎng)絡(luò)的輸入。第三列包含當(dāng)提供給神經(jīng)網(wǎng)絡(luò)第一列中的數(shù)字時的期盼的輸出值。我們必須使得訓(xùn)練員能夠存取該列以便能確定誤差。該錯誤是神經(jīng)網(wǎng)絡(luò)的實際輸出和期盼的輸出之間的差距。下列代碼創(chuàng)建另外一個FileInputSynapse并作好準(zhǔn)備以讀取與前面相同的輸入文件。
這時,我們想指向在第三列的FileInputSynapse。下列代碼實現(xiàn)了這一點,然后讓訓(xùn)練員使用這個FileInputSynapse。
最后,訓(xùn)練員被連結(jié)到神經(jīng)網(wǎng)絡(luò)輸出層,這將使訓(xùn)練員接收神經(jīng)網(wǎng)絡(luò)的輸出。
我們現(xiàn)在已為所有的層準(zhǔn)備好后臺線程,包括訓(xùn)練員。
最后,我們?yōu)橛?xùn)練設(shè)置一些參數(shù)。我們指定在輸入文件中共有四行,而且想訓(xùn)練20,000個周期,而且還在不段學(xué)習(xí)。如果你設(shè)置學(xué)習(xí)參數(shù)為false,該神經(jīng)網(wǎng)絡(luò)將簡單地處理輸入并不進行學(xué)習(xí)。我們將在下一節(jié)討論輸入處理。
現(xiàn)在我們已經(jīng)為訓(xùn)練過程作好準(zhǔn)備。調(diào)用監(jiān)視器的Go方法將在后臺啟動訓(xùn)練過程。
神經(jīng)網(wǎng)絡(luò)現(xiàn)在將要被訓(xùn)練20,000個周期。當(dāng)神經(jīng)網(wǎng)絡(luò)訓(xùn)練完成,誤差層應(yīng)該在一個合理的低級別上。一般低于10%的誤差級是可接受的。 |
|