Si vous voulez porter le modèle entraîné de Pytorch torchvision.models.googlenet vers Keras, vous pouvez être curieux.
Quel est le ceil_mode de MaxPool2d?
En regardant la documentation, il dit: "Si True, utilisez ceil (arrondi vers le haut) au lieu de floor (arrondi vers le haut) pour calculer la forme de sortie."
torch.nn — PyTorch master documentation
ceil_mode – when True, will use ceil instead of floor to compute the output shape
Ci-dessous, MaxPool2D, qui apparaît pour la première fois sur ** torchvision.models.googlenet **.
#L'entrée est(112, 112, 64)
MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=True)
Lorsque je calcule la taille de sortie, ** 55,5 **
output\_shape = \frac{input\_shape + 2 \times padding - kernel\_size}{stride} + 1 \\
= \frac{112 + 2 \times 0 - 3}{2} + 1 = 55.5
En regardant la taille de sortie réelle avec le résumé de la torche, c'est ** (ch = 64, 56, 56) **, donc il semble certainement être arrondi (ceil) après la virgule décimale.
MaxPool2d-4 [-1, 64, 56, 56]
Insérez les exemples de données suivants de taille (10,10) dans MaxPool2d de kernel = (3,3), stride = (2,2) et voyez le résultat.
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)
#Taille de sortie(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
Tronquer après la virgule décimale, 5,5 → 5
padding = 0
>>> nn.MaxPool2d((3,3), stride=2, padding=0, ceil_mode=False)(x)
#Taille de sortie(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
Tronquer après la virgule décimale, 4,5 → 4
ceil_mode = True padding = 1
>>> nn.MaxPool2d((3,3), stride=2, padding=1, ceil_mode=True)(x)
#Taille de sortie(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
Arrondir après la virgule décimale, 5,5 → 6
padding = 0
>>> nn.MaxPool2d((3,3), stride=2, padding=0, ceil_mode=True)(x)
#Taille de sortie(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
Arrondir après la virgule décimale, 4,5 → 5
Les tailles de sortie suivantes sont toutes (5, 5), mais quelle est la différence?
padding=1, ceil_mode=False
padding=0, ceil_mode=True
Puisqu'il n'y a pas de remplissage, la mise en commun est effectuée à partir du coin supérieur gauche. En arrondissant la forme de sortie, le résultat est le même que le remplissage uniquement à droite et en bas.
Insérez les exemples de données suivants de taille (10,10) dans MaxPool2d de kernel = (3,3), stride = (2,2) et voyez le résultat. MaxPooling2D de Keras n'a pas de paramètres de type ceil_mode.
Il semble que Keras tronque toujours le résultat du calcul de la forme de sortie après le point décimal (** ceil_mode = False ** dans Pytorch).
Comme avec Pytorch, générez des données 10x10.
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 Même sortie que ** padding = 1, ceil_mode = False ** sur 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)
#Taille de sortie(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 Même sortie que ** padding = 0, ceil_mode = False ** sur 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)
#Taille de sortie(4, 4)
[[[[23. 25. 27. 29.]
[43. 45. 47. 49.]
[63. 65. 67. 69.]
[83. 85. 87. 89.]]]]
Lorsque ZeroPadding2D est défini comme suit, le remplissage zéro est effectué verticalement et horizontalement.
ZeroPadding2D((1,1))(x)
Il est également possible de modifier les paramètres de remplissage pour le haut et le bas, la gauche et la droite, comme indiqué ci-dessous. (Le remplissage nul n'est appliqué qu'en bas et à droite)
ZeroPadding2D(((0,1), (0,1)))(x)
En appliquant un remplissage nul uniquement en bas et à droite, nous avons pu obtenir le même résultat que ceil_mode = True.
>>> 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)
#Taille de sortie(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.]]]]