33.9 C
Colombia
lunes, julio 7, 2025

Weblog de Posit AI: Entrenamiento de ImageNet con R



Weblog de Posit AI: Entrenamiento de ImageNet con R

ImagenNet (Deng et al. 2009) es una base de datos de imágenes organizada según el WordNet (molinero 1995) jerarquía que, históricamente, se ha utilizado en investigaciones y evaluaciones comparativas de visión por computadora. Sin embargo, no fue hasta AlexNet (Krizhevsky, Sutskever y Hinton 2012) demostró la eficiencia del aprendizaje profundo utilizando redes neuronales convolucionales en GPU, por lo que la disciplina de la visión por computadora recurrió al aprendizaje profundo para lograr modelos de última generación que revolucionaron su campo. Dada la importancia de ImageNet y AlexNet, esta publicación presenta herramientas y técnicas a considerar al entrenar ImageNet y otros conjuntos de datos a gran escala con R.

Ahora, para procesar ImageNet, primero tendremos que divide y vencerásdividiendo el conjunto de datos en varios subconjuntos manejables. Luego, entrenaremos ImageNet usando AlexNet en múltiples GPU e instancias informáticas. Preprocesamiento de ImageNet y entrenamiento distribuido son los dos temas que esta publicación presentará y discutirá, comenzando con el preprocesamiento de ImageNet.

Preprocesamiento de ImageNet

Cuando se trabaja con grandes conjuntos de datos, incluso tareas simples como descargar o leer un conjunto de datos pueden ser mucho más difíciles de lo que cabría esperar. Por ejemplo, dado que ImageNet tiene un tamaño aproximado de 300 GB, deberá asegurarse de tener al menos 600 GB de espacio libre para dejar algo de espacio para la descarga y la descompresión. Pero no te preocupes, siempre puedes pedir prestados ordenadores con grandes unidades de disco a tu proveedor de nube favorito. Mientras lo hace, también debe solicitar instancias informáticas con múltiples GPU, unidades de estado sólido (SSD) y una cantidad razonable de CPU y memoria. Si desea utilizar la configuración exacta que utilizamos, eche un vistazo a la mlverso/imagenet repo, que contiene una imagen de Docker y comandos de configuración necesarios para proporcionar recursos informáticos razonables para esta tarea. En resumen, asegúrese de tener acceso a suficientes recursos informáticos.

Ahora que tenemos recursos capaces de trabajar con ImageNet, necesitamos encontrar un lugar desde donde descargar ImageNet. La forma más sencilla es utilizar una variación de ImageNet utilizada en el Desafío de reconocimiento visible a gran escala de ImageNet (ILSVRC)que contiene un subconjunto de aproximadamente 250 GB de datos y se puede descargar fácilmente desde muchos Kaggle competiciones, como la Desafío de localización de objetos ImageNet.

Si ha leído algunas de nuestras publicaciones anteriores, es posible que ya esté pensando en utilizar el patas paquete, que puede utilizar para: almacenar en caché, descubrir y compartir recursos de muchos servicios, incluido Kaggle. Puede obtener más información sobre la recuperación de datos de Kaggle en el Usando tableros Kaggle artículo; Mientras tanto, supongamos que ya está familiarizado con este paquete.

Todo lo que tenemos que hacer ahora es registrar el tablero Kaggle, recuperar ImageNet como pin y descomprimir este archivo. Advertencia, el siguiente código requiere que mires fijamente una barra de progreso durante, potencialmente, más de una hora.

library(pins)
board_register("kaggle", token = "kaggle.json")

pin_get("c/imagenet-object-localization-challenge", board = "kaggle")[1] %>%
  untar(exdir = "/localssd/imagenet/")

Si vamos a entrenar este modelo una y otra vez usando múltiples GPU e incluso múltiples instancias informáticas, queremos asegurarnos de no perder demasiado tiempo descargando ImageNet cada vez.

La primera mejora a considerar es conseguir un disco duro más rápido. En nuestro caso, montamos localmente una serie de SSD en el /localssd camino. Luego usamos /localssd para extraer ImageNet y configurar la ruta temporal de R y el caché de pines para usar los SSD también. Consulte la documentación de su proveedor de nube para configurar SSD o eche un vistazo a mlverso/imagenet.

A continuación, un enfoque bien conocido que podemos seguir es dividir ImageNet en fragmentos que se pueden descargar individualmente para realizar una capacitación distribuida más adelante.

Además, también es más rápido descargar ImageNet desde una ubicación cercana, idealmente desde una URL almacenada en el mismo centro de datos donde se encuentra nuestra instancia en la nube. Para esto, también podemos usar pines para registrar un tablero con nuestro proveedor de nube y luego volver a cargar cada partición. Dado que ImageNet ya está particionado por categoría, podemos dividir fácilmente ImageNet en varios archivos zip y volver a cargarlos en nuestro centro de datos más cercano de la siguiente manera. Asegúrese de que el depósito de almacenamiento se cree en la misma región que sus instancias informáticas.

board_register("<board>", identify = "imagenet", bucket = "r-imagenet")

train_path <- "/localssd/imagenet/ILSVRC/Information/CLS-LOC/practice/"
for (path in dir(train_path, full.names = TRUE)) {
  dir(path, full.names = TRUE) %>%
    pin(identify = basename(path), board = "imagenet", zip = TRUE)
}

Ahora podemos recuperar un subconjunto de ImageNet de manera bastante eficiente. Si está motivado para hacerlo y tiene aproximadamente un gigabyte de sobra, no dude en seguir ejecutando este código. Observe que ImageNet contiene lotes de imágenes JPEG para cada categoría de WordNet.

board_register("https://storage.googleapis.com/r-imagenet/", "imagenet")

classes <- pin_get("classes", board = "imagenet")
pin_get(classes$id[1], board = "imagenet", extract = TRUE) %>%
  tibble::as_tibble()
# A tibble: 1,300 x 1
   worth                                                           
   <chr>                                                           
 1 /localssd/pins/storage/n01440764/n01440764_10026.JPEG
 2 /localssd/pins/storage/n01440764/n01440764_10027.JPEG
 3 /localssd/pins/storage/n01440764/n01440764_10029.JPEG
 4 /localssd/pins/storage/n01440764/n01440764_10040.JPEG
 5 /localssd/pins/storage/n01440764/n01440764_10042.JPEG
 6 /localssd/pins/storage/n01440764/n01440764_10043.JPEG
 7 /localssd/pins/storage/n01440764/n01440764_10048.JPEG
 8 /localssd/pins/storage/n01440764/n01440764_10066.JPEG
 9 /localssd/pins/storage/n01440764/n01440764_10074.JPEG
10 /localssd/pins/storage/n01440764/n01440764_1009.JPEG 
# … with 1,290 extra rows

Al realizar entrenamiento distribuido a través de ImageNet, ahora podemos permitir que una única instancia informática procese una partición de ImageNet con facilidad. Digamos que se puede recuperar y extraer 1/16 de ImageNet, en menos de un minuto, mediante descargas paralelas con el llamar paquete:

classes <- pin_get("classes", board = "imagenet")
classes <- classes$id[1:(length(categories$id) / 16)]

procs <- lapply(classes, operate(cat)
  callr::r_bg(operate(cat) {
    library(pins)
    board_register("https://storage.googleapis.com/r-imagenet/", "imagenet")
    
    pin_get(cat, board = "imagenet", extract = TRUE)
  }, args = listing(cat))
)
  
whereas (any(sapply(procs, operate(p) p$is_alive()))) Sys.sleep(1)

Podemos resumir esta partición en una lista que contiene un mapa de imágenes y categorías, que luego usaremos en nuestro modelo AlexNet a través de conjuntos de datos tf.

information <- listing(
    picture = unlist(lapply(classes, operate(cat) {
        pin_get(cat, board = "imagenet", obtain = FALSE)
    })),
    class = unlist(lapply(classes, operate(cat) {
        rep(cat, size(pin_get(cat, board = "imagenet", obtain = FALSE)))
    })),
    classes = classes
)

¡Excelente! Estamos a mitad de camino entrenando ImageNet. La siguiente sección se centrará en presentar la capacitación distribuida utilizando múltiples GPU.

Entrenamiento distribuido

Ahora que hemos dividido ImageNet en partes manejables, podemos olvidarnos por un segundo del tamaño de ImageNet y centrarnos en entrenar un modelo de aprendizaje profundo para este conjunto de datos. Sin embargo, es possible que cualquier modelo que elijamos requiera una GPU, incluso para un subconjunto de 1/16 de ImageNet. Así que asegúrese de que sus GPU estén configuradas correctamente ejecutando is_gpu_available(). Si necesita ayuda para configurar una GPU, el Usando GPU con TensorFlow y Docker El vídeo puede ayudarle a ponerse al día.

[1] TRUE

Ahora podemos decidir qué modelo de aprendizaje profundo sería mejor para las tareas de clasificación de ImageNet. En cambio, para esta publicación, retrocederemos en el tiempo a los días de gloria de AlexNet y usaremos el r-tensorflow/alexnet repositorio en su lugar. Este repositorio contiene un puerto de AlexNet a R, pero tenga en cuenta que este puerto no ha sido probado y no está listo para ningún caso de uso actual. De hecho, agradeceríamos que las relaciones públicas lo mejoraran si alguien se siente inclinado a hacerlo. De todos modos, el enfoque de esta publicación está en los flujos de trabajo y las herramientas, no en lograr puntuaciones de clasificación de imágenes de última generación. Así que, por supuesto, siéntete libre de utilizar modelos más apropiados.

Una vez que hayamos elegido un modelo, queremos asegurarnos de que se entrene correctamente en un subconjunto de ImageNet:

remotes::install_github("r-tensorflow/alexnet")
alexnet::alexnet_train(information = information)
Epoch 1/2
 103/2269 [>...............] - ETA: 5:52 - loss: 72306.4531 - accuracy: 0.9748

¡Hasta ahora, todo bien! Sin embargo, esta publicación trata sobre cómo habilitar el entrenamiento a gran escala en múltiples GPU, por lo que queremos asegurarnos de usar tantas como podamos. Desafortunadamente, corriendo nvidia-smi Mostrará que actualmente solo se utiliza una GPU:

+-----------------------------------------------------------------------------+
| NVIDIA-SMI 418.152.00   Driver Model: 418.152.00   CUDA Model: 10.1     |
|-------------------------------+----------------------+----------------------+
| GPU  Identify        Persistence-M| Bus-Id        Disp.A | Risky Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Utilization/Cap|         Reminiscence-Utilization | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  Tesla K80           Off  | 00000000:00:05.0 Off |                    0 |
| N/A   48C    P0    89W / 149W |  10935MiB / 11441MiB |     28%      Default |
+-------------------------------+----------------------+----------------------+
|   1  Tesla K80           Off  | 00000000:00:06.0 Off |                    0 |
| N/A   74C    P0    74W / 149W |     71MiB / 11441MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+
                                                                               
+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Reminiscence |
|  GPU       PID   Kind   Course of identify                             Utilization      |
|=============================================================================|
+-----------------------------------------------------------------------------+

Para entrenar en múltiples GPU, necesitamos definir una estrategia de procesamiento distribuido. Si se trata de un concepto nuevo, podría ser un buen momento para echar un vistazo a Entrenamiento distribuido con Keras tutorial y el entrenamiento distribuido con TensorFlow documentos. O, si nos permite simplificar demasiado el proceso, todo lo que tiene que hacer es definir y compilar su modelo en el alcance correcto. Una explicación paso a paso está disponible en el Aprendizaje profundo distribuido con TensorFlow y R video. En este caso, el alexnet modelo ya apoya un parámetro de estrategia, por lo que todo lo que tenemos que hacer es pasarlo.

library(tensorflow)
technique <- tf$distribute$MirroredStrategy(
  cross_device_ops = tf$distribute$ReductionToOneDevice())

alexnet::alexnet_train(information = information, technique = technique, parallel = 6)

Aviso también parallel = 6 que configura tfdatasets para hacer uso de múltiples CPU al cargar datos en nuestras GPU, consulte Mapeo paralelo para más detalles.

Ahora podemos volver a ejecutar nvidia-smi Para validar que se estén utilizando todas nuestras GPU:

+-----------------------------------------------------------------------------+
| NVIDIA-SMI 418.152.00   Driver Model: 418.152.00   CUDA Model: 10.1     |
|-------------------------------+----------------------+----------------------+
| GPU  Identify        Persistence-M| Bus-Id        Disp.A | Risky Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Utilization/Cap|         Reminiscence-Utilization | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  Tesla K80           Off  | 00000000:00:05.0 Off |                    0 |
| N/A   49C    P0    94W / 149W |  10936MiB / 11441MiB |     53%      Default |
+-------------------------------+----------------------+----------------------+
|   1  Tesla K80           Off  | 00000000:00:06.0 Off |                    0 |
| N/A   76C    P0   114W / 149W |  10936MiB / 11441MiB |     26%      Default |
+-------------------------------+----------------------+----------------------+
                                                                               
+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Reminiscence |
|  GPU       PID   Kind   Course of identify                             Utilization      |
|=============================================================================|
+-----------------------------------------------------------------------------+

El MirroredStrategy puede ayudarnos a escalar hasta aproximadamente 8 GPU por instancia informática; sin embargo, es possible que necesitemos 16 instancias con 8 GPU cada una para entrenar ImageNet en un tiempo razonable (consulte la publicación de Jeremy Howard sobre Formación Imagenet en 18 Minutos). Entonces, ¿adónde vamos desde aquí?

Bienvenido a MultiWorkerMirroredStrategy: Esta estrategia puede utilizar no solo varias GPU, sino también varias GPU en varias computadoras. Para configurarlos solo tenemos que definir un TF_CONFIG variable de entorno con las direcciones correctas y ejecute exactamente el mismo código en cada instancia informática.

library(tensorflow)

partition <- 0
Sys.setenv(TF_CONFIG = jsonlite::toJSON(listing(
    cluster = listing(
        employee = c("10.100.10.100:10090", "10.100.10.101:10090")
    ),
    activity = listing(kind = 'employee', index = partition)
), auto_unbox = TRUE))

technique <- tf$distribute$MultiWorkerMirroredStrategy(
  cross_device_ops = tf$distribute$ReductionToOneDevice())

alexnet::imagenet_partition(partition = partition) %>%
  alexnet::alexnet_train(technique = technique, parallel = 6)

Por favor tenga en cuenta que partition debe cambiar para cada instancia informática para identificarla de forma única, y que las direcciones IP también deben ajustarse. Además, information debería apuntar a una partición diferente de ImageNet, que podemos recuperar con pins; aunque, por comodidad, alexnet contiene un código comparable bajo alexnet::imagenet_partition(). Aparte de eso, el código que necesita ejecutar en cada instancia informática es exactamente el mismo.

Sin embargo, si usáramos 16 máquinas con 8 GPU cada una para entrenar ImageNet, ejecutar código manualmente en cada sesión de R llevaría mucho tiempo y sería propenso a errores. Entonces, en lugar de eso, deberíamos pensar en hacer uso de marcos de computación en clúster, como Apache Spark con ejecución de barrera. Si es nuevo en Spark, hay muchos recursos disponibles en sparklyr.ai. Para obtener más información sobre cómo ejecutar Spark y TensorFlow juntos, vea nuestro Aprendizaje profundo con Spark, TensorFlow y R video.

En conjunto, el entrenamiento de ImageNet en R con TensorFlow y Spark se ve de la siguiente manera:

library(sparklyr)
sc <- spark_connect("yarn|mesos|and so on", config = listing("sparklyr.shell.num-executors" = 16))

sdf_len(sc, 16, repartition = 16) %>%
  spark_apply(operate(df, barrier) {
      library(tensorflow)

      Sys.setenv(TF_CONFIG = jsonlite::toJSON(listing(
        cluster = listing(
          employee = paste(
            gsub(":[0-9]+$", "", barrier$tackle),
            8000 + seq_along(barrier$tackle), sep = ":")),
        activity = listing(kind = 'employee', index = barrier$partition)
      ), auto_unbox = TRUE))
      
      if (is.null(tf_version())) install_tensorflow()
      
      technique <- tf$distribute$MultiWorkerMirroredStrategy()
    
      end result <- alexnet::imagenet_partition(partition = barrier$partition) %>%
        alexnet::alexnet_train(technique = technique, epochs = 10, parallel = 6)
      
      end result$metrics$accuracy
  }, barrier = TRUE, columns = c(accuracy = "numeric"))

Esperamos que esta publicación le brinde una descripción basic razonable de cómo es el entrenamiento de grandes conjuntos de datos en R. ¡Gracias por seguir leyendo!

Deng, Jia, Wei Dong, Richard Socher, Li-Jia Li, Kai Li y Li Fei-Fei. 2009. “Imagenet: una base de datos de imágenes jerárquica a gran escala”. En Conferencia IEEE 2009 sobre visión por computadora y reconocimiento de patrones248–55. Es decir.

Krizhevsky, Alex, Ilya Sutskever y Geoffrey E Hinton. 2012. “Clasificación de Imagenet con redes neuronales convolucionales profundas”. En Avances en los sistemas de procesamiento de información neuronal1097-1105.

Molinero, George A. 1995. “WordNet: una base de datos léxica para inglés”. Comunicaciones de la ACM 38 (11): 39–41.

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles