[PYTHON] Bayesianische Optimierungsimplementierung von Hyperparametern des neuronalen Netzwerks (Chainer + GPyOpt)

Lassen Sie uns die Hyperparameter des neuronalen Netzwerks automatisch optimieren

Hyperparameter des neuronalen Netzwerks

Wie entscheidest du dich? Die Berechnung neuronaler Netze dauert lange, daher verlassen Sie sich häufig auf Ihre Intuition und Erfahrung. Wenn es jedoch innerhalb einer bestimmten Zeit abgeschlossen ist (wenn die Berechnung in etwa 30 Minuten bis höchstens 1 Stunde abgeschlossen werden kann), gibt es eine Methode, die als Bayes'sche Optimierung bezeichnet wird. Die Bayes'sche Optimierung ist auch für Blackboxen wirksam, die Sie optimieren möchten. Die Berechnung dauert jedoch eine gewisse Zeit.

Er schrieb Artikel über GPyOpt für die Bayes'sche Optimierung in Python. Dieses Mal haben wir diese Methode verwendet, um die Hyperparameter des neuronalen Netzwerks so zu optimieren, dass die korrekte Antwortrate von MNIST hoch ist. Ich habe es tatsächlich in Python codiert, also versuchen Sie es bitte.

Ergebnis sofort

Nun, zunächst werde ich Ihnen das Ergebnis zeigen.

Die diesmal zu erledigende Aufgabe besteht darin, die Identifikationsrate von MNIST (Handwritten Character Recognition) zu verbessern.

MNIST ist in Trainingsdaten und Testdaten unterteilt, und die Trainingsdaten werden zum Trainieren des neuronalen Netzwerks verwendet. Danach werden die Testdaten identifiziert, aber diese Fehlerrate wird reduziert.

Die zu optimierenden Hyperparameter sind wie folgt.

[Ergänzung 2017/2/8] Ich habe den Code, der die Anzahl der Schritte korrigierte, auf die Anzahl der Epochen umgestellt.

Hyperparameter Reichweite
Anzahl der Epochen 1~20
Abbruchquote 0~0.9
Anzahl der Kanäle für verborgene Ebenen (wie oft sollte die verborgene Ebene eine Einheit der Eingabeebene sein) 0.51~5
Chargengröße 50,100,200
Ob zu folden True,False
Anzahl der Schichten 1,2,3
Ob es restlich gemacht werden soll True,False
Klappfiltergröße 5,7,9,11,13

Zunächst wurde als Vergleichsexperiment ein orthodoxes neuronales Netzwerk verwendet, und die Fehlerrate betrug 2,58%.

Nach der Bayes'schen Optimierung (20 zufällige Stichproben + 20 Bayes'sche Optimierungsiterationen) betrug die Fehlerrate 1,18%. Die Hyperparameter nach der Optimierung sind:

Hyperparameter Reichweite Vergleichsexperiment Optimierungsergebnis
Anzahl der Epochen 1~20 10 20(Höchstgrenze)
Abbruchquote 0~0.9 0 0
Anzahl der Kanäle für verborgene Ebenen (wie oft sollte die verborgene Ebene eine Einheit der Eingabeebene sein) 0.51~5 1 5(Höchstgrenze)
Chargengröße 50,100,200 100 200(Höchstgrenze)
Ob zu folden True,False False True
Anzahl der Schichten 1,2,3 2 3(Höchstgrenze)
Ob es restlich gemacht werden soll True,False False True
Klappfiltergröße 5,7,9,11,13 - 9

Basierend auf dem Ergebnis

Die Anzahl der Epochen und die Anzahl der Kanäle mit versteckten Schichten haben die Obergrenze erreicht.

Nun, diesmal gab es ein Problem mit den Spezifikationen des Computers, also habe ich die Anzahl der Epochen reduziert (immer noch nur 20 Iterationen, insbesondere die letztere versuchte nur diejenigen mit der Obergrenze für Epochenanzahl und Stapelgröße, also war es viel Zeit Es dauerte).

Wenn Sie die Obergrenze wie die Anzahl der Epochen erhöhen, ist die Genauigkeit höher.

Nun, ich bin froh, dass es immer noch optimiert zu sein schien.

Implementierung des neuronalen Netzes

Implementiert mit Chainer.

Ich habe eine test_mnist_nn-Funktion erstellt. Diese Funktion verwendet die Hyperparameter des neuronalen Netzwerks als Eingabe und gibt die Fehlerrate aus. Eine Bayes'sche Optimierung wird durchgeführt, um diese Fehlerrate zu minimieren.

mnist_nn.py


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Ein neuronales Netzwerk für MNIST, das Parameter optimiert.
Die zu optimierenden Parameter sind
epoch_num:Anzahl der Epochen(1~20)
dropout_r:Abbruchquote(0~0.9)
h_cnl:Anzahl der Kanäle für verborgene Ebenen (wie oft sollte die verborgene Ebene eine Einheit der Eingabeebene sein)(0.51~5)
batch_size:Chargengröße(50,100,200)
conv:Ob zu folden(True or False)
layers:Anzahl der Schichten(1~3)
residual:Ob es restlich gemacht werden soll(True or False)
conv_ksize:Klappfiltergröße(5,7,9,11,13)
"""

import numpy as np
import chainer
from chainer import optimizers,datasets
import chainer.functions as F
import chainer.links as L

class mnist_nn(chainer.Chain):
    '''
Neuronales Netz für mnistische Klassifizierungsaufgaben
    '''
    def __init__(self, dropout_r=0.5, h_cnl=0.51, conv=True, layers=3, residual=True, conv_ksize=9):
        '''
Parameterinitialisierung und
Erstellen einer Ebene (Hinzufügen eines Links)
halten
        '''
        super(mnist_nn, self).__init__()
        self.dropout_r = dropout_r
        self.h_cnl = h_cnl
        self.conv = conv
        self.layers = layers
        self.residual = residual
        self.conv_ksize = conv_ksize

        if conv:
            p_size = int((conv_ksize-1)/2)
            self.add_link('layer{}'.format(0), L.Convolution2D(1,round(h_cnl),(conv_ksize,conv_ksize),pad=(p_size,p_size)))
            for i in range(1,layers):
                self.add_link('layer{}'.format(i), L.Convolution2D(round(h_cnl),round(h_cnl),(conv_ksize,conv_ksize),pad=(p_size,p_size)))
            self.add_link('fin_layer', L.Convolution2D(round(h_cnl),10,(28,28)))
        else:
            self.add_link('layer{}'.format(0), L.Linear(784,round(784*h_cnl)))
            for i in range(1,layers):
                self.add_link('layer{}'.format(i), L.Linear(round(784*h_cnl),round(784*h_cnl)))
            self.add_link('fin_layer', L.Linear(round(784*h_cnl),10))

    def __call__(self, x, train=False):
        '''
Der Hauptteil des neuronalen Netzwerks
        '''
        if self.conv:
            batch_size = x.shape[0]
            x = x.reshape(batch_size, 1, 28, 28)
            h = chainer.Variable(x)
            h = F.dropout(F.relu(self['layer{}'.format(0)](h)),train=train,ratio=self.dropout_r)
            for i in range(1,self.layers):
                if self.residual:
                    h = F.dropout(F.relu(self['layer{}'.format(i)](h)),train=train,ratio=self.dropout_r) + h
                else:
                    h = F.dropout(F.relu(self['layer{}'.format(i)](h)),train=train,ratio=self.dropout_r)
            h = self['fin_layer'](h)[:,:,0,0]
        else:
            h = chainer.Variable(x)
            h = F.dropout(F.relu(self['layer{}'.format(0)](h)),train=train,ratio=self.dropout_r)
            for i in range(1,self.layers):
                if self.residual:
                    h = F.dropout(F.relu(self['layer{}'.format(i)](h)),train=train,ratio=self.dropout_r) + h
                else:
                    h = F.dropout(F.relu(self['layer{}'.format(i)](h)),train=train,ratio=self.dropout_r)
            h = self['fin_layer'](h)
        return h
    def loss(self,x,t):
        '''
Die Fehlerfunktion ist Kreuzentropie
        '''
        x = self.__call__(x, True)
        t = chainer.Variable(t)
        loss = F.softmax_cross_entropy(x,t)
        return loss


def test_mnist_nn(epoch_num=10, dropout_r=0.5, h_cnl=0.51, batch_size=100, conv=True, layers=3, residual=True, conv_ksize=9):
    '''
Eine Funktion, die bei der Eingabe von Parametern die falsche Antwortrate von MNIST angibt
    '''
    #Der Startwert ist vorerst festgelegt (dies bestimmt die Ausgabe als genau für den Parameter.
    np.random.seed(1234)

    #Vorbereitung für die Modelloptimierung
    model = mnist_nn(dropout_r, h_cnl, conv, layers, residual, conv_ksize)
    optimizer = optimizers.Adam()
    optimizer.setup(model)

    #Vorbereitung der Daten
    train, test = datasets.get_mnist()
    trainn, testn = len(train), len(test)

    #Linspace für die Protokollausgabe
    logging_num = np.linspace(0,epoch_num*int(trainn/batch_size),11).astype(int)

    iter = 0
    for epoch in range(epoch_num):
        #Stapelerstellung
        batch_idx = np.array(range(trainn))
        np.random.shuffle(batch_idx)
        for batch_num in np.hsplit(batch_idx,int(trainn/batch_size)):
            batch = train[batch_num]
            x,t = batch[0],batch[1]

            #Lernen
            model.zerograds()
            loss = model.loss(x,t)
            #Nur für den Fall
            if np.isnan(loss.data):
                print("pass")
                continue
            loss.backward()
            optimizer.update()

            #Protokollausgabe
            if iter in logging_num:
                print(str(np.where(logging_num==iter)[0][0]*10)+'%','\tcross entropy =',loss.data)
            iter+=1


    #Leistungsbeurteilung(Tun Sie dies in einem Mini-Batch, um Speicherplatz zu sparen)
    batch_idx = np.array(range(testn))
    false_p = []
    for batch_num in np.hsplit(batch_idx,100):
        batch = test[batch_num]
        x,t = batch[0].reshape(len(batch_num), 1, 28, 28),batch[1]
        res = model(x).data.argmax(axis=1)
        false_p.append(np.mean(t!=res))
    false_p = np.mean(false_p)

    print("False {:.2f}%".format(false_p*100))
    return false_p

if __name__ == '__main__':
    test_mnist_nn(epoch_num=10, dropout_r=0, h_cnl=1, batch_size=100, conv=False, layers=2, residual=False, conv_ksize=9)

Implementierung der Bayes'schen Optimierung

Ich habe GPyOpt verwendet.

Ich habe zuerst 20 abgetastet und dann versucht, durch 100 Iterationen zu optimieren (tatsächlich haben sich 100 Iterationen nicht gedreht).

bayesian_opt.py


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Fri Jan 27 20:09:10 2017

@author: marshi
"""

import GPyOpt
import numpy as np
import mnist_nn
import os

def f(x):
    '''
    mnist_nn.test_mnist_nn Wrapper-Funktion
    _x[0](1~20)->epoch_num=int(_x[0])
    _x[1](0~0.9)->dropout_r=np.float32(_x[1])
    _x[2](0.51~5)->h_cnl=np.float32(_x[2])
    _x[3](50,100,200)->batch_size=int(_x[3])
    _x[4](0,1)->conv=bool(_x[4])
    _x[5](1,2,3)->layers=int(_x[5])
    _x[6](0,1)->residual=bool(_x[6])
    _x[7](5,7,9,11,13)->conv_ksize=int(_x[7])
    '''
    ret = []
    for _x in x:
        print(_x)
        _ret = mnist_nn.test_mnist_nn(epoch_num = int(_x[0]),
                                        dropout_r = np.float32(_x[1]),
                                        h_cnl = np.float32(_x[2]),
                                        batch_size = int(_x[3]),
                                        conv = bool(_x[4]),
                                        layers = int(_x[5]),
                                        residual = bool(_x[6]),
                                        conv_ksize = int(_x[7]))
        ret.append(_ret)
    ret = np.array(ret)
    return ret

#Geben Sie den Bereich jeder Variablen an
bounds = [{'name': 'epochs', 'type': 'continuous', 'domain': (1,20)},
          {'name': 'dropout_r', 'type': 'continuous', 'domain': (0.0,0.9)},
          {'name': 'h_cnl', 'type': 'continuous', 'domain': (0.51,5)},
          {'name': 'batch_size', 'type': 'discrete', 'domain': (50,100,200)},
          {'name': 'conv', 'type': 'discrete', 'domain': (0,1)},
          {'name': 'layers', 'type': 'discrete', 'domain': (1,2,3)},
          {'name': 'residual', 'type': 'discrete', 'domain': (0,1)},
          {'name': 'conv_ksize', 'type': 'discrete', 'domain': (5,7,9,11,13)}]

#Bayesianisch optimierte Objekterstellung
#Zuvor gespeichertes X.,Wenn es Y gibt, mach es von der Mitte aus
#Wenn nicht, probieren Sie zuerst zufällig einige Proben aus
filename = "XY.npz"
if os.path.exists(filename):
    XY = np.load(filename)
    X,Y = XY['x'],XY['y']
    myBopt = GPyOpt.methods.BayesianOptimization(f=f, domain=bounds, X=X, Y=Y)
else:
    myBopt = GPyOpt.methods.BayesianOptimization(f=f, domain=bounds)

#Bayes'sche Optimierung 100 Schritte und Anzeige der schrittweisen Ergebnisse
for i in range(1000):
    print(len(myBopt.X),"Samples")
    myBopt.run_optimization(max_iter=1)
    print(myBopt.fx_opt)
    print(myBopt.x_opt)
    #Sequentielles Speichern
    np.savez(filename, x=myBopt.X, y=myBopt.Y)

Recommended Posts

Bayesianische Optimierungsimplementierung von Hyperparametern des neuronalen Netzwerks (Chainer + GPyOpt)
Implementierung von "verschwommenen" neuronalen Netzen mit Chainer
Einfache Implementierung eines neuronalen Netzwerks mit Chainer
Implementierung eines zweischichtigen neuronalen Netzwerks 2
Rank Learning über ein neuronales Netzwerk (RankNet-Implementierung von Chainer)
Implementierung eines 3-Schicht-Neuronalen Netzwerks (kein Lernen)
Übersicht über DNC (Differentiable Neural Computers) + Implementierung durch Chainer
Implementierung eines Faltungs-Neuronalen Netzwerks mit nur Numpy
Neuronales Netz beginnend mit Chainer
Implementierung eines neuronalen Netzwerks in Python
Passen Sie die Hyperparameter mit der Bayes'schen Optimierung an
Implementierung eines neuronalen Netzwerks (nur NumPy)
PRML Kapitel 5 Python-Implementierung für neuronale Netze
GPyOpt, ein Paket zur Bayes'schen Optimierung in Python
Einfache Theorie und Implementierung des neuronalen Netzes
Berühren Sie das Objekt des neuronalen Netzes
Implementierung eines Dialogsystems mit Chainer [seq2seq]
Einfache Implementierung eines neuronalen Netzwerks mithilfe der Chainer-Datenaufbereitung
Einfache Implementierung eines neuronalen Netzwerks mithilfe der Beschreibung des Chainer-Modells
[Chainer] Dokumentklassifizierung nach Faltungsnetzwerk
Python vs Ruby "Deep Learning von Grund auf neu" Kapitel 3 Implementierung eines dreischichtigen neuronalen Netzwerks
Einfache Implementierung eines neuronalen Netzwerks mit Chainer ~ Optimierungsalgorithmus einstellen ~
Visualisieren Sie die innere Schicht des neuronalen Netzwerks
Überprüfung der Chargennormalisierung mit einem mehrschichtigen neuronalen Netz
Erkennung handgeschriebener Zahlen durch ein mehrschichtiges neuronales Netzwerk
Ein Hinweis zur Bibliotheksimplementierung, in der Hyperparameter mithilfe der Bayes'schen Optimierung in Python untersucht werden