L'apprentissage automatique et l'apprentissage en profondeur sont riches en bibliothèques, vous pouvez donc faire des prédictions avec un simple copier-coller. J'ai moi-même exécuté des programmes créés par de nombreux ancêtres et suis arrivé à un niveau où je peux comprendre les grandes lignes. En particulier, l'apprentissage en profondeur (réseau neuronal) est appliqué au GAN et au traitement du langage naturel. C'est un genre où les nouvelles technologies sont créées à un rythme vertigineux, et je crois que son application à la société et à l'industrie progresse rapidement. Par conséquent, nous la reconnaissons comme la technologie au centre d'une telle transformation et aimerions avoir une compréhension très intéressante et approfondie de ces domaines! Il y a un motif.
Actuellement, nous commençons à apprendre des bases ici, qui est célèbre comme un manuel d'apprentissage en profondeur. https://www.oreilly.co.jp/books/9784873117584/ Cette fois, en construisant un réseau de neurones à partir de presque rien (bien que j'utilise numpy), j'aimerais avoir une idée réelle des calculs qui y sont effectués.
Le résumé est ci-dessous.
Perceptron signifie qu'il reçoit plusieurs signaux en tant qu'entrées et sort un signal. Dans le domaine de l'apprentissage automatique, ne pas émettre de signal est traité comme 0 et sortir un signal est traité comme 1.
La figure ci-dessus est un simple schéma de cette idée. x est le signal d'entrée, y est le signal de sortie et w est le poids. Ce 〇 s'appelle un neurone. Le neurone reçoit la somme du poids multipliée par la valeur d'entrée. A ce moment, la sortie 1 est sortie lorsque la somme totale dépasse le seuil θ. La formule est la suivante.
Maintenant, faisons un programme. J'ai reproduit le modèle simple montré dans la figure ci-dessus. Tout d'abord, calculons quand le seuil est de 0,4.
NN.ipynb
def AND(x1,x2):
w1,w2,theta = 0.5,0.5,0.4
tmp = x1*w1 + x2*w2
b = -0.5
if tmp <= theta:
return 0
elif tmp > theta:
return 1
python
print(AND(0,0))
print(AND(1,0))
print(AND(0,1))
print(AND(1,1))
0
1
1
1
En conséquence, il a été constaté que si x1 ou x2 est égal à 1, 1 est sorti en sortie. En revanche, si le seuil est de 0,7, ce sera le suivant.
print(AND(0,0))
print(AND(1,0))
print(AND(0,1))
print(AND(1,1))
0
0
0
1
Si un seul de x1 et x2 vaut 1, la sortie ne crachera plus 1. Vous pouvez voir que la sortie obtenue change en fonction du réglage du seuil.
Un perceptron multicouche est un réseau qui a une couche appelée couche intermédiaire entre la couche d'entrée et la couche de sortie. La description peut différer selon le livre, mais dans le cas de la figure ci-dessous, la couche d'entrée est appelée couche 0, la couche intermédiaire est appelée 1 couche et la couche de sortie est appelée 2 couches.
Ici, il semble y avoir un style (personnalisé?) Dans la façon de compter en l'appelant un réseau de neurones à 〇 couches. Il semble que nous puissions compter la couche de poids ou appeler la couche de neurones. Je n'ai pas beaucoup d'expérience avec ce qui est le plus courant, mais j'aimerais suivre le manuel d'O'Reilly et le nommer en fonction du poids.
Ensuite, nous introduisons une valeur appelée biais b. En réarrangeant l'équation ci-dessus avec le seuil précédent θ comme -b, il est possible de déterminer la sortie de y à 0 ou 1 avec 0 comme référence, comme dans l'équation ci-dessus. Le biais est la signification d'une valeur de correction qui "bloque" dans l'industrie du petit travail (industrie manufacturière), et il est possible d'augmenter ou de réduire la valeur sur l'axe y dans son ensemble.
La fonction qui détermine si y vaut 0 ou 1 est appelée fonction d'activation. Comme la valeur obtenue par cette fonction d'activation peut être une valeur proche de 0 ou 1, il existe également une fonction qui peut empêcher le calcul de diverger. Il existe plusieurs types de cette fonction d'activation.
C'est l'une des fonctions souvent utilisées dans la fonction d'activation. C'est une fraction de la fonction du nombre de Napier e, qui est la base du logarithme naturel comme indiqué ci-dessous. La forme de cette fonction est difficile à trouver, mais elle ressemble à ce qui suit.
NN.ipynb
import numpy as np
def sigmoid(x):
return 1/(1+np.exp(-x))
xxx = np.arange(-5.0,5.0,0.1)#Afficher la fonction sigmoïde
yyy = sigmoid(xxx)
plt.plot(xxx,yyy)
plt.ylim(-0.1,1.1)
plt.show
On peut voir que lorsque x> 0 avec x = 0 comme limite, il s'approche progressivement de y = 1. Au contraire, lorsque x <0, il s'approche progressivement de y = 0. Vous pouvez voir que c'est très pratique car la valeur d'entrée peut être sortie entre 0 et 1 car elle joue le rôle de la fonction d'activation.
Ensuite, il y a une fonction pas à pas en tant que fonction qui produit 0,1 à l'extrême de la fonction sigmoïde. Cela s'écrirait comme suit.
NN.ipynb
def step_function(x):
return np.array(x > 0, dtype=np.int)
x = np.arange(-5.0, 5.0, 0.1)
y = step_function(x)
plt.plot(xxx,yyy)
plt.plot(x, y)
plt.ylim(-0.1, 1.1)
plt.show()
Le bleu est la fonction d'étape et l'orange est la fonction sigmoïde. Vous pouvez voir que la valeur de sortie n'est que de 0 ou 1. Je ne sais pas comment utiliser correctement cette fonction, alors laissez-moi en faire mes futurs devoirs. ** En tant que sentiment, je comprends que la fonction sigmoïde a pour fonction de distinguer la différence même avec une légère différence d'entrée car elle peut prendre la valeur plus finement. Par contre, s'il y a plusieurs couches et que la charge de calcul est élevée, je pense qu'il est possible de distinguer tout en réduisant la charge en utilisant la fonction step selon le cas. ** **
Enfin, je voudrais parler de la fonction ReLU (Rectified Linear Unit), qui a également l'impression d'être souvent utilisée. Si x dépasse 0, la valeur est sortie sous la forme y telle quelle, et si elle est égale ou inférieure à 0, 0 est sortie.
NN.ipynb
def relu(x):
return np.maximum(0,x)
xx = np.arange(-5.0,5.0,0.1)
yy = relu(xx)
plt.plot(xx,yy)
plt.ylim(-0.1,5)
plt.show
Cette fois, nous allons créer un réseau neuronal de type propagation directe. Ce type de propagation vers l'avant indique que le flux circule de l'entrée vers la sortie dans une direction. Lorsque vous envisagez de former un modèle, le calcul est effectué de la sortie à l'entrée. C'est ce qu'on appelle la méthode de rétropropagation.
Maintenant, je voudrais vraiment décrire un réseau neuronal à trois couches.
Envisagez de créer un réseau neuronal à trois couches, comme illustré dans la figure ci-dessus. Tout d'abord, supprimons uniquement les calculs qui ressortent en gras dans la figure ci-dessus ci-dessous.
NN.ipynb
def init_network():
network = {}
network['W1'] = np.array([[0.1,0.3,0.5],[0.2,0.4,0.6]])
network['b1'] = np.array([0.1,0.2,0.3])
return network
def forword(network,x):
W1= network['W1']
b1= network['b1']
a1 = np.dot(x,W1)+b1
z1 = sigmoid(a1)
return y
network = init_network()
x = np.array([2,1])
z1 = forword(network,x)
print(z1)
[0.40442364 0.59557636]
Je laisse la fonction init_network () définir les poids et les biais, et la fonction forword () définir les formules qui calculent réellement. Après cela, la fonction est appelée et la valeur initiale x est attribuée afin que la réponse puisse être crachée. C'est plus facile à comprendre que d'écrire sans définir une fonction d'affilée.
** Notez également la fonction qui représente le produit interne de la matrice décrite ici comme np.dot. Soyez prudent lorsque vous décrivez le produit des matrices, car les dimensions de la matrice obtenue dans l'ordre de multiplication changent. ** **
NN.ipynb
def init_network():
network = {}
network['W1'] = np.array([[0.1,0.3,0.5],[0.2,0.4,0.6]])
network['b1'] = np.array([0.1,0.2,0.3])
network['W2'] = np.array([[0.1,0.4],[0.2,0.5],[0.3,0.6]])
network['b2'] = np.array([0.1,0.2])
network['W3'] = np.array([[0.1,0.3],[0.2,0.4]])
network['b3'] = np.array([0.1,0.2])
return network
def forword(network,x):
W1,W2,W3 = network['W1'],network['W2'],network['W3']
b1,b2,b3 = network['b1'],network['b2'],network['b3']
a1 = np.dot(x,W1)+b1
z1 = sigmoid(a1)
a2 = np.dot(z1,W2)+b2
z2 = sigmoid(a2)
a3 = np.dot(z2,W3)+b3
y = softmax(a3)
return y
Si vous laissez les deux fonctions décrire jusqu'à la fin, cela s'écrira ainsi. Eh bien, je l'ai mentionné plus tôt ici, mais il y a une description écrite comme softmax à la fin. Ceci est résumé ci-dessous.
Après cela, nous pouvons voir que nous devons ajouter des couches à ces deux fonctions. Ensuite, considérez la valeur y comme sortie à la fin. Lorsqu'il est nécessaire de classer des problèmes tels que l'estimation de 0 à 9 types de nombres, la probabilité correspondant à chaque type est sortie et celle avec la probabilité la plus élevée est utilisée comme valeur prédite. Une fonction pratique pour exprimer une telle probabilité est la fonction softmax.
La somme des valeurs prises pour tous les éléments d'une certaine catégorie peut être utilisée comme dénominateur, et les valeurs individuelles prises peuvent être utilisées comme numérateur pour représenter la probabilité. En terminant par cette fonction softmax, le problème de classification est réduit à la probabilité, et la valeur la plus élevée est la valeur prédite.
En termes d'implémentation, puisqu'il s'agit d'une fonction exponentielle de exp, il existe un problème en ce que la valeur est très facile à diverger. Par conséquent, il semble que c'est souvent fait pour des raisons de commodité qu'il devient difficile de diverger en multipliant une certaine constante par le dénominateur et la molécule et en l'insérant dans l'exposant de exp.
NN.ipynb
def softmax(a):
c = np.max(a)
exp_a = np.exp(a-c)
sum_exp_a = np.sum(exp_a)
y = exp_a/sum_exp_a
return y
NN.ipynb
network = init_network()
x = np.array([2,1])
y = forword(network,x)
print(y)
[0.40442364 0.59557636]
En guise de test, j'ai mis une valeur appropriée dans x et la réponse a été renvoyée comme suit. Une valeur indiquant que y1 a une probabilité de 40% et y2 a une probabilité de 60% a été sortie. Après cela, je comprends qu'une classification compliquée deviendra possible à mesure que la matrice d'entrée deviendra plus grande et que les couches deviendront plus profondes (≈ augmenter).
Cette fois, j'ai créé à la main un réseau de neurones très basique. Juste en bougeant ma main, j'ai approfondi ma compréhension. ** J'ai finalement compris les bases de l'algorithme GAN que j'ai copié et déplacé. ** En mettant ici des idées telles que l'apprentissage de modèle et la convolution, il sera connecté au réseau neuronal de convolution et ensuite au GAN. C'est peut-être un début pour atteindre les dernières technologies, mais j'espère qu'en approfondissant régulièrement ma compréhension de cette manière, j'améliorerai sûrement mes capacités techniques.
Le programme complet est ici. Il est divisé en un fichier que vous venez de jouer avec la fonction et un fichier qui est un réseau neuronal à 3 couches. https://github.com/Fumio-eisan/neuralnetwork_20200318
Recommended Posts