[PYTHON] Deep Learning / Deep Learning à partir de Zero 2 Chapitre 5 Mémo

1.Tout d'abord

Je lis un chef-d'œuvre, ** "Deep Learning from Zero 2" **. Cette fois, c'est un mémo du chapitre 5. Pour exécuter le code, téléchargez le code complet depuis Github et utilisez le notebook jupyter dans ch05.

2.RNNLM Tout d'abord, essayez d'exécuter le code suivant, ch05 / train_custom_loop.py, qui apprend l'ordre des mots de l'ensemble de données PTB.

import sys
sys.path.append('..')
import matplotlib.pyplot as plt
import numpy as np
from common.optimizer import SGD
from dataset import ptb
from simple_rnnlm import SimpleRnnlm

#Paramètres des hyper paramètres
batch_size = 10
wordvec_size = 100
hidden_size = 100
time_size = 5  #Durée de déploiement du BPTT tronqué
lr = 0.1
max_epoch = 100

#Lire les données d'entraînement (réduire le jeu de données)
corpus, word_to_id, id_to_word = ptb.load_data('train')
corpus_size = 1000
corpus = corpus[:corpus_size]
vocab_size = int(max(corpus) + 1)

xs = corpus[:-1]  #contribution
ts = corpus[1:]  #Sortie (étiquette de l'enseignant)
data_size = len(xs)
print('corpus size: %d, vocabulary size: %d' % (corpus_size, vocab_size))

#Variables utilisées lors de l'apprentissage
max_iters = data_size // (batch_size * time_size)
time_idx = 0
total_loss = 0
loss_count = 0
ppl_list = []

#Génération de modèle
model = SimpleRnnlm(vocab_size, wordvec_size, hidden_size)
optimizer = SGD(lr)

#Calculer la position de départ de chargement de chaque échantillon dans le mini-lot
jump = (corpus_size - 1) // batch_size
offsets = [i * jump for i in range(batch_size)]

for epoch in range(max_epoch):
    for iter in range(max_iters):
        #Obtenez un mini lot
        batch_x = np.empty((batch_size, time_size), dtype='i')
        batch_t = np.empty((batch_size, time_size), dtype='i')
        for t in range(time_size):
            for i, offset in enumerate(offsets):
                batch_x[i, t] = xs[(offset + time_idx) % data_size]
                batch_t[i, t] = ts[(offset + time_idx) % data_size]
            time_idx += 1

        #Trouvez le dégradé et mettez à jour les paramètres
        loss = model.forward(batch_x, batch_t)
        model.backward()
        optimizer.update(model.params, model.grads)
        total_loss += loss
        loss_count += 1

    #Évaluation de la perplexité pour chaque époque
    ppl = np.exp(total_loss / loss_count)
    print('| epoch %d | perplexity %.2f'
          % (epoch+1, ppl))
    ppl_list.append(float(ppl))
    total_loss, loss_count = 0, 0

#Dessiner un graphique
x = np.arange(len(ppl_list))
plt.plot(x, ppl_list, label='train')
plt.xlabel('epochs')
plt.ylabel('perplexity')
plt.show()

スクリーンショット 2020-05-18 18.32.37.png L'axe vertical du graphique est un index appelé ** perplexité ** qui prédit la probabilité du mot suivant, et $ perplexité = e ^ L \ (L = - \ frac {1} {N} \ sum_n \ sum_k t_ { Il est exprimé par la formule nk} log y_ {nk}) $. Plus la valeur de perplexité est proche de 1, plus la précision de prédiction est élevée. En termes simples, la perplexité est le nombre de choix pour le mot suivant. Jetons un coup d'œil à la partie qui prépare les données.

スクリーンショット 2020-05-19 10.45.53.png

** corpus ** utilise uniquement les 1 000 premiers mots de l'ensemble de données PTB, et ** les données de formation xs ** et ** les données de l'enseignant ts ** obtiennent 999 mots chacune dans un mot.

Ensuite, utilisez des «décalages» pour déterminer les positions de lecture (10 emplacements) pour la taille du lot, et créez un mini-lot en divisant chaque donnée pour la taille de temps (5). Lorsque ʻoffsets + time_idx` devient 999 ou plus de la taille des données, il recommence à partir de 0 et les données sont acquises.

Jetons un coup d'œil à la ** class SimpleRnnlm **, qui génère le modèle.

3.SimpleRnnlm

class SimpleRnnlm:
    def __init__(self, vocab_size, wordvec_size, hidden_size):
        V, D, H = vocab_size, wordvec_size, hidden_size
        rn = np.random.randn

        #Initialisation du poids
        embed_W = (rn(V, D) / 100).astype('f')
        rnn_Wx = (rn(D, H) / np.sqrt(D)).astype('f')
        rnn_Wh = (rn(H, H) / np.sqrt(H)).astype('f')
        rnn_b = np.zeros(H).astype('f')
        affine_W = (rn(H, V) / np.sqrt(H)).astype('f')
        affine_b = np.zeros(V).astype('f')

        #Génération de couches
        self.layers = [
            TimeEmbedding(embed_W),
            TimeRNN(rnn_Wx, rnn_Wh, rnn_b, stateful=True),
            TimeAffine(affine_W, affine_b)
        ]
        self.loss_layer = TimeSoftmaxWithLoss()
        self.rnn_layer = self.layers[1]

        #Lister tous les poids et dégradés
        self.params, self.grads = [], []
        for layer in self.layers:
            self.params += layer.params
            self.grads += layer.grads

    def forward(self, xs, ts):
        for layer in self.layers:
            xs = layer.forward(xs)
        loss = self.loss_layer.forward(xs, ts)
        return loss

    def backward(self, dout=1):
        dout = self.loss_layer.backward(dout)
        for layer in reversed(self.layers):
            dout = layer.backward(dout)
        return dout

    def reset_state(self):
        self.rnn_layer.reset_state()

スクリーンショット 2020-05-17 13.58.22.png

** class SimpleRnnlm ** est une pile de quatre ** couches de temps **: ** TimeEmbedding, Time RNN, Time Affine et Time Softmax With Loss **. Jetons un coup d'œil à la couche Time dans l'ordre.

4. Couche d'intégration temporelle

class TimeEmbedding:
    def __init__(self, W):
        self.params = [W]
        self.grads = [np.zeros_like(W)]
        self.layers = None
        self.W = W

    def forward(self, xs):
        N, T = xs.shape
        V, D = self.W.shape

        out = np.empty((N, T, D), dtype='f')
        self.layers = []

        for t in range(T):
            layer = Embedding(self.W)
            out[:, t, :] = layer.forward(xs[:, t])
            self.layers.append(layer)

        return out

    def backward(self, dout):
        N, T, D = dout.shape

        grad = 0
        for t in range(T):
            layer = self.layers[t]
            layer.backward(dout[:, t, :])
            grad += layer.grads[0]

        self.grads[0][...] = grad
        return None

スクリーンショット 2020-05-21 09.21.15.png

La ** couche Time Embedding ** coupe les données une colonne à la fois à partir de xs, les entre dans la ** couche Embedding ** et stocke la sortie dans ** out (N, T, D) **. Il répète T fois en boucle.

5. Couche RNN

Avant de regarder la couche TimeRNN, regardons la couche RNN utilisée pour la couche TimeRNN.

class RNN:
    def __init__(self, Wx, Wh, b):
        self.params = [Wx, Wh, b]
        self.grads = [np.zeros_like(Wx), np.zeros_like(Wh), np.zeros_like(b)]
        self.cache = None

    def forward(self, x, h_prev):
        Wx, Wh, b = self.params
        t = np.dot(h_prev, Wh) + np.dot(x, Wx) + b
        h_next = np.tanh(t)

        self.cache = (x, h_prev, h_next)
        return h_next

スクリーンショット 2020-05-21 10.53.11.png

La couche RNN a deux poids. Ce sont le poids ** W_x ** qui prend l'entrée x_t et le produit interne (MatMul) et le poids ** W_h ** qui prend l'entrée h_prev et le produit interne (MatMUl).

    def backward(self, dh_next):
        Wx, Wh, b = self.params
        x, h_prev, h_next = self.cache

        dt = dh_next * (1 - h_next ** 2)
        db = np.sum(dt, axis=0)
        dWh = np.dot(h_prev.T, dt)
        dh_prev = np.dot(dt, Wh.T)
        dWx = np.dot(x.T, dt)
        dx = np.dot(dt, Wx.T)

        self.grads[0][...] = dWx
        self.grads[1][...] = dWh
        self.grads[2][...] = db

        return dx, dh_prev

スクリーンショット 2020-05-21 10.54.58.png

La rétropropagation ressemble à ceci. C'est une version modifiée d'Affine, donc rien de compliqué.

6. Couche TimeRNN

class TimeRNN:
    def __init__(self, Wx, Wh, b, stateful=False):
        self.params = [Wx, Wh, b]
        self.grads = [np.zeros_like(Wx), np.zeros_like(Wh), np.zeros_like(b)]
        self.layers = None

        self.h, self.dh = None, None
        self.stateful = stateful

    def forward(self, xs):
        Wx, Wh, b = self.params
        N, T, D = xs.shape
        D, H = Wx.shape

        self.layers = []
        hs = np.empty((N, T, H), dtype='f')

        if not self.stateful or self.h is None:
            self.h = np.zeros((N, H), dtype='f')

        for t in range(T):
            layer = RNN(*self.params)
            self.h = layer.forward(xs[:, t, :], self.h)
            hs[:, t, :] = self.h
            self.layers.append(layer)

        return hs

スクリーンショット 2020-05-21 10.56.02.png

** La couche TimeRNN ** est un réseau de couches T RNN connectées entre elles. Vous permet d'ajuster s'il faut hériter de l'état h entre les blocs avec l'argument stateful.

Pour la propagation directe, préparez d'abord le conteneur de sortie hs (N, T, H). Ensuite, en tournant la boucle for, les t-ièmes données sont coupées par xs [:, t,:] et entrées dans le RNN normal, et la sortie est le conteneur préparé par hs [:, t,:]. Tout en le stockant dans la position spécifiée de, enregistrez le calque dans les calques.

En d'autres termes, la couche TimeRNN est l'entrée / sortie de la couche RNN avec les fonctions d'extraction et de récapitulation des données.

    def backward(self, dhs):
        Wx, Wh, b = self.params
        N, T, H = dhs.shape
        D, H = Wx.shape

        dxs = np.empty((N, T, D), dtype='f')
        dh = 0
        grads = [0, 0, 0]
        for t in reversed(range(T)):
            layer = self.layers[t]
            dx, dh = layer.backward(dhs[:, t, :] + dh)  #Gradient additionné
            dxs[:, t, :] = dx

            for i, grad in enumerate(layer.grads):
                grads[i] += grad

        for i, grad in enumerate(grads):
            self.grads[i][...] = grad
        self.dh = dh

        return dxs

    def set_state(self, h):
        self.h = h

    def reset_state(self):
        self.h = None

スクリーンショット 2020-05-19 10.27.35.png

La propagation directe TimeRNN a deux sorties, donc dans le cas de la propagation arrière, $ dh_t + dh_ {next} $, qui est la somme des deux, est entrée.

Tout d'abord, créez un conteneur dxs qui coule en aval, trouvez le gradient dx à chaque fois avec backward () de la couche RNN dans l'ordre inverse de la propagation directe, et affectez-le à l'indice correspondant de dxs. Le paramètre poids ajoute les gradients de poids pour chaque calque et écrase le résultat final dans self.grads.

7. Couche TimeAffine

class TimeAffine:
    def __init__(self, W, b):
        self.params = [W, b]
        self.grads = [np.zeros_like(W), np.zeros_like(b)]
        self.x = None

    def forward(self, x):
        N, T, D = x.shape
        W, b = self.params

        rx = x.reshape(N*T, -1)
        out = np.dot(rx, W) + b
        self.x = x
        return out.reshape(N, T, -1)

    def backward(self, dout):
        x = self.x
        N, T, D = x.shape
        W, b = self.params

        dout = dout.reshape(N*T, -1)
        rx = x.reshape(N*T, -1)

        db = np.sum(dout, axis=0)
        dW = np.dot(rx.T, dout)
        dx = np.dot(dout, W.T)
        dx = dx.reshape(*x.shape)

        self.grads[0][...] = dW
        self.grads[1][...] = db

        return dx

スクリーンショット 2020-05-21 10.56.51.png

La ** couche Affine temporelle ** est l'entrée et la sortie de la ** couche Affine ** avec remodelage ajouté afin qu'elle puisse correspondre à T dans la direction de l'axe des temps.

8.TimeSoftmaxWithLoss

class TimeSoftmaxWithLoss:
    def __init__(self):
        self.params, self.grads = [], []
        self.cache = None
        self.ignore_label = -1

    def forward(self, xs, ts):
        N, T, V = xs.shape

        if ts.ndim == 3:  #L'étiquette de l'enseignant en est une-Pour vecteur chaud
            ts = ts.argmax(axis=2)

        mask = (ts != self.ignore_label)

        #Collecter des lots et des séries chronologiques (remodeler)
        xs = xs.reshape(N * T, V)
        ts = ts.reshape(N * T)
        mask = mask.reshape(N * T)

        ys = softmax(xs)
        ls = np.log(ys[np.arange(N * T), ts])
        ls *= mask  # ignore_Les données correspondant à l'étiquette définissent la perte sur 0
        loss = -np.sum(ls)
        loss /= mask.sum()

        self.cache = (ts, ys, mask, (N, T, V))
        return loss

    def backward(self, dout=1):
        ts, ys, mask, (N, T, V) = self.cache

        dx = ys
        dx[np.arange(N * T), ts] -= 1
        dx *= dout
        dx /= mask.sum()
        dx *= mask[:, np.newaxis]  # ignore_Mettre le dégradé à 0 pour les données correspondant à l'étiquette

        dx = dx.reshape((N, T, V))

        return dx

スクリーンショット 2020-05-20 19.00.44.png ** Time Softmax with Loss Layer ** est une couche qui ajoute T de Sotmax avec perte de $ x_t et t_t $ et divise par T.

9. Création d'un jeu de données de version japonaise

Essayons-le avec un ensemble de données japonais pour avoir une meilleure compréhension de l'ensemble. Cependant, si vous essayez de le faire mot par mot, une analyse morphologique est nécessaire, donc ** unité de caractère **. Cette fois, j'ai téléchargé "Old Man and the Sea" depuis Aozora Bunko et l'ai utilisé.

import numpy as np
import io

def load_data():
    
    # file_UTF les 1000 premiers caractères du nom-Lire en texte au format 8
    file_name = './data_rojinto_umi.txt'
    length = 1000
    with io.open(file_name, encoding='utf-8') as f:
        text = f.read().lower()
        text = text[:length]

    # word_to_id, id_to_Créer un mot
    word_to_id, id_to_word = {}, {}
    for word in text:
        if word not in word_to_id:
            new_id = len(word_to_id)
            word_to_id[word] = new_id
            id_to_word[new_id] = word

    #Créer un corpus
    corpus = np.array([word_to_id[W] for W in text])  
    
    return text, corpus, word_to_id, id_to_word

Lit 1000 caractères à partir du début du fichier texte spécifié par nom_fichier au format UTF-8. Une fonction qui renvoie du texte, du corpus, du mot_à_id, de l'id_ au mot. Bougeons un peu.

text, corpus, word_to_id, id_to_word = load_data()
print('text_length = ', len(text))
print(text)

スクリーンショット 2020-05-20 15.09.17.png La longueur du "texte" est de 1000 comme spécifié. Si vous le préparez en unités de caractères, le texte est très compact.

print('vocab_size = ', len(word_to_id))
print(word_to_id)

スクリーンショット 2020-05-20 15.17.08.png

C'est word_to_id. «vocab_size» n'est pas aussi grand que je le pensais 236. Ceci est utilisé pour remplacer chaque caractère de «texte» par id pour créer un «corpus».

print('corpus_length = ', len(corpus))
print(corpus[:500])

スクリーンショット 2020-05-20 15.22.04.png C'est un corpus. L'affichage est limité à 500 caractères depuis le début.

text2 = ''.join([id_to_word[id] for id in corpus])
print(text2)

スクリーンショット 2020-05-20 15.26.55.png

La conversion de l'identifiant de corpus en un caractère en utilisant ʻid_to_word` retournera au premier texte comme ceci.

Maintenant, comme c'est un gros problème, j'aimerais préparer des données de test et des réponses et vérifier combien de prédictions peuvent être faites pour chaque époque.

#Échantillon de corpus
x = corpus[:50]
t = corpus[1:51]
print('x = ', x)
print('t = ', t)

#Confirmation par SMS
text_x = ''.join([id_to_word[id] for id in x])
text_t = ''.join([id_to_word[id] for id in t])
print('text_x = ', text_x)
print('text_t = ', text_t)

#Convertir au format batch
test_x = x.reshape(10, 5)
test_t = t.reshape(10, 5)
print(test_x)
print(test_t)

スクリーンショット 2020-05-20 15.57.51.png Obtenez x, t de corpus en décalant 50 caractères d'un caractère. Pour le moment, je le convertis en caractères et vérifie le contenu. Ensuite, il est converti en la forme (10, 5) utilisée dans le modèle, et les données de prédiction test_x et test_t pour les tests sont créées.

    def generate(self, xs):
        for layer in self.layers:
            xs = layer.forward(xs)
        return xs

Plus tard, j'ajouterai ce code à la fin de simple_rnnlm.py pour faire des prédictions pour chaque époque.

10. RNNLM modifié

Ensuite, en vous basant sur le code ch05 / train_custom_loop.py qui a été exécuté en premier, modifiez et ajoutez les deux parties de ** lecture des données d'apprentissage et exécution de l'inférence des données de test **. Le nombre d'époques est de 1000 fois.

import sys
sys.path.append('..')
import matplotlib.pyplot as plt
import numpy as np
from common.optimizer import SGD
from dataset import ptb
from simple_rnnlm import SimpleRnnlm    

#Paramètres des hyper paramètres
batch_size = 10
wordvec_size = 100
hidden_size = 100
time_size = 5  #Durée de déploiement du BPTT tronqué
lr = 0.1
max_epoch = 1000  

# -----------Lecture des données d'entraînement-------------
text, corpus, word_to_id, id_to_word = load_data()
corpus_size = 1000
vocab_size = int(max(corpus) + 1)
# ----------------------------------------------

xs = corpus[:-1]  #contribution
ts = corpus[1:]  #Sortie (étiquette de l'enseignant)
data_size = len(xs)
print('corpus size: %d, vocabulary size: %d' % (corpus_size, vocab_size))

#Variables utilisées lors de l'apprentissage
max_iters = data_size // (batch_size * time_size)  
time_idx = 0
total_loss = 0
loss_count = 0
ppl_list = []

#Génération de modèle
model = SimpleRnnlm(vocab_size, wordvec_size, hidden_size)
optimizer = SGD(lr)

#Calculer la position de départ de chargement de chaque échantillon dans le mini-lot
jump = (corpus_size - 1) // batch_size
offsets = [i * jump for i in range(batch_size)]

for epoch in range(max_epoch):
    for iter in range(max_iters):
        #Obtenez un mini lot
        batch_x = np.empty((batch_size, time_size), dtype='i')
        batch_t = np.empty((batch_size, time_size), dtype='i')
        for t in range(time_size):
            for i, offset in enumerate(offsets):
                batch_x[i, t] = xs[(offset + time_idx) % data_size]
                batch_t[i, t] = ts[(offset + time_idx) % data_size]
            time_idx += 1

        #Trouvez le dégradé et mettez à jour les paramètres
        loss = model.forward(batch_x, batch_t)
        model.backward()
        optimizer.update(model.params, model.grads)
        total_loss += loss
        loss_count += 1

    #Évaluation de la perplexité pour chaque époque
    ppl = np.exp(total_loss / loss_count)
    print('| epoch %d | perplexity %.2f'
          % (epoch+1, ppl))
    ppl_list.append(float(ppl))
    total_loss, loss_count = 0, 0
    
    # ----------Prédiction avec les données de test------------
    pred= model.generate(test_x) 
    predict = np.argmax(pred, axis = 2) 
    print(predict)
    # ------------------------------------------------
    
#Dessiner un graphique
x = np.arange(len(ppl_list))
plt.plot(x, ppl_list, label='train')
plt.xlabel('epochs')
plt.ylabel('perplexity')
plt.show()

スクリーンショット 2020-05-20 17.02.11.png Après 1000 époques, la perplexité est tombée à 1,08. Puisque le résultat de la prédiction basé sur les données de test est affiché pour chaque époque, si vous regardez le résultat de la prédiction après 1 époque, il est de 5 ("ta" de Hiragana). Quand vous venez d'apprendre, cela ressemble à ceci. Ceci, le résultat de la prédiction après 1000 époques est tout à fait comme ça. Vérifions maintenant le résultat final de la prédiction.

スクリーンショット 2020-05-20 18.42.27.png

La bonne réponse est entourée de rouge après la correspondance des résultats de prédiction. Puisqu'il est 24/50, le taux de réponse correcte est de 48%, ce qui n'est pas aussi élevé que prévu. Est-ce parce que le taux de réponse correcte dans la seconde moitié des cinq caractères est élevé parce qu'il peut être prédit en fonction des caractères de la première moitié? Si vous essayez d'exprimer le résultat de la prédiction de la première ligne avec un modèle,

スクリーンショット 2020-05-20 18.36.00.png

Je vois. Avez-vous fait une erreur comme celle-ci?

Recommended Posts

Deep learning / Deep learning from scratch 2 Chapitre 4 Mémo
Deep learning / Deep learning made from scratch Chapitre 3 Mémo
Deep Learning / Deep Learning à partir de Zero 2 Chapitre 5 Mémo
Deep Learning / Deep Learning à partir de Zero 2 Chapitre 7 Mémo
Deep Learning / Deep Learning à partir de Zero 2 Chapitre 8 Mémo
Deep learning / Deep learning made from scratch Chapitre 5 Mémo
Deep learning / Deep learning made from scratch Chapitre 4 Mémo
Deep learning / Deep learning from scratch 2 Chapitre 3 Mémo
Deep Learning / Deep Learning à partir de Zero 2 Chapitre 6 Mémo
[Mémo d'apprentissage] Le Deep Learning fait de zéro [Chapitre 7]
Deep learning / Deep learning made from scratch Chapitre 6 Mémo
[Mémo d'apprentissage] Deep Learning fait de zéro [Chapitre 5]
[Mémo d'apprentissage] Le Deep Learning fait de zéro [Chapitre 6]
Deep learning / Deep learning made from scratch Chapitre 7 Mémo
[Mémo d'apprentissage] Deep Learning fait de zéro [~ Chapitre 4]
Deep Learning from scratch Chapter 2 Perceptron (lecture du mémo)
Mémo d'auto-apprentissage "Deep Learning from scratch" (partie 12) Deep learning
Apprentissage profond à partir de zéro
Mémo d'auto-apprentissage "Deep Learning from scratch" (glossaire illisible)
"Deep Learning from scratch" Mémo d'auto-apprentissage (n ° 9) Classe MultiLayerNet
Deep Learning from scratch ① Chapitre 6 "Techniques liées à l'apprentissage"
[Mémo d'apprentissage] Apprentissage profond à partir de zéro ~ Mise en œuvre de l'abandon ~
Mémo d'auto-apprentissage «Deep Learning from scratch» (10) Classe MultiLayerNet
Mémo d'auto-apprentissage «Deep Learning from scratch» (n ° 11) CNN
Apprentissage profond à partir de zéro 1 à 3 chapitres
Mémo d'auto-apprentissage «Deep Learning from scratch» (n ° 19) Augmentation des données
Mémo d'apprentissage Python pour l'apprentissage automatique par Chainer du chapitre 2
Deep Learning 2 from scratch 1.3 Traitement du langage naturel 1.3 Résumé
Un amateur a trébuché dans le Deep Learning ❷ fait à partir de zéro Note: Chapitre 5
Un amateur a trébuché dans le Deep Learning ❷ fait à partir de zéro Note: Chapitre 2
Apprentissage profond à partir de zéro (calcul des coûts)
Un amateur a trébuché dans le Deep Learning à partir de zéro Note: Chapitre 3
Un amateur a trébuché dans le Deep Learning à partir de zéro Note: Chapitre 7
Un amateur a trébuché dans le Deep Learning à partir de zéro Note: Chapitre 5
Un amateur a trébuché dans le Deep Learning ❷ fait de zéro Note: Chapitre 1
Un amateur a trébuché dans le Deep Learning ❷ fait à partir de zéro Note: Chapitre 4
Mémo d'auto-apprentissage «Deep Learning from scratch» (n ° 18) One! Miaou! Grad-CAM!
Un amateur a trébuché dans le Deep Learning à partir de zéro.
Mémo d'apprentissage profond créé à partir de zéro
L'apprentissage en profondeur
Un amateur a trébuché dans le Deep Learning à partir de zéro Note: Chapitre 2
Mémo d'auto-apprentissage "Deep Learning from scratch" (n ° 15) Tutoriel pour débutants TensorFlow
Tutoriel d'apprentissage en profondeur de la construction d'environnement
"Deep Learning from scratch" Mémo d'auto-apprentissage (n ° 14) Exécutez le programme du chapitre 4 sur Google Colaboratory
Mémo d'auto-apprentissage "Deep Learning from scratch" (partie 8) J'ai dessiné le graphique du chapitre 6 avec matplotlib
Mémo d'auto-apprentissage "Deep Learning from scratch" (n ° 13) Essayez d'utiliser Google Colaboratory
Mémo d'auto-apprentissage «Deep Learning from scratch» (n ° 10-2) Valeur initiale du poids
Apprentissage profond à partir de zéro (propagation vers l'avant)
Apprentissage profond / Apprentissage profond à partir de zéro 2-Essayez de déplacer GRU
Alignement d'image: du SIFT au deep learning
"Deep Learning from scratch" avec Haskell (inachevé)
[Windows 10] Construction de l'environnement "Deep Learning from scratch"
Enregistrement d'apprentissage de la lecture "Deep Learning from scratch"
[Deep Learning from scratch] À propos de l'optimisation des hyper paramètres
Apprentissage profond à partir des bases mathématiques (pendant la fréquentation)
Note d'étude LPIC201
Mémo d'apprentissage Django