TensorFlow / Python: Comparación de Imágenes con Redes Neuronales Siamesas

A continuación, trabajaremos en la implementación de una Red Neuronal Siamesa en TensorFlow. Una red neuronal siamesa se utiliza para calcular la similitud o distancia entre dos entradas. En este ejemplo, crearemos una red siamesa para comparar imágenes y determinar si pertenecen a la misma clase o no. Usaremos TensorFlow para construir esta red.

import tensorflow as tf
from tensorflow.keras.layers import Input, Flatten, Dense, Lambda
from tensorflow.keras.models import Model
from tensorflow.keras.datasets import mnist
import numpy as np

# Cargar y preparar el conjunto de datos MNIST
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0

# Función para crear una capa de distancia euclidiana
def euclidean_distance(vectors):
    vector1, vector2 = vectors
    sum_square = tf.reduce_sum(tf.square(vector1 - vector2), axis=1, keepdims=True)
    return tf.sqrt(sum_square)

# Crear dos entradas para las imágenes
input_shape = (28, 28)
input_a = Input(shape=input_shape)
input_b = Input(shape=input_shape)

# Definir una base convolucional compartida (siamesa)
shared_base = tf.keras.Sequential([
    tf.keras.layers.Flatten(input_shape=input_shape),
    tf.keras.layers.Dense(128, activation='relu'),
    tf.keras.layers.Dense(64, activation='relu'),
    tf.keras.layers.Dense(32, activation='relu')
])

# Obtener la salida de la base compartida para ambas entradas
output_a = shared_base(input_a)
output_b = shared_base(input_b)

# Usar la capa de distancia para calcular la similitud
distance = Lambda(euclidean_distance)([output_a, output_b])

# Crear el modelo Siamese
siamese_model = Model(inputs=[input_a, input_b], outputs=distance)

# Compilar el modelo
siamese_model.compile(loss='mean_squared_error', optimizer='adam')

# Crear pares de entrenamiento para la verificación de escritura a mano
def create_pairs(x, digit_indices):
    pairs = []
    labels = []
    n = min([len(digit_indices[d]) for d in range(10)]) - 1
    for d in range(10):
        for i in range(n):
            z1, z2 = digit_indices[d][i], digit_indices[d][i + 1]
            pairs += [[x[z1], x[z2]]]
            inc = np.random.randint(1, 10)
            dn = (d + inc) % 10
            z1, z2 = digit_indices[d][i], digit_indices[dn][i]
            pairs += [[x[z1], x[z2]]]
            labels += [1, 0]
    return np.array(pairs), np.array(labels)

digit_indices = [np.where(y_train == i)[0] for i in range(10)]
tr_pairs, tr_y = create_pairs(x_train, digit_indices)

# Entrenar la red siamesa
siamese_model.fit([tr_pairs[:, 0], tr_pairs[:, 1]], tr_y, batch_size=128, epochs=20)

# Para hacer predicciones, proporciona dos imágenes y obtén la distancia como resultado
image1 = x_test[0]
image2 = x_test[1]
distance = siamese_model.predict([image1[np.newaxis], image2[np.newaxis]])
print("Distancia entre las imágenes:", distance)
import matplotlib.pyplot as plt

# Supongamos que tienes dos índices que deseas comparar
index1 = 4  # Índice de la primera imagen
index2 = 6  # Índice de la segunda imagen

# Recupera las imágenes
image1 = x_test[index1]
image2 = x_test[index2]

# Calcula la distancia entre las imágenes
distance = siamese_model.predict([image1[np.newaxis], image2[np.newaxis]])

# Muestra las imágenes junto con la distancia
plt.figure(figsize=(10, 4))
plt.subplot(1, 2, 1)
plt.imshow(image1, cmap='gray')
plt.title('Imagen 1')

plt.subplot(1, 2, 2)
plt.imshow(image2, cmap='gray')
plt.title('Imagen 2')

plt.suptitle(f'Distancia: {distance[0][0]:.4f}')
plt.show()

La línea print("Distancia entre las imágenes:", distance) muestra la distancia calculada entre dos imágenes por el modelo Siamese. En este contexto, “distancia” se refiere a la diferencia o similitud entre las características extraídas de las dos imágenes.

La idea detrás de una red neuronal Siamesa es aprender una representación de las imágenes de tal manera que dos imágenes similares tengan una distancia pequeña entre sus representaciones, mientras que dos imágenes diferentes tengan una distancia grande.

Cuando ejecutas siamese_model.predict([image1[np.newaxis], image2[np.newaxis]), el modelo calcula la distancia entre las representaciones de image1 y image2. Esta distancia puede considerarse como una medida de cuán similares o diferentes son las dos imágenes. Cuanto menor sea la distancia, más similares serán las imágenes, y cuanto mayor sea la distancia, más diferentes serán

Deja un comentario