1. 程式人生 > >實現數字手寫圖片識別(純程式碼)

實現數字手寫圖片識別(純程式碼)

假設環境都OK

import scipy.special

class NeuralNetWork:
    def __init__(self,inputnodes,hiddennodes,outputnodes,learningrate):
        #初始化網路,設定網路值,中間層,和輸出層節點數
        self.inodes=inputnodes
        self.hnodes=hiddennodes
        self.onodes=outputnodes
        
        #設定學習效率
        self.lr=learningrate
        '''
        初始化權重矩陣,我們有兩個權重矩陣,一個是wish表示輸入層和中間層節點間鏈路權重形成的矩陣
        '''
        self.wih=numpy.random.rand(self.hnodes,self.inodes)-0.5
        self.who=numpy.random.rand(self.onodes,self.hnodes)-0.5  #作者寫錯了
        
        
        self.activation_function=lambda x:scipy.special.expit(x)
        
        pass
    
    def train(self,inputs_list,targets_list):
        #根據輸入的訓練資料更新節點鏈路權重
        '''
        把inputs_list,targets_list轉化成numpy支援的二維矩陣
        
        '''
        print(inputs_list.shape)
        print(targets_list.shape)
        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-final_outputs)),numpy.transpose(hidden_outputs))
        self.wih +=self.lr*numpy.dot((hidden_errors*hidden_outputs*(1-hidden_outputs)),numpy.transpose(inputs))
        pass
    
    def query(self,inputs):
        #根據輸入資料計算並輸出答案
        #計算中間層從輸入層接受到的訊號量
        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)
        
        print(final_outputs)
        return final_outputs
        pass




#初始化網路 
input_nodes = 784
hidden_nodes = 100
output_nodes = 10
learning_rate = 0.3 
n = NeuralNetWork(input_nodes, hidden_nodes, output_nodes, learning_rate) 
#讀入訓練資料 
#open函式裡的路徑根據資料儲存的路徑來設定 
training_data_file = open("/home/zbl/data/mnist_train.csv") 
trainning_data_list = training_data_file.readlines()
print(len(trainning_data_list ))
training_data_file.close() 
#把資料依靠','區分,並分別讀入 
for record in trainning_data_list: 
    all_values = record.split(',') 
    inputs = (numpy.asfarray(all_values[1:]))/255.0 * 0.99 + 0.01
    #設定圖片與數值的對應關係 
    targets = numpy.zeros(output_nodes) + 0.01 
    targets[int(all_values[0])] = 0.99
    
    n.train(inputs, targets)


#open函式里路徑
test_data_file = open("/home/zbl/data/mnist_test.csv")
test_data_list = test_data_file.readlines()
test_data_file.close() 
import numpy 
import matplotlib.pyplot 
%matplotlib inline 
#把資料依靠','區分,並分別讀入 
all_values = test_data_list[6].split(',') 
#第一個值對應的是圖片的表示的數字,所以我們讀取圖片資料時要去掉第一個數值 
image_array = numpy.asfarray(all_values[1:]).reshape((28, 28))
matplotlib.pyplot.imshow(image_array, cmap='Greys', interpolation='None')
label = numpy.argmax(n.query(numpy.asfarray(all_values[1:]) / 255.0 * 0.99 + 0.01 ))
#print(n.query(numpy.asfarray(all_values[1:]) / 255.0 * 0.99 + 0.01 ).type)
print(label)





scores = [] 
for record in test_data_list: 
    all_values = record.split(',') 
    correct_number = int(all_values[0])
    print("該圖片對應的數字為:",correct_number)
    #預處理數字圖片
    inputs = (numpy.asfarray(all_values[1:])) / 255.0 * 0.99 + 0.01 
    #讓網路判斷圖片對應的數字 
    outputs = n.query(inputs) 
    #找到數值最大的神經元對應的編號 
    
   # print("out put is : ", outputs)
    label = numpy.argmax(outputs)
    print("out put reslut is : ", label)
    #print("網路認為圖片的數字是:", label)
    if label == correct_number: 
        scores.append(1) 
    else: scores.append(0)
print(scores)
scores_array = numpy.asarray(scores)
print("perfermance = ", scores_array.sum() / scores_array.size)

注:測試集和訓練集需要單獨下載,放在本地。