一提到深度學習,神經網絡等技術,大部分肯定會想到TensorFlow,Keras,Caffe,PyTorch等框架,而這些框架大部分都是使用Python來進行開發的,毫無疑問,在人工智能領域技術上比如神經網絡等Python是一種很不錯的選擇,但是作為一個JAVA程序員,如果想要使用java語言來玩玩神經網絡的話,有沒有更好的選擇呢,其實java在這一方面確實沒有Python做的好,不過要使用java來做神經網絡的話還是有很多選擇的,比如DeepLearning4J, Encog, JOONE等等,這篇文章我們來介紹一款java神經網絡學習框架Encog。
Encog是一款Java和.Net上的機器學習框架,好像也有JavaScript版的,但我沒找到,它除了支持神經網絡之外,也支持大部分通用的機器學習技術。Encog的第一個版本為0.5, 正式發布于2008年7月10號,之后的Encog1.0到2.0極大地擴展了神經網絡,到了3.0后增加了更多的機器學習方法。Encog他也不僅僅包括了機器學習,它內部還包括了一款爬蟲工具,可以很方便地為神經網絡獲取數據(不過這款工具我感覺不好用,還沒有Jsoup好使呢)。
使用Encog構建一個神經網絡也特別簡單,在Encog中,創建神經網絡主要使用BasicNetwork和BasicLayer這兩個類,當然也會用到其他的類比如激活函數。
使用maven導入相關的包
這里我們使用maven導入encog的相關包,只需要導入encog-core這個包就可以了。
Encog神經網絡的介紹
神經網絡通常是分層的,至少有一個輸入和輸出層,也許還有隱藏層,某些神經網絡類型不會在輸入和輸出層之外分解成任何形式層,然而,這個輸入層和輸出層將永遠存在,也許可能被整合在同一層,我們現在先介紹一下輸入層,輸出層和隱藏層。
輸入層: 輸入層是神經網絡的第一層,和其他層一樣,這一層包括了一個指定數字的神經元,同一層的神經元都含有相似的屬性,一般情況下,對于分類,回歸或者聚類的神經網絡的每個屬性,輸入層都會有一個神經元與之一一對應。
神經元的數量決定了神經網絡層的結構,對于每個輸入神經元,在Encog中為一個double值,例如,以下的數組能夠輸入到一個包含五個神經元層的結構中
double[] input = new double[5];
Encog中使用double類型數據,使用MLData接口管理這些double數組,上面的double數據要想被神經網絡使用,得先將其轉換為MLData,代碼如下:
MLData data = new BasicMLData(input);
MLData是可以直接提供給Encog的數據,BasicMLData類是其中一個實現了MLData接口的類。其他實現了MLData接口的類也可以作為Encog神經網絡處理的數據。
輸出層: 輸出層是神經網絡的最后一層,這層給出了神經網絡最終的輸出結果。同樣,輸出結果也是一個實現了MLData接口的類,大多數神經網絡返回的輸出類是一個BasicMLData,從MLData中我們也可以得到一個doube數組。
隱藏層:在前面的討論中,神經網絡包含了輸入層和輸出時,有時候,輸出層和輸入層是相同的,但是大多數通常是兩個單獨的層,此外,在輸入層和輸出層之間也許存在其他的層,這層被稱為隱藏層,隱藏層在輸入層和輸出層之間。隱藏層也可以承擔更多復雜的結構。
隱藏層唯一的目標是讓神經網絡更好的為給定的輸入產生預期的輸出,神經網絡編程首先涉及到的是定義輸入層和輸出層神經元個數,然后在定義隱藏層。
隱藏層是一個非常大的“黑盒子”,怎樣創建一個隱藏層結構,要達到不要太簡單,也不要太復雜,太簡單的隱藏層結構將學習不精,太復雜的隱藏層結構也要花太多數據和時間去訓練,通常是一個單一的隱藏層神經元數目等于輸入層的兩倍(這個不一定對,但可以先試試),在根據神經網絡的性能,在適當增加或者減少隱藏層神經元的數量。
為XOR運算構造一個神經網絡
一般我們在編程的時候第一個入門的例子就是打印一句hello world, 相應地,學習XOR運算是我們學習Encog的第一個例子,相當于神經網絡編程的hello world。
XOR的運算規則為:0 XOR 0 = 0, 1 XOR 0 = 1, 0 XOR 1 = 1, 1 XOR 1 = 0。
我們希望給神經網絡輸入0, 0得到0, 輸入1,0得到1,輸入0,1得到1,輸入1,1得到0。
該神經網絡是最原始的神經網絡,被稱為感知器,是一種前饋神經網絡,也是我們將要學習的第一個神經網絡。XOR運算符有兩個輸入和一個輸出,此外,我們還需要一個隱藏層,該隱藏層具有兩個神經元,兩個神經元的選擇是任意的,你也可以嘗試三個或者一個。XOR問題很簡單,兩個隱藏層神經元足以解決它,該網絡的結構如下:
上圖中:輸入神經元為I1, I2。 輸出神經元為O1。隱藏神經元為H1, H2。偏執神經元為B1, B2
使用代碼實現XOR運算
構造神經網絡:使用Encog構建一個神經網絡特別簡單,首先需要new 一個BasicNetwork對象,然后往這個對象里面添加層就可以了。BasicLayer構造函數第一個參數指定激活函數,第二個參數指定是由有偏置神經元,第三個參數指定神經元個數,如果只傳一個數字,則表示只指定神經元個數,而默認激活函數為ActivationSigmoid, 有偏置神經元。
因為偏執神經元影響的是下一層,以及激活函數影響的是前一層的數據。所以一般第一層(輸入層)不需要激活函數,最后一層(輸出層)不需要偏置神經元。調用finalizeStructure表示已經構建完成,不需要在往里面添加層了,reset是隨機初始化各層之間的連接權重。
處理數據:
- 準備好輸入數據和我們期望輸出的數據
- 構造一個MLDataSet對象訓練集,我們將我們的訓練數據傳給它。
使用彈性傳播(RPROP)訓練:我們在這個使用彈性傳播訓練(RPROP)來訓練我們的網絡, RPROP是Encog所支持的最好的訓練算法,當然,Encog還提供了其他訓練技術,并且在一定的訓練技術下能較好地解決某些問題。使用RPROP訓練的代碼如下:
上面的代碼通過多次的迭代,當迭代到使神經網絡的錯誤率低于1%的時候,神經網絡訓練就結束了。到了這里,我們可以運行我們的代碼看看訓練的結果:
可以看到,在第一次迭代的時候錯誤率很大,然后隨著迭代次數的增加,當迭代到一百次左右的時候,錯誤率已經降低到0.01了。注意這里每次的運行結果都不一樣,但是只要是錯誤率在降低說明我們的神經網絡構建成功了。
使用該神經網絡計算XOR:接下來就是測試一下我們的神經網絡能不能得到正確的XOR運算。
輸出的結果如下:
可以看到,我們的神經網絡最終的結果還是相當不錯的。
完整的代碼: