程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

Mise en œuvre dun réseau neuronal entièrement connecté à partir de zéro en python

編輯:Python

Création continue,Accélérer la croissance!C'est ma participation「Nouveau plan de la Journée des Nuggets · 6 Le défi de la lune」De31Oh, mon Dieu.,Cliquez pour voir les détails de l'événement

Dans cet article,Prêt à l'emploi Python Mise en place d'un réseau neuronal entièrement connecté à partir de zéro.Vous pourriez demander,Pourquoi faut - il le faire soi - même?,Il y a beaucoup de bibliothèques et de cadres pour faire ça pour nous.,Par exemple, Tensorflow、Pytorch Attendez..Je veux juste dire que je l'ai fait moi - même.,C'est le sien..

Pensez à ce que vous avez fait aujourd'hui, du contact au travail sur les réseaux neuronaux 2、3 Ça fait un an.,Et j'ai essayé d'utiliser tensorflow Ou pytorch Cadre pour mettre en œuvre certains réseaux classiques.Mais le mécanisme derrière la Rétropropagation est encore flou.

Gradient

Le Gradient est la direction de la fonction qui augmente le plus rapidement,La direction la plus rapide, c'est - à - dire la fonction de direction, est très raide.,C'est la direction dans laquelle la fonction diminue le plus rapidement..

Bien que certaines théories、La disparition du gradient et la saturation des noeuds peuvent produire un 1、2、3 Mais il n'y a toujours pas de base.,Après tout, je n'a i pas mis en place un processus de Rétropropagation et d'entraînement complet..C'est comme ça qu'on se sent toujours à la surface.,Et pourtant.

Parce qu'il y a eu un temps libre récemment、 L'utilisation de ce temps de repos va donc permettre d'organiser cette partie des connaissances 、 En savoir plus

TypeSymboleDescriptionExpressionDimensionsScalaire n L n^L nLIndique le paragraphe L Le nombre de neurones de la couche Vecteur B L B^L BLIndique le paragraphe L Décalage de couche n L × 1 n^L \times 1 nL×1Matrice W L W^L WLIndique le paragraphe L Poids des couches n L × n L n^L \times n^L nL×nLVecteur Z L Z^L ZLIndique le paragraphe L Valeur saisie par le calque dans la fonction active Z L = W L A ( L 1 ) + B L Z^L=W^LA^{(L-1)} + B^L ZL=WLA(L−1)+BL n L × 1 n^L \times 1 nL×1Vecteur A L A^L ALIndique le paragraphe L Valeur de sortie de la couche A L = σ ( Z L ) A^L = \sigma(Z^L) AL=σ(ZL) n L × 1 n^L \times 1 nL×1

Nous connaissons tous le processus de formation des réseaux neuronaux , Est de mettre à jour les paramètres du réseau , La direction de la mise à jour est de réduire la valeur de la fonction de perte . C'est - à - dire transformer un problème d'apprentissage en un problème d'optimisation . Comment mettre à jour les paramètres ? Nous devons calculer la dérivée des paramètres de formation impliqués par rapport à la fonction de perte , Et ensuite résoudre le gradient , Ensuite, utilisez la méthode de descente par Gradient pour mettre à jour les paramètres , Itérer ce processus , Une solution optimale peut être trouvée pour minimiser la fonction de perte .

Nous savons que la Rétropropagation est principalement utilisée pour régler les dérivés de la fonction de perte par rapport au poids et au biais

J'ai peut - être entendu ou lu , Beaucoup d'informations sur la transmission d'erreurs par Rétropropagation sur le réseau . Et ensuite, selon les neurones w Et b L'ampleur de la contribution à l'écart . C'est - à - dire que l'erreur est attribuée à chaque neurone . Mais l'erreur ici (error)Qu'est - ce que ça veut dire?? Quelle est la définition exacte de cette erreur ? La réponse est que ces erreurs sont dues à chaque couche du réseau neuronal , Et l'erreur d'une couche est répartie sur la base de l'erreur de la couche suivante ,Dans le réseau l l l L'erreur de couche est utilisée pour δ l \delta^l δl Pour représenter.

La Rétropropagation est basée sur 4 Des équations de base , Ces équations permettent de calculer les erreurs δ L \delta^L δL Et la fonction de perte, Voici ce que 4 Les équations sont énumérées une par une

δ ( L ) = a C σ ( z L ) (BP1) \delta^{(L)} = \nabla_a C \odot \sigma^{\prime}(z^L) \tag{BP1} δ(L)=∇a​C⊙σ′(zL)(BP1) δ l = ( ( w l ) T δ l + 1 ) σ ( z l ) (BP1) \delta^l = ((w^l)^T \delta^{l+1}) \odot \sigma^{\prime}(z^l) \tag{BP1} δl=((wl)Tδl+1)⊙σ′(zl)(BP1) C b j l = δ j l (BP3) \frac{\partial C}{\partial b_{j}^l} = \delta_j^l \tag{BP3} ∂bjl​∂C​=δjl​(BP3) C w j k l = a k l 1 δ j l (BP4) \frac{\partial C}{\partial w_{jk}^l} = a_k^{l-1}\delta_j^l \tag{BP4} ∂wjkl​∂C​=akl−1​δjl​(BP4)

Comment interpréter ça 4 Les équations, Ensuite, j'aimerais utiliser un numéro de partage pour illustrer .

class NeuralNetwork(object):
def __init__(self):
pass
def forward(self,x):
# Retour à propagation vers l'avant Z C'est - à - dire w Et b Combinaison linéaire, Saisissez la valeur avant d'activer la fonction 
# Renvoie la valeur de sortie de la fonction active A
# z_s , a_s
pass
def backward(self,y,z_s,a_s):
# Renvoie la dérivée du paramètre d'apprentissage dans la propagation vers l'avant dw db
pass
def train(self,x,y,batch_size=10,epochs=100,lr=0.001):
pass

Nous sommes tous des processus d'apprentissage en réseau neuronal , C'est le processus d'entraînement .Il y a deux étapes principalesPropagation vers l'avantEtRétropropagation

  • Dans la fonction de propagation vers l'avant, Calcul principal de la propagation Z Et A,À propos de Z Et A Voir le tableau précédent pour plus de détails
  • Calcul des variables d'apprentissage en Rétropropagation w Et b Dérivé de
 def __init__(self,layers = [2 , 10, 1], activations=['sigmoid', 'sigmoid']):
assert(len(layers) == len(activations)+1)
self.layers = layers
self.activations = activations
self.weights = []
self.biases = []
for i in range(len(layers)-1):
self.weights.append(np.random.randn(layers[i+1], layers[i]))
self.biases.append(np.random.randn(layers[i+1], 1))
  • layers Le paramètre est utilisé pour spécifier le nombre de neurones par couche
  • activations Spécifiez une fonction d'activation pour chaque couche ,C'est - à - dire σ ( w x + b ) \sigma(wx + b) σ(wx+b)

Lisez simplement le Code assert(len(layers) == len(activations)+1)

for i in range(len(layers)-1):
self.weights.append(np.random.randn(layers[i+1], layers[i]))
self.biases.append(np.random.randn(layers[i+1], 1))

Parce que les poids relient chaque couche de neurones w Et b , C'est juste l'équation entre deux couches , Le code ci - dessus est correct

Propagation vers l'avant

Dans la propagation vers l'avant,Entrée X Entrée dans a_s Moyenne, z = w x + b z = wx + b z=wx+b Et ensuite calculer la sortie a = σ ( z ) a=\sigma(z) a=σ(z),

def feedforward(self, x):
# Renvoie la valeur de propagation vers l'avant 
a = np.copy(x)
z_s = []
a_s = [a]
for i in range(len(self.weights)):
activation_function = self.getActivationFunction(self.activations[i])
z_s.append(self.weights[i].dot(a) + self.biases[i])
a = activation_function(z_s[-1])
a_s.append(a)
return (z_s, a_s)

Activez la fonction ici , La valeur de retour de cette fonction est une fonction ,In python Avec lambda Pour retourner une fonction , Ici Jane a laissé un stylo , Il sera ensuite modifié .

 @staticmethod
def getActivationFunction(name):
if(name == 'sigmoid'):
return lambda x : np.exp(x)/(1+np.exp(x))
elif(name == 'linear'):
return lambda x : x
elif(name == 'relu'):
def relu(x):
y = np.copy(x)
y[y<0] = 0
return y
return relu
else:
print('Unknown activation function. linear is used')
return lambda x: x

[@staticmethod]
def getDerivitiveActivationFunction(name):
if(name == 'sigmoid'):
sig = lambda x : np.exp(x)/(1+np.exp(x))
return lambda x :sig(x)*(1-sig(x))
elif(name == 'linear'):
return lambda x: 1
elif(name == 'relu'):
def relu_diff(x):
y = np.copy(x)
y[y>=0] = 1
y[y<0] = 0
return y
return relu_diff
else:
print('Unknown activation function. linear is used')
return lambda x: 1

Rétropropagation

C'est l'objet de ce partage

 def backpropagation(self,y, z_s, a_s):
dw = [] # dC/dW
db = [] # dC/dB
deltas = [None] * len(self.weights) # delta = dC/dZ Calculer l'erreur pour chaque couche
# Erreur de dernière couche 
deltas[-1] = ((y-a_s[-1])*(self.getDerivitiveActivationFunction(self.activations[-1]))(z_s[-1]))
# Rétropropagation
for i in reversed(range(len(deltas)-1)):
deltas[i] = self.weights[i+1].T.dot(deltas[i+1])*(self.getDerivitiveActivationFunction(self.activations[i])(z_s[i]))
#a= [print(d.shape) for d in deltas]
batch_size = y.shape[1]
db = [d.dot(np.ones((batch_size,1)))/float(batch_size) for d in deltas]
dw = [d.dot(a_s[i].T)/float(batch_size) for i,d in enumerate(deltas)]
# Retour au poids (weight)Matrice and Vecteur offset(biases)
return dw, db

Calculer d'abord l'erreur de la dernière couche basée sur BP1 L'équation donne l'équation suivante

deltas[-1] = ((y-a_s[-1])*(self.getDerivitiveActivationFunction(self.activations[-1]))(z_s[-1]))

δ L = ( a L y ) σ ( z L ) \delta^L = (a^L - y)\sigma(z^L) δL=(aL−y)σ(zL)

La prochaine étape est basée sur δ l + 1 \delta^{l+1} δl+1 Erreur pour calculer la couche courante δ l \delta^l δl

δ l = ( ( w l ) T δ l + 1 ) σ ( z l ) (BP1) \delta^l = ((w^l)^T \delta^{l+1}) \odot \sigma^{\prime}(z^l) \tag{BP1} δl=((wl)Tδl+1)⊙σ′(zl)(BP1)
batch_size = y.shape[1]
db = [d.dot(np.ones((batch_size,1)))/float(batch_size) for d in deltas]
dw = [d.dot(a_s[i].T)/float(batch_size) for i,d in enumerate(deltas)]
C b j l = δ j l (BP3) \frac{\partial C}{\partial b_{j}^l} = \delta_j^l \tag{BP3} ∂bjl​∂C​=δjl​(BP3) C w j k l = a k l 1 δ j l (BP4) \frac{\partial C}{\partial w_{jk}^l} = a_k^{l-1}\delta_j^l \tag{BP4} ∂wjkl​∂C​=akl−1​δjl​(BP4)

Commencez l'entraînement.

 def train(self, x, y, batch_size=10, epochs=100, lr = 0.01):
# update weights and biases based on the output
for e in range(epochs):
i=0
while(i<len(y)):
x_batch = x[i:i+batch_size]
y_batch = y[i:i+batch_size]
i = i+batch_size
z_s, a_s = self.feedforward(x_batch)
dw, db = self.backpropagation(y_batch, z_s, a_s)
self.weights = [w+lr*dweight for w,dweight in zip(self.weights, dw)]
self.biases = [w+lr*dbias for w,dbias in zip(self.biases, db)]
# print("loss = {}".format(np.linalg.norm(a_s[-1]-y_batch) ))

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved