Tensorflow- Eine beeindruckende Deep-Learning-Bibliothek!

Quellknoten: 1058343

Dieser Artikel wurde als Teil des veröffentlicht Data-Science-Blogathon

Einleitung

Tensorflow (im Folgenden – TF) ist ein relativ junges Framework für Deep Machine Learning, das in Google Brain entwickelt wird. Lange Zeit wurde das Framework in einem geschlossenen Modus namens disbelief entwickelt, aber nach einem globalen Refactoring am 9. November 2015 wurde es als Open Source freigegeben. In einem Jahr mit einem kleinen TF ist es auf Version 1.0 gewachsen, hat die Integration mit Keras erworben, wurde viel schneller und erhielt Unterstützung für mobile Plattformen. Wir betrachten nur die Python-API, obwohl dies nicht die einzige Option ist – es gibt auch Schnittstellen für C++ und mobile Plattformen.

Installation

TF wird standardmäßig über Python-Pip installiert. Es gibt eine Nuance: Es gibt separate Installationsalgorithmen für die Ausführung auf einer CPU und auf Grafikkarten.

Bei der CPU ist alles einfach: Sie müssen ein Paket von pip namens TensorFlow installieren.

Im zweiten Fall benötigen Sie:

  1. Überprüfen Sie die Kompatibilität mit der Grafikkarte. Der Parameter CUDA Compute Capability muss größer als 3.0 sein.

  2. Installieren Sie CUDA Toolkit Version 8

  3. Installieren Sie cuDNN-Version 5.1

  4. Installieren Sie das TensorFlow-GPU-Paket von pip

In der Dokumentation heißt es jedoch, dass frühere Versionen des CUDA Toolkit und cuDNN unterstützt werden, empfiehlt jedoch die Installation der oben aufgeführten Versionen.

Die Entwickler empfehlen, TF in einer separaten Umgebung mit einer virtuellen Umgebung zu installieren, um mögliche Versions- und Abhängigkeitsprobleme zu vermeiden.

Grundlegende TF-Elemente

Mit Hilfe von „Hello, world“ stellen wir sicher, dass alles richtig installiert ist:

import tensorflow as tf # connect TF hello = tf.constant ('Hallo, TensorFlow!') # ein Objekt aus TF erstellen sess = tf.InteractiveSession () #um eine neue Sitzung zu erstellen print (sess.run (hello)) # session "führt" das Objekt aus >>> b'Hallo, TensorFlow! '

Verbinden Sie TF mit der ersten Zeile. Es gibt bereits eine Regel, eine entsprechende Abkürzung für das Framework einzuführen. Der gleiche Code ist in der Dokumentation zu finden und ermöglicht es Ihnen, sicherzustellen, dass alles richtig installiert wurde.

Berechnungsgraph

Die Arbeit mit TF basiert auf der Konstruktion und Ausführung eines Berechnungsgraphen. Ein Berechnungsgraph ist ein Konstrukt, das beschreibt, wie Berechnungen durchgeführt werden. Grundlage von TF ist die Erstellung einer Struktur, die die Reihenfolge der Berechnungen festlegt. Programme sind natürlich in zwei Teile gegliedert – Erstellung eines Berechnungsgraphen und Ausführung von Berechnungen in den erstellten Strukturen.

In TF besteht ein Graph aus Platzhaltern, Variablen und Operationen. Aus diesen Elementen können Sie einen Graphen zusammenstellen, in dem Tensoren berechnet werden. Ein Tensor ist ein Multi-D-Array, das entweder eine einzelne Zahl, ein Vektor von Merkmalen des zu lösenden Problems oder ein Bild oder eine ganze Reihe von Objektbeschreibungen oder ein Array von Bildern sein kann. Anstelle eines Objekts können wir ein Array von Objekten an den Graphen übergeben und ein Array von Antworten wird dafür berechnet. TF arbeitet mit Tensoren ähnlich wie NumPy Arrays handhabt, in deren Funktionen Sie die Achse des Arrays angeben können, relativ zu der die Berechnung durchgeführt wird.

Sessions

Computergrafiken werden in Sitzungen ausgeführt. Das Sitzungsobjekt (tf.Session) verbirgt den Kontext der Graphenausführung – die notwendigen Ressourcen, Hilfsklassen, Adressräume.

Es gibt zwei Arten von Sitzungen – die erste ist regulär, die in tf.Session implementiert ist, und die andere ist interaktiv, die in ( tf.InteractiveSession ) implementiert ist. Der Unterschied zwischen den beiden besteht darin, dass eine interaktive Sitzung besser für die Ausführung in der Konsole geeignet ist und sich sofort als Standardsitzung identifiziert. Der Haupteffekt besteht darin, dass das Sitzungsobjekt nicht als Parameter an die Berechnungsfunktion übergeben werden muss. In den folgenden Beispielen gehe ich davon aus, dass die interaktive Sitzung, die wir im ersten Beispiel deklariert haben, derzeit ausgeführt wird, und wenn ich auf die Sitzung zugreifen muss, verweise ich auf das Objekt sess.

Weiter im Beitrag erscheinen Standard-TF-Bilder mit Diagrammbildern, die von einem integrierten Dienstprogramm namens Tensorboard generiert wurden. Die Bezeichnungen dort lauten wie folgt:

Variable Produktion Hilfsergebnis
Ein Graphknoten enthält normalerweise Daten. Macht etwas mit Variablen. Dazu gehören auch Platzhalter, die Werte in der Grafik ersetzen. Caching und Nebenberechnungen wie Gradienten werden normalerweise als Link zu einem separaten Teil des Diagramms bezeichnet.

variabel | Tensorflow

Betrieb | Tensorflow

Hilfsergebnis

Tensoren, Operationen und Variablen

Erstellen wir zum Beispiel einen mit Nullen gefüllten Tensor.

zeros_tensor = tf.zeros([3, 3])

Im Allgemeinen ähnelt die API in TF in vielerlei Hinsicht NumPy, und tf.zeros() ist bei weitem nicht die einzige Funktion, die ein direktes Analogon in NumPy hat. Um den Wert eines Tensors zu sehen, müssen Sie ihn ausführen. Mehr Details zur Ausführung des Graphen sind etwas niedriger, vorerst kommen wir damit zurecht, dass wir den Wert des Tensors und den Tensor selbst ausgeben.

print(zeros_tensor.eval()) print(zeros_tensor) >>> [[ 0. 0. 0.] [ 0. 0. 0.] [ 0. 0. 0.]] >>> Tensor("zeros_1:0 ", shape=(3, 3), dtype=float32)

Der Unterschied zwischen den Zeilen besteht darin, dass wir in der ersten Zeile den Tensor berechnen und in der zweiten Zeile nur die Darstellung des Objekts ausgeben.

Die wichtigen Dinge, die durch die Tensorbeschreibung angezeigt werden:

  1. Tensoren haben Namen. Unsere hat ihre Nullen: 0

  2. Es gibt ein Konzept einer Tensorform, es ähnelt der Dimension eines Arrays von NumPy.

  3. Tensoren werden typisiert und Typen für sie werden aus der Bibliothek festgelegt.

An Tensoren können verschiedene Operationen durchgeführt werden:

a = tf.truncated_normal([2, 2]) b = tf.fill([2, 2], 0.5) print(sess.run(a + b)) print(sess.run(a - b)) print( sess.run(a * b)) print(sess.run(tf.matmul(a, b))) >>> [[-1.12130964 -1.02217746] [ 0.85684788 0.5425666 ]] >>> [[ 0.35249496 0.96118248] [- 1.55395389 -1.18111515]] >>> [[-0.06559008 -0.11100233] [ 0.51474923 -0.27813852]] >>> [[-0.16202734 -0.16202734] [-0.8864761 -0.8864761 ]]

Im obigen Beispiel verwenden wir die Konstruktion sess.run – dies ist eine Methode zum Ausführen von Graphoperationen in einer Sitzung. Es verwendet die Standardgenerierung einer Normalverteilung, schließt jedoch alles aus, was außerhalb der beiden Standardabweichungen liegt. Ganz typisch für TF – die meisten gängigen Optionen zur Durchführung der Operation sind bereits implementiert und vielleicht lohnt sich vor der Erfindung des Fahrrads ein Blick in die Dokumentation. Der zweite Tensor ist ein mehrdimensionales 2×2-Array, das mit einem Wert von 0.5 gefüllt ist und ähnelt NumPy und seinen Funktionen zum Erstellen mehrdimensionaler Arrays.

Lassen Sie uns nun eine tensorbasierte Variable erstellen:

v = tf.Variable(zeros_tensor)

Eine Variable nimmt an Berechnungen teil, da ein Knoten eines Berechnungsgraphen seinen Zustand beibehält und eine Art Initialisierung benötigt. Wenn wir also im folgenden Beispiel auf die erste Zeile verzichten, löst TF eine Ausnahme aus.

sess.run(v.initializer) v.eval() >>> array([[ 0., 0., 0.], [ 0., 0., 0.], [ 0., 0., 0. ]], dtype=float32)

Operationen an Variablen erstellen einen Rechengraphen, der dann ausgeführt werden kann. Es gibt auch Platzhalter – Objekte, die den Graphen parametrisieren und Stellen zum Ersetzen externer Werte markieren. Wie es in der offiziellen Dokumentation steht, ist ein Platzhalter ein Versprechen, einen Wert später zu ersetzen. Lassen Sie uns einen Platzhalter erstellen und ihm einen Datentyp und eine Größe zuweisen:

x = tf.placeholder(tf.float32, shape=(4, 4))

Ein weiteres Anwendungsbeispiel. Knoten, die als Eingabe für den Addierer dienen, sind hier zwei Platzhalter:

a = tf.placeholder("float") b = tf.placeholder("float") y = tf.multiply(a, b) print(sess.run(y, feed_dict={a:100, b:500}) ) >>> 50000.0

Die einfachsten Berechnungen.

Lassen Sie uns als Beispiel einige Ausdrücke erstellen und auswerten.

ans = tf.placeholder(tf.float32) f = 1 + 2 * ans + tf.pow(ans, 2) sess.run(f, feed_dict={x: 10}) >>> 121.0

Und die Berechnungsgrafik:

Berechnungsgraph | Tensorflow

X und y, die die Operationen in diesem Schema angeben, sind zusätzliche Parameter, anstelle derer die Kanten des Graphen sein könnten, aber wir haben f1 und 2 in den Skalarwerten ersetzt und dies ist nur eine Notation im Graphen für Zahlen . In diesem Beispiel erstellen wir einen Platzhalter und darauf basierend einen Ausdrucksgraphen und führen anschließend Graphberechnungen im Kontext der aktuellen Sitzung durch. Ich habe die Form in den Platzhalterparametern nicht angegeben, was bedeutet, dass Sie Tensoren beliebiger Größe eingeben können. Das einzige, was angegeben werden muss, ist der Tensortyp. Bei der Berechnung von Parametern innerhalb der Sitzung werden diese durch feed_dict geleitet - ein Wörterbuch mit allem, was für Berechnungen erforderlich ist.

Zum Beispiel ein Sigmoid:

x = tf.placeholder(dtype=tf.float32) sigma = 1 / (1 + tf.exp(-x)) sigma.eval(feed_dict={x: np.linspace(-5, 5) })

Und hier ist eine solche Grafik für sie.

Sigmoid-Berechnungsgraph | Tensorflow

Im Schnipsel mit dem Start der Funktionsberechnung gibt es einen Punkt, der dieses Beispiel von den vorherigen unterscheidet. Tatsache ist, dass wir anstelle eines einzelnen Skalarwerts ein ganzes Array an den Platzhalter übergeben. TF verarbeitet alle Werte eines Arrays zusammen in einem einzigen Tensor (denken Sie daran, dass Array == Tensor). Genauso können wir Objekte in ganzen Batches auf den Graphen übertragen und das gesamte Bild an das neuronale Netz liefern.

Im Allgemeinen ähnelt die Arbeit mit Tensoren der Arbeit mit Arrays in NumPy. Es gibt jedoch einige Unterschiede. Wenn wir die Dimension reduzieren möchten, indem wir die Werte in einem Tensor irgendwie entlang einer bestimmten Dimension kombinieren, verwenden wir diese Funktionen, die mit der Reduzierung beginnen.

Vergleichen wir mit der Theano-API – in TF gibt es keine Unterteilung in Vektoren und Matrizen, sondern man muss die Dimensionen der Tensoren im Graphen überwachen und es gibt einen Mechanismus zur Ableitung der Tensorform, mit dem man die Dimensionen schon vor der Laufzeit.

Maschinelles Lernen

Lassen Sie uns zunächst die bereits mehrfach erwähnte klassische lineare Regression analysieren, aber zum Training verwenden wir die Gradientenabstiegsmethode.

Maschinelles Lernen | Tensorflow

SOURCE

Wohin ohne dieses Bild?

Beginnen Sie zunächst mit der linearen Regression und fügen Sie dann polynomiale Merkmale hinzu.

So extrahieren Sie die synthetischen Daten:

x = np.linspace(0, 10, 1000) y = np.sin(x) + np.random.normal(size=len(x))

Sie werden ungefähr so ​​aussehen:

Grafik | Tensorflow

SOURCE

Ich werde die Probe auch in einem 70/30-Verhältnis in Training und Kontrolle aufteilen, aber ich werde diese und einige andere Routinemomente in der vollständigen Quelle belassen, deren Link etwas weiter unten ist.

Lassen Sie uns zuerst eine einfache lineare Regression erstellen.

a_ = tf.placeholder(name="input", shape=[None, 1], dtype = tf.float32) b_ = tf.placeholder(name= "output", shape=[None, 1], dtype = tf. float32) model_op = tf.Variable(tf.random_normal([1]), name='bias') + tf.Variable(tf.random_normal([1]), name='k') * x_

Hier erstelle ich zwei Platzhalter für das Attribut und die Antwort und eine Ansichtsformel.

Eine Nuance – im Platzhalter enthält der Formparameter None. Die Platzhalterdimension bedeutet, dass der Platzhalter zweidimensionale Tensoren verbraucht, aber entlang einer der Achsen ist die Tensorgröße nicht definiert und kann beliebig sein. Dies geschieht, damit der Benutzer Werte in ganzen Batches auf einmal in den Graphen übertragen kann. Solche spezifischen Dimensionen werden als dynamisch bezeichnet, TF berechnet zur Laufzeit die tatsächliche Dimension der zugehörigen Elemente.

Der Platzhalter für das Merkmal wird in der Formel verwendet, aber ich werde den Platzhalter für die Antwort in der Verlustfunktion ersetzen:

Verlust = tf.reduce_mean(tf.pow(y_ - model_output, 2))

TF implementiert ein Dutzend Optimierungsmethoden. Wir verwenden den klassischen Gradientenabstieg und geben die Lernrate in den Parametern an.

gd = tf.train.GradientDescentOptimizer(0.001) train_step = gd.minimize(Verlust)

Initialisierung von Variablen – für weitere Berechnungen notwendig:

sess.run(tf.global_variables_initializer())

Endlich kann alles gelehrt werden. Ich werde 100 Trainingsepochen auf dem Trainingsteil der Stichprobe laufen lassen, nach jedem Training werde ich die Kontrolle auf dem verschobenen Teil veranlassen.

n_epochs = 100 train_errors = [] test_errors = []
für i in tqdm.tqdm(range(n_epochs)): # 100 _, train_err = sess.run([train_step, loss ], feed_dict={x_:X_Train.reshape((len(X_Train), 1)) , y_: Y_Train.reshape ((len(Y_Train), 1))}) train_errors.append(train_err) test_err.append(ses.run(loss, feed_dict={x_:X_Test.reshape((len(X_Test), 1)) , y_: Y_Test .reshape((len(Y_Test), 1))}))

Die erste Sitzung der Implementierung der beiden Operationen train_stepund loss make direct und training, und Auswertung der Fehler auf dem Trainingsset, dh tatsächlich eine Schätzung, wie gut wir die Stichprobe auswendig gelernt haben. Die zweite Ausführung der Sitzung ist die Berechnung der Verluste des Testmusters. Im Parameter feed_dictI übergeben Sie Werte für Platzhalter an das Diagramm und formen Sie es so um, dass die Datenarrays in der Dimension übereinstimmen. Wo im Platzhalter Keine ein Wert war, können Sie eine beliebige Zahl übertragen. Tensoren mit solch unbestimmten Dimensionen werden als dynamisch bezeichnet, und hier verwende ich sie, um Batches mit Beispielen zum Training in den Graphen zu übertragen.

Es stellt sich heraus, dass dies die Dynamik des Lernens ist:

Lernen trainieren und testen

Dieser Graph enthält Hilfsvariablen mit Gradienten und Initialisierungsoperationen, sie sind in einem separaten Block platziert.

Berechnungsgraph mit Gradienten

Und hier sind die Ergebnisse der Berechnung des Modells:

Ergebnisse des Rechenmodells | Tensorflow

Die Werte für die Grafik habe ich so berechnet:

sess.run(model_output, feed_dict={x_:x.reshape((len(x), 1))})

Hier übergebe ich den Wert nur für den Platzhalter x_ an den Graphen - der Rest wird einfach nicht benötigt, um den Ausdruck model_output auszuwerten.

Polynomialregression

Versuchen wir, die Regression mit Polynommerkmalen, Regularisierung und Änderung der Lernrate des Modells zu diversifizieren.

Fügen Sie bei der Generierung des Datasets eine Anzahl von Graden hinzu und normalisieren Sie die Features mit PolynomialFeatures und StandardScaler aus der scikit-learn-Bibliothek. Das erste Objekt erzeugt für uns so viele Polynommerkmale, wie wir wollen, und das zweite normalisiert sie.

Um zur polynomialen Regression zu wechseln, ersetzen Sie nur einige Zeilen im Berechnungsgraphen:

order = 26 x_ = tf.placeholder(name="input", shape=[None, order], dtype=tf.float32) y_ = tf.placeholder(name= "output", shape=[None, 1], dtype =tf.float32) w = tf.Variable(tf.random_normal([order, 1]), name='weights') model_output = tf.matmul(x_, w)

Tatsächlich zählen wir jetzt. Offensichtlich besteht die Gefahr, dass das Modell aus heiterem Himmel überangepasst wird, also fügen wir den Gewichtungen Regularisierungsabzüge hinzu. Fügen Sie der Verlustfunktion (Verlust in den Beispielen) Strafen in Form von Zusatzbedingungen hinzu und erhalten Sie fast ElasticNet von sklearn.

loss = tf.reduce_mean(tf.square(y_ - model_output)) + 0.85* tf.nn.l2_loss(w) + 0.15* tf.reduce_mean(tf.abs(w))

Für die beliebteste L2-Regression gibt es eine separate Funktion l2_loss, aber die Merkmalsauswahl mit L1 muss manuell implementiert werden, aber wir haben einen durchschnittlichen Gesamtabsolutwert der Gewichte.

Als Beispiel füge ich eine weitere bedeutende Änderung hinzu, die sich auf das Lerntempo auswirkt. Oftmals ist dies beim Training schwerer neuronaler Netze einfach eine notwendige Maßnahme, um Trainingsprobleme zu vermeiden und ein akzeptables Ergebnis zu erzielen. Eine sehr einfache Idee besteht darin, den Schrittparameter während des Lernens schrittweise zu verringern, um große Probleme zu vermeiden.

Anstelle eines konstanten Tempos verwenden wir einen exponentiellen Decay, den ich direkt aus der Dokumentation entnommen habe:

learning_rate = tf.train.exponential_decay(starter_learning_rate, global_step, 100000, 0.96, Treppenhaus=True)

Die Formel ist in der Funktion versteckt:

Decay_stepsin unserem Beispiel ist der Wert 100000, Decay_rate- 0.96.

Wir erhalten die folgenden Raten zur Reduzierung von Fehlern in Training und Kontrolle:

Zugtestfehler | Tensorflow

Neben dem exponentiellen Zerfall gibt es weitere Funktionen, mit denen Sie die Lernrate reduzieren können, und natürlich hindert Sie nichts daran, eine andere Funktion zu erstellen, die Ihren Anforderungen entspricht.

Grafiken speichern und laden

Wir haben das Modell bekommen und es wäre schön, es zu behalten. Zwei Dinge, die das spezielle Serializer-Objekt der API tut, sind:

  1. Speichert das aktuelle Diagramm, seinen Zustand und die Variablenwerte in einer Datei;

  2. Liest trotzdem aus einer Datei.

Alles, was Sie tun müssen, ist dieses Objekt zu erstellen:

Schoner = tf.train.Saver()

Der Status der aktuellen Sitzung wird mit der Methode save gespeichert:

saver.save(sess, "checkpoint_dir/model.ckpt")

Es wird irgendwie akzeptiert, dass die gespeicherten Zustände des Modells Prüfpunkte genannt werden, daher der Name der Ordner und Dateierweiterungen. Die Wiederherstellung erfolgt mit der Methode restore:

ckpt = tf.train.get_checkpoint_state(ckpt_dir)
if ckpt und ckpt.model_checkpoint_path: print(ckpt.model_checkpoint_path) saver.restore(session, ckpt.model_checkpoint_path)

Zuerst rufen wir mit einer speziellen Funktion den Status des Checkpoints ab (wenn plötzlich kein gespeichertes Modell im Zielverzeichnis vorhanden ist, gibt die Funktion None zurück). Standardmäßig sucht die Funktion nach einem Dateiprüfpunkt, aber dieses Verhalten kann mit einem Parameter geändert werden. Danach stellt es den Zustand des Graphen wieder her.

Tensorbrett

Ein äußerst nützliches System als Teil von TF ist das Web-Dashboard, mit dem Sie Statistiken aus Dumps und Logs sammeln und beobachten können, was während der Berechnungen tatsächlich passiert. Es ist äußerst praktisch, dass das Dashboard auf einem Webserver läuft und Sie beispielsweise durch Ausführen von Tensorboard auf einem Remote-Computer in der Cloud sehen können, was in Ihrem Browserfenster passiert.

Tensorboard kann:

Die andere Seite der Medaille ist, dass Statistiken, damit sie in das Dashboard gelangen, mit einer speziellen API in Protokollen (im Protobuf-Format) gespeichert werden müssen. Die API ist nicht sehr komplex, gruppiert in tf.summary.

Auch bei der Verwendung von Tensorboard ist es wichtig, den Parameter name der Variablen nicht zu vergessen. Der Name, der der Variablen zugewiesen wird, wird dann verwendet, um den Graphen zu zeichnen, wählen Sie in der Dashboard-Benutzeroberfläche im Allgemeinen überall aus. Bei kleinen Graphen ist dies nicht kritisch, aber mit zunehmender Komplexität des Problems können Probleme beim Verständnis des Geschehens auftreten.

Es gibt verschiedene Arten von Funktionen, die variable Daten auf unterschiedliche Weise speichern:

tf.summary.histogram("layer_output", w_h)

Mit dieser Funktion können Sie ein Histogramm für die Ausgabe des Layers erstellen und die Dynamik der Änderungen während des Trainings ungefähr abschätzen. Die Funktion tf.summary.scalar(“accuracy”, learning_rate) behält die Zahl. Sie können auch Audio und Bilder speichern.

Um die Protokolle zu speichern, benötigen Sie etwas mehr: Zuerst müssen Sie einen FileWriter erstellen, um die Datei zu schreiben.

Writer = tf.summary.FileWriter("./logs/nn_logs", sess.graph) # für 1.0 zusammengeführt = tf.summary.merge_all()

Und vereinen Sie alle Statistiken in einem Objekt.

Jetzt müssen Sie dieses Objekt zusammengeführt zur Ausführung an die Sitzung übertragen und dann FileWriter neue Daten hinzufügen, die von der Sitzung mit der Methode empfangen wurden.

Summary, op_res = ses.run([merged, op], feed_dict={X: X_train, Y: y_train, p_keep_input: 1.0, p_keep_hidden: 1.0}) Writer.add_summary(summary, i)

Für das einfache Speichern des Graphen reicht jedoch folgender Code:

zusammengeführt = tf.summary.merge_all(key='Zusammenfassungen')
if nicht os.path.exists('tensorboard_logs/'): os.makedirs('tensorboard_logs/') my_writer = tf.summary.FileWriter('tensorboard_logs/', sess.graph)

Und eine Nuance: Standardmäßig ist Tensorboard lokal unter 127.0 verfügbar. 1 .1: 6006. Hoffentlich hat dieser Hinweis den Lesern ein paar Sekunden Zeit und Nerven gespart.

Mehrschichtiges Perzeptron

Lassen Sie uns ein kanonisches Beispiel analysieren, indem wir die Funktion xor auswendig lernen, die das lineare Modell aufgrund der Unmöglichkeit einer linearen Teilung des Merkmalsraums nicht assimilieren kann.

mehrschichtiges Perzeptron | Tensorflow

Mehrschichtnetzwerke lernen die Funktion dadurch, dass sie eine implizite Transformation des Merkmalsraums in einen separierbaren vornehmen oder (je nach Implementierung) eine nichtlineare Partition dieses Raums vornehmen. Wir werden die erste Option implementieren – wir werden ein zweischichtiges Perzeptron mit nichtlinearer Aktivierung von Schichten erstellen. Der erste Layer führt eine nichtlineare Transformation durch, und der zweite Layer ist eine fast lineare Regression, die auf dem transformierten Feature-Raum funktioniert.

Wir verwenden die relu-Funktion als nichtlineares Element.

Lassen Sie uns die Struktur des Netzwerks definieren:

x_ = tf.placeholder(name="input", shape=[None, 2], dtype=tf.float32) y_ = tf.placeholder(name= "output", shape=[None, 1], dtype=tf. float32) hidden_neurons = 15 w1 = tf.Variable(tf.random_uniform(shape=[2, hidden_neurons ])) b1 = tf.Variable(tf.constant(value=0.0, shape=[hidden_neurons], dtype=tf.float32) ) layer1 = tf.nn.relu(tf.add(tf.matmul(x_, w1), b1)) w2 = tf.Variable(tf.random_uniform(shape=[hidden_neurons,1])) b2 = tf.Variable( tf.constant(value=0.0, shape=[1], dtype=tf.float32)) nn_output = tf.nn.relu(tf.add(tf.matmul(layer1, w2), b2))

Im Gegensatz zu Keras und anderen Bibliotheken auf höherer Ebene geht TF wie Theano von einer detaillierten Definition jeder Schicht als Sammlung einiger arithmetischer Operationen aus. Dies gilt nicht für alle Arten von Schichten, zum Beispiel werden Faltungs- und Dropout-Schichten durch eine Funktion definiert, während eine gewöhnliche vollständig verbundene Schicht nicht nur Variablen für Gewichtungen und Verschiebungen deklariert, sondern auch die Operationen selbst (Multiplikation von Gewichten mit die Ausgabe der vorherigen Schicht, Hinzufügen von Verschiebung, Anwendung der Aktivierungsfunktion).

Natürlich führt das alles oft zu einer ähnlichen Funktion:

def vollständig_verbunden(input_layer,weights,biases):layer = tf.add(tf.matmul(input_layer,weights),biases)
Rückkehr(tf.nn.relu(Schicht))

Gleichzeitig ist es nach meiner eigenen Erfahrung bequemer, Variablen außerhalb zu deklarieren und zu initialisieren: Manchmal müssen Sie sie an anderer Stelle innerhalb des Graphen verwenden (ein typisches Beispiel sind siamesische neuronale Netze mit gemeinsamen Gewichten) oder einfach Zugriff haben für einfache Protokollierung in eine Datei und Anzeige aktueller Werte, und aus irgendeinem Grund möchte ich kein Tensorboard verwenden.

Wir verwenden eine elementare Verlustfunktion:

gd = tf.train.GradientDescentOptimizer(0.001) loss = tf.reduce_mean(tf.square(nn_output - y_)) train_step = gd.minimize(loss)

und trainiere:

a = np.array([[0, 0], [0, 1], [1, 0], [1, 1]]) b = np.array([[0], [1], [1] , [0]])
für _ in range(20000): sess.run(train_step, feed_dict={x_:a, y_:b})

Die resultierende Grafik:

Ergebnisgrafik

Im Vergleich zur Regression hat sich praktisch nichts geändert: der gleiche Lernprozess, die gleiche Verlustfunktion. Der einzige Teil des Codes, der sich stark geändert hat, ist der Code zum Erstellen des Rechengraphen. Es kam so weit, dass ich für bestimmte Aufgaben eine Reihe von Skripten angesammelt habe, in denen ich nur den Datenfeed und die Berechnungsgrafik ändere.

Natürlich gibt es in diesem Beispiel keine Lazy-Fetch-Prüfung. Sie können überprüfen, ob das Netzwerk korrekt funktioniert, indem Sie die Ausgabe des neuronalen Netzwerks in der Grafik berechnen:

sess.run(nn_output, feed_dict={x_:x})

Bei komplexeren Modellen werden natürlich die Validierung von Lazy Sampling und Qualitätsverfolgung während des Trainings und in TF integrierte Methoden zum Einspeisen von Daten in den Graphen hinzugefügt.

Resourcenmanagement

Sehr oft ist die Welt ungerecht und die Aufgabe passt möglicherweise nicht vollständig in ein Gerät. Oder das Management hat nur einen Tesla gekauft, und die Entwickler geraten immer wieder in Konflikte wegen einer besetzten Karte. TF verfügt für solche Fälle über Rechenkontrollmechanismen. Im Framework werden Geräte als „/cpu: 0“, „/gpu: 0“ usw. bezeichnet. Das Einfachste ist, dass Sie angeben können, wo genau diese oder jene Variable „leben“ wird:

mit tf.device('/cpu:0'): a = ...

In diesem Beispiel wird die Variable a an den Prozessor gesendet.

Sie können der Sitzung auch ein Konfigurationsobjekt übergeben, mit dem Sie die Durchführung von Graphenberechnungen ändern können. Es sieht aus wie das:

cfg = tf.ConfigProto() sess = tf.Session(config=cfg)

In der Konfiguration können Sie zunächst den Parameter log_device_placement aktivieren, um zu verstehen, an welches Computergerät die Berechnung dieses oder jenes Teils des Graphen ging.

Nehmen wir an, das Entwicklerteam kann sich darauf einigen, den Verbrauch des GPU-Speichers zu begrenzen. Der folgende Code zeigt das:

gpu_opts = tf.GPUOptions(per_process_gpu_memory_fraction = 0.25) sess = tf.Session(config=tf.ConfigProto(gpu_options = gpu_opts))

In dieser Konfiguration verbraucht die Sitzung nicht mehr als ein Viertel des GPU-Speichers, was bedeutet, dass Sie die Berechnungen mehrerer weiterer Modelle gleichzeitig ausführen und das zu zählende Modell auch auf der CPU ausführen können, aber am einfachsten ist es, den Parameter allow_soft_placements zu aktivieren, damit TF diese Probleme selbst löst. Für diesen Teil der API ist die Dokumentation noch recht lückenhaft und einige Links führen direkt zu GitHub im Quellcode der Konfigurationsklassen. Einige der Eigenschaften sind als veraltet markiert, andere sind experimentell, daher müssen Sie hier vorsichtig sein.

Zusammenfassung

TF ist buchstäblich in anderthalb Jahren so stark gewachsen, dass es an der Zeit ist, separate Überprüfungen über den Einsatz von Faltungs- und wiederkehrenden Netzwerken, Reinforcement Learning und die Anwendung des Frameworks auf verschiedene Aufgaben vorzunehmen.

Die in diesem Artikel gezeigten Medien sind nicht Eigentum von Analytics Vidhya und werden nach Ermessen des Autors verwendet.

Quelle: https://www.analyticsvidhya.com/blog/2021/08/tensorflow-an-impressive-deep-learning-library/

Zeitstempel:

Mehr von Analytics-Vidhya