Posit AI Weblog: tocha fora da caixa



Posit AI Weblog: tocha fora da caixa

Para o bem ou para o mal, vivemos em um mundo em constante mudança. Focando no melhorarum exemplo notável é a abundância, bem como a rápida evolução de software program que nos ajuda a atingir nossos objetivos. Mas com essa bênção vem um desafio. Precisamos ser capazes de realmente usar esses novos recursos, instale essa nova biblioteca, integre essa nova técnica em nosso pacote.

Com torchhá tantas coisas que podemos realizar como estão, das quais apenas uma pequena fração foi sugerida neste weblog. Mas se há uma coisa para ter certeza é que nunca, jamais haverá falta de demanda por mais coisas para fazer. Aqui estão três cenários que vêm à mente.

  • carregar um modelo pré-treinado que foi definido em Python (sem precisar portar manualmente todo o código)

  • modificar um módulo de rede neural, de modo a incorporar algum novo refinamento algorítmico (sem incorrer no custo de desempenho de ter o código personalizado executado em R)

  • faça uso de uma das muitas bibliotecas de extensão disponíveis no ecossistema PyTorch (com o mínimo de esforço de codificação possível)

Esta postagem ilustrará cada um desses casos de uso em ordem. Do ponto de vista prático, isto constitui uma mudança gradual da perspectiva do usuário para a perspectiva do desenvolvedor. Mas nos bastidores, são realmente os mesmos blocos de construção que alimentam todos eles.

Habilitadores: torchexport e Torchscript

O pacote R torchexport e TorchScript (lado do PyTorch) operam em escalas muito diferentes e desempenham funções muito diferentes. No entanto, ambos são importantes neste contexto, e eu diria mesmo que o ator de “pequena escala” (torchexport) é o componente verdadeiramente essencial, do ponto de vista do usuário R. Em parte, isso ocorre porque ele aparece em todos os três cenários, enquanto o TorchScript está envolvido apenas no primeiro.

torchexport: Gerencia a “pilha de tipos” e cuida dos erros

Em R torcha profundidade da “pilha de tipos” é estonteante. O código voltado para o usuário é escrito em R; a funcionalidade de baixo nível é empacotada em libtorchuma biblioteca compartilhada C++ usada por torch bem como PyTorch. O mediador, como tantas vezes acontece, é o Rcpp. No entanto, não é aí que a história termina. Devido a incompatibilidades específicas do compilador do sistema operacional, deve haver uma camada adicional, intermediária e de ação bidirecional que remova todos os tipos C++ de um lado da ponte (Rcpp ou libtorchrespectivamente), deixando apenas ponteiros de memória bruta e adicionando-os novamente ao outro. No remaining, o resultado é uma pilha de chamadas bastante complicada. Como você pode imaginar, há uma necessidade concomitante de tratamento de erros cuidadosamente posicionado e com nível adequado, garantindo que o usuário receba informações úteis no remaining.

Agora, o que vale para torch aplica-se a todas as extensões do lado R que adicionam código personalizado ou chamam bibliotecas C++ externas. É aqui que torchexport entra. Como autor da extensão, tudo o que você precisa fazer é escrever uma pequena fração do código geral necessário – o restante será gerado por torchexport. Voltaremos a isso nos cenários dois e três.

TorchScript: permite a geração de código “on the fly”

Já encontramos TorchScript em um postagem anteriorembora de um ângulo diferente, e destacando um conjunto diferente de termos. Nesse submit, mostramos como você pode treinar um modelo em R e rastrear isso, resultando em uma representação intermediária otimizada que pode então ser salva e carregada em um ambiente diferente (possivelmente sem R). Lá, o foco conceitual estava no agente que viabiliza esse fluxo de trabalho: o PyTorch Simply-in-time Compiler (JIT) que gera a representação em questão. Mencionamos rapidamente que no lado do Python, há outra maneira de invocar o JIT: não em um modelo “vivo” instanciado, mas em código de definição de modelo com script. É essa segunda by way of, correspondentemente denominada scriptque é relevante no contexto atual.

Mesmo que o script não esteja disponível em R (a menos que o código do script seja escrito em Python), ainda nos beneficiamos de sua existência. Quando as bibliotecas de extensão do lado Python usam TorchScript (em vez do código C++ regular), não precisamos adicionar ligações às respectivas funções no lado R (C++). Em vez disso, tudo é cuidado pelo PyTorch.

Isto – embora completamente transparente para o usuário – é o que permite o cenário um. No (Python) TorchVision, os modelos pré-treinados fornecidos geralmente farão uso de operadores especiais (dependentes do modelo). Graças ao script, não precisamos adicionar uma ligação para cada operador, muito menos reimplementá-los no lado R.

Tendo delineado algumas das funcionalidades subjacentes, apresentamos agora os próprios cenários.

Cenário um: carregar um modelo pré-treinado do TorchVision

Talvez você já tenha usado um dos modelos pré-treinados disponibilizados pela TorchVision: um subconjunto deles foi portado manualmente para torchvisiono pacote R. Mas há mais deles – um muito mais. Muitos usam operadores especializados – raramente necessários fora do contexto de algum algoritmo. Parece haver pouca utilidade na criação de wrappers R para esses operadores. E, claro, o aparecimento contínuo de novos modelos exigiria esforços contínuos de portabilidade, da nossa parte.

Felizmente, existe uma solução elegante e eficaz. Toda a infraestrutura necessária é configurada pelo pacote enxuto e dedicado torchvisionlib. (Ele pode se dar ao luxo de ser enxuto devido ao uso liberal do TorchScript pelo lado do Python, conforme explicado na seção anterior. Mas para o usuário – cuja perspectiva estou adotando neste cenário – esses detalhes não precisam importar.)

Depois de instalar e carregar torchvisionlibvocê pode escolher entre um número impressionante de modelos relacionados ao reconhecimento de imagem. O processo, então, é duplo:

  1. Você instancia o modelo em Python, roteiro e salve-o.

  2. Você carrega e usa o modelo em R.

Aqui está o primeiro passo. Observe como, antes de criar o script, colocamos o modelo em eval modo, garantindo assim que todas as camadas exibam comportamento de tempo de inferência.

lltm. Este pacote tem um toque recursivo. Ao mesmo tempo, é uma instância de um C++ torch extensão, e serve como um tutorial mostrando como criar tal extensão.

O próprio README explica como o código deve ser estruturado e por quê. Se você estiver interessado em como torch em si foi projetado, esta é uma leitura elucidativa, independentemente de você planejar ou não escrever uma extensão. Além desse tipo de informação de bastidores, o README traz instruções passo a passo sobre como proceder na prática. De acordo com o propósito do pacote, o código-fonte também está ricamente documentado.

Como já foi sugerido na seção “Facilitadores”, a razão pela qual ouso escrever “tornar isso razoavelmente fácil” (referindo-se à criação de um torch extensão) é torchexporto pacote que gera automaticamente código C++ relacionado à conversão e tratamento de erros em várias camadas na “pilha de tipos”. Normalmente, você descobrirá que a quantidade de código gerado automaticamente excede significativamente a quantidade de código que você mesmo escreveu.

Cenário três: Interface para extensões PyTorch integradas/no código C++

É tudo menos improvável que, algum dia, você encontre uma extensão PyTorch que gostaria que estivesse disponível em R. Caso essa extensão fosse escrita em Python (exclusivamente), você a traduziria para R “manualmente”, fazendo uso de qualquer funcionalidade aplicável torch fornece. Às vezes, porém, essa extensão conterá uma mistura de código Python e C++. Em seguida, você precisará vincular-se à funcionalidade C++ de baixo nível de maneira análoga a como torch liga-se a libtorch – e agora, todos os requisitos de digitação descritos acima se aplicarão à sua extensão da mesma maneira.

Novamente, é torchexport que vem em socorro. E aqui, também, o lltm README ainda se aplica; acontece que, em vez de escrever seu código personalizado, você adicionará ligações a funções C++ fornecidas externamente. Feito isso, você terá torchexport crie todo o código de infraestrutura necessário.

Uma espécie de modelo pode ser encontrada no torchsparse pacote (atualmente em desenvolvimento). As funções em csrc/src/torchsparse.cpp todos ligam para PyTorch esparsocom declarações de função encontradas no arquivo desse projeto csrc/esparso.h.

Depois de integrar o código C++ externo dessa maneira, uma questão adicional poderá surgir. Tome um exemplo de torchsparse. No arquivo de cabeçalho, você notará tipos de retorno como std::tuple<:tensor torch::tensor=""/>, <:tensor torch::tensor="">>, torch::Tensor>> … e muito mais. Em R torch (a camada C++) temos torch::Tensore temos torch::non-obligatory<:tensor/>também. Mas não temos um tipo personalizado para todos os possíveis std::tuple você poderia construir. Assim como ter base torch fornecer todos os tipos de funcionalidades especializadas e específicas de domínio não é sustentável, faz pouco sentido tentar prever todos os tipos de tipos que estarão em demanda.

Conseqüentemente, os tipos devem ser definidos nos pacotes que deles necessitam. Como exatamente fazer isso é explicado no torchexport Tipos personalizados vinheta. Quando esse tipo personalizado está sendo usado, torchexport precisa ser informado como os tipos gerados, em vários níveis, devem ser nomeados. É por isso que, nesses casos, em vez de uma frase concisa //((torch::export))você verá linhas como / ((torch::export(register_types=c("tensor_pair", "TensorPair", "void*", "torchsparse::tensor_pair")))). A vinheta explica isso em detalhes.

O que vem a seguir

“O que vem a seguir” é uma forma comum de encerrar uma postagem, substituindo, digamos, “Conclusão” ou “Encerramento”. Mas aqui, isso deve ser interpretado literalmente. Esperamos fazer o nosso melhor para tornar o uso, a interface e a extensão torch tão fácil quanto possível. Portanto, informe-nos sobre quaisquer dificuldades que você esteja enfrentando ou problemas que possa enfrentar. Basta criar um problema em exportação de tocha, lltm, tochaou qualquer repositório que pareça aplicável.

Como sempre, obrigado pela leitura!

Foto de Antonino Visalli sobre Remover respingo

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *