Dies ist ein Thema, das häufig mit maschinellem Lernen zusammenhängt, aber ich möchte Schwarzweißfotos kolorieren. Ich habe den Code auch auf GitHub gestellt. [GitHub]
Als ich neulich auf die Reliquien meines Vaters zurückblickte, sah ich plötzlich ein altes Schwarzweißfoto. Ich habe es so gelassen, wie es war, als ich starb, aber jetzt denke ich, dass es gefärbt werden kann. Es ist eher ein persönliches Hobby-Blog als ein technisches Blog. Darüber hinaus gibt es Blogs und Bücher von Personen, auf die beim Studium von GAN Bezug genommen wird. Der Artikel dieser Person ist sehr lehrreich und dieser Artikel enthält auch einige Inhalte. Ich werde unten einen Link posten, also schauen Sie bitte.
[Referenz-URL] Shikoan's ML Blog Lernen Sie aus der Mosaikentfernung und dem neuesten Deep Learning
GAN Der Diskriminator ist in den Generator integriert, und beide werden parallel gelernt. Es ist ein Bild des Hinzufügens einer dynamischen Verlustfunktion unter Verwendung des vorhergesagten Werts von Diskriminator zu Generatorverlust. Es gibt verschiedene Arten von GAN, und die Unterteilung variiert je nach Definition. Es gibt jedoch die folgenden Unterteilungen.
Art | Überblick |
---|---|
Conditional GAN | Es gibt eine Beziehung zwischen dem Generator-Eingang und -Ausgang |
Non-Conditional GAN | Generatoreingang und -ausgang sind nicht miteinander verbunden |
Diesmal ist pix2pix ein typisches bedingtes GAN (CGAN). DCGAN, das häufig in GAN-Tutorials verwendet wird, generiert eine Ausgabe aus Rauschdaten, sodass es zu einem nicht bedingten GAN wird. Da pix2pix CGAN ist, werden Eingabeinformationen sehr wichtig. In DCGAN wird beispielsweise mit Adversarial Loss, der in Bezug auf Discriminator angezeigt wird, weiter gelernt. Bei pix2pix wird jedoch zusätzlich zu Adversarial Loss auch der Unterschied zwischen gefälschtem Bild und realem Bild (z. B. L1-Verlust oder MSE) verwendet. Das Lernen schreitet voran. Auf diese Weise schreitet das Lernen schneller voran als bei anderen GANs, und die Ergebnisse sind stabiler. Im Gegensatz dazu ist bei einer Lernmethode, bei der nur der L1-Verlust verwendet wird, die Ausgabe insgesamt vage oder das Ganze mit durchschnittlichen Pixeln verfestigt, um den Verlust zu verringern. Es fühlt sich in der Regel schlampig an, und durch Hinzufügen von Adversarial Loss wird der L1-Verlust in der Regel gelernt, sodass ein realistischeres Bild ausgegeben werden kann, selbst wenn es ziemlich groß ist. Das Prinzip, dass es einen Kompromiss zwischen wahrgenommener Qualität und Verzerrung gibt, ist einer der sehr wichtigen Faktoren bei der Betrachtung von GAN.
Referenz: The Perception-Distortion Tradeoff (2017) [arXiv]
PatchGAN Das Folgende ist das Originalpapier von pix2pix, aber ich denke, es ist besser, hier auf Details zu PatchGAN zu verweisen.
Image-to-Image Translation with Conditional Adversarial Networks (2016) [arXiv]
Wenn in PatchGAN Discriminator die Richtigkeit eines Bildes beurteilt, wird es in mehrere Bereiche unterteilt und in jedem Bereich wird die Richtigkeit beurteilt.
Das Teilen des Bereichs bedeutet nicht, dass Sie das Bild tatsächlich teilen und es separat in den Diskriminator eintauchen. Theoretisch ist dies der Fall, aber in Bezug auf die Implementierung wird ein Bild in den Diskriminator eingefügt und seine Ausgabe in einen Tensor im zweiten Stock umgewandelt. Zu diesem Zeitpunkt wird der Wert jedes Pixels des Tensors basierend auf der Information des Patch-Bereichs des Eingabebildes abgeleitet, und als Ergebnis liegt der Wert jedes Pixels des Tensors zwischen dem tatsächlichen Wahr oder Falsch (1 oder 0). Patch GAN wird realisiert, indem der Verlust von genommen wird. Ich denke nicht, dass es einfach ist, es in Worten zu erklären, deshalb werde ich oben ein Beispiel mit der französischen Flagge geben.
fig, axes = plt.subplots(1,2)
#Bilder laden
img = cv2.imread('france.jpg')
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = cv2.resize(img, (600, 300)) #Originalgröße-> (300, 600, 3)
axes[0].imshow(img)
axes[0].set_xticks([])
axes[0].set_yticks([])
img = ToTensor()(img) # (300, 600, 3) -> (3, 300, 600)
img = img.view(1, 3, 300, 600) # (3, 300, 600) -> (1, 3, 300, 600)
img = nn.AvgPool2d(100)(img) # (1, 3, 300, 600) -> (1, 3, 3, 6)
img = nn.Conv2d(3, 1, kernel_size=1)(img) # (1, 3, 3, 6) -> (1, 1, 3, 6)
img = np.squeeze(img.detach().numpy())
axes[1].imshow(img, cmap='gray')
axes[1].set_xticks([])
axes[1].set_yticks([])
[Ergebnis]
Oben wird das Eingabebild in eine Feature-Map mit der Größe (3, 6) eingefügt. Dies ist jedoch nichts anderes als das Komprimieren des gesamten Patch-Bereichs des Originalbilds auf (1, 1). In dem obigen Beispiel wird eine Echtheitsbeurteilung für "3 × 6 = 18" Pixel durchgeführt.
Unet pix2pix verwendet U-net als Generator. U-net, das in der Segmentierung identisch ist, verfügt zusätzlich zur Encoder-Decoder-Struktur über eine Skip-Verbindung, damit die Informationen der Eingabedaten nicht so weit wie möglich verloren gehen. Das Folgende ist die im Experiment verwendete Vorwärtsmethode des Generators, aber Sie können sehen, dass die ursprünglichen Informationen jedes Mal mit "torch.cat" verkettet werden.
def forward(self, x):
x1 = self.enc1(x)
x2 = self.enc2(x1)
x3 = self.enc3(x2)
x4 = self.enc4(x3)
out = self.dec1(x4)
out = self.dec2(torch.cat([out, x3], dim=1))
out = self.dec3(torch.cat([out, x2], dim=1))
out = self.dec4(torch.cat([out, x1], dim=1))
return out
Das folgende U-Net-Bild ist übrigens eine Bildrutsche zum Thema maschinelles Lernen, die von Google kostenlos veröffentlicht wurde und kürzlich auf Twitter erwähnt wurde. [ML Visuals] Es gibt viele schöne Bilder, also schauen Sie bitte.
Google PhotoScan Verwenden Sie MIT-Adobe FiveK-Datensatz als Trainingsdaten. Dies wird häufig in Bildverbesserungspapieren verwendet, und es handelt sich um eine Reihe von unverarbeiteten Bildern und nachbearbeiteten Bildern durch einen professionellen Redakteur. Dieses Mal werde ich dieses verarbeitete Bild verwenden. Bei den verarbeiteten Fotos gibt es viele Fotos mit helleren Farben als bei normalen Farbfotos. Daher dachte ich, dass sie auch für diese Aufgabe geeignet sind. Wenn die Datengröße klein ist, ist die Datenkapazität nicht groß und der Download ist bis zu einem gewissen Grad angemessen. Dies ist ein echtes Schwarzweißfoto, das jedoch mithilfe einer App namens "Google PhotoScan" auf dem iPhone in Daten konvertiert wurde. Diese App wird im Detail veröffentlicht, wenn Sie sie googeln. Sie ist jedoch hervorragend und wandelt sie in hübsche Daten um, ohne in einen Fotoladen zu gehen (und zwar sofort). Das Originalfoto war ziemlich alt und vergilbt, aber als ich es in ein Schwarzweißbild konvertierte, sah es nicht viel anders aus als ein normales Schwarzweißbild.
Das Bild in Fivek und das Bild, das Sie tatsächlich einfärben möchten, sind nicht quadratisch, sondern rechteckig, und die Seitenverhältnisse sind unterschiedlich. Daher habe ich mich für eines der folgenden vier Muster entschieden.
Vorerst habe ich mich dieses Mal für Methode 3 entschieden. In Bezug auf 1 und 4 besteht der Grund für die Annahme darin, dass die Möglichkeit besteht, dass sich die Eigenschaften des Bildes erheblich ändern, und für 2 und 3 dachte ich, dass 3 mehr Informationen enthalten würde. Wenn Sie geradeaus fahren, ist es natürlich die Nummer 5, aber ich mag keine quadratischen Ernten bis zu den Produktionsfotos. Das Ausgabeergebnis wird bei der Nachbearbeitung auf das ursprüngliche Seitenverhältnis zugeschnitten.
Teil 1 lernen
Sie können sehen, wie der Diskriminator allmählich stärker wird, beginnend an der Stelle, an der er in den frühen Stadien zum Amoklauf neigt, und der Verlust des Generators steigt. Was den L1-Verlust betrifft, bin ich mir nicht sicher, ob er abnimmt. (Die Schwierigkeit der GAN-Bewertung besteht darin, dass "L1loss klein = nahe an der realen Farbe" ist.)
Teil 2 lernen In Lernen 1 war der Diskriminator tendenziell stärker, daher habe ich mich entschlossen, zu experimentieren, indem ich die folgenden Punkte geändert habe.
- D,Und Gs gegnerischer Verlust änderte sich von BCE zu Scharnierverlust
-Ändern Sie die Stapelnormalisierung von D in Instanznormalisierung
-Halbieren Sie die Häufigkeit der Gewichtsaktualisierung von D (die Hälfte von G).
In Teil 2 besteht die Änderung von Teil 1 darin, die Verlustfunktion von der in Teil 1 verwendeten binären Kreuzentropie in Scharnierverlust zu ändern. Grob gesagt ist das Ziel, "einen schwachen Verlust zu machen, um zu verhindern, dass ein (D- oder G-) Netzwerk zu stark wird". Das Folgende ist die Kreuzentropie (D-Version) der Eisenplatte.
D:loss = -\sum_{i=1}^{n}\bigl(t_ilogy_i - (1-t_i) log(1-y_i) \bigl)
Kurz gesagt, wenn "Ziel = 1" ist, sollte die Ausgabe so hoch wie möglich sein (da die letzte Schicht Sigmoid ist, ist sie umso näher an 1, je größer sie ist). Wenn "Ziel = 0" ist und Sie trainieren, um die Leistung in negativer Richtung zu erhöhen, ist der Verlust geringer.
Im Gegenteil, für G werden wir trainieren, um die obige Gleichung zu maximieren. Darüber hinaus wird im Fall von G nur das von sich selbst erzeugte gefälschte Bild ausgewertet, so dass der linke Term der obigen Formel verschwindet und einfacher wird.
G:loss = \sum_{i=1}^{n}log\Bigl(1 - D\bigl(G(z_i))\bigl) \Bigl)(Maximieren)\\
= \sum_{i=1}^{n}log\Bigl(D\bigl(G(z_i)) - 1\bigl) \Bigl)(Minimieren)\\
= -\sum_{i=1}^{n}log\Bigl(D\bigl(G(z_i))\bigl) \Bigl) (Man kann auch denken, dass dies minimiert ist)
Das Obige gibt zwei Optimierungsmuster an, aber es scheint, dass es beide Implementierungsmethoden gibt.
Auf der anderen Seite denke ich, dass diese Seite in Bezug auf Scharnierverlust leicht zu verstehen ist. [Referenz] Die Site sagt, dass es nicht oft für etwas anderes als SVM verwendet wird, aber es ist interessant, dass es derzeit in anderen Methoden verwendet wird. In der Kreuzentropie wird das Ziel als (0,1) ausgedrückt, im Scharnier als (-1,1).
t = ±1 \\
Loss = max(0, 1-t*y)
Wenn Sie für die Formel eine kleinere Ausgabe ausgeben, wenn "Ziel = -1", und umgekehrt eine größere Ausgabe ausgeben, wenn "Ziel = 1", ist der Verlust gering. Im Gegensatz zur Kreuzentropie können Sie jedoch auch sehen, dass der Verlust bis zu einem gewissen Grad auf 0 gesenkt wird. Im Fall der Kreuzentropie verschwindet der Verlust niemals, es sei denn, er wird vollständig durch (0,1) vorhergesagt, dies ist jedoch bei Scharnieren nicht der Fall. Dies ist der Grund, warum es als "schwacher Verlust" bezeichnet wird. Die Implementierung von PyTorch ist wie folgt. An den Scharnieren ist es schwierig, die Muster durch D und G zu teilen, daher denke ich, dass es besser ist, sie alle zusammen zu klassifizieren.
# ones:Patch mit allen Werten 1
# zeros:Patch mit allen Werten 0
# Gloss(BCE)
loss = torch.nn.BCEWithLogitsLoss()(d_out_fake, ones)
# Gloss(Hinge)
loss = -1 * torch.mean(d_out_fake)
# Dloss(BCE)
loss_real = torch.nn.BCEWithLogitsLoss()(d_out_real, ones)
loss_fake = torch.nn.BCEWithLogitsLoss()(d_out_fake, zeros)
loss = loss_reak + loss_fake
# Dloss(Hinge)
loss_real = -1 * torch.mean(torch.min(d_out_real-1, zeros))
loss_fake = -1 * torch.mean(torch.min(-d_out_fake-1, zeros))
loss = loss_reak + loss_fake
Instance Normalization Die Instanznormalisierung ist eine Ableitung der Stapelnormalisierung. Der Inhalt einschließlich der Chargennormalisierung ist in den folgenden Artikeln gut organisiert.
[GIF] Erklärung von CNN für Anfänger zur Batch-Normalisierung und ihre Freunde
Die Chargennormalisierung führt eine Standardisierungsverarbeitung zwischen denselben Datenkanälen durch, die in einem Mini-Batch enthalten sind. Die Instanznormalisierung führt jedoch nicht den gesamten Mini-Batch durch, sondern nur die Daten. Der Punkt ist Chargennormalisierung mit Chargengröße 1. Zum Beispiel wird es auch in pix2pix HD verwendet, einem Derivat von pix2pix, aber sein Zweck ist es, es schwierig zu machen, das Lernen durch Unterdrücken des Anstiegs des Gradienten zu konvergieren. Der Hauptzweck besteht darin, D und G auszugleichen, indem dies auf D angewendet wird.
Unten sind die Ergebnisse. Sie können sehen, dass die Konvergenz von Discriminator deutlich langsamer ist als zuvor. Ich habe auch das Gefühl, dass die Abnahme des L1-Verlusts größer ist als zuvor.
Lernen # 3 hat die folgenden Punkte von Lernen 1 geändert.
-Grundsätzlich folgen Sie dem Lernen 1
-Richten Sie die Lernrate an der Originalarbeit aus.(1e-4 -> 2e-4)
-Die Anpassung der Lernrate mit dem Scheduler wurde entfernt
-Die Bildgröße wurde von 320 auf 256 geändert (gemäß dem Papier).
-Die Anzahl der PatchGAN-Bereiche wurde von 10x10 auf 4x4 geändert
-Unschärfe in Augmentation im Zug entfernt
Das Ergebnis war jedoch fast das gleiche wie 1.
Wenn wir uns die bisherigen Ergebnisse ansehen, können wir die Tendenz erkennen, dass "natürliche Landschaften relativ gefärbt werden können, aber die Menschen überhaupt nicht arbeiten". Dies ist für den ursprünglichen Zweck bedeutungslos, daher habe ich beschlossen, die Daten erneut selbst zu erfassen. Wie man Daten sammelt, habe ich im vorherigen Qiita-Artikel geschrieben, aber BingImageSearch verwendet. [Qiita-Artikel-Link] Obwohl es auf Teil 2 basiert, wurde es außerdem leicht manipuliert. Da sich die Anzahl der Daten verdreifacht hat (mehr als 13.000), haben wir 200 Epochen auf 100 Epochen reduziert.
#Änderungen vom Lernen 1
-Trainingsdaten hinzufügen (Fivek)-> fivek+Menschen Bild)
-200 Epochennummern-> 97
- D,Der gegnerische Verlust wurde von BCE in Scharnierverlust geändert(Mit Teil 2)
-Ändern Sie die Stapelnormalisierung von D in Instanznormalisierung(Mit Teil 2)
-Halbieren Sie die Häufigkeit der Gewichtsaktualisierung von D.(Mit Teil 2)
-Die Anpassung der Lernrate mit dem Scheduler wurde entfernt(Mit Teil 3)
-Lernrate 1e-4->2e-Geändert zu 4 (mit Teil 3)
#Der Grund, warum die Anzahl der Pixel in der Ausgabe etwas unbefriedigend war, ist möglicherweise nicht wirklich gut
-Bildgröße ändern(320->352) (<-new)
-Zusammen mit den oben genannten die Anzahl der PatchGAN-Bereiche(10,10)->(11,11)ändern (<-new)
Unten sind die Ergebnisse. Im Vergleich zu Teil 2 scheint die große vertikale Bewegung in der Endphase die Hauptursache für das Entfernen des Schedulers zu sein.
Durch verschiedene Versuche und Irrtümer können Landschaftsbilder mit einer beträchtlichen Geschwindigkeit ohne Unbehagen gefärbt werden, während Porträtbilder und auffällige Kontrastbilder (z. B. Menschen, Kleidung, Blumen, künstliche Objekte usw.) nicht so gefärbt sind. Ich fand eine Tendenz, nicht fortzufahren.
(Links: falsches Bild Rechts: echtes Bild) Im Gegenteil, ich fühle, dass sich das mysteriös anfühlt. Es ist interessant anzusehen. Außerdem schien mein Foto für die eigentliche Produktion gut gefärbt zu sein (lacht). .. ..
(Schließlich betrachtet) Obwohl es mein Testbild ist (Foto des Vaters), ist das Ergebnis ungleichmäßiger als die Lern- und Verifizierungsdaten. Wahrscheinlich denke ich, dass es wahrscheinlich überhaupt ein Problem mit der Auflösung gibt. Das obige Bild ist immer noch gut, und selbst wenn andere Schwarzweißbilder in Daten konvertiert werden, kann der Umriss beim Vergrößern gesehen werden, aber die Auflösung ist in kleinen Bereichen ungleichmäßig und das Ergebnis ist enttäuschend. Wenn ich es also ernsthaft tun möchte, werde ich die Superauflösungsaufgabe parallel erledigen. Alternativ kann es erforderlich sein, Maßnahmen wie das Verwischen der Lerndaten zu ergreifen. Ich werde es nächstes Mal tun (geplant).
Recommended Posts