Gema Parreño Senior Data Scientist

The Lord of the Words: Os Dois Frameworks

Na PyCon 2023, em Espanha, explorámos um mundo fascinante de Inteligência Artificial através da lente dos Transformers: estes modelos revolucionaram a forma como compreendemos e trabalhamos com o Processamento de Linguagem Natural (NLP) e até mesmo noutros campos, e nesta keynote, mergulhamos na sua arquitetura, nos avanços do campo, na exploração dentro da tarefa de tradução e a emocionante comparação de duas das principais frameworks de IA de código aberto: Tensorflow e Pytorch, no contexto da biblioteca Transformers da HuggingFace.

Transformers: para além das palavras

O Transformer traz consigo uma inovação fundamental subjacente: o mecanismo de auto-attention. Este mecanismo permite-nos compreender melhor o contexto de uma frase e confere ao modelo a capacidade de focagem.

Fig1. Nesta frase, verificamos que a palavra "right” tem significados diferentes consoante o contexto. O mecanismo de self-attention permite distinguir entre a correção de "right" e a direção de "right" para exatamente onde está Moria.

Para além das inúmeras demonstrações e pequenos projetos, estamos a assistir ao lançamento de modelos pré-treinados através de código aberto e à adoção em massa da IA em produtos de software, onde tanto as técnicas de desenvolvimento como as de IA estão a ser normalizadas através de novas ferramentas e processos.

Estamos a assistir ao lançamento de modelos pré-treinados através de código aberto e à adoção em massa da IA em produtos de software, em que a IA e as técnicas de desenvolvimento estão a ser normalizadas através de novas ferramentas e processos.

Como guia nesta exploração, utilizamos a valiosa biblioteca Transformers da HuggingFace, que se tornou a "Rivendell da Machine Learning": tal como Frodo e Sam se aventuram em direção à montanha do destino, também nós nos aventuramos na engenharia de modelos linguísticos pré-treinados. Mas em vez de um anel, levamos connosco a capacidade de carregar modelos pré-treinados para utilizá-los em várias tarefas.

Na PyCon, explorámos experiências com a biblioteca no contexto de duas frameworks suportadas diferentes: Tensorflow e Pytorch. Embora existam semelhanças a nível concetual, a verdadeira beleza reside nas diferenças sintáticas entre as estruturas, que refletem a forma como os mesmos conceitos são implementados de formas únicas.

Tal como as personagens do Senhor dos Anéis, que encontram diferentes raças e culturas na sua viagem, também nós descobriremos as particularidades destes dois mundos da IA.

Diferenças a nível de grafos

No Tensorflow, as operações são definidas antes de executar o grafo com tensores e operações e, para executar, iniciamos uma sessão com tf.Session() para otimizar os cálculos. No Pytorch, as operações são executadas imediatamente após a sua definição, o que facilita o desenvolvimento iterativo. Vale a pena notar, no entanto, como o Tensorflow evoluiu para incorporar a execução "eager" à imitação do Pytorch.

Fig2. Em Tensorflow, temos de iniciar um grafo com tf.Session(). A estrutura também sofreu uma mutação para o modo eager. No Pytorch, desde a sua conceção, não precisamos de uma sessão.

Diferenças a nível de operações de cálculo

A diferenciação automática no Tensorflow é conseguida através de um contexto de tape com tf.GradienTape(), enquanto no Pytorch é inerente à estrutura graças ao Autograd. Isto significa que, no Pytorch, a diferenciação automática ocorre sem a necessidade de contexto adicional. Tal como o fluxo de energia entre Saruman e Gandalf, o processo de diferenciação manifesta-se de forma diferente nestes dois frameworks.

Fig3. No Tensorflow, temos de iniciar um grafo com tf.Session(). O framework também sofreu uma mutação para o modo eager. No Pytorch, desde a sua conceção, não precisamos de uma sessão.

Gestão de Dispositivos

O Tensorflow usa tf.device() para especificar o dispositivo no qual será executado um bloco de código, enquanto o Pytorch utiliza .to(device) para mover objetos para um dispositivo específico. Ambas as abordagens oferecem controlo sobre o dispositivo, mas variam na forma como são implementadas. Tal como a escolha das armas numa batalha épica, a escolha dos dispositivos nestes frameworks pode determinar o resultado da batalha pelo desempenho.

Fig4. Pytorch atribui o dispositivo como um objeto

Gestão da memória

O PyTorch oferece um gerenciamento mais flexível da memória da GPU, permitindo o uso incremental e proporcional com métodos como memory_allocated() e memory_reserved(). O Tensorflow, por outro lado, atribui toda a GPU por padrão. Enquanto a flexibilidade do Pytorch fornece um controlo mais granular sobre os recursos, o Tensorflow parece estar a explorar estas características com a classe tf.config.experimental.

Fig5. No TensorFlow, utilizamos a classe de configuração para aprender mais sobre a memória.

Conclusões da viagem

Embora a biblioteca suporte ambos os frameworks, o Pytorch parece ser a aposta para estrutura nativa: a definição de muitas das suas classes com o Pytorch, o facto de o Pytorch apontar diretamente para o HuggingFace e o número esmagador de modelos no Pytorch (100K) em comparação com aproximadamente 10K no Tensorflow - apesar de muitos dos modelos pré-treinados estarem em ambas as estruturas - demonstram como a biblioteca parece ter-se integrado harmoniosamente no Framework.

Ao longo da nossa exploração, descobrimos que do tutorial para o script de exemplo há um salto significativo. Embora o tutorial tenha uma mentalidade comparativa muito útil entre os dois frameworks e seja extremamente didático, a pasta de exemplos no repositório GitHub da biblioteca é certamente um recurso sólido. A estrutura dos scripts e a semântica em relação às duas estruturas são bastante semelhantes.

Além disso, é essencial rever a documentação no README.md das tarefas na biblioteca Transformers da HuggingFace para compreender os modelos e os datasets dos exemplos, bem como para verificar que framework suporta o modelo no Hub. Além disso, verificámos que a integração com as plataformas de experimentação no PyTorch está bem documentada e fornece flags que facilitam a alteração de modelos e datasets.

Fig6. Resultados. 192 downloads totais do Hub dos modelos pré-treinados, o resultado da exploração. O melhor modelo, de acordo com a métrica BLEU, parece ser o modelo que traduz do inglês para o hebraico.

A magia do Open Source

Preparar a palestra e explorar a biblioteca nos dois Frameworks serviu também para contribuir para um exemplo numa docstring python para uma das classes da biblioteca no âmbito de uma good first issue, em que pude aprender sobre a evolução de uma classe no contexto do Open Source, conhecer contribuidores fantásticos - a minha eterna gratidão a ti, nablabits - e preparar contribuições para a biblioteca, bem como analisar possíveis casos de utilização.

Fig7. A forma como fechamos uma issue é tão importante como a forma como a abrimos.

Contribuir para o software de código aberto não é apenas um ato generoso, mas também um investimento valioso no crescimento pessoal e profissional. No mundo do software de código aberto, há uma dança constante entre dar e receber. Muitos de nós utilizamos software de código aberto e construímos as nossas soluções e modelos mentais com base no trabalho de outros, o que me fez refletir a vários níveis sobre o dever de retribuir à comunidade. Ao colaborar em projetos de código aberto, partilhamos os nossos conhecimentos e competências com a comunidade, contribuindo para o avanço da tecnologia e criando soluções mais robustas e fiáveis. Em troca, temos a oportunidade de aprender com os outros, melhorar as nossas próprias competências e fazer parte de uma comunidade global de mentes criativas. Este equilíbrio entre dar e receber faz lembrar a "Irmandade do Anel", em que cada membro contribui com a sua capacidade única para atingir um objetivo comum e, no processo, todos são fortalecidos e avançam para a vitória sobre as forças das trevas. Da mesma forma, ao dar, podemos ajudar a forjar um futuro tecnológico mais brilhante e mais resistente.