Skip to content

Commit efeed3e

Browse files
authored
Update padding layers (#14)
1 parent 16690b0 commit efeed3e

File tree

6 files changed

+127
-75
lines changed

6 files changed

+127
-75
lines changed

tensorlayerx/backend/ops/mindspore_backend.py

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1287,9 +1287,14 @@ def resize(inputs, output_size, method, antialias):
12871287

12881288
class ZeroPadding1D(Cell):
12891289

1290-
def __init__(self, padding):
1290+
def __init__(self, padding, data_format):
12911291
super(ZeroPadding1D, self).__init__()
1292-
padding = ((0, 0), padding, (0, 0))
1292+
if data_format == 'channels_first':
1293+
padding = ((0, 0), (0, 0), padding)
1294+
elif data_format == 'channels_last':
1295+
padding = ((0, 0), padding, (0, 0))
1296+
else:
1297+
raise ValueError('data_format must be channels_first or channels_last.')
12931298
self.pad = P.Pad(paddings=padding)
12941299

12951300
def construct(self, inputs):
@@ -1300,9 +1305,14 @@ def construct(self, inputs):
13001305

13011306
class ZeroPadding2D(Cell):
13021307

1303-
def __init__(self, padding):
1308+
def __init__(self, padding, data_format):
13041309
super(ZeroPadding2D, self).__init__()
1305-
padding = ((0, 0), padding[0], padding[1], (0, 0))
1310+
if data_format == 'channels_first':
1311+
padding = ((0, 0), (0, 0), padding[0], padding[1])
1312+
elif data_format == 'channels_last':
1313+
padding = ((0, 0), padding[0], padding[1], (0, 0))
1314+
else:
1315+
raise ValueError('data_format must be channels_first or channels_last.')
13061316
self.pad = P.Pad(paddings=padding)
13071317

13081318
def construct(self, inputs):
@@ -1311,9 +1321,14 @@ def construct(self, inputs):
13111321

13121322
class ZeroPadding3D(Cell):
13131323

1314-
def __init__(self, padding):
1324+
def __init__(self, padding, data_format):
13151325
super(ZeroPadding3D, self).__init__()
1316-
padding = ((0, 0), padding[0], padding[1], padding[2], (0, 0))
1326+
if data_format == 'channels_first':
1327+
padding = ((0, 0), (0, 0), padding[0], padding[1], padding[2])
1328+
elif data_format == 'channels_last':
1329+
padding = ((0, 0), padding[0], padding[1], padding[2], (0, 0))
1330+
else:
1331+
raise ValueError('data_format must be channels_first or channels_last.')
13171332
self.pad = P.Pad(paddings=padding)
13181333

13191334
def construct(self, inputs):

tensorlayerx/backend/ops/paddle_backend.py

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1316,34 +1316,64 @@ def resize(inputs, output_size, method, antialias):
13161316
return Resize(output_size, method, antialias)(inputs)
13171317

13181318

1319+
def channels_switching(data_format, dim='2d', padding=None):
1320+
if dim == '1d':
1321+
if data_format == 'channels_first':
1322+
out = 'NCL'
1323+
if data_format == 'channels_last':
1324+
out = 'NLC'
1325+
pads = padding
1326+
if dim == '2d':
1327+
if data_format == 'channels_first':
1328+
out = 'NCHW'
1329+
if data_format == 'channels_last':
1330+
out = 'NHWC'
1331+
pads = [padding[1][0], padding[1][1], padding[0][0], padding[0][1]]
1332+
if dim == '3d':
1333+
if data_format == 'channels_first':
1334+
out = 'NCDHW'
1335+
if data_format == 'channels_last':
1336+
out = 'NDHWC'
1337+
pads = [padding[2][0], padding[2][1],
1338+
padding[1][0], padding[1][1],
1339+
padding[0][0], padding[0][1]]
1340+
return out, pads
1341+
1342+
13191343
class ZeroPadding1D(object):
13201344

1321-
def __init__(self, padding):
1322-
padding = ((0, 0), padding, (0, 0))
1323-
self.pad = Pad(paddings=padding)
1345+
def __init__(self, padding, data_format):
1346+
self.padding = padding
1347+
self.data_format = data_format
13241348

13251349
def __call__(self, inputs):
1326-
return self.pad(inputs)
1350+
data_format, padding = channels_switching(self.data_format, '1d', self.padding)
1351+
out = pd.nn.functional.pad(inputs, padding, mode='constant', value=0.0, data_format=data_format)
1352+
return out
13271353

13281354

13291355
class ZeroPadding2D(object):
13301356

1331-
def __init__(self, padding):
1332-
padding = ((0, 0), padding[0], padding[1], (0, 0))
1333-
self.pad = Pad(paddings=padding)
1357+
def __init__(self, padding, data_format):
1358+
self.padding = padding
1359+
self.data_format = data_format
13341360

13351361
def __call__(self, inputs):
1336-
return self.pad(inputs)
1362+
data_format, padding = channels_switching(self.data_format, '2d', self.padding)
1363+
out = pd.nn.functional.pad(inputs, padding, mode='constant', value=0.0, data_format=data_format)
1364+
return out
13371365

13381366

13391367
class ZeroPadding3D(object):
13401368

1341-
def __init__(self, padding):
1342-
padding = ((0, 0), padding[0], padding[1], padding[2], (0, 0))
1343-
self.pad = Pad(paddings=padding)
1369+
def __init__(self, padding, data_format):
1370+
self.padding = padding
1371+
self.data_format = data_format
13441372

13451373
def __call__(self, inputs):
1346-
return self.pad(inputs)
1374+
data_format, padding = channels_switching(self.data_format, '3d', self.padding)
1375+
out = pd.nn.functional.pad(inputs, padding, mode='constant', value=0.0, data_format=data_format)
1376+
return out
13471377

13481378

13491379
class Sign(object):

tensorlayerx/backend/ops/tensorflow_backend.py

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1497,29 +1497,47 @@ def resize(inputs, output_size, method, antialias):
14971497

14981498
class ZeroPadding1D(object):
14991499

1500-
def __init__(self, padding):
1501-
self.zeropad = tf.keras.layers.ZeroPadding1D(padding=padding)
1500+
def __init__(self, padding, data_format):
1501+
if data_format == 'channels_first':
1502+
padding = ((0, 0), (0, 0), padding)
1503+
elif data_format == 'channels_last':
1504+
padding = ((0, 0), padding, (0, 0))
1505+
else:
1506+
raise ValueError('data_format must be channels_first or channels_last.')
1507+
self.pad = Pad(paddings=padding)
15021508

15031509
def __call__(self, inputs):
1504-
return self.zeropad(inputs)
1510+
return self.pad(inputs)
15051511

15061512

15071513
class ZeroPadding2D(object):
15081514

1509-
def __init__(self, padding):
1510-
self.zeropad = tf.keras.layers.ZeroPadding2D(padding=padding)
1515+
def __init__(self, padding, data_format):
1516+
if data_format == 'channels_first':
1517+
padding = ((0, 0), (0, 0), padding[0], padding[1])
1518+
elif data_format == 'channels_last':
1519+
padding = ((0, 0), padding[0], padding[1], (0, 0))
1520+
else:
1521+
raise ValueError('data_format must be channels_first or channels_last.')
1522+
self.pad = Pad(paddings=padding)
15111523

15121524
def __call__(self, inputs):
1513-
return self.zeropad(inputs)
1525+
return self.pad(inputs)
15141526

15151527

15161528
class ZeroPadding3D(object):
15171529

1518-
def __init__(self, padding):
1519-
self.zeropad = tf.keras.layers.ZeroPadding3D(padding=padding)
1530+
def __init__(self, padding, data_format):
1531+
if data_format == 'channels_first':
1532+
padding = ((0, 0), (0, 0), padding[0], padding[1], padding[2])
1533+
elif data_format == 'channels_last':
1534+
padding = ((0, 0), padding[0], padding[1], padding[2], (0, 0))
1535+
else:
1536+
raise ValueError('data_format must be channels_first or channels_last.')
1537+
self.pad = Pad(paddings=padding)
15201538

15211539
def __call__(self, inputs):
1522-
return self.zeropad(inputs)
1540+
return self.pad(inputs)
15231541

15241542

15251543
class Sign(object):

tensorlayerx/backend/ops/torch_backend.py

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1163,8 +1163,13 @@ def resize(inputs, output_size, method, antialias):
11631163

11641164
class ZeroPadding1D(object):
11651165

1166-
def __init__(self, padding):
1167-
padding = ((0, 0), padding, (0, 0))
1166+
def __init__(self, padding, data_format):
1167+
if data_format == 'channels_first':
1168+
padding = ((0, 0), (0, 0), padding)
1169+
elif data_format == 'channels_last':
1170+
padding = ((0, 0), padding, (0, 0))
1171+
else:
1172+
raise ValueError('data_format must be channels_first or channels_last.')
11681173
self.pad = Pad(paddings=padding)
11691174

11701175
def __call__(self, inputs):
@@ -1173,8 +1178,13 @@ def __call__(self, inputs):
11731178

11741179
class ZeroPadding2D(object):
11751180

1176-
def __init__(self, padding):
1177-
padding = ((0, 0), padding[0], padding[1], (0, 0))
1181+
def __init__(self, padding, data_format):
1182+
if data_format == 'channels_first':
1183+
padding = ((0, 0), (0, 0), padding[0], padding[1])
1184+
elif data_format == 'channels_last':
1185+
padding = ((0, 0), padding[0], padding[1], (0, 0))
1186+
else:
1187+
raise ValueError('data_format must be channels_first or channels_last.')
11781188
self.pad = Pad(paddings=padding)
11791189

11801190
def __call__(self, inputs):
@@ -1183,8 +1193,13 @@ def __call__(self, inputs):
11831193

11841194
class ZeroPadding3D(object):
11851195

1186-
def __init__(self, padding):
1187-
padding = ((0, 0), padding[0], padding[1], padding[2], (0, 0))
1196+
def __init__(self, padding, data_format):
1197+
if data_format == 'channels_first':
1198+
padding = ((0, 0), (0, 0), padding[0], padding[1], padding[2])
1199+
elif data_format == 'channels_last':
1200+
padding = ((0, 0), padding[0], padding[2], padding[1], (0, 0))
1201+
else:
1202+
raise ValueError('data_format must be channels_first or channels_last.')
11881203
self.pad = Pad(paddings=padding)
11891204

11901205
def __call__(self, inputs):

tensorlayerx/nn/layers/padding.py

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,7 @@ class ZeroPad1d(Module):
8484
8585
Parameters
8686
----------
87-
padding : int, or tuple of 2 ints
88-
- If int, zeros to add at the beginning and end of the padding dimension (axis 1).
87+
padding : tuple of 2 ints
8988
- If tuple of 2 ints, zeros to add at the beginning and at the end of the padding dimension.
9089
name : None or str
9190
A unique layer name.
@@ -104,10 +103,12 @@ class ZeroPad1d(Module):
104103
def __init__(
105104
self,
106105
padding,
107-
name=None, # 'zeropad1d',
106+
name=None,
107+
data_format='channels_last',
108108
):
109109
super().__init__(name)
110110
self.padding = padding
111+
self.data_format = data_format
111112
logging.info("ZeroPad1d %s: padding: %s" % (self.name, str(padding)))
112113

113114
if not isinstance(self.padding, (int, tuple, dict)):
@@ -124,7 +125,7 @@ def __repr__(self):
124125
return s.format(classname=self.__class__.__name__, **self.__dict__)
125126

126127
def build(self, inputs_shape=None):
127-
self.layer = tlx.ops.ZeroPadding1D(padding=self.padding)
128+
self.layer = tlx.ops.ZeroPadding1D(padding=self.padding, data_format=self.data_format)
128129

129130
def forward(self, inputs):
130131
outputs = self.layer(inputs)
@@ -141,9 +142,7 @@ class ZeroPad2d(Module):
141142
142143
Parameters
143144
----------
144-
padding : tuple of 2 ints or int, or tuple of 2 tuples of 2 ints.
145-
- If int, the same symmetric padding is applied to width and height.
146-
- If tuple of 2 ints, interpreted as two different symmetric padding values for height and width as ``(symmetric_height_pad, symmetric_width_pad)``.
145+
padding : tuple of 2 tuples of 2 ints.
147146
- If tuple of 2 tuples of 2 ints, interpreted as ``((top_pad, bottom_pad), (left_pad, right_pad))``.
148147
name : None or str
149148
A unique layer name.
@@ -162,11 +161,12 @@ class ZeroPad2d(Module):
162161
def __init__(
163162
self,
164163
padding,
165-
name=None, # 'zeropad2d',
164+
name=None,
165+
data_format='channels_last',
166166
):
167167
super().__init__(name)
168-
169168
self.padding = padding
169+
self.data_format = data_format
170170
logging.info("ZeroPad2d %s: padding: %s" % (self.name, str(self.padding)))
171171

172172
if not isinstance(self.padding, (int, tuple)):
@@ -183,7 +183,7 @@ def __repr__(self):
183183
return s.format(classname=self.__class__.__name__, **self.__dict__)
184184

185185
def build(self, inputs_shape=None):
186-
self.layer = tlx.ops.ZeroPadding2D(padding=self.padding)
186+
self.layer = tlx.ops.ZeroPadding2D(padding=self.padding, data_format=self.data_format)
187187

188188
def forward(self, inputs):
189189
outputs = self.layer(inputs)
@@ -200,9 +200,7 @@ class ZeroPad3d(Module):
200200
201201
Parameters
202202
----------
203-
padding : int, or tuple of 2 ints, or tuple of 2 tuples of 2 ints.
204-
- If int, the same symmetric padding is applied to width and height.
205-
- If tuple of 2 ints, interpreted as two different symmetric padding values for height and width as ``(symmetric_dim1_pad, symmetric_dim2_pad, symmetric_dim3_pad)``.
203+
padding : tuple of 2 tuples of 2 ints.
206204
- If tuple of 2 tuples of 2 ints, interpreted as ``((left_dim1_pad, right_dim1_pad), (left_dim2_pad, right_dim2_pad), (left_dim3_pad, right_dim3_pad))``.
207205
name : None or str
208206
A unique layer name.
@@ -221,11 +219,12 @@ class ZeroPad3d(Module):
221219
def __init__(
222220
self,
223221
padding,
224-
name=None, # 'zeropad3d',
222+
name=None,
223+
data_format='channels_last',
225224
):
226225
super().__init__(name)
227226
self.padding = padding
228-
227+
self.data_format = data_format
229228
logging.info("ZeroPad3d %s: padding: %s" % (self.name, str(self.padding)))
230229

231230
if not isinstance(self.padding, (int, tuple)):
@@ -242,7 +241,7 @@ def __repr__(self):
242241
return s.format(classname=self.__class__.__name__, **self.__dict__)
243242

244243
def build(self, inputs_shape=None):
245-
self.layer = tlx.ops.ZeroPadding3D(padding=self.padding)
244+
self.layer = tlx.ops.ZeroPadding3D(padding=self.padding, data_format=self.data_format)
246245

247246
def forward(self, inputs):
248247
outputs = self.layer(inputs)

tests/layers/test_layers_padding.py

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -19,34 +19,24 @@ def setUpClass(cls):
1919
## 1D
2020
cls.input_layer1 = tlx.nn.Input([None, 100, 1], name='input_layer1')
2121

22-
n1 = tlx.nn.ZeroPad1d(padding=1)(cls.input_layer1)
2322
n2 = tlx.nn.ZeroPad1d(padding=(2, 3))(cls.input_layer1)
2423

25-
cls.n1_shape = n1.get_shape().as_list()
2624
cls.n2_shape = n2.get_shape().as_list()
2725

2826
## 2D
2927
cls.input_layer2 = tlx.nn.Input([None, 100, 100, 3], name='input_layer2')
3028

3129
n0 = tlx.nn.PadLayer([[0, 0], [3, 3], [3, 3], [0, 0]], "REFLECT", name='inpad')(cls.input_layer2)
32-
n3 = tlx.nn.ZeroPad2d(padding=2)(cls.input_layer2)
33-
n4 = tlx.nn.ZeroPad2d(padding=(2, 3))(cls.input_layer2)
34-
n5 = tlx.nn.ZeroPad2d(padding=((3, 3), (4, 4)))(cls.input_layer2)
30+
n5 = tlx.nn.ZeroPad2d(padding=((3, 3), (4, 4)), data_format='channels_last')(cls.input_layer2)
3531

3632
cls.n0_shape = n0.get_shape().as_list()
37-
cls.n3_shape = n3.get_shape().as_list()
38-
cls.n4_shape = n4.get_shape().as_list()
3933
cls.n5_shape = n5.get_shape().as_list()
4034

4135
## 3D
4236
cls.input_layer3 = tlx.nn.Input([None, 100, 100, 100, 3], name='input_layer3')
4337

44-
n6 = tlx.nn.ZeroPad3d(padding=2)(cls.input_layer3)
45-
n7 = tlx.nn.ZeroPad3d(padding=(2, 3, 4))(cls.input_layer3)
4638
n8 = tlx.nn.ZeroPad3d(padding=((3, 3), (4, 4), (5, 5)))(cls.input_layer3)
4739

48-
cls.n6_shape = n6.get_shape().as_list()
49-
cls.n7_shape = n7.get_shape().as_list()
5040
cls.n8_shape = n8.get_shape().as_list()
5141

5242
@classmethod
@@ -56,27 +46,12 @@ def tearDownClass(cls):
5646
def test_n0_shape(self):
5747
self.assertEqual(self.n0_shape[1:], [106, 106, 3])
5848

59-
def test_n1_shape(self):
60-
self.assertEqual(self.n1_shape[1:], [102, 1])
61-
6249
def test_n2_shape(self):
6350
self.assertEqual(self.n2_shape[1:], [105, 1])
6451

65-
def test_n3_shape(self):
66-
self.assertEqual(self.n3_shape[1:], [104, 104, 3])
67-
68-
def test_n4_shape(self):
69-
self.assertEqual(self.n4_shape[1:], [104, 106, 3])
70-
7152
def test_n5_shape(self):
7253
self.assertEqual(self.n5_shape[1:], [106, 108, 3])
7354

74-
def test_n6_shape(self):
75-
self.assertEqual(self.n6_shape[1:], [104, 104, 104, 3])
76-
77-
def test_n7_shape(self):
78-
self.assertEqual(self.n7_shape[1:], [104, 106, 108, 3])
79-
8055
def test_n8_shape(self):
8156
self.assertEqual(self.n8_shape[1:], [106, 108, 110, 3])
8257

0 commit comments

Comments
 (0)