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.
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 |
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.
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)
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