Как безопасно передать аргумент обучения слоям Keras в динамическом списке, если я не знаю, поддерживает ли его каждый сPython

Программы на Python
Ответить
Anonymous
 Как безопасно передать аргумент обучения слоям Keras в динамическом списке, если я не знаю, поддерживает ли его каждый с

Сообщение Anonymous »

Я создаю собственный слой Keras, состоящий из списка подслоев, но я не знаю заранее, какие слои принимают аргумент обучения (например, BatchNormalization принимает, а ReLU — нет).
Вот мой текущий подход к методу вызова:

Код: Выделить всё

class SingleConv(keras.layers.Layer):
"""
Basic convolutional module consisting of a Conv2d/Conv3d, non-linearity and optional batchnorm/groupnorm. The order of operations can be specified via the `order` parameter

Args:
out_channels (int): number of output channels
kernel_size (int or tuple): size of the convolving kernel
order (string): determines the order of layers, e.g.
'cr' -> conv + ReLU
'crg' -> conv + ReLU + groupnorm
'cl' -> conv + LeakyReLU
'ce' -> conv + ELU
padding (int or tuple): add zero-padding
dropout_prob (float): dropout probability, default 0.1
is3d (bool): if True use Conv3d, otherwise use Conv2d
"""

def __init__(self, out_channels, padding='same', kernel_size=3, order='cr', dropout_prob=0.1, is3d=True, in_channels=3, **kwargs):
super().__init__(**kwargs)

self.out_channels = out_channels
self.padding = padding
self.kernel_size = kernel_size
self.order = order
self.dropout_prob = dropout_prob
self.is3d = is3d
self.in_channels = in_channels

# get layers from  create_conv (assumes no or groupnorm and padding = "Same" and "Channels_last" )
layers_list = self.create_conv(out_channels=self.out_channels, kernel_size=self.kernel_size, order=self.order, dropout_prob=self.dropout_prob, is3d=self.is3d, padding=self.padding)

self.module_layers = []
for i, (name, layer) in enumerate(layers_list):
# Giving each layer a unique attribute name (e.g., self.layer_0)
# ensures Keras "sees" these layers and saves their weights.
attr_name = f"layer_{i}_{name}"
setattr(self, attr_name, layer)
self.module_layers.append(layer)

def create_conv( self, out_channels, kernel_size, order,
dropout_prob, is3d, padding='same'):
"""
Create a CONV block. Padding is always "SAME".  This function assumes channels last ( keras default).
Args:
out_channels (int): number of output channels
kernel_size(int or tuple): size of the convolving kernel
order (string): order of things, e.g.
'cr' -> conv + ReLU
'cl' -> conv + LeakyReLU
'ce' -> conv + ELU
'bcr' -> batchnorm + conv + ReLU
'cbrd' -> conv + batchnorm + ReLU + dropout
'cbrD' -> conv + batchnorm + ReLU + dropout2d
dropout_prob (float): dropout probability
is3d (bool): is3d (bool): if True use Conv3d, otherwise use Conv2d
Returns a list of tf.keras.layers in the specified `order`.

"""
assert 'c' in order, "Conv layer MUST be present"
assert order[0] not in 'rle', "Non-linearity cannot be the first operation in the layer"

Conv = layers.Conv3D if is3d else layers.Conv2D
Dropout = layers.Dropout if is3d else layers.SpatialDropout2D
Dropout3D = layers.SpatialDropout3D

modules = []
for i, char in enumerate(order):
if char == 'r':
modules.append(('ReLU', layers.ReLU()))
elif char == 'l':
modules.append(('LeakyReLU', layers.LeakyReLU()))
elif char == 'e':
modules.append(('ELU', layers.ELU()))
elif char == 'c':
# disable bias if normalization follows
use_bias = not ('b' in order)
modules.append(('conv',
Conv(
out_channels,
kernel_size,
use_bias=use_bias,
padding=padding,
data_format='channels_last'
)
))

elif char == 'b':
# Determine channels before/after conv
is_before_conv = i < order.index('c')
bn_axis = -1  # channels_last
modules.append(('batchnorm',
layers.BatchNormalization(axis=bn_axis)
))
elif char == 'd':
modules.append(('dropout',Dropout(rate=dropout_prob)))

elif char == 'D':
if is3d:
modules.append(('dropout',layers.SpatialDropout3D(rate=dropout_prob)))
else:
modules.append(('dropout',layers.SpatialDropout2D(rate=dropout_prob)))

else:
raise ValueError(f"Unsupported layer type '{char}'. "
"MUST be one of ['b', 'g', 'r', 'l', 'e', 'c', 'd', 'D']")
return modules

def call(self, inputs, training=None):

x = inputs

for layer in self.module_layers:
try:
x = layer(x, training=training)
except TypeError as e:
if "training" in str(e):
x = layer(x)
else:
raise  # real bug → don't hide it

return x

Мои вопросы:
  • Разумно ли это подход к динамической обработке аргумента обучения, не зная, какой уровень его поддерживает?
  • Есть ли какие-либо издержки производительности или подводные камни при использовании try/Exception внутри цикла?
  • Есть ли более чистая/лучшая практика способ определить, принимает ли уровень обучение перед его вызовом?


Подробнее здесь: https://stackoverflow.com/questions/798 ... -when-i-do
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»