python神經網絡編程之手寫數字識別
寫在之前
首先是寫在之前的一些建議:
首先是關於這本書,我真的認為他是將神經網絡裡非常棒的一本書,但你也需要註意,如果你真的想自己動手去實現,那麼你一定需要有一定的python基礎,並且還需要有一些python數據科學處理能力
然後希望大傢在看這邊博客的時候對於神經網絡已經有一些瞭解瞭,知道什麼是輸入層,什麼是輸出層,並且明白他們的一些理論,在這篇博客中我們僅僅是展開一下代碼;
然後介紹一下本篇博客的環境等:
語言:Python3.8.5
環境:jupyter
庫文件: numpy | matplotlib | scipy
一、代碼框架
我們即將設計一個神經網絡對象,它可以幫我們去做數據的訓練,以及數據的預測,所以我們將具有以下的三個方法:
首先我們需要初始化這個函數,我們希望這個神經網絡僅有三層,因為再多也不過是在隱藏層去做文章,所以先做一個簡單的。那麼我們需要知道我們輸入層、隱藏層和輸出層的節點個數;訓練函數,我們需要去做訓練,得到我們需要的權重。通過我們已有的權重,將給定的輸入去做輸出。
二、準備工作
現在我們需要準備一下:
1.將我們需要的庫導入
import numpy as np import scipy.special as spe import matplotlib.pyplot as plt
2.構建一個類
class neuralnetwork: # 我們需要去初始化一個神經網絡 def __init__(self, inputnodes, hiddennodes, outputnodes, learningrate): pass def train(self, inputs_list, targets_list): pass def query(self, inputs_list): pass
3.我們的主函數
input_nodes = 784 # 輸入層的節點數 hidden_nodes = 88 # 隱藏層的節點數 output_nodes = 10 # 輸出層的節點數 learn_rate = 0.05 # 學習率 n = neuralnetwork(input_nodes, hidden_nodes, output_nodes, learn_rate)
4.導入文件
data_file = open("E:\sklearn_data\神經網絡數字識別\mnist_train.csv", 'r') data_list = data_file.readlines() data_file.close() file2 = open("E:\sklearn_data\神經網絡數字識別\mnist_test.csv") answer_data = file2.readlines() file2.close()
這裡需要介紹以下這個數據集,訓練集在這裡,測試集在這裡
三、框架的開始
def __init__(self, inputnodes, hiddennodes, outputnodes, learningrate): self.inodes = inputnodes # 輸入層節點設定 self.hnodes = hiddennodes # 影藏層節點設定 self.onodes = outputnodes # 輸出層節點設定 self.lr = learningrate # 學習率設定,這裡可以改進的 self.wih = (np.random.normal(0.0, pow(self.hnodes, -0.5),(self.hnodes, self.inodes))) # 這裡是輸入層與隱藏層之間的連接 self.who = (np.random.normal(0.0, pow(self.onodes, -0.5),(self.onodes, self.hnodes))) # 這裡是隱藏層與輸出層之間的連接 self.activation_function = lambda x: spe.expit(x) # 返回sigmoid函數
Δw j,k =α∗E k ∗ sigmoid (O k )∗(1−sigmoid(O k ))⋅O j ⊤
def query(self, inputs_list): inputs = np.array(inputs_list, ndmin=2).T # 輸入進來的二維圖像數據 hidden_inputs = np.dot(self.wih, inputs) # 隱藏層計算,說白瞭就是線性代數中的矩陣的點積 hidden_outputs = self.activation_function(hidden_inputs) # 將隱藏層的輸出是經過sigmoid函數處理 final_inputs = np.dot(self.who, hidden_outputs) # 原理同hidden_inputs final_outputs = self.activation_function(final_inputs) # 原理同hidden_outputs return final_outputs # 最終的輸出結果就是我們預測的數據
這裡我們對預測這一部分做一個簡單的解釋:我們之前的定義輸出的節點是10個,對應的是十個數字。
而為什麼會通過神經網絡能達到這個亞子,我推薦這本書深度學習的數學 這本書的理論講解非常不錯!!!
四、訓練模型構建
之前的部分相對而言還是比較簡單的,那麼接下來就是如何去構建訓練模型瞭。
def train(self, inputs_list, targets_list): # 前期和識別過程是一樣的,說白瞭我們與要先看看現在的預測結果如何,隻有根據這次的預期結果才能去修改之前的權重 inputs = np.array(inputs_list, ndmin=2).T hidden_inputs = np.dot(self.wih, inputs) hidden_outputs = self.activation_function(hidden_inputs) final_inputs = np.dot(self.who, hidden_outputs) final_outputs = self.activation_function(final_inputs) # 接下來將標簽拿遲來 targets = np.array(targets_list, ndmin=2).T # 得到我們的數據預測的誤差,這個誤差將是向前反饋的基礎 output_errors = targets - final_outputs # 這部分是根據公式得到的反向傳播參數 hidden_errors = np.dot(self.who.T, output_errors) # 根據我們的反饋參數去修改兩個權重 self.who += self.lr * np.dot((output_errors * final_outputs * ( 1.0-final_outputs)), np.transpose(hidden_outputs)) self.wih += self.lr * np.dot((hidden_errors * hidden_outputs * (1.0-hidden_outputs)), np.transpose(inputs))
如此我們的基礎神經網絡構建完成瞭。
五、手寫數字的識別
接下來神經網絡是完成的,那麼我們究竟該如何去將數據輸入呢?
csv文件我們並不陌生【或許陌生?】,他是逗號分割文件,顧名思義,它是通過逗號分隔的,所以我們可以打開看一下:
眼花繚亂!!
但是細心的我們可以發現他的第一個數字都是0~9,說明是我們的標簽,那麼後面的應該就是圖像瞭,通過瞭解我們知道這個後面的數據是一個28*28的圖像。
all_value = data_list[0].split(',') # split分割成列表 image_array = np.asfarray(all_value[1:]).reshape((28,28)) # 將數據reshape成28*28的矩陣 plt.imshow(image_array, cmap='Greys', interpolation='None') # 展示一下
通過這段代碼,我們可以簡單的看一下每個數字是什麼:
很好,知道這裡就足夠瞭,那麼我們接下來就是將這些數據傳入瞭!
我們在訓練的時候,需要將他們都轉化成數字列表,方便處理
data = [] # 用來保存訓練過程的數據 sum_count = 0 # 統計總識別的正確的個數 for i in range(15): # 訓練的輪數 count = 0 # 單次訓練識別正確的個數 for j in range(len(data_list)): # 對60000張圖片開始訓練, 沒有劃分數據集的過程主要是別人直接給瞭,我也懶得自己去做瞭,主要就是展示一下神經網絡嘛~ target = np.zeros(10)+0.01 # 生成初始標簽集合,用來和結果對比 line_ = data_list[j].split(',') # 對每一行的數據處理切割 imagearray = np.asfarray(line_) # 將切割完成的數據轉換成數字列表 target[int(imagearray[0])] = 1.0 # 將正確答案挑出來 n.train(imagearray[1:]/255*0.99+0.01, target) # 丟入訓練,丟入的時候註意將數據轉換成0.01~1.0之間的結果 for line in answer_data: # 對10000組測試集測試 all_values = line.split(',') answer = n.query((np.asfarray(all_values[1:])/255*0.99)+0.01) if answer[int(all_values[0])] > 0.85: # 查看對應位置是否達到自定義的閾值? count += 1 sum_count += count string = "訓練進度 %05f\n本輪準確度 %05f\n總準確度 %05f\n\n"%(i/120,count/len(answer_data), sum_count/(len(answer_data)*(i+1))) data.append([i/120,count/len(answer_data), sum_count/(len(answer_data)*(i+1))]) # 將數據保存方便生成訓練曲線 print(string) ``` 接下來我們將結果圖片展示以下吧~ ```python data = np.array(data) plt.plot(range(len(data)), data[:, 1:])
六、源碼
把源碼整理一下貼出來
import numpy as np import scipy.special as spe import matplotlib.pyplot as plt class neuralnetwork: # 我們需要去初始化一個神經網絡 def __init__(self, inputnodes, hiddennodes, outputnodes, learningrate): self.inodes = inputnodes self.hnodes = hiddennodes self.onodes = outputnodes self.lr = learningrate self.wih = (np.random.normal(0.0, pow(self.hnodes, -0.5),(self.hnodes, self.inodes))) self.who = (np.random.normal(0.0, pow(self.onodes, -0.5),(self.onodes, self.hnodes))) self.activation_function = lambda x: spe.expit(x) # 返回sigmoid函數 def train(self, inputs_list, targets_list): inputs = np.array(inputs_list, ndmin=2).T hidden_inputs = np.dot(self.wih, inputs) hidden_outputs = self.activation_function(hidden_inputs) final_inputs = np.dot(self.who, hidden_outputs) final_outputs = self.activation_function(final_inputs) targets = np.array(targets_list, ndmin=2).T output_errors = targets - final_outputs hidden_errors = np.dot(self.who.T, output_errors) self.who += self.lr * np.dot((output_errors * final_outputs * ( 1.0-final_outputs)), np.transpose(hidden_outputs)) self.wih += self.lr * np.dot((hidden_errors * hidden_outputs * (1.0-hidden_outputs)), np.transpose(inputs)) def query(self, inputs_list): inputs = np.array(inputs_list, ndmin=2).T hidden_inputs = np.dot(self.wih, inputs) hidden_outputs = self.activation_function(hidden_inputs) final_inputs = np.dot(self.who, hidden_outputs) final_outputs = self.activation_function(final_inputs) return final_outputs input_nodes = 784 hidden_nodes = 88 output_nodes = 10 learn_rate = 0.05 n = neuralnetwork(input_nodes, hidden_nodes, output_nodes, learn_rate) data_file = open("E:\sklearn_data\神經網絡數字識別\mnist_train.csv", 'r') data_list = data_file.readlines() data_file.close() file2 = open("E:\sklearn_data\神經網絡數字識別\mnist_test.csv") answer_data = file2.readlines() file2.close() data = [] sum_count = 0 for i in range(15): count = 0 for j in range(len(data_list)): target = np.zeros(10)+0.01 line_ = data_list[j].split(',') imagearray = np.asfarray(line_) target[int(imagearray[0])] = 1.0 n.train(imagearray[1:]/255*0.99+0.01, target) for line in answer_data: all_values = line.split(',') answer = n.query((np.asfarray(all_values[1:])/255*0.99)+0.01) if answer[int(all_values[0])] > 0.85: count += 1 sum_count += count string = "訓練進度 %05f\n本輪準確度 %05f\n總準確度 %05f\n\n"%(i/120,count/len(answer_data), sum_count/(len(answer_data)*(i+1))) data.append([i/120,count/len(answer_data), sum_count/(len(answer_data)*(i+1))]) print(string) data = np.array(data) plt.plot(range(len(data)), data[:, 1:])
可以說是相對簡單的一個程序,但卻是包含著神經網絡最基礎的思想!值得好好康康~
七、思考
如何識別其他手寫字體等?
我的想法:通過圖像處理,將像素規定到相近大小【尺度放縮】
圖像大小運行速度問題
我的想法:如何快速的矩陣運算,通過C語言是否可以加速?相較於darknet這個神經網絡僅有三層,運算速度並不是十分理想。當然cuda編程對於GPU加速肯定是最好的選擇之一。
到此這篇關於python神經網絡編程之手寫數字識別的文章就介紹到這瞭,更多相關python手寫數字識別內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- tensorflow2.0實現復雜神經網絡(多輸入多輸出nn,Resnet)
- Python通過樸素貝葉斯和LSTM分別實現新聞文本分類
- PyTorch實現MNIST數據集手寫數字識別詳情
- 基於Tensorflow搭建一個神經網絡的實現
- 使用Python處理KNN分類算法的實現代碼