Ist es möglich, Bilder variabler Größe als Eingabe für ein Faltungsnetzwerk zu geben?
17
Können wir Bilder mit variabler Größe als Eingabe für die Objekterkennung in ein Faltungsnetzwerk geben? Wenn möglich, wie können wir das tun?
Wenn wir jedoch versuchen, das Bild zuzuschneiden, verlieren wir einen Teil des Bildes, und wenn wir versuchen, die Größe zu ändern, geht die Klarheit des Bildes verloren. Bedeutet dies, dass die Verwendung der inhärenten Netzwerkeigenschaften am besten ist, wenn die Bildschärfe im Vordergrund steht?
Es gibt verschiedene Möglichkeiten, dies zu tun. Die meisten davon wurden bereits in einer Reihe von Posts über StackOverflow, Quora und andere Content-Websites behandelt.
Zusammenfassend lässt sich sagen, dass die meisten der aufgeführten Techniken in zwei Klassen von Lösungen eingeteilt werden können, nämlich
Transformationen
Inhärente Netzwerkeigenschaft
In Transformationen kann man Techniken wie nachschlagen
Ändern Sie die Größe , die einfachste aller genannten Techniken
Zuschneiden , das als Schiebefenster oder einmaliges Zuschneiden mit Informationsverlust durchgeführt werden kann
Man kann sich auch Netzwerke ansehen, die die inhärente Eigenschaft haben, aufgrund des Schichtverhaltens, das das Netzwerk aufbaut, immun gegen die Größe der Eingabe zu sein. Beispiele hierfür sind:
Vollfaltungsnetzwerke (FCN) , bei denen die Eingabegröße überhaupt nicht eingeschränkt ist, da die Faltung auf jeder Schicht nach der Beschreibung der Kernel- und Schrittgrößen geeignete Dimensionsausgaben gemäß den entsprechenden Eingaben erzeugen kann.
Spatial Pyramid Pooling (SPP) , FCNs haben keine vollständig verbundene dichte Schicht und sind daher unabhängig von der Bildgröße. Wenn Sie jedoch eine dichte Schicht ohne Berücksichtigung von Eingabetransformationen verwenden möchten, gibt es ein interessantes Papier , in dem die Schicht in erklärt wird ein tiefes Lernnetzwerk.
Das klingt theoretisch in Ordnung, funktioniert aber bei Tensorflow nicht. Hat jemand irgendwelche Implementierungen dafür?
Hossein
1
@Hossein Ich bin auch auf einige Probleme bei der praktischen Implementierung gestoßen, aber ich habe heute ein CNN mit variabler Größe in Tensorflow Keras 2.x mit einigen Einschränkungen. Ich habe in meiner Antwort einen Überblick über den Ansatz in Bezug auf einige praktische Details veröffentlicht. Viel Glück!
J Trana
4
Die Faltungsschichten und Poolschichten selbst sind unabhängig von den Eingabedimensionen. Die Ausgabe der Faltungsschichten hat jedoch unterschiedliche räumliche Größen für Bilder unterschiedlicher Größe, und dies verursacht ein Problem, wenn wir danach eine vollständig verbundene Ebene haben (da unsere vollständig verbundene Ebene eine Eingabe mit fester Größe erfordert). Hierfür gibt es mehrere Lösungen:
1. Globales Pooling: Vermeiden Sie vollständig verbundene Layer am Ende der Faltungs-Layer und verwenden Sie stattdessen Pooling (z. B. Global Average Pooling), um Ihre Feature-Maps von einer Form von (N, H, W, C) (vor dem globalen Pool) zu reduzieren ) zu formen (N, 1,1, C) (nach globalem Pool), wobei:
N = Anzahl der Minibatch-Proben
H = räumliche Höhe der Merkmalskarte
W = räumliche Breite der Merkmalskarte
C = Anzahl der Merkmalskarten (Kanäle)
As Wie zu sehen ist, ist die Ausgabedimensionalität (N * C) nun unabhängig von der räumlichen Größe (H, W) der Merkmalskarten. Im Falle einer Klassifizierung können Sie dann eine vollständig verbundene Ebene verwenden, um die Protokolle für Ihre Klassen abzurufen.
2. Pooling mit variabler Größe:Verwenden Sie Pooling-Regionen mit variabler Größe, um dieselbe Feature-Map-Größe für verschiedene Eingabegrößen zu erhalten.
3. Zuschneiden / Ändern der Größe / Auffüllen von Eingabebildern: Sie können versuchen, Ihre Eingabebilder neu zu skalieren / zuzuschneiden / aufzufüllen , damit alle dieselbe Form haben.
Im Zusammenhang mit dem Transferlernen möchten Sie möglicherweise Eingaben unterschiedlicher Größe als die ursprünglichen Eingaben verwenden, mit denen das Modell trainiert wurde. Hier sind einige Optionen, um dies zu tun:
4. Neue vollständig verbundene Ebenen erstellen: Sie können die ursprünglichen vollständig verbundenen Ebenen vollständig entfernen und eine neue vollständig verbundene Ebene mit der erforderlichen Dimensionalität initialisieren und von Grund auf neu trainieren.
5. Behandeln Sie die vollständig verbundene Ebene als Faltung: Normalerweise formen wir die Feature-Maps von (N, H, W, C) nach (N, H * W * C) um, bevor wir sie der vollständig verbundenen Ebene zuführen. Sie können die vollständig verbundene Schicht aber auch als Faltung mit einem Empfangsfeld von (H, W) behandeln. Dann können Sie diesen Kernel einfach mit Ihren Feature-Maps zusammenfassen, unabhängig von ihrer Größe (verwenden Sie bei Bedarf keine Auffüllung) [http://cs231n.github.io/transfer-learning/ ].
Ich musste dieses Problem heute lösen, also dachte ich, ich würde teilen, was ich fand, dass es funktionierte. Ich habe festgestellt, dass es im Web einige Antworten und Leckerbissen gab, die "theoretisch funktionieren könnten", aber weniger aus einem praktischen "So setzen Sie dies konkret um".
Um dies mit Tensorflow Keras zu implementieren, musste ich Folgendes tun. Vielleicht kann jemand anderes feststellen, dass einige davon modifiziert, entspannt oder fallengelassen werden können.
Stellen Sie die Eingabe des Netzwerks so ein, dass eine Eingabe mit variabler Größe möglich ist, indem Sie "Keine" als Platzhalterdimension für die Eingabeform verwenden. Siehe Francois Chollets Antwort hier .
Verwenden Sie Faltungsschichten nur, bis eine globale Pooloperation ausgeführt wurde (z. B. GlobalMaxPooling2D). Dann können dichte Schichten usw. verwendet werden, da die Größe jetzt festgelegt ist.
Verwenden Sie nur eine Stapelgröße von 1. Dies vermeidet den Umgang mit gemischten Größen innerhalb einer Charge.
Schreiben Sie eine kleine benutzerdefinierte Sequenz, die Stapel der Größe 1 aus der Liste der Eingaben erstellt. Ich habe dies getan, um zu vermeiden, dass in einem einzelnen Numpy-Array unterschiedliche Größen verwendet werden.
Verwenden Sie Model.fit_generator in Ihrer benutzerdefinierten Sequenz für Training und Validierung. (vs Model.fit)
Aus irgendeinem Grund ist Model.predict_generator auch bei Verwendung der obigen Sequenz aufgetaucht. Ich musste bei einzelnen Eingaben auf Model.predict zurückgreifen.
Beachten Sie, dass sich Aufrufe von Model.predict über die Leistung beschwert haben - was angesichts der Ineffizienz der Lösung nicht überraschend ist -, aber es funktioniert!
Ja, wählen Sie einfach ein geeignetes Backbone-Netzwerk aus, das nicht von der Größe des Eingabebilds abhängt, um einen genauen Wert zu erhalten. Die meisten Netzwerke erfüllen diese Kriterien.
Sie liegen nicht falsch, aber Ihre Antwort ist nicht sehr informativ. Wie wäre es, wenn Sie sie erweitern, um zu erklären, warum die meisten modernen CNN mit Bildern variabler Größe arbeiten können? Was sind auch die Grenzen dieser Variabilität (versuchen Sie beispielsweise nicht, Bilder unterschiedlicher Größe in demselben Mini-Batch zu mischen ...)? Die meisten Leute, die entweder von altmodischen MLPs (Eingabelänge ist fest) oder altmodischen CNNs (AlexNet & VGG-1X) mit ihren nervigen FlattenSchichten kommen, verstehen nicht, wie die modernen CNNs im Prinzip Bilder jeder Größe aufnehmen können.
Die Faltungsschichten und Poolschichten selbst sind unabhängig von den Eingabedimensionen. Die Ausgabe der Faltungsschichten hat jedoch unterschiedliche räumliche Größen für Bilder unterschiedlicher Größe, und dies verursacht ein Problem, wenn wir danach eine vollständig verbundene Ebene haben (da unsere vollständig verbundene Ebene eine Eingabe mit fester Größe erfordert). Hierfür gibt es mehrere Lösungen:
1. Globales Pooling: Vermeiden Sie vollständig verbundene Layer am Ende der Faltungs-Layer und verwenden Sie stattdessen Pooling (z. B. Global Average Pooling), um Ihre Feature-Maps von einer Form von (N, H, W, C) (vor dem globalen Pool) zu reduzieren ) zu formen (N, 1,1, C) (nach globalem Pool), wobei:
N = Anzahl der Minibatch-Proben
H = räumliche Höhe der Merkmalskarte
W = räumliche Breite der Merkmalskarte
C = Anzahl der Merkmalskarten (Kanäle)
As Wie zu sehen ist, ist die Ausgabedimensionalität (N * C) nun unabhängig von der räumlichen Größe (H, W) der Merkmalskarten. Im Falle einer Klassifizierung können Sie dann eine vollständig verbundene Ebene verwenden, um die Protokolle für Ihre Klassen abzurufen.
2. Pooling mit variabler Größe:Verwenden Sie Pooling-Regionen mit variabler Größe, um dieselbe Feature-Map-Größe für verschiedene Eingabegrößen zu erhalten.
3. Zuschneiden / Ändern der Größe / Auffüllen von Eingabebildern: Sie können versuchen, Ihre Eingabebilder neu zu skalieren / zuzuschneiden / aufzufüllen , damit alle dieselbe Form haben.
Im Zusammenhang mit dem Transferlernen möchten Sie möglicherweise Eingaben unterschiedlicher Größe als die ursprünglichen Eingaben verwenden, mit denen das Modell trainiert wurde. Hier sind einige Optionen, um dies zu tun:
4. Neue vollständig verbundene Ebenen erstellen: Sie können die ursprünglichen vollständig verbundenen Ebenen vollständig entfernen und eine neue vollständig verbundene Ebene mit der erforderlichen Dimensionalität initialisieren und von Grund auf neu trainieren.
5. Behandeln Sie die vollständig verbundene Ebene als Faltung: Normalerweise formen wir die Feature-Maps von (N, H, W, C) nach (N, H * W * C) um, bevor wir sie der vollständig verbundenen Ebene zuführen. Sie können die vollständig verbundene Schicht aber auch als Faltung mit einem Empfangsfeld von (H, W) behandeln. Dann können Sie diesen Kernel einfach mit Ihren Feature-Maps zusammenfassen, unabhängig von ihrer Größe (verwenden Sie bei Bedarf keine Auffüllung) [http://cs231n.github.io/transfer-learning/ ].
quelle
Ich musste dieses Problem heute lösen, also dachte ich, ich würde teilen, was ich fand, dass es funktionierte. Ich habe festgestellt, dass es im Web einige Antworten und Leckerbissen gab, die "theoretisch funktionieren könnten", aber weniger aus einem praktischen "So setzen Sie dies konkret um".
Um dies mit Tensorflow Keras zu implementieren, musste ich Folgendes tun. Vielleicht kann jemand anderes feststellen, dass einige davon modifiziert, entspannt oder fallengelassen werden können.
Beachten Sie, dass sich Aufrufe von Model.predict über die Leistung beschwert haben - was angesichts der Ineffizienz der Lösung nicht überraschend ist -, aber es funktioniert!
quelle
Ja, wählen Sie einfach ein geeignetes Backbone-Netzwerk aus, das nicht von der Größe des Eingabebilds abhängt, um einen genauen Wert zu erhalten. Die meisten Netzwerke erfüllen diese Kriterien.
quelle
Flatten
Schichten kommen, verstehen nicht, wie die modernen CNNs im Prinzip Bilder jeder Größe aufnehmen können.