[PYTHON] [Lernnotiz] Deep Learning von Grund auf neu gemacht [~ Kapitel 4]

Lernnotiz Deep Learning von Grund auf neu gemacht

https://www.amazon.co.jp/dp/4873117585/

Funktionsnotiz, die verwendet zu werden scheint

Sigmoidfunktion: Sigmoid

Wichtige Eigenschaften: Rückgabe zwischen 0 und 1, glatt, eintönig (obwohl im Buch nicht erwähnt)

Sigmaid-Funktion


h(x) = \frac{1}{1+\exp(-x)} 
def sigmoid(x):
    return 1/(1+np.exp(-x))

sigmoid.png

Softmax-Funktion

Schließlich wird der Maximalwert unabhängig davon gesucht, ob er angewendet wird oder nicht. Daher ist es üblich, die Softmax-Funktion der Ausgabeebene wegzulassen.

python


y_k = \frac{\exp(a_k)}{\sum_{i=1}^{n}\exp(a_i)} = \frac{\exp(a_k + C')}{\sum_{i=1}^{n}\exp(a_i + C')} 
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

Verlustfunktion

Gründe für die Einstellung der Verlustfunktion Wenn die Erkennungsgenauigkeit indiziert ist, wird das Differential des Parameters an den meisten Stellen 0 (stecken geblieben).

Summe der Fehlerquadrate: mittlerer quadratischer Fehler

E = \frac{1}{2}\sum_{k=1} (y_k - t_k)^2

python


def mean_squared_error(y,t):
    return 0.5 * np.sum((y-t)**2)

Kreuzentropiefehler: Kreuzentropiefehler

Punkt: One-Hot-Ausdruck: Nur das richtige Antwortetikett ist 1, die anderen sind 0 (Etikett ist t)

E=\sum_{k=1} - t_k \log y_k 

python


def cross_entropy_error(y, t) :
    delta = le-7
    return -np.sum(t*np.log(y+delta))

Mini-Batch-kompatible Version: Kreuzentropiefehler

Mini-Batch (kleiner Block): Wählen Sie einen Teil aus den Daten aus und verwenden Sie den Teil der Daten als "ungefähr" des Ganzen Punkt: In One-Hot ist die falsche Bezeichnung 0 (= Fehler ist 0), sodass Sie sie ignorieren können. Teilen Sie durch N, um unabhängig von der Anzahl der Trainingsdaten einen einheitlichen Index zu erhalten

E=-\frac{1}{N}\sum_{n}\sum_{k=1} t_{nk} \log y_{nk} 

python


def cross_entropy_error(y, t) :
    if y.ndim == 1:
        t = t.reshape(1, t.size)
        y = y.reshape(1, y.size)
        
    batch_size = y.shape[0]
    return -np.sum(t*np.log(y[np.arange(bathch_size), t])) / bathc_size

Differential

Numerische Differenzierung

Punkt: Auf ungefähr 1e-4 einstellen, um keinen Rundungsfehler zu verursachen

python


def numerical_diff(f, x) :
    h = 1e-4
    return (f(x+h)-f(x-h))/(2*h)

Teilweise Differenzierung

python


# x1=4 Uhr

def function_tmp1(x0):
    return x0*x0 + 4.0*2.0

numerical_diff(function_tmp1, 3.0)

Steigung

Gradient: Ein Vektor, der die teilweise Differenzierung aller Variablen zusammenfasst

python


def numerical_gradient(f, x):
    h = 1e-4 # 0.0001
    grad = np.zeros_like(x) #Generieren Sie ein Array mit der gleichen Form wie x und füllen Sie es mit Werten

    #Der Punkt ist, dass die Variablen nacheinander nacheinander unterschieden werden.
    for idx in range(x.size):
        tmp_val = x[idx]
        x[idx] = float(tmp_val) + h
        fxh1 = f(x) # f(x+h)
        
        x[idx] = tmp_val - h 
        fxh2 = f(x) # f(x-h)
        grad[idx] = (fxh1 - fxh2) / (2*h)
        
        x[idx] = tmp_val #Stellen Sie den Wert wieder her
        
    return grad

Gradientenmethode

Verlaufsmethode: Wiederholen Sie die Bewegung in Verlaufsrichtung und verringern Sie den Wert der Funktion schrittweise. Punkt: Die Gradientenmethode erreicht den Minimalwert, nicht den Minimalwert. Das Bild ist für Dr. Andrew Ng von Coursera Machine Learning Week 5, Vorlesung 9, S. 31, leicht zu verstehen

x_0=x_0-\eta\frac{\partial f}{\partial x_0} \\
x_1=x_1-\eta\frac{\partial f}{\partial x_1} \\
\\
\eta :Lernrate (wie viel Sie in einem Lernen lernen, nicht zu groß oder zu klein)

python


def gradient_descent(f, init_x, lr=0.01, step_num=100):
    x = init_x
    
    for i in range(step_num):
        grad = numerical_gradient(f, x)
        x -= lr * grad
        
    return x

def function_2(x):
    return x[0]**2 + x[1]**2

init_x = np.array([-3.0, 4.0])
gradient_descent(function_2, init_x=init_x, lr=0.1, step_num=100)

Von Menschen festgelegte Parameter wie die oben genannte Lernrate werden als Hyperparameter bezeichnet.

Gradient in Bezug auf das neuronale Netzwerk

W = \biggl(\begin{matrix}
w_{11} & w_{21} & w_{31} \\
w_{12} & w_{22} & w_{32} 
\end{matrix}\biggr)\\


\frac{\partial L}{\partial W} = \Biggl(\begin{matrix}
\frac{\partial L}{\partial w_{11}} & \frac{\partial L}{\partial w_{21}} & \frac{\partial L}{\partial w_{31}}\\
\frac{\partial L}{\partial w_{12}} & \frac{\partial L}{\partial w_{22}} & \frac{\partial L}{\partial w_{32}} 
\end{matrix}\Biggr)\\

\frac{\partial L}{\partial w_{11}} : w_{11}Gibt an, um wie viel sich die Verlustfunktion L wann ändert

python


# coding: utf-8
import sys, os
sys.path.append(os.pardir)  #Einstellungen zum Importieren von Dateien in das übergeordnete Verzeichnis
import numpy as np
from common.functions import softmax, cross_entropy_error
from common.gradient import numerical_gradient


class simpleNet:
    def __init__(self):
        self.W = np.random.randn(2,3)

    def predict(self, x):
        return np.dot(x, self.W)

    def loss(self, x, t):
        z = self.predict(x)
        y = softmax(z)
        loss = cross_entropy_error(y, t)

        return loss

python


#Versuchen Sie es mit
#Parameter
x = np.array([0.6, 0.9])
#Etikette
t = np.array([0, 0, 1])

net = simpleNet()

f = lambda w: net.loss(x, t)
#Kurz gesagt, wir führen die Gradientenmethode aus, um diejenige zu finden, deren Verlustfunktion der Mindestwert ist.
dW = numerical_gradient(f, net.W)

print(dW)

[[ 0.10181684 0.35488728 -0.45670412] [ 0.15272526 0.53233092 -0.68505618]] Das obige Ergebnis zeigt, dass die Erhöhung von w_11 um h um 0,10181684 zunimmt. W_23 ist der größte Beitrag

python


#Lambda-Stil
myfunc = lambda x: x ** 2 

myfunc(5)  # 25
myfunc(6)  # 36

#Dies ist das gleiche wie unten
def myfunc(x):
    return x ** 2

Implementierung eines Lernalgorithmus

Lernübersicht

Neuronales Netzwerktraining: Anpassen von Gewichten und Vorurteilen zur Anpassung an Trainingsdaten

Verfahren

Schritt 1: Mini-Charge </ b> Wählen Sie zufällig einige Daten aus den Trainingsdaten aus. (Mini-Charge) Der Zweck besteht darin, den Wert der Verlustfunktion dieser Mini-Charge zu verringern

Schritt 2: Berechnen Sie den Gradienten </ b> Ermitteln Sie die Steigung jedes Gewichtsparameters, um die Verlustfunktion der Mini-Charge zu verringern. Der Gradient gibt die Richtung an, in der der Wert der Verlustfunktion am stärksten reduziert wird

Schritt 3: Parameter aktualisieren </ b> Aktualisieren Sie den Gewichtsparameter in Verlaufsrichtung um einen kleinen Betrag.

Schritt 4: Wiederholen Sie </ b> Wiederholen Sie die Schritte 1-3

der Begriff

Probabilistischer Gradientenabstieg (SGD Stochastic Gradient Descent): Probabilistisch: "Probabilistisch zufällig ausgewählt" Gradientenabstiegsmethode *: "Finden Sie den Mindestwert"

  • Es gibt auch eine Gradientenerhöhungsmethode, und es ist im Wesentlichen das gleiche Problem, wenn das Vorzeichen umgekehrt wird, so dass es nicht im Wesentlichen erforderlich ist.

Epoche: Epoche 1 Epoche entspricht der Häufigkeit, mit der alle Trainingsdaten beim Lernen verbraucht werden Beispiel: Trainingsdaten mit 10.000 Daten, wobei die probabilistische Gradientenabstiegsmethode 100 Mal für 100 Mini-Batch wiederholt wird

Implementierung und Beschreibung

python


# coding: utf-8
import sys, os
sys.path.append(os.pardir)  #Einstellungen zum Importieren von Dateien in das übergeordnete Verzeichnis
from common.functions import *
from common.gradient import numerical_gradient


class TwoLayerNet:

    #Initialisieren
    def __init__(self, input_size, hidden_size, output_size, weight_init_std=0.01):
        #Gewichtsinitialisierung
        self.params = {}
        self.params['W1'] = weight_init_std * np.random.randn(input_size, hidden_size)
        self.params['b1'] = np.zeros(hidden_size)
        self.params['W2'] = weight_init_std * np.random.randn(hidden_size, output_size)
        self.params['b2'] = np.zeros(output_size)

    #Führen Sie eine Erkennung durch (Inferenz). Argument x sind Bilddaten
    def predict(self, x):
        W1, W2 = self.params['W1'], self.params['W2']
        b1, b2 = self.params['b1'], self.params['b2']
    
        a1 = np.dot(x, W1) + b1
        z1 = sigmoid(a1)
        a2 = np.dot(z1, W2) + b2
        y = softmax(a2)
        
        return y

    #Finden Sie die Verlustfunktion
    # x:Eingabedaten, t:Lehrerdaten
    def loss(self, x, t):
        y = self.predict(x)
        
        return cross_entropy_error(y, t)
    
    #Finden Sie die Erkennungsgenauigkeit
    def accuracy(self, x, t):
        y = self.predict(x)
        y = np.argmax(y, axis=1)
        t = np.argmax(t, axis=1)
        
        accuracy = np.sum(y == t) / float(x.shape[0])
        return accuracy
        
    #Finden Sie den Gradienten für den Gewichtsparameter
    # x:Eingabedaten, t:Lehrerdaten
    def numerical_gradient(self, x, t):
        loss_W = lambda W: self.loss(x, t)
        
        grads = {}
        grads['W1'] = numerical_gradient(loss_W, self.params['W1'])
        grads['b1'] = numerical_gradient(loss_W, self.params['b1'])
        grads['W2'] = numerical_gradient(loss_W, self.params['W2'])
        grads['b2'] = numerical_gradient(loss_W, self.params['b2'])
        
        return grads

Illustration schwer zu verstehen Führen Sie diese bildähnliche Berechnung sofort mit der Matrixberechnung durch Das Bild ist in Courseras Dr. Andrew Ng, Woche 5 des maschinellen Lernens, Vorlesung 9, S. 13, leichter zu verstehen. memo.png

Mini-Batch-Lernen, Auswertung mit Testdaten

Weggelassen, da die Genauigkeit nur durch Wiederholen der Gradientenmethode verbessert wird Die Auswertung mit Testdaten wird ebenfalls weggelassen, da sie nur die Genauigkeit der Testdaten veranschaulicht, um zu beurteilen, ob es sich um ein Übertraining handelt.

Recommended Posts