官术网_书友最值得收藏!

3.2 在每個節點上增加數據的輸入和計算結果

我們已從原理上、架構上以及TensorFlow的可視化運行過程層面學習了前向傳播的工作過程。接下來,我們將實現前向傳播功能,在項目中新增ForwardPropagation.py程序,完成后的目錄結構如圖3-9所示。

圖3-9 chapter3_Create_AI_Framework目錄結構

先運行一下在2.1節建立的程序Neuron_Network_Entry.py,當隱藏層設置為hidden_layers=[8,4,2]時,運行結果如下:

以上運行結果顯示創建了3個隱藏層,第一個隱藏層有8個神經元,N[i][j]中索引i表示第i個隱藏層,索引j表示第j個神經元,第二個隱藏層有4個神經元,第三個隱藏層有2個神經元,參見圖3-6。根據實例集(instances)第1列的數據和第2列的數據得出第3列的數據,異或計算當第1個元素和第2個元素不同時,結果為1,第1個元素和第2個元素相同時,結果為0。實例集的數據是我們輸入系統的,但系統并不知道要進行異或計算,神經網絡的訓練就是要讓系統準確地預測到第一列與第二列的某種關系,由此得出第三列到底是0還是1。讀者可能認為這里只有4行數據,而實際環境中可能有上“TB”級的數據量,但是系統的原理都是一樣的,處理上百萬條、上億條數據在理解上和這個是完全一樣的。

訓練的時候會有誤差,調整誤差是反向傳播算法的功能,看看預測的值和實際的值是否一致,誤差有多大。反向傳播算法是從后向前推,看哪些因素導致了誤差以及誤差的程度,以使下一次的表現更好。反向傳播算法將在后續章節講解。

接下來編寫代碼,我們的目標是從輸入層出發,經過所有隱藏層的處理,最終在輸出層得出結果,實現前向傳播算法的功能。

前向傳播算法是個業務類,在編寫ForwardPropagation.py之前,由于每個神經元的分析都會產生計算結果,我們需先對Node.py的代碼進行修改。例如,圖3-10所示的TensorFlow的可視化運行示意圖中,第一個隱藏層的第一個神經元要接收輸入層的數據進行處理并得出結果,每個神經元會有2個新的方法,get_value方法接收上一個神經元的數據,set_value方法存儲神經元計算的結果。

圖3-10 神經元節點的輸入及輸出

chapter3_Create_AI_Framework版本的Node.py,在chapter2_Create_AI_Framework版本的Node.py代碼的第38行之后新增代碼,增加以下set_input_value、get_input_value、set_value、get_value方法。

在ForwardPropagation.py文件中調用Node.py中的set_value、get_value及set_input_value方法,其中get_value方法獲取上一層中和自己有權重關系的一個神經元的值,set_value方法設置經過神經元非線性變換以后的結果,set_input_value方法設置上一層中所有和自己有權重關系的神經元的值并設置給當前神經元。

接下來進行前向傳播業務類代碼的編寫,這是關鍵的部分。在service目錄下創建ForwardPropagation.py文件,該程序將實現從輸入層,經過若干隱藏層,最后得出輸出層的值的功能。在ForwardPropagation.py文件中編寫class ForwardPropagation類,定義一個applyForwardPropagation方法從神經元網絡的最左側運行到最右側。applyForwardPropagation方法是一個工具方法,也是一個業務邏輯方法,但不是實例的方法,不需要創建類的實例來調用,因此不需要傳入self參數。applyForwardPropagation方法中傳入的第一個參數為nodes,表示所有的節點;傳入的第二個參數為weights,表示權重。例如,圖3-11所示的TensorFlow的可視化示意圖中,從輸入層的第一個節點,運行到第一個隱藏層的第一個節點,連接兩者的只有權重。這里傳入所有的權重。

圖3-11 權重示意圖

傳入的第三個參數為實例(instance),每次傳入一個實例。例如實例集第二條記錄[0,1,1]是輸入數據,第一個0作為x1的數據,第二個1作為x2的數據,經過一系列處理,最后得出一個計算結果(結果可能是0,也可能是其他數字),每次傳入的參數是一個訓練實例。

ForwardPropagation.py中的applyForwardPropagation方法的代碼如下:

這里我們先不實現applyForwardPropagation方法,而在chapter2_Create_AI_Framework版本的Neuron_Network_Entry.py代碼末尾新增代碼。在chapter3_Create_AI_Framework版本的Neuron_Network_Entry.py入口程序中先調用applyForwardPropagation方法,代碼如下。

實例集中的每個實例都會用到applyForwardPropagation方法,因此需循環遍歷實例集。該實例集有4個實例,分別為[0,0,0]、[0,1,1]、[1,0,1]、[1,1,0],程序每次只處理一個實例,instances[i]的索引從0開始,在第7行代碼處調用ForwardPropagation.applyForwardPropagation方法。applyForwardPropagation方法傳入的第一個參數是所有節點,傳入的第二個參數是權重,傳入的第三個參數是實例,在第10行代碼打印訓練的結果。注意,每次輸入一個實例是指輸入實例的第1列數據x1、第2列數據x2,而實例集的第3列數據是實際值,訓練的預測值和實際值可能不一致。

接下來我們將編寫applyForwardPropagation的代碼,該程序由以下幾部分組成:

  • 設置偏愛因子節點的值。
  • 把數據輸入到輸入層。
  • 隱藏層的處理,進行線性轉換(在3.2節中介紹)。
  • 使用Sigmoid函數作為激活函數,進行非線性轉換(在3.3節中介紹)。

(1)設置偏愛因子節點的值。

因為計算發生在不同層的神經元節點之間,節點中設置了層次信息,獲得神經元節點的時候也會知道節點所在的層,所以首先循環所有的節點。神經網絡節點可能是神經元節點,也可能是偏愛因子節點,而計算是發生在神經元節點之間的。偏愛因子節點是一個固定的值,偏愛因子節點沒有輸入數據和輸出數據,因此這里需將偏愛因子節點過濾掉。如果當前的節點是偏愛因子,get_is_bias_unit()等于True。這里為了簡化,暫將Bias的值設置為1,偏愛因子節點不需要進行計算。偏愛因子節點不參與線性、非線性的轉換過程,線性、非線性的轉換過程是神經元節點涉及的。

ForwardPropagation.py的applyForwardPropagation的源代碼如下:

(2)把數據輸入到輸入層。

回顧一下NetworkStructure.py中構建網絡算法的實現,每一層神經元網絡的第一個節點都是偏愛因子。NetworkStructure.py的create_nodes方法在創建輸入層節點時,首先在輸入層中創建偏愛因子節點,偏愛因子節點的索引ID是0;然后創建輸入層的2個節點x1x2,x1節點的索引ID是1,x2節點的索引ID是2,如圖3-12所示。

圖3-12 偏愛因子節點

例如處理實例集的第1個元素instance[0,1,1],訓練的時候只需要前2個特征,遍歷次數為2,獲得該條數據中每個特征具體的值。然后通過for語句循環遍歷所有的節點,索引為0的節點為偏愛因子,因此不能從0開始,要從索引為1的節點開始。第1次設置的是輸入層x1節點的值0,第2次設置的是輸入層x2節點的值1,這就完成了把數據輸入到輸入層的過程。

ForwardPropagation.py的applyForwardPropagation的源代碼如下:

主站蜘蛛池模板: 延安市| 莱州市| 灵武市| 海宁市| 睢宁县| 唐河县| 巩义市| 宝鸡市| 息烽县| 堆龙德庆县| 乐平市| 凌源市| 内丘县| 泽州县| 山阳县| 泽普县| 望谟县| 孙吴县| 句容市| 喀喇| 醴陵市| 手机| 闽清县| 萨迦县| 洪泽县| 丹阳市| 牡丹江市| 汉川市| 普格县| 晋中市| 鸡东县| 醴陵市| 遂平县| 平南县| 德江县| 略阳县| 高尔夫| 南和县| 德昌县| 怀化市| 确山县|