# <h1>Learning 8-bit parity checking problem with MLP</h1> ###### tags: `深度學習` `Python` `大三` <h2>目錄</h2> <ul> <li>目錄</li> <li> 問題 <ul> <li>問題內容</li> <li>問題限制</li> </ul> </li> <li> 解決過程 <ul> <li>產生訓練資料以及測試資料</li> <li>產生神經網絡模型</li> <li>開始訓練模型</li> <li>繪製學習曲線圖</li> <li>顯示訓練後的結果</li> </ul> </li> <li>比較兩層、三層、四層</li> </ul> <h2>問題</h2> **問題內容:**<br> 設計一個MLP來學習解決判定8位元的奇偶數量問題,其問題是8位元的二進制輸入,檢測其中1的數量,若1的數量為奇數,則會輸出1,若反之1的數量為偶數,則會輸出0。 **問題限制:**<br> 1. 不能使用如Keras、Tensorflow、Pytorch、CNTK、MXNet等任何的深度學習框架<br> 2. 必須試驗兩層、三層、四層神經元網絡,並比較性能<br> 3. 需使用Sigmoid(x)、Relu(x)、Linear(x)以及Tanh(x)函數<br> 4. 需繪製Loss值的學習曲線圖,以及使用表格列出所有256個輸入的輸出以及停止時獲得的最終Loss值。 <h2>解決過程</h2> **產生訓練資料以及測試資料** 在進行訓練以前,需要獲得訓練以及測試使用的資料,藉以下的程式碼可以產生256個二進制的8-bit訓練資料以及256個1-bit的訓練資料答案 ``` data = [0,0,0,0,0,0,0,0] print('([',end='') count=0 while(True): print("[",end='') count1=0 for i in range(0,8,1): if(data[i]==1): count1+=1 #if(i!=7): #從此行開始以下四行可以產生8-bit訓練資料 #print(data[i],end=',') #else: #print(data[i],end='') #if(count1%2==0): #此行開始下面四行可以產生1-bit的訓練資料答案 print('0',end='') #else: print('1',end='') print("]",end='') count+=1 if(count==256): print('])') break print(',',end='') data[7]+=1 j = 7 while(j>-1): #檢查是否進位(二進制) if(data[j]==2): data[j]=0 data[j-1]+=1 j-=1 else: break ``` 使用X來儲存產生的訓練資料,Y來儲存訓練資料用來比較Loss值的答案 ``` x=np.array([[0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,1],[0,0,0,0,0,0,1,0],[0,0,0,0,0,0,1,1],[0,0,0,0,0,1,0,0],[0,0,0,0,0,1,0,1],[0,0,0,0,0,1,1,0],[0,0,0,0,0,1,1,1],[0,0,0,0,1,0,0,0],[0,0,0,0,1,0,0,1],[0,0,0,0,1,0,1,0],[0,0,0,0,1,0,1,1],[0,0,0,0,1,1,0,0],[0,0,0,0,1,1,0,1],[0,0,0,0,1,1,1,0],[0,0,0,0,1,1,1,1],[0,0,0,1,0,0,0,0],[0,0,0,1,0,0,0,1],[0,0,0,1,0,0,1,0],[0,0,0,1,0,0,1,1],[0,0,0,1,0,1,0,0],[0,0,0,1,0,1,0,1],[0,0,0,1,0,1,1,0],[0,0,0,1,0,1,1,1],[0,0,0,1,1,0,0,0],[0,0,0,1,1,0,0,1],[0,0,0,1,1,0,1,0],[0,0,0,1,1,0,1,1],[0,0,0,1,1,1,0,0],[0,0,0,1,1,1,0,1],[0,0,0,1,1,1,1,0],[0,0,0,1,1,1,1,1],[0,0,1,0,0,0,0,0],[0,0,1,0,0,0,0,1],[0,0,1,0,0,0,1,0],[0,0,1,0,0,0,1,1],[0,0,1,0,0,1,0,0],[0,0,1,0,0,1,0,1],[0,0,1,0,0,1,1,0],[0,0,1,0,0,1,1,1],[0,0,1,0,1,0,0,0],[0,0,1,0,1,0,0,1],[0,0,1,0,1,0,1,0],[0,0,1,0,1,0,1,1],[0,0,1,0,1,1,0,0],[0,0,1,0,1,1,0,1],[0,0,1,0,1,1,1,0],[0,0,1,0,1,1,1,1],[0,0,1,1,0,0,0,0],[0,0,1,1,0,0,0,1],[0,0,1,1,0,0,1,0],[0,0,1,1,0,0,1,1],[0,0,1,1,0,1,0,0],[0,0,1,1,0,1,0,1],[0,0,1,1,0,1,1,0],[0,0,1,1,0,1,1,1],[0,0,1,1,1,0,0,0],[0,0,1,1,1,0,0,1],[0,0,1,1,1,0,1,0],[0,0,1,1,1,0,1,1],[0,0,1,1,1,1,0,0],[0,0,1,1,1,1,0,1],[0,0,1,1,1,1,1,0],[0,0,1,1,1,1,1,1],[0,1,0,0,0,0,0,0],[0,1,0,0,0,0,0,1],[0,1,0,0,0,0,1,0],[0,1,0,0,0,0,1,1],[0,1,0,0,0,1,0,0],[0,1,0,0,0,1,0,1],[0,1,0,0,0,1,1,0],[0,1,0,0,0,1,1,1],[0,1,0,0,1,0,0,0],[0,1,0,0,1,0,0,1],[0,1,0,0,1,0,1,0],[0,1,0,0,1,0,1,1],[0,1,0,0,1,1,0,0],[0,1,0,0,1,1,0,1],[0,1,0,0,1,1,1,0],[0,1,0,0,1,1,1,1],[0,1,0,1,0,0,0,0],[0,1,0,1,0,0,0,1],[0,1,0,1,0,0,1,0],[0,1,0,1,0,0,1,1],[0,1,0,1,0,1,0,0],[0,1,0,1,0,1,0,1],[0,1,0,1,0,1,1,0],[0,1,0,1,0,1,1,1],[0,1,0,1,1,0,0,0],[0,1,0,1,1,0,0,1],[0,1,0,1,1,0,1,0],[0,1,0,1,1,0,1,1],[0,1,0,1,1,1,0,0],[0,1,0,1,1,1,0,1],[0,1,0,1,1,1,1,0],[0,1,0,1,1,1,1,1],[0,1,1,0,0,0,0,0],[0,1,1,0,0,0,0,1],[0,1,1,0,0,0,1,0],[0,1,1,0,0,0,1,1],[0,1,1,0,0,1,0,0],[0,1,1,0,0,1,0,1],[0,1,1,0,0,1,1,0],[0,1,1,0,0,1,1,1],[0,1,1,0,1,0,0,0],[0,1,1,0,1,0,0,1],[0,1,1,0,1,0,1,0],[0,1,1,0,1,0,1,1],[0,1,1,0,1,1,0,0],[0,1,1,0,1,1,0,1],[0,1,1,0,1,1,1,0],[0,1,1,0,1,1,1,1],[0,1,1,1,0,0,0,0],[0,1,1,1,0,0,0,1],[0,1,1,1,0,0,1,0],[0,1,1,1,0,0,1,1],[0,1,1,1,0,1,0,0],[0,1,1,1,0,1,0,1],[0,1,1,1,0,1,1,0],[0,1,1,1,0,1,1,1],[0,1,1,1,1,0,0,0],[0,1,1,1,1,0,0,1],[0,1,1,1,1,0,1,0],[0,1,1,1,1,0,1,1],[0,1,1,1,1,1,0,0],[0,1,1,1,1,1,0,1],[0,1,1,1,1,1,1,0],[0,1,1,1,1,1,1,1],[1,0,0,0,0,0,0,0],[1,0,0,0,0,0,0,1],[1,0,0,0,0,0,1,0],[1,0,0,0,0,0,1,1],[1,0,0,0,0,1,0,0],[1,0,0,0,0,1,0,1],[1,0,0,0,0,1,1,0],[1,0,0,0,0,1,1,1],[1,0,0,0,1,0,0,0],[1,0,0,0,1,0,0,1],[1,0,0,0,1,0,1,0],[1,0,0,0,1,0,1,1],[1,0,0,0,1,1,0,0],[1,0,0,0,1,1,0,1],[1,0,0,0,1,1,1,0],[1,0,0,0,1,1,1,1],[1,0,0,1,0,0,0,0],[1,0,0,1,0,0,0,1],[1,0,0,1,0,0,1,0],[1,0,0,1,0,0,1,1],[1,0,0,1,0,1,0,0],[1,0,0,1,0,1,0,1],[1,0,0,1,0,1,1,0],[1,0,0,1,0,1,1,1],[1,0,0,1,1,0,0,0],[1,0,0,1,1,0,0,1],[1,0,0,1,1,0,1,0],[1,0,0,1,1,0,1,1],[1,0,0,1,1,1,0,0],[1,0,0,1,1,1,0,1],[1,0,0,1,1,1,1,0],[1,0,0,1,1,1,1,1],[1,0,1,0,0,0,0,0],[1,0,1,0,0,0,0,1],[1,0,1,0,0,0,1,0],[1,0,1,0,0,0,1,1],[1,0,1,0,0,1,0,0],[1,0,1,0,0,1,0,1],[1,0,1,0,0,1,1,0],[1,0,1,0,0,1,1,1],[1,0,1,0,1,0,0,0],[1,0,1,0,1,0,0,1],[1,0,1,0,1,0,1,0],[1,0,1,0,1,0,1,1],[1,0,1,0,1,1,0,0],[1,0,1,0,1,1,0,1],[1,0,1,0,1,1,1,0],[1,0,1,0,1,1,1,1],[1,0,1,1,0,0,0,0],[1,0,1,1,0,0,0,1],[1,0,1,1,0,0,1,0],[1,0,1,1,0,0,1,1],[1,0,1,1,0,1,0,0],[1,0,1,1,0,1,0,1],[1,0,1,1,0,1,1,0],[1,0,1,1,0,1,1,1],[1,0,1,1,1,0,0,0],[1,0,1,1,1,0,0,1],[1,0,1,1,1,0,1,0],[1,0,1,1,1,0,1,1],[1,0,1,1,1,1,0,0],[1,0,1,1,1,1,0,1],[1,0,1,1,1,1,1,0],[1,0,1,1,1,1,1,1],[1,1,0,0,0,0,0,0],[1,1,0,0,0,0,0,1],[1,1,0,0,0,0,1,0],[1,1,0,0,0,0,1,1],[1,1,0,0,0,1,0,0],[1,1,0,0,0,1,0,1],[1,1,0,0,0,1,1,0],[1,1,0,0,0,1,1,1],[1,1,0,0,1,0,0,0],[1,1,0,0,1,0,0,1],[1,1,0,0,1,0,1,0],[1,1,0,0,1,0,1,1],[1,1,0,0,1,1,0,0],[1,1,0,0,1,1,0,1],[1,1,0,0,1,1,1,0],[1,1,0,0,1,1,1,1],[1,1,0,1,0,0,0,0],[1,1,0,1,0,0,0,1],[1,1,0,1,0,0,1,0],[1,1,0,1,0,0,1,1],[1,1,0,1,0,1,0,0],[1,1,0,1,0,1,0,1],[1,1,0,1,0,1,1,0],[1,1,0,1,0,1,1,1],[1,1,0,1,1,0,0,0],[1,1,0,1,1,0,0,1],[1,1,0,1,1,0,1,0],[1,1,0,1,1,0,1,1],[1,1,0,1,1,1,0,0],[1,1,0,1,1,1,0,1],[1,1,0,1,1,1,1,0],[1,1,0,1,1,1,1,1],[1,1,1,0,0,0,0,0],[1,1,1,0,0,0,0,1],[1,1,1,0,0,0,1,0],[1,1,1,0,0,0,1,1],[1,1,1,0,0,1,0,0],[1,1,1,0,0,1,0,1],[1,1,1,0,0,1,1,0],[1,1,1,0,0,1,1,1],[1,1,1,0,1,0,0,0],[1,1,1,0,1,0,0,1],[1,1,1,0,1,0,1,0],[1,1,1,0,1,0,1,1],[1,1,1,0,1,1,0,0],[1,1,1,0,1,1,0,1],[1,1,1,0,1,1,1,0],[1,1,1,0,1,1,1,1],[1,1,1,1,0,0,0,0],[1,1,1,1,0,0,0,1],[1,1,1,1,0,0,1,0],[1,1,1,1,0,0,1,1],[1,1,1,1,0,1,0,0],[1,1,1,1,0,1,0,1],[1,1,1,1,0,1,1,0],[1,1,1,1,0,1,1,1],[1,1,1,1,1,0,0,0],[1,1,1,1,1,0,0,1],[1,1,1,1,1,0,1,0],[1,1,1,1,1,0,1,1],[1,1,1,1,1,1,0,0],[1,1,1,1,1,1,0,1],[1,1,1,1,1,1,1,0],[1,1,1,1,1,1,1,1]]) y=np.array([[0],[1],[1],[0],[1],[0],[0],[1],[1],[0],[0],[1],[0],[1],[1],[0],[1],[0],[0],[1],[0],[1],[1],[0],[0],[1],[1],[0],[1],[0],[0],[1],[1],[0],[0],[1],[0],[1],[1],[0],[0],[1],[1],[0],[1],[0],[0],[1],[0],[1],[1],[0],[1],[0],[0],[1],[1],[0],[0],[1],[0],[1],[1],[0],[1],[0],[0],[1],[0],[1],[1],[0],[0],[1],[1],[0],[1],[0],[0],[1],[0],[1],[1],[0],[1],[0],[0],[1],[1],[0],[0],[1],[0],[1],[1],[0],[0],[1],[1],[0],[1],[0],[0],[1],[1],[0],[0],[1],[0],[1],[1],[0],[1],[0],[0],[1],[0],[1],[1],[0],[0],[1],[1],[0],[1],[0],[0],[1],[1],[0],[0],[1],[0],[1],[1],[0],[0],[1],[1],[0],[1],[0],[0],[1],[0],[1],[1],[0],[1],[0],[0],[1],[1],[0],[0],[1],[0],[1],[1],[0],[0],[1],[1],[0],[1],[0],[0],[1],[1],[0],[0],[1],[0],[1],[1],[0],[1],[0],[0],[1],[0],[1],[1],[0],[0],[1],[1],[0],[1],[0],[0],[1],[0],[1],[1],[0],[1],[0],[0],[1],[1],[0],[0],[1],[0],[1],[1],[0],[1],[0],[0],[1],[0],[1],[1],[0],[0],[1],[1],[0],[1],[0],[0],[1],[1],[0],[0],[1],[0],[1],[1],[0],[0],[1],[1],[0],[1],[0],[0],[1],[0],[1],[1],[0],[1],[0],[0],[1],[1],[0],[0],[1],[0],[1],[1],[0]]) ``` <br> **產生神經網絡模型** 會使用到四種函數(Sigmoid,Relu,Linear,Tanh) ``` class Sigmoid(): def __init__(self): pass def forward(self,x): #往前推所使用的Sigmoid函數 out = 1/(1+np.exp(-x)) self.o = out return out def backward(self,dout): #往回推所使用的Sigmoid導函數 dx = dout*self.o*(1-self.o) return dx class Tanh(): def __init__(self): pass def forward(self,x): #往前推所使用的Tanh函數 out = (1-np.exp(-x))/(1+np.exp(-x)) self.o = out return out def backward(self,out): #往回推所使用的Tanh導函數 dx = out * (1 - (self.o * self.o)) return dx class Relu(): def __init__(self): pass def forward(self, x): #往前推所使用的Relu函數 self.mask = (x<=0) out = x out[out<=0] = 0 return out def backward(self, dout): #往回推所使用的Relu導函數 dx = dout dx[self.mask] = 0 return dx class Linear(): #Linear函數 def __init__(self, m, n): self.W, self.b = np.random.randn(m,n),np.random.randn(1,n) #隨機給予MxN個W和1xN個b self.dW , self.db = None,None #dW,db設為none def forward(self, x): self.x = x out = np.dot(x, self.W)+self.b #計算Wx+b放進out return out def backward(self, dout): #往回推計算學習後的dW和db dx = np.dot(dout, self.W.T) self.dW = np.dot(self.x.T, dout) self.db = np.sum(dout, axis = 0) return dx ``` 還會使用Loss函數來計算與測試資料的差別 ``` class Loss(): def __init__(self): pass def forward(self, y ,ybar): #y為算出的資料,ybar為訓練資料 self.ybar = ybar return np.sum((y-ybar)**2) def backward(self, dout): #往回推計算dy dy = -(2*(y-self.ybar)) return dy ``` 每多一層神經元,會多使用一層Linear函數和四選一的函數,為本題方便計算最後一層都為Sigmoid函數。 二層神經元的class和呼叫函數 ``` class TwoLayer(): def __init__(self, m, n, o): self.linear1 = Linear(m,n) #第一層 self.act1 = Tanh() self.linear2 = Linear(n,o) #第二層 self.act2 = Sigmoid() self.loss = Loss() #最後計算的Loss函數 self.last_dW1, self.last_db1 = 0 , 0 #初始化第一層最終的dW,db self.last_dW2, self.last_db2 = 0 , 0 #初始化第二層最終的dW,db def forward(self, x): #每層從Linear開始跑而後經過每層的函數 x = self.linear1.forward(x) x = self.act1.forward(x) x = self.linear2.forward(x) self.ybar = self.act2.forward(x) return self.ybar def backward(self, y): #從最後開始由導函數按照順序回頭調整資料 self.L = self.loss.forward(y,self.ybar) g = self.loss.backward(1) g = self.act2.backward(g) g = self.linear2.backward(g) g = self.act1.backward(g) g = self.linear1.backward(g) def update(self, eta, alpha): #使用eta和alpha來調整每層的Linear和最終W,b self.linear1.W = self.linear1.W-eta*self.linear1.dW + alpha*self.last_dW1 self.linear1.b = self.linear1.b-eta*self.linear1.db + alpha*self.last_db1 self.last_dW1 = eta*self.linear1.dW self.last_db1 = eta*self.linear1.db self.linear2.W = self.linear2.W-eta*self.linear2.dW + alpha*self.last_dW2 self.linear2.b = self.linear2.b-eta*self.linear2.db + alpha*self.last_db2 self.last_dW2 = eta*self.linear2.dW self.last_db2 = eta*self.linear2.db model = TwoLayer(8, 10, 1) #建立模型,初始進入8-bit,經過中間的神經元,最後輸出1-bit max_epochs, chk_epochs = 20000, 500 #最多20000次,每500次輸出一次 last_dW, last_db = 0, 0 eta, alpha = 0.02, 0.07 #eta是學習效率係數,alpha為衝量係數 Epochs_data=[] #儲存Epochs的List Loss_data=[] #儲存Loss值的List for e in range(max_epochs): model.forward(X) model.backward(y) model.update(eta, alpha) if (e+1)%chk_epochs == 0: print('epochs = %3d,loss = %.6f'%(e+1, model.L)) Loss_data.append(model.L) Epochs_data.append(e+1) plt.plot(Epochs_data,Loss_data,label='Loss_data',color='blue') #繪製曲線圖 plt.legend() plt.show() #輸出曲線圖 ``` 三層神經元的class和呼叫函數 ``` class ThreeLayer(): def __init__(self, m, n, o, p): self.linear1 = Linear(m,n) #第一層 self.act1 = Tanh() self.linear2 = Linear(n,o) #第二層 self.act2 = Relu() self.linear3 = Linear(o,p) #第三層 self.act3 = Sigmoid() self.loss = Loss() #最後計算的Loss函數 self.last_dW1, self.last_db1 = 0 , 0 #初始化第一層最終的dW,db self.last_dW2, self.last_db2 = 0 , 0 #初始化第二層最終的dW,db self.last_dW3, self.last_db3 = 0 , 0 #初始化第三層最終的dW,db def forward(self, x): #每層從Linear開始跑而後經過每層的函數 x = self.linear1.forward(x) x = self.act1.forward(x) x = self.linear2.forward(x) x = self.act2.forward(x) x = self.linear3.forward(x) self.ybar = self.act3.forward(x) return self.ybar def backward(self, y): #從最後開始由導函數按照順序回頭調整資料 self.L = self.loss.forward(y,self.ybar) g = self.loss.backward(1) g = self.act3.backward(g) g = self.linear3.backward(g) g = self.act2.backward(g) g = self.linear2.backward(g) g = self.act1.backward(g) g = self.linear1.backward(g) def update(self, eta, alpha): #使用eta和alpha來調整每層的Linear和最終W,b self.linear1.W = self.linear1.W-eta*self.linear1.dW + alpha*self.last_dW1 self.linear1.b = self.linear1.b-eta*self.linear1.db + alpha*self.last_db1 self.last_dW1 = eta*self.linear1.dW self.last_db1 = eta*self.linear1.db self.linear2.W = self.linear2.W-eta*self.linear2.dW + alpha*self.last_dW2 self.linear2.b = self.linear2.b-eta*self.linear2.db + alpha*self.last_db2 self.last_dW2 = eta*self.linear2.dW self.last_db2 = eta*self.linear2.db self.linear3.W = self.linear3.W-eta*self.linear3.dW + alpha*self.last_dW3 self.linear3.b = self.linear3.b-eta*self.linear3.db + alpha*self.last_db3 self.last_dW3 = eta*self.linear3.dW self.last_db3 = eta*self.linear3.db model = ThreeLayer(8, 10, 10, 1)#建立模型,初始進入8-bit,經過中間的神經元,最後輸出1-bit max_epochs, chk_epochs = 20000, 1000 #最多20000次,每1000次輸出一次 last_dW, last_db = 0, 0 eta, alpha = 0.001, 0.5 #eta是學習效率係數,alpha為衝量係數 Epochs_data=[] #儲存Epochs值的List Loss_data=[] #儲存Loss值的List for e in range(max_epochs): model.forward(x) model.backward(y) model.update(eta, alpha) if (e+1)%chk_epochs == 0: print('epochs = %3d,loss = %.6f'%(e+1, model.L)) Loss_data.append(model.L) Epochs_data.append(e+1) plt.plot(Epochs_data,Loss_data,label='Loss_data',color='blue') #繪製曲線圖 plt.legend() plt.show ``` 四層神經元的class和呼叫函數 ``` class FourLayer(): def __init__(self, m, n, o, p, q): self.linear1 = Linear(m,n) #第一層 self.act1 = Tanh() self.linear2 = Linear(n,o) #第二層 self.act2 = Relu() self.linear3 = Linear(o,p) #第三層 self.act3 = Relu() self.linear4 = Linear(p,q) #第四層 self.act4 = Sigmoid() self.loss = Loss() #最後計算的Loss函數 self.last_dW1, self.last_db1 = 0 , 0 #初始化第一層最終的dW,db self.last_dW2, self.last_db2 = 0 , 0 #初始化第二層最終的dW,db self.last_dW3, self.last_db3 = 0 , 0 #初始化第三層最終的dW,db self.last_dW4, self.last_db4 = 0 , 0 #初始化第四層最終的dW,db def forward(self, x): #每層從Linear開始跑而後經過每層的函數 x = self.linear1.forward(x) x = self.act1.forward(x) x = self.linear2.forward(x) x = self.act2.forward(x) x = self.linear3.forward(x) x = self.act3.forward(x) x = self.linear4.forward(x) self.ybar = self.act4.forward(x) return self.ybar def backward(self, y): #從最後開始由導函數按照順序回頭調整資料 self.L = self.loss.forward(y,self.ybar) g = self.loss.backward(1) g = self.act4.backward(g) g = self.linear4.backward(g) g = self.act3.backward(g) g = self.linear3.backward(g) g = self.act2.backward(g) g = self.linear2.backward(g) g = self.act1.backward(g) g = self.linear1.backward(g) def update(self, eta, alpha): #使用eta和alpha來調整每層的Linear和最終W,b self.linear1.W = self.linear1.W-eta*self.linear1.dW + alpha*self.last_dW1 self.linear1.b = self.linear1.b-eta*self.linear1.db + alpha*self.last_db1 self.last_dW1 = eta*self.linear1.dW self.last_db1 = eta*self.linear1.db self.linear2.W = self.linear2.W-eta*self.linear2.dW + alpha*self.last_dW2 self.linear2.b = self.linear2.b-eta*self.linear2.db + alpha*self.last_db2 self.last_dW2 = eta*self.linear2.dW self.last_db2 = eta*self.linear2.db self.linear3.W = self.linear3.W-eta*self.linear3.dW + alpha*self.last_dW3 self.linear3.b = self.linear3.b-eta*self.linear3.db + alpha*self.last_db3 self.last_dW3 = eta*self.linear3.dW self.last_db3 = eta*self.linear3.db self.linear4.W = self.linear4.W-eta*self.linear4.dW + alpha*self.last_dW4 self.linear4.b = self.linear4.b-eta*self.linear4.db + alpha*self.last_db4 self.last_dW4 = eta*self.linear4.dW self.last_db4 = eta*self.linear4.db model = FourLayer(8, 10, 10, 10, 1)#建立模型,初始進入8-bit,經過中間的神經元,最後輸出1-bit max_epochs, chk_epochs = 10000, 500 #最多10000次,每500次輸出一次 last_dW, last_db = 0, 0 eta, alpha = 0.001 , 0.6 #eta是學習效率係數,alpha為衝量係數 Loss_data=[] #儲存Loss值的List Epochs_data=[] #儲存Epochs值的List for e in range(max_epochs): model.forward(x) model.backward(y) model.update(eta, alpha) if (e+1)%chk_epochs == 0: print('epochs = %3d,loss = %.6f'%(e+1, model.L)) Loss_data.append(model.L) Epochs_data.append(e+1) plt.plot(Epochs_data,Loss_data,label='Loss_data',color='blue') #繪製曲線圖 plt.legend() plt.show() ``` <br> **開始訓練模型** 二層的訓練過程 ``` epochs = 500,loss = 64.006983 epochs = 1000,loss = 63.960385 epochs = 1500,loss = 41.666004 epochs = 2000,loss = 11.239978 epochs = 2500,loss = 9.035393 epochs = 3000,loss = 8.327138 epochs = 3500,loss = 7.651564 epochs = 4000,loss = 2.703534 epochs = 4500,loss = 2.179452 epochs = 5000,loss = 2.075702 epochs = 5500,loss = 2.031646 epochs = 6000,loss = 2.006583 epochs = 6500,loss = 1.989978 epochs = 7000,loss = 1.977873 epochs = 7500,loss = 1.968416 epochs = 8000,loss = 1.960591 epochs = 8500,loss = 1.953756 epochs = 9000,loss = 1.947417 epochs = 9500,loss = 1.941092 epochs = 10000,loss = 1.934153 epochs = 10500,loss = 1.925638 epochs = 11000,loss = 1.914327 epochs = 11500,loss = 1.900473 epochs = 12000,loss = 1.886242 epochs = 12500,loss = 1.868232 epochs = 13000,loss = 1.792538 epochs = 13500,loss = 1.548158 epochs = 14000,loss = 1.300410 epochs = 14500,loss = 1.124723 epochs = 15000,loss = 1.016667 epochs = 15500,loss = 0.827030 epochs = 16000,loss = 0.760825 epochs = 16500,loss = 0.724202 epochs = 17000,loss = 0.699248 epochs = 17500,loss = 0.680387 epochs = 18000,loss = 0.665197 epochs = 18500,loss = 0.652476 epochs = 19000,loss = 0.641561 epochs = 19500,loss = 0.632050 epochs = 20000,loss = 0.623675 ``` --- 三層神經元的訓練過程 ``` epochs = 1000,loss = 63.719888 epochs = 2000,loss = 63.422269 epochs = 3000,loss = 63.050350 epochs = 4000,loss = 61.718144 epochs = 5000,loss = 59.181346 epochs = 6000,loss = 55.746686 epochs = 7000,loss = 51.429207 epochs = 8000,loss = 45.477023 epochs = 9000,loss = 39.902673 epochs = 10000,loss = 34.967170 epochs = 11000,loss = 28.262937 epochs = 12000,loss = 22.592299 epochs = 13000,loss = 18.526720 epochs = 14000,loss = 14.513283 epochs = 15000,loss = 9.566735 epochs = 16000,loss = 6.163954 epochs = 17000,loss = 3.994223 epochs = 18000,loss = 2.747954 epochs = 19000,loss = 2.063435 epochs = 20000,loss = 1.621340 ``` --- 四層神經元的訓練過程 ``` epochs = 500,loss = 64.850557 epochs = 1000,loss = 60.814486 epochs = 1500,loss = 54.855777 epochs = 2000,loss = 41.767946 epochs = 2500,loss = 25.836491 epochs = 3000,loss = 14.888509 epochs = 3500,loss = 4.237126 epochs = 4000,loss = 2.617696 epochs = 4500,loss = 2.017337 epochs = 5000,loss = 1.709142 epochs = 5500,loss = 1.513393 epochs = 6000,loss = 1.391095 epochs = 6500,loss = 1.311712 epochs = 7000,loss = 1.254371 epochs = 7500,loss = 1.212571 epochs = 8000,loss = 1.181797 epochs = 8500,loss = 1.158027 epochs = 9000,loss = 1.138851 epochs = 9500,loss = 1.123523 epochs = 10000,loss = 1.110921 ``` <br> **繪製學習曲線圖** 使用matplotlib模組可以繪製學習曲線圖,使用以下程式碼儲存資料、繪圖、印出曲線圖 ``` import matplotlib.pyplot as plt Loss_data=[] #儲存Epochs值的List Epochs_data=[] #儲存Loss值的List for e in range(max_epochs): model.forward(x) model.backward(y) model.update(eta, alpha) if (e+1)%chk_epochs == 0: print('epochs = %3d,loss = %.6f'%(e+1, model.L)) Loss_data.append(model.L) Epochs_data.append(e+1) plt.plot(Epochs_data,Loss_data,label='Loss_data',color='blue') #繪製曲線圖 plt.legend() plt.show() ``` 二層的學習曲線圖 ![](https://i.imgur.com/1c2vBop.png) --- 三層的學習曲線圖 ![](https://i.imgur.com/Gokedc2.png) --- 四層的學習曲線圖 ![](https://i.imgur.com/yIrtXgp.png) <br> **顯示訓練後結果** 二層最後的256個輸出結果 ``` 5.06565127e-03 9.94308914e-01 9.97965508e-01 3.05645022e-03 9.97951422e-01 3.06003186e-03 1.54950197e-02 9.98107911e-01 9.94381568e-01 3.00221062e-02 3.28890245e-03 9.93888754e-01 3.29298956e-03 9.93877828e-01 9.97919634e-01 2.23539564e-03 9.99910383e-01 2.71903334e-02 6.26887770e-03 9.99863328e-01 6.26610399e-03 9.99863659e-01 9.95304535e-01 5.55687840e-03 2.77555471e-02 4.88225575e-01 9.99878940e-01 2.81686918e-02 9.99879231e-01 2.81938445e-02 5.53988538e-03 9.99746427e-01 9.98484179e-01 1.52990421e-02 1.58075755e-02 9.97735420e-01 1.58128244e-02 9.97742132e-01 9.62548091e-01 7.39970498e-03 1.41027681e-02 9.95621978e-01 9.97909736e-01 1.46640927e-02 9.97915683e-01 1.45629891e-02 6.87586063e-03 9.96495564e-01 7.57311122e-03 9.99533641e-01 9.90469364e-01 5.71818308e-03 9.90459812e-01 5.72363275e-03 3.33825045e-03 9.90266732e-01 9.99657582e-01 1.52537580e-02 5.86530564e-03 9.98266819e-01 5.87126645e-03 9.98285305e-01 9.90113502e-01 4.61414015e-03 9.97994277e-01 3.02114883e-03 1.55149429e-02 9.98147905e-01 1.55097680e-02 9.98135018e-01 9.62231851e-01 7.64591856e-03 3.24967827e-03 9.93849946e-01 9.97962706e-01 2.21338750e-03 9.97948800e-01 2.21547854e-03 7.04860619e-03 9.98004674e-01 6.25459002e-03 9.99861577e-01 9.95318003e-01 5.55148823e-03 9.95314039e-01 5.55173119e-03 4.19589370e-03 9.95084986e-01 9.99877426e-01 2.80794041e-02 5.53390395e-03 9.99740821e-01 5.53407409e-03 9.99741541e-01 9.95024138e-01 5.09987411e-03 1.57982273e-02 9.97717595e-01 9.62546954e-01 7.39451415e-03 9.62546937e-01 7.39630775e-03 8.11158251e-02 9.82342767e-01 9.97893780e-01 1.48132451e-02 6.87045713e-03 9.96449975e-01 6.87226859e-03 9.96463353e-01 9.83124936e-01 3.80364655e-03 9.90488601e-01 5.70005201e-03 3.33985235e-03 9.90297152e-01 3.33942635e-03 9.90287193e-01 9.85775927e-01 2.38689147e-03 5.84502694e-03 9.98193767e-01 9.90144455e-01 4.59766912e-03 9.90134311e-01 4.60311760e-03 2.30093542e-03 9.89836720e-01 9.99011151e-01 1.11081633e-02 2.10845968e-03 9.98383910e-01 2.12621651e-03 9.98379169e-01 9.91084914e-01 9.47562582e-04 1.09317856e-02 9.40291138e-01 9.98412945e-01 1.18786304e-02 9.98408304e-01 1.18667542e-02 1.10908125e-03 9.97228961e-01 8.78837265e-03 9.39570400e-01 9.99745587e-01 7.67195866e-03 9.99744301e-01 7.70083729e-03 1.39183665e-03 9.99550352e-01 9.39470959e-01 5.60921041e-01 8.23351166e-03 9.60476406e-01 8.26426797e-03 9.60489681e-01 9.99563822e-01 7.24944411e-03 7.04162795e-03 9.99258320e-01 9.91113407e-01 5.77328971e-03 9.91094791e-01 5.78930033e-03 3.49776529e-03 9.91354895e-01 9.99266755e-01 6.02184378e-03 5.99615977e-03 9.98790007e-01 6.01302034e-03 9.98784491e-01 9.91096992e-01 5.41251859e-03 9.99622621e-01 1.42631682e-02 2.63952188e-03 9.98824236e-01 2.63602473e-03 9.98819382e-01 9.86148598e-01 1.63072999e-03 1.38244041e-02 9.58712010e-01 9.98937813e-01 1.57629586e-02 9.98933216e-01 1.57328770e-02 1.66647590e-03 9.95438624e-01 2.05867091e-03 9.98373107e-01 9.91146930e-01 9.23035163e-04 9.91142942e-01 9.29705652e-04 1.39150442e-02 9.92769434e-01 9.98402827e-01 1.19039376e-02 1.07930358e-03 9.97212281e-01 1.08739349e-03 9.97202179e-01 9.92483419e-01 5.88406506e-04 9.99744816e-01 7.59257700e-03 1.40600519e-03 9.99548313e-01 1.39817216e-03 9.99546303e-01 9.93974095e-01 1.04281485e-03 8.14916714e-03 9.60542190e-01 9.99562405e-01 7.14798780e-03 9.99560324e-01 7.17428570e-03 9.96317180e-04 9.99032923e-01 9.91174406e-01 5.74107222e-03 3.50799738e-03 9.91409343e-01 3.50510770e-03 9.91399727e-01 9.81239066e-01 2.71148160e-03 5.96167235e-03 9.98773843e-01 9.91161743e-01 5.37782286e-03 9.91149085e-01 5.39145587e-03 2.58686648e-03 9.90808356e-01 2.63152653e-03 9.98806099e-01 9.86134573e-01 1.63037810e-03 9.86159854e-01 1.62823925e-03 3.21099694e-02 9.87536218e-01 9.98922385e-01 1.58243357e-02 1.66527561e-03 9.95346922e-01 1.66328399e-03 9.95329741e-01 9.87475850e-01 1.07434743e-03 ``` 最後的Loss值 ``` epochs = 20000,loss = 0.623675 ``` 三層最後的256個輸出結果 ``` 6.30075104e-04 9.87412179e-01 9.97117168e-01 3.56296033e-05 9.63390563e-01 4.68022487e-02 1.34084508e-02 9.89557079e-01 8.35154986e-01 6.69495123e-03 9.99585316e-02 9.97631620e-01 2.13484637e-01 9.57111657e-01 7.75058083e-01 2.45574534e-02 9.74597353e-01 1.38918482e-01 6.22203548e-06 9.74717073e-01 2.71162348e-02 9.65643253e-01 9.96212155e-01 4.03896462e-02 2.53471433e-03 9.90987883e-01 9.97573925e-01 4.69151617e-05 9.88048753e-01 4.61275486e-02 7.45971493e-03 9.92068555e-01 9.74268745e-01 1.94253525e-02 2.95491464e-02 9.96434522e-01 1.22853239e-01 8.40082802e-01 9.82182573e-01 1.71816247e-02 1.22000009e-01 9.82712414e-01 8.64265759e-01 3.37232765e-02 9.99234095e-01 6.45021671e-02 1.45806577e-01 9.88962635e-01 1.06144100e-02 9.20164391e-01 9.84245857e-01 8.39425179e-03 8.53883597e-01 1.28449766e-01 8.56537796e-02 9.38981574e-01 9.96691496e-01 3.18502087e-02 8.90232817e-02 9.97967577e-01 1.07574241e-01 7.95194617e-01 9.92530909e-01 2.51606709e-02 9.59708810e-01 4.99763937e-04 3.39686518e-02 9.96489389e-01 1.71227370e-02 9.86995226e-01 9.94410783e-01 2.63571317e-04 2.18778152e-01 9.93244780e-01 9.99673723e-01 3.84390956e-02 7.39620680e-01 2.39471871e-02 2.34738818e-01 9.06066573e-01 1.10060601e-04 8.94033102e-01 9.23254653e-01 9.22028337e-02 9.73894395e-01 8.99798476e-02 1.26990222e-04 9.91079817e-01 9.67602686e-01 7.18839635e-04 4.28317178e-02 9.96499401e-01 1.53128466e-02 9.91985855e-01 9.83920947e-01 2.68787116e-04 4.37653790e-02 9.92884952e-01 8.77868197e-01 6.27593971e-04 9.65425401e-01 1.54079985e-03 1.56875018e-02 9.97617759e-01 7.97435935e-01 2.89314939e-02 2.03215120e-01 9.95167301e-01 1.75053343e-01 9.93607770e-01 7.63943454e-01 3.76344869e-02 9.99009800e-01 4.43524598e-02 6.08078923e-04 9.39688778e-01 3.05140346e-03 9.20493979e-01 9.70174022e-01 4.61689552e-02 7.51395310e-02 9.96904065e-01 9.07502593e-01 1.13025377e-03 9.60214027e-01 2.34497439e-03 4.46759063e-02 9.97337897e-01 9.88963040e-01 6.87358172e-02 3.74936278e-05 8.95142609e-01 4.51068312e-02 9.46631402e-01 9.93474475e-01 1.39734387e-01 7.90602409e-03 9.93878149e-01 9.96953220e-01 6.90780210e-04 9.53636603e-01 6.17013730e-02 3.17166385e-02 9.96108884e-01 1.34088278e-01 8.83844367e-01 9.76455839e-01 1.09119317e-01 9.66511240e-01 1.42986182e-01 3.42605307e-02 8.15934712e-01 9.92261735e-01 5.86817862e-02 3.88068750e-05 8.66032301e-01 5.60372440e-02 9.65814015e-01 9.93808772e-01 1.24843786e-01 2.33492448e-02 9.40702178e-01 9.98161927e-01 4.95981633e-02 8.15652539e-01 1.59850806e-01 2.06672988e-02 9.32716600e-01 9.82424289e-01 7.27609196e-02 4.70132966e-02 9.97055771e-01 9.58601241e-02 8.16530316e-01 9.95646545e-01 1.22782504e-02 9.31554308e-01 1.53013999e-01 1.01127268e-02 9.10443331e-01 1.25822924e-01 9.72867443e-01 9.59248228e-01 5.01153526e-02 4.90499189e-02 9.51884677e-01 9.98776160e-01 3.78427039e-02 8.23120290e-01 1.62808760e-01 3.81261163e-02 9.17998435e-01 6.08108342e-04 9.06682062e-01 9.96970308e-01 7.92051458e-02 9.93375228e-01 8.66272806e-02 3.04936027e-04 9.09520385e-01 9.93839535e-01 1.32330704e-03 4.47108897e-02 9.49813719e-01 2.81502079e-02 9.93879296e-01 9.19055578e-01 6.01018610e-03 8.99412641e-01 2.19016157e-01 9.08974020e-02 8.27809174e-01 8.72330236e-02 8.08258048e-01 9.93486455e-01 8.99356052e-02 7.65079928e-04 8.89231610e-01 9.96716823e-01 1.02965756e-01 9.95548239e-01 7.88945721e-02 3.40673327e-04 9.03977244e-01 9.91093959e-01 1.17508576e-01 9.95902527e-04 9.98247318e-01 2.30885543e-03 9.57274482e-01 9.99004351e-01 5.10899280e-02 5.46362551e-02 9.98462364e-01 9.93049633e-01 1.62383681e-03 9.95703085e-01 2.80585660e-03 2.75710096e-02 9.97874750e-01 4.88903074e-02 7.77309402e-01 9.53106800e-01 9.54789746e-02 9.24408857e-01 1.00404942e-01 5.23241326e-02 9.54147637e-01 9.98151306e-01 8.90220385e-02 1.13966581e-03 9.97893411e-01 3.73579608e-03 9.47928508e-01 9.98803848e-01 3.08694304e-02 ``` 最後的Loss值 ``` epochs = 20000,loss = 1.621340 ``` 四層最後的256個輸出結果 ``` 0.02703342 0.9997266 0.96434816 0.00872148 0.99977255 0.00588859 0.01631082 0.99975773 0.98792582 0.00676656 0.00460467 0.99356196 0.00804919 0.97464623 0.99126323 0.01150138 0.99964793 0.00698693 0.01247588 0.99967225 0.00721424 0.96988608 0.99974821 0.00498008 0.00870172 0.99824273 0.97568426 0.00630293 0.99905684 0.00924758 0.00798213 0.99884483 0.99155919 0.00388602 0.00293092 0.99610998 0.0059407 0.99598387 0.99776406 0.0030091 0.00364455 0.98963164 0.97601486 0.00291671 0.99030807 0.01258211 0.00321267 0.98254445 0.0050546 0.9977336 0.99927981 0.0059216 0.99713916 0.03914043 0.00411022 0.99840139 0.99866663 0.02138521 0.00344153 0.99851854 0.02090338 0.99847959 0.99824453 0.01459646 0.99973362 0.00545886 0.00859084 0.99984869 0.00625143 0.98778296 0.99984151 0.00402625 0.00715914 0.97725328 0.99331943 0.01658061 0.97093919 0.01520107 0.01465205 0.97306428 0.00750264 0.97927037 0.99976247 0.00485207 0.98090426 0.0662089 0.004939 0.98206748 0.99866744 0.01031971 0.00716142 0.99130063 0.01044761 0.92891994 0.99865188 0.00714822 0.00467602 0.99653061 0.99658791 0.00263037 0.99650455 0.08853935 0.00269588 0.99746052 0.98893965 0.01309402 0.00315638 0.98427122 0.01817288 0.94914373 0.98477915 0.00755183 0.99804299 0.04616213 0.00654843 0.99892273 0.03732178 0.87580975 0.99868447 0.0487141 0.02114952 0.98169323 0.9988512 0.01296707 0.9975096 0.06924399 0.01331219 0.99528152 0.99519531 0.01352103 0.99987886 0.99881119 0.02337009 0.99423919 0.99899635 0.00734103 0.01454398 0.98007931 0.94553297 0.01189111 0.97101532 0.01894722 0.02000454 0.98996579 0.02632993 0.99680696 0.99726402 0.02668914 0.9969222 0.01536692 0.0261257 0.99654932 0.98303638 0.0192096 0.04556013 0.97588533 0.01882383 0.98286538 0.98621335 0.0324123 0.01818293 0.99947004 0.97237642 0.01090769 0.99960236 0.00596079 0.02364898 0.99965769 0.99390101 0.00779484 0.00682176 0.99293197 0.00823552 0.97078533 0.99362855 0.01333203 0.99946338 0.00763562 0.01301885 0.99966069 0.01008159 0.96917283 0.99970943 0.00488672 0.00717558 0.98677254 0.97828321 0.00646851 0.98243167 0.0114093 0.00625458 0.98526655 0.00706674 0.99390027 0.99821516 0.0071698 0.99220796 0.00975581 0.00647336 0.995081 0.98571092 0.01893768 0.01143141 0.99113047 0.01081838 0.96215191 0.98979431 0.04723369 0.99552842 0.01039407 0.02197644 0.99682124 0.00814605 0.96053097 0.99673047 0.01395353 0.01501896 0.97971788 0.97967936 0.03430472 0.97230421 0.01443078 0.02835657 0.97699346 0.99968362 0.00497827 0.00884332 0.99970753 0.00780441 0.98663913 0.999745 0.00311976 0.01089792 0.97027835 0.98937393 0.02138175 0.95355966 0.01682119 0.01799441 0.97553557 0.00944472 0.97909898 0.99976587 0.00453673 0.97321851 0.06182825 0.0048744 0.9878081 0.98286013 0.01243165 0.00751149 0.98703873 0.01452024 0.9313321 0.98630306 0.00754203 ``` 最後的Loss值 ``` epochs = 10000,loss = 1.110921 ``` **比較兩層、三層、四層** 在兩層、三層、四層的程式碼中,eta以及alpha值的調整是需要比較的地方,當層數比較少時,學習效率係數和衝量係數可以比較大,一樣可以得到較小的Loss值,但是容易浮動,有較高的機率會得到很高的Loss值。 但相反的,在層數越高的神經元網路中,學習效率係數和衝量係數會越來越小,但是只要調整成功了,Loss值的浮動不會像少層的一樣浮動大,只會在小範圍中浮動。