
La red neuronal siamesa es uno de los algoritmos de aprendizaje único más simples y populares. Métodos en los que para cada clase se toma solo un estudio de caso. Por lo tanto, la red siamesa se usa generalmente en aplicaciones donde no hay muchas unidades de datos en cada clase.
Supongamos que necesitamos hacer un modelo de reconocimiento facial para una organización que emplea a unas 500 personas. Si hacemos un modelo desde cero basado en la red neuronal convolucional (CNN), para entrenar el modelo y lograr una buena precisión de reconocimiento, necesitaremos muchas imágenes de cada una de estas 500 personas. Pero es obvio que no podemos compilar dicho conjunto de datos, por lo que no debe hacer un modelo basado en CNN o cualquier otro algoritmo de
aprendizaje profundo si no tenemos suficientes datos. En tales casos, puede utilizar el complejo algoritmo de aprendizaje de una sola vez, como la red siamesa, que puede entrenarse con menos datos.
De hecho, las redes siamesas consisten en dos redes neuronales simétricas, con los mismos pesos y arquitectura, que al final combinan y usan la función de energía - E.
Veamos la red siamesa, creando un modelo de reconocimiento facial basado en ella. Le enseñaremos a determinar cuándo dos caras son iguales y cuándo no. Y para empezar, utilizaremos el conjunto de datos AT&T Database of Faces, que se puede descargar del sitio web del
laboratorio de computación de la Universidad de Cambridge .
Descargue, descomprima y vea carpetas de s1 a s40:

Cada carpeta contiene 10 fotografías diferentes de una sola persona tomadas desde diferentes ángulos. Aquí está el contenido de la carpeta s1:

Y esto es lo que hay en la carpeta s13:

Las redes siamesas necesitan ingresar valores emparejados con marcas, así que creemos tales conjuntos. Tome dos fotos al azar de la misma carpeta y márquelas como un par "genuino". Luego tomamos dos fotos de diferentes carpetas y las marcamos como un par "falso" (falso):

Habiendo distribuido todas las fotos en pares marcados, estudiaremos la red. De cada par, transferiremos una foto a la red A, y la segunda a la red B. Ambas redes solo extraen vectores de propiedad. Para hacer esto, utilizaremos dos capas convolucionales con activación de unidad lineal rectificada (ReLU). Después de estudiar las propiedades, transferimos los vectores generados por ambas redes a una función de energía que estima la similitud. Usamos la distancia euclidiana como una función.
Ahora considere todos estos pasos con más detalle.
Primero, importe las bibliotecas necesarias:
import re import numpy as np from PIL import Image from sklearn.model_selection import train_test_split from keras import backend as K from keras.layers import Activation from keras.layers import Input, Lambda, Dense, Dropout, Convolution2D, MaxPooling2D, Flatten from keras.models import Sequential, Model from keras.optimizers import RMSprop
Ahora definimos una función para leer imágenes de entrada. La función
read_image
toma una imagen y devuelve una matriz NumPy:
def read_image(filename, byteorder='>'):
Por ejemplo, abra esta foto:
Image.open("data/orl_faces/s1/1.pgm")

Lo pasamos a la función
read_image
y obtenemos una matriz NumPy:
img = read_image('data/orl_faces/s1/1.pgm') img.shape (112, 92)
Ahora definimos la función
get_data
que generará los datos. Permítame recordarle que las redes siamesas deben enviar pares de datos (genuinos e imposibles) con marcado binario.
Primero, lea las imágenes (
img1
,
img2
) de un directorio,
x_genuine_pair,
en la matriz
x_genuine_pair,
establezca
y_genuine
en
1
. Luego leemos las imágenes (
img1
,
img2
) de diferentes directorios, las
x_imposite,
en el par
x_imposite,
y establecemos
y_imposite
en
0
.
Concatenar
x_genuine_pair
y
x_imposite
en
X
, y
y_genuine
e
y_imposite
en
Y
:
size = 2 total_sample_size = 10000 def get_data(size, total_sample_size):
Ahora generaremos los datos y verificaremos su tamaño. Tenemos 20,000 fotos, de las cuales se recolectaron 10,000 pares genuinos y 10,000 falsos:
X, Y = get_data(size, total_sample_size) X.shape (20000, 2, 1, 56, 46) Y.shape (20000, 1)
Compartiremos toda la gama de información: el 75% de las parejas irán a entrenamiento y el 25% a pruebas:
x_train, x_test, y_train, y_test = train_test_split(X, Y, test_size=.25)
Ahora crea una red siamesa. Primero definimos la red central: será una red neuronal convolucional para extraer propiedades. Cree dos capas convolucionales usando activaciones ReLU y una capa con la agrupación máxima después de una capa plana:
def build_base_network(input_shape): seq = Sequential() nb_filter = [6, 12] kernel_size = 3
Luego transferiremos un par de imágenes de la red central, que devolverán representaciones vectoriales, es decir, vectores de propiedad:
input_dim = x_train.shape[2:] img_a = Input(shape=input_dim) img_b = Input(shape=input_dim) base_network = build_base_network(input_dim) feat_vecs_a = base_network(img_a) feat_vecs_b = base_network(img_b)
feat_vecs_a
y
feat_vecs_b
son vectores de propiedad de un par de imágenes. Pasemos sus funciones de energía para calcular la distancia entre ellos. Y en función de la energía, usamos la distancia euclidiana:
def euclidean_distance(vects): x, y = vects return K.sqrt(K.sum(K.square(x - y), axis=1, keepdims=True)) def eucl_dist_output_shape(shapes): shape1, shape2 = shapes return (shape1[0], 1) distance = Lambda(euclidean_distance, output_shape=eucl_dist_output_shape)([feat_vecs_a, feat_vecs_b])
Establecemos el número de épocas en 13, aplicamos la propiedad RMS para la optimización y declaramos el modelo:
epochs = 13 rms = RMSprop() model = Model(input=[input_a, input_b], output=distance)
Ahora definimos la función de pérdida
contrastive_loss
y compilamos el modelo:
def contrastive_loss(y_true, y_pred): margin = 1 return K.mean(y_true * K.square(y_pred) + (1 - y_true) * K.square(K.maximum(margin - y_pred, 0))) model.compile(loss=contrastive_loss, optimizer=rms)
Estudiemos el modelo:
img_1 = x_train[:, 0] img_2 = x_train[:, 1] model.fit([img_1, img_2], y_train, validation_split=.25, batch_size=128, verbose=2, nb_epoch=epochs)
Usted ve cómo las pérdidas disminuyen a medida que pasan las eras:
Train on 11250 samples, validate on 3750 samples Epoch 1/13 - 60s - loss: 0.2179 - val_loss: 0.2156 Epoch 2/13 - 53s - loss: 0.1520 - val_loss: 0.2102 Epoch 3/13 - 53s - loss: 0.1190 - val_loss: 0.1545 Epoch 4/13 - 55s - loss: 0.0959 - val_loss: 0.1705 Epoch 5/13 - 52s - loss: 0.0801 - val_loss: 0.1181 Epoch 6/13 - 52s - loss: 0.0684 - val_loss: 0.0821 Epoch 7/13 - 52s - loss: 0.0591 - val_loss: 0.0762 Epoch 8/13 - 52s - loss: 0.0526 - val_loss: 0.0655 Epoch 9/13 - 52s - loss: 0.0475 - val_loss: 0.0662 Epoch 10/13 - 52s - loss: 0.0444 - val_loss: 0.0469 Epoch 11/13 - 52s - loss: 0.0408 - val_loss: 0.0478 Epoch 12/13 - 52s - loss: 0.0381 - val_loss: 0.0498 Epoch 13/13 - 54s - loss: 0.0356 - val_loss: 0.0363
Y ahora probemos el modelo en los datos de prueba:
pred = model.predict([x_test[:, 0], x_test[:, 1]])
Defina una función para calcular la precisión:
def compute_accuracy(predictions, labels): return labels[predictions.ravel()
Calculamos la precisión:
compute_accuracy(pred, y_test) 0.9779092702169625
Conclusiones
En esta guía, aprendimos cómo crear modelos de reconocimiento facial basados en redes siamesas. La arquitectura de tales redes consiste en dos redes neuronales idénticas que tienen el mismo peso y estructura, y los resultados de su trabajo se transfieren a una función de energía: esto determina la identidad de los datos de entrada. Para obtener más información sobre el metaaprendizaje con
Python, consulte
Meta-Learning práctico
con Python.Mi comentario
Actualmente se requiere conocimiento de las redes siamesas cuando se trabaja con imágenes. Existen muchos enfoques para capacitar redes en muestras pequeñas, nueva generación de datos, métodos de aumento. Este método permite obtener resultados relativamente “baratos”, aquí hay un ejemplo más clásico de la red siamesa en “Hello world” para redes neuronales: conjunto de datos MNIST
keras.io/examples/mnist_siamese