Bei der Aufteilung des Lernprozesses in TensorFlow ist die Variable save / restore erforderlich, die von der Klasse tf.train.Saver in TensorFlow unterstützt wird. Wenn der Maßstab des Modells klein ist, können Sie alle verwendeten Variablen speichern / wiederherstellen. Wenn das Modell jedoch groß ist, möchten Sie nur die Variablen speichern / wiederherstellen, die Sie wirklich benötigen.
In diesem Artikel werden wir die Methode zum Speichern / Wiederherstellen von Variablen am Beispiel der handschriftlichen Nummernklassifizierung MNIST bestätigen. (Die Umgebung ist Python 2.7.11, Tensorflow 0.8.0.)
Abhängig vom Inhalt des Programms gibt es verschiedene mögliche Situationen, was benötigt wird. Am einfachsten ist es, die gesamte verwendete Variable (tf.Variable-Klassenvariable) zu speichern.
chkpt_file = '../MNIST_data/mnist_cnn.ckpt'
# Create the model
def inference(x, y_, keep_prob, phase_train):
(Weggelassen)
Aufbau eines Netzwerkmodells usw.
return loss, accuracy, y_pred
if __name__ == '__main__':
(Weggelassen)
loss, accuracy, y_pred = inference(x, y_,
keep_prob, phase_train)
#
#Speichern Sie den Vorgang, bevor Sie in die Sitzung eintreten(ops)Wird ohne Argumente definiert
#
saver = tf.train.Saver()
with tf.Session() as sess:
sess.run(init)
if restore_call:
# Restore variables from disk.
saver.restore(sess, chkpt_file)
if TASK == 'train':
print('\n Training...')
for i in range(5001):
(Lernprozess)
# Save the variables to disk.Zum Schluss auf CD schreiben
if TASK == 'train':
save_path = saver.save(sess, chkpt_file)
print("Model saved in file: %s" % save_path)
Wie oben erwähnt, können Sie Operationen (ops) mit "tf.train.Saver ()" ohne Argumente definieren und die gesamte tf.Variable mit ihrer Speichermethode speichern. (Hinweis. Die in tf.placeholder definierten gelten nicht.)
In den meisten einfachen Modellen neuronaler Netze sind jedoch das ** Gewicht w ** und die ** Vorspannung b ** jeder Einheit ausreichend. Die hier empfohlene Methode besteht darin, das trainierbare Flag in die Variablendefinition einzufügen.
Das Folgende ist eine Klassendefinition der Faltungsschicht und ein Klassenbeispiel der vollständig verbundenen Schicht.
class Convolution2D(object):
'''
constructor's args:
input : input image (2D matrix)
input_siz ; input image size
in_ch : number of incoming image channel
out_ch : number of outgoing image channel
patch_siz : filter(patch) size
weights : (if input) (weights, bias)
'''
def __init__(self, input, input_siz, in_ch, out_ch, patch_siz, activation='relu'):
self.input = input
self.rows = input_siz[0]
self.cols = input_siz[1]
self.in_ch = in_ch
self.activation = activation
wshape = [patch_siz[0], patch_siz[1], in_ch, out_ch]
w_cv = tf.Variable(tf.truncated_normal(wshape, stddev=0.1),
trainable=True)
b_cv = tf.Variable(tf.constant(0.1, shape=[out_ch]),
trainable=True)
self.w = w_cv
self.b = b_cv
self.params = [self.w, self.b]
(Weggelassen)
# Full-connected Layer
class FullConnected(object):
def __init__(self, input, n_in, n_out):
self.input = input
w_h = tf.Variable(tf.truncated_normal([n_in,n_out],
mean=0.0, stddev=0.05), trainable=True)
b_h = tf.Variable(tf.zeros([n_out]), trainable=True)
self.w = w_h
self.b = b_h
self.params = [self.w, self.b]
(Weggelassen)
Wenn Sie die Variablen (w_cv, b_cv) und (w_h, b_h) deklarieren, die dem Gewicht und der Abweichung entsprechen, wird "trainable = True" (trainable) hinzugefügt. Mit diesem Aufwand können Sie später nur trainierbare Variablen erfassen.
if __name__ == '__main__':
(Weggelassen)
vars_to_train = tf.trainable_variables()
if os.path.exists(chkpt_file) == False:
restore_call = False
init = tf.initialize_all_variables()
else:
restore_call = True
vars_all = tf.all_variables()
vars_to_init = list(set(vars_all) - set(vars_to_train))
init = tf.initialize_variables(vars_to_init)
saver = tf.train.Saver(vars_to_train)
with tf.Session() as sess:
(Weggelassen)
Der Punkt im obigen Code ist
Wir haben gerade die mit trainable = True
deklarierten Variablen mit ** tf.trainable_variables () ** und die gesamten mit ** tf.all_variables () ** deklarierten Variablen gesammelt. Das Bild des Variablensatzes ist wie folgt.
Im ersten Prozess werden nur die Variablen mit trainierbar gespeichert, und im zweiten und nachfolgenden Prozess werden diese gespeicherten Variablen wiederhergestellt und verwendet. Der Ablauf besteht jedoch darin, dass Variablen, die nicht gespeichert / wiederhergestellt werden, initialisiert werden (auch nach dem zweiten Mal).
Vergleichen Sie hier die Größe der gespeicherten Dateien.
-rw-rw-r--1 52404005 31. Mai 09:54 mnist_cnn.all_vars
-rw-rw-r--1 13100491 22. Mai 09:15 mnist_cnn.trainable
Dies ist nur ein Beispiel, aber die gespeicherte Datei kann bis zu 1/4 klein sein. (Die obige Datei wurde von mnist_cnn.ckpt umbenannt.)
Als nächstes werden wir eine andere Methode vorstellen, eine Methode zum Sammeln von Variablen unter Verwendung des Variablennamensraums und zum Speichern / Wiederherstellen. In TensorFlow denke ich, dass zur Visualisierung von Graph (Modellkonfiguration) die Graphkonstruktion beim Definieren eines Namespace fortgesetzt werden kann, aber dieser Namespace kann zum Sammeln der definierten Variablen verwendet werden.
Das folgende Beispiel ist ein Verfahren zum Sammeln der Variablen, die bei der der Faltungsschicht hinzugefügten Chargennormalisierung verwendet werden.
def batch_norm(x, n_out, phase_train):
with tf.variable_scope('bn'):
(Stapelnormalisierungsverarbeitung, verschiedene)
return normed
#Erstellen Sie das Modellmodellbauteil, Stapel oben_norm()Ruft an
def inference(x, y_, keep_prob, phase_train):
x_image = tf.reshape(x, [-1, 28, 28, 1])
with tf.variable_scope('conv_1'):
conv1 = Convolution2D(x, (28, 28), 1, 32, (5, 5), activation='none')
conv1_bn = batch_norm(conv1.output(), 32, phase_train)
conv1_out = tf.nn.relu(conv1_bn)
pool1 = MaxPooling2D(conv1_out)
pool1_out = pool1.output()
with tf.variable_scope('conv_2'):
conv2 = Convolution2D(pool1_out, (28, 28), 32, 64, (5, 5),
activation='none')
conv2_bn = batch_norm(conv2.output(), 64, phase_train)
conv2_out = tf.nn.relu(conv2_bn)
pool2 = MaxPooling2D(conv2_out)
pool2_out = pool2.output()
pool2_flat = tf.reshape(pool2_out, [-1, 7*7*64])
(Andere Schichten weggelassen)
return loss, accuracy, y_pred
#Hauptverarbeitung
if __name__ == '__main__':
TASK = 'train' # 'train' or 'test'
# Variables
x = tf.placeholder(tf.float32, [None, 784])
y_ = tf.placeholder(tf.float32, [None, 10])
keep_prob = tf.placeholder(tf.float32)
phase_train = tf.placeholder(tf.bool, name='phase_train')
loss, accuracy, y_pred = inference(x, y_,
keep_prob, phase_train)
# Train
lr = 0.01
train_step = tf.train.AdagradOptimizer(lr).minimize(loss)
vars_to_train = tf.trainable_variables() # option-1
vars_for_bn1 = tf.get_collection(tf.GraphKeys.VARIABLES, scope='conv_1/bn')
vars_for_bn2 = tf.get_collection(tf.GraphKeys.VARIABLES, scope='conv_2/bn')
vars_to_train = list(set(vars_to_train).union(set(vars_for_bn1)))
vars_to_train = list(set(vars_to_train).union(set(vars_for_bn2)))
if TASK == 'train':
restore_call = False
init = tf.initialize_all_variables()
elif TASK == 'test':
restore_call = True
vars_all = tf.all_variables()
vars_to_init = list(set(vars_all) - set(vars_to_train))
init = tf.initialize_variables(vars_to_init) # option-1
# init = tf.initialize_all_variables() option-2
else:
print('Check task switch.')
saver = tf.train.Saver(vars_to_train)
with tf.Session() as sess:
(Im Folgenden der Inhalt der TensorFlow-Sitzung)
Hier gibt es die Faltungsschicht 1 (conv_1) und die Faltungsschicht 2 (conv_2), und es wird jeweils eine Chargennormalisierung durchgeführt. Die dort verwendeten Variablen werden von ** tf.get_collection () ** wie folgt gesammelt. ing.
vars_for_bn1 = tf.get_collection(tf.GraphKeys.VARIABLES, scope='conv_1/bn')
vars_for_bn2 = tf.get_collection(tf.GraphKeys.VARIABLES, scope='conv_2/bn')
In diesem Beispiel definiert inference () die Namespaces von ** conv_1 ** und ** conv_2 **, und in diesem Beispiel wird batch_norm () mit dem Namespace von ** bn ** aufgerufen. , Die oben genannten (verschachtelten) Namespaces "conv_1 / bn", "conv_2 / bn".
Danach wird der Variablensatz organisiert und in "zu speichernde Dinge" und "nicht zu speichernde Dinge (nach dem nächsten Mal initialisiert)" unterteilt. (Da der Code schwer zu lesen ist, werde ich eine Abbildung anhängen, um Ihnen das Verständnis zu erleichtern.)
Die erforderlichen Variablen werden gespeichert, indem der farbige Teil in der obigen Abbildung als "vars_to_train" an "tf.train.Saver ()" übergeben wird. Bei der Einführung der Chargennormalisierung "in einer Black Box" trat ein Fehler auf, da die erforderlichen Variablen nicht gespeichert wurden. Mit der oben beschriebenen Methode konnte der Fehler jedoch behoben werden.
Überprüfen Sie abschließend erneut die Dateigröße.
-rw-rw-r--1 52404005 31. Mai 09:54 mnist_cnn.all_vars
-rw-rw-r--1 13105573 31. Mai 10:05 mnist_cnn.ckpt
-rw-rw-r--1 13100491 22. Mai 09:15 mnist_cnn.trainable
Das obere ist der Fall, in dem alle Variablen gespeichert sind, ungefähr 52 MB, das zweite ist der Fall, in dem das obige trainable und der Namespace zusammen verwendet werden, ungefähr 13 MB, und das dritte ist der Fall, in dem nur trainable verwendet wird ( Die Operation enthält Fehler), was ungefähr 13 MB entspricht. Wir glauben, dass das Reduzieren der Dateigröße die Datenträger-E / A-Zeit effektiver reduziert als die Datenträgerverwendung.
(Ich werde den endgültigen Code auf Gist hochladen. Hier ist er.)
Recommended Posts