[PYTHON] [Rabbit Challenge (E-Qualifikation)] Deep Learning (Tag 2)

Einführung

Dies ist ein Lernrekord, als ich die Rabbit Challenge mit dem Ziel absolvierte, die Qualifikation der Japan Deep Learning Association (JDLA) E zu bestehen, die am 19. und 20. Januar 2021 stattfinden wird.

Rabbit Challenge ist ein Kurs, der die Unterrichtsmaterialien verwendet, die aus dem aufgezeichneten Video des Schulbesuchskurses "Deep Learning-Kurs, der vor Ort zerstört werden kann" bearbeitet wurden. Es gibt keine Unterstützung für Fragen, aber es ist ein billiger Kurs (der niedrigste Preis ab Juni 2020) für die E-Qualifikationsprüfung.

Bitte überprüfen Sie die Details über den unten stehenden Link.

Liste der Themen

Angewandte Mathematik Maschinelles Lernen Deep Learning (Tag 1) Deep Learning (Tag 2) Deep Learning (Tag 3) Deep Learning (Tag 4)

Abschnitt 1: Problem des Verschwindens des Gradienten

Wenn das Fehler-Backpropagation-Verfahren zu den unteren Schichten fortschreitet, wird der Gradient immer sanfter. Daher ändert die Aktualisierung durch das Gradientenabstiegsverfahren kaum die Parameter der unteren Schicht, und das Training konvergiert nicht zum optimalen Wert.

Lösung für das Verschwinden des Gradienten

--ReLU-Funktion $ f(x) = \left\\{ \begin{array} \\\ x & (x > 0) \\\ 0 & (x \leq 0) \\\ \end{array} \right. $ Gute Ergebnisse wurden erzielt, indem dazu beigetragen wurde, das Problem des Verschwindens des Gradienten zu vermeiden und es spärlich zu machen.

Was passiert, wenn ich das Anfangsgewicht auf 0 setze? → Weil alle Werte mit demselben Wert übertragen werden. Parameter werden nicht mehr eingestellt.

Der Durchschnitt und die Varianz der Mini-Charge $\mu_t=\frac{1}{N_t}\sum_{i=1}^{N_t}x_{ni}, \quad \sigma_t^2=\frac{1}{N_t}\sum_{i=1}^{N_t}(x_{ni}-\mu_t)^2$ Wenn der Ausgang normalisiert ist $\hat x_{ni}=\frac{x_{ni}-\mu_t}{\sqrt{\sigma_t^2-\theta}}$ Wird sein. Diese normalisierte Ausgabe wird linear mit dem lernbaren Skalierungsparameter $ \ gamma $ und dem Verschiebungsparameter $ \ beta $ transformiert. $y_{ni}=\gamma x_{ni}+\beta$

Beitrag zum Verschwinden des Gradienten beim Ändern der Aktivierungsfunktion, des anfänglichen Gewichtswerts und des Vorhandenseins / Nichtvorhandenseins einer Chargennormalisierung


import sys, os
sys.path.append(os.pardir)  #Einstellungen zum Importieren von Dateien in das übergeordnete Verzeichnis
import numpy as np
from common import layers
from collections import OrderedDict
from common import functions
from data.mnist import load_mnist
import matplotlib.pyplot as plt
from common import optimizer

class MultiLayerNet:
    '''
    input_size:Anzahl der Knoten in der Eingabeebene
    hidden_size_list:Liste der Knoten versteckter Ebenen
    output_size:Anzahl der Knoten in der Ausgabeschicht
    activation:Aktivierungsfunktion
    weight_init_std:So initialisieren Sie Gewichte
    weight_decay_lambda:Stärke der L2-Regularisierung
    use_dropout:Mit oder ohne Ausfall
    dropout_ratio:Abbruchquote
    use_batchnorm:Mit oder ohne Chargennormalisierung
    '''
    def __init__(self, input_size, hidden_size_list, output_size, activation='relu', weight_init_std='relu', weight_decay_lambda=0,
                 use_dropout = False, dropout_ratio = 0.5, use_batchnorm=False):
        self.input_size = input_size
        self.output_size = output_size
        self.hidden_size_list = hidden_size_list
        self.hidden_layer_num = len(hidden_size_list)
        self.use_dropout = use_dropout
        self.weight_decay_lambda = weight_decay_lambda
        self.use_batchnorm = use_batchnorm
        self.params = {}

        #Gewichtsinitialisierung
        self.__init_weight(weight_init_std)

        #Schichterzeugung
        activation_layer = {'sigmoid': layers.Sigmoid, 'relu': layers.Relu}
        self.layers = OrderedDict()
        for idx in range(1, self.hidden_layer_num+1):
            self.layers['Affine' + str(idx)] = layers.Affine(self.params['W' + str(idx)], self.params['b' + str(idx)])
            if self.use_batchnorm:
                self.params['gamma' + str(idx)] = np.ones(hidden_size_list[idx-1])
                self.params['beta' + str(idx)] = np.zeros(hidden_size_list[idx-1])
                self.layers['BatchNorm' + str(idx)] = layers.BatchNormalization(self.params['gamma' + str(idx)], self.params['beta' + str(idx)])
                
            self.layers['Activation_function' + str(idx)] = activation_layer[activation]()
            
            if self.use_dropout:
                self.layers['Dropout' + str(idx)] = layers.Dropout(dropout_ratio)

        idx = self.hidden_layer_num + 1
        self.layers['Affine' + str(idx)] = layers.Affine(self.params['W' + str(idx)], self.params['b' + str(idx)])

        self.last_layer = layers.SoftmaxWithLoss()

    def __init_weight(self, weight_init_std):
        all_size_list = [self.input_size] + self.hidden_size_list + [self.output_size]
        for idx in range(1, len(all_size_list)):
            scale = weight_init_std
            if str(weight_init_std).lower() in ('relu', 'he'):
                scale = np.sqrt(2.0 / all_size_list[idx - 1])  #Empfohlener Anfangswert bei Verwendung von ReLU
            elif str(weight_init_std).lower() in ('sigmoid', 'xavier'):
                scale = np.sqrt(1.0 / all_size_list[idx - 1])  #Empfohlener Anfangswert bei Verwendung von Sigmoid
            self.params['W' + str(idx)] = scale * np.random.randn(all_size_list[idx-1], all_size_list[idx])
            self.params['b' + str(idx)] = np.zeros(all_size_list[idx])

    def predict(self, x, train_flg=False):
        for key, layer in self.layers.items():
            if "Dropout" in key or "BatchNorm" in key:
                x = layer.forward(x, train_flg)
            else:
                x = layer.forward(x)

        return x

    def loss(self, x, d, train_flg=False):
        y = self.predict(x, train_flg)

        weight_decay = 0
        for idx in range(1, self.hidden_layer_num + 2):
            W = self.params['W' + str(idx)]
            weight_decay += 0.5 * self.weight_decay_lambda * np.sum(W**2)

        return self.last_layer.forward(y, d) + weight_decay

    def accuracy(self, X, D):
        Y = self.predict(X, train_flg=False)
        Y = np.argmax(Y, axis=1)
        if D.ndim != 1 : D = np.argmax(D, axis=1)

        accuracy = np.sum(Y == D) / float(X.shape[0])
        return accuracy

    def gradient(self, x, d):
        # forward
        self.loss(x, d, train_flg=True)

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

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

        #Aufbau
        grads = {}
        for idx in range(1, self.hidden_layer_num+2):
            grads['W' + str(idx)] = self.layers['Affine' + str(idx)].dW + self.weight_decay_lambda * self.params['W' + str(idx)]
            grads['b' + str(idx)] = self.layers['Affine' + str(idx)].db

            if self.use_batchnorm and idx != self.hidden_layer_num+1:
                grads['gamma' + str(idx)] = self.layers['BatchNorm' + str(idx)].dgamma
                grads['beta' + str(idx)] = self.layers['BatchNorm' + str(idx)].dbeta

        return grads

#Batch-Regularisierungsschicht
class BatchNormalization:
    '''
    gamma:Skalenkoeffizient
    beta:Versatz
    momentum:Trägheit
    running_mean:Durchschnittlich während des Tests zu verwenden
    running_var:Verteilung während des Testens verwendet
    '''
    def __init__(self, gamma, beta, momentum=0.9, running_mean=None, running_var=None):
        self.gamma = gamma
        self.beta = beta
        self.momentum = momentum
        self.input_shape = None

        self.running_mean = running_mean
        self.running_var = running_var  
        
        #Zwischendaten, die rückwärts verwendet werden sollen
        self.batch_size = None
        self.xc = None
        self.std = None
        self.dgamma = None
        self.dbeta = None

    def forward(self, x, train_flg=True):
        if self.running_mean is None:
            N, D = x.shape
            self.running_mean = np.zeros(D)
            self.running_var = np.zeros(D)
                        
        if train_flg:
            mu = x.mean(axis=0) #durchschnittlich
            xc = x - mu #Mitte x
            var = np.mean(xc**2, axis=0) #Verteilt
            std = np.sqrt(var + 10e-7) #Skalierung
            xn = xc / std
            
            self.batch_size = x.shape[0]
            self.xc = xc
            self.xn = xn
            self.std = std
            self.running_mean = self.momentum * self.running_mean + (1-self.momentum) * mu #Gewichteter Durchschnitt der Durchschnittswerte
            self.running_var = self.momentum * self.running_var + (1-self.momentum) * var #Gewichteter Durchschnitt der Varianzwerte
        else:
            xc = x - self.running_mean
            xn = xc / ((np.sqrt(self.running_var + 10e-7)))
            
        out = self.gamma * xn + self.beta 
        
        return out

    def backward(self, dout):
        dbeta = dout.sum(axis=0)
        dgamma = np.sum(self.xn * dout, axis=0)
        dxn = self.gamma * dout
        dxc = dxn / self.std
        dstd = -np.sum((dxn * self.xc) / (self.std * self.std), axis=0)
        dvar = 0.5 * dstd / self.std
        dxc += (2.0 / self.batch_size) * self.xc * dvar
        dmu = np.sum(dxc, axis=0)
        dx = dxc - dmu / self.batch_size
        
        self.dgamma = dgamma
        self.dbeta = dbeta

        return dx    
    
#Daten lesen
# (x_train, d_train), (x_test, d_test) = load_mnist(normalize=True, one_hot_label=True)
(x_train, d_train), (x_test, d_test) = load_mnist(normalize=True)

print('Datenlesung abgeschlossen')

activations = ['sigmoid', 'relu']
weight_init_stds = [0.01, 'Xavier', 'He']
use_batchnorms = [False, True]

iters_num = 2000
train_size = x_train.shape[0]
batch_size = 100
learning_rate = 0.1

plot_interval = 100
plot_idx = 0 

for k in range(len(activations)):
    for l in range(len(weight_init_stds)):
            for m in range(len(use_batchnorms)):
                network = MultiLayerNet(input_size=784, hidden_size_list=[40, 20], output_size=10, activation=activations[k], weight_init_std=weight_init_stds[l], use_batchnorm=use_batchnorms[m])

                train_loss_list = []
                accuracies_train = []
                accuracies_test = []
                lists = []
                plot_idx = plot_idx + 1

                for i in range(iters_num):            
                    batch_mask = np.random.choice(train_size, batch_size)
                    x_batch = x_train[batch_mask]
                    d_batch = d_train[batch_mask]

                    #Steigung
                    grad = network.gradient(x_batch, d_batch)

                    for key in ('W1', 'W2', 'W3', 'b1', 'b2', 'b3'):
                        network.params[key] -= learning_rate * grad[key]

                    loss = network.loss(x_batch, d_batch)
                    train_loss_list.append(loss)

                    if (i + 1) % plot_interval == 0:
                        accr_test = network.accuracy(x_test, d_test)
                        accuracies_test.append(accr_test)        
                        accr_train = network.accuracy(x_batch, d_batch)
                        accuracies_train.append(accr_train)

                        print('Generation: ' + str(i+1) + '.Richtige Antwortrate(Ausbildung) = ' + str(accr_train))
                        print('                : ' + str(i+1) + '.Richtige Antwortrate(Prüfung) = ' + str(accr_test))


                lists = range(0, iters_num, plot_interval)

                plt.rcParams['figure.figsize'] = (12.0, 10.0)
                plt.subplot(4,3,plot_idx)
                plt.plot(lists, accuracies_train, label='training set')
                plt.plot(lists, accuracies_test,  label='test set')
                plt.legend(loc='lower right')
                plt.title(activations[k] + ', '  + str(weight_init_stds[l]) + ',Chargennormalisierung'  + str(use_batchnorms[m]) + ' ('  + str(np.round(accuracies_test[-1],2)) + ')')
                plt.xlabel('count')
                plt.ylabel('accuracy')
                plt.ylim(0, 1.0)
        
#Grafik anzeigen
plt.tight_layout()
# plt.suptitle('Vorhersagegenauigkeit, wenn die Anfangswerte der Aktivierungsfunktion und des Gewichts geändert werden', fontsize = 16)
plt.show()

image.png

Abschnitt 2: Methode zur Optimierung der Lernrate

Wenn der Wert der Lernrate groß ist, wird der optimale Wert nicht für immer erreicht und divergiert. Wenn der Wert der Lernrate klein ist, wird er nicht divergieren, aber wenn er zu klein ist, wird es einige Zeit dauern, bis er konvergiert, oder es wird schwierig sein, zum globalen lokalen optimalen Wert zu konvergieren.

--Schwung $ V_t = \mu V_{t-1}-\epsilon\nabla E $ $ w^{(t+1)} = w^{(t)}+V_t $ Nach Subtraktion des Produkts des durch den Parameter und die Lernrate differenzierten Fehlers wird das Produkt aus dem aktuellen Gewicht abzüglich des vorherigen Gewichts und der Trägheit addiert.

[Vorteile der Dynamik]

Impulsgradient


#Steigung
grad = network.gradient(x_batch, d_batch)
if i == 0:
    v = {}
for key in ('W1', 'W2', 'W3', 'b1', 'b2', 'b3'):
    if i == 0:
        v[key] = np.zeros_like(network.params[key])
    v[key] = momentum * v[key] - learning_rate * grad[key]
    network.params[key] += v[key]

    loss = network.loss(x_batch, d_batch)
    train_loss_list.append(loss)

image.png

[Vorteile von AdaGrad] ――Für Hänge mit leichten Hängen nähern Sie sich dem optimalen Wert.

AdaGrad-Gradient


#Steigung
grad = network.gradient(x_batch, d_batch)
if i == 0:
    h = {}
for key in ('W1', 'W2', 'W3', 'b1', 'b2', 'b3'):
    if i == 0:
        h[key] = np.full_like(network.params[key], 1e-4)
    else:
        h[key] += np.square(grad[key])
    network.params[key] -= learning_rate * grad[key] / (np.sqrt(h[key]))

    loss = network.loss(x_batch, d_batch)
    train_loss_list.append(loss)    

image.png

[Vorteile von RMS Drop]

RMS Drop Gradient


#Steigung
grad = network.gradient(x_batch, d_batch)
if i == 0:
    h = {}
for key in ('W1', 'W2', 'W3', 'b1', 'b2', 'b3'):
    if i == 0:
        h[key] = np.zeros_like(network.params[key])
    h[key] *= decay_rate
    h[key] += (1 - decay_rate) * np.square(grad[key])
    network.params[key] -= learning_rate * grad[key] / (np.sqrt(h[key]) + 1e-7)

    loss = network.loss(x_batch, d_batch)
    train_loss_list.appen

image.png

[Vorteile von Adam]

Adams Gefälle


#Steigung
grad = network.gradient(x_batch, d_batch)
if i == 0:
    m = {}
    v = {}
learning_rate_t  = learning_rate * np.sqrt(1.0 - beta2 ** (i + 1)) / (1.0 - beta1 ** (i + 1))    
for key in ('W1', 'W2', 'W3', 'b1', 'b2', 'b3'):
    if i == 0:
        m[key] = np.zeros_like(network.params[key])
        v[key] = np.zeros_like(network.params[key])

    m[key] += (1 - beta1) * (grad[key] - m[key])
    v[key] += (1 - beta2) * (grad[key] ** 2 - v[key])            
    network.params[key] -= learning_rate_t * m[key] / (np.sqrt(v[key]) + 1e-7)                

    loss = network.loss(x_batch, d_batch)
    train_loss_list.append(loss)

image.png

Abschnitt 3: Überlernen

Die Lernkurve weicht zwischen dem Testfehler und dem Trainingsfehler ab, und das Training ist auf eine bestimmte Trainingsprobe spezialisiert. Es gibt die folgenden Methoden, um Überlernen zu verhindern.


Keine Regularisierung (Reproduktion von Überlernen)
(optimizer.SGD(learning_rate=0.01)) image.png


L2-Regularisierung
(learning_rate=0.01) image.png


L1-Regularisierung
(learning_rate=0.1) image.png


Aussteiger
(optimizer.SGD(learning_rate=0.01), weight_decay_lambda = 0.01) image.png (optimizer.Momentum(learning_rate=0.01, momentum=0.9), weight_decay_lambda = 0.01) image.png (optimizer.AdaGrad(learning_rate=0.01), weight_decay_lambda = 0.01) image.png (optimizer.Adam(learning_rate=0.01), weight_decay_lambda = 0.01) image.png


Dropout + L1-Regularisierung
(dropout_ratio = 0.1, weight_decay_lambda=0.005) image.png

Abschnitt 4: Konzept des Faltungsnetzwerks

Faltungsarithmetikkonzept

--Vorspannen image.png

--Schreiten image.png

Wenn die Eingangsgröße W × H ist, ist die Filtergröße Fw × Fh, die Polsterung ist p, der Schritt ist s und die Ausgangsgröße der Faltungsschicht ist OW × OH, OW und OH werden durch die folgenden Gleichungen berechnet. $ OW=\frac{W+2p-Fw}{s}+1, \quad OH=\frac{H+2p-Fh}{s}+1 $

Nachteile einer vollständig verbundenen Schicht: Bei einem Bild handelt es sich um 3D-Daten von vertikal, horizontal und kanalförmig, die jedoch als 1D-Daten verarbeitet werden. Das heißt, die Beziehung zwischen jedem RGB-Kanal spiegelt sich nicht im Lernen wider.

Abschnitt 5: Neueste CNN (obwohl sie nicht als die neueste ab 2020 bezeichnet werden kann ...)

AlexNet

スクリーンショット 2020-07-18 19.37.25.png

Es heißt Alex Net nach dem Namen des Hauptautors der Zeitung, Alex Krizhevsky. Es besteht aus drei vollständig verbundenen Schichten, einschließlich einer fünfschichtigen Faltschicht und einer Poolschicht. Im Vergleich zu LeNet, einem CNN, das erstmals 1998 von Yann LeCun et al. Entwickelt wurde, weist es eine erheblich tiefere Struktur auf. Um ein Überlernen zu vermeiden, verwenden wir Aussetzer für die Ausgabe der vollständig verbundenen Schicht der Größe 4096.

Chainers AlexNet enthält den folgenden Code.

alex.py


import chainer
import chainer.functions as F
import chainer.links as L


class Alex(chainer.Chain):

    """Single-GPU AlexNet without partition toward the channel axis."""

    insize = 227

    def __init__(self):
        super(Alex, self).__init__()
        with self.init_scope():
            self.conv1 = L.Convolution2D(None, 96, 11, stride=4)
            self.conv2 = L.Convolution2D(None, 256, 5, pad=2)
            self.conv3 = L.Convolution2D(None, 384, 3, pad=1)
            self.conv4 = L.Convolution2D(None, 384, 3, pad=1)
            self.conv5 = L.Convolution2D(None, 256, 3, pad=1)
            self.fc6 = L.Linear(None, 4096)
            self.fc7 = L.Linear(None, 4096)
            self.fc8 = L.Linear(None, 1000)

    def __call__(self, x, t):
        h = F.max_pooling_2d(F.local_response_normalization(
            F.relu(self.conv1(x))), 3, stride=2)
        h = F.max_pooling_2d(F.local_response_normalization(
            F.relu(self.conv2(h))), 3, stride=2)
        h = F.relu(self.conv3(h))
        h = F.relu(self.conv4(h))
        h = F.max_pooling_2d(F.relu(self.conv5(h)), 3, stride=2)
        h = F.dropout(F.relu(self.fc6(h)))
        h = F.dropout(F.relu(self.fc7(h)))
        h = self.fc8(h)

        loss = F.softmax_cross_entropy(h, t)
        chainer.report({'loss': loss, 'accuracy': F.accuracy(h, t)}, self)
        return loss

Recommended Posts

[Rabbit Challenge (E-Qualifikation)] Deep Learning (Tag 2)
[Rabbit Challenge (E-Qualifikation)] Deep Learning (Tag 3)
[Rabbit Challenge (E-Qualifikation)] Deep Learning (Tag 4)
[Rabbit Challenge (E-Qualifikation)] Angewandte Mathematik
Maschinelles Lernen Kaninchen Herausforderung
<Kurs> Tiefes Lernen: Day2 CNN
<Kurs> Tiefes Lernen: Tag 1 NN
Themen> Deep Learning: Tag 3 RNN
[Deep Learning Association E-Qualifikation] Was tun, um zu erhalten?
Studiere gründlich Deep Learning [DW Tag 0]
Tiefes Lernen
<Kurs> Deep Learning Day4 Stärkung des Lernens / Tensorflusses
Deep Learning Memorandum
Starten Sie Deep Learning
Python-Lerntag 4
Python Deep Learning
Deep Learning × Python
Erstes tiefes Lernen ~ Kampf ~
Python: Deep Learning-Praxis
Deep Learning / Aktivierungsfunktionen
Deep Learning von Grund auf neu
Lernrekord 4 (8. Tag)
Lernrekord 9 (13. Tag)
Lernrekord 3 (7. Tag)
Deep Learning 1 Übung des Deep Learning
Deep Learning / Cross Entropy
Lernrekord 5 (9. Tag)
Lernrekord 6 (10. Tag)
Erstes tiefes Lernen ~ Vorbereitung ~
Programmieren des Lernprotokolls 2. Tag
Erstes tiefes Lernen ~ Lösung ~
Lernrekord 8 (12. Tag)
[AI] Deep Metric Learning
Lernrekord 1 (4. Tag)
Lernrekord 7 (11. Tag)
Ich habe versucht, tief zu lernen
Python: Deep Learning Tuning
Lernrekord 2 (6. Tag)
Deep Learning Großtechnologie
Lernrekord 16 (20. Tag)
Lernrekord 22 (26. Tag)
Deep Learning / Softmax-Funktion
[Deep Learning] Bildklassifizierung mit Faltungsnetz [DW Tag 4]
Selbstgesteuertes Lied durch tiefes Lernen (gestapelte LSTM-Ausgabe) [DW Tag 6]