[PYTHON] [Mémo d'apprentissage] Le Deep Learning fait de zéro [Chapitre 7]

Apprentissage profond à partir de zéro Chapitre 7

Le thème du chapitre 7 est le réseau de neurones convolutifs: ** CNN **

Structure générale

CNN est le même que le réseau de neurones que nous avons vu jusqu'à présent, et il peut être créé en combinant des couches comme un bloc lego. Le suivant est nouveau ・ "Couche de convolution" ・ "Couche de mise en commun"

Kobito.JxbIF2.png

Kobito.SXd9XQ.png

Fonctionnalités générales de CNN ・ Flux de "Convolution --ReLU- (Regroupement)" ・ La couche de regroupement peut être omise ・ La combinaison "Affine --ReLU" est utilisée dans le calque proche de la sortie. ・ La dernière couche de sortie est une combinaison de "Affine --Softmax"

Couche pliante

Les termes suivants sont apparus · En mettant ·foulée

De plus, des données tridimensionnelles sont apparues

Problèmes avec les couches entièrement connectées

Le problème avec les jointures complètes est que ** la structure des données est "ignorée" **

Par exemple, dans le cas d'une image, il s'agit généralement d'une forme tridimensionnelle dans les directions verticale, horizontale et de canal. Cette forme contient des informations spatiales importantes Par exemple -Les pixels proches spatiaux peuvent avoir des valeurs similaires ・ Il existe une relation étroite entre chaque canal de RBG ・ Les pixels éloignés ne sont pas si liés Il y a un motif essentiel à saisir dans la forme tridimensionnelle.

La couche entièrement connectée ignore la forme ci-dessus et les traite tous comme des neurones équivalents (neurones de même dimension). D'autre part, la couche convolutive conserve sa forme

Dans CNN, les données d'entrée / sortie de la couche de convolution sont ** feature map ** (feature map). Données d'entrée ** Carte des caractéristiques d'entrée ** (carte des caractéristiques) Données de sortie ** Carte des caractéristiques de sortie ** (carte des caractéristiques) Parfois je dis.

Opération de pliage

Kobito.uMcQj4.png

"Opération de pliage" Équivalent au "traitement de filtre" dans le traitement d'image Dans certaines publications, le terme «filtre» est parfois appelé «noyau».

Les paramètres utilisés pour ce filtre correspondent aux "poids" dans le réseau neuronal entièrement couplé.

Exemple de calcul

Kobito.Wo1MG2.png

Opération biaisée

Kobito.gNgZ98.png

Rembourrage

Mettre: Remplir des données fixes (par exemple 0) autour des données d'entrée

La figure ci-dessous est remplie avec 1 pixel 0 de largeur Kobito.joYXx3.png

foulée

Stride: La distance entre les positions où le filtre est appliqué.

Kobito.WoeNb7.png

Calcul de la taille de sortie

Taille d'entrée (H, W) Taille de filtre (FH, FW) Taille de sortie (OH, OW) Rembourrage P Foulée S La taille de sortie est la suivante

OH = \frac{H + 2P - FH}{S} + 1\\
OW = \frac{W + 2P - FW}{S} + 1

Pensez en blocs

Compte tenu de l'opération de convolution tridimensionnelle dans un bloc rectangulaire facile à comprendre, c'est comme suit.

Kobito.ITLGJH.png

Ce qui précède est une carte des caractéristiques avec une sortie. En d'autres termes, il s'agit d'une carte de caractéristiques avec un canal.

Ce qui suit est un diagramme en cas de méthodes de canaux multiples.

Kobito.l5nAG0.png

L'ajout du terme de biais est le suivant. image.png

Le traitement par lots

Lors du traitement par lots de N éléments de données, la forme des données est la même

image.png

Couche de regroupement

Pooling: calcul pour réduire la vue verticale et horizontale du ciel

Dans la figure ci-dessous, la taille de l'espace est réduite en effectuant un traitement qui regroupe la zone 2x2 en un seul élément.

Kobito.HL2U8Q.png

Dans cet exemple, il s'agit du processus lors de la mise en pool 2x2 Max sur la diapositive 2.

Pooling max: calcul pour prendre la valeur maximale dans la zone De plus, en général, la taille de la fenêtre de regroupement et la diapositive sont définies sur la même valeur.

En plus de la mise en commun maximale, il existe une mise en commun moyenne qui prend la valeur moyenne de la zone.

Caractéristiques de la couche de pooling

・ Il n'y a pas de paramètres à apprendre

La mise en commun est un processus qui ne prend que la valeur maximale (ou la valeur moyenne) de la cible, il n'y a donc pas de paramètres à apprendre.

・ Le nombre de canaux ne change pas

Le calcul de regroupement ne modifie pas le nombre de canaux de données d'entrée et de données de sortie. (OH et OW changent, mais FN ne le fait pas)

・ Robuste contre les changements de position infimes

La mise en commun renvoie des résultats similaires pour de petits écarts dans les données d'entrée. Par conséquent, il est robuste contre de légers écarts dans les données d'entrée.

Kobito.rOBXno.png

Implémentation de la couche Convolution / Pooling

Tableau à 4 dimensions

#Générer des données de manière aléatoire
x = np.random.rand(10,1,28,28)
x.shape
# (10, 1, 28, 28)

x[0].shape
# (1, 28, 28)
x[1].shape
# (1, 28, 28)

x[0, 0].shape # x[0][0]Mais d'accord
# (28, 28)

Déploiement par im2col

Si vous implémentez la convolution comme indiqué dans la figure précédente, vous devez combiner plusieurs instructions for. En outre, NumPy est lent lors de l'utilisation de l'instruction for.

Par conséquent, implémentez en utilisant une fonction appelée im2col au lieu d'une instruction for. im2col est une fonction qui étend les données d'entrée en fonction du filtre.

image.png

Dans cette figure, nous avons souligné la facilité de compréhension et donné un exemple dans lequel les zones de filtre ne se chevauchent pas.

・ Avantages Im2col Inconvénients Avantage: Il est possible d'utiliser efficacement la bibliothèque d'algèbre linéaire car elle peut être réduite au calcul matriciel. Inconvénients: consomme plus de mémoire que d'habitude

#----------------------------------------------------
# Parameters
#   input_data : (Le nombre de données,Canal,la taille,Largeur)Données d'entrée constituées d'un tableau à 4 dimensions de
#   filter_h :Hauteur du filtre
#   filter_w :Largeur du filtre
#   stride :foulée
#   pad :Rembourrage
# Returns
#   col :Un tableau bidimensionnel
#----------------------------------------------------
def im2col(input_data, filter_h, filter_w, stride=1, pad=0):

    N, C, H, W = input_data.shape
    out_h = (H + 2*pad - filter_h)//stride + 1
    out_w = (W + 2*pad - filter_w)//stride + 1

    img = np.pad(input_data, [(0,0), (0,0), (pad, pad), (pad, pad)], 'constant')
    col = np.zeros((N, C, filter_h, filter_w, out_h, out_w))

    for y in range(filter_h):
        y_max = y + stride*out_h
        for x in range(filter_w):
            x_max = x + stride*out_w
            col[:, :, y, x, :, :] = img[:, :, y:y_max:stride, x:x_max:stride]

    col = col.transpose(0, 4, 5, 1, 2, 3).reshape(N*out_h*out_w, -1)
    return col

Afficher avec im2col

import sys, os
sys.path.append(os.pardir)
from common.util import im2col

x1 = np.random.rand(1, 3, 7, 7)
col1 = im2col(x1, 5, 5, stride=1, pad=0)
print(col1.shape)

x2 = np.random.rand(10, 3, 7, 7)
col2 = im2col(x2, 5, 5, stride=1, pad=0)
print(col2.shape)

résultat (9, 75) (90, 75)

x1 correspond à des données 7x7 avec une taille de lot 1 et 3 canaux x2 correspond à des données 7x7 avec une taille de lot de 10 et 3 canaux

Dans les deux cas, le nombre d'éléments dans la deuxième dimension est de 75, qui est la somme du nombre d'aspects du filtre. (Canal 3, taille 5 x 5)

Implémentation de la couche de convolution

Après avoir développé les données avec im2col, tout ce que vous avez à faire est de développer le filtre (poids) de la couche de convolution dans une colonne et de calculer le produit interne des deux matrices. C'est presque la même chose que ce que nous avons fait dans la couche Affine de la couche entièrement connectée. image.png

class Convolution:
    def __init__(self, W, b, stride=1, pad=0):
        self.W = W
        self.b = b
        self.stride = stride
        self.pad = pad
        
        #Données intermédiaires (utilisées en arrière)
        self.x = None   
        self.col = None
        self.col_W = None
        
        #Gradient du paramètre poids / biais
        self.dW = None
        self.db = None

    def forward(self, x):
        FN, C, FH, FW = self.W.shape
        N, C, H, W = x.shape
        out_h = 1 + int((H + 2*self.pad - FH) / self.stride)
        out_w = 1 + int((W + 2*self.pad - FW) / self.stride)

        col = im2col(x, FH, FW, self.stride, self.pad)
        #à la fonction de remodelage-Si 1 est spécifié, le nombre d'éléments sera résumé afin que le Tsuji du tableau multidimensionnel corresponde.
        col_W = self.W.reshape(FN, -1).T

        out = np.dot(col, col_W) + self.b
        #Enfin, façonnez la taille de sortie à la forme appropriée
        #reshape reconfigure la taille de sortie spécifiée
        #transposer change l'ordre des axes
        out = out.reshape(N, out_h, out_w, -1).transpose(0, 3, 1, 2)

        self.x = x
        self.col = col
        self.col_W = col_W

        return out

    def backward(self, dout):
        FN, C, FH, FW = self.W.shape
        dout = dout.transpose(0,2,3,1).reshape(-1, FN)

        #Le calcul de la matrice inverse elle-même se fait dans les deux lignes suivantes, ce qui est le même que dans Affine, la seule différence est l'ajustement des dimensions de la matrice.
        self.db = np.sum(dout, axis=0)
        self.dW = np.dot(self.col.T, dout)

        self.dW = self.dW.transpose(1, 0).reshape(FN, C, FH, FW)

        dcol = np.dot(dout, self.col_W.T)
        #Traitement inverse de im2col
        dx = col2im(dcol, self.x.shape, FH, FW, self.stride, self.pad)

        return dx

Implémentation de la couche Pooling

Comme pour la couche Convolution, utilisez im2col pour développer et implémenter les données d'entrée Cependant, dans le cas du pooling, la différence est qu'ils sont indépendants dans le sens du canal.

class Pooling:
    def __init__(self, pool_h, pool_w, stride=1, pad=0):
        self.pool_h = pool_h
        self.pool_w = pool_w
        self.stride = stride
        self.pad = pad
        
        self.x = None
        self.arg_max = None

    def forward(self, x):
        N, C, H, W = x.shape
        out_h = int(1 + (H - self.pool_h) / self.stride)
        out_w = int(1 + (W - self.pool_w) / self.stride)

        col = im2col(x, self.pool_h, self.pool_w, self.stride, self.pad)
        col = col.reshape(-1, self.pool_h*self.pool_w)

        arg_max = np.argmax(col, axis=1)
        out = np.max(col, axis=1)
        out = out.reshape(N, out_h, out_w, C).transpose(0, 3, 1, 2)

        self.x = x
        self.arg_max = arg_max

        return out

    def backward(self, dout):
        dout = dout.transpose(0, 2, 3, 1)
        
        pool_size = self.pool_h * self.pool_w
        dmax = np.zeros((dout.size, pool_size))
        #flatten réinsère la structure dans un tableau unidimensionnel
        dmax[np.arange(self.arg_max.size), self.arg_max.flatten()] = dout.flatten()
        dmax = dmax.reshape(dout.shape + (pool_size,)) 
        
        dcol = dmax.reshape(dmax.shape[0] * dmax.shape[1] * dmax.shape[2], -1)
        dx = col2im(dcol, self.x.shape, self.pool_h, self.pool_w, self.stride, self.pad)
        
        return dx

Mise en œuvre de CNN

# coding: utf-8
import sys, os
sys.path.append(os.pardir)  #Paramètres d'importation des fichiers dans le répertoire parent
import pickle
import numpy as np
from collections import OrderedDict
from common.layers import *
from common.gradient import numerical_gradient

#ConvNet simple
# conv - relu - pool - affine - relu - affine - softmax
class SimpleConvNet:

    
    #----------------------------------------------------
    # Parameters
    #   input_size :Taille d'entrée (784 pour MNIST)
    #   hidden_size_list :Liste des nombres de neurones de la couche cachée (e.g. [100, 100, 100])
    #   output_size :Taille de sortie (10 pour MNIST)
    #   activation : 'relu' or 'sigmoid'
    #   weight_init_std :Spécifiez l'écart type du poids (e.g. 0.01)
    #                    'relu'Ou'he'Si est spécifié, "Valeur initiale de He" est définie.
    #                    'sigmoid'Ou'xavier'Si est spécifié, "Valeur initiale de Xavier" est défini.
    #----------------------------------------------------
    def __init__(self, input_dim=(1, 28, 28), 
                 conv_param={'filter_num':30, 'filter_size':5, 'pad':0, 'stride':1},
                 hidden_size=100, output_size=10, weight_init_std=0.01):

        #Initialisation des poids, calcul de la taille de sortie de la couche de convolution
        filter_num = conv_param['filter_num']
        filter_size = conv_param['filter_size']
        filter_pad = conv_param['pad']
        filter_stride = conv_param['stride']
        input_size = input_dim[1]
        conv_output_size = (input_size - filter_size + 2*filter_pad) / filter_stride + 1
        pool_output_size = int(filter_num * (conv_output_size/2) * (conv_output_size/2))

        #Initialisation du poids
        self.params = {}
        self.params['W1'] = weight_init_std * \
                            np.random.randn(filter_num, input_dim[0], filter_size, filter_size)
        self.params['b1'] = np.zeros(filter_num)
        self.params['W2'] = weight_init_std * \
                            np.random.randn(pool_output_size, hidden_size)
        self.params['b2'] = np.zeros(hidden_size)
        self.params['W3'] = weight_init_std * \
                            np.random.randn(hidden_size, output_size)
        self.params['b3'] = np.zeros(output_size)

        #Génération de couches
        self.layers = OrderedDict()
        self.layers['Conv1'] = Convolution(self.params['W1'], self.params['b1'],
                                           conv_param['stride'], conv_param['pad'])
        self.layers['Relu1'] = Relu()
        self.layers['Pool1'] = Pooling(pool_h=2, pool_w=2, stride=2)
        self.layers['Affine1'] = Affine(self.params['W2'], self.params['b2'])
        self.layers['Relu2'] = Relu()
        self.layers['Affine2'] = Affine(self.params['W3'], self.params['b3'])

        self.last_layer = SoftmaxWithLoss()

    #Faites une déduction
    def predict(self, x):
        for layer in self.layers.values():
            x = layer.forward(x)

        return x

    #Trouvez la fonction de perte
    def loss(self, x, t):
        """Trouvez la fonction de perte
L'argument x est les données d'entrée, t est l'étiquette de l'enseignant
        """
        y = self.predict(x)
        return self.last_layer.forward(y, t)

    def accuracy(self, x, t, batch_size=100):
        if t.ndim != 1 : t = np.argmax(t, axis=1)
        
        acc = 0.0
        
        for i in range(int(x.shape[0] / batch_size)):
            tx = x[i*batch_size:(i+1)*batch_size]
            tt = t[i*batch_size:(i+1)*batch_size]
            y = self.predict(tx)
            y = np.argmax(y, axis=1)
            acc += np.sum(y == tt) 
        
        return acc / x.shape[0]

    def numerical_gradient(self, x, t):
        """Trouver le dégradé (différenciation numérique)

        Parameters
        ----------
        x :Des données d'entrée
        t :Label enseignant

        Returns
        -------
Variable de dictionnaire avec gradient de chaque couche
            grads['W1']、grads['W2']、...Est le poids de chaque couche
            grads['b1']、grads['b2']、...Est-ce que le biais de chaque couche
        """
        loss_w = lambda w: self.loss(x, t)

        grads = {}
        for idx in (1, 2, 3):
            grads['W' + str(idx)] = numerical_gradient(loss_w, self.params['W' + str(idx)])
            grads['b' + str(idx)] = numerical_gradient(loss_w, self.params['b' + str(idx)])

        return grads

    def gradient(self, x, t):
        """Trouvez le dégradé (méthode de propagation de retour d'erreur)

        Parameters
        ----------
        x :Des données d'entrée
        t :Label enseignant

        Returns
        -------
Variable de dictionnaire avec gradient de chaque couche
            grads['W1']、grads['W2']、...Est le poids de chaque couche
            grads['b1']、grads['b2']、...Est-ce que le biais de chaque couche
        """
        # forward
        self.loss(x, t)

        # backward
        dout = 1
        dout = self.last_layer.backward(dout)

        layers = list(self.layers.values())
        layers.reverse()
        for layer in layers:
            dout = layer.backward(dout)

        #Réglage
        grads = {}
        grads['W1'], grads['b1'] = self.layers['Conv1'].dW, self.layers['Conv1'].db
        grads['W2'], grads['b2'] = self.layers['Affine1'].dW, self.layers['Affine1'].db
        grads['W3'], grads['b3'] = self.layers['Affine2'].dW, self.layers['Affine2'].db

        return grads
        
    def save_params(self, file_name="params.pkl"):
        params = {}
        for key, val in self.params.items():
            params[key] = val
        with open(file_name, 'wb') as f:
            pickle.dump(params, f)

    def load_params(self, file_name="params.pkl"):
        with open(file_name, 'rb') as f:
            params = pickle.load(f)
        for key, val in params.items():
            self.params[key] = val

        for i, key in enumerate(['Conv1', 'Affine1', 'Affine2']):
            self.layers[key].W = self.params['W' + str(i+1)]
            self.layers[key].b = self.params['b' + str(i+1)]

Le fait est qu'il peut être implémenté simplement en augmentant le nombre de couches et en augmentant la valeur de l'hyper paramètre utilisé dans la couche cachée.

Effectuer l'apprentissage De plus, mon Macbook Air utilisait beaucoup le processeur, je n'ai donc pas commenté la réduction des données et l'ai exécutée.

# coding: utf-8
import sys, os
sys.path.append(os.pardir)  #Paramètres d'importation des fichiers dans le répertoire parent
import numpy as np
import matplotlib.pyplot as plt
from dataset.mnist import load_mnist
from simple_convnet import SimpleConvNet
from common.trainer import Trainer

#Lire les données
(x_train, t_train), (x_test, t_test) = load_mnist(flatten=False)

#Réduisez les données si le traitement prend du temps
#x_train, t_train = x_train[:5000], t_train[:5000]
#x_test, t_test = x_test[:1000], t_test[:1000]

max_epochs = 20

network = SimpleConvNet(input_dim=(1,28,28), 
                        conv_param = {'filter_num': 30, 'filter_size': 5, 'pad': 0, 'stride': 1},
                        hidden_size=100, output_size=10, weight_init_std=0.01)
                        
trainer = Trainer(network, x_train, t_train, x_test, t_test,
                  epochs=max_epochs, mini_batch_size=100,
                  optimizer='Adam', optimizer_param={'lr': 0.001},
                  evaluate_sample_num_per_epoch=1000)
trainer.train()

#Enregistrer les paramètres
network.save_params("params.pkl")
print("Saved Network Parameters!")

#Dessiner un graphique
markers = {'train': 'o', 'test': 's'}
x = np.arange(max_epochs)
plt.plot(x, trainer.train_acc_list, marker='o', label='train', markevery=2)
plt.plot(x, trainer.test_acc_list, marker='s', label='test', markevery=2)
plt.xlabel("epochs")
plt.ylabel("accuracy")
plt.ylim(0, 1.0)
plt.legend(loc='lower right')
plt.show()

…… train loss:0.0145554384445 train loss:0.0275851756417 train loss:0.00785021651885 train loss:0.00986611950473 =============== Final Test Accuracy =============== test acc:0.956 Saved Network Parameters!

image.png

Visualisation de CNN

Visualisation des poids dans la première couche

Avant l'apprentissage: Il n'y a pas de régularité dans les tons noir et blanc car le filtre est initialisé aléatoirement. image.png

Après l'apprentissage: régulier image.png

Qu'est-ce qu'un filtre avec une telle régularité «regarde»? ・ ** Bord **: Bordure où la couleur change ・ ** Blob **: zone localement grumeleuse

Extraire les informations de nuit dans une structure hiérarchique

Convolution de la 1ère couche: extrait les informations de bas niveau telles que les bords et les gouttes Empilez plusieurs couches de convolution: extrayez des informations plus complexes et abstraites

La DEMO 1 suivante a été citée http://vision03.csail.mit.edu/cnn_art/index.html#v_single

Dans la démo, c'était comme suit. Cov1: Bord, Blob (Bord + Blob) Cov3: Texture Cov5: Parties d'objets Fc8: Classes d'objets comme les chiens et les chats

Par conséquent, à mesure que la couche s'approfondit, les neurones passent de formes simples à des informations "avancées" **. En d'autres termes, c'est le jour où l'objet qui réagit change pour que vous puissiez comprendre le «sens» des choses.

CNN typique

Ce livre explique ce qui suit ・ CNN, qui a été proposé pour la première fois en 1998, est également le LeNet original ・ AlexNet en 2012, lorsque l'apprentissage profond a attiré l'attention

LeNet

Les points suivants sont différents par rapport à "CNN actuel" ・ Utilisez la fonction sigmoïde pour la fonction d'activation (Actuellement fonction ReLU) ・ La taille des données intermédiaires est réduite par le sous-échantillonnage. (Actuellement Max Pooling) http://dx.doi.org/10.1109/5.726791

AlexNet

AlexNet empile la couche de convolution et la couche de pooling, et renvoie finalement le résultat via la couche entièrement connectée. Les points suivants sont différents de LeNet -Utiliser la fonction ReLU comme fonction d'activation ・ Utilisez une couche qui effectue une normalisation locale appelée LRN (Local Response Normalization) ・ Utiliser Dropout

Maintenant et dans le passé

Il n'y a pas de grande différence entre LeNet et AlexNe dans la configuration du réseau, mais il y a eu des progrès majeurs dans la technologie informatique. En particulier ・ Une grande quantité de données est désormais accessible à tous ・ Les GPU spécialisés dans de grandes quantités de calculs parallèles se sont généralisés, ce qui permet d'effectuer de grandes quantités d'opérations à grande vitesse.

Recommended Posts

[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)
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
Mémo d'apprentissage profond créé à partir de zéro
Deep Learning / Deep Learning à partir de Zero 2 Chapitre 6 Mémo
Mémo d'auto-apprentissage "Deep Learning from scratch" (partie 12) Deep learning
Mémo d'auto-apprentissage "Deep Learning from scratch" (glossaire illisible)
Apprentissage profond à partir de zéro 1 à 3 chapitres
"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
Mémo d'auto-apprentissage «Deep Learning from scratch» (n ° 19) Augmentation des données
Application de Deep Learning 2 à partir de zéro Filtre anti-spam
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 1
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
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.
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
Apprentissage profond à partir de zéro (propagation vers l'avant)
Apprentissage profond / Apprentissage profond à partir de zéro 2-Essayez de déplacer GRU
"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
Écrivez vos impressions sur l'édition du framework Deep Learning 3 créée à partir de zéro
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
Chapitre 3 Réseau de neurones Ne découpez que les bons points de Deeplearning à partir de zéro
Django memo n ° 1 à partir de zéro
"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
Chapitre 2 Implémentation de Perceptron Ne découpez que les bons points de Deeplearning à partir de zéro
GitHub du bon livre "Deep Learning from scratch"
Résumé Python vs Ruby "Deep Learning from scratch"
Python vs Ruby «Deep Learning from scratch» Chapitre 2 Circuit logique par Perceptron