In einer bestimmten Aufgabe wollte ich die Merkmale in Y-Richtung erhöhen und gleichzeitig die Merkmale in X-Richtung reduzieren. Zum Beispiel möchte ich mit conv / deconv ein Bild der Größe (100, 100) bis (50, 200) erstellen. Es gibt ungefähr zwei Möglichkeiten, dies zu lösen.
Ich möchte die erste Methode vermeiden, da sie eine zweischichtige Struktur hat. Aus diesem Grund haben wir eine Methode zum Strecken und Konvieren untersucht und implementiert.
Ich konnte mir jedoch keine gute Implementierungsmethode vorstellen und verwendete functions.deconvolution_2d
.
Ich möchte es wenn möglich intelligenter implementieren.
Durch die Verwendung der Faltung ist es möglich, eine kleinere Anzahl von Merkmalen abzubilden, während die Positionsinformationen beibehalten werden.
x = numpy.random.rand(1, 1, 100, 100).astype(numpy.float32)
shape = chainer.links.Convolution2D(1, 1, ksize=(4, 1), stride=(2, 1), pad=(1, 0))(x).shape
# shape: (1, 1, 50, 100)
Durch die Verwendung der Entfaltung ist es möglich, eine größere Anzahl von Merkmalen abzubilden, während die Positionsinformationen beibehalten werden.
x = numpy.random.rand(1, 1, 100, 100).astype(numpy.float32)
shape = chainer.links.Deconvolution2D(1, 1, ksize=(1, 4), stride=(1, 2), pad=(0, 1))(x).shape
# shape: (1, 1, 100, 200)
Es gibt jedoch wahrscheinlich keinen Layer, der einer kleinen Anzahl von Features in einer Dimension und einer großen Anzahl von Features in einer anderen Dimension zugeordnet ist.
conv→deconv/deconv→conv Dies ist die einfachste Implementierung, aber ich möchte sie vermeiden, da sie eine zweischichtige Struktur aufweist und der Gradient wahrscheinlich verschwindet.
conv->deconv
x = numpy.random.rand(1, 1, 100, 100).astype(numpy.float32)
x = chainer.links.Convolution2D(1, 1, ksize=(4, 1), stride=(2, 1), pad=(1, 0))(x)
x = chainer.links.Deconvolution2D(1, 1, ksize=(1, 4), stride=(1, 2), pad=(0, 1))(x)
# x.shape: (1, 1, 50, 200)
deconv->conv
x = numpy.random.rand(1, 1, 100, 100).astype(numpy.float32)
x = chainer.links.Deconvolution2D(1, 1, ksize=(1, 4), stride=(1, 2), pad=(0, 1))(x)
x = chainer.links.Convolution2D(1, 1, ksize=(4, 1), stride=(2, 1), pad=(1, 0))(x)
# x.shape: (1, 1, 50, 200)
Ich habe über zwei Dinge nachgedacht. Zunächst 1.
Nachdem Sie mit functions.unpooling_2d
gedehnt haben, reduzieren Sie es mit conv.
unpooling->conv
x = numpy.random.rand(1, 1, 100, 100).astype(numpy.float32)
x = chainer.functions.unpooling_2d(x, ksize=(1, 2))
x = chainer.links.Convolution2D(1, 1, ksize=(4, 4), stride=(2, 1), pad=(1, 2))(x)
# x.shape: (1, 1, 50, 200)
Dann das 2.
Nachdem Sie mit functions.deconvolution_2d
gedehnt haben, reduzieren Sie es mit conv.
Es fühlt sich an, als würde man eine Maske wie 1010101010 herstellen ... und sie mit Dekonv dehnen.
upsample->conv
x = numpy.random.rand(1, 1, 100, 100).astype(numpy.float32)
x = chainer.functions.deconvolution_2d(x, W=numpy.array([0, 1, 0], numpy.float32).reshape(1, 1, 1, 3), stride=(1, 2))
x = chainer.links.Convolution2D(1, 1, ksize=(4, 4), stride=(2, 1), pad=(1, 1))(x)
# x.shape: (1, 1, 50, 200)
Welches ist besser?
upsample-> conv
...Erstens beabsichtige ich, es anzuwenden, wenn 3D-Conv mit links.ConvolutionND
anstelle von 2D durchgeführt wird, aber ich habe festgestellt, dass es keine functions.unpooling_nd
gibt. Was soll ich machen.
Recommended Posts