程式碼實現三層神經網路的手寫字訓練及測試
- 2019 年 10 月 5 日
- 筆記
本篇使用的原理和計算公式是來自於上一篇:神經元矩陣計算示例
廢話不說直接上程式碼:
import numpy import scipy.special import matplotlib.pyplot class network: def __init__(self , inputnodes, hiddennodes, outputnodes,learningrate ): self.inputnodes=inputnodes self.hiddennodes=hiddennodes self.outputnodes=outputnodes self.lr=learningrate # 計算輸入層隱藏層的權重係數 self.wih = numpy.random.normal(0.0, pow(self.hiddennodes, -0.5),(self.hiddennodes, self.inputnodes)) # 計算隱藏層輸出層的權重係數 self.who = numpy.random.normal(0.0, pow(self.outputnodes, -0.5),(self.outputnodes, self.hiddennodes)) # 定義激活函數,使用scipy中的expit函數 self.activation_function = lambda x:scipy.special.expit(x) # 訓練神經網路 def train(self, inputs_list, targets_list): # 將輸入轉化為2維矩陣 inputs = numpy.array(inputs_list, ndmin=2).T targets = numpy.array(targets_list, ndmin=2).T # 計算隱藏層的輸入 hidden_inputs = numpy.dot(self.wih, inputs) # 計算激活函數處理後隱藏層的輸入變成輸出 hidden_outputs = self.activation_function(hidden_inputs) # 計算輸出層的輸入 final_inputs = numpy.dot(self.who, hidden_outputs) #計算激活函數處理後輸出層的輸入變成輸出 final_outputs = self.activation_function(final_inputs) output_errors = targets - final_outputs # 計算輸出層隱藏層的誤差矩陣 hidden_errors = numpy.dot(self.who.T, output_errors) # 更新輸出層隱藏層的權重 self.who += self.lr * numpy.dot((output_errors *final_outputs * (1.0 - final_outputs)),numpy.transpose(hidden_outputs)) # 更新隱藏層隱藏層的權重 self.wih += self.lr * numpy.dot((hidden_errors *hidden_outputs * (1.0 - hidden_outputs)), numpy.transpose(inputs)) pass # query the neural network def query(self,inputs_list): # 將輸入轉化為二維矩陣 inputs = numpy.array(inputs_list, ndmin=2).T # 計算隱藏層的輸入 hidden_inputs = numpy.dot(self.wih, inputs) # 計算激活函數處理後隱藏層的輸入變成輸出 hidden_outputs = self.activation_function(hidden_inputs) # 計算輸出層的輸入 final_inputs = numpy.dot(self.who, hidden_outputs) # 計算激活函數處理後輸出層的輸入變成輸出 final_outputs = self.activation_function(final_inputs) return final_outputs pass #載入數據進行訓練 def train_datas(output_nodes,network): with open('/home/opprash/Desktop/mnist_train_100.csv', 'r') as f: data_list = f.readlines() f.close() #可視化csv中的數字的意義 # all_values = data_list[1].split(',') # image_array = numpy.asfarray(all_values[1:]).reshape((28, 28)) # matplotlib.pyplot.imshow(image_array, cmap='Greys', interpolation='None') # matplotlib.pyplot.show() # scaled_input = (numpy.asfarray(all_values[1:]) / 255.0 * 0.99) + 0.01 # print(scaled_input) # 訓練神經網路 # 遍歷訓練集的所有數據 for record in data_list: # 以逗號分割 all_values = record.split(',') # 將數據壓縮到0到1之間,原始數據是在0-255之間 inputs = (numpy.asfarray(all_values[1:]) / 255.0 * 0.99) + 0.01 # 創建目標輸出值(全部0.01,除了所需的值標籤是0.99) targets = numpy.zeros(output_nodes) + 0.01 # all_values[0] 是此記錄的目標標籤 targets[int(all_values[0])] = 0.99 network.train(inputs, targets) pass #載入數據進行測試 def test_data(network): with open('/home/opprash/Desktop/mnist_test_10.csv', 'r') as f: data_list = f.readlines() f.close() scorecard = [] for record in data_list: # 以逗號分割 all_values = record.split(',') # 正確答案是第一個值 correct_label = int(all_values[0]) print( "真實的標籤",correct_label) # 將數據壓縮到0到1之間,原始數據是在0-255之間 inputs = (numpy.asfarray(all_values[1:]) / 255.0 * 0.99) + 0.01 # 使用網路進行查詢 outputs = network.query(inputs) # 最高值的索引就是對應的標籤 label = numpy.argmax(outputs) print("神經網路預測的答案:",label) # 追加正確或者不正確的list if (label == correct_label): # 網路的答案匹配正確的答案,添加1 scorecard.append(1) else: # 網路的答案匹配不正確的答案,添加0 scorecard.append(0) scorecard_array = numpy.asarray(scorecard) print("準確率 = ", scorecard_array.sum()/scorecard_array.size) if __name__ == '__main__': # 定義輸入,隱藏層,輸出層節點個數 input_nodes = 784 hidden_nodes = 100 output_nodes = 10 # 學習率 0.3 learning_rate = 0.3 # 實例化神經網路 n = network(input_nodes,hidden_nodes,output_nodes,learning_rate) train_datas(output_nodes,n) test_data(n)
運行結果:
