Forma de entrada de la subclase de capa TensorFlow
Estoy tratando de crear una capa personalizada a partir de la instancia de layers.Layer
de TensorFlow.
Estoy tratando de crear un filtro IIR, para lo cual se utilizan valores de la capa de entrada y se calcula una secuencia de salida, algo así como esto:
y[i] = a0 * x[i] + a1 * x[i - 1] + b1 * y[i - 1]
donde x
es la entrada y y
es la salida. Defino la clase de esta manera:
class IIR(keras.layers.Layer):
def __init__(self, input_dim):
super(IIR, self).__init__()
self.input_dim = 60
self.b0 = tf.Variable(tf.constant([uniform(-1, 1)]))
self.b1 = tf.Variable(tf.constant([uniform(-1, 1)]))
self.b2 = tf.Variable(tf.constant([uniform(-1, 1)]))
self.a1 = tf.Variable(tf.constant([uniform(-1, 1)]))
self.a2 = tf.Variable(tf.constant([uniform(-1, 1)]))
def call(self, inputs):
order = 3
init_dim = [0,1,2]
output_sequence = tf.constant(np.zeros((self.input_dim)),dtype=tf.float32)
outt = np.zeros(self.input_dim)
outt[0] = inputs[0]
outt[1] = inputs[1]
outt[2] = inputs[2]
for i in range(2,self.input_dim):
outt[i] = self.b0*inputs[i] + self.b1*inputs[i-1] + self.b2*inputs[i-2] - self.a1*outt[i-1] - self.a2*outt[i-2]
output_sequence = tf.constant(outt)
return output_sequence
Pero sigo recibiendo el error:
ValueError: Exception encountered when calling layer "iir_13" (type IIR).
En el código del usuario:
En el archivo <ipython-input-37-0717fc982e73>, línea 17, en call *
outt[0] = inputs[:][0]
ValueError: setting an array element with a sequence.
Los argumentos recibidos son:
• inputs=tf.Tensor(shape=(None, 60), dtype=float32)
La forma de entrada es (None, 60)
(estoy estableciendo 60 solo para fines de prueba) y estoy suponiendo que None
será reemplazado por el tamaño del lote durante el entrenamiento. ¿Cómo puedo acceder a los valores de entrada? ¿Cuál es la forma real de entrada? ¿Es este el enfoque correcto?
EDIT: Estoy intentando implementar esto en un modelo, algo así como esto:
model = keras.Sequential()
model.add(keras.layers.Input(shape=60))
model.add(IIR(input_dim=60))
model.add(keras.layers.Dense(8, activation='relu'))
model.add(keras.layers.Dense(1, activation='sigmoid'))
model.compile(optimizer='adam', loss='binary_crossentropy')
davy.ai
La causa del error que estás viendo se debe a la línea:
outt[0] = inputs[:,0]
En esta línea, estás intentando acceder al primer elemento de
inputs
, pero la sintaxis que estás usando es incorrecta. En su lugar, debes usar:outt[0] = inputs[:,0]
Esto te dará la primera columna de
inputs
(ya que la entrada tiene una forma(None, 60)
).Además, en el método
__init__
de tu claseIIR
, estás codificando el valor deinput_dim
a 60, en lugar de usar el valor pasado como argumento. Para solucionar eso, puedes cambiar:self.input_dim = 60
por:
self.input_dim = input_dim
Finalmente, en tu método
call
, estás inicializandooutt
a ceros y luego estableciendo manualmente los primeros tres elementos. Sin embargo, estás asumiendo que la entrada tiene una longitud de al menos 3, lo cual podría no ser el caso. Para solucionar esto, puedes cambiar la inicialización a:outt = tf.TensorArray(tf.float32, size=self.input_dim)
Luego, puedes establecer los primeros tres elementos usando:
Y en el bucle, puedes actualizar el arreglo usando:
outt = outt.write(i, self.b0*inputs[i] + self.b1*inputs[i-1] + self.b2*inputs[i-2] - self.a1*outt.read(i-1) - self.a2*outt.read(i-2))
Al final del bucle, puedes convertir el
TensorArray
a un tensor regular usando:output_sequence = outt.stack()
En cuanto a tu enfoque, me parece razonable. Estás definiendo una capa personalizada que realiza una operación personalizada, y luego la incluyes en un modelo junto con otras capas. Sin embargo, ten en cuenta que podría haber otras formas de lograr resultados similares o idénticos utilizando capas o funciones integradas.