Cualquier marco de aprendizaje profundo para tener éxito tiene que
proporcionar una buena colección de redes neuronales de vanguardia, junto con
sus pesos entrenados en conjuntos de datos populares y ampliamente aceptados.
Muchos marcos generalmente se refieren a esta colección como Model Zoo. TensorFlow
en sus versiones iniciales proporcionó este zoológico de redes a través de su
marco TF-Slim. Pero la usabilidad de TF-Slim para las redes no era intuitiva y,
con el tiempo, TF-Slim quedo en desuso.
TensorFlow,
ahora ha creado un marco mejor conocido como TensorFlow Hub, que es muy fácil
de usar y está bien organizado. Con TensorFlow Hub, podemos realizar con
confianza la actividad ampliamente utilizada de Transfer Learning al importar
redes grandes y populares en unas pocas líneas de código. TensorFlow Hub es muy
flexible y proporciona la posibilidad de alojar nuestras redes para que otros
usuarios las utilicen. Estas redes en TensorFlow Hub se denominan módulos.
En
este artículo, echaremos un vistazo a los conceptos básicos sobre cómo usar
TensorFlow Hub, sus diversos tipos y ejemplos de código.
Es
importante tener en cuenta que TensorFlow Hub solo proporciona un gráfico que
comprende la arquitectura de la red junto con sus pesos entrenados en ciertos
conjuntos de datos. La mayoría de los módulos dan acceso a capas internas de la
red que se pueden usar en función de diferentes casos de uso. Sin embargo,
algunos de los módulos no son ajustables. Antes de comenzar con el desarrollo,
es recomendable consultar la descripción proporcionada sobre el módulo en el
sitio web de TensorFlow Hub.
A
continuación, veremos algunos aspectos y funciones importantes que se pueden
utilizar para comprender más detalles sobre el módulo del TensorFlow Hub.
Prerrequisitos
Instanciación
En TensorFlow Hub se alojan varios módulos formados con
diferentes redes (Inception, ResNet, ElMo, etc.) que sirven para diferentes
propósitos (clasificación de imágenes, incrustaciones de texto, etc.). El
usuario tiene que navegar por el catálogo de módulos y luego, una vez
finalizado su propósito, necesitamos copiar la URL donde está alojada la red.
Luego, podemos instanciar nuestro módulo de la siguiente forma:
import
tensorflow_hub as hub
module =
hub.Module(<<Module URL as
string>>, trainable=True)
Además
del parámetro URL, el otro parámetro más notable es "trainable". Si
deseamos ajustar / modificar los pesos
del modelo, este parámetro debe establecerse como Verdadero.
Firma
La
firma del módulo especifica para qué se utiliza el módulo. Todo el módulo viene
con la firma "predeterminada" y la utiliza, si una firma no se
menciona explícitamente. Para la mayoría de los módulos, cuando se utiliza la
firma "predeterminada", las capas internas del modelo se abstraen del
usuario. La función utilizada para enumerar todos los nombres de firma del
módulo es get_signature_names ().
import
tensorflow_hub as hub
module =
hub.Module('https://tfhub.dev/google/imagenet/inception_v3/classification/1')
print(module.get_signature_names())
# ['default', 'image_classification', 'image_feature_vector']
Entradas
esperadas
Cada
módulo tiene un conjunto de entradas esperadas dependiendo de la firma del
módulo que se esté utilizando. Aunque la mayoría de los módulos han documentado
el conjunto de entradas esperadas en el sitio web de TensorFlow Hub
(particularmente para la firma "predeterminada"), algunos de ellos no
lo han hecho. En este caso, es más fácil obtener la entrada esperada junto con
su tamaño y tipo de datos usando get_input_info_dict ().
import
tensorflow_hub as hub
module =
hub.Module('https://tfhub.dev/google/imagenet/inception_v3/classification/1')
print(module.get_input_info_dict())
# When no
signature is given, considers it as 'default'# {'images': <hub.ParsedTensorInfo
shape=(?, 299, 299, 3) dtype=float32 is_sparse=False>}
print(module.get_input_info_dict(signature='image_feature_vector')) # {'images': <hub.ParsedTensorInfo shape=(?, 299, 299, 3)
dtype=float32 is_sparse=False>}
Resultados
esperados
Para
construir la parte restante del gráfico después de que se construye el modelo
de TensorFlow Hub, es necesario conocer el tipo de salida esperado. La función
get_output_info_dict () se usa para este propósito. Hay que tener en cuenta que
para la firma "predeterminada", generalmente habrá solo una salida,
pero cuando utilizamos una firma no predeterminada, se expondrán varias capas
del gráfico.
import
tensorflow_hub as hub
module =
hub.Module('https://tfhub.dev/google/imagenet/inception_v3/classification/1')
print(module.get_output_info_dict())
# When no
signature is given, considers it as 'default'
# {'default': <hub.ParsedTensorInfo shape=(?, 1001)
dtype=float32 is_sparse=False>}
print(module.get_output_info_dict(signature='image_classification'))
# {'InceptionV3/global_pool': <hub.ParsedTensorInfo shape=(?,
1, 1, 2048) dtype=float32 is_sparse=False>,
# 'InceptionV3/Logits': <hub.ParsedTensorInfo shape=(?, 1001)
dtype=float32 is_sparse=False>,
# 'InceptionV3/Conv2d_2b_3x3': <hub.ParsedTensorInfo shape=(?,
147, 147, 64) dtype=float32 is_sparse=False>
# ..... Several other exposed layers...... }
Recopilación
de las capas necesarias del módulo
Después
de crear una instancia del módulo, debemos extraer la capa/salida deseada del
módulo y agregarla al gráfico. Estas son algunas de las formas de hacerlo:
import
tensorflow as tf
import
tensorflow_hub as hub
images =
tf.placeholder(tf.float32, (None, 299, 299, 3))
module =
hub.Module('https://tfhub.dev/google/imagenet/inception_v3/classification/1')
logits1 =
module(dict(images=images))
# implies
default signature
print(logits1)
# Tensor("module_apply_default/InceptionV3/Logits/SpatialSqueeze:0",
shape=(?, 1001), dtype=float32)
module_features =
module(dict(images=images),
signature='image_classification', as_dict=True)
# module_features stores all layers in key-value pairs
logits2 =
module_features['InceptionV3/Logits']
print(logits2)
#
Tensor("module_apply_image_classification/InceptionV3/Logits/SpatialSqueeze:0",
shape=(?, 1001), dtype=float32)
global_pool =
module_features['InceptionV3/global_pool']
print(global_pool)
# Tensor("module_apply_image_classification/InceptionV3/Logits/GlobalPool:0",
shape=(?, 1, 1, 2048), dtype=float32)
Inicialización
de las operaciones de TensorFlow Hub
TensorFlow
Hub aloja el peso / valores de salida resultantes de todas las operaciones
presentes en los módulos en formato tabular. Esto debe inicializarse usando
tf.tables_initializer () junto con las inicializaciones de variables regulares.
El bloque de código se ve así:
import
tensorflow as tf
with
tf.Session() as sess:
sess.run([tf.tables_initializer(), <<other initializers>>])
Bloque
de esqueleto de código
Una
vez que se construye el gráfico completo que comprende su módulo, optimizadores
de algoritmos de aprendizaje, función objetivo, capas personalizadas, etc., así
es como puede verse la parte gráfica de su código.
import tensorflow as tf
import tensorflow_hub as hub
<< Create Placeholders >>
<< Create Dataset and Iterators >>
module1 = hub.Module(<< Module URL >>)
logits1 =
module1(<< input_dict >>)
module2 =
hub.Module(<< Module URL
>>)
module2_features =
module2(<< input_dict >>, signature='default', as_dict=True)
logits2 =
module2_features['default']
<<
Remaining graph, learning algorithms, objective function, etc >>
with
tf.Session() as sess:
sess.run([tf.tables_initializer(), <<
other initializers >>])
<< Remaining training pipeline >>
Estamos
haciendo uso de dos módulos. El primer módulo se construye utilizando un código
mínimo básico que utiliza implícitamente la firma y la capa predeterminadas. En
el segundo módulo, especifica explícitamente la firma y la capa
predeterminadas. De manera similar, podemos especificar la firma y las capas no
predeterminadas.
Ahora
que hemos analizado cómo integrar un módulo en el gráfico, veamos varios tipos
de módulos presentes en TensorFlow Hub. En cada uno de los ejemplos, se ha
integrado con el conjunto de datos y la tubería Iterator y guardado con
Saved_Model.
Módulos
de clasificación de imágenes
Como
su nombre indica, este conjunto de módulos se utilizan para la clasificación de
imágenes. En esta categoría de módulos, se proporciona la arquitectura completa
de la red. Esto incluye la capa densa final que se usa para la clasificación.
En el ejemplo de código para esta categoría, solo vamos a ver el problema de
clasificación de perros y gatos de Kaggle en 1001 clases ImageNet usando el
módulo Inception V3.
import tensorflow as tf
import tensorflow_hub as hub
from Dataset import Dataset
tf.reset_default_graph()
dataset = Dataset()
module = hub.Module('https://tfhub.dev/google/imagenet/inception_v3/classification/1')
logits = module(dict(images=dataset.img_data))
softmax = tf.nn.softmax(logits)
top_predictions = tf.nn.top_k(softmax, top_k, name='top_predictions')
Si
imprimimos las firmas de estos módulos, la mayoría de ellos tendrá un total de
tres firmas que son "predeterminadas", "clasificación_imagen"
e "imagen_feature_vector". Aunque la firma de
"image_feature_vector" aparece en esta categoría de módulos, esta
firma exhibirá características similares a las de la categoría de módulos de
vectores de características que se explica a continuación.
Módulos
de vectores de características
Esto
es muy similar al de los módulos de clasificación de imágenes, con la única
diferencia de que el módulo no incluye la capa de clasificación densa final. En
el ejemplo de código para esta categoría, voy a ajustar el módulo Resnet-50
para el problema de clasificación de atributos de animales con múltiples
etiquetas de Hackerearth.
Durante
la operación de ajuste, muy a menudo, se hace necesario optimizar las capas
finales del módulo además de las capas densas anexas de manera personalizada.
Durante tales escenarios, tendremos que encontrar los nombres del alcance o las
variables que deseamos ajustar. Se adjunta la parte relevante del código para
realizar dicho procedimiento en el Módulo de vectores de características.
Module =
hub.Module('https://tfhub.dev/google/imagenet/resnet_v2_50/feature_vector/1',
trainable=True) # Trainable is True since we are going to
fine-tune the model
module_features
= module(dict(images=dataset.image_data), signature="image_feature_vector",
as_dict=True)
features =
module_features["default"]
with
tf.variable_scope('CustomLayer'):
weight = tf.get_variable('weights',
initializer=tf.truncated_normal((2048, n_class)))
bias = tf.get_variable('bias',
initializer=tf.ones((n_class)))
logits = tf.nn.xw_plus_b(features, weight,
bias)
# Find out the
names of all variables present in graph
print(tf.all_variables())
# After finding
the names of variables or scope, gather the variables you wish to fine-tune
var_list =
tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, scope='CustomLayer')
var_list2 =
tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES,
scope='module/resnet_v2_50/block4')
var_list.extend(var_list2)
# Pass this set
of variables into your optimiser
optimizer =
tf.train.AdamOptimizer(learning_rate=lr).minimize(loss, var_list=var_list)
Código
de función del vector que muestra cómo ajustar las capas del módulo
Si
los nodos en el gráfico del módulo no se nombran intuitivamente (escenario muy
poco probable), tendremos que descubrir la arquitectura del módulo y luego
asignarlos a los nodos que se están imprimiendo.
En
el ejemplo de código, Se han ajustado las variables finales de las pocas capas
que se encuentran dentro del alcance variable de "resnet_v2_50 /
block4". Al entrenar durante 10 épocas, obtendremos un puntaje de F1 de
0.95819 sin esfuerzo para este problema.
Módulos
de clasificación de video
La
clasificación de video se refiere a categorizar la naturaleza de las actividades
que ocurren en un video clip. En el ejemplo de código, se ha entrenado el
conjunto de datos 20BN-Jester que consta de 27 clases en el módulo Inception
3D. Nuevamente, con solo 3 épocas de entrenamiento, he logrado un puntaje de
91.45% de precisión. La parte relevante del código del módulo se muestra a
continuación.
import tensorflow as tf
import
tensorflow_hub as hub
from Dataset
import Dataset
dataset =
Dataset()
module =
hub.Module("https://tfhub.dev/deepmind/i3d-kinetics-400/1",
trainable=True)
features =
module(dict(rgb_input=dataset.image_data))
n_class = 27
with
tf.variable_scope('CustomLayer'):
weight = tf.get_variable('weights',
initializer=tf.truncated_normal((400, n_class)))
bias = tf.get_variable('bias',
initializer=tf.ones((n_class)))
logits =
tf.nn.xw_plus_b(features, weight, bias)
Para
probar la precisión del modelo, se creó una aplicación simple de clasificación
de vídeo en tiempo real y aquí hay un pequeño vídeo.
Clasificación
de vídeo en tiempo real construida utilizando TensorFlow Hub
Módulos
de incrustación de texto
TensorFlow
Hub ha suministrado varios módulos de incrustación de texto no solo en inglés
sino también en varios otros idiomas como alemán, coreano, japonés, etc.,
muchos de ellos producen incrustaciones a nivel de oración y no a nivel de
oración. nivel de palabra En el ejemplo del código, se ha trabajado en el
análisis de sentimientos de Kaggle sobre la crítica de películas. Usando el
módulo de incrustaciones ELMO, se entrenó una la red usando incrustaciones
producidas a nivel de oración y palabra por separado. La red se compone de una
sola capa de LSTM bidireccional. A nivel de la oración, después de entrenar
durante 6 épocas, la precisión alcanzada fue del 65%. Adjuntando la parte
relevante del código del módulo Incorporación de texto de TensorFlow Hub
module = hub.Module('https://tfhub.dev/google/elmo/2',
trainable=True)
embeddings =
module(dict(text=dataset.text_data))
embeddings =
tf.expand_dims(embeddings, axis=1)
with tf.variable_scope('Layer1'):
cell_fw1 =
tf.nn.rnn_cell.LSTMCell(num_units=128, state_is_tuple=True)
cell_bw1 =
tf.nn.rnn_cell.LSTMCell(num_units=128, state_is_tuple=True)
outputs1, states1 =
tf.nn.bidirectional_dynamic_rnn(
cell_fw=cell_fw1,
cell_bw=cell_bw1,
inputs=embeddings)
rnn_output =
tf.reshape(outputs1[0], (-1, 128))
with
tf.variable_scope('Layer2'):
weight2 = tf.get_variable('weight',
initializer=tf.truncated_normal((128, n_class)))
bias2 = tf.get_variable('bias',
initializer=tf.ones(n_class))
logits =
tf.nn.xw_plus_b(rnn_output, weight2, bias2)
Módulos
de aumento de imagen
El
aumento de imagen es un componente esencial en el proceso de capacitación para
aumentar la precisión de una red. Ninguno de los módulos de aumento de imagen
tiene ninguna variable en ellos, y en consecuencia, estos módulos no son
ajustables / entrenables. Con la firma de "from_decoded_images",
podemos alimentar directamente las imágenes a estos módulos. A continuación se
muestra un bloque de código de ejemplo junto con las imágenes aumentadas
generadas.
import tensorflow as tf
import
tensorflow_hub as hub
import
tensorflow.contrib.image #
Needed for Image Augmentation modules
from Dataset
import Dataset
dataset =
Dataset()
module =
hub.Module('https://tfhub.dev/google/image_augmentation/nas_svhn/1')
input_dict =
dict(image_size=image_size, # Output Image size
images=dataset.img_data, # Has the image in Numpy data format
augmentation=True)
aug_images = module(input_dict,
signature='from_decoded_images')
La
utilidad real del aumento de imagen se produce cuando agrupamos este módulo con
otros módulos de clasificación de imágenes, vector de características, etc. En
el problema de clasificación de atributos de animales multi-etiqueta
previamente entrenado usando el módulo Feature Vector, se agregó el módulo de
aumento de imagen crop_color, y con el mismo número de épocas, el puntaje F1
mejora a 0.96244. En este ejemplo de código, se utiliza la firma
predeterminada, que esperará que la imagen en forma codificada sea su entrada.
Ahora, a medida que el módulo de aumento de imagen redimensiona la imagen de
entrada a un tamaño fijo para su posterior procesamiento por el módulo
Resnet50, se ha guardado el trabajo de cambiar explícitamente el tamaño de las
imágenes, lo que había hecho anteriormente.
import tensorflow as tf
import
tensorflow_hub as hub
import
tensorflow.contrib.image #
Needed for Image Augmentation modules
aug_module =
hub.Module('https://tfhub.dev/google/image_augmentation/crop_color/1')
aug_features =
aug_module(dict(encoded_images=dataset.encoded_img_data,
image_size=image_size,
augmentation=is_training)) # No
augmentation needed for test and validation pipeline
resnet_module = hub.Module('https://tfhub.dev/google/imagenet/resnet_v2_50/feature_vector/1',
trainable=True)
img_features =
resnet_module(dict(images=aug_features))
with
tf.variable_scope('CustomLayer'):
weight = tf.get_variable('weights',
initializer=tf.truncated_normal((2048, n_class)))
bias = tf.get_variable('bias',
initializer=tf.ones((n_class)))
logits =
tf.nn.xw_plus_b(img_features, weight, bias)
Módulos
de detección de objetos
Los
módulos de detección de objetos no son compatibles con el ajuste fino, por lo
que tendremos que realizar un entrenamiento desde cero si tiene su propio
conjunto de datos. El procesamiento por lotes de los datos tampoco es
compatible en este momento. En el ejemplo de código, solo realizaremos
inferencias en las imágenes usando FasterRCNN en el módulo Inception-ResNet V2.
Se ha adjuntado la parte del módulo de código e imágenes generadas a partir del
módulo a continuación.
import tensorflow as tf
import
tensorflow_hub as hub
from Dataset
import Dataset
dataset =
Dataset()
module =
hub.Module('https://tfhub.dev/google/faster_rcnn/openimages_v4/inception_resnet_v2/1')
detector =
module(dict(images=dataset.image_data), as_dict=True)
class_entities =
detector['detection_class_entities']
boxes =
detector['detection_boxes']
scores =
detector['detection_scores']
class_labels =
detector['detection_class_labels']
class_names = detector['detection_class_names']
Módulos
generadores
Estos
corresponden a Redes Adversales Generativas (GAN). Algunos de los módulos no
han expuesto su parte Discriminadora de la red. Al igual que la detección de
objetos, incluso aquí en la muestra de código, solo realizaremos inferencia.
Usando el módulo Progressive GANs que está capacitado en el conjunto de datos
CelebA, generaremos nuevas caras. Se ha adjuntado la parte del módulo de código
e imágenes generadas a partir del módulo a continuación.
import tensorflow as tf
import
tensorflow_hub as hub
from Dataset
import Dataset
dataset =
Dataset()
module =
hub.Module("https://tfhub.dev/google/progan-128/1")
images = module(dataset.latent_vector_space)
Para
ver el código completo integrado con Dataset e Iterators, y guardado con
Saved_Model, consultar el código en el repositorio de GitHub.