02.22 製作屬於自己的人工神經網絡

在本文中,我已經實現了具有Dropout和L2正則化的人工神經網絡的完全向量化代碼。

在本文中,我實現了一個在多個數據集上測試的人工神經網絡的完全向量化python代碼。此外,並對Dropout和L2正則化技術進行了實現和詳細說明。

強烈建議通過人工神經網絡的基本工作,正向傳播和反向傳播。

本文分為10個部分:

  1. 介紹
  2. 先決條件
  3. 導入我們的庫
  4. 激活函數及求導
  5. 神經網絡類
  6. 初始化權重和偏差
  7. 正向傳播
  8. 成本函數
  9. 反向傳播
  10. 預測新數據集的標籤

1.簡介

人工神經網絡是監督深度學習中最簡單和最基本的概念之一。它可用於執行多個任務,如二進制或分類。它看起來很容易理解和實現。在編寫這樣一個網絡的過程中,會出現一些小問題,這些問題會導致很大的錯誤,並幫助您理解以前忽略的概念。因此,在本文中,我嘗試實現一個人工神經網絡,它可能會幫助您節省正確編碼和理解主題的每個概念所需的工作時間。

2.先決條件

我假設你知道神經網絡是什麼以及它們是如何學習的。如果你對Python和像numpy這樣的庫很熟悉的話,這將很容易理解。另外,還需要對線性代數和微積分知識有很好的瞭解,以便於輕鬆地理解正向和反向傳播部分。此外,我強烈建議您閱讀Andrew Ng在Coursera上的課程視頻(https://www.coursera.org/ ; https://www.deeplearning.ai/ )。

3.導入我們的庫

現在,我們可以開始對神經網絡進行編碼了。第一件事是需要導入我們實現網絡所需的所有庫。

# Importing the libraries
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import warnings
import time
warnings.filterwarnings('ignore');
import os
import sys
製作屬於自己的人工神經網絡

我們將使用pandas導入和清理我們的數據集。Numpy 是執行矩陣代數和複雜計算的最重要的庫。

4.激活函數及求導

在本文後面的部分中,我們將需要激活函數來執行正向傳播。另外,我們還需要在反向傳播過程中對激活函數求導。

所以,讓我們編寫一些激活函數。

def sigmoid(z) :
""" Reutrns the element wise sigmoid function. """
return 1./(1 + np.exp(-z))
def sigmoid_prime(z) :
""" Returns the derivative of the sigmoid function. """
return sigmoid(z)*(1-sigmoid(z))
def ReLU(z) :
""" Reutrns the element wise ReLU function. """
return (z*(z > 0))
def ReLU_prime(z) :
""" Returns the derivative of the ReLU function. """
return 1*(z>=0)
def lReLU(z) :
""" Reutrns the element wise leaky ReLU function. """
return np.maximum(z/100,z)
def lReLU_prime(z) :
""" Returns the derivative of the leaky ReLU function. """
z = 1*(z>=0)
z[z==0] = 1/100
return z
def tanh(z) :
""" Reutrns the element wise hyperbolic tangent function. """
return np.tanh(z)
def tanh_prime(z) :
""" Returns the derivative of the tanh function. """
return (1-tanh(z)**2)
# A dictionary of our activation functions
PHI = {'sigmoid':sigmoid, 'relu':ReLU, 'lrelu':lReLU, 'tanh':tanh}
# A dictionary containing the derivatives of our activation functions
PHI_PRIME = {'sigmoid':sigmoid_prime, 'relu':ReLU_prime, 'lrelu':lReLU_prime, 'tanh':tanh_prime}

製作屬於自己的人工神經網絡

我們有四種最流行的激活函數。首先是常規的sigmoid激活函數。

製作屬於自己的人工神經網絡

我們有ReLU或“ 線性整流函數 ”。我們將主要使用這個激活函數。注意,我們將保持ReLU 0的導數在點0處。

製作屬於自己的人工神經網絡

我們還有一個ReLU的擴展版本叫做Leaky ReLU。它的工作原理與ReLU類似,可以在某些數據集上提供更好的結果(不一定是全部)。

我們還有tanh(雙曲正切)激活函數。它也被廣泛使用,並且幾乎總是優於sigmoid。

製作屬於自己的人工神經網絡

另外,PHI和PHI_PRIME是分別包含激活函數及其導數的python字典。

5.我們的神經網絡類

在本節中,我們將創建並初始化我們的神經網絡類。首先,我們將決定在初始化期間使用哪些參數。我們需要:

  1. 每層神經元的數量
  2. 我們想在每一層中使用激活函數
  3. 我們的特徵矩陣(X包含行特徵和列特徵)。
  4. 特徵矩陣對應的標籤(y是行向量)
  5. 初始化權重和偏差的方法
  6. 使用損失函數

記住這一點,讓我們開始編寫神經網絡的類:

class NeuralNet : 
"""
This is a class for making Artificial Neural Networks. L2 and Droupout are the
default regularization methods implemented in this class. It takes the following parameters:

1. layers : A python list containing the different number of neurons in each layer.
(containing the output layer)
Eg - [64,32,16,16,1]

2. X : Matrix of features with rows as features and columns as different examples.

3. y : Numpy array containing the ouputs of coresponding examples.

4. ac_funcs : A python list containing activation function of each layer.
Eg - ['relu','relu','lrelu','tanh','sigmoid']

5. init_method : Meathod to initialize weights of the network. Can be 'gaussian','random','zeros'.


6. loss_func : Currently not implemented

7. W : Weights of a pretrained neural network with same architecture.

8. W : Biases of a pretrained neural network with same architecture.
"""
製作屬於自己的人工神經網絡

現在我們有了一個正確記錄的神經網絡類,我們可以繼續初始化網絡的其他變量。

 def __init__(self, layers, X, y, ac_funcs, init_method='gaussian', loss_func='b_ce', W=np.array([]), B=np.array([])) :
""" Initialize the network. """
# Store the layers of the network
self.layers = layers
# ----
self.W = None

self.B = None
# Store the number of examples in the dataset as m
self.m = X.shape[1]
# Store the full layer list as n
self.n = [X.shape[0], *layers]
# Save the dataset
self.X = X
# Save coresponding output
self.y = y
# List to store the cost of the model calculated during training
self.cost = []
# Stores the accuracy obtained on the test set.
self.acc = 0
# Activation function of each layer
self.ac_funcs = ac_funcs
self.loss = loss_func
# Inittialize the weights by provided methods if not provided.
製作屬於自己的人工神經網絡

我們將使用' self.m'來存儲數據集中示例的數量。' self.n '將存儲每層中神經元數量的信息。' self.ac_funcs '是每層的激活函數的python列表。' self.cost '將在我們訓練網絡時存儲成本函數的記錄值。' self.acc '將在訓練後的數據集上存儲記錄的精度。在初始化網絡的所有變量之後,讓我們進一步初始化網絡的權重和偏差。

6.初始化權重和偏差

我們知道權重不能初始化為零,因為每個神經元的假設變得相同而網絡永遠不會學習。因此,我們必須有一些方法來使我們的神經網絡學習。我們可以使用高斯正態分佈來獲得隨機值。由於這些分佈的均值為零,因此權重集中在零並且非常小。因此,網絡開始非常快速有效地學習。我們可以使用np.random.randn()函數從正態分佈中生成隨機值。

 # Inittialize the weights by provided methods if not provided.
if len(W) and len(B) :
self.W = W
self.B = B
else :
if init_method=='gaussian':
self.W = [np.random.randn(self.n[nl], self.n[nl-1]) for nl in range(1,len(self.n))]
self.B = [np.zeros((nl,1), 'float32') for nl in self.layers]
elif init_method == 'random':
self.W = [np.random.rand(self.n[nl], self.n[nl-1]) for nl in range(1,len(self.n))]
self.B = [np.random.rand(nl,1) for nl in self.layers]
elif init_method == 'zeros':
self.W = [np.zeros((self.n[nl], self.n[nl-1]), 'float32') for nl in range(1,len(self.n))]
self.B = [np.zeros((nl,1), 'float32') for nl in self.layers]
製作屬於自己的人工神經網絡

我們已將權重初始化為正態分佈中的隨機值。偏差已初始化為零。

7.正向傳播

首先,讓我們理解沒有正則化的正向傳播。

製作屬於自己的人工神經網絡

我們用Z表示每個神經元從一層到另一層的連接。一旦我們計算了Z,我們將激活函數f應用於Z值以獲得每層中每個神經元的激活y。這是簡單的正向傳播。Dropout是一種提高神經網絡泛化能力和魯棒性的神奇技術。所以,讓我們首先了解一下Dropout正則化。

Dropout正則化的本質

Dropout,顧名思義,是指神經網絡中的一些神經元“失活”,並對其餘的神經元進行訓練。

製作屬於自己的人工神經網絡

為了提高性能,我們可以訓練幾十個和幾百個具有不同超參數值的神經網絡,獲得所有網絡的輸出並取其平均值來獲得最終結果。這個過程在計算上非常昂貴並且實際上不能實現。因此,我們需要一種以更優化和計算成本更低的方式執行類似操作的方法。Dropout正則化以非常便宜和簡單的方式完成相似的事情。事實上,Dropout是優化性能的簡單方法,近年來受到了廣泛的關注,並且幾乎在許多其他深度學習模型中無處不在。

要實現Dropout,我們將使用以下方法:

製作屬於自己的人工神經網絡

我們將首先從伯努利分佈中提取隨機值,如果概率高於某個閾值則保持神經元不變,然後執行常規正向傳播。注意,我們不會在預測新數據集上的值或測試時間期間應用dropout。

實現Dropout的代碼

我們使用keep_prob作為每層神經元存活的概率。我們只保留概率高於存活概率或keep_prob的神經元。假設,它的值是0.8。這意味著我們將使每一層中20%的神經元失活,並訓練其餘80%的神經元。注意,我們在每次迭代後停用隨機選擇的神經元。這有助於神經元學習在更大的數據集上泛化的特徵。

 def _feedForward(self, keep_prob):
""" Forward pass """
z = [];a = []
z.append(np.dot(self.W[0], self.X) + self.B[0])
a.append(PHI[self.ac_funcs[0]](z[-1]))
for l in range(1,len(self.layers)):
z.append(np.dot(self.W[l], a[-1]) + self.B[l])
# a.append(PHI[self.ac_funcs[l]](z[l]))
_a = PHI[self.ac_funcs[l]](z[l])
a.append( ((np.random.rand(_a.shape[0],1) < keep_prob)*_a)/keep_prob )
return z,a
製作屬於自己的人工神經網絡

我們首先初始化將存儲Z和A值的列表。我們首先在Z中附加第一層的線性值,然後在A中附加第一層神經元的激活。PHI是一個python字典,包含我們之前編寫的激活函數。類似地使用for循環計算所有其他層的Z和A的值。注意,我們沒有在輸入層應用dropout。我們最終返回Z和A的計算值。

8.成本函數

我們將使用標準二進制/分類交叉熵成本函數。

 def _cost_func(self, a, _lambda):
""" Binary Cross Entropy Cost Function """
return ( (-1/self.m)*np.sum(np.nan_to_num(self.y*np.log(a) + (1-self.y)*np.log(1-a))) + (_lambda/(2*self.m))*np.sum([np.sum(i**2) for i in self.W]) )
def _cost_derivative(self, a) :
""" The derivative of cost w.r.t z """
return (a-self.y)

製作屬於自己的人工神經網絡

我們用L2正則化對我們的成本函數進行了編譯。lambda參數稱為“ 懲罰參數 ”。它有助於使權重值不會迅速增加,從而更好地形成。這裡,' a'包含輸出層的激活值。我們還有函數_cost_derivative來計算成本函數對輸出層激活的導數。我們稍後會在反向傳播期間使用它。

9.反向傳播

以下是我們需要執行反向傳播的一些公式。

製作屬於自己的人工神經網絡

我們將在深度神經網絡上實現這一點。右邊的公式是完全向量化的。一旦理解了這些公式,我們就可以繼續對它們進行編譯。

 def startTraining(self, epochs, alpha, _lambda, keep_prob=0.5, interval=100):
"""
Start training the neural network. It takes the followng parameters :

1. epochs : Number of epochs for which you want to train the network.


2. alpha : The learning rate of your network.

3. _lambda : L2 regularization parameter or the penalization parameter.

4. keep_prob : Dropout regularization parameter. The probability of neurons to deactivate.
Eg - 0.8 means 20% of the neurons have been deactivated.

5. interval : The interval between updates of cost and accuracy.
"""
start = time.time()
for i in range(epochs+1) :
z,a = self._feedForward(keep_prob)
delta = self._cost_derivative(a[-1])
for l in range(1,len(z)) :
delta_w = np.dot(delta, a[-l-1].T) + (_lambda)*self.W[-l]
delta_b = np.sum(delta, axis=1, keepdims=True)
delta = np.dot(self.W[-l].T, delta)*PHI_PRIME[self.ac_funcs[-l-1]](z[-l-1])
self.W[-l] = self.W[-l] - (alpha/self.m)*delta_w
self.B[-l] = self.B[-l] - (alpha/self.m)*delta_b
delta_w = np.dot(delta, self.X.T ) + (_lambda)*self.W[0]
delta_b = np.sum(delta, axis=1, keepdims=True)
self.W[0] = self.W[0] - (alpha/self.m)*delta_w
self.B[0] = self.B[0] - (alpha/self.m)*delta_b
製作屬於自己的人工神經網絡

我們將epochs、alpha(學習率)、_lambda、keep_prob和interval作為函數的參數來實現反向傳播。

我們從正向傳播開始。然後我們將成本函數的導數計算為delta。現在,對於每一層,我們計算delta_w和delta_b,其中包含成本函數對網絡的權重和偏差的導數。然後我們根據各自的公式更新delta,權重和偏差。在將最後一層的權重和偏差更新到第二層之後,我們更新第一層的權重和偏差。我們這樣做了幾次迭代,直到權重和偏差的值收斂。

重要提示:此處可能出現的一個重大錯誤是在更新權重和偏差後更新delta 。這樣做可能會導致非常糟糕的梯度漸變消失/爆炸問題。

我們的大部分工作都在這裡完成,但是我們仍然需要編譯可以預測新數據集結果的函數。因此,作為我們的最後一步,我們將編寫一個函數來預測新數據集的標籤。

10.預測新數據集的標籤

這一步非常簡單。我們只需要執行正向傳播但不需要Dropout正則化。我們不需要在測試時應用Dropout正則化,因為我們需要所有層的所有神經元來為我們提供適當的結果,而不僅僅是一些隨機值。

 def predict(self, X_test) :
""" Predict the labels for a new dataset. Returns probability. """
a = PHI[self.ac_funcs[0]](np.dot(self.W[0], X_test) + self.B[0])
for l in range(1,len(self.layers)):
a = PHI[self.ac_funcs[l]](np.dot(self.W[l], a) + self.B[l])
return a
製作屬於自己的人工神經網絡

我們將返回輸出層的激活作為結果。

整個代碼

以下是您自己實現人工神經網絡的完整代碼。我在培訓時添加了一些代碼來打印網絡的成本和準確性。除此之外,一切都是一樣的。

# Importing the libraries
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import warnings
import time
warnings.filterwarnings('ignore');
import os
import sys
# Importing our dataset
os.chdir("C:/Users/Hilak/Desktop/INTERESTS/Machine Learning A-Z Template Folder/Part 3 - Classification/Section 14 - Logistic Regression");
training_set = pd.read_csv("Social_Network_Ads.csv");
# Splitting our dataset into matrix of features and output values.
X = training_set.iloc[:, 1:4].values
y = training_set.iloc[:, 4].values
# Encoding our object features.
from sklearn.preprocessing import LabelEncoder, OneHotEncoder
le_x = LabelEncoder()
X[:,0] = le_x.fit_transform(X[:,0])
ohe = OneHotEncoder(categorical_features = [0])
X = ohe.fit_transform(X).toarray()
# Performing Feature scaling
from sklearn.preprocessing import StandardScaler
ss = StandardScaler()
X[:,2:4] = ss.fit_transform(X[:, 2:4])
# Splitting the dataset into train and test set.
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.3)
X_train = X_train.T
X_test = X_test.T
# # Alternate Dataset for test purposes. Not used in the example shown
# os.chdir("C:\\\\Users\\\\Hilak\\\\Desktop\\\\INTERESTS\\\\Machine Learning A-Z Template Folder\\\\Part 8 - Deep Learning\\\\Section 39 - Artificial Neural Networks (ANN)");
# dataset = pd.read_csv('Churn_Modelling.csv')
# X = dataset.iloc[:, 3:13].values
# y = dataset.iloc[:, 13].values
# # Encoding categorical data
# from sklearn.preprocessing import LabelEncoder, OneHotEncoder
# labelencoder_X_1 = LabelEncoder()
# X[:, 1] = labelencoder_X_1.fit_transform(X[:, 1])
# labelencoder_X_2 = LabelEncoder()
# X[:, 2] = labelencoder_X_2.fit_transform(X[:, 2])
# onehotencoder = OneHotEncoder(categorical_features = [1])
# X = onehotencoder.fit_transform(X).toarray()
# X = X[:, 1:]
# # Splitting the dataset into the Training set and Test set
# from sklearn.model_selection import train_test_split
# X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2)
# X_test, X_CV, y_test, y_CV = train_test_split(X, y, test_size = 0.5)
# # Feature Scaling

# from sklearn.preprocessing import StandardScaler
# sc = StandardScaler()
# X_train = sc.fit_transform(X_train)
# X_test = sc.transform(X_test)
# X_train = X_train.T
# X_test = X_test.T
# X_CV = X_CV.T
def sigmoid(z) :
""" Reutrns the element wise sigmoid function. """
return 1./(1 + np.exp(-z))
def sigmoid_prime(z) :
""" Returns the derivative of the sigmoid function. """
return sigmoid(z)*(1-sigmoid(z))
def ReLU(z) :
""" Reutrns the element wise ReLU function. """
return (z*(z > 0))
def ReLU_prime(z) :
""" Returns the derivative of the ReLU function. """
return 1*(z>=0)
def lReLU(z) :
""" Reutrns the element wise leaky ReLU function. """
return np.maximum(z/100,z)
def lReLU_prime(z) :
""" Returns the derivative of the leaky ReLU function. """
z = 1*(z>=0)
z[z==0] = 1/100
return z
def tanh(z) :
""" Reutrns the element wise hyperbolic tangent function. """
return np.tanh(z)
def tanh_prime(z) :
""" Returns the derivative of the tanh function. """
return (1-tanh(z)**2)
# A dictionary of our activation functions
PHI = {'sigmoid':sigmoid, 'relu':ReLU, 'lrelu':lReLU, 'tanh':tanh}
# A dictionary containing the derivatives of our activation functions
PHI_PRIME = {'sigmoid':sigmoid_prime, 'relu':ReLU_prime, 'lrelu':lReLU_prime, 'tanh':tanh_prime}
class NeuralNet :
"""
This is a class for making Artificial Neural Networks. L2 and Droupout are the
default regularization methods implemented in this class. It takes the following parameters:

1. layers : A python list containing the different number of neurons in each layer.
(containing the output layer)
Eg - [64,32,16,16,1]

2. X : Matrix of features with rows as features and columns as different examples.

3. y : Numpy array containing the ouputs of coresponding examples.

4. ac_funcs : A python list containing activation function of each layer.
Eg - ['relu','relu','lrelu','tanh','sigmoid']

5. init_method : Meathod to initialize weights of the network. Can be 'gaussian','random','zeros'.

6. loss_func : Currently not implemented

7. W : Weights of a pretrained neural network with same architecture.

8. W : Biases of a pretrained neural network with same architecture.
"""
def __init__(self, layers, X, y, ac_funcs, init_method='gaussian', loss_func='b_ce', W=np.array([]), B=np.array([])) :
""" Initialize the network. """
# Store the layers of the network
self.layers = layers
# ----
self.W = None
self.B = None
# Store the number of examples in the dataset as m
self.m = X.shape[1]
# Store the full layer list as n
self.n = [X.shape[0], *layers]
# Save the dataset
self.X = X
# Save coresponding output
self.y = y
# List to store the cost of the model calculated during training
self.cost = []
# Stores the accuracy obtained on the test set.
self.acc = 0
# Activation function of each layer
self.ac_funcs = ac_funcs
self.loss = loss_func
# Inittialize the weights by provided methods if not provided.
if len(W) and len(B) :
self.W = W
self.B = B
else :
if init_method=='gaussian':
self.W = [np.random.randn(self.n[nl], self.n[nl-1]) for nl in range(1,len(self.n))]
self.B = [np.zeros((nl,1), 'float32') for nl in self.layers]
elif init_method == 'random':
self.W = [np.random.rand(self.n[nl], self.n[nl-1]) for nl in range(1,len(self.n))]
self.B = [np.random.rand(nl,1) for nl in self.layers]
elif init_method == 'zeros':
self.W = [np.zeros((self.n[nl], self.n[nl-1]), 'float32') for nl in range(1,len(self.n))]
self.B = [np.zeros((nl,1), 'float32') for nl in self.layers]

def startTraining(self, epochs, alpha, _lambda, keep_prob=0.5, interval=100):
"""

Start training the neural network. It takes the followng parameters :

1. epochs : Number of epochs for which you want to train the network.

2. alpha : The learning rate of your network.

3. _lambda : L2 regularization parameter or the penalization parameter.

4. keep_prob : Dropout regularization parameter. The probability of neurons to deactivate.
Eg - 0.8 means 20% of the neurons have been deactivated.

5. interval : The interval between updates of cost and accuracy.
"""
start = time.time()
for i in range(epochs+1) :
z,a = self._feedForward(keep_prob)
delta = self._cost_derivative(a[-1])
for l in range(1,len(z)) :
delta_w = np.dot(delta, a[-l-1].T) + (_lambda)*self.W[-l]
delta_b = np.sum(delta, axis=1, keepdims=True)
delta = np.dot(self.W[-l].T, delta)*PHI_PRIME[self.ac_funcs[-l-1]](z[-l-1])
self.W[-l] = self.W[-l] - (alpha/self.m)*delta_w
self.B[-l] = self.B[-l] - (alpha/self.m)*delta_b
delta_w = np.dot(delta, self.X.T ) + (_lambda)*self.W[0]
delta_b = np.sum(delta, axis=1, keepdims=True)
self.W[0] = self.W[0] - (alpha/self.m)*delta_w
self.B[0] = self.B[0] - (alpha/self.m)*delta_b
if not i%interval :
aa = self.predict(self.X)
if self.loss == 'b_ce':
aa = aa > 0.5
self.acc = sum(sum(aa == self.y)) / self.m
cost_val = self._cost_func(a[-1], _lambda)
self.cost.append(cost_val)
elif self.loss == 'c_ce':
aa = np.argmax(aa, axis = 0)
yy = np.argmax(self.y, axis = 0)
self.acc = np.sum(aa==yy)/(self.m)
cost_val = self._cost_func(a[-1], _lambda)
self.cost.append(cost_val)
sys.stdout.write(f'\\rEpoch[{i}] : Cost = {cost_val:.2f} ; Acc = {(self.acc*100):.2f}% ; Time Taken = {(time.time()-start):.2f}s')
print('\\n')
return None

def predict(self, X_test) :
""" Predict the labels for a new dataset. Returns probability. """
a = PHI[self.ac_funcs[0]](np.dot(self.W[0], X_test) + self.B[0])
for l in range(1,len(self.layers)):
a = PHI[self.ac_funcs[l]](np.dot(self.W[l], a) + self.B[l])
return a



def _feedForward(self, keep_prob):
""" Forward pass """
z = [];a = []
z.append(np.dot(self.W[0], self.X) + self.B[0])
a.append(PHI[self.ac_funcs[0]](z[-1]))
for l in range(1,len(self.layers)):
z.append(np.dot(self.W[l], a[-1]) + self.B[l])
# a.append(PHI[self.ac_funcs[l]](z[l]))
_a = PHI[self.ac_funcs[l]](z[l])
a.append( ((np.random.rand(_a.shape[0],1) < keep_prob)*_a)/keep_prob )
return z,a

def _cost_func(self, a, _lambda):
""" Binary Cross Entropy Cost Function """
return ( (-1/self.m)*np.sum(np.nan_to_num(self.y*np.log(a) + (1-self.y)*np.log(1-a))) + (_lambda/(2*self.m))*np.sum([np.sum(i**2) for i in self.W]) )
def _cost_derivative(self, a) :
""" The derivative of cost w.r.t z """
return (a-self.y)

@property
def summary(self) :
return self.cost, self.acc, self.W,self.B
def __repr__(self) :
return f'<neural>'
# Initializing our neural network
neural_net_sigmoid = NeuralNet([32,16,1], X_train, y_train, ac_funcs = ['relu','relu','sigmoid'])
# Staring the training of our network.
neural_net_sigmoid.startTraining(5000, 0.01, 0.2, 0.5, 100)
# Predicting on new dataset using our trained network.
preds = neural_net_sigmoid.predict(X_test)
preds = preds > 0.5
acc = (sum(sum(preds == y_test)) / y_test.size)*100
# Accuracy (metric of evaluation) obtained by the network.
print(f'Test set Accuracy ( r-t-s ) : {acc}%')
# Plotting our cost vs epochs relationship
sigmoid_summary = neural_net_sigmoid.summary
plt.plot(range(len(sigmoid_summary[0])), sigmoid_summary[0], label='Sigmoid Cost')
plt.title('Cost')
plt.show()
# Comparing our results with the library keras.
from keras.models import Sequential
from keras.layers import Dense
X_train, X_test = X_train.T, X_test.T
classifier = Sequential()
classifier.add(Dense(input_dim=4, units = 32, kernel_initializer="uniform", activation="relu"))
classifier.add(Dense(units = 16, kernel_initializer = "uniform", activation="relu"))
# classifier.add(Dense(units = 16, kernel_initializer = "uniform", activation="tanh"))
classifier.add(Dense(units = 1, kernel_initializer = "uniform", activation = "sigmoid"))

classifier.compile(optimizer = "adam", loss = "binary_crossentropy", metrics = ["accuracy"])
classifier.fit(X_train, y_train, batch_size = 1, epochs = 30)
y_pred = classifier.predict(X_test)
y_pred = 1*(y_pred > 0.5)
test_acc = sum(sum(y_pred.T == y_test)) / y_test.size
print(f"Test set Accuracy : {test_acc*100}%")
X_train, X_test = X_train.T, X_test.T
/<neural>
製作屬於自己的人工神經網絡

我們終於完成了神經網絡的編譯。現在,我們可以在不同的數據集上測試我們的網絡。

測試我們的神經網絡

我們將在著名的MNIST數據集上測試我們的網絡以進行數字分類。我們將僅使用8000個圖像來訓練我們的網絡並預測2000個其他圖像。

我訓練了兩個隱藏的分層神經網絡,有32個和16個神經元。我在這兩層中都使用了ReLU激活函數。在訓練網絡2500個週期後,懲罰參數為1.0,學習率為0.1,得到:

製作屬於自己的人工神經網絡

Cost與Epochs的關係圖如下所示:

製作屬於自己的人工神經網絡

我們在訓練和測試集上都獲得了相當好的準確性。通過使用網格搜索,隨機網格搜索等技術調整超參數,我們可以獲得更高的準確率。

另外,您可以隨意嘗試不同的超參數,激活函數和數據集值。

其他

如果您已經理解了我上面提供的神經網絡的代碼,那麼您可以進行一些更改以使其更好。

  1. 嘗試編譯softmax激活功能並使其正常工作。
  2. 比如,我想讓第一層30%的神經元失活第二層50%的神經元失活。嘗試編寫一個網絡,在其中我可以為每個層使用不同的keep_prob值。
  3. 嘗試實現小批量梯度下降算法。這對於手寫數字分類非常適合。


分享到:


相關文章: