Evgenii Legotckoi
Evgenii Legotckoi13. Mai 2020 05:42

Python-Bilderkennung mit TensorFlow und Keras

Einführung

Eine der häufigsten Anwendungen von TensorFlow und Keras ist die Bilderkennung und -klassifizierung. Wenn Sie lernen möchten, wie Sie Keras zur Bildklassifizierung oder -erkennung verwenden, erfahren Sie in diesem Artikel, wie es geht.

Definitionen

Wenn Sie die grundlegenden Konzepte der Bilderkennung nicht verstehen, wird es für Sie schwierig sein, den Hauptteil dieses Artikels vollständig zu verstehen. Bevor wir fortfahren, definieren wir daher die Terminologie.


TensorFlow / Keras

TensorFlow ist eine Open-Source-Bibliothek, die vom Google Brain-Team für Python entwickelt wurde. TensorFlow kompiliert viele verschiedene Algorithmen und Modelle, die es dem Benutzer ermöglichen, tiefe neuronale Netze für Aufgaben wie Bilderkennung und -klassifizierung sowie Verarbeitung natürlicher Sprache zu implementieren. TensorFlow ist ein leistungsstarkes Framework, das durch die Implementierung einer Reihe von Verarbeitungsknoten funktioniert, von denen jeder eine mathematische Operation darstellt, und die gesamte Reihe von Knoten wird als "Graphen" bezeichnet.

Apropos Keras, es ist eine High-Level-API (Application Programming Interface), die TensorFlow-Funktionen (sowie andere ML-Bibliotheken wie Theano) verwenden kann. Keras wurde mit Komfort und Modularität als Richtlinien entworfen. In der Praxis macht Keras viele der leistungsstarken, aber oft komplexen Funktionen von TensorFlow einfach zu implementieren, und es ist so konfiguriert, dass es ohne größere Änderungen oder Optimierungen mit Python funktioniert.

Bilderkennung (Klassifizierung)

Bilderkennung bezieht sich auf die Aufgabe, ein Bild in ein neuronales Netz einzugeben und diesem Bild eine Art Label zuzuweisen. Das Label, das die Netzwerkausgaben mit der vordefinierten Klasse übereinstimmen. Es können mehrere Klassen gleichzeitig oder nur eine zugeordnet werden. Gibt es nur eine Klasse, wird meist der Begriff „Erkennung“ verwendet, während das Problem der Erkennung mehrerer Klassen oft als „Klassifikation“ bezeichnet wird.

Eine Teilmenge von Bildklassifikationen ist bereits eine Definition von Objekten, wenn bestimmte Instanzen von Objekten als einer bestimmten Klasse zugehörig identifiziert werden, beispielsweise Tiere, Autos oder Menschen.

Ein markantes Beispiel für eine solche Klassifizierung ist die Lösung des gängigsten Captchas - ReCaptcha v2 von Google, bei dem Sie aus der Menge der Bilder nur diejenigen auswählen müssen, die zu der in der Beschreibung angegebenen Klasse gehören.

Extraktionsfunktion

Um eine Bilderkennung oder -klassifizierung durchzuführen, muss das neuronale Netz eine Merkmalsextraktion durchführen. Traits sind die Datenelemente, die von maximalem Interesse sind und die über das neuronale Netz übertragen werden. Im speziellen Fall der Bilderkennung sind solche Merkmale Pixelgruppen, wie Linien und Punkte, die das Netzwerk auf das Vorhandensein eines Musters hin analysiert.

Merkmalserkennung (oder Merkmalsextraktion) ist der Prozess des Extrahierens relevanter Merkmale aus dem Eingabebild, damit sie analysiert werden können. Viele Bilder enthalten Anmerkungen oder Metadaten, die dem neuronalen Netz helfen, relevante Merkmale zu finden.

Wie neuronale Netze lernen, Bilder zu erkennen

Wenn Sie verstehen, wie ein neuronales Netzwerk Bilder erkennt, können Sie ein neuronales Netzwerkmodell implementieren. Sehen wir uns daher in den folgenden Abschnitten kurz den Bilderkennungsprozess an.

Merkmalsextraktion mit Filtern

Die erste Schicht des neuronalen Netzes nimmt alle Pixel im Bild auf. Nachdem alle Daten in das Netzwerk eingegeben wurden, werden verschiedene Filter auf das Bild angewendet, die ein Verständnis der verschiedenen Teile des Bildes ermöglichen. Es ist die Merkmalsextraktion, die "Merkmalskarten" erstellt.

Dieser Vorgang des Extrahierens von Merkmalen aus einem Bild wird unter Verwendung einer "Faltungsschicht" durchgeführt, und die Faltung bildet einfach eine Darstellung eines Teils des Bildes. Aus diesem Konzept der Faltung leiten wir den Begriff Convolutional Neural Network (CNN) ab – die Art von neuronalen Netzen, die am häufigsten bei der Bildklassifizierung und -erkennung verwendet wird.

Wenn Sie sich genau vorstellen möchten, wie Feature-Mapping funktioniert, stellen Sie sich vor, Sie halten eine Taschenlampe über einem Bild in einem dunklen Raum. Wenn Sie den Balken über das Bild schieben, lernen Sie die Eigenschaften des Bildes kennen. Ein Filter ist das, was das Netzwerk verwendet, um eine Darstellung des Bildes zu bilden, und in dieser Metapher ist das Licht der Taschenlampe der Filter.

Die Strahlbreite Ihrer Taschenlampe bestimmt die Größe des Bildausschnitts, den Sie gleichzeitig betrachten, und neuronale Netze haben einen ähnlichen Parameter - die Filtergröße. Die Filtergröße beeinflusst, wie viele Pixel gleichzeitig überprüft werden. Die in CNN verwendete Gesamtfiltergröße beträgt 3 und deckt sowohl Höhe als auch Breite ab, sodass der Filter auf einen 3 x 3 Pixel großen Bereich überprüft.

Während die Größe des Filters die Höhe und Breite des Filters abdeckt, muss auch die Tiefe des Filters angegeben werden.

Aber wie kann ein 2D-Bild Tiefe haben?

Tatsache ist, dass digitale Bilder in Form von Höhe, Breite und einem RGB-Wert angezeigt werden, der die Farbe des Pixels bestimmt, so dass die verfolgte "Tiefe" die Anzahl der Farbkanäle ist, die das Bild hat. Graustufenbilder (keine Farbe) haben nur 1 Farbkanal, während Farbbilder eine Tiefe von 3 Kanälen haben.

Dies alles bedeutet, dass für einen Filter der Größe 3, der auf ein Vollfarbbild angewendet wird, die endgültigen Abmessungen dieses Filters 3 x 3 x 3 betragen. Für jedes Pixel, das von diesem Filter abgedeckt wird, multipliziert das Netzwerk die Filterwerte mit den Werten der Pixel selbst, um eine numerische Darstellung dieses Pixels zu erhalten. ... Dieser Vorgang wird dann über das gesamte Bild durchgeführt, um ein vollständiges Bild zu erhalten. Der Filter bewegt sich gemäß einem Parameter namens "step" durch den Rest des Bildes, der bestimmt, wie viele Pixel sich der Filter bewegen soll, nachdem er einen Wert an seiner aktuellen Position berechnet hat. Die übliche Schrittgröße für CNN ist 2.

Das Endergebnis all dieser Berechnungen ist eine Merkmalskarte. Dieser Vorgang wird normalerweise mit mehreren Filtern durchgeführt, um die Komplexität des Bildes zu erhalten.

Aktivierungsfunktionen

Nachdem eine Bildmerkmalskarte erstellt wurde, werden die das Bild repräsentierenden Werte durch eine Aktivierungsfunktion oder Aktivierungsschicht geleitet. Die Aktivierungsfunktion nimmt diese Werte, die dank der Faltungsschicht in linearer Form vorliegen (dh nur eine Liste von Zahlen), und erhöht ihre Nichtlinearität, da die Bilder selbst nichtlinear sind.

Die typische Aktivierungsfunktion, die dazu verwendet wird, ist die rektifizierte Lineareinheit (ReLU), obwohl es manchmal auch andere Aktivierungsfunktionen gibt, die manchmal verwendet werden (diese können Sie [hier] nachlesen (https://keras.io/activations/ ).

Ebenen zusammenführen

Bei der Aktivierung werden die Daten durch die Zusammenführungsschicht gesendet. Die Verkettung "vereinfacht" ein Bild: Sie nimmt Informationen, die das Bild darstellen, und komprimiert es. Der Pooling-Prozess macht das Netzwerk flexibler und kann Objekte und Bilder anhand ihrer jeweiligen Funktionen besser erkennen.

Wenn wir ein Bild betrachten, beschäftigen wir uns in der Regel nicht mit allen Informationen (zum Beispiel was sich im Hintergrund des Bildes befindet), sondern nur mit den Zeichen, die uns interessieren - Menschen, Tiere usw .

Ebenso entfernt die Zusammenführungsebene von CNN unnötige Teile des Bildes, sodass nur die Teile übrig bleiben, die sie für relevant hält, abhängig von der Größe der Zusammenführungsebene.

Da das Netzwerk Entscheidungen über die wichtigsten Teile des Bildes treffen muss, wird erwartet, dass es nur die Teile des Bildes untersucht, die wirklich die Essenz des betreffenden Objekts repräsentieren. Dies hilft, ein „Overfitting“ zu vermeiden, wenn das Netzwerk alle Aspekte der Fallstudie zu gut lernt und nicht mehr auf neue Daten verallgemeinern kann, weil es irrelevante Unterschiede berücksichtigt.

Es gibt verschiedene Möglichkeiten, Werte zu kombinieren, aber die am häufigsten verwendete ist die maximale Verkettung. Maximales Zusammenführen bedeutet, dass der maximale Wert unter Pixeln innerhalb eines Filters (innerhalb eines Bildfragments) genommen wird. Dadurch werden 3/4 der Informationen ausgeschnitten, sofern ein 2 x 2-Filter verwendet wird.

Die maximalen Pixelwerte werden verwendet, um mögliche Bildverzerrungen zu berücksichtigen, und die Anzahl der Parameter (Bildgröße) wird reduziert, um die Überanpassung zu kontrollieren. Es gibt andere Zusammenführungsprinzipien wie Mittelwert- oder Summenzusammenführung, diese werden jedoch nicht so oft verwendet, da die Maximierung der Zusammenführung mehr Präzision bietet.

Kompression

Die letzten Schichten unseres CNN – die eng gekoppelten Schichten – erfordern, dass die Daten für die weitere Verarbeitung vektorisiert werden. Aus diesem Grund müssen die Daten „zusammengeführt“ werden. Dazu werden die Werte in einen langen Vektor oder eine Spalte aus sequentiell geordneten Zahlen komprimiert.

Vollständig verknüpfte Ebene

Die endlichen Schichten von CNN sind eng verbundene Schichten oder künstliche neuronale Netze (ANN). Die Hauptfunktion von KNN besteht darin, die Eingabemerkmale zu analysieren und sie zu verschiedenen Attributen zu kombinieren, die bei der Klassifizierung helfen. Diese Schichten bilden Sätze von Neuronen, die verschiedene Teile des betreffenden Objekts darstellen, und der Satz von Neuronen kann beispielsweise die hängenden Ohren eines Hundes oder die Rötung eines Apfels sein. Wenn eine ausreichende Anzahl dieser Neuronen als Reaktion auf das Eingabebild aktiviert wird, wird es als Objekt klassifiziert.

Der Fehler oder die Differenz zwischen den berechneten Werten und dem erwarteten Wert im Trainingssatz wird mit ANN berechnet. Dann wird das Netzwerk dem Backpropagation-Verfahren unterzogen, bei dem der Einfluss dieses Neurons auf das Neuron in der nächsten Schicht berechnet und dann sein Einfluss (Gewicht) korrigiert wird. Dies dient der Optimierung der Leistung des Modells. Dieser Vorgang wird immer wieder wiederholt: So trainiert das Netzwerk an den Daten und lernt die Zusammenhänge zwischen den Eingabemerkmalen und den Ausgabeklassen.

Die Neuronen in den mittleren vollständig verbundenen Schichten geben Binärwerte aus, die sich auf die möglichen Klassen beziehen. Wenn Sie vier verschiedene Klassen haben (z. B. Hund, Auto, Haus und Person), hat das Neuron einen Wert von "1" für die Klasse, von der es glaubt, dass sie das Bild repräsentiert, und einen Wert von "0" für die anderen Klassen.

Die letzte vollständig verbundene Schicht weist die Wahrscheinlichkeit jeder der Klassen innerhalb einer (zusammengefasst) zu, nachdem sie die Ausgabe der vorherigen Schicht erhalten hat. Wird der Kategorie „Hund“ ein Wert von 0,75 zugewiesen, bedeutet dies eine 75%ige Chance, dass es sich bei dem Bild um einen Hund handelt.

Workflow für maschinelles Lernen

Bevor wir zu einem Beispiel für das Training eines Bildklassifizierers übergehen, nehmen wir uns einen Moment Zeit, um den Workflow oder die Pipeline für maschinelles Lernen zu verstehen. Der Prozess des Trainierens eines neuronalen Netzmodells ist ziemlich standardisiert und kann in vier verschiedene Phasen unterteilt werden.

Der Bildklassifizierer wurde nun trainiert und die Bilder können an CNN gesendet werden, das nun eine Vermutung über den Inhalt dieses Bildes ableitet.

Datenaufbereitung

Zuerst müssen Sie Ihre Daten sammeln und formatieren, damit das neuronale Harznetzwerk daraus lernt. Dazu gehört das Sammeln von Bildern und deren Kennzeichnung. Auch wenn Sie einen Datensatz heruntergeladen haben, der von einer anderen Person erstellt wurde, müssen Sie ihn wahrscheinlich noch vorbereiten, bevor Sie ihn für das Training verwenden können. Das Aufbereiten von Daten ist eine Kunst für sich, die mit der Lösung von Problemen wie fehlenden Werten, beschädigten Daten, Daten im falschen Format, falschen Labels usw. verbunden ist.

In diesem Artikel verwenden wir einen vorverarbeiteten Datensatz.

Modell erstellen

Das Erstellen eines neuronalen Netzmodells beinhaltet die Auswahl verschiedener Parameter und Hyperparameter. Sie müssen entscheiden, wie viele Layer in Ihrem Modell verwendet werden, wie groß die Eingabe- und Ausgabe-Layer sein sollen, welche Aktivierungsfunktionen Sie verwenden, ob Sie Dropout verwenden usw.

Es wird mit der Zeit zu verstehen sein, welche Parameter und Hyperparameter es wert sind, verwendet zu werden (es gibt viel zu lernen), aber es gibt einige grundlegende Methoden, die Sie am Anfang verwenden können, und wir werden einige davon in unserem Beispiel betrachten.

Trainiere das Modell

Nachdem Ihr Modell erstellt wurde, müssen Sie lediglich eine Instanz des Modells erstellen und diese zum Training an Ihre Daten anpassen. Beim Trainieren eines Modells wird größtes Augenmerk auf den Zeitaufwand für das Training gelegt. Sie können die Dauer des Netzwerktrainings festlegen, indem Sie die Anzahl der Trainingsepochen angeben. Je länger Sie das Modell trainieren, desto höher ist seine Effektivität, aber wenn Sie zu viele Lernepochen verwenden, riskieren Sie eine Überanpassung des Modells.

Die Anzahl der zu trainierenden Epochen wird man mit der Zeit bestimmen lernen, und in der Regel sollte man die Gewichte des neuronalen Netzes zwischen den Trainingseinheiten immer beibehalten, damit man nach einigen Fortschritten nicht von vorne beginnen muss Ausbildung.

Modellbewertung

Die Bewertung eines Modells umfasst mehrere Schritte. Der erste Schritt besteht darin, die Leistung des Modells mit einer Reihe von Testdaten zu vergleichen: Daten, auf die das Modell nicht trainiert wurde. Daher testen Sie die Leistung des Modells mit diesem neuen Datensatz und analysieren seine Leistung anhand verschiedener Metriken.

Es gibt verschiedene Metriken zum Bestimmen der Leistung eines neuronalen Netzwerkmodells, aber die gebräuchlichste ist die "Präzision", d. h. die Anzahl der richtig klassifizierten Bilder geteilt durch die Gesamtzahl der Bilder in Ihrem Dataset.

Nachdem Sie die Genauigkeit des Modells im Validierungs-Dataset gesehen haben, werden Sie wahrscheinlich zurückgehen und das Netzwerk mit leicht optimierten Parametern neu trainieren, da Sie mit der Leistung Ihres Netzwerks beim ersten Training wahrscheinlich nicht zufrieden sind. Sie werden Ihre Netzwerkparameter weiter optimieren, neu trainieren und die Leistung messen, bis Sie mit der Genauigkeit des Netzwerks zufrieden sind.

Abschließend testen Sie die Netzwerkleistung an einem Testset. Dies ist ein weiterer Datensatz, den Ihr Modell noch nie zuvor gesehen hat.

Sie fragen sich vielleicht: Warum brauchen wir einen weiteren Testdatensatz? Schließlich haben Sie sich schon ein Bild von der Genauigkeit Ihres Modells gemacht, war das nicht der Zweck des „Testsets“?

Die Sache ist die, dass alle Änderungen an den Parametern, die Sie vorgenommen haben, das Optimieren des Netzwerks bei der Arbeit mit einem "Testdatensatz" in Kombination mit dem wiederholten erneuten Testen dieses Satzes - dazu führen können, dass Ihr Netzwerk einige der Funktionen des Satzes gelernt hat , aber gleichzeitig wäre es nicht so gut, Out-of-Sample-Daten zu verallgemeinern. Aus diesem Grund sollten Sie dem Netzwerk komplett neue Testdaten zur Verfügung stellen.

Der Zweck einer Testsuite besteht darin, auf Probleme wie Überanpassung zu prüfen, um sicherer zu sein, dass Ihr Modell in der realen Welt wirklich verwendbar ist.

Bilder von CNN erkennen

Wir haben bereits viel behandelt und wenn all diese Informationen vielleicht ein wenig unklar waren, sollte die Kombination der obigen Konzepte in einem auf einem Datensatz trainierten Stichprobenklassifikator endlich alles klären. Schauen wir uns also ein vollständiges Beispiel für die Bilderkennung mit Keras an - vom Laden der Daten bis zur Bewertung der Effektivität des Modells.

Zuerst benötigen wir einen Trainingsdatensatz. Für dieses Beispiel verwenden wir den bekannten CIFAR-10-Datensatz. CIFAR-10 ist ein großer Datensatz mit über 60.000 Bildern, die 10 verschiedene Objektklassen wie Katzen, Flugzeuge und Autos repräsentieren.

Die Bilder sind Vollfarb-RGB, aber sie sind ziemlich klein, nur 32 x 32. Das Tolle am CIFAR-10-Datensatz ist, dass er mit Keras gebündelt ist, so dass das Laden des Datensatzes einfach ist und die Bilder selbst nur minimale Vorverarbeitung benötigen.

Als erstes müssen wir die erforderlichen Bibliotheken importieren. Sie werden unterwegs genau sehen, wie dieser Import funktioniert, aber denken Sie vorerst daran, dass wir Numpy und verschiedene Keras-bezogene Module verwenden werden:

import numpy
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten, BatchNormalization, Activation
from keras.layers.convolutional import Conv2D, MaxPooling2D
from keras.constraints import maxnorm
from keras.utils import np_utils

Wir werden einen zufälligen SEED (Symmetric Block Crypto Algorithm basierend auf dem Feistel Network) verwenden, damit die in diesem Artikel erhaltenen Ergebnisse von Ihnen reproduziert werden können, daher benötigen wir numpy:

# Set random seed for purposes of reproducibility
seed = 21

Datenaufbereitung

Jetzt müssen wir noch einen weiteren Import durchführen: den Datensatz selbst.

from keras.datasets import cifar10

Laden wir nun den Datensatz. Wir können dies tun, indem wir einfach angeben, in welche Variablen wir die Daten laden möchten, und dann die Funktion load_data() verwenden:

# loading in the data
(X_train, y_train), (X_test, y_test) = cifar10.load_data()

In den meisten Fällen müssen Sie Ihre Daten vorverarbeiten, um sie einsatzbereit zu machen. Da wir jedoch einen vorgefertigten Datensatz verwenden, wird diese Verarbeitung minimiert. Eine der Aktionen, die wir ausführen möchten, ist die Normalisierung der Eingabedaten.

Wenn die Eingabedatenwerte zu breit sind, kann dies die Netzwerkleistung beeinträchtigen. In unserem Fall sind die Eingabewerte Pixel im Bild, die einen Wert zwischen 0 und 255 haben.

Um die Daten zu normalisieren, können wir die Bildwerte einfach durch 255 dividieren. Dazu müssen wir die Daten zunächst in Gleitkommazahlen umwandeln, da es sich derzeit um Ganzzahlen handelt. Wir können dies mit dem Befehl astype() von Numpy tun und dann den gewünschten Datentyp deklarieren:

# normalize the inputs from 0-255 to between 0 and 1 by dividing by 255
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')
X_train = X_train / 255.0
X_test = X_test / 255.0

Das nächste, was wir tun müssen, um die Daten für das Web vorzubereiten, besteht darin, sie in einen einheitlichen Code zu übersetzen. Wir werden nicht auf die Details der unitären Kodierung eingehen, aber beachten Sie, dass Bilder von einem neuronalen Netz in der Form, in der sie vorliegen, nicht verwendet werden können - sie müssen zuerst kodiert werden, und es ist am besten, bei der binären Klassifikation die einheitliche Kodierung zu verwenden.

Wir wenden hier erfolgreich die binäre Klassifizierung an, weil das Bild entweder zu einer bestimmten Klasse gehört oder nicht: es kann nicht irgendwo in der Mitte sein. Verwenden Sie für eine einheitliche Codierung den Befehl Numpy to_categorical(). Aus diesem Grund haben wir die Funktion np_utils aus Keras importiert, da sie to_categorical() enthält.

Wir müssen auch die Anzahl der Klassen im Datensatz festlegen, damit wir verstehen, wie viele Neuronen die letzte Schicht komprimieren müssen:

# one hot encode outputs
y_train = np_utils.to_categorical(y_train)
y_test = np_utils.to_categorical(y_test)
class_num = y_test.shape[1]

Modelldesign

Wir haben das Designstadium des CNN-Modells erreicht. Als erstes müssen Sie das Format definieren, das wir für das Modell verwenden möchten. Keras hat verschiedene Formate (Pläne) für Gebäudemodelle, aber Sequential ist das am häufigsten verwendete Format – deshalb haben wir es aus Keras importiert.

Modell erstellen

model = Sequential()

Die erste Schicht in unserem Modell ist die Faltungsschicht. Es nimmt Eingaben entgegen und leitet sie durch Faltungsfilter.

Wenn wir dies in Keras implementieren, müssen wir die Anzahl der Kanäle (Filter), die wir benötigen (32), die Filtergröße (in unserem Fall 3 x 3), das Anmeldeformular (beim Erstellen der ersten Ebene), die Aktivierung angeben Funktion und Polsterung.

Wie bereits erwähnt, ist relu die häufigste Aktivierungsfunktion, und wir definieren Padding mit padding = 'same', d.h. wir ändern die Größe des Bildes nicht:

model.add(Conv2D(32, (3, 3), input_shape=X_train.shape[1:], padding='same'))
model.add(Activation('relu'))

Hinweis: Sie können die erforderlichen Befehle auch in einer Zeile verketten, zum Beispiel:

model.add(Conv2D(32, (3, 3), input_shape=(3, 32, 32), activation='relu', padding='same'))

Wir erstellen jetzt eine Ausschlussebene, um eine Überanpassung zu verhindern, die zufällig Verbindungen zwischen den Ebenen entfernt (0,2 bedeutet, dass 20% der vorhandenen Verbindungen verworfen werden):

model.add(Dropout(0.2))

Wir können auch eine Batch-Normalisierung durchführen. Die Stapelnormalisierung normalisiert die Eingaben auf die nächste Schicht und stellt sicher, dass das Netzwerk immer Aktivierungsfunktionen mit der gleichen Verteilung erstellt, wie wir es möchten:

model.add(BatchNormalization())

Nun folgt eine weitere Faltungsschicht, allerdings nimmt die Filtergröße zu, sodass das Netzwerk bereits komplexere Darstellungen lernen kann:

model.add(Conv2D(64, (3, 3), padding='same'))
model.add(Activation('relu'))

Und hier ist die Vereinheitlichungsschicht, die, wie bereits erwähnt, dazu beiträgt, den Bildklassifizierer korrekter zu machen, damit er die relevanten Muster lernen kann. Wir werden auch das Dropout und die Batch-Normalisierung beschreiben:

model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.2))
model.add(BatchNormalization())

Dies ist der Kern des Workflows im ersten Teil der CNN-Implementierung: Falten, Aktivieren, Ausschließen, Zusammenführen. Jetzt verstehen Sie, warum wir Dropout, BatchNormalization, Activation, Conv2d und MaxPooling2d importiert haben.

Sie können die Anzahl der Faltungsschichten nach Belieben variieren, aber jede erhöht den Rechenaufwand. Beachten Sie, dass Sie beim Hinzufügen von Faltungsschichten normalerweise auch die Anzahl der Filter erhöhen, damit das Modell komplexere Darstellungen lernen kann. Wenn die für diese Ebenen gewählten Zahlen etwas willkürlich erscheinen, dann wissen Sie nur, dass es empfohlen wird, die Filter schrittweise zu erhöhen und den Wert auf 2 hoch (2 ^ n) zu setzen, was beim Training des Modells einen leichten Vorteil bringen kann eine GPU.

Es ist wichtig, nicht zu viele Zusammenführungsebenen zu verwenden, da jede einzelne einen Teil der Daten verwirft. Eine zu häufige Kombination führt dazu, dass eng verbundene Schichten fast nichts lernen, wenn die Daten sie erreichen.

Die Anzahl der erforderlichen Zusammenführungsebenen hängt von der jeweiligen Aufgabe ab - dies wird im Laufe der Zeit festgelegt. Da die Bilder in unserem Set schon recht klein sind, werden wir sie nicht öfter als zweimal zusammenführen.

Sie können jetzt über diese Ebenen iterieren, um Ihrem Netzwerk mehr Ansichten zur Verfügung zu stellen, mit denen Sie arbeiten können:

model.add(Conv2D(64, (3, 3), padding='same'))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.2))
model.add(BatchNormalization())
model.add(Conv2D(128, (3, 3), padding='same'))
model.add(Activation('relu'))
model.add(Dropout(0.2))
model.add(BatchNormalization())

Nachdem wir mit den Faltungsschichten fertig sind, müssen wir die Daten komprimieren, also haben wir die obige Flatten-Funktion importiert. Wir fügen auch wieder eine Ausschlussebene hinzu:

model.add(Flatten())
model.add(Dropout(0.2))

Wir verwenden nun die importierte Dense-Funktion und erstellen die erste eng gekoppelte Schicht. Wir müssen die Anzahl der Neuronen in der dichten Schicht angeben. Beachten Sie, dass die Anzahl der Neuronen in nachfolgenden Schichten abnimmt und sich schließlich der gleichen Anzahl von Neuronen annähert wie die Klassen im Datensatz (in diesem Fall 10). Das Einschränken des Kernels kann die Daten während des Trainings anordnen, was auch dazu beiträgt, eine Überanpassung zu verhindern. Aus diesem Grund haben wir früher maxnorm importiert.

model.add(Dense(256, kernel_constraint=maxnorm(3)))
model.add(Activation('relu'))
model.add(Dropout(0.2))
model.add(BatchNormalization())
model.add(Dense(128, kernel_constraint=maxnorm(3)))
model.add(Activation('relu'))
model.add(Dropout(0.2))
model.add(BatchNormalization())

In dieser letzten Schicht setzen wir die Anzahl der Klassen mit der Anzahl der Neuronen gleich. Jedes Neuron stellt eine Klasse dar, so dass die Ausgabe dieser Schicht ein Vektor von 10 Neuronen ist, von denen jedes eine bestimmte Wahrscheinlichkeit speichert, dass das fragliche Bild zu seiner Klasse gehört.

Schließlich wählt die Softmax-Aktivierungsfunktion das Neuron mit der höchsten Wahrscheinlichkeit als Ausgabewert aus, vorausgesetzt, das Bild gehört zu dieser bestimmten Klasse:

model.add(Dense(class_num))
model.add(Activation('softmax'))

Nachdem wir nun das Modell entwickelt haben, das wir verwenden möchten, müssen Sie es nur noch kompilieren. Geben wir die Anzahl der zu trainierenden Epochen sowie den Optimierer an, den wir verwenden möchten.

Der Optimierer stimmt die Gewichtungen in Ihrem Netzwerk ab, um näher an den Punkt mit dem geringsten Verlust zu kommen. Der Algorithmus von Adam ist einer der am häufigsten verwendeten Optimierer, da er bei den meisten Aufgaben eine hohe Leistung bietet:

epochs = 25
optimizer = 'adam'

Lassen Sie uns nun das Modell mit den ausgewählten Parametern kompilieren. Lassen Sie uns auch eine Metrik für die Bewertung bereitstellen.

model.compile(loss='categorical_crossentropy', optimizer=optimizer, metrics=['accuracy'])

Wir können auch eine Zusammenfassung des Modells drucken, um ein Bild vom Modell als Ganzes zu bekommen.

print(model.summary())

Ein Ausdruck der Zusammenfassung gibt uns einige Informationen:

Results:

Layer (type) Output Shape Param #
=================================================================
conv2d_1 (Conv2D) (None, 32, 32, 32) 896
_________________________________________________________________
activation_1 (Activation) (None, 32, 32, 32) 0
_________________________________________________________________
dropout_1 (Dropout) (None, 32, 32, 32) 0
_________________________________________________________________
batch_normalization_1 (Batch (None, 32, 32, 32) 128
_________________________________________________________________
conv2d_2 (Conv2D) (None, 32, 32, 64) 18496
_________________________________________________________________
activation_2 (Activation) (None, 32, 32, 64) 0
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 16, 16, 64) 0
_________________________________________________________________
dropout_2 (Dropout) (None, 16, 16, 64) 0
_________________________________________________________________
batch_normalization_2 (Batch (None, 16, 16, 64) 256
_________________________________________________________________
conv2d_3 (Conv2D) (None, 16, 16, 64) 36928
_________________________________________________________________
activation_3 (Activation) (None, 16, 16, 64) 0
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 8, 8, 64) 0
_________________________________________________________________
dropout_3 (Dropout) (None, 8, 8, 64) 0
_________________________________________________________________
batch_normalization_3 (Batch (None, 8, 8, 64) 256
_________________________________________________________________
conv2d_4 (Conv2D) (None, 8, 8, 128) 73856
_________________________________________________________________
activation_4 (Activation) (None, 8, 8, 128) 0
_________________________________________________________________
dropout_4 (Dropout) (None, 8, 8, 128) 0
_________________________________________________________________
batch_normalization_4 (Batch (None, 8, 8, 128) 512
_________________________________________________________________
flatten_1 (Flatten) (None, 8192) 0
_________________________________________________________________
dropout_5 (Dropout) (None, 8192) 0
_________________________________________________________________
dense_1 (Dense) (None, 256) 2097408
_________________________________________________________________
activation_5 (Activation) (None, 256) 0
_________________________________________________________________
dropout_6 (Dropout) (None, 256) 0
_________________________________________________________________
batch_normalization_5 (Batch (None, 256) 1024
_________________________________________________________________
dense_2 (Dense) (None, 128) 32896
_________________________________________________________________
activation_6 (Activation) (None, 128) 0
_________________________________________________________________
dropout_7 (Dropout) (None, 128) 0
_________________________________________________________________
batch_normalization_6 (Batch (None, 128) 512
_________________________________________________________________
dense_3 (Dense) (None, 10) 1290
_________________________________________________________________
activation_7 (Activation) (None, 10) 0
=================================================================
Total params: 2,264,458
Trainable params: 2,263,114
Non-trainable params: 1,344

Jetzt beginnen wir mit dem Training des Modells. Dazu müssen wir die Funktion fit() im Modell aufrufen und die ausgewählten Parameter übergeben.

Hier wird SEED verwendet, das aus Gründen der Reproduzierbarkeit ausgewählt wurde.

numpy.random.seed(seed)
model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=epochs, batch_size=64)

Nehmen Sie ein Trainingsset mit 50.000 Samples und ein Testset mit 10.000 Samples.

Wenn Sie diesen Code ausführen, erhalten Sie:

Epoch 1/25

64/50000 [..............................] - ETA: 16:57 - loss: 3.1479 - acc: 0.0938
128/50000 [..............................] - ETA: 10:12 - loss: 3.0212 - acc: 0.0938
192/50000 [..............................] - ETA: 7:57 - loss: 2.9781 - acc: 0.1250
256/50000 [..............................] - ETA: 6:48 - loss: 2.8830 - acc: 0.1484
320/50000 [..............................] - ETA: 6:07 - loss: 2.8878 - acc: 0.1469
384/50000 [..............................] - ETA: 5:40 - loss: 2.8732 - acc: 0.1458
448/50000 [..............................] - ETA: 5:20 - loss: 2.8842 - acc: 0.1406

...
...
...

49664/50000 [============================>.] - ETA: 1s - loss: 1.5160 - acc: 0.4611
49728/50000 [============================>.] - ETA: 1s - loss: 1.5157 - acc: 0.4612
49792/50000 [============================>.] - ETA: 1s - loss: 1.5153 - acc: 0.4614
49856/50000 [============================>.] - ETA: 0s - loss: 1.5147 - acc: 0.4615
49920/50000 [============================>.] - ETA: 0s - loss: 1.5144 - acc: 0.4617
49984/50000 [============================>.] - ETA: 0s - loss: 1.5141 - acc: 0.4617
50000/50000 [==============================] - 262s 5ms/step - loss: 1.5140 - acc: 0.4618 - val_loss: 1.0715 - val_acc: 0.6195

End of Epoch 1

Beachten Sie, dass Sie in den meisten Fällen einen anderen Testsatz als den Testsatz benötigen. Sie müssen also den Prozentsatz der Trainingsdaten angeben, der als Testsatz verwendet werden soll. In diesem Fall übergeben wir nur die Testdaten, um sicherzustellen, dass die Testdaten zurückgestellt und nicht für das Training verwendet werden. In diesem Beispiel werden wir nur Testdaten haben, um die Dinge einfacher zu halten.

Wir können nun das Modell auswerten und sehen, wie es funktioniert. Rufen Sie einfach model.evaluate() auf:

# Model evaluation
scores = model.evaluate(X_test, y_test, verbose=0)
print("Accuracy: %.2f%%" % (scores[1]*100))

Und hier bekommen wir das Ergebnis:

Accuracy: 83.01%

OK, jetzt ist alles vorbei! Wir haben jetzt die CNN-Bilderkennung trainiert. Nicht schlecht für einen ersten Durchlauf, aber Sie möchten wahrscheinlich mit der Modellstruktur und den Parametern experimentieren, um die beste Leistung zu erzielen.

Praktische Anwendung neuronaler Netze zur Captcha-Erkennung

Theoretische und experimentelle Arbeiten an CNN führen natürlich zu den Möglichkeiten, neuronale Netze zur Lösung praktischer Alltagsprobleme einzusetzen. Die relevanteste Aufgabe im Bereich der Bilderkennung und -klassifizierung ist insbesondere die Aufgabe, Captcha zu lösen – das heute beliebteste Google ReCaptcha v2.

Trotz der Ähnlichkeit mit unserem Beispiel erscheint in der Praxis die Implementierung eines funktionierenden neuronalen Netzes zur Captcha-Lösung aufgrund des sich ständig ändernden Datenbestandes (Bilder im Captcha) als äußerst aufwendig und ineffektiv. Solche häufigen und unvorhersehbaren Aktualisierungen eingehender Daten bringen eine ganze Reihe von Problemen mit sich:

  • die Notwendigkeit, regelmäßig neue Daten zu erheben und zu verarbeiten
  • die Notwendigkeit einer ständigen Überwachung des Prozesses durch eine Person und der Durchführung von Änderungen am Modell während des Prozesses (einschließlich Experimenten mit Parametern)
  • der Bedarf an leistungsstarker Ausrüstung, um das Modell rund um die Uhr zu trainieren
  • usw.

Eine universelle Lösung für das Problem, verschiedene Captchas online zu umgehen

Um Captchas im Dauerbetrieb, mit hoher Geschwindigkeit und zu relativ geringen Kosten zu lösen, sind Online-Dienste zur Erkennung von Captchas sehr gefragt, die dafür echte Nutzer anziehen. Auf dem heimischen Markt ist der Dienst RuCaptcha.com führend, der im Vergleich zu seinen Konkurrenten günstig abschneidet:
hohe Genauigkeit (bis zu 99%) und Entscheidungsgeschwindigkeit (12 Sekunden für normale Text-Captchas und 24 Sekunden für ReCaptcha)
akzeptable Festpreise (der Preis steigt nicht mit steigender Auslastung der Serviceserver): 35 Rubel für 1000 Lösungen von gewöhnlichen Captchas und 160 Rubel für 1000 Lösungen von ReCaptcha
Rückerstattung für seltene erfolglose Anerkennungen
technische Fähigkeit, große Mengen an Captchas zu lösen (mehr als 10.000 pro Minute)
einfache und funktionale API
vorgefertigte Bibliotheken und Codebeispiele für verschiedene Programmiersprachen
* ein attraktives Partnerprogramm, das es Entwicklern und Weiterempfehlungen ermöglicht, bis zu 15 % der Kosten der angezogenen Kunden und 10 % des Einkommens der am Service beteiligten Mitarbeiter zu erhalten.

Eventuelle Fragen zum Betrieb des Dienstes werden vom Support über das Ticketsystem umgehend geklärt.

Fazit

Nun, da Sie Ihr erstes Bilderkennungsnetzwerk in Keras implementiert haben, ist es eine gute Idee, mit dem Modell zu spielen und zu sehen, wie sich die Änderung seiner Parameter auf die Leistung auswirkt.

Dadurch erhalten Sie ein intuitives Verständnis der optimalen Werte für verschiedene Modellparameter. Sie sollten auch die verschiedenen Optionen und Hyperparameter erkunden, während Sie an Ihrem Modell arbeiten. Sobald Sie sich gründlich damit vertraut gemacht haben, können Sie versuchen, Ihren eigenen Bildklassifizierer für einen anderen Datensatz zu implementieren.

Für alltägliche praktische Arbeitsaufgaben, wie die Captcha-Erkennung, ist der Aufbau und das Training eines neuronalen Netzes kaum eine flexible und effektive Lösung. Wesentlich schneller, günstiger und bequemer ist es, hierfür den Online-Dienst RuCaptcha.com zu nutzen.

Рекомендуємо хостинг TIMEWEB
Рекомендуємо хостинг TIMEWEB
Stabiles Hosting des sozialen Netzwerks EVILEG. Wir empfehlen VDS-Hosting für Django-Projekte.

Magst du es? In sozialen Netzwerken teilen!

Vladimir Sergeevich
  • 14. Mai 2020 04:37

Собственно, а что исходников то нет?

Evgenii Legotckoi
  • 14. Mai 2020 04:51
  • (bearbeitet)

Большая кнопка GITHUB РЕПОЗИТОРИЙ ни о чём не говорит?

Окей, нашел (возможно глаза привыкают к тому, что на сайтах мелькают объявления и большие яркие кнопки автоматически игнорируются). Но не нашел данные на которых обучалась нейросеть. Без них повторить "это" я все равно не смогу ведь...

хех... непривычно, что практически всё является полезным контентом? Самому непривычно... надеюсь, что протяну год в таком режиме, чтобы в конце сделать выводы - "может ли бесплатный ресурс жить без рекламных сетей?"

Что касается исходных данных, то извини, тут не помогу, есть причины, почему они не приложены. Ок?

Ок :)

Спасибо за Ваш труд, очень крутой у вас ресурс, особенно нравятся статьи по Django!

Evgenii Legotckoi
  • 27. Mai 2020 01:19

Не тому написали, ну да ладно )) Спасибо за отзыв :D

BG
  • 28. Mai 2020 04:38

будем считать что авторы статьи по django примут на свой счет :D

progammist
  • 5. Juni 2020 11:52
  • (bearbeitet)

Огромное спасибо за метериал, по-больше бы подобных статей (с подробным описанием работы и примерами применения) на тему современных технологий.
Вопрос поразмышлять. На текущий момент реализовано немало технологий в основе которых лежит комп. зрение. Одна из таких - это государственные сканнеры проходящих людей, например в аэропортах. Что лежит в основе такой технологии? как такой объем данных обрабатывается в реальном времени и как входные данные подгоняются под один тип?

R
  • 15. April 2021 11:55

R
  • 15. April 2021 11:56

почему то вместо 50000 обрабатывает по 782 картинки кажду. эпоху

4X_Pro
  • 25. August 2021 09:39
  • (bearbeitet)

"может ли бесплатный ресурс жить без рекламных сетей?"

А в чём проблема-то? Если не жалко тратить пару-тройку сотен рублей на хостинг/VDS в месяц, то любой сайт прекрасно существует без всякой рекламы сколь угодно долго.

Статья очень понравилась! Как раз искал пример, где работа с изображениями с помощью нейросети расписана по шагам для начинающих.

Evgenii Legotckoi
  • 25. August 2021 10:20

Время на развитие, трудозатраты на разработку, ответы на специализированные вопросы и т.д. вы видимо в расчёт не берёте.

4X_Pro
  • 25. August 2021 12:02

Естественно, поскольку собственное время — ресурс бесплатный, и предполагается, что проект приносит удовольствие (или какие-то другие нематериальные бонусы типа чувства собственной значимости и компетентности).

Evgenii Legotckoi
  • 25. August 2021 15:26

Собственное время не бесплатно, поскольку бесценно и не возобновимо. И не все это понимают, а Вы понимаете?
А поддержание подобного ресурса со временем становится накладным, сколько бы удовольствия он не приносил, это не личный бложик обо всём и ни о чём. Я много раз порывался писать статьи обо всякой ерунде, но останавливал себя, поскольку это не то место, чтобы устраивать здесь свой дневник. Это специализированный ресурс, а подготовка специализированной статьи порой занимает много времени.
И при всём своём желании его развивать, у меня нет желания делать это в ущерб личной жизни. Поэтому со временем такой ресурс либо монетизируется и все силы бросаются на него, либо застывает без новых статей и нового материала, как сейчас.
Так что делайте выводы сами. Но далее обсуждать это не буду, это оффтоп и пустое столкновение мнений.

4X_Pro
  • 26. August 2021 07:32

Понимаю. А ещё понимаю, что не потратить время нельзя. День всё равно пройдёт, и вопрос только в том, на что он будет потрачен: на то, что приносит в жизни удовольствие или нет.
Насчёт застывает — ничего страшного в этом нет (кроме негативного влияния на SEO). Я, например, у себя на сайте в некоторые разделы пишу 2—3 раза в год, когда есть идеи, вдохновение и желание поделиться информацией, и считаю это совершенно нормальным.
Впрочем, похоже, мы и правда не поймём друг друга. Слишком разная система жизненных ценностей. Так что оставлю вас в покое.

А что собственно выводит программа, как вывести то что она смогла распознать?

Kommentare

Nur autorisierte Benutzer können Kommentare posten.
Bitte Anmelden oder Registrieren
Letzte Kommentare
ИМ
Игорь Максимов5. Oktober 2024 14:51
Django – Lektion 064. So schreiben Sie eine Python-Markdown-Erweiterung Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
d
dblas55. Juli 2024 18:02
QML - Lektion 016. SQLite-Datenbank und das Arbeiten damit in QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
k
kmssr9. Februar 2024 02:43
Qt Linux - Lektion 001. Autorun Qt-Anwendung unter Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
Qt WinAPI - Lektion 007. Arbeiten mit ICMP-Ping in Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
EVA
EVA25. Dezember 2023 18:30
Boost - statisches Verknüpfen im CMake-Projekt unter Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
Jetzt im Forum diskutieren
J
JacobFib17. Oktober 2024 10:27
добавить qlineseries в функции Пользователь может получить любые разъяснения по интересующим вопросам, касающимся обработки его персональных данных, обратившись к Оператору с помощью электронной почты https://topdecorpro.ru…
JW
Jhon Wick1. Oktober 2024 22:52
Indian Food Restaurant In Columbus OH| Layla’s Kitchen Indian Restaurant If you're looking for a truly authentic https://www.laylaskitchenrestaurantohio.com/ , Layla’s Kitchen Indian Restaurant is your go-to destination. Located at 6152 Cleveland Ave, Colu…
КГ
Кирилл Гусарев27. September 2024 16:09
Не запускается программа на Qt: точка входа в процедуру не найдена в библиотеке DLL Написал программу на C++ Qt в Qt Creator, сбилдил Release с помощью MinGW 64-bit, бинарнику напихал dll-ки с помощью windeployqt.exe. При попытке запуска моей сбилженной программы выдаёт три оши…
F
Fynjy22. Juli 2024 11:15
при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …

Folgen Sie uns in sozialen Netzwerken