TensorFlow y Pytorch son dos de las bibliotecas de aprendizaje profundo más populares recientemente. Ambas bibliotecas han desarrollado sus respectivos nichos en el aprendizaje profundo convencional con excelente documentación, tutoriales y, lo que es más importante, una comunidad exuberante y de apoyo detrás de ellos.
Diferencia entre gráficos computacionales estáticos en TensorFlow y gráficos computacionales dinámicos en Pytorch
Aunque ambas bibliotecas emplean un gráfico acíclico dirigido (o DAG) para representar sus modelos de aprendizaje automático y aprendizaje profundo, aún existe una gran diferencia entre cómo permiten que sus datos y cálculos fluyan a través del gráfico. La diferencia sutil entre las dos bibliotecas es que mientras Tensorflow (v < 2.0) permite cálculos de gráficos estáticos, Pytorch permite cálculos de gráficos dinámicos. Este artículo cubrirá estas diferencias de manera visual con ejemplos de código. El artículo asume un conocimiento práctico de los gráficos de computación y una comprensión básica de los módulos TensorFlow y Pytorch. Para un repaso rápido de estos conceptos, se sugiere al lector leer los siguientes artículos:
- Gráficos computacionales en aprendizaje profundo
- Primeros pasos con PyTorch
- Introducción a TensorFlow
Gráfico de cálculo estático en Tensorflow
Propiedades de Nodes y bordes: los Nodes representan las operaciones que se aplican directamente en los datos que entran y salen a través de los bordes. Para el conjunto de ecuaciones anterior, podemos tener en cuenta lo siguiente al implementarlo en TensorFlow:
- Dado que las entradas actúan como los bordes del gráfico, podemos usar el objeto tf.Placeholder() que puede tomar cualquier entrada del tipo de datos deseado.
- Para calcular la salida ‘c’, definimos una operación de multiplicación simple e iniciamos una sesión de tensorflow donde pasamos los valores de entrada requeridos a través del atributo feed_dict en el método session.run() para calcular las salidas y los gradientes.
Ahora implementemos los cálculos anteriores en TensorFlow y observemos cómo ocurren las operaciones:
Python3
# Importing tensorflow version 1 import tensorflow.compat.v1 as tf tf.disable_v2_behavior() # Initializing placeholder variables of # the graph a = tf.placeholder(tf.float32) b = tf.placeholder(tf.float32) # Defining the operation c = tf.multiply(a, b) # Instantiating a tensorflow session with tf.Session() as sess: # Computing the output of the graph by giving # respective input values out = sess.run(, feed_dict={a: [15.0], b: [20.0]})[0][0] # Computing the output gradient of the output with # respect to the input 'a' derivative_out_a = sess.run(tf.gradients(c, a), feed_dict={ a: [15.0], b: [20.0]})[0][0] # Computing the output gradient of the output with # respect to the input 'b' derivative_out_b = sess.run(tf.gradients(c, b), feed_dict={ a: [15.0], b: [20.0]})[0][0] # Displaying the outputs print(f'c = {out}') print(f'Derivative of c with respect to a = {derivative_out_a}') print(f'Derivative of c with respect to b = {derivative_out_b}')
Producción:
c = 300.0 Derivative of c with respect to a = 20.0 Derivative of c with respect to b = 15.0
Como podemos ver, el resultado coincide correctamente con nuestros cálculos en la sección Introducción, lo que indica que se completó con éxito. La estructura estática es evidente en el código, ya que podemos ver que una vez, dentro de una sesión, no podemos definir nuevas operaciones (o Nodes), pero seguramente podemos cambiar las variables de entrada usando el atributo feed_dict en el sess.run ( ) método.
ventajas:
- Dado que el gráfico es estático, ofrece muchas posibilidades de optimización en la estructura y distribución de recursos.
- Los cálculos son ligeramente más rápidos que un gráfico dinámico debido a la estructura fija.
Desventajas:
- Escala mal a entradas de dimensión variable. Por ejemplo, una arquitectura CNN (red neuronal convolucional) con un gráfico de cálculo estático entrenado en imágenes de 28 × 28 no funcionaría bien en imágenes de diferentes tamaños como 100 × 100 sin una gran cantidad de código repetitivo de preprocesamiento.
- Mala depuración. Estos son muy difíciles de depurar, principalmente porque el usuario no tiene acceso a cómo ocurre el flujo de información. erg: supongamos que un usuario crea un gráfico estático con formato incorrecto, el usuario no puede rastrear el error directamente hasta que la sesión de TensorFlow encuentre un error mientras calcula la propagación hacia atrás y hacia adelante. Esto se convierte en un problema importante cuando el modelo es enorme, ya que desperdicia tanto el tiempo como los recursos informáticos de los usuarios.
Gráfico de cálculo dinámico en Pytorch
Propiedades de Nodes y bordes: los Nodes representan los datos (en forma de tensores) y los bordes representan las operaciones aplicadas a los datos de entrada.
Para las ecuaciones dadas en la Introducción, podemos tener en cuenta lo siguiente al implementarlas en Pytorch:
- Dado que todo en Pytorch se crea dinámicamente, no necesitamos marcadores de posición y podemos definir nuestras entradas y operaciones sobre la marcha.
- Después de definir las entradas y calcular la salida ‘c’, llamamos al métodoBACK() , que calcula las derivadas parciales correspondientes con respecto a las dos entradas accesibles a través del especificador .grad .
Ahora veamos un ejemplo de código para verificar nuestros hallazgos:
Python3
# Importing torch import torch # Initializing input tensors a = torch.tensor(15.0, requires_grad=True) b = torch.tensor(20.0, requires_grad=True) # Computing the output c = a * b # Computing the gradients c.backward() # Collecting the output gradient of the # output with respect to the input 'a' derivative_out_a = a.grad # Collecting the output gradient of the # output with respect to the input 'b' derivative_out_b = b.grad # Displaying the outputs print(f'c = {c}') print(f'Derivative of c with respect to a = {derivative_out_a}') print(f'Derivative of c with respect to b = {derivative_out_b}')
Producción:
c = 300.0 Derivative of c with respect to a = 20.0 Derivative of c with respect to b = 15.0
Como podemos ver, el resultado coincide correctamente con nuestros cálculos en la sección Introducción, lo que indica que se completó con éxito. La estructura dinámica es evidente en el código. Podemos ver que se puede acceder y cambiar todas las entradas y salidas solo durante el tiempo de ejecución, lo cual es completamente diferente del enfoque utilizado por Tensorflow.
ventajas:
- Escalabilidad a diferentes entradas dimensionales: se escala muy bien para diferentes entradas dimensionales, ya que se puede agregar dinámicamente una nueva capa de preprocesamiento a la propia red.
- Facilidad de depuración: estos son muy fáciles de depurar y son una de las razones por las que muchas personas están cambiando de Tensorflow a Pytorch. Como los Nodes se crean dinámicamente antes de que la información fluya a través de ellos, el error se vuelve muy fácil de detectar ya que el usuario tiene el control total de las variables utilizadas en el proceso de capacitación.
Desventajas:
- Deja muy poco espacio para la optimización de gráficos porque es necesario crear un nuevo gráfico para cada instancia/lote de entrenamiento.
Conclusión
Este artículo arroja luz sobre la diferencia entre la estructura de modelado de Tensorflow y Pytorch. El artículo también enumera algunas ventajas y desventajas de ambos enfoques mediante ejemplos de código. Las respectivas organizaciones detrás del desarrollo de estas bibliotecas continúan mejorando en iteraciones posteriores, pero el lector ahora puede tomar una decisión mejor informada antes de elegir el mejor marco para su próximo proyecto.
Publicación traducida automáticamente
Artículo escrito por adityasaini70 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA