Transformers documentation

Glossário

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v5.22.1).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Glossário

Este glossário define termos gerais de machine learning e do 🤗 Transformers para ajudá-lo a compreender melhor a documentação.

A

máscara de atenção

A attention mask é um argumento opcional usado ao agrupar sequências em lotes.

Este argumento indica ao modelo quais tokens devem ser considerados e quais devem ser ignorados.

Por exemplo, considere as seguintes duas sequências:

>>> from transformers import BertTokenizer

>>> tokenizer = BertTokenizer.from_pretrained("google-bert/bert-base-cased")

>>> sequence_a = "This is a short sequence."
>>> sequence_b = "This is a rather long sequence. It is at least longer than the sequence A."

>>> encoded_sequence_a = tokenizer(sequence_a)["input_ids"]
>>> encoded_sequence_b = tokenizer(sequence_b)["input_ids"]

As versões codificadas têm comprimentos diferentes:

>>> len(encoded_sequence_a), len(encoded_sequence_b)
(8, 19)

Portanto, não podemos colocá-los juntos no mesmo tensor como estão. A primeira sequência precisa ser preenchida até o comprimento da segunda, ou a segunda precisa ser truncada até o comprimento da primeira.

No primeiro caso, a lista de IDs será estendida pelos índices de padding. Podemos passar uma lista para o tokenizer e pedir que ele faça o padding da seguinte forma:

>>> padded_sequences = tokenizer([sequence_a, sequence_b], padding=True)

Podemos ver que 0s foram adicionados à direita da primeira frase para que ela tenha o mesmo comprimento que a segunda:

>>> padded_sequences["input_ids"]
[[101, 1188, 1110, 170, 1603, 4954, 119, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [101, 1188, 1110, 170, 1897, 1263, 4954, 119, 1135, 1110, 1120, 1655, 2039, 1190, 1103, 4954, 138, 119, 102]]

Em seguida, isso pode ser convertido em um tensor no PyTorch. A máscara de atenção é um tensor binário que indica a posição dos índices preenchidos, para que o modelo não preste atenção a eles. Para o BertTokenizer, 1 indica um valor que deve ser considerado, enquanto 0 indica um valor preenchido. Essa máscara de atenção está no dicionário retornado pelo tokenizador sob a chave “attention_mask”:

>>> padded_sequences["attention_mask"]
[[1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]

modelos de autoencoding

Veja modelos de codificador e modelagem de linguagem mascarada

modelos autoregressivos

Veja modelagem de linguagem causal e modelos decodificadores

B

backbone

O backbone é a rede (embeddings e camadas) que produz os estados ocultos brutos ou os recursos. Ele geralmente está conectado a um head, que recebe os recursos como entrada para fazer uma previsão. Por exemplo, ViTModel é um backbone sem um head específico no topo. Outros modelos também podem usar ViTModel como backbone, como o DPT.

C

modelagem de linguagem causal

Uma tarefa de pré-treinamento em que o modelo lê os textos em ordem e deve prever a próxima palavra. Geralmente, isso é feito lendo a frase inteira, mas usando uma máscara dentro do modelo para ocultar os tokens futuros em um determinado timestep.

canal

Imagens coloridas são compostas por alguma combinação de valores em três canais: vermelho, verde e azul (RGB), enquanto imagens em escala de cinza possuem apenas um canal. No 🤗 Transformers, o canal pode ser a primeira ou a última dimensão do tensor de uma imagem: [n_channels, height, width] ou [height, width, n_channels].

classificação temporal conexionista (CTC)

Um algoritmo que permite que um modelo aprenda sem saber exatamente como a entrada e a saída estão alinhadas; o CTC calcula a distribuição de todas as saídas possíveis para uma entrada dada e escolhe a saída mais provável a partir dela. O CTC é comumente usado em tarefas de reconhecimento de fala, pois a fala nem sempre se alinha perfeitamente com a transcrição, por diversas razões, como as diferentes taxas de fala de um locutor.

convolução

Um tipo de camada em uma rede neural em que a matriz de entrada é multiplicada elemento a elemento por uma matriz menor (kernel ou filtro) e os valores são somados em uma nova matriz. Isso é conhecido como uma operação de convolução, que é repetida sobre toda a matriz de entrada. Cada operação é aplicada a um segmento diferente da matriz de entrada. Redes neurais convolucionais (CNNs) são comumente usadas em visão computacional.

D

DataParallel (DP)

Técnica de paralelismo para treinamento em múltiplas GPUs, na qual a mesma configuração é replicada várias vezes, com cada instância recebendo uma fatia de dados distinta. O processamento é feito em paralelo e todas as configurações são sincronizadas ao final de cada etapa de treinamento.

Saiba mais sobre DataParallel.

IDs de entrada do decoder

Esta entrada é específica para modelos encoder-decoder e contém os IDs de entrada que serão fornecidos ao decoder. Essas entradas devem ser usadas para tarefas de sequência para sequência, como tradução ou sumarização, e geralmente são construídas de uma forma específica para cada modelo.

A maioria dos modelos encoder-decoder (BART, T5) cria seus decoder_input_ids por conta própria a partir dos labels. Em modelos assim, passar os labels é a forma preferida de lidar com o treinamento.

Verifique a documentação de cada modelo para ver como eles lidam com esses IDs de entrada para treinamento de sequência para sequência.

modelos de decodificador

Também chamados de modelos autoregressivos, os modelos de decodificador envolvem uma tarefa de pré-treinamento (chamada de modelagem de linguagem causal) em que o modelo lê os textos em ordem e deve prever a próxima palavra. Isso geralmente é feito lendo a frase inteira com uma máscara para ocultar os tokens futuros em um determinado passo de tempo.

aprendizado profundo (DL)

Algoritmos de aprendizado de máquina que utilizam redes neurais com várias camadas.

E

modelos de codificador

Também conhecidos como modelos de autoencoding, os modelos de codificador recebem uma entrada (como texto ou imagens) e a transformam em uma representação numérica condensada chamada embedding. Frequentemente, os modelos de codificador são pré-treinados usando técnicas como modelagem de linguagem mascarada, que mascara partes da sequência de entrada e força o modelo a criar representações mais significativas.

F

extração de recursos

O processo de seleção e transformação de dados brutos em um conjunto de características mais informativas e úteis para algoritmos de aprendizado de máquina. Alguns exemplos de extração de características incluem a transformação de texto bruto em incorporações de palavras e a extração de características importantes, como bordas ou formas, de dados de imagem/vídeo.

chunking de feed forward

Em cada bloco de atenção residual em transformers, a camada de autoatenção é geralmente seguida por 2 camadas feed forward. O tamanho de incorporação intermediário das camadas feed forward é frequentemente maior que o tamanho oculto do modelo (por exemplo, para google-bert/bert-base-uncased).

Para uma entrada de tamanho [batch_size, sequence_length], a memória necessária para armazenar os embeddings intermediários do feed forward [batch_size, sequence_length, config.intermediate_size] pode representar uma grande fração do uso de memória. Os autores de Reformer: The Efficient Transformer notaram que, como o cálculo é independente da dimensão sequence_length, é matematicamente equivalente calcular os embeddings de saída de ambas as camadas feed forward [batch_size, config.hidden_size]_0, ..., [batch_size, config.hidden_size]_n individualmente e concatená-los em seguida para [batch_size, sequence_length, config.hidden_size] com n = sequence_length, o que troca um aumento no tempo de cálculo por uma redução no uso de memória, mas produz um resultado matematicamente equivalente.

Para modelos que utilizam a função apply_chunking_to_forward(), o chunk_size define o número de embeddings de saída que são calculados em paralelo e, portanto, define o equilíbrio entre a complexidade de memória e a de tempo. Se chunk_size for definido como 0, nenhum chunking de feed forward é realizado.

modelos ajustados

O finetuning é uma forma de transferência de aprendizado que consiste em pegar um modelo pré-treinado, congelar seus pesos e substituir a camada de saída por uma nova model head. A model head é treinada no seu conjunto de dados de destino.

Veja o tutorial Fine-tune a pretrained model para mais detalhes e aprenda como fazer o fine-tuning de modelos com 🤗 Transformers.

H

cabeçalho

A cabeça do modelo (model head) refere-se à última camada de uma rede neural que aceita os estados ocultos brutos (raw hidden states) e os projeta em uma dimensão diferente. Existe uma cabeça de modelo diferente para cada tarefa. Por exemplo:

I

patch de imagem

Modelos de Transformers baseados em visão dividem uma imagem em patches menores, que são incorporados linearmente e, em seguida, passados como uma sequência para o modelo. Você pode encontrar o patch_size — ou a resolução — do modelo em sua configuração.

inferência

Inferência é o processo de avaliar um modelo em novos dados após a conclusão do treinamento. Consulte o tutorial Pipeline para inferência para aprender a realizar inferência com 🤗 Transformers.

IDs de entrada

Os ids de entrada são frequentemente os únicos parâmetros obrigatórios a serem passados ao modelo como entrada. Eles são índices de tokens, representações numéricas dos tokens que compõem as sequências que serão usadas como entrada pelo modelo.

Cada tokenizer funciona de maneira diferente, mas o mecanismo subjacente permanece o mesmo. Aqui está um exemplo usando o tokenizer BERT, que é um tokenizer WordPiece:

>>> from transformers import BertTokenizer

>>> tokenizer = BertTokenizer.from_pretrained("google-bert/bert-base-cased")

>>> sequence = "A Titan RTX has 24GB of VRAM"

O tokenizer cuida de dividir a sequência em tokens disponíveis no vocabulário do tokenizer.

>>> tokenized_sequence = tokenizer.tokenize(sequence)

Os tokens são palavras ou subpalavras. Neste caso, por exemplo, “VRAM” não estava no vocabulário do modelo, então foi dividida em “V”, “RA” e “M”. Para indicar que esses tokens não são palavras separadas, mas sim partes da mesma palavra, um prefixo de dois caracteres de hash é adicionado a “RA” e “M”:

>>> print(tokenized_sequence)
['A', 'Titan', 'R', '##T', '##X', 'has', '24', '##GB', 'of', 'V', '##RA', '##M']

Esses tokens podem então ser convertidos em IDs compreensíveis pelo modelo. Isso pode ser feito fornecendo diretamente a frase ao tokenizer, que utiliza a implementação em Rust do 🤗 Tokenizers para desempenho máximo.

>>> inputs = tokenizer(sequence)

O tokenizer retorna um dicionário com todos os argumentos necessários para que o modelo correspondente funcione corretamente. Os índices dos tokens estão sob a chave input_ids:

>>> encoded_sequence = inputs["input_ids"]
>>> print(encoded_sequence)
[101, 138, 18696, 155, 1942, 3190, 1144, 1572, 13745, 1104, 159, 9664, 2107, 102]

Observe que o tokenizer adiciona automaticamente “tokens especiais” (se o modelo associado depender deles), que são IDs especiais que o modelo usa às vezes.

Se decodificarmos a sequência de ids anterior,

>>> decoded_sequence = tokenizer.decode(encoded_sequence)

veremos

>>> print(decoded_sequence)
[CLS] A Titan RTX has 24GB of VRAM [SEP]

pois é assim que um BertModel espera receber suas entradas.

L

labels

Os rótulos são um argumento opcional que pode ser passado para que o modelo calcule a perda por conta própria. Esses rótulos devem ser a previsão esperada do modelo: ele usará a perda padrão para calcular a diferença entre suas previsões e o valor esperado (o rótulo).

Esses rótulos são diferentes de acordo com a cabeça do modelo, por exemplo:

  • Para modelos de classificação de sequência (BertForSequenceClassification), o modelo espera um tensor de dimensão (batch_size) em que cada valor do lote corresponde à etiqueta esperada para a sequência inteira.
  • Para modelos de classificação de tokens (BertForTokenClassification), o modelo espera um tensor de dimensão (batch_size, seq_length) em que cada valor corresponde ao rótulo esperado de cada token individual.
  • Para modelagem de linguagem mascarada (BertForMaskedLM), o modelo espera um tensor de dimensão (batch_size, seq_length) em que cada valor corresponde ao rótulo esperado de cada token individual: os rótulos sendo o ID do token para o token mascarado, e valores a serem ignorados para o restante (geralmente -100).
  • Para tarefas de sequência para sequência (BartForConditionalGeneration, MBartForConditionalGeneration), o modelo espera um tensor de dimensão (batch_size, tgt_seq_length) em que cada valor corresponde às sequências de destino associadas a cada sequência de entrada. Durante o treinamento, tanto o BART quanto o T5 criam internamente os decoder_input_ids e as máscaras de atenção do decodificador apropriados. Normalmente, não é necessário fornecê-los. Isso não se aplica a modelos que utilizam o framework Encoder-Decoder.
  • Para modelos de classificação de imagens (ViTForImageClassification), o modelo espera um tensor de dimensão (batch_size), em que cada valor do lote corresponde à etiqueta esperada de cada imagem individual.
  • Para modelos de segmentação semântica (SegformerForSemanticSegmentation), o modelo espera um tensor de dimensão (batch_size, height, width) em que cada valor do lote corresponde à etiqueta esperada de cada pixel individual.
  • Para modelos de detecção de objetos (DetrForObjectDetection), o modelo espera uma lista de dicionários com as chaves class_labels e boxes, em que cada valor do lote corresponde ao rótulo esperado e ao número de caixas delimitadoras de cada imagem individual.
  • Para modelos de reconhecimento automático de fala, (Wav2Vec2ForCTC), o modelo espera um tensor de dimensão (batch_size, target_length) em que cada valor corresponde ao rótulo esperado de cada token individual.

As rótulos de cada modelo podem ser diferentes, portanto, certifique-se de sempre consultar a documentação de cada modelo para obter mais informações sobre os rótulos específicos!

Os modelos base (BertModel) não aceitam rótulos, pois são os modelos transformer base, que simplesmente saem com recursos.

grandes modelos de linguagem (LLM)

Termo genérico que se refere a modelos de linguagem transformer (GPT-3, BLOOM, OPT) treinados em uma grande quantidade de dados. Esses modelos também tendem a ter um grande número de parâmetros aprendíveis (por exemplo, 175 bilhões para o GPT-3).

M

modelagem de linguagem mascarada (MLM)

Uma tarefa de pré-treinamento em que o modelo vê uma versão corrompida dos textos, geralmente feita mascarando alguns tokens aleatoriamente, e deve prever o texto original.

multimodal

Uma tarefa que combina textos com outro tipo de entrada (por exemplo, imagens).

N

Geração de linguagem natural (NLG)

Todas as tarefas relacionadas à geração de texto (por exemplo, Write With Transformers, tradução).

Processamento de linguagem natural (NLP)

Uma forma genérica de dizer “tratar textos”.

Compreensão de linguagem natural (NLU)

Todas as tarefas relacionadas à compreensão do que há em um texto (por exemplo, classificar o texto inteiro, palavras individuais).

P

pipeline

Um pipeline no 🤗 Transformers é uma abstração que se refere a uma série de etapas executadas em uma ordem específica para pré-processar e transformar dados e retornar uma previsão de um modelo. Alguns exemplos de etapas encontradas em um pipeline podem ser o pré-processamento de dados, a extração de características e a normalização.

Para mais detalhes, consulte Pipelines para inferência.

PipelineParallel (PP)

Técnica de paralelismo na qual o modelo é dividido verticalmente (nível de camada) entre várias GPUs, de modo que apenas uma ou várias camadas do modelo são alocadas em uma única GPU. Cada GPU processa em paralelo diferentes estágios do pipeline, trabalhando em um pequeno trecho do lote. Saiba mais sobre PipelineParallel.

valores de pixel

Um tensor com as representações numéricas de uma imagem que é passado para um modelo. Os valores de pixel têm a forma [batch_size, num_channels, height, width] e são gerados por um processador de imagem.

pooling

Uma operação que reduz uma matriz em uma matriz menor, seja tomando o valor máximo ou a média das dimensões de pooling. As camadas de pooling são comumente encontradas entre camadas convolucionais para reduzir a resolução da representação de características.

IDs de posição

Ao contrário das RNNs, que incorporam a posição de cada token em sua estrutura, os transformers não têm noção da posição de cada token. Portanto, os IDs de posição (position_ids) são usados pelo modelo para identificar a posição de cada token na lista de tokens.

Eles são um parâmetro opcional. Se nenhum position_ids for passado para o modelo, os IDs são criados automaticamente como embeddings posicionais absolutos.

Os embeddings posicionais absolutos são selecionados no intervalo [0, config.max_position_embeddings - 1]. Alguns modelos utilizam outros tipos de embeddings posicionais, como embeddings posicionais sinusoidais ou embeddings de posição relativa.

pré-processamento

A tarefa de preparar dados brutos em um formato que possa ser facilmente consumido por modelos de aprendizado de máquina. Por exemplo, o texto é tipicamente pré-processado por tokenização. Para ter uma melhor ideia de como o pré-processamento funciona para outros tipos de entrada, confira o tutorial Preprocess.

modelo pré-treinado

Um modelo que foi pré-treinado em alguns dados (por exemplo, toda a Wikipedia). Os métodos de pré-treino envolvem um objetivo auto-supervisionado, que pode ser ler o texto e tentar prever a próxima palavra (veja modelagem de linguagem causal) ou mascarar algumas palavras e tentar prever as palavras mascaradas (veja modelagem de linguagem mascarada).

Modelos de fala e visão possuem seus próprios objetivos de pré-treinamento. Por exemplo, o Wav2Vec2 é um modelo de fala pré-treinado em uma tarefa contrastiva que exige que o modelo identifique a representação de fala “verdadeira” a partir de um conjunto de representações de fala “falsas”. Por outro lado, o BEiT é um modelo de visão pré-treinado em uma tarefa de modelagem de imagem mascarada, que mascara alguns dos patches da imagem e exige que o modelo preveja os patches mascarados (similar ao objetivo de modelagem de linguagem mascarada).

R

rede neural recorrente (RNN)

Um tipo de modelo que usa um loop sobre uma camada para processar textos.

aprendizado de representações

Um subcampo de aprendizado de máquina que se concentra em aprender representações significativas de dados brutos. Alguns exemplos de técnicas de aprendizado de representação incluem incorporações de palavras, autoencoders e Redes Adversariais Generativas (GANs).

S

taxa de amostragem

Uma medição em hertz do número de amostras (o sinal de áudio) capturadas por segundo. A taxa de amostragem é o resultado da discretização de um sinal contínuo, como a fala.

autoatenção

Cada elemento da entrada descobre quais outros elementos da entrada ele deve observar.

aprendizado auto-supervisionado

Uma categoria de técnicas de aprendizado de máquina na qual um modelo cria seu próprio objetivo de aprendizado a partir de dados não rotulados. Diferencia-se de aprendizado não supervisionado e aprendizado supervisionado no fato de que o processo de aprendizado é supervisionado, mas não explicitamente pelo usuário.

Um exemplo de aprendizado auto-supervisionado é o modelamento de linguagem mascarado, no qual um modelo recebe frases com uma proporção de seus tokens removidos e aprende a prever os tokens ausentes.

aprendizado semi-supervisionado

Uma categoria ampla de técnicas de treinamento de aprendizado de máquina que utiliza uma pequena quantidade de dados rotulados junto com uma maior quantidade de dados não rotulados para melhorar a precisão de um modelo, diferentemente do aprendizado supervisionado e do aprendizado não supervisionado.

Um exemplo de uma abordagem de aprendizado semi-supervisionado é o “self-training”, no qual um modelo é treinado em dados rotulados e, em seguida, usado para fazer previsões nos dados não rotulados. A parte dos dados não rotulados para a qual o modelo faz previsões com maior confiança é adicionada ao conjunto de dados rotulados e usada para re-treinar o modelo.

sequência-para-sequência (seq2seq)

Modelos que geram uma nova sequência a partir de uma entrada, como modelos de tradução ou de sumarização (como Bart ou T5).

DDP fragmentado

Outro nome para o conceito fundamental ZeRO, conforme utilizado por diversas outras implementações do ZeRO.

stride

Em convolução ou pooling, o stride se refere à distância que o kernel é deslocado sobre uma matriz. Um stride de 1 significa que o kernel é movido um pixel por vez, e um stride de 2 significa que o kernel é movido dois pixels por vez.

aprendizado supervisionado

Uma forma de treinamento de modelo que utiliza diretamente dados rotulados para corrigir e orientar o desempenho do modelo. Os dados são fornecidos ao modelo em treinamento, e suas previsões são comparadas aos rótulos conhecidos. O modelo atualiza seus pesos com base no grau de incorreção de suas previsões, e o processo é repetido para otimizar o desempenho do modelo.

T

Paralelismo de Tensors (TP)

Técnica de paralelismo para treinamento em múltiplas GPUs na qual cada tensor é dividido em vários fragmentos, de modo que, em vez de o tensor inteiro residir em uma única GPU, cada fragmento do tensor reside em sua GPU designada. Os fragmentos são processados separadamente e em paralelo em diferentes GPUs, e os resultados são sincronizados ao final da etapa de processamento. Isso é o que às vezes é chamado de paralelismo horizontal, pois a divisão ocorre em nível horizontal. Saiba mais sobre Tensor Parallelism aqui.

token

Uma parte de uma frase, geralmente uma palavra, mas também pode ser um subtoken (palavras não comuns são frequentemente divididas em subtokens) ou um símbolo de pontuação.

IDs de tipo de token

O objetivo de alguns modelos é realizar classificação em pares de frases ou resposta a perguntas.

Isso requer que duas sequências diferentes sejam unidas em uma única entrada de “input_ids”, o que geralmente é feito com a ajuda de tokens especiais, como os tokens de classificador ([CLS]) e separador ([SEP]). Por exemplo, o modelo BERT constrói sua entrada de duas sequências da seguinte forma:

>>> # [CLS] SEQUENCE_A [SEP] SEQUENCE_B [SEP]

Podemos usar nosso tokenizer para gerar automaticamente uma frase assim, passando as duas sequências para tokenizer como dois argumentos (e não como uma lista, como antes) da seguinte forma:

>>> from transformers import BertTokenizer

>>> tokenizer = BertTokenizer.from_pretrained("google-bert/bert-base-cased")
>>> sequence_a = "HuggingFace is based in NYC"
>>> sequence_b = "Where is HuggingFace based?"

>>> encoded_dict = tokenizer(sequence_a, sequence_b)
>>> decoded = tokenizer.decode(encoded_dict["input_ids"])

que retornará:

>>> print(decoded)
[CLS] HuggingFace is based in NYC [SEP] Where is HuggingFace based? [SEP]

Isso é suficiente para alguns modelos entenderem onde uma sequência termina e onde outra começa. No entanto, outros modelos, como o BERT, também utilizam IDs de tipo de token (também chamados de IDs de segmento). Eles são representados como uma máscara binária que identifica os dois tipos de sequência no modelo.

O tokenizer retorna essa máscara como a entrada “token_type_ids”:

>>> encoded_dict["token_type_ids"]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1]

A primeira sequência, o “contexto” usado para a pergunta, tem todos os seus tokens representados por um 0, enquanto a segunda sequência, correspondente à “pergunta”, tem todos os seus tokens representados por um 1.

Alguns modelos, como XLNetModel, usam um token adicional representado por um 2.

transfer learning

Uma técnica que consiste em pegar um modelo pré-treinado e adaptá-lo a um conjunto de dados específico para a sua tarefa. Em vez de treinar um modelo do zero, você pode aproveitar o conhecimento obtido de um modelo existente como ponto de partida. Isso acelera o processo de aprendizado e reduz a quantidade de dados de treinamento necessários.

transformer

Arquitetura de modelo de deep learning baseada em autoatenção.

U

aprendizado não supervisionado

Uma forma de treinamento de modelo em que os dados fornecidos ao modelo não possuem rótulos. As técnicas de aprendizado não supervisionado exploram as informações estatísticas da distribuição dos dados para encontrar padrões úteis para a tarefa em questão.

Z

Zero Redundancy Optimizer (ZeRO)

Técnica de paralelismo que realiza o sharding dos tensores de forma um pouco semelhante ao TensorParallel, exceto que o tensor inteiro é reconstruído a tempo para um cálculo de forward ou backward, portanto o modelo não precisa ser modificado. Este método também suporta diversas técnicas de offloading para compensar a memória de GPU limitada. Saiba mais sobre o ZeRO aqui.

Update on GitHub