Ich untersuchte Yuki Kashiwagis Gesichtszüge, um TensorFlow und CNN (Convolutional Neural Network) zu verstehen. Dies ist eine Fortsetzung des Artikels "Ich habe die Gesichtszüge von Yuki Kashiwagi untersucht, um TensorFlow [Teil 1] zu verstehen". Dieses Mal werde ich mich im gesamten Prozess auf den Lernteil von TensorFlow konzentrieren. Es tut mir leid, dass es viele Teile gibt, die ich beim Kommentieren nicht verstehe: bow_tone1: Fahren Sie mit Teil 2 fort, der sich auf den Urteilsteil konzentriert.
Wie ich im ersten Teil erklärt habe, lerne ich mit TensorFlow. Es ist fast das gleiche Modell wie das TensorFlow Expert Tutorial Deep MNIST für Experten. Eine Erklärung finden Sie im Artikel ["[Erklärung für Anfänger] TensorFlow-Tutorial Deep MNIST"] Bitte beziehen Sie sich auf (http://qiita.com/FukuharaYohei/items/0aef74a0411273705512).
Obwohl dies in der Abbildung "Übersicht über den Lernprozess" nicht dargestellt ist, wird die Bildgröße vor der Verarbeitung mit TensorFlow mithilfe von OpenCV in eine einheitliche Größe geändert. Wie bei "[Erklärung für Anfänger] TensorFlow-Tutorial Deep MNIST" sind 27 Pixel im Quadrat zu klein, diesmal also 81 Pixel im Quadrat. ↓ ist ein Referenzbild, aber aus irgendeinem Grund ist die Farbe seltsam, wenn Sie das Bild nach dem Ändern der Größe mit TensorBoard betrachten (es ist normal, wenn Sie es anzeigen ...).
In Python heißt es (den gesamten Code hinter sich lassen):
img = cv2.imread(file_name[0])
img = cv2.resize(img, (FLAGS.image_size, FLAGS.image_size))
Im Faltungsprozess der ersten Schicht wird der Faltungsprozess unter Verwendung von 32 Filtertypen mit einem Quadrat von 5 Pixeln durchgeführt. Dies hat sich gegenüber "[Erklärung für Anfänger] TensorFlow-Tutorial Deep MNIST" nicht geändert. Die Aktivierungsfunktion bleibt ReLU. Eine Erläuterung des Faltungsprozesses finden Sie im Artikel "[Erklärung für Anfänger] Einführung in den Faltungsprozess (erklärt in TensorFlow)". In ↓ wird nur ein Teil des Bildes eingefügt. Es ist durch den Faltungsprozess gekennzeichnet. Auf dem Bild ganz rechts sehen Sie, dass Nase und Mund verschwunden sind und die Eigenschaften der Augen zeigen. Der Filter macht nicht wirklich Sinn.
Beim Pooling-Prozess der 1. Schicht wird das Bild des Faltungsergebnisses der 1. Schicht maximal auf 1/3 gepoolt. Da die anfängliche Bildgröße 81 betrug, habe ich sie im Vergleich zu Deep MNIST von 1/2 auf 1/3 geändert. Weitere Informationen zum Pooling finden Sie im Artikel "[Erklärung für Anfänger] Einführung in das Pooling (erklärt in TensorFlow)". Wenn Sie sich das Bild ansehen, können Sie sehen, dass es durch maximales Pooling aufgeraut wird.
In dem Faltungsprozess der zweiten Schicht wird der Faltungsprozess unter Verwendung von 4 Filtertypen mit einem Quadrat von 8 Pixeln durchgeführt. Ich habe 8 Pixel gewählt, weil ich dachte, es wäre ungefähr so groß wie meine Nase. Außerdem habe ich 4 Typen ausprobiert, um die Funktionen einzugrenzen (obwohl das Ergebnis keinen Sinn ergab). Wenn Sie sich das Bild ansehen, können Sie sehen, dass es an dieser Stelle fehlgeschlagen ist. Weit entfernt von den Merkmalen sind die meisten verschwunden ... Ist das Bild, das Sie aufgenommen haben, schlecht?
Beim Pooling der 2. Schicht wird das Bild des Faltungsergebnisses der 2. Schicht maximal auf 1/3 gepoolt. Wenn Sie sich das Bild ansehen, können Sie sehen, dass wir nach Features an den Rändern suchen. Siehst du deine Frisur an?
Der Rest ist eine eng gekoppelte Schicht. Dies ist unverändert gegenüber Deep MNIST, einschließlich Drop Apt.
Die Ordnerstruktur sieht folgendermaßen aus, und durch Tabulatoren getrennte Textdateien mit den Namen Testdaten test.txt und Trainingsdaten train.txt werden im Ordner "Eingaben" abgelegt. Diese Ordner- / Dateistruktur kann mit Laufzeitparametern geändert werden.
inputs
│ test.txt
│ train.txt
Der Inhalt der Datei ist wie das Bild, die erste Spalte ist die Datei, die zweite Spalte ist 0 oder 1 (0 ist Yuki Kashiwagi). Der Zeichencode ist S-JIS und der Zeilenvorschubcode ist CR-LF.
python fully_connected_feed.py
Bei Ausführung mit dem obigen Befehl werden der Fortschritt und das Ergebnis wie in der folgenden Abbildung gezeigt ausgegeben.
Die folgenden Angaben dienen als Laufzeitparameter. Implementiert mit der Bibliothek argparse, die im Artikel ["Parameter mit openCV-Gesichtserkennung angeben, um die Erkennungsgenauigkeit schnell zu verbessern"] erläutert wird (http://qiita.com/FukuharaYohei/items/116932920c99a5b73b32). tun.
Parameter | Inhalt | Ursprünglicher Wert | Bemerkungen |
---|---|---|---|
learning_rate | Lernrate | 1e-4 | AdamOptimizerのLernrate |
batch_size | Chargengröße | 20 | Wir werden Trainingsdaten für jede dieser Zahlen lernen. Obwohl nur wenige Trainingsdaten vorhanden sind, ist der Anfangswert aufgrund des Ziehens gering |
input_train_data | Trainingsdaten | ./inputs/train.txt | この値を変えればTrainingsdatenのフォルダ・ファイルを指定可能 |
input_test_data | Testdaten | ./inputs/test.txt | この値を変えればTestdatenのフォルダ・ファイルを指定可能 |
log_dir | Protokollspeicherverzeichnis | /tmp/tensorflow/kashiwagi/logs | Verzeichnis zum Speichern der gelernten Parameter und TensorBoard-Protokolle |
image_size | Bildgröße | 81 | resizeするときの初期Bildgröße |
pool_size | Poolgröße | 3 | マックスPoolgröße |
Der gesamte Prozess mit dem Namen Computational Graph in TensorBorad (["[Einführung] TensorFlow Basic Syntax and Concept"](http: // qiita). com / FukuharaYohei / items / 0825c3518d8596c09396 # Computergraph)) wird wie in der folgenden Abbildung gezeigt ausgegeben. Der Ablauf dieses Prozesses wird anhand des offiziellen Tutorials TensorFlow Mechanics 101 erstellt. Die folgende Abbildung zeigt die Erweiterung des Hauptinferenzteils.
Mnist.py von TensorFlow Mechanics 101 Dies ist der Lernmodellteil, der unter Bezugnahme auf (/tutorials/mnist/mnist.py) erstellt wurde.
import tensorflow as tf
#Bild-Tag, das an TensorBoard ausgegeben werden soll
IMAGE_SOURCE = 'source'
IMAGE_FILTER = 'filter'
IMAGE_CONV = 'conv'
IMAGE_POOL = 'pool'
#Anzahl der Identifikationsetiketten(Diesmal Yuki Kashiwagi:0,Andere: 1)
NUM_CLASSES = 2
NUM_OUTPUT_IMAGES = 64
NUM_FILTER1 = 32
NUM_FILTER2 = 4
SIZE_FILTER1 = 5
SIZE_FILTER2 = 8
NUM_FC = 1024
def inference(images, keep_prob, image_size, pool_size):
with tf.name_scope('inference'):
#Gewichtsstandardabweichung 0.Definiert durch eine Normalverteilungs-Zufallszahl von 1
def weight_variable(shape):
return tf.Variable(tf.truncated_normal(shape, stddev=0.1))
#Anfangswert der Vorspannung 0.Definiert durch 1 Konstante
def bias_variable(shape):
return tf.Variable(tf.constant(0.1, shape=shape))
#Faltungsschichtdefinition
def conv2d(x, W):
return tf.nn.conv2d(x, W, [1, 1, 1, 1], 'SAME')
#Definition der Pooling-Ebene
def max_pool(x):
return tf.nn.max_pool(x, ksize=[1, pool_size, pool_size, 1], strides=[1, pool_size, pool_size, 1], padding='SAME')
#Informationen eingeben
with tf.name_scope('input'):
tf.summary.image(IMAGE_SOURCE, images, NUM_OUTPUT_IMAGES, family=IMAGE_SOURCE)
#1. Schicht
with tf.name_scope('1st_layer'):
#1. Faltungsschicht
with tf.name_scope('conv1_layer') as scope:
W_conv1 = weight_variable([SIZE_FILTER1, SIZE_FILTER1, 3, NUM_FILTER1])
b_conv1 = bias_variable([NUM_FILTER1])
h_conv1 = tf.nn.relu(conv2d(images, W_conv1) + b_conv1)
#Tensor[Vertikal,Seite,3,Anzahl der Filter]Von[Anzahl der Filter,Vertikal,Seite,3]Und Bildausgabe
tf.summary.image(IMAGE_FILTER, tf.transpose(W_conv1, perm=[3,0,1,2]), 4, family=IMAGE_FILTER)
#Tensor[-1,Vertikal,Seite,Anzahl der Filter]Von[-1,Anzahl der Filter,Vertikal,Seite]Und bestellen Sie die Konvertierung, führen Sie die ersten beiden Dimensionen zusammen und geben Sie das Bild aus
tf.summary.image(IMAGE_CONV, tf.reshape(tf.transpose(h_conv1, perm=[0,3,1,2]), [-1,image_size,image_size,1]), 4 , family=IMAGE_CONV)
#1. Pooling-Schicht
with tf.name_scope('pool1_layer') as scope:
#Bildgrößenberechnung nach dem Pooling
image_size1 = int(image_size / pool_size)
h_pool1 = max_pool(h_conv1)
#Tensor[-1,Vertikal,Seite,Anzahl der Filter]Von[-1,Anzahl der Filter,Vertikal,Seite]Und bestellen Sie die Konvertierung, führen Sie die ersten beiden Dimensionen zusammen und geben Sie das Bild aus
tf.summary.image(IMAGE_POOL, tf.reshape(tf.transpose(h_pool1,perm=[0,3,1,2]),[-1, image_size1, image_size1, 1]),
NUM_OUTPUT_IMAGES, family=IMAGE_POOL)
#2. Schicht
with tf.name_scope('2nd_layer'):
#2. Faltungsschicht
with tf.name_scope('conv2_layer') as scope:
W_conv2 = weight_variable([SIZE_FILTER2, SIZE_FILTER2, NUM_FILTER1, NUM_FILTER2])
b_conv2 = bias_variable([NUM_FILTER2])
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
#Tensor[Vertikal,Seite,Anzahl der Filter 1,Anzahl der Filter 2]Von[Anzahl der Filter 1*Anzahl der Filter 2,Vertikal,Seite,1]Und geben Sie das Bild an TensorBoard aus
tf.summary.image(IMAGE_FILTER, tf.reshape(tf.transpose(W_conv2,perm=[2,3,0,1]),[-1,SIZE_FILTER2,SIZE_FILTER2,1]), 4, family=IMAGE_FILTER)
#Tensor[-1,Vertikal,Seite,64]Von[-1,64,Vertikal,Seite]Und Auftragsumwandlung,[-1]Wann[64]Und geben Sie das Bild an TensorBoard aus
tf.summary.image(IMAGE_CONV, tf.reshape(tf.transpose(h_conv2,perm=[0,3,1,2]),[-1,image_size1,image_size1,1]), 4, family=IMAGE_CONV)
#2. Pooling-Schicht
with tf.name_scope('pool2_layer') as scope:
#Bildgrößenberechnung nach dem Pooling
image_size2 = int(image_size1 / pool_size)
h_pool2 = max_pool(h_conv2)
#Tensor[-1,Vertikal,Seite,Anzahl der Filter 2]Von[-1,Anzahl der Filter 2,Vertikal,Seite]Und bestellen Sie die Konvertierung, führen Sie die Kopf-2-Dimensionen zusammen und geben Sie das Bild an TensorBoard aus
tf.summary.image(IMAGE_POOL, tf.reshape(tf.transpose(h_pool2,perm=[0,3,1,2]),[-1,image_size2,image_size2,1]),
NUM_OUTPUT_IMAGES, family=IMAGE_POOL)
#Erstellung der vollständig verbundenen Schicht 1
with tf.name_scope('fc1_layer') as scope:
W_fc1 = weight_variable([image_size2 ** 2 * NUM_FILTER2, NUM_FC])
b_fc1 = bias_variable([NUM_FC])
h_pool2_flat = tf.reshape(h_pool2, [-1, image_size2 ** 2 * NUM_FILTER2])
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)
#Erstellung der vollständig verbundenen Schicht 2(Ebene lesen)
with tf.name_scope('fc2_layer') as scope:
W_fc2 = weight_variable([NUM_FC, NUM_CLASSES])
b_fc2 = bias_variable([NUM_CLASSES])
logits = tf.matmul(h_fc1_drop, W_fc2) + b_fc2
return logits
def loss(logits, labels):
with tf.name_scope('loss'):
#Berechnung der gekreuzten Entropie
cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=labels, logits=logits, name='xentropy')
#Wert der Fehlerrate(cross_entropy)Gib es zurück
return tf.reduce_mean(cross_entropy)
#Error(loss)Trainieren Sie ein Lernmodell, das mit Hilfe der Fehler-Backpropagation basierend auf entwickelt wurde
def training(loss, learning_rate):
with tf.name_scope('training'):
#Skalare Fehlerausgabe an TensorBoard
tf.summary.scalar('loss', loss)
#Optimiert mit Adam
train_op = tf.train.AdamOptimizer(learning_rate).minimize(loss)
return train_op
#Berechnen Sie die Anzahl der richtigen Antworten für die vom Lernmodell erzeugten Vorhersageergebnisse
def evaluation(logits, labels, batch_size):
with tf.name_scope('evaluation'):
#Berechnung der Anzahl der richtigen Antworten
correct = tf.reduce_sum(tf.cast(tf.nn.in_top_k(logits, labels, 1), tf.int32))
#Berechnung der korrekten Antwortrate und der skalaren Ausgabe an TensorBoard
accuracy = correct / batch_size
tf.summary.scalar('accuracy', accuracy)
return correct, accuracy
TensorFlow Mechanics 101 [full_connected_feed.py](https://www.github.com/tensorflow/tensorflow/blob/r1.3/tensorflow /examples/tutorials/mnist/fully_connected_feed.py) ist ein Modellaufrufprogramm zum Lernen. Da die Trainingsdaten für eine kleine Anzahl erstellt werden, ändern Sie bitte den Code entsprechend, wenn es viele gibt.
import argparse
import cv2
import os
import time
import numpy as np
import random
import sys
import tensorflow as tf
import model_deep
#Grundlegende Modellparameter
FLAGS = None
#Beantworten Sie alle Daten
def do_eval(sess,
eval_correct,
images_placeholder,
labels_placeholder,
images_data, labels_data,
keep_prob):
true_count = 0 #Anzahl der richtigen Antworten
#Berechnen Sie die Gesamtzahl
steps_per_epoch = len(images_data) // FLAGS.batch_size #Teilung abschneiden
num_examples = steps_per_epoch * FLAGS.batch_size # num_Beispiele subtrahieren schließlich nur die Kürzung
#Bewertung aller Fälle
for step in range(steps_per_epoch):
#Erhalten Sie die Anzahl der richtigen Antworten und fügen Sie hinzu
true_count += sess.run(eval_correct,
feed_dict={images_placeholder: images_data[step * FLAGS.batch_size: step * FLAGS.batch_size + FLAGS.batch_size],
labels_placeholder: labels_data[step * FLAGS.batch_size: step * FLAGS.batch_size + FLAGS.batch_size],
keep_prob: 1.0
})
#Richtige Berechnung und Anzeige der Antwortrate
print(' Num examples: %d Num correct: %d Precision @ 1: %0.04f' % (num_examples, true_count, (float(true_count) / num_examples)))
def run_training():
#Geben Sie den Bereich an, der in das TensorBoard-Diagramm ausgegeben werden soll
with tf.Graph().as_default():
#Platzhalterdefinition
images_placeholder = tf.placeholder(tf.float32, name='images', shape=(FLAGS.batch_size, FLAGS.image_size, FLAGS.image_size, 3))
labels_placeholder = tf.placeholder(tf.int32, name='labels', shape=(FLAGS.batch_size) )
keep_prob = tf.placeholder(tf.float32, name='keep_probability' )
# inference()Ein Modell machen
logits = model_deep.inference(images_placeholder, keep_prob, FLAGS.image_size, FLAGS.pool_size)
# loss()Den Verlust berechnen
loss_value = model_deep.loss(logits, labels_placeholder)
# training()Trainieren und Anpassen der Parameter des Lernmodells
train_op = model_deep.training(loss_value, FLAGS.learning_rate)
#Berechnung der Genauigkeit
eval_correct, accuracy = model_deep.evaluation(logits, labels_placeholder, FLAGS.batch_size)
#Geben Sie den bisherigen Inhalt an TensorBoard aus
summary = tf.summary.merge_all()
#Bereit zum Speichern
saver = tf.train.Saver()
#Sitzung erstellen
with tf.Session() as sess:
#Vorbereitung zum Schreiben an TensorBoard
summary_writer = tf.summary.FileWriter(FLAGS.log_dir, sess.graph)
#Variable Initialisierung
sess.run(tf.global_variables_initializer())
#Bilddatenschleife
for step in range(len(FLAGS.train_image) // FLAGS.batch_size):
#Startzeit sparen
start_time = time.time()
# batch_Durchführung eines Trainings für Größenbilder
train_batch = FLAGS.batch_size * step
#Durchführung des Trainings
feed_dict = {
images_placeholder: FLAGS.train_image[train_batch:train_batch + FLAGS.batch_size],
labels_placeholder: FLAGS.train_label[train_batch:train_batch+FLAGS.batch_size],
keep_prob: 0.5
}
# train_Ich werfe op weg, aber ich bin nicht schlau, wenn ich es nicht spezifiziere
_, loss_val, accuracy_val = sess.run([train_op, loss_value, accuracy] , feed_dict=feed_dict)
# (Pro Epoche)Berechnung der Bearbeitungszeit
duration = time.time() - start_time
#Zusammenfassung alle 5 mal(Instanz der Tensorplatine)Holen Sie sich und fügen Sie zum Schriftsteller hinzu
if step % 5 == 0:
#Ergebnisausgabe alle 10 mal
print('Step %d: loss = %.2f, accuracy = %.3f (%.4f sec)' % (step, loss_val, accuracy_val, duration))
#Führen Sie eine Sitzung aus und erhalten Sie eine Zusammenfassung von TensorBoard
summary_str = sess.run(summary, feed_dict=feed_dict)
#Zusammenfassung zu TensorBoard hinzugefügt
summary_writer.add_summary(summary_str, step)
summary_writer.flush()
#Wird während der letzten Schleife ausgewertet
if (step + 1) == len(FLAGS.train_image)//FLAGS.batch_size:
saver.save(sess, os.path.join(FLAGS.log_dir, 'model.ckpt'), global_step=step)
print('Training Data Eval:')
#Auswertung der Trainingsdaten
do_eval(sess, eval_correct, images_placeholder, labels_placeholder, FLAGS.train_image, FLAGS.train_label, keep_prob)
#Auswertung der Testdaten
print('Test Data Eval:')
do_eval(sess, eval_correct, images_placeholder, labels_placeholder, FLAGS.test_image, FLAGS.test_label, keep_prob)
#TensorBoard schreiben nah
summary_writer.close()
#Lesen Sie die Bildlistendatei und konvertieren Sie einzelne Bilddateien und Beschriftungen in das TensorFlow-Format
def read_images(file_image_list):
#Array zum Einfügen von Daten
image_list = []
label_list = []
#Datei im Lesemodus öffnen
with open(file_image_list) as file:
file_data = file.readlines()
#Zufällige Shuffle-Reihenfolge
random.shuffle(file_data)
for line in file_data:
#Durch Leerzeichen mit Ausnahme von Zeilenumbrüchen getrennt
line = line.rstrip() #Leerzeichen entfernen
file_name = line.split('\t') #Delimita-Saite(Tab)Separat als
#Bilddaten und FLAGGEN lesen.image_Größe nach allen Seiten reduziert
img = cv2.imread(file_name[0])
img = cv2.resize(img, (FLAGS.image_size, FLAGS.image_size))
# 0-In einen Gleitkommawert von 1 konvertieren
image_list.append(img.astype(np.float32)/255.0)
#Am Ende des Label-Arrays hinzufügen
label_list.append(int(file_name[1]))
#In das Numpy-Format konvertieren und zurückgeben
return np.asarray(image_list), np.asarray(label_list)
#Hauptverarbeitung
def main(_):
#Wenn das TensorBoard-Speicherverzeichnis vorhanden ist, löschen Sie es und erstellen Sie es neu.
if tf.gfile.Exists(FLAGS.log_dir):
tf.gfile.DeleteRecursively(FLAGS.log_dir)
tf.gfile.MakeDirs(FLAGS.log_dir)
#Trainings- und Testdaten Lesen von Bilddateien
print('Start reading images')
FLAGS.train_image, FLAGS.train_label = read_images(FLAGS.input_train_data)
FLAGS.test_image, FLAGS.test_label = read_images(FLAGS.input_test_data)
#Fange an zu trainieren
print('Start training')
run_training()
#Machen Sie es auch beim Import verwendbar
parser = argparse.ArgumentParser()
#Definition der Eingabeparameter
parser.add_argument(
'--learning_rate',
type=float,
default=1e-4,
help='Initial learning rate.'
)
parser.add_argument(
'--batch_size',
type=int,
default=20,
help='Batch size. Must divide evenly into the dataset sizes.'
)
parser.add_argument(
'--input_train_data',
type=str,
default='./inputs/train.txt',
help='File list data to put the input train data.'
)
parser.add_argument(
'--input_test_data',
type=str,
default='./inputs/test.txt',
help='File list data to put the input test data.'
)
parser.add_argument(
'--log_dir',
type=str,
default='/tmp/tensorflow/kashiwagi/logs',
help='Directory to put the log data.'
)
parser.add_argument(
'--image_size',
type=int,
default=81,
help='Input image size'
)
parser.add_argument(
'--pool_size',
type=int,
default=3,
help='MAX pooling size'
)
FLAGS, unparsed = parser.parse_known_args()
if __name__ == '__main__':
#Hauptfunktion starten
tf.app.run(main=main, argv=[sys.argv[0]] + unparsed)
Recommended Posts