人工智能 Java 坦克機器人系列: 神經網絡,上部

發表于:2007-05-24來源:作者:點擊數: 標簽:java人工智能坦克機器人系列
神經網絡是人工智能應用中最重要的一部分,本文介紹了神經網絡在 Robocode 中的應用,并分析了用 Java 編寫的 Robocode 機器人例子代碼。但本文不限于 Robocode 這個 Java 編程 游戲 與神經網絡,同時還涉及到貝葉斯網絡、神經網絡 Java 公共包的應用、AICODE
神經網絡是人工智能應用中最重要的一部分,本文介紹了神經網絡在 Robocode 中的應用,并分析了用 Java 編寫的 Robocode 機器人例子代碼。但本文不限于 Robocode 這個 Java 編程游戲與神經網絡,同時還涉及到貝葉斯網絡、神經網絡 Java 公共包的應用、AICODE 這個編程游戲與 Robocode 互補特點。本文希望幫助大家利用 Robocode 這個有趣的編程游戲更好的領會神經網絡與 Java 技術,在大家學習人工智能與 Java 方面拋磚引玉。

神經網絡概念與適合領域

神經網絡最早的研究是 40 年代心理學家 Mclearcase/" target="_blank" >cculloch 和數學家 Pitts 合作提出的 ,他們提出的MP模型拉開了神經網絡研究的序幕。

神經網絡的發展大致經過 3 個階段:1947~1969 年為初期,在這期間科學家們提出了許多神經元模型和學習規則,如 MP 模型、HEBB 學習規則和感知器等;60 年代末期至 80 年代中期,神經網絡控制與整個神經網絡研究一樣,處于低潮。在此期間,科學家們做了大量的工作,如 Hopfield 教授對網絡引入能量函數的概念,給出了網絡的穩定性判據,提出了用于聯想記憶和優化計算的途徑。1984年,Hiton 教授提出 Bol tzman 機模型;1986年 Kumelhart 等人提出誤差反向傳播神經網絡,簡稱 BP 網絡。目前,BP網絡已成為廣泛使用的網絡。1987年至今為發展期,在此期間,神經網絡受到國際重視,各個國家都展開研究,形成神經網絡發展的另一個高潮。

人工神經網絡(ANN)受到生物學的啟發是生物神經網絡的一種模擬和近似,它從結構、實現機理和功能上模擬生物神經網絡。從系統觀點看,人工神經元網絡是由大量神經元通過極其豐富和完善的連接而構成的自適應非線性動態系統。人工神經網絡,因為生物的學習系統是由相互連接的神經元組成的異常復雜的網絡,其中每一個神經元單元有一定數量的實值輸入,并產生單一的實數值輸出。1960 年威德羅和霍夫率先把神經網絡用于自動控制研究。神經網絡以其獨特的結構和處理信息的方法,在許多實際應用領域中取得了顯著的成效,主要應用如下:自動控制領域、處理組合優化問題、模式識別、圖像處理、傳感器信號處理、機器人控制、信號處理、衛生保健、醫療、經濟、化工領 域、焊接領域、地理領域、數據挖掘、電力系統、交通、軍事、礦業、農業和氣象等領域。





回頁首


攻擊策略與神經網絡基本結構

在 Robocode 中所有的機器人都是在指定大小的地圖上移動作戰,所以我們可以近似的把這些戰斗的機器人看做是一些非線性移動的點。要想準確的打中對手,我們必須要知道動手的運動軌跡,也即要知道戰場中每個非自身機器人點的非線性規律。在手寫代碼中,我們可以把敵人假想的動作都放入到攻擊程序代碼中,但是戰場的情況和環境是不斷變化的,我們不可能預測到所有的可能變化,所以擁有一個自學習,自適應的攻擊系統尤為重要。本文借丹麥奧爾堡大學 Robocode 研究小組的 outRobot 機器人來分析神經網絡的代碼實現。

根據上面神經網絡的一些特性。我們發現 Robocode 的攻擊系統設計其實就是神經網絡處理不確定或不知道的非線性系統的問題求解過程。

神經網絡基本結構

人工神經網絡由神經元模型構成,這種由許多神經元組成的信息處理網絡具有并行分布結構。每個神經元具有單一輸出,并且能夠與其它神經元連接;存在許多(多重)輸出連接方法,每種連接方法對應一個連接權系數??砂?ANN 看成是以處理單元 PE(processing element) 為節點,用加權有向弧(鏈)相互連接而成的有向圖。令來自其它處理單元(神經元)i的信息為Xi,它們與本處理單元的互相作用強度為 Wi,i=0,1,…,n-1,處理單元的內部閾值為 θ。那么本神經元的輸入為:



                               

而處理單元的輸出為:

              

式中,xi為第 i 個元素的輸入,wi 為第 i 個元素與本處理單元的互聯權重。f 稱為激發函數(activation function)或作用函數。它決定節點(神經元)的輸出。該輸出為 1 或 0 取決于其輸入之和大于或小于內部閾值 θ。

下圖所示神經元單元由多個輸入,i=1,2,...,n和一個輸出y組成。中間狀態由輸入信號的權和表示,而輸出為:


圖1:神經元模型
圖1:神經元模型

攻擊輸入輸出

由上面神經網絡的基本結構我們知道,設計攻擊瞄準系統網絡前我們必須決定為網絡提供哪些參數。而且要考慮到哪些輸出是合格的。在決定攻擊網絡系統輸入數據之前,我們先來看看輸出的是什么。攻擊系統最終目的是提高命中敵人的概率,也即盡可能的多打中敵人,也即控制炮管在發射前轉動多少度才能打中目標,所以我們的神經網絡中最后輸出的數據是已經計算好的炮管需要轉動的角度。

在炮管指向目標前,需要計算目標狀態以調整我們的炮管角度,如果目標不是固定的,神經網絡的輸出可以被看做是需要調整的角度。當攻擊一個固定目標,神經網絡不需要調整角度,直接輸出零值。

Robocode 基本規則機器人移動速度在每個單位時間不可能超過8 pixels,子彈最小能達到的速度在每個單位時間是 11 pixels。我們數學三角函數計算公式求得調整角度為 sin(8/11)=47,由此可以得出最大的角度范疇是 47*2=94 度,如圖所示:


圖2:最大的調整角度
圖2:最大的調整角度

我們從圖上可以看出目標在被打中前無論如何也不可能移出圖中的圓錐體。這樣我們可以把神經網絡的輸出范圍縮小為 94 度或 [-47,47] 區間。

上面的 8 和 11 都是理想狀態下的測試數據,在 Robocode 規則中能量不同的子彈速度是不一樣的,而且射擊位置的遠近也同樣會影響到子彈擊中目標的概率。所以只有知道了射擊的位置以及射擊能量。神經網絡才能夠精確計算自身和炮管的調整角度。

由于戰斗情況是千變萬化的,不同的能量可能帶來不同的效果。所以我們同樣把能量參數并入到神經網絡中,讓攻擊網絡系統自我學習在當時的新情況下什么樣的能量是最合適的。炮管調整角度是精確到了區間 [-47,47],同樣我們也可用這個方法來假定一個能量區間減少能量輸出范圍盡快求得好的結果。如下式,我們用距離參數來劃定能量區間:



dist在此處代表目標距離,不同的距離輸出不同的能量值。

在上面的輸出基礎上,我們來檢驗各種可能的輸入情況,下面列出了對調整射擊角度有影響的基本輸入信息: 敵人相對方向(Enemy heading),Enemy velocity(敵人速度),炮管絕對方向(Gun bearing),距離(Distance)。我們用神經網絡的輸入和輸出數據建立一個神經網絡瞄準系統關聯表示圖。



神經網絡中所有計算和反饋的數據都是以二進制的方式保存在內存空間,所有的這些輸入我們在神經網絡用一個二進制字符來表示,如圖:



在 Robocode 中我們建立一個輸入數組函數 getInputs,用于處理所有相關的輸入數據。


private double[] getInputs (Enemy tm, Vektor mig, Vektor ham)  {
            …
            Vektor diff = ham.substract (mig);
            double[] inputvalues = new double[36];    //創建輸入數組大小為36位
            return inputvalues;
            }
            

類Vektor是一個虛構類,里面包含了機器人常用的參數和常用的處理方法。比如機器人的X坐標、Y坐標、XY之間的角度等等。它其實就是一個機器人相關信息的容器,在下面的代碼實現中會介紹到 Vektor 類中的部分方法和屬性。Mig 是一個包含自身機器人信息類實現,ham 包含敵人信息的類實現。


 public double getAngle ()  {
            return Math.toDegrees ((Math.atan2 (x, y)));
            }
            //調整0-360度到[-180,180]區間
            public static double normalize (double angle)  {
            angle = mod (angle, 360.0);
            if (angle > 180)
            angle = angle - 360;
            return angle;
            }
            private static double mod (double n, double m)  {
            if (n < 0)
            return mod (n + m, m);
            if (n >= m)
            return mod (n - m, m);
            return n;
            }
            

此處根據 getAngle 由三角反正切函數得到,normalize 函數是把得到的角度規范到 [-180,180] 區間上來。

敵人相對方向最基本的信息,它告訴我們目標的相對方向。要神經網絡成功計算調整角,瞄準系統需要知道在炮管指向目標時,目標是向左或向右移動。比如:目標向右直線移動,它就要給我們 90 度相對方向,瞄準系統才能比較理想的攻擊到右邊的目標:


int enemyRelativeHeading = (int) (tm.getHeading ());
            enemyRelativeHeading =
            (int) Vektor.normalize (enemyRelativeHeading) + 180;//設置敵人相對方向
            for (int i = 1; i < 10; i++)    {
            inputvalues[i - 1] = enemyRelativeHeading >>> 9 - i &
            0x01;//轉換為二進制
            }
            

敵人相對方向這個數在 0 到 360 度之間,為了表示這些數據我們需要內存提供九個位來保存相對方向角的二進制數,通過循環把角度轉換為二進制碼并寫入到 inputvalues 數組變量中。

敵人速度告訴我們目標以多快速度移動,要想瞄準系統知道目標的移動大概方向,就需要知道目標移動速度,這樣才能計算出正確的調整角。


int enemyVelocity = (int) tm.getVelocity () + 8;
            for (int i = 1; i < 6; i++)    {
            inputvalues[i + 8] = enemyVelocity >>> 5 - i & 0x01; //轉換二進制
            }
            

由于速度的范圍是 [-8,8] 之間,我們共需要 17 個不同的表現值,所以內存要提供 5 個位保存速度的二進制碼,inputvalues 數組變量中我們的計數在上面方向角的基礎上增加 5 位。但在神經網絡中我們可以不考慮負值,所以此處我們在速度的基礎上加上 8,以去除負的速度對神經網絡的影響。

炮管絕對方向告訴我們當前炮管應該指向哪個方向,如果炮管要指向 30 度的方向,它必須轉動 (turn)30 度。這個角度類似于敵人相對方向角度,同樣是 0 到 360 度之間的角度,同樣需要九個二進制位來表示。


int gunBearing =
            (int) Vektor.normalize (diff.getAngle);
            gunBearing = (int) Vektor.normalize (gunBearing) + 180;
            for (int i = 1; i < 10; i++)     {
            inputvalues[i + 13] = gunBearing >>> 9 - i & 0x01;
            }
            

距離是目標的原始距離。知道目標方向、速度和距離,瞄準系統有足夠多的信息猜出當子彈接近目標時,目標將到達哪個地方。這有一點要注意的地方,子彈的速度會影響到調整角度,因為距離是由速度計算得來,所以速度實際上是隱藏在距離這個輸入數據之中的。只要給出距離,瞄準系統就能知道子彈的正確速度。Robocode 戰場最大長高是 5000,則最大的由公式 50002 + 50002 = C2 得到 C=7071,這需要 13 個二進制位來表示。


int distanceToEnemy = (int) diff.getLength ();
            for (int i = 1; i < 14; i++)    {
            inputvalues[i + 22] = distanceToEnemy >>> 13 - i & 0x01;
            }
            

getLength() 函數即求二點間的距離函數:


    public double getLength ()   {
            return Math.hypot (x, y);
            }
            

在我們神經網絡設計說明中,我們需要輸出一個角度,告訴我們炮管要打中移動中的目標要轉動多少。要達到這一步我們需要表示 94 度,也即二進制中的 7 位。下面是一個二進制位表示的輸入輸出訓練例子如下:10100111000100110101110010100111110 1001110

最后 7 位(1001110)是網絡給出的 36 位輸入中最佳輸出。也即我們要求的角度。





回頁首


訓練網絡

神經網絡結構被設計完成,有了輸入、輸出參數后,我們就要對網絡進行訓練。神經網絡的訓練有包括感知器訓練、delta 規則訓練和反向傳播算法等訓練,其中感知器訓練是基礎。

感知器和 delta 訓練規則

理解神經網絡的第一步是從對抽象生物神經開始,本文用到的人工神經網絡系統是以被稱為感知器的單元為基礎,如圖所示。感知器以一個實數值向量作為輸入,計算這些輸入的線性組合,如果結果大于某個閾值,就輸出 1,否則輸出 -1,如果 x 從 1 到 n,則感知器計算公式如下:



其中每個 wi 是一個實數常量,或叫做權值,用來決定輸入 xi 對感知器輸出的貢獻率。特別地,-w0是閾值。

盡管當訓練樣例線性可分時,感知器法則可以成功地找到一個權向量,但如果樣例不是線性可分時它將不能收斂,因此人們設計了另一個訓練法則來克服這個不足,這個訓練規則叫做 delta 規則。感知器訓練規則是基于這樣一種思路--權系數的調整是由目標和輸出的差分方程表達式決定。而 delta 規則是基于梯度降落這樣一種思路。這個復雜的數學概念可以舉個簡單的例子來表示。從給定的幾點來看,向南的那條路徑比向東那條更陡些。向東就像從懸崖上掉下來,但是向南就是沿著一個略微傾斜的斜坡下來,向西象登一座陡峭的山,而北邊則到了平地,只要慢慢的閑逛就可以了。所以您要尋找的是到達平地的所有路徑中將陡峭的總和減少到最小的路徑。在權系數的調整中,神經網絡將會找到一種將誤差減少到最小的權系數的分配方式。這部分我們不做詳細介紹,如有需要大家可參考相關的人工智能書籍。

反向傳播算法

人工神經網絡學習為學習實數值和向量值函數提供了一種實際的方法,對于連續的和離散的屬性都可以使用。并且對訓練數據中的噪聲具有很好的健壯性。反向傳播算法是最常見的網絡學習算法。這是我們所知用來訓練神經網絡很普遍的方法,反向傳播算法是一種具有很強學習能力的系統,結構比較簡單,且易于編程。

魯梅爾哈特(Rumelhart)和麥克萊蘭(Meclelland)于 1985 年發展了 BP 網絡學習算法,實現了明斯基的多層網絡設想。BP網絡不僅含有輸入節點和輸出節點,而且含有一層或多層隱(層)節點。輸入信號先向前傳遞到隱藏節點,經過作用后,再把隱藏節點的輸出信息傳遞到輸出節點,最后給出輸出結果。節點的激發函數一般選用 S 型函數。

反向傳播(back-propagation,BP)算法是一種計算單個權值變化引起網絡性能變化值的較為簡單的方法。由于BP算法過程包含從輸出節點開始,反向地向第一隱含層(即最接近輸入層的隱含層)傳播由總誤差引起的權值修正,所以稱為"反向傳播"。反向傳播特性與所求解問題的性質和所作細節選擇有極為密切的關系。

對于由一系列確定的單元互連形成的多層網絡,反向傳播算法可用來學習這個多層網絡的權值。它采用梯度下降方法試圖最小化網絡輸出值和目標值之間的誤差平方,因為我們要考慮多個輸出單元的網絡,而不是像以前只考慮單個單元,所以我們要重新計算誤差E,以便對所有網絡輸出的誤差求和:



Outpus 是網絡輸出單元的集合,tkd 和 okd 是與訓練樣例 d 和第 k 個輸出單元的相關輸出值.

反向傳播算法的一個迷人特性是:它能夠在網絡內部的隱藏層發現有用的中間表示:

1.訓練樣例僅包含網絡輸入和輸出,權值調節的過程可以自由地設置權值,來定義任何隱藏單元表示,這些隱藏單元表示在使誤差E達到最小時最有效。

2.引導反向傳播算法定義新的隱藏層特征,這些特征在輸入中沒有明確表示出來,但能捕捉輸入實例中與學習目標函數最相關的特征

Robocode代碼實現

反向傳播訓練神經元的算法如下:



1.選取比率參數r

2.進行下列過程直至性能滿足要求為止:

① 對于每一訓練(采樣)輸入,
      (a) 計算所得輸出。
      (b) 按下式計算輸出節點的值
        
                  (c) 按下式計算全部其它節點
       
              (d) 按下式計算全部權值變化

      
            

② 對于所有訓練(采樣)輸入,對權值變化求和,并修正各權值。

權值變化與輸出誤差成正比,作為訓練目標輸出只能逼近 1 和 0 兩值,而絕不可能達到 1 和 0 值。因次,當采用 1 作為目標值進行訓練時,所有輸出實際上呈現出大于 0.9 的值;而當采用 0 作為目標值進行訓練時,所有輸出實際上呈現出小于 0.1 的值;這樣的性能就被認為是滿意的。

下面是 Robocode 中反向傳播算法神經網絡實現過程,把各個相關的輸入信號先正向傳遞到隱節點,經過作用后,再把隱節點的輸出信息傳遞到輸出節點,最后給出輸出結果。節點的激發函數一般選用 S 型函數。

Robocode 的 BP 算法學習過程由正向傳播和反向傳播組成。在正向傳播過程中,輸入信息從輸入層經隱單元層逐層處理后,傳至輸出層。每一層神經元的狀態只影響下一層神經元的狀態。如果在輸出層得不到期望輸出,那么就轉為反向傳播,把誤差信號沿原連接路徑返回,并通過修改各層神經元的權值,使誤差信號最小。


public class BPN {
            …
            //構造神經網絡對象
            public BPN (int hidden, double lrate, int output, int input)  {
            inputNeurons = input;  //輸入
            hiddenNeurons = hidden; //隱藏層
            outputNeurons = output;  //輸出
            learningrate = lrate;   //學習概率
            outputValues = new double[output];
            hiddenValues = new double[hidden];
            m1 = new double[input][hidden];  //輸入到隱藏層的加權
            m2 = new double[hidden][output]; //隱藏層到輸出層的加權
            fillRandom (m1);
            fillRandom (m2);
            }
            

Learningrate 是學習速率,inputNeurons 是網絡輸入的數量,hiddenNeurons 是隱藏層單元數,outputNeurons 是輸出單元數,m1 表示節點輸入層到隱藏層的權值,m2 表示節點隱藏層到輸出層的權值。為了讓神經網絡的權值更容易保存,m1、m2 放在一個序列化對象 MatrixSave 之中。


public class MatrixSave implements Serializable{
            double[][] m1;
            double[][] m2;
            public MatrixSave (double[][]m1, double[][]m2) {
            this.m1 = m1;
            this.m2 = m2;
            }
            

1.通過構造函數 BPN () 我們創建一個具有 input 個輸入,hidden 個隱藏,output 個輸出單元的網絡。


//迭代設置網絡最小權值
            public void fillRandom (double[][]matrix)  {
            Random ran = new Random ();
            for (int i = 0; i < matrix.length; i++)    {
            for (int j = 0; j < matrix[0].length; j++)  {
            matrix[i][j] = ran.nextDouble () * 2 - 1;
            }
            }
            }
            

2.fillRandom 是初始化所有的網絡權值為小的隨機值,即 -1 和 1 之間的隨機數。

3.把輸入沿網絡正向傳播,把實例輸入網絡:輸入信號先向前傳遞到隱藏節點hiddenNeurons,經過加權作用后,利用神經網絡的計算函數公式常規 S 激勵函數求得隱藏節點的激勵數,再把隱藏節點的輸出信息傳遞到輸出節點,同樣用激勵函數求得輸出激勵,最后給出輸出結果并計算網絡中每個單元的輸出output.

激發函數一般具有非線性特性。常用的非線性特性如圖所示,分述于下: 一種二值函數可由下式表示:




閾值型(二值函數)

對于這種模型,神經元沒有內部狀態,激發函數為一階躍函數,如圖 a 所示。這時,輸出為:



Sigmoid 型激發函數稱為西格莫伊德(Sigmoid)函數,簡稱 S 型函數,其輸入輸出特性常用對數曲線或正切曲線等表示。這類曲線反映了神經元的飽和特性。S 型函數是最常用的激發函數,它便于應用梯度技術進行搜索求解。一種常規的 S 形函數見圖,可由下式表示如圖 b:



常用雙曲正切函數來取代常規 S 形函數,因為 S 形函數的輸出均為正值,而雙曲正切函數的輸出值可為正或負。雙曲正切函數如下式所示如圖 c:





由上面的激勵函數求得如下:


  public double[] calculate (double[]inputValues)   {
            for (int i = 0; i < hiddenNeurons; i++)     {
            double sum = 0;
            //設置輸入層到隱藏層的網絡權值
            for (int j = 0; j < inputNeurons; j++) 	  {
            sum += m1[j][i] * inputValues[j];
            }
            hiddenValues[i] = 1 / (1 + Math.exp (-(sum))); //計算隱藏層
            }
            //計算隱藏層到輸出層的網絡權值
            for (int i = 0; i < outputNeurons; i++)     {
            double sum = 0;
            for (int j = 0; j < hiddenNeurons; j++)   {
            sum += m2[j][i] * hiddenValues[j];
            }
            outputValues[i] = 1 / (1 + Math.exp (-(sum)));
            }
            return outputValues;
            }
            

4.把訓練樣例 TrainingExample 輸入網絡,并計算網絡中每個單元的輸出,然后使誤差沿網絡反向傳播,并分別計算網絡的每個輸出單元 outputNeurons 和隱藏單元 hiddenNeurons 的誤差項,最后更新每個網絡權值。訓練樣例 TrainingExample 是序偶 <inputvalues,targetvalues> 的集合,即網絡輸入值向量和目標輸出值。threshold 為網絡閥值。


public void learn (TrainingExample[]te, double threshold)  {
            double[] outputError = new double[outputNeurons]; //輸出單元誤差
            double[] hiddenError = new double[hiddenNeurons]; //隱藏單元誤差
            double[] inputValues;
            double outputs[]; //訓練樣例中的輸入值
            double targets[]; //訓練樣例中的目標值
            for (int tal = 0; tal < (int) threshold; tal++)
            

根據正向傳播計算輸出單元


  outputs = calculate (inputValues);
            //利用神經網絡加權計算輸出單元誤差outputError
            for (int j = 0; j < outputs.length; j++)   {
            outputError[j] =outputs[j] * (1 - outputs[j]) * (targets[j] - outputs[j]);
            }
            

利用神經網絡加權計算隱藏單元誤差hiddenError


    for (int j = 0; j < hiddenValues.length; j++)     {
            double sum = 0;
            for (int k = 0; k < outputNeurons; k++)		  {
            sum += m2[j][k] * outputError[k];
            }
            hiddenError[j] = hiddenValues[j] * (1 - hiddenValues[j]) * sum;
            }
            

分別更新網絡權值m1,m2


 //更新網絡權值m1
            for (int l = 0; l < m1.length; l++)	      {
            for (int o = 0; o < m1[0].length; o++)		  {
            m1[l][o] = m1[l][o] + learningrate * hiddenError[o] * inputValues[l];
            }
            }
            //更新網絡權值m2
            for (int l = 0; l < m2.length; l++)     {
            for (int o = 0; o < m2[0].length; o++)  {
            m2[l][o] =m2[l][o] +learningrate * outputError[o] * hiddenValues[l];
            }
            }
            

完成了我們的神經網絡機器人結構的初步構建,我們就要開始訓練網絡,讓我們的機器人在不斷的學習、自我適應過程中完成進化,找到最終要輸出的最佳結果。在這里有兩個辦法訓練可以我們的網絡:分別是離線學習和在線學習。





回頁首


離線學習(off-line learning)

一般人工智能的機器人的訓練過程都要經過一個漫長的過程才有可能找到最優化的結果。但 Robocode 的規則以及電腦 CPU 不可能給出很多的時間讓我們的神經網絡機器人運行。所以機器人必須在游戲運行之外學習。也即要使用離線學習方法,我們在 Robocode 運行中收集計算有用數據并把它們保存到文件當中。新的數據收集都是以保存在文件中的數據為依據。比如:新的加權是根據以前保存的加權文件來構造的隨機加權集合。


public class Learn {
            public static void main (String[]args)   {
            BPN net = new BPN (27, 0.45, 15, 36);
            net.loadWeights (new File ("weights.dat"));
            TrainingExample[] te = loadTE (new File ("danivan.txt"));
            performance (net, te); //判斷最佳的網絡
            net.learn (te, Integer.parseInt (args[0])+ 0.0); //反向傳播學習
            performance (net, te);
            net.saveWeights (new File ("weights.dat"));
            }
            }
            

上式通過 loadWeights,loadTE 分別讀取保存的加權集及訓練示例,利用反向傳播學習方法來訓練示例。一定時間內數據通過網絡,并依據我們的設想運作,當所有的訓練示例都通過了反向傳播算法,并判斷網絡中的最佳結果,加權集將保存到磁盤中,這些加權集將用于 Robocode 的戰斗,作為機器人的瞄準系統參數。這里我們要注意不要使用大量的隱藏神經單元,因為這樣有可能會得到一個帶有風險的網絡,以至網絡可能只接受精確的示例導致沒有理想結果。


  //判斷最佳的網絡
            public static boolean performance (BPN net, TrainingExample te) {
            boolean b = false;
            double[] output = net.calculate (te.getInputValues ());
            double[] target = te.getTargetValues ();
            for (int i = 0; i < output.length; i++)    {
            if (!((output[i] > 0.5 ? 1.0 : 0.0) == target[i]))	  {
            b = false;
            break;
            }
            else  {
            b = true;
            }
            }
            return b;
            }
            





回頁首


實時學習進化(Online-Learning)

實時學習,即在 Robocode 的運行當中,讓我們的機器人進行神經網絡學習。它的原理和離線學習是一樣的,只是它是即時學習即時利用輸入的數據更新加權值。而離線學習是把權值保存到磁盤當中。每次炮管的開火在線學習都會做如下的動作:

1.輸入X到神經網絡并計算輸出

2.調整輸出角度,發射子彈

3.保存射擊數據

4.從開火中等待是否擊中事件返回

5.從保存的數據和打擊事件構造訓練示例

6.用反向傳播算法訓練示例神經網絡

第 5 步我們用保存的數據和到達的開火事件構造訓練示例。使用這些數據我們能知道目標精確的移動,并且能構造一個算法計算在當時的環境和時間中子彈最優的攻擊線路。我們通過訓練示例計算得到所有的輸入和輸出,當我們有了這些關于射擊的最優數據,我們就能更新網絡中的加權集。


  //在線學習
            public OnlineLearn (BPN net, File weights, File trainingExamples)   {
            TrainingExample[]te = loadTE (trainingExamples);
            net.learn (te, 1.0);
            }
            


原文轉自:http://www.anti-gravitydesign.com

評論列表(網友評論僅供網友表達個人看法,并不表明本站同意其觀點或證實其描述)
国产97人人超碰caoprom_尤物国产在线一区手机播放_精品国产一区二区三_色天使久久综合给合久久97