Imagenet (Deng et al. 2009) é um banco de dados de imagem organizado de acordo com o WordNet (Miller 1995) Hierarquia que, historicamente, tem sido usada em benchmarks e pesquisas de visão computacional. No entanto, não foi até Alexnet (Krizhevsky, Sutskever e Hinton 2012) demonstraram a eficiência do aprendizado profundo usando redes neurais convolucionais nas GPUs de que a disciplina de visão de computador se transformou em um aprendizado profundo para alcançar modelos de ponta que revolucionavam seu campo. Dada a importância do ImageNet e AlexNet, este publish apresenta ferramentas e técnicas a serem consideradas ao treinar ImageNet e outros conjuntos de dados em larga escala com R.
Agora, para processar o imagenet, teremos que primeiro teremos que dividir e conquistarparticionando o conjunto de dados em vários subconjuntos gerenciáveis. Posteriormente, treinaremos o ImageNet usando o Alexnet em várias GPUs e calcular instâncias. Imagenet de pré -processamento e treinamento distribuído são os dois tópicos que este publish apresentará e discutirão, começando com o pré -processamento da imagem.
Imagenet de pré -processamento
Ao lidar com conjuntos de dados grandes, mesmo tarefas simples, como baixar ou ler um conjunto de dados, podem ser muito mais difíceis do que você esperaria. Por exemplo, como o ImageNet tem cerca de 300 GB de tamanho, você precisará ter pelo menos 600 GB de espaço livre para deixar espaço para obtain e descompressão. Mas não se preocupe, você sempre pode emprestar computadores com enormes unidades de disco do seu provedor de nuvem favorito. Enquanto você estiver nisso, você também deve solicitar instâncias de computação com várias GPUs, unidades de estado sólido (SSDs) e uma quantidade razoável de CPUs e memória. Se você quiser usar a configuração exata que usamos, dê uma olhada no mlverse/imagenet repo, que contém uma imagem do docker e comandos de configuração necessários para provisionar recursos de computação razoável para esta tarefa. Em resumo, verifique se você tem acesso a recursos de computação suficientes.
Agora que temos recursos capazes de trabalhar com o ImageNet, precisamos encontrar um lugar para baixar o ImageNet. A maneira mais fácil é usar uma variação de imagenet usada no Desafio de reconhecimento visible em larga escala ImageNet (ILSVRC)que contém um subconjunto de cerca de 250 GB de dados e pode ser facilmente baixado de muitos Kaggle competições, como o Desafio de localização de objetos ImageNet.
Se você leu algumas de nossas postagens anteriores, você já está pensando em usar o pinos Pacote, para o qual você pode usar: cache, descubra e compartilhe recursos de muitos serviços, incluindo Kaggle. Você pode aprender mais sobre a recuperação de dados de Kaggle no Usando placas Kaggle artigo; Enquanto isso, vamos supor que você já esteja familiarizado com este pacote.
Tudo o que precisamos fazer agora é registrar a placa Kaggle, recuperar o imagenet como um pino e descomprimir esse arquivo. Aviso, o código a seguir exige que você olhe para uma barra de progresso por, potencialmente, mais de uma hora.
Se vamos treinar esse modelo repetidamente usando várias GPUs e até várias instâncias de computação, queremos ter certeza de que não perdemos muito tempo baixando o ImageNet todas as vezes.
A primeira melhoria a considerar é obter um disco rígido mais rápido. No nosso caso, montamos localmente uma variedade de SSDs no /localssd
caminho. Nós então usamos /localssd
Para extrair o ImageNet e configurar o caminho da temperatura e o cache de pinos de R para usar os SSDs também. Consulte a documentação do seu provedor de nuvem para configurar SSDs ou dê uma olhada mlverse/imagenet.
Em seguida, uma abordagem bem conhecida que podemos seguir é dividir o ImageNet em pedaços que podem ser baixados individualmente para executar o treinamento distribuído posteriormente.
Além disso, também é mais rápido baixar o ImageNet de um native próximo, idealmente de um URL armazenado no mesmo information heart em que nossa instância em nuvem está localizada. Para isso, também podemos usar pinos para registrar uma placa com nosso provedor de nuvem e depois re-applar cada partição. Como o ImageNet já é particionado por categoria, podemos facilmente dividir o ImageNet em vários arquivos ZIP e reaparecer ao nosso information heart mais próximo da seguinte forma. Verifique se o balde de armazenamento é criado na mesma região que suas instâncias de computação.
Agora podemos recuperar um subconjunto de imagenet com bastante eficiência. Se você estiver motivado para fazê -lo e tem cerca de um gigabyte de sobra, fique à vontade para seguir a execução deste código. Observe que o imagenet contém muito de imagens JPEG para cada categoria 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
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
Ao fazer treinamento distribuído no ImageNet, agora podemos deixar uma única instância de computação processar uma partição do ImageNet com facilidade. Digamos, 1/16 do imagenet pode ser recuperado e extraído, em menos de um minuto, usando downloads paralelos com o Callr pacote:
classes <- pin_get("classes", board = "imagenet")
classes <- classes$id(1:(size(classes$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 encerrar essa partição em uma lista contendo um mapa de imagens e categorias, que mais tarde usaremos em nosso modelo Alexnet através tfdatasets.
Ótimo! Estamos no meio do caminho para treinar imagenet. A próxima seção se concentrará na introdução de treinamento distribuído usando várias GPUs.
Treinamento distribuído
Agora que quebramos o ImageNet em peças gerenciáveis, podemos esquecer um segundo sobre o tamanho do ImageNet e focar no treinamento de um modelo de aprendizado profundo para esse conjunto de dados. No entanto, qualquer modelo que escolhemos provavelmente exigirá uma GPU, mesmo para um subconjunto de 1/16 do ImageNet. Portanto, verifique se suas GPUs estão configuradas corretamente executando is_gpu_available()
. Se você precisar de ajuda para configurar uma GPU, o Usando GPUs com Tensorflow e Docker O vídeo pode ajudá -lo a acelerar.
(1) TRUE
Agora podemos decidir qual modelo de aprendizado profundo seria melhor adequado para tarefas de classificação do ImageNet. Em vez disso, para este publish, voltaremos no tempo aos dias de glória de Alexnet e usaremos o R-TensorFlow/AlexNet repo. Este repo contém uma porta de Alexnet para R, mas observe que esta porta não foi testada e não está pronta para nenhum caso de uso actual. De fato, apreciaríamos o PRS para melhorá -lo se alguém se sentir inclinado a fazê -lo. Independentemente disso, o foco desta postagem está nos fluxos de trabalho e ferramentas, não sobre a obtenção de pontuações de classificação de imagem de última geração. Portanto, por todos os meios, sinta -se à vontade para usar modelos mais apropriados.
Depois de escolhermos um modelo, vamos querer garantir que ele treine corretamente em um 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
Até agora tudo bem! No entanto, este publish é sobre o treinamento em larga escala em várias GPUs, por isso queremos garantir que estamos usando o máximo possível. Infelizmente, correndo nvidia-smi
mostrará que apenas uma GPU está sendo usada atualmente:
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 418.152.00 Driver Model: 418.152.00 CUDA Model: 10.1 |
|-------------------------------+----------------------+----------------------+
| GPU Title Persistence-M| Bus-Id Disp.A | Unstable 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 treinar várias GPUs, precisamos definir uma estratégia de processamento distribuído. Se este é um novo conceito, pode ser um bom momento para dar uma olhada no Treinamento distribuído com Keras tutorial e o Treinamento distribuído com tensorflow documentos. Ou, se você nos permitir simplificar demais o processo, tudo o que você precisa fazer é definir e compilar seu modelo no escopo certo. Uma explicação passo a passo está disponível no Aprendizado profundo distribuído com tensorflow e r vídeo. Nesse caso, o alexnet
modelo já suporta Um parâmetro de estratégia, então tudo o que precisamos fazer é transmiti -lo.
library(tensorflow)
technique <- tf$distribute$MirroredStrategy(
cross_device_ops = tf$distribute$ReductionToOneDevice())
alexnet::alexnet_train(information = information, technique = technique, parallel = 6)
Observe também parallel = 6
que configura tfdatasets
Para fazer uso de várias CPUs ao carregar dados em nossas GPUs, consulte Mapeamento paralelo Para detalhes.
Agora podemos voltar novamente nvidia-smi
Para validar todas as nossas GPUs, estão sendo usadas:
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 418.152.00 Driver Model: 418.152.00 CUDA Model: 10.1 |
|-------------------------------+----------------------+----------------------+
| GPU Title Persistence-M| Bus-Id Disp.A | Unstable 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 |
|=============================================================================|
+-----------------------------------------------------------------------------+
O MirroredStrategy
pode nos ajudar a escalar até cerca de 8 GPUs por instância de computação; No entanto, é provável que precisemos de 16 instâncias com 8 GPUs cada para treinar Imagenet em um tempo razoável (consulte a postagem de Jeremy Howard no Treinando imagenet em 18 minutos). Então, para onde vamos daqui?
Bem -vindo a MultiWorkerMirroredStrategy
: Essa estratégia pode usar não apenas várias GPUs, mas também várias GPUs em vários computadores. Para configurá -los, tudo o que precisamos fazer é definir um TF_CONFIG
Variável de ambiente com os endereços corretos e execute exatamente o mesmo código em cada instância de computação.
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(sort = '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)
Observe isso partition
Deve mudar para cada instância de computação para identificá -la exclusiva e que os endereços IP também precisam ser ajustados. Além disso, information
deve apontar para uma partição diferente do imagenet, com a qual podemos recuperar pins
; Embora, por conveniência, alexnet
contém código semelhante em alexnet::imagenet_partition()
. Fora isso, o código que você precisa executar em cada instância de computação é exatamente o mesmo.
No entanto, se usássemos 16 máquinas com 8 GPUs cada para treinar o Imagenet, seria bastante demorado e propenso a erros para executar manualmente o código em cada sessão R. Então, em vez disso, devemos pensar em fazer uso de estruturas de computação em cluster, como o Apache Spark com execução da barreira. Se você é novo no Spark, há muitos recursos disponíveis em Sparklyr.ai. Para aprender a executar o Spark e o Tensorflow juntos, assista ao nosso Aprendizado profundo com faísca, tensorflow e r vídeo.
Juntando tudo, treinando ImageNet em r com tensorflow e faísca parece:
library(sparklyr)
sc <- spark_connect("yarn|mesos|and many others", 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$deal with),
8000 + seq_along(barrier$deal with), sep = ":")),
activity = listing(sort = 'employee', index = barrier$partition)
), auto_unbox = TRUE))
if (is.null(tf_version())) install_tensorflow()
technique <- tf$distribute$MultiWorkerMirroredStrategy()
consequence <- alexnet::imagenet_partition(partition = barrier$partition) %>%
alexnet::alexnet_train(technique = technique, epochs = 10, parallel = 6)
consequence$metrics$accuracy
}, barrier = TRUE, columns = c(accuracy = "numeric"))
Esperamos que este publish tenha dado a você uma visão geral razoável de como é o treinamento de grandes dados em R-obrigado por ler junto!
Deng, Jia, Wei Dong, Richard Socher, Li-Jia Li, Kai Li e Li Fei-Fei. 2009. “Imagenet: um banco de dados de imagem hierárquica em larga escala.” Em 2009 Conferência IEEE sobre visão computacional e reconhecimento de padrões248-55. IEEE.
Krizhevsky, Alex, Ilya Sutskever e Geoffrey E Hinton. 2012. “Classificação do ImageNet com profundas redes neurais convolucionais”. Em Avanços nos sistemas de processamento de informações neurais1097-1105.
Miller, George A. 1995. “WordNet: um banco de dados lexical para o inglês.” Comunicações do ACM 38 (11): 39–41.