Wenn Sie das von Pytorch trainierte Modell torchvision.models.googlenet nach Keras portieren möchten, sind Sie möglicherweise neugierig.
Was ist der Ceil_Mode von MaxPool2d?
In der Dokumentation heißt es: "Wenn True, verwenden Sie Ceil (Aufrunden) anstelle von Floor (Aufrunden), um die Ausgabeform zu berechnen."
torch.nn — PyTorch master documentation
ceil_mode – when True, will use ceil instead of floor to compute the output shape
Unten ist MaxPool2D, das zuerst auf ** torchvision.models.googlenet ** erscheint.
#Eingabe ist(112, 112, 64)
MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=True)
Wenn ich die Ausgabegröße berechne, ** 55,5 **
output\_shape = \frac{input\_shape + 2 \times padding - kernel\_size}{stride} + 1 \\
= \frac{112 + 2 \times 0 - 3}{2} + 1 = 55.5
Betrachtet man die tatsächliche Ausgabegröße mit Fackelzusammenfassung, so ist sie ** (ch = 64, 56, 56) **, so dass sie nach dem Dezimalpunkt sicherlich aufgerundet (Ceil) zu sein scheint.
MaxPool2d-4 [-1, 64, 56, 56]
Fügen Sie die folgenden Beispieldaten der Größe (10,10) in MaxPool2d von Kernel = (3,3), Schritt = (2,2) ein und sehen Sie das Ergebnis.
import torch
import torch.nn as nn
>>> x = torch.arange(1, 101).view(1, 10, 10).float()
>>> x
tensor([[[ 1., 2., 3., 4., 5., 6., 7., 8., 9., 10.],
[ 11., 12., 13., 14., 15., 16., 17., 18., 19., 20.],
[ 21., 22., 23., 24., 25., 26., 27., 28., 29., 30.],
[ 31., 32., 33., 34., 35., 36., 37., 38., 39., 40.],
[ 41., 42., 43., 44., 45., 46., 47., 48., 49., 50.],
[ 51., 52., 53., 54., 55., 56., 57., 58., 59., 60.],
[ 61., 62., 63., 64., 65., 66., 67., 68., 69., 70.],
[ 71., 72., 73., 74., 75., 76., 77., 78., 79., 80.],
[ 81., 82., 83., 84., 85., 86., 87., 88., 89., 90.],
[ 91., 92., 93., 94., 95., 96., 97., 98., 99., 100.]]])
>>> x.shape
torch.Size([1, 10, 10])
ceil_mode = False padding = 1
>>> nn.MaxPool2d((3,3), stride=2, padding=1, ceil_mode=False)(x)
#Ausgabegröße(5, 5)
tensor([[[ 12., 14., 16., 18., 20.],
[ 32., 34., 36., 38., 40.],
[ 52., 54., 56., 58., 60.],
[ 72., 74., 76., 78., 80.],
[ 92., 94., 96., 98., 100.]]])
output\_shape = \frac{input\_shape + 2 \times padding - kernel\_size}{stride} + 1 \\
= \frac{10 + 2 \times 1 - 3}{2} + 1 = 5.5
Nach dem Dezimalpunkt abschneiden, 5.5 → 5
padding = 0
>>> nn.MaxPool2d((3,3), stride=2, padding=0, ceil_mode=False)(x)
#Ausgabegröße(4, 4)
tensor([[[23., 25., 27., 29.],
[43., 45., 47., 49.],
[63., 65., 67., 69.],
[83., 85., 87., 89.]]])
output\_shape = \frac{input\_shape + 2 \times padding - kernel\_size}{stride} + 1 \\
= \frac{10 + 2 \times 0 - 3}{2} + 1 = 4.5
Nach dem Dezimalpunkt abschneiden, 4.5 → 4
ceil_mode = True padding = 1
>>> nn.MaxPool2d((3,3), stride=2, padding=1, ceil_mode=True)(x)
#Ausgabegröße(6, 6)
tensor([[[ 12., 14., 16., 18., 20., 20.],
[ 32., 34., 36., 38., 40., 40.],
[ 52., 54., 56., 58., 60., 60.],
[ 72., 74., 76., 78., 80., 80.],
[ 92., 94., 96., 98., 100., 100.],
[ 92., 94., 96., 98., 100., 100.]]])
output\_shape = \frac{input\_shape + 2 \times padding - kernel\_size}{stride} + 1 \\
= \frac{10 + 2 \times 1 - 3}{2} + 1 = 5.5
Nach dem Dezimalpunkt aufrunden, 5.5 → 6
padding = 0
>>> nn.MaxPool2d((3,3), stride=2, padding=0, ceil_mode=True)(x)
#Ausgabegröße(5, 5)
tensor([[[ 23., 25., 27., 29., 30.],
[ 43., 45., 47., 49., 50.],
[ 63., 65., 67., 69., 70.],
[ 83., 85., 87., 89., 90.],
[ 93., 95., 97., 99., 100.]]])
output\_shape = \frac{input\_shape + 2 \times padding - kernel\_size}{stride} + 1 \\
= \frac{10 + 2 \times 0 - 3}{2} + 1 = 4.5
Nach dem Dezimalpunkt aufrunden, 4.5 → 5
Die folgenden Ausgabegrößen sind alle (5, 5), aber was ist der Unterschied?
padding=1, ceil_mode=False
padding=0, ceil_mode=True
Da keine Polsterung vorhanden ist, wird das Pooling von oben links durchgeführt. Durch Aufrunden der Ausgabeform entspricht das Ergebnis dem Auffüllen nur der rechten und unteren Form.
Fügen Sie die folgenden Beispieldaten der Größe (10,10) in MaxPool2d von Kernel = (3,3), Schritt = (2,2) ein und sehen Sie das Ergebnis. Keras 'MaxPooling2D hat keine Ceil_Mode-ähnlichen Parameter.
Es scheint, dass Keras das Berechnungsergebnis der Ausgabeform immer nach dem Dezimalpunkt abschneidet (** lid_mode = False ** in Pytorch).
Generieren Sie wie bei Pytorch 10x10 Daten.
from tensorflow.keras.layers import MaxPooling2D
import numpy as np
x = np.arange(1, 101).reshape(1, 10, 10, 1).astype(np.float)
padding=1 Gleiche Ausgabe wie ** padding = 1, lid_mode = False ** auf Pytorch.
>>> out = MaxPooling2D((3,3), strides=(2,2))(ZeroPadding2D((1,1))(x))
>>> out = tf.transpose(out, perm=[0,3,1,2])
>>> with tf.Session() as sess:
>>> out_value = sess.run(out)
>>> print(out_value)
#Ausgabegröße(5, 5)
[[[[ 12. 14. 16. 18. 20.]
[ 32. 34. 36. 38. 40.]
[ 52. 54. 56. 58. 60.]
[ 72. 74. 76. 78. 80.]
[ 92. 94. 96. 98. 100.]]]]
padding=0 Gleiche Ausgabe wie ** padding = 0, lid_mode = False ** auf Pytorch.
>>> out = MaxPooling2D((3,3), strides=(2,2))(x)
>>> out = tf.transpose(out, perm=[0,3,1,2])
>>> with tf.Session() as sess:
>>> out_value = sess.run(out)
>>> print(out_value)
#Ausgabegröße(4, 4)
[[[[23. 25. 27. 29.]
[43. 45. 47. 49.]
[63. 65. 67. 69.]
[83. 85. 87. 89.]]]]
Wenn ZeroPadding2D wie folgt eingestellt ist, wird das Null-Auffüllen vertikal und horizontal durchgeführt.
ZeroPadding2D((1,1))(x)
Es ist auch möglich, die Polstereinstellungen für oben und unten, links und rechts zu ändern, wie unten gezeigt. (Nullpolsterung wird nur unten und rechts angewendet.)
ZeroPadding2D(((0,1), (0,1)))(x)
Durch Anwenden der Null-Auffüllung nur unten und rechts konnten wir die gleiche Ausgabe wie Ceil_Mode = True erzielen.
>>> out = MaxPooling2D((3,3), strides=(2,2))(ZeroPadding2D(((0,1), (0,1)))(x))
>>> out = tf.transpose(out, perm=[0,3,1,2])
>>> with tf.Session() as sess:
>>> out_value = sess.run(out)
>>> print(out_value)
#Ausgabegröße(5, 5)
[[[[ 23. 25. 27. 29. 30.]
[ 43. 45. 47. 49. 50.]
[ 63. 65. 67. 69. 70.]
[ 83. 85. 87. 89. 90.]
[ 93. 95. 97. 99. 100.]]]]