《手寫數字識別》神經網路 學習筆記
本文主要參考《深度學習入門-基於python的理論與實現》一書。
“手寫數字識別” 可以說是機器學習界的“hello world”了,本文將簡單說下如何不使用成熟的機器學習庫,來手動實現一個神經網路。
首先,我們需要匯入訓練集和測試集:
"""load_mnist(normalize=True, flatten=True, one_hot_label=False)
讀入MNIST資料集
Parameters
----------
normalize : 將影像的畫素值正規化為0.0~1.0
one_hot_label :
one_hot_label為True的情況下,標籤作為one-hot陣列返回
one-hot陣列是指[0,0,1,0,0,0,0,0,0,0]這樣的陣列
flatten : 是否將影像展開為一維陣列
Returns
-------
(訓練影像, 訓練標籤), (測試影像, 測試標籤)
"""
(x_train, t_train), (x_test, t_test) = load_mnist(normalize = True, one_hot_label = True)
接著,我們要實現一個雙層網路,它應該接收一系列輸入,並經過若干個隱藏層的內部處理,最終識別出數字為0-9中的哪一個。
上面提到的過程叫做前向傳播,我們通過前向傳播來得出一個結果。但是,這個結果不一定對,所以,我們同樣需要一個叫做反向傳播的東西,來修正學習模型。
在我們的例子中,會設計4個層,分別是Affine層,Relu層,Affine層,SoftmaxWithLoss層。
- Affine層:在Affine層我們會對輸入矩陣進行形如:y = ax+b的計算,反映到矩陣上就像一次線性變換和一次平移,所以叫做仿射變換層
- Relu層:啟用函式層,在這裡會將上一層輸出的資料進行一次運算,輸出0-1之間的一個數。至於為什麼需要啟用層而不是直接把結果傳遞下去,可以參考 https://zhuanlan.zhihu.com/p/165194685
- SoftmaxWithLoss層:如果不訓練ANN,那麼這層是不需要的。softmax的作用就是將輸出正規化(輸出值的和為1),以便進行反向傳播的計算。
先來看下前向傳播的實現:
- Affine層的前向傳播:
def forward(self, x):
# 對應張量
self.original_x_shape = x.shape
x = x.reshape(x.shape[0], -1)
self.x = x
out = np.dot(self.x, self.W) + self.b
return out
很簡單,就是基本就是形如y = ax + b的形式。
- Relu層的前向傳播:
def forward(self, x):
self.mask = (x <= 0)
out = x.copy()
out[self.mask] = 0
return out
Relu層也很好理解,它會將傳入的x陣列大於0的元素存為False,小於0的存為True。這是為了給反向傳播使用。實際上,Relu會把大於0的元素保持不變,小於0的元素變為0。
需要注意,這裡的運算用到了numpy陣列的特性。
- SoftmaskWithLoss的前向傳播:
def forward(self, x, t):
self.t = t
self.y = softmax(x)
self.loss = cross_entropy_error(self.y, self.t)
return self.loss
這裡的t是監督資料,通過交叉熵誤差計算損失函式,得到損失值。
接著就是前向傳播,很簡單,依次遍歷每個層的forward函式:
def predict(self, x):
for layer in self.layers.values():
x = layer.forward(x)
return x
別忘了,我們前面還提到,要想訓練ANN,需要實現反向傳播。那麼什麼叫反向傳播?
其實反向傳播就是一個對引數求導的過程,目的是使損失函式降到最低。除了反向傳播,還有一種使用數值微分求梯度的辦法來降低損失函式的值,但這種方法計算量比較大。所以我們選擇反向傳播。
先來實現以下各個層的反向傳播演算法:
- Affine層的反向傳播:
def backward(self, x):
dx = np.dot(dout, self.W.T)
self.dW = np.dot(self.x.T, dout)
self.db = np.sum(dout, axis=0)
dx = dx.reshape(*self.original_x_shape) # 還原輸入資料的形狀(對應張量)
return dx
- Relu層的反向傳播:
def backward(self, x):
dout[self.mask] = 0
dx = dout
return dx
需要注意,這裡的運算用到了numpy陣列的特性。
- SoftmaskWithLoss的反向傳播:
def backward(self, x, t):
batch_size = self.t.shape[0]
if self.t.size == self.y.size: # 監督資料是one-hot-vector的情況
dx = (self.y - self.t) / batch_size
else:
dx = self.y.copy()
dx[np.arange(batch_size), self.t] -= 1
dx = dx / batch_size
return dx
訓練的完整程式碼如下:
# 讀入資料
(x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, one_hot_label=True)
# 新建一個輸入層784神經元、隱藏層50神經元、輸出層10神經元的雙層神經網路
network = TwoLayerNet(input_size=784, hidden_size=50, output_size=10)
# 更新次數
iters_num = 10000
train_size = x_train.shape[0]
batch_size = 100
learning_rate = 0.1
train_loss_list = []
train_acc_list = []
test_acc_list = []
# 所有訓練資料均被使用過一次時的更新次數,假如有1w個訓練資料,batch為100,那每100次就是一個epoch
iter_per_epoch = max(train_size / batch_size, 1)
for i in range(iters_num):
# 挑選100個索引
batch_mask = np.random.choice(train_size, batch_size)
# 訓練資料
x_batch = x_train[batch_mask]
# 結果
t_batch = t_train[batch_mask]
# 梯度
#grad = network.numerical_gradient(x_batch, t_batch)
grad = network.gradient(x_batch, t_batch)
# 更新
for key in ('W1', 'b1', 'W2', 'b2'):
network.params[key] -= learning_rate * grad[key]
# 記錄每次更新完梯度的損失值
loss = network.loss(x_batch, t_batch)
train_loss_list.append(loss)
# 每訓練完一個epoch,對比下訓練資料的準確率和測試資料的準群率。避免不知不覺間發生過擬合現象
if i % iter_per_epoch == 0:
train_acc = network.accuracy(x_train, t_train)
test_acc = network.accuracy(x_test, t_test)
train_acc_list.append(train_acc)
test_acc_list.append(test_acc)
print(train_acc, test_acc)
相關文章
- 使用神經網路識別手寫數字神經網路
- Spark學習筆記——手寫數字識別Spark筆記
- 手寫數字圖片識別-卷積神經網路卷積神經網路
- 使用人工神經網路訓練手寫數字識別模型神經網路模型
- 卷積神經網路CNN實戰:MINST手寫數字識別——網路定義卷積神經網路CNN
- 幾種型別神經網路學習筆記型別神經網路筆記
- 一個單層的基礎神經網路實現手寫數字識別神經網路
- AI BP神經網路判斷手寫數字AI神經網路
- 深度學習與神經網路學習筆記一深度學習神經網路筆記
- 【Get】用深度學習識別手寫數字深度學習
- matlab練習程式(神經網路識別mnist手寫資料集)Matlab神經網路
- 深度學習筆記------卷積神經網路深度學習筆記卷積神經網路
- 深度學習卷積神經網路筆記深度學習卷積神經網路筆記
- 全連線神經網路學習筆記神經網路筆記
- 機器學習之神經網路識別手寫數字(純python實現)機器學習神經網路Python
- 卷積神經網路學習筆記——Siamese networks(孿生神經網路)卷積神經網路筆記
- 卷積神經網路學習筆記——SENet卷積神經網路筆記SENet
- TensorFlow.NET機器學習入門【5】採用神經網路實現手寫數字識別(MNIST)機器學習神經網路
- 卷積神經網路初探——LeNet-5的原理與手寫數字識別的實現卷積神經網路
- 手寫數字圖片識別-全連線網路
- 吳恩達機器學習筆記 —— 9 神經網路學習吳恩達機器學習筆記神經網路
- Stanford機器學習課程筆記——神經網路學習機器學習筆記神經網路
- 【自己動手寫神經網路】---人人都可以學的神經網路書神經網路
- 吳恩達《神經網路與深度學習》課程筆記(4)– 淺層神經網路吳恩達神經網路深度學習筆記
- 吳恩達《神經網路與深度學習》課程筆記(5)– 深層神經網路吳恩達神經網路深度學習筆記
- 用TensorFlow搭建卷積神經網路識別數字0~9卷積神經網路
- 【機器學習】手寫數字識別機器學習
- 深度學習實驗:Softmax實現手寫數字識別深度學習
- 深度學習筆記8:利用Tensorflow搭建神經網路深度學習筆記神經網路
- 從零開始構建並編寫神經網路【學習筆記】[2/2]神經網路筆記
- Neural Networks and Deep Learning(神經網路與深度學習) - 學習筆記神經網路深度學習筆記
- 深度學習入門筆記(十八):卷積神經網路(一)深度學習筆記卷積神經網路
- 語音學習筆記14------卷積神經網路CNN引數說明筆記卷積神經網路CNN
- bp神經網路學習神經網路
- 從零開始構建並編寫神經網路---Keras【學習筆記】[1/2]神經網路Keras筆記
- 深度學習--基於卷積神經網路的歌唱嗓音識別深度學習卷積神經網路
- 機器學習框架ML.NET學習筆記【4】多元分類之手寫數字識別機器學習框架筆記
- 【機器學習】搭建神經網路筆記機器學習神經網路筆記