Crear un modelo y compilarlo para extraer las incrustaciones de una imagen

Estoy tratando de migrar este código 3.3 Omniglot Clasificación de caracteres usando la red prototípica. ipynb, de Tensorflow 1.1 a Tensorflow 2.x.

Mi duda es que no sé lo que estoy haciendo. El código donde tengo el problema es:

import numpy as np
import tensorflow as tf

def convolution_block(inputs, out_channels, name='conv'):

    conv = tf.layers.conv2d(inputs, out_channels, kernel_size=3, padding='SAME')
    conv = tf.contrib.layers.batch_norm(conv, updates_collections=None, decay=0.99, scale=True, center=True)
    conv = tf.nn.relu(conv)
    conv = tf.contrib.layers.max_pool2d(conv, 2)
    
    return conv

def get_embeddings(support_set, h_dim, z_dim, reuse=False):

    net = convolution_block(support_set, h_dim)
    net = convolution_block(net, h_dim)
    net = convolution_block(net, h_dim) 
    net = convolution_block(net, z_dim) 
    net = tf.contrib.layers.flatten(net)
        
    return net

Y he migrado a:

import tensorflow as tf
from tensorflow.keras.layers import Input, Conv2D, MaxPooling2D

def get_embedding_function(img_shape):
    inputs = Input(img_shape)
    conv1 = Conv2D(64, (3, 3), activation='relu', padding='same', name='conv1_1')(inputs)
    pool1 = MaxPooling2D(pool_size=(2, 2), data_format='channels_last', name='pool1')(conv1)

    conv2 = Conv2D(96, (3, 3), activation='relu', padding='same', name='conv2_1')(pool1)
    pool2 = MaxPooling2D(pool_size=(2, 2), data_format='channels_last', name='pool2')(conv2)

    conv3 = Conv2D(128, (3, 3), activation='relu', padding='same', name='conv3_1')(pool2)
    pool3 = MaxPooling2D(pool_size=(2, 2), data_format='channels_last', name='pool3')(conv3)

    conv4 = Conv2D(256, (3, 3), activation='relu', padding='same', name='conv4_1')(pool3)
    pool4 = MaxPooling2D(pool_size=(2, 2), data_format='channels_last', name='pool4')(conv4)

    model = tf.keras.models.Model(inputs=inputs, outputs=pool4)

    model.compile(tf.keras.optimizers.Adam(lr=(1e-4) * 2), loss='binary_crossentropy', metrics=['accuracy'])

    return model

Esta función no tiene las mismas capas que la anterior porque quiero probar mi propia red.

Voy a usar esta función para extraer características de imágenes.

He tenido que añadir model = tf.keras.models.Model(inputs=inputs, outputs=pool4) porque si sólo vuelvo pool4 No funciona. Y también he añadido model.compile(tf.keras.optimizers.Adam(lr=(1e-4) * 2), loss='binary_crossentropy', metrics=['accuracy']) pero No sé si lo necesito.

¿Necesito crear el modelo y compilarlo para extraer características de una imagen?

Pregunta hecha hace 3 años, 4 meses, 29 días - Por compilercaptain7dab


4 Respuestas:

  • Hay principalmente dos maneras de entrenar una red usando la API keras:

    • usando el fit método
    • escribiendo un bucle personalizado desde cero.

    En ambos casos, si utiliza el keras API, necesitas crear un Modelo, que es la colección de capas conectadas.

    Permite definir un MLP simple (multi layer perceptron) Modelo utilizando keras:

    import tensorflow as tf
    
    inp = tf.keras.Input((1,))
    hidden = tf.keras.layers.Dense(10, activation="tanh")(inp)
    out = tf.keras.layers.Dense(1, activation="simgoid")(hidden)
    model = tf.keras.Model(inputs=inp, outputs=out)
    

    Permite también generar algunos datos sintéticos simples

    x = tf.random.normal((100,1))
    y = 2*x + 1
    

    Tenga en cuenta que el uso de un MLP para una regresión tan simple como esto es exagerado. Una simple regresión lineal sería suficiente.

    Capacitación mediante fit

    Si quieres usar el fit método, entonces usted necesita compilar el modelo. Compiling the model is akin to providing the training strategy of the model: which objective function (loss) to use, with which optimization algoritmo.

    En ese caso, permite utilizar un simple error cuadrado medio como pérdida, y un SGD como algoritmo de optimización. Una vez hecho, puedes simplemente llamar fit en sus datos.

    >>> model.compile(optimizer="sgd", loss="mse")
    >>> model.fit(x,y)
    4/4 [==============================] - 0s 2ms/step - loss: 4.5469
    

    El método fit proporciona muchas opciones, usted puede explorarlas mirando el documentación.

    Escribir un bucle de entrenamiento desde cero

    A veces, usar el método de ajuste no es lo suficientemente flexible. En ese caso, es posible entrenar el modelo desde cero escribiendo un bucle de entrenamiento. En ese caso, necesitas definir todo tú mismo. Si quiero utilizar SDG como optimizador, y una función de pérdida de errores cuadrada media, puedo hacerlo de esa manera:

    opt = tf.optimizers.SGD()
    for data,label in zip(x,y):
        with tf.GradientTape() as tape:
            pred = model(data)
            loss = tf.losses.mse(pred,label)
        grad = tape.gradient([loss], model.weights)
        opt.apply_gradients(zip(grad, model.weights))
    

    Este enfoque es más flexible, pero también más verboso. En ese caso, no necesito compilar el modelo. El compilado es sólo el método que hará que el optimizador y la función de pérdida se conozcan method.

    Leer más

    Puedes leer más sobre:

    Respondida el Dec 17, 2020 a las 08:07 - por binarybrainiac

    Votos positivos: 0 | Votos negativos: 0

  • El modelo de compilación o no depende del método que utilice para entrenar el modelo, es decir:

    Si usas model.fit entonces usted necesita compilar el modelo antes de ajustar el modelo

    Si usas entrenamiento personalizado entonces no tienes que hacerlo, simplemente devuelve el modelo y utilízalo como:

    optimizer = tf.keras.optimizers.Adam(lr=(1e-4) * 2)
    bce = tf.keras.losses.BinaryCrossentropy()
    
    tf.GradientTape() as tape:
        y_pred = model(X)
        loss = bce(y_true, y_pred)
    
    grads = tape.gradient(loss , model.trainable_variables)
    optimizer.apply_gradients(zip(grads , model.trainable_variables))
    

    Respondida el Dec 17, 2020 a las 08:13 - por algorithmarchitect

    Votos positivos: 0 | Votos negativos: 0

  • En TensorFlow 2.x, la creación y compilación del modelo son pasos separados, y no es estrictamente necesario compilar el modelo si solo deseas usarlo para extraer características de una imagen.

    En tu caso, si solo quieres usar la red convolucional para extraer características de las imágenes, puedes definir el modelo y luego simplemente llamar al método predict del modelo para obtener las salidas de la capa que deseas. No necesitas compilar el modelo si solo necesitas extraer las características.

    Aquí te dejo un ejemplo de cómo podrías modificar tu función get_embedding_function para solo crear el modelo y usarlo para extraer características:

    python
    import tensorflow as tf
    from tensorflow.keras.layers import Input, Conv2D, MaxPooling2D
    
    def get_embedding_function(img_shape):
        inputs = Input(img_shape)
        conv1 = Conv2D(64, (3, 3), activation='relu', padding='same', name='conv1_1')(inputs)
        pool1 = MaxPooling2D(pool_size=(2, 2), data_format='channels_last', name='pool1')(conv1)
    
        conv2 = Conv2D(96, (3, 3), activation='relu', padding='same', name='conv2_1')(pool1)
        pool2 = MaxPooling2D(pool_size=(2, 2), data_format='channels_last', name='pool2')(conv2)
    
        conv3 = Conv2D(128, (3, 3), activation='relu', padding='same', name='conv3_1')(pool2)
        pool3 = MaxPooling2D(pool_size=(2, 2), data_format='channels_last', name='pool3')(conv3)
    
        conv4 = Conv2D(256, (3, 3), activation='relu', padding='same', name='conv4_1')(pool3)
        pool4 = MaxPooling2D(pool_size=(2, 2), data_format='channels_last', name='pool4')(conv4)
    
        model = tf.keras.models.Model(inputs=inputs, outputs=pool4)
    
        return model
    

    De esta forma, puedes crear tu modelo, llamar a model.predict() con una imagen de entrada y luego obtener las activaciones de la capa pool4 que te darán las características de la imagen. No es necesario compilar el modelo si solo lo usas para extraer características.

    Respondida el Dec 18, 2020 a las 08:06 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • ¿Necesitas crear y compilar el modelo para extraer características de una imagen?

    No, no es necesario crear ni compilar el modelo para extraer características de una imagen.

    Las funciones de extracción de características, como get_embeddings o get_embedding_function en tu código, generalmente solo requieren la definición de la arquitectura de la red y no necesitan ser compiladas. La compilación es un paso posterior que se utiliza para entrenar el modelo en un conjunto de datos específico, lo cual no es necesario para la extracción de características.

    Pasos para extraer características:

    • Define la función de extracción de características: Define la arquitectura de tu red como una función que toma como entrada una imagen y devuelve las características extraídas.
    • Carga la imagen: Carga la imagen de la que deseas extraer las características.
    • Preprocesa la imagen: Aplica cualquier preprocesamiento necesario a la imagen, como cambiar el tamaño o normalizar los valores de los píxeles.
    • Extrae las características: Pasa la imagen preprocesada a través de la función de extracción de características para obtener las características.

    Código de ejemplo:

    python
    import tensorflow as tf
    
    

    Define la función de extracción de características

    def get_embedding_function(img_shape): inputs = Input(img_shape)

    Define la arquitectura de la red aquí

    model = tf.keras.models.Model(inputs=inputs, outputs=pool4) return model

    Carga la imagen

    image = tf.keras.preprocessing.image.load_img("image.jpg")

    Preprocesa la imagen

    image = tf.keras.preprocessing.image.img_to_array(image) image = tf.keras.applications.imagenet_utils.preprocess_input(image)

    Extrae las características

    model = get_embedding_function(image.shape) embeddings = model(image)

    En este código, el modelo se define pero no se compila. La función get_embedding_function devuelve un modelo que se puede utilizar directamente para extraer características.

    Respondida el Dec 18, 2020 a las 08:13 - por Gemini

    Votos positivos: 0 | Votos negativos: 0