C'est un record d'apprentissage lorsque j'ai pris le Rabbit Challenge dans le but de réussir la qualification JDLA (Japan Deep Learning Association) E, qui se tiendra les 19 et 20 janvier 2021.
Rabbit Challenge est un cours qui utilise le matériel pédagogique édité à partir de la vidéo enregistrée du cours de fréquentation scolaire du «cours d'apprentissage en profondeur qui peut être écrasé sur le terrain». Il n'y a pas de support pour les questions, mais c'est un cours bon marché (le prix le plus bas en juin 2020) pour passer l'examen de qualification E.
Veuillez vérifier les détails à partir du lien ci-dessous.
Mathématiques appliquées Apprentissage automatique Apprentissage en profondeur (jour1) Apprentissage en profondeur (jour2) Apprentissage en profondeur (jour3) Apprentissage en profondeur (jour 4)
Le réseau neuronal récurrent (RNN) est un réseau neuronal capable de gérer des données chronologiques. Les données de séries chronologiques sont une série de données qui sont observées à intervalles réguliers dans l'ordre chronologique et qui ont une dépendance statistique les unes sur les autres, et qui incluent des données audio et des données textuelles.
Puisque RNN gère les données de séries chronologiques, il a besoin d'une structure récursive qui contient l'état initial et l'état de $ t-1 $ dans le passé, et trouve l'état de $ t $ la fois suivante.
En tant que méthode de réglage des paramètres dans RNN, il existe BPTT qui est une sorte de propagation de retour d'erreur.
[Formule de mise à jour des paramètres]
simple_RNN (addition binaire)
import sys, os
sys.path.append(os.pardir) #Paramètres d'importation des fichiers dans le répertoire parent
import numpy as np
from common import functions
import matplotlib.pyplot as plt
def d_tanh(x):
return 1/(np.cosh(x) ** 2)
#Préparez les données
#Nombre de chiffres binaires
binary_dim = 8
#Valeur maximum+ 1
largest_number = pow(2, binary_dim)
# largest_Préparez des nombres binaires jusqu'au nombre
binary = np.unpackbits(np.array([range(largest_number)],dtype=np.uint8).T,axis=1)
input_layer_size = 2
hidden_layer_size = 16
output_layer_size = 1
weight_init_std = 1
learning_rate = 0.1
iters_num = 10000
plot_interval = 100
#Initialisation du poids(Le biais est omis pour plus de simplicité)
W_in = weight_init_std * np.random.randn(input_layer_size, hidden_layer_size)
W_out = weight_init_std * np.random.randn(hidden_layer_size, output_layer_size)
W = weight_init_std * np.random.randn(hidden_layer_size, hidden_layer_size)
# Xavier
# W_in = np.random.randn(input_layer_size, hidden_layer_size) / (np.sqrt(input_layer_size))
# W_out = np.random.randn(hidden_layer_size, output_layer_size) / (np.sqrt(hidden_layer_size))
# W = np.random.randn(hidden_layer_size, hidden_layer_size) / (np.sqrt(hidden_layer_size))
# He
# W_in = np.random.randn(input_layer_size, hidden_layer_size) / (np.sqrt(input_layer_size)) * np.sqrt(2)
# W_out = np.random.randn(hidden_layer_size, output_layer_size) / (np.sqrt(hidden_layer_size)) * np.sqrt(2)
# W = np.random.randn(hidden_layer_size, hidden_layer_size) / (np.sqrt(hidden_layer_size)) * np.sqrt(2)
#Pente
W_in_grad = np.zeros_like(W_in)
W_out_grad = np.zeros_like(W_out)
W_grad = np.zeros_like(W)
u = np.zeros((hidden_layer_size, binary_dim + 1))
z = np.zeros((hidden_layer_size, binary_dim + 1))
y = np.zeros((output_layer_size, binary_dim))
delta_out = np.zeros((output_layer_size, binary_dim))
delta = np.zeros((hidden_layer_size, binary_dim + 1))
all_losses = []
for i in range(iters_num):
# A,Initialisation B(a + b = d)
a_int = np.random.randint(largest_number/2)
a_bin = binary[a_int] # binary encoding
b_int = np.random.randint(largest_number/2)
b_bin = binary[b_int] # binary encoding
#Corriger les données de réponse
d_int = a_int + b_int
d_bin = binary[d_int]
#Sortie binaire
out_bin = np.zeros_like(d_bin)
#Erreur sur la série chronologique
all_loss = 0
#Boucle de séries temporelles
for t in range(binary_dim):
#Valeur d'entrée
X = np.array([a_bin[ - t - 1], b_bin[ - t - 1]]).reshape(1, -1)
#Corriger les données de réponse au temps t
dd = np.array([d_bin[binary_dim - t - 1]])
u[:,t+1] = np.dot(X, W_in) + np.dot(z[:,t].reshape(1, -1), W)
z[:,t+1] = functions.sigmoid(u[:,t+1])
# z[:,t+1] = functions.relu(u[:,t+1])
# z[:,t+1] = np.tanh(u[:,t+1])
y[:,t] = functions.sigmoid(np.dot(z[:,t+1].reshape(1, -1), W_out))
#Erreur
loss = functions.mean_squared_error(dd, y[:,t])
delta_out[:,t] = functions.d_mean_squared_error(dd, y[:,t]) * functions.d_sigmoid(y[:,t])
all_loss += loss
out_bin[binary_dim - t - 1] = np.round(y[:,t])
for t in range(binary_dim)[::-1]:
X = np.array([a_bin[-t-1],b_bin[-t-1]]).reshape(1, -1)
delta[:,t] = (np.dot(delta[:,t+1].T, W.T) + np.dot(delta_out[:,t].T, W_out.T)) * functions.d_sigmoid(u[:,t+1])
# delta[:,t] = (np.dot(delta[:,t+1].T, W.T) + np.dot(delta_out[:,t].T, W_out.T)) * functions.d_relu(u[:,t+1])
# delta[:,t] = (np.dot(delta[:,t+1].T, W.T) + np.dot(delta_out[:,t].T, W_out.T)) * d_tanh(u[:,t+1])
#Mise à jour du dégradé
W_out_grad += np.dot(z[:,t+1].reshape(-1,1), delta_out[:,t].reshape(-1,1))
W_grad += np.dot(z[:,t].reshape(-1,1), delta[:,t].reshape(1,-1))
W_in_grad += np.dot(X.T, delta[:,t].reshape(1,-1))
#Application de dégradé
W_in -= learning_rate * W_in_grad
W_out -= learning_rate * W_out_grad
W -= learning_rate * W_grad
W_in_grad *= 0
W_out_grad *= 0
W_grad *= 0
if(i % plot_interval == 0):
all_losses.append(all_loss)
print("iters:" + str(i))
print("Loss:" + str(all_loss))
print("Pred:" + str(out_bin))
print("True:" + str(d_bin))
out_int = 0
for index,x in enumerate(reversed(out_bin)):
out_int += x * pow(2, index)
print(str(a_int) + " + " + str(b_int) + " = " + str(out_int))
print("------------")
lists = range(0, iters_num, plot_interval)
plt.plot(lists, all_losses, label="loss")
plt.xlabel("iters_num", fontsize=14)
plt.ylabel("loss", fontsize=14)
plt.show()
--Modification du poids_init_std → Lorsque weight_init_std a été réduit de 1,0 à 0,5 ou augmenté à 2,0, les deux ont convergé lentement.
--Changé taille_couche_cachée → Diminuer hidden_layer_size de 16 à 8 ralentit l'apprentissage, mais l'augmenter à 32 accéléra l'apprentissage et l'augmenter à 128 ralentit l'apprentissage.
--Modification de la méthode d'initialisation du poids ・ Changer pour Xavier ・ Changer pour He → Les deux méthodes d'initialisation ont ralenti l'apprentissage.
--Changé la fonction d'activation de la couche intermédiaire
・ Changer pour ReLU
・ Changer pour tanh
Section2:LSTM(Long Short-Term Memory) Avec un RNN simple, les dépendances à longue distance ne peuvent pas être bien apprises en raison de la disparition du gradient lors de l'exécution de la propagation de retour d'erreur. LSTM est utilisé comme méthode pour résoudre le problème.
Input gate:$ i_t = \sigma(W^{(i)}x_t + U^{(i)}h_{t-1} + b^{(i)} ) $
Forget gate:$ f_t = \sigma(W^{(f)}x_t + U^{(f)}h_{t-1} + b^{(f)} ) $
output gate:$ o_t = \sigma(W^{(o)}x_t + U^{(o)}h_{t-1} + b^{(o)} ) $ --Cellule mémoire: $ \ tilde c_t = tanh (W ^ {(\ tilde c)} x_t + U ^ {(\ tilde c)} h_ {t-1} + b ^ {(\ tilde c)}, \ quad c_t = i_t \ circ \ tilde c_t + f_t \ circ c_ {t-1} $ --Mise à jour de l'état: $ h_t = o_t \ circ tanh (c_t) $
CEC(Constant Error Carousel) Comme solution pour la disparition du gradient et l'explosion du gradient, elle peut être résolue si le gradient est 1. Problème: le poids des données d'entrée est uniforme quelle que soit la dépendance temporelle. → Il n'y a pas de caractéristique d'apprentissage du réseau de neurones.
Porte d'entrée et porte de sortie Le problème de CEC est résolu en ajoutant une porte d'entrée et une porte de sortie et en faisant le poids de la valeur d'entrée à chaque porte variable par les matrices de poids W et U.
Porte de l'oubli CEC stocke toutes les informations passées, mais lorsque les informations passées ne sont plus nécessaires, elles ne peuvent pas être supprimées et restent stockées. Par conséquent, lorsque les informations passées ne sont plus nécessaires, la porte de l'oubli est née comme hier pour oublier les informations à ce moment-là.
Connexion judas Je veux propager ou oublier les informations passées stockées dans CEC vers d'autres nœuds à tout moment. La valeur de CEC elle-même n'affecte pas la commande de porte. → Connexion judas comme structure qui permet la propagation à la valeur de CEC elle-même via une matrice de poids.
Section3:GRU(Gated Recurrent Unit) Dans le LSTM conventionnel, comme il y avait de nombreux paramètres, l'ajout de calcul était important. Par conséquent, GRU a une structure dans laquelle les paramètres sont considérablement réduits et la précision peut être espérée égale ou supérieure à cela.
Un modèle pour améliorer la précision en ajoutant non seulement des informations passées mais également des informations futures. Utilisé pour l'élaboration de texte et la traduction automatique.
Section5:Seq2Seq Les RNN normaux doivent avoir la même longueur et ordre d'entrée et de sortie. D'autre part, Seq2Seq est une sorte de modèle Encoder-Decoder et utilise différents RNN du côté entrée et du côté sortie. Utilisé pour le dialogue automatique et la traduction automatique.
Encoder RNN Une structure dans laquelle les données de texte entrées par l'utilisateur sont divisées en jetons tels que des mots et transmises. Entrez vec1 dans RNN et affichez l'état caché. Cet état masqué et la prochaine entrée vec2 ont de nouveau été saisis dans RNN. Définissez l'état masqué lorsque le dernier vec est inséré comme état final. Cet état final est appelé un vecteur de pensée et devient un vecteur qui exprime le sens de la phrase d'entrée.
Decoder RNN Une structure dans laquelle le système génère des données de sortie pour chaque jeton tel qu'un mot.
[Procédure de traitement RNN du décodeur]
HRED Générez le prochain énoncé à partir des n-1 énoncés précédents. Dans Seq2seq, la réponse a été faite en ignorant le contexte de la conversation, mais dans HRED, la réponse suit le flux du mot précédent, donc une phrase plus humaine est générée. Avec une structure qui combine Seq2seq et Context RNN (une structure qui combine la série de phrases compilées par Encoder et la convertit en un vecteur qui représente tout le contexte de conversation jusqu'à présent), il génère une réponse qui prend en compte l'historique des énoncés passés. Il y a. Problème 1: Il n'y a que la diversité littérale, pas le «flux» de la conversation. → Même si le même contexte (liste de discours) est donné, le contenu de la réponse ne peut être que le même que le flux de la conversation à chaque fois. Problème 2: il a tendance à donner des réponses courtes et pauvres en informations. → A tendance à apprendre des réponses courtes et communes.
VHRED Une structure qui résout les problèmes de HRED en ajoutant le concept de variables latentes de VAE à HRED.
VAE En supposant une distribution de probabilité pour la variable latente z.
Section6:Word2vec Dans RNN, il n'est pas possible de donner à NN une chaîne de caractères de longueur variable telle qu'un mot. Dans word2vec, un vocabulaire a été créé à partir de données d'apprentissage, et une matrice pondérée «nombre de vocabulaire x nombre de dimensions du vecteur de mot arbitraire» a permis de réaliser l'apprentissage de la représentation distribuée de données à grande échelle avec une vitesse de calcul et une quantité de mémoire réalistes. Le vecteur numérique résultant peut être utilisé pour transformer du texte brut en une représentation numérique adaptée à la visualisation de données, à l'apprentissage automatique et à l'apprentissage en profondeur.
Section7:Attention Mechanism Un mécanisme pour apprendre le degré de pertinence de «quel mot d'entrée et de sortie est lié». En utilisant la moyenne pondérée de l'état caché de chaque mot dans le codeur en tant qu'entrée en tant qu'information lorsque le décodeur sort chaque mot, les informations de contexte de la phrase source de traduction peuvent être appréhendées plus en détail. Avec l'introduction du mécanisme Attention, la précision de la traduction automatique neuronale a été considérablement améliorée, dépassant les performances des modèles de traduction automatique statistiques conventionnels.