Entrenamiento de imagen basado en parche y combinar su probabilidad de una imagen
En primer lugar, he implementado un simple VGG16
red para clasificación de imágenes.
model = keras.applications.vgg16.VGG16(include_top = False,
weights = None,
input_shape = (32,32,3),
pooling = 'max',
classes = 10)
Cuya forma de entrada es 32 x 32
. Ahora, estoy tratando de implementar un patch-based neural network
. La idea principal es, desde la imagen de entrada, extraer 4 parche de imagen como esta imagen,
y entrenar la imagen de parche extraída(resizing to 32 x 32
como es la forma de entrada de nuestro modelo) finalmente, combinar sus cuatro probabilidades de salida y encontrar el resultado de salida final (Using normalizing & argmax). Así,
¿Cómo puedo hacer eso?
Gracias por su ayuda.
Nota:
Supongo que usando lambda layer
puede ser posible.
Mi simple implementación de clasificación VGG es aquí en Colab.
Pregunta hecha hace 3 años, 5 meses, 0 días - Por geekglitcher
3 Respuestas:
-
Usé el conjunto de datos MNIST para conseguir cada imagen como 4 parches con
tf.image.extract_patches
, que posteriormente se pasan como un lote:import tensorflow as tf from tensorflow import keras as K from tensorflow.keras.layers import Conv2D, Flatten, Dense, MaxPooling2D, Dropout from tensorflow import nn as nn from functools import partial import matplotlib.pyplot as plt (xtrain, ytrain), (xtest, ytest) = tf.keras.datasets.mnist.load_data() train = tf.data.Dataset.from_tensor_slices((xtrain, ytrain)) test = tf.data.Dataset.from_tensor_slices((xtest, ytest)) patch_s = 18 stride = xtrain.shape[1] - patch_s get_patches = lambda x, y: (tf.reshape( tf.image.extract_patches( images=tf.expand_dims(x[..., None], 0), sizes=[1, patch_s, patch_s, 1], strides=[1, stride, stride, 1], rates=[1, 1, 1, 1], padding='VALID'), (4, patch_s, patch_s, 1)), y) train = train.map(get_patches) test = test.map(get_patches) fig = plt.figure() plt.subplots_adjust(wspace=.1, hspace=.2) images, labels = next(iter(train)) for index, image in enumerate(images): ax = plt.subplot(2, 2, index + 1) ax.set_xticks([]) ax.set_yticks([]) ax.imshow(image) plt.show()
Entonces, en el circuito de entrenamiento, me estoy perdiendo por cada uno de estos 4 productos:
def compute_loss(model, x, y, training): out = model(x=x, training=training) repeated_y = tf.repeat(tf.expand_dims(y, 0), repeats=4, axis=0) loss = loss_object(y_true=repeated_y, y_pred=out, from_logits=True) loss = tf.reduce_mean(loss, axis=0) return loss
Entonces estoy reduciendo la media del eje 0 para fusionar todas las probabilidades juntas. Aquí está el código completo de funcionamiento:
import tensorflow as tf from tensorflow import keras as K from tensorflow.keras.layers import Conv2D, Flatten, Dense, MaxPooling2D, Dropout from tensorflow import nn as nn from functools import partial import matplotlib.pyplot as plt (xtrain, ytrain), (xtest, ytest) = tf.keras.datasets.mnist.load_data() train = tf.data.Dataset.from_tensor_slices((xtrain, ytrain)) test = tf.data.Dataset.from_tensor_slices((xtest, ytest)) patch_s = 18 stride = xtrain.shape[1] - patch_s get_patches = lambda x, y: (tf.reshape( tf.image.extract_patches( images=tf.expand_dims(x[..., None], 0), sizes=[1, patch_s, patch_s, 1], strides=[1, stride, stride, 1], rates=[1, 1, 1, 1], padding='VALID'), (4, patch_s, patch_s, 1)), y) train = train.map(get_patches) test = test.map(get_patches) fig = plt.figure() plt.subplots_adjust(wspace=.1, hspace=.2) images, labels = next(iter(train)) for index, image in enumerate(images): ax = plt.subplot(2, 2, index + 1) ax.set_xticks([]) ax.set_yticks([]) ax.imshow(image) plt.show() def prepare(inputs, targets): inputs = tf.divide(x=inputs, y=255) targets = tf.one_hot(indices=targets, depth=10) return inputs, targets train = train.take(10_000).map(prepare) test = test.take(10_00).map(prepare) class MyCNN(K.Model): def __init__(self): super(MyCNN, self).__init__() Conv = partial(Conv2D, kernel_size=(3, 3), activation=nn.relu) MaxPool = partial(MaxPooling2D, pool_size=(2, 2)) self.conv1 = Conv(filters=16) self.maxp1 = MaxPool() self.conv2 = Conv(filters=32) self.maxp2 = MaxPool() self.conv3 = Conv(filters=64) self.maxp3 = MaxPool() self.flatt = Flatten() self.dens1 = Dense(64, activation=nn.relu) self.drop1 = Dropout(.5) self.dens2 = Dense(10, activation=nn.softmax) def call(self, inputs, training=None, **kwargs): x = self.conv1(inputs) x = self.maxp1(x) x = self.conv2(x) x = self.maxp2(x) x = self.conv3(x) x = self.maxp3(x) x = self.flatt(x) x = self.dens1(x) x = self.drop1(x) x = self.dens2(x) return x model = MyCNN() loss_object = tf.losses.categorical_crossentropy def compute_loss(model, x, y, training): out = model(inputs=x, training=training) repeated_y = tf.repeat(tf.expand_dims(y, 0), repeats=4, axis=0) loss = loss_object(y_true=repeated_y, y_pred=out, from_logits=True) loss = tf.reduce_mean(loss, axis=0) return loss def get_grad(model, x, y): with tf.GradientTape() as tape: loss = compute_loss(model, x, y, training=False) return loss, tape.gradient(loss, model.trainable_variables) optimizer = tf.optimizers.Adam() verbose = "Epoch {:2d}" \ " Loss: {:.3f} Acc: {:.3%} TLoss: {:.3f} TAcc: {:.3%}" for epoch in range(1, 10 + 1): train_loss = tf.metrics.Mean() train_acc = tf.metrics.CategoricalAccuracy() test_loss = tf.metrics.Mean() test_acc = tf.metrics.CategoricalAccuracy() for x, y in train: loss_value, grads = get_grad(model, x, y) optimizer.apply_gradients(zip(grads, model.trainable_variables)) train_loss.update_state(loss_value) train_acc.update_state(y, model(x, training=True)) for x, y in test: loss_value, _ = get_grad(model, x, y) test_loss.update_state(loss_value) test_acc.update_state(y, model(x, training=False)) print(verbose.format(epoch, train_loss.result(), train_acc.result(), test_loss.result(), test_acc.result()))
Alerta de spoiler: con parches tan pequeños, no hace bien. Hacer parches más grandes que 18/28 para un mejor rendimiento.
Respondida el Dec 16, 2020 a las 19:42 - por cyberscribe
Votos positivos: 0 | Votos negativos: 0 -
Para implementar un enfoque de entrenamiento de imagen basado en parche y combinar sus probabilidades de una imagen, puedes seguir los siguientes pasos utilizando una capa Lambda en Keras.
- Dividir la imagen de entrada en 4 parches de imagen de tamaño 32x32 cada uno.
- Alimentar cada parche de imagen a una copia de tu red neuronal VGG16 pre-entrenada.
- Obtener las probabilidades de salida de cada copia de la red para cada parche.
- Combinar las probabilidades de salida de los 4 parches y encontrar el resultado final.
Aquí te dejo un ejemplo de cómo podrías implementarlo:
python from tensorflow.keras.models import Model from tensorflow.keras.layers import Input, Lambda, concatenate
Definir la forma de entrada para la imagen completa
input_full = Input(shape=(128, 128, 3))Dividir la imagen en 4 parches de tamaño 32x32 cada uno
patch1 = Lambda(lambda x: x[:, :32, :32, :])(input_full) patch2 = Lambda(lambda x: x[:, :32, 96:, :])(input_full) patch3 = Lambda(lambda x: x[:, 96:, :32, :])(input_full) patch4 = Lambda(lambda x: x[:, 96:, 96:, :])(input_full)Crear copias de la red VGG16 para cada parche
model_patch1 = Model(inputs=input_full, outputs=model(patch1)) model_patch2 = Model(inputs=input_full, outputs=model(patch2)) model_patch3 = Model(inputs=input_full, outputs=model(patch3)) model_patch4 = Model(inputs=input_full, outputs=model(patch4))Obtener las probabilidades de salida para cada parche
preds_patch1 = model_patch1.predict(input_full) preds_patch2 = model_patch2.predict(input_full) preds_patch3 = model_patch3.predict(input_full) preds_patch4 = model_patch4.predict(input_full)Combinar las probabilidades de salida de los 4 parches
combined_preds = concatenate([preds_patch1, preds_patch2, preds_patch3, preds_patch4])Normalizar y obtener la clase predicha final
final_output = keras.layers.Lambda(lambda x: keras.backend.mean(keras.backend.softmax(x), axis=0))(combined_preds)Crear el modelo final
model_final = Model(inputs=input_full, outputs=final_output)Este código te permite dividir la imagen de entrada en 4 parches, pasar cada parche a una copia de tu modelo VGG16, obtener las probabilidades de salida para cada parche, combinar las probabilidades de salida de los 4 parches y obtener la clase predicha final después de normalizar. Puedes ajustar los detalles según tus necesidades y requisitos específicos.
Espero que esta respuesta te sea de ayuda. ¡Déjame saber si tienes alguna otra pregunta!
Respondida el Dec 17, 2020 a las 19:39 - por Gpt
Votos positivos: 0 | Votos negativos: 0 -
Aquí tienes un enfoque paso a paso para implementar una red neuronal basada en parches para la clasificación de imágenes utilizando Keras:
1. Extracción de parches
Define una función que tome una imagen como entrada y la divida en parches superpuestos. Por ejemplo, puedes utilizar una ventana deslizante de 32x32 con un desplazamiento de 16 píxeles.
2. Redimensionamiento y normalización
Redimensiona cada parche a 32x32 píxeles para que coincida con la forma de entrada de tu modelo VGG16. Aplica normalización, como restar la media y dividir por la desviación estándar, a cada parche.
3. Creación de un modelo de red neuronal basado en parches
Crea cuatro copias del modelo VGG16 preentrenado, una para cada parche. Utiliza la capa Lambda de Keras para paralelizar la entrada de los parches en los cuatro modelos.
4. Combinación de probabilidades
Después de que los cuatro modelos hayan procesado los parches, utiliza otra capa Lambda para combinar sus probabilidades. Puedes utilizar la media, la suma o cualquier otra función de agregación para combinar las probabilidades.
5. Capa de salida
Aplica una capa de activación softmax a la capa de combinación para obtener las probabilidades finales de clase. Utiliza la función argmax para encontrar la clase predicha.
Código de ejemplo:
python import keras from keras.applications.vgg16 import VGG16 from keras.layers import Input, Lambda, Dense, Flatten from keras.models import Model
Función de extracción de parches
def extract_patches(image): patches = [] for i in range(0, image.shape[0], 16): for j in range(0, image.shape[1], 16): patch = image[i:i+32, j:j+32] patches.append(patch) return patchesFunción de combinación de probabilidades
def combine_probabilities(probabilities): return keras.backend.mean(probabilities, axis=0)Modelo original VGG16
base_model = VGG16(include_top=False, weights=None, input_shape=(32, 32, 3), pooling='max', classes=10)Extracción de parches
input_image = Input(shape=(32, 32, 3)) patches = Lambda(extract_patches)(input_image)Procesamiento de parches
processed_patches = [] for i in range(4): processed_patches.append(base_model(patches[i]))Combinación de probabilidades
combined_probabilities = Lambda(combine_probabilities)(processed_patches)Capa de salida
output = Dense(10, activation='softmax')(combined_probabilities)Creación del modelo
model = Model(input_image, output)Nota:
Puedes ajustar el tamaño de la ventana deslizante y el desplazamiento según tus necesidades. También puedes experimentar con diferentes funciones de agregación para combinar las probabilidades.
Respondida el Dec 17, 2020 a las 19:46 - por Gemini
Votos positivos: 0 | Votos negativos: 0