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.
Собственно, а что исходников то нет?
Большая кнопка GITHUB РЕПОЗИТОРИЙ ни о чём не говорит?
Окей, нашел (возможно глаза привыкают к тому, что на сайтах мелькают объявления и большие яркие кнопки автоматически игнорируются). Но не нашел данные на которых обучалась нейросеть. Без них повторить "это" я все равно не смогу ведь...
хех... непривычно, что практически всё является полезным контентом? Самому непривычно... надеюсь, что протяну год в таком режиме, чтобы в конце сделать выводы - "может ли бесплатный ресурс жить без рекламных сетей?"
Что касается исходных данных, то извини, тут не помогу, есть причины, почему они не приложены. Ок?
Ок :)
Спасибо за Ваш труд, очень крутой у вас ресурс, особенно нравятся статьи по Django!
Не тому написали, ну да ладно )) Спасибо за отзыв :D
будем считать что авторы статьи по django примут на свой счет :D
Огромное спасибо за метериал, по-больше бы подобных статей (с подробным описанием работы и примерами применения) на тему современных технологий.
Вопрос поразмышлять. На текущий момент реализовано немало технологий в основе которых лежит комп. зрение. Одна из таких - это государственные сканнеры проходящих людей, например в аэропортах. Что лежит в основе такой технологии? как такой объем данных обрабатывается в реальном времени и как входные данные подгоняются под один тип?
почему то вместо 50000 обрабатывает по 782 картинки кажду. эпоху
А в чём проблема-то? Если не жалко тратить пару-тройку сотен рублей на хостинг/VDS в месяц, то любой сайт прекрасно существует без всякой рекламы сколь угодно долго.
Статья очень понравилась! Как раз искал пример, где работа с изображениями с помощью нейросети расписана по шагам для начинающих.
Время на развитие, трудозатраты на разработку, ответы на специализированные вопросы и т.д. вы видимо в расчёт не берёте.
Естественно, поскольку собственное время — ресурс бесплатный, и предполагается, что проект приносит удовольствие (или какие-то другие нематериальные бонусы типа чувства собственной значимости и компетентности).
Собственное время не бесплатно, поскольку бесценно и не возобновимо. И не все это понимают, а Вы понимаете?
А поддержание подобного ресурса со временем становится накладным, сколько бы удовольствия он не приносил, это не личный бложик обо всём и ни о чём. Я много раз порывался писать статьи обо всякой ерунде, но останавливал себя, поскольку это не то место, чтобы устраивать здесь свой дневник. Это специализированный ресурс, а подготовка специализированной статьи порой занимает много времени.
И при всём своём желании его развивать, у меня нет желания делать это в ущерб личной жизни. Поэтому со временем такой ресурс либо монетизируется и все силы бросаются на него, либо застывает без новых статей и нового материала, как сейчас.
Так что делайте выводы сами. Но далее обсуждать это не буду, это оффтоп и пустое столкновение мнений.
Понимаю. А ещё понимаю, что не потратить время нельзя. День всё равно пройдёт, и вопрос только в том, на что он будет потрачен: на то, что приносит в жизни удовольствие или нет.
Насчёт застывает — ничего страшного в этом нет (кроме негативного влияния на SEO). Я, например, у себя на сайте в некоторые разделы пишу 2—3 раза в год, когда есть идеи, вдохновение и желание поделиться информацией, и считаю это совершенно нормальным.
Впрочем, похоже, мы и правда не поймём друг друга. Слишком разная система жизненных ценностей. Так что оставлю вас в покое.
А что собственно выводит программа, как вывести то что она смогла распознать?