# Course

## Docs

- [Introdução](https://huggingface.co/learn/course/pt/chapter7/1.md)
- [Parte 1 completa!](https://huggingface.co/learn/course/pt/chapter4/5.md)
- [O Hugging Face Hub](https://huggingface.co/learn/course/pt/chapter4/1.md)
- [Compartilhando modelos pré-treinados](https://huggingface.co/learn/course/pt/chapter4/3.md)
- [Questionário de fim de capítulo](https://huggingface.co/learn/course/pt/chapter4/6.md)
- [Construindo um cartão para o modelo](https://huggingface.co/learn/course/pt/chapter4/4.md)
- [Usando modelos pré-treinados](https://huggingface.co/learn/course/pt/chapter4/2.md)
- [Introdução](https://huggingface.co/learn/course/pt/chapter3/1.md)
- [Introdução](https://huggingface.co/learn/course/pt/chapter8/1.md)
- [Pedindo ajuda nos fóruns](https://huggingface.co/learn/course/pt/chapter8/3.md)
- [O que fazer quando ocorrer um erro](https://huggingface.co/learn/course/pt/chapter8/2.md)
- [Evento de lançamento da Parte 2](https://huggingface.co/learn/course/pt/events/2.md)
- [Introdução](https://huggingface.co/learn/course/pt/chapter6/1.md)
- [Os poderes especiais dos tokenizadores rápidos](https://huggingface.co/learn/course/pt/chapter6/3.md)
- [Treinando um novo tokenizador](https://huggingface.co/learn/course/pt/chapter6/2.md)
- [Criando seu próprio dataset](https://huggingface.co/learn/course/pt/chapter5/5.md)
- [Introdução](https://huggingface.co/learn/course/pt/chapter5/1.md)
- [Hora de fatiar e dividir os dados](https://huggingface.co/learn/course/pt/chapter5/3.md)
- [Busca semântica com o FAISS](https://huggingface.co/learn/course/pt/chapter5/6.md)
- [Questionário de fim de capítulo](https://huggingface.co/learn/course/pt/chapter5/8.md)
- [Big data? 🤗 Datasets ao resgate](https://huggingface.co/learn/course/pt/chapter5/4.md)
- [Confira o 🤗 Datasets!](https://huggingface.co/learn/course/pt/chapter5/7.md)
- [E se o meu dataset não estiver no Hub?](https://huggingface.co/learn/course/pt/chapter5/2.md)
- [Tratando sequências múltiplas](https://huggingface.co/learn/course/pt/chapter2/5.md)
- [Introdução](https://huggingface.co/learn/course/pt/chapter2/1.md)
- [Modelos](https://huggingface.co/learn/course/pt/chapter2/3.md)
- [Colocando tudo junto](https://huggingface.co/learn/course/pt/chapter2/6.md)
- [Questionário de fim de capítulo](https://huggingface.co/learn/course/pt/chapter2/8.md)
- [Tokenizers](https://huggingface.co/learn/course/pt/chapter2/4.md)
- [Uso básico concluído!](https://huggingface.co/learn/course/pt/chapter2/7.md)
- [Por dentro da função pipeline](https://huggingface.co/learn/course/pt/chapter2/2.md)
- [Introdução](https://huggingface.co/learn/course/pt/chapter0/1.md)
- [Resumo](https://huggingface.co/learn/course/pt/chapter1/9.md)
- [Modelos codificadores](https://huggingface.co/learn/course/pt/chapter1/5.md)
- [Introdução](https://huggingface.co/learn/course/pt/chapter1/1.md)
- [Transformers, o que eles podem fazer?](https://huggingface.co/learn/course/pt/chapter1/3.md)
- [Modelos decodificadores](https://huggingface.co/learn/course/pt/chapter1/6.md)
- [Questionário de fim de capítulo](https://huggingface.co/learn/course/pt/chapter1/10.md)
- [Vieses e limitações](https://huggingface.co/learn/course/pt/chapter1/8.md)
- [Como os Transformers trabalham?](https://huggingface.co/learn/course/pt/chapter1/4.md)
- [Modelos sequência a sequência](https://huggingface.co/learn/course/pt/chapter1/7.md)
- [Processamento de Linguagem Natural (NLP)](https://huggingface.co/learn/course/pt/chapter1/2.md)

### Introdução
https://huggingface.co/learn/course/pt/chapter7/1.md

# Introdução

<CourseFloatingBanner
    chapter={7}
    classNames="absolute z-10 right-0 top-0"
/>

No [Capítulo 3](/course/chapter3), você viu como fazer o ajuste fino (fine-tune) de um modelo de classificação de texto. Neste capítulo, abordaremos as seguintes tarefas de NLP (também conhecido como PLN):

- Classificação dos Tokens
- Modelagem de linguagem mascarada (como BERT)
- Sumarização 
- Tradução
- Modelagem de linguagem causal pré-treinamento (como GPT-2)
- Responder perguntas

{#if fw === 'pt'}

Para fazer isso, terá de aproveitar tudo o que aprendeu sobre a API `Trainer` e a biblioteca 🤗 Accelerate no [Capítulo 3](/course/chapter3), a biblioteca 🤗 Datasets no [Capítulo 5](/course/chapter5), e a biblioteca 🤗 Tokenizers no [Capítulo 6](/course/chapter6). Também vamos fazer o upload dos nossos resultados para o Model Hub, assim como fizemos no [Capítulo 4](/course/chapter4), então realmente esse é o capítulo onde tudo se junta!

Cada seção pode ser lida de forma independente e irá mostrar como treinar um modelo com a API `Trainer` ou com o seu próprio laço de treinamento, utilizando 🤗 Accelerate. Sinta-se à vontade para pular qualquer parte e se concentrar na que mais lhe interessa: a API `Trainer` é excelente para o ajuste fino ou para treinar o seu modelo sem se preocupar com o que se passa nos bastidores, enquanto que o laço de treinamento com `Accelerate` permite personalizar qualquer parte que queira com mais facilidade.

{:else}

Para fazer isso, terá de aproveitar tudo o que aprendeu sobre o treinamento de modelo com a API Keras no [Capítulo 3](/course/chapter3), a biblioteca 🤗 Datasets no [Capítulo 5](/course/chapter5), e a biblioteca 🤗 Tokenizers no [Capítulo 6](/course/chapter6). Também vamos fazer o upload dos nossos resultados para o Model Hub, assim como fizemos no [Capítulo 4](/course/chapter4), então realmente esse é o capítulo onde tudo se junta!

Cada seção pode ser lida de forma independente.

{/if}


<Tip>

Se ler as seções em sequência, notará que elas têm bastante código e texto em comum. Essa repetição é intencional para que possa mergulhar (ou voltar mais tarde) em qualquer tarefa que lhe interesse e encontrar um exemplo completo.

</Tip>


<EditOnGithub source="https://github.com/huggingface/course/blob/main/chapters/pt/chapter7/1.mdx" />

### Parte 1 completa!
https://huggingface.co/learn/course/pt/chapter4/5.md

# Parte 1 completa!

<CourseFloatingBanner
    chapter={4}
    classNames="absolute z-10 right-0 top-0"
/>

Este é o fim da primeira parte do curso! A segunda parte será lançada em 15 de novembro com um grande evento comunitário, veja mais informações [aqui](https://huggingface.co/blog/course-launch-event).

Agora você deverá ser capaz de afinar um modelo pré-treinado sobre um problema de classificação de texto (frases simples ou pares de frases) e carregar o resultado para o Model Hub. Para garantir que você domine esta primeira seção, você deve fazer exatamente isso em um problema que lhe interesse (e não necessariamente em inglês se você falar outro idioma)! Você pode encontrar ajuda nos [fóruns Hugging Face](https://discuss.huggingface.co/) e compartilhar seu projeto em [este tópico](https://discuss.huggingface.co/t/share-your-projects/6803) uma vez terminado.

Mal podemos esperar para ver o que você vai construir com isto!


<EditOnGithub source="https://github.com/huggingface/course/blob/main/chapters/pt/chapter4/5.mdx" />

### O Hugging Face Hub
https://huggingface.co/learn/course/pt/chapter4/1.md

# O Hugging Face Hub

<CourseFloatingBanner
    chapter={4}
    classNames="absolute z-10 right-0 top-0"
/>

O [Hugging Face Hub](https://huggingface.co/) –- nosso site principal –- é uma plataforma central que permite a qualquer pessoa descobrir, usar e contribuir com novos modelos e datasets do estado da arte. Ele hospeda uma grande variedade de modelos, com mais de 10.000 disponíveis publicamente. Vamos nos concentrar nos modelos deste capítulo, e daremos uma olhada nos conjuntos de dados do Capítulo 5.

Os modelos no Hub não estão limitados a 🤗 Transformers ou mesmo NLP. Há modelos da [Flair](https://github.com/flairNLP/flair) e [AllenNLP](https://github.com/allenai/allennlp) para NLP, [Asteroid](https://github.com/asteroid-team/asteroid) e [pyannote](https://github.com/pyannote/pyannote-audio) para discurso, e [timm](https://github.com/rwightman/pytorch-image-models) para visão, para citar alguns. 

Cada um destes modelos é hospedado como um repositório Git, o que permite a criação de versões e a reprodutibilidade. Compartilhar um modelo no Hub significa abri-lo para a comunidade e torná-lo acessível a qualquer pessoa que queira usá-lo facilmente, eliminando, por sua vez, a necessidade de treinar um modelo por conta própria e simplificando o compartilhamento e o uso. 

Além disso, o compartilhamento de um modelo no Hub automaticamente fornece acesso a uma API de Inferência hospedada para esse modelo. Qualquer pessoa da comunidade é livre para testá-lo diretamente na página do modelo, com entradas personalizadas e widgets apropriados.

A melhor parte é que compartilhar e usar qualquer modelo público no Hub é completamente gratuito! [Planos pagos](https://huggingface.co/pricing) também existem se você desejar compartilhar modelos em particular.

O vídeo abaixo mostra como navegar no Hub.

<Youtube id="XvSGPZFEjDY"/>

É necessário ter uma conta huggingface.co para acompanhar esta parte, pois estaremos criando e gerenciando repositórios no Hugging Face Hub: [criar conta](https://huggingface.co/join)

<EditOnGithub source="https://github.com/huggingface/course/blob/main/chapters/pt/chapter4/1.mdx" />

### Compartilhando modelos pré-treinados
https://huggingface.co/learn/course/pt/chapter4/3.md

# Compartilhando modelos pré-treinados

{#if fw === 'pt'}

<CourseFloatingBanner chapter={4}
  classNames="absolute z-10 right-0 top-0"
  notebooks={[
    {label: "Google Colab", value: "https://colab.research.google.com/github/huggingface/notebooks/blob/master/course/pt/chapter4/section3_pt.ipynb"},
    {label: "Aws Studio", value: "https://studiolab.sagemaker.aws/import/github/huggingface/notebooks/blob/master/course/pt/chapter4/section3_pt.ipynb"},
]} />

{:else}

<CourseFloatingBanner chapter={4}
  classNames="absolute z-10 right-0 top-0"
  notebooks={[
    {label: "Google Colab", value: "https://colab.research.google.com/github/huggingface/notebooks/blob/master/course/pt/chapter4/section3_tf.ipynb"},
    {label: "Aws Studio", value: "https://studiolab.sagemaker.aws/import/github/huggingface/notebooks/blob/master/course/pt/chapter4/section3_tf.ipynb"},
]} />

{/if}

Nas etapas abaixo, veremos as maneiras mais fáceis de compartilhar modelos pré-treinados para o Hub 🤗. Há ferramentas e utilitários disponíveis que facilitam o compartilhamento e atualização de modelos diretamente no Hub, que exploraremos a seguir.

<Youtube id="9yY3RB_GSPM"/>

Encorajamos todos os usuários que treinam modelos a contribuir compartilhando-os com a comunidade - compartilhar modelos, mesmo quando treinados em conjuntos de dados muito específicos, ajudará outros, economizando tempo e recursos e fornecendo acesso a artefatos úteis treinados. Por sua vez, você pode se beneficiar do trabalho que outros realizaram!

Há três maneiras de se criar novos repositórios modelo:

- Usando a API`push_to_hub`
- Usando a biblioteca Python `huggingface_hub`
- Usando a interface web 

Uma vez criado um repositório, você pode fazer o upload de arquivos para ele via git e git-lfs. Nós o acompanharemos na criação de repositórios modelo e no upload de arquivos para eles nas seções seguintes.


## Usando a API`push_to_hub`

{#if fw === 'pt'}

<Youtube id="Zh0FfmVrKX0"/>

{:else}

<Youtube id="pUh5cGmNV8Y"/>

{/if}

A maneira mais simples de carregar arquivos no Hub é usando a API `push_to_hub`.

Antes de ir adiante, você precisará gerar um token de autenticação para que a API `huggingface_hub` saiba quem você é e a que namespaces você tem acesso de escrita. Certifique-se de estar em um ambiente onde você tenha `transformers` instalado (ver [Setup](/course/chapter0)). Se você estiver em um notebook, você pode utilizar a seguinte função para fazer o login:


```python
from huggingface_hub import notebook_login

notebook_login()
```

Em um terminal, você pode rodar:

```bash
huggingface-cli login
```

Em ambos os casos, você será solicitado seu nome de usuário e senha, que são os mesmos que você usa para fazer o login no Hub. Se você ainda não tem um perfil do Hub, você deve criar um [aqui](https://huggingface.co/join).

Ótimo! Agora você tem seu token de autenticação armazenado em sua pasta de cache. Vamos criar alguns repositórios!

{#if fw === 'pt'}

Se você usou a API do `Trainer` para treinar um modelo, a maneira mais fácil de carregá-lo no Hub é definir `push_to_hub=True` quando você definir seus `TrainingArguments`:

```py
from transformers import TrainingArguments

training_args = TrainingArguments(
    "bert-finetuned-mrpc", save_strategy="epoch", push_to_hub=True
)
```

Quando você chama `trainer.train()`, o `Trainer` então carregará seu modelo no Hub cada vez que ele for salvo (aqui a cada época) em um repositório em seu namespace. Esse repositório será nomeado como o diretório de saída que você escolheu (aqui `bert-finetuned-mrpc`), mas você pode escolher um nome diferente com `hub_model_id = "a_diferent_name"`.

Para enviar seu modelo para uma organização da qual você é membro, basta passá-lo com `hub_model_id = "my_organization/my_repo_name"`.

Uma vez terminado seu treinamento, você deve fazer um último `trainer.push_to_hub()` para carregar a última versão de seu modelo. Ele também gerará um cartão modelo com todos os metadados relevantes, relatando os hiperparâmetros utilizados e os resultados da avaliação! Aqui está um exemplo do conteúdo que você pode encontrar em um cartão modelo deste tipo:

<div class="flex justify-center">
  <img src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter4/model_card.png" alt="An example of an auto-generated model card." width="100%"/>
</div>

{:else}


Se você estiver utilizando Keras para treinar seu modelo, a maneira mais fácil de carregá-lo no Hub é passar um `PushToHubCallback` quando você chama de `model.fit()`:

```py
from transformers import PushToHubCallback

callback = PushToHubCallback(
    "bert-finetuned-mrpc", save_strategy="epoch", tokenizer=tokenizer
)
```

Então você deve adicionar `callbacks=[callback]` em sua chamada de `model.fit()`. A chamada de retorno será então enviada ao Hub cada vez que o modelo for salvo (aqui a cada época) em um repositório em seu namespace. Esse repositório será nomeado como o diretório de saída que você escolheu (aqui `bert-finetuned-mrpc`), mas você pode escolher um nome diferente com `hub_model_id = "a_diferent_name"`.

Para enviar seu modelo para uma organização da qual você é membro, basta passá-lo com `hub_model_id = "my_organization/my_repo_name"`.

{/if}

Em um nível inferior, o acesso ao Model Hub pode ser feito diretamente nos modelos, tokenizers e objetos de configuração através de seu método `push_to_hub()`. Este método cuida da criação do repositório e empurra os arquivos modelo e tokenizer diretamente para o repositório. Não é necessário nenhum tratamento manual, ao contrário do que acontece com a API, veremos abaixo.

Para se ter uma idéia de como funciona, vamos primeiro inicializar um modelo e um tokenizer:

{#if fw === 'pt'}
```py
from transformers import AutoModelForMaskedLM, AutoTokenizer

checkpoint = "camembert-base"

model = AutoModelForMaskedLM.from_pretrained(checkpoint)
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
```
{:else}
```py
from transformers import TFAutoModelForMaskedLM, AutoTokenizer

checkpoint = "camembert-base"

model = TFAutoModelForMaskedLM.from_pretrained(checkpoint)
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
```
{/if}

Você é livre para fazer o que quiser com elas - adicionar fichas ao tokenizer, treinar o modelo, afinar o modelo. Quando você estiver satisfeito com o modelo, pesos e tokenizer resultantes, você pode aproveitar o método `push_to_hub()` diretamente disponível no objeto `model`:

```py
model.push_to_hub("dummy-model")
```

Isto criará o novo repositório `dummy-model`  em seu perfil, e o preencherá com seus arquivos de modelos.
Faça o mesmo com o tokenizer, para que todos os arquivos estejam agora disponíveis neste repositório:

```py
tokenizer.push_to_hub("dummy-model")
```

Se você pertence a uma organização, basta especificar o argumento `organization` a ser carregado no namespace dessa organização:

```py
tokenizer.push_to_hub("dummy-model", organization="huggingface")
```

Se você desejar utilizar um toke específica do Hugging Face, você é livre para especificá-la também para o método `push_to_hub()`:

```py
tokenizer.push_to_hub("dummy-model", organization="huggingface", use_auth_token="<TOKEN>")
```

Agora vá até o Model Hub para encontrar seu modelo recém-carregado: *https://huggingface.co/user-or-organization/dummy-model*.

Clique na aba "Files and versions", e você deve ver os arquivos visíveis na seguinte captura de tela:

{#if fw === 'pt'}
<div class="flex justify-center">
<img src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter4/push_to_hub_dummy_model.png" alt="Dummy model containing both the tokenizer and model files." width="80%"/>
</div>
{:else}
<div class="flex justify-center">
<img src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter4/push_to_hub_dummy_model_tf.png" alt="Dummy model containing both the tokenizer and model files." width="80%"/>
</div>
{/if}

<Tip>

✏️ **Teste-o!** Pegue o modelo e o tokenizer associados ao checkpoint `bert-base-cased` e carregue-os para um repo em seu namespace utilizando o método `push_to_hub()`. Verifique novamente se o repo aparece corretamente em sua página antes de excluí-lo.

</Tip>

Como você já viu, o método `push_to_hub()` aceita vários argumentos, tornando possível carregar para um repositório específico ou espaço de nomes de organizações, ou utilizar um token API diferente. Recomendamos que você dê uma olhada na especificação do método disponível diretamente na documentação [🤗 Transformers documentation](https://huggingface.co/transformers/model_sharing.html) para ter uma idéia do que é possível.

O método `push_to_hub()` é apoiado pelo pacote [`huggingface_hub`](https://github.com/huggingface/huggingface_hub) Python, que oferece uma API direta para o Hub Hugging Face. Está integrado ao 🤗 Transformers e várias outras bibliotecas de aprendizagem de máquinas, como [`allenlp`](https://github.com/allenai/allennlp). Embora nos concentremos na integração do 🤗 Transformers neste capítulo, integrá-lo em seu próprio código ou biblioteca é simples.

Salte para a última seção para ver como carregar arquivos em seu repositório recém-criado!

## Usando a biblioteca Python `huggingface_hub`

A biblioteca Python`huggingface_hub` é um pacote que oferece um conjunto de ferramentas para os hubs do modelo e dos conjuntos de dados. Ela fornece métodos e classes simples para tarefas comuns como obter informações sobre os repositórios no centro e gerenciá-los. Ele fornece APIs simples que funcionam em cima do git para gerenciar o conteúdo desses repositórios e para integrar o Hub em seus projetos e bibliotecas.

Da mesma forma que a utilização da API `push_to_hub`, isto exigirá que você tenha seu token API salvo em seu cache. Para fazer isso, você precisará utilizar o comando `login` do CLI, como mencionado na seção anterior (mais uma vez, certifique-se de utilizar antes desses comandos o caracter `!` se estiver rodando no Google Colab):

```bash
huggingface-cli login
```

O pacote `huggingface_hub` oferece vários métodos e classes que são úteis para nosso propósito. Em primeiro lugar, existem alguns métodos para gerenciar a criação de repositórios, exclusão, e outros:

```python no-format
from huggingface_hub import (
    # Gestão de usuários
    login,
    logout,
    whoami,

    # Criação e gestão de repositório
    create_repo,
    delete_repo,
    update_repo_visibility,

    #E alguns métodos para recuperar/trocar informações sobre o conteúdo
    list_models,
    list_datasets,
    list_metrics,
    list_repo_files,
    upload_file,
    delete_file,
)
```


Além disso, oferece uma poderosa classe `Repository` para gerenciar um repositório local. Vamos explorar esses métodos e essa classe na próxima seção para entender como aproveitá-los.

O método `create_repo` pode ser utilizado para criar um novo repositório no centro:

```py
from huggingface_hub import create_repo

create_repo("dummy-model")
```

Isto criará o repositório `dummy-model` em seu namespace. Se desejar, você pode especificar a que organização o repositório deve pertencer utilizando o argumento `organization`:

```py
from huggingface_hub import create_repo

create_repo("dummy-model", organization="huggingface")
```


Isto criará o repositório `dummy-model` no espaço de nomes `huggingface`, assumindo que você pertença a essa organização.
Outros argumentos que podem ser úteis são:

- `private`, a fim de especificar se o repositório deve ser visível de outros ou não.
- `token`,se você gostaria de substituir o token armazenada em seu cache por uma determinada token.
- `repo_type`, se você gostaria de criar um "`dataset` ou um "espaço" em vez de um modelo. Os valores aceitos são `"dataset"`  e `"space"`.

Uma vez criado o repositório, devemos adicionar arquivos a ele! Salte para a próxima seção para ver as três maneiras como isto pode ser tratado.


## Usando a interface web 

A interface web oferece ferramentas para gerenciar os repositórios diretamente no Hub. Usando a interface, você pode facilmente criar repositórios, adicionar arquivos (mesmo grandes!), explorar modelos, visualizar diffs, e muito mais.

Para criar um novo repositório, visite [huggingface.co/novo](https://huggingface.co/new):

<div class="flex justify-center">
<img src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter4/new_model.png" alt="Page showcasing the model used for the creation of a new model repository." width="80%"/>
</div>

Primeiro, especifique o proprietário do repositório: este pode ser você ou qualquer uma das organizações às quais você está afiliado. Se você escolher uma organização, o modelo será apresentado na página da organização e cada membro da organização terá a capacidade de contribuir com o repositório.

A seguir, digite o nome do seu modelo. Este também será o nome do repositório. Finalmente, você pode especificar se deseja que seu modelo seja público ou privado. Os modelos privados não podem ser encontrados publicamente.

Depois de criar seu repositório de modelos, você deve ver uma página como esta:

<div class="flex justify-center">
<img src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter4/empty_model.png" alt="An empty model page after creating a new repository." width="80%"/>
</div>

Aqui é onde seu modelo será hospedado. Para começar a preenchê-lo, você pode adicionar um arquivo README diretamente da interface web.

<div class="flex justify-center">
<img src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter4/dummy_model.png" alt="The README file showing the Markdown capabilities." width="80%"/>
</div>

O arquivo README está em Markdown - sinta-se à vontade para ficar louco com ele! A terceira parte deste capítulo é dedicada à construção de um modelo de cartão. Estes são de extrema importância para trazer valor ao seu modelo, pois estão onde você diz aos outros o que ele pode fazer.

Se você olhar a aba "Files and versions", você verá que ainda não há muitos arquivos - apenas o *README.md* que você acabou de criar e o arquivo *.gitattributes* que mantém o controle de arquivos grandes.

<div class="flex justify-center">
<img src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter4/files.png" alt="The 'Files and versions' tab only shows the .gitattributes and README.md files." width="80%"/>
</div>

A seguir, veremos como adicionar alguns novos arquivos.

## Fazendo upload dos arquivos de modelos

O sistema para gerenciar arquivos no Hub Hugging Face Hub é baseado no git para arquivos regulares, e git-lfs (que significa [Git Large File Storage](https://git-lfs.github.com/)) para arquivos maiores. 

Na seção seguinte, passamos por três maneiras diferentes de carregar arquivos no Hub: através de `huggingface_hub` e através de comandos de git.

### A abordagem: `upload_file`

A utilização do `upload_file` não requer que git e git-lfs sejam instalados em seu sistema. Ele empurra os arquivos diretamente para o Hub 🤗 utilizando solicitações HTTP POST. Uma limitação desta abordagem é que ele não lida com arquivos maiores que 5GB de tamanho.
Se seus arquivos forem maiores que 5GB, por favor, siga os dois outros métodos detalhados abaixo.

A API pode ser usada da seguinte forma:

```py
from huggingface_hub import upload_file

upload_file(
    "<path_to_file>/config.json",
    path_in_repo="config.json",
    repo_id="<namespace>/dummy-model",
)
```

Isto fará o upload do arquivo `config.json` disponível em `<path_to_file>` para a raiz do repositório como `config.json`, para o repositório `dummy-model`.
Outros argumentos que podem ser úteis são:

- `token`, se você gostaria de substituir o token armazenado em seu cache por um determinado token.
- `repo_type`, se você gostaria de carregar em um `dataset` ou em um `espaço` em vez de um modelo. Os valores aceitos são `"dataset"` e `"space"`.

### A classe: `Repository`

A classe `Repository` gerencia um repositório local de forma idiota. Ele resume a maioria dos pontos de dor que se pode ter com o git para fornecer todas as características que necessitamos. 

A utilização desta classe requer ter git e git-lfs instalados, portanto certifique-se de ter o git-lfs instalado (veja [aqui](https://git-lfs.github.com/) para instruções de instalação) e configure-o antes de começar. 

Para começar a brincar com o repositório que acabamos de criar, podemos começar inicializando-o em uma pasta local através da clonagem do repositório remoto:

```py
from huggingface_hub import Repository

repo = Repository("<path_to_dummy_folder>", clone_from="<namespace>/dummy-model")
```

Isto criou a pasta `<path_to_dummy_folder>` em nosso diretório de trabalho. Esta pasta contém apenas o arquivo `.gitattributes`, pois este é o único arquivo criado ao instanciar o repositório através do `create_repo`.

A partir deste ponto, podemos aproveitar vários dos métodos tradicionais do gitattributes:

```py
repo.git_pull()
repo.git_add()
repo.git_commit()
repo.git_push()
repo.git_tag()
```

E outros! Recomendamos dar uma olhada na documentação `Repository` disponível [aqui](https://github.com/huggingface/huggingface_hub/tree/main/src/huggingface_hub#advanced-programmatic-repository-management) para uma visão geral de todos os métodos disponíveis.

No momento, temos um modelo e um tokenizer que gostaríamos de empurrar para o centro. Clonamos com sucesso o repositório, portanto, podemos salvar os arquivos dentro desse repositório.

Primeiro nos certificamos de que nosso clone local esteja atualizado, puxando as últimas mudanças:

```py
repo.git_pull()
```

Uma vez feito isso, salvamos os arquivos do modelo e do tokenizer:

```py
model.save_pretrained("<path_to_dummy_folder>")
tokenizer.save_pretrained("<path_to_dummy_folder>")
```

O `<path_to_dummy_folder>` agora contém todos os modelos e arquivos de fichas. Seguimos o fluxo de trabalho habitual do git, adicionando arquivos à área de encenação, comprometendo-os e empurrando-os para o centro:

```py
repo.git_add()
repo.git_commit("Add model and tokenizer files")
repo.git_push()
```

Parabéns! Você acabou de empurrar seus primeiros arquivos para o centro.

### A abordagem: `baseada em git`

Esta é a própria abordagem do barebone para carregar arquivos: faremos isso com git e git-lfs diretamente. A maior parte da dificuldade é abstraída por abordagens anteriores, mas há algumas advertências com o seguinte método, então seguiremos um caso de uso mais complexo.

O uso desta classe requer ter git e git-lfs instalados, portanto, certifique-se de ter [git-lfs](https://git-lfs.github.com/) instalado (veja aqui as instruções de instalação) e configurado antes de começar. 

Primeiro comece inicializando o git-lfs:

```bash
git lfs install
```

```bash
Updated git hooks.
Git LFS initialized.
```

Uma vez feito isso, o primeiro passo é clonar seu repositório modelo:

```bash
git clone https://huggingface.co/<namespace>/<your-model-id>
```

Meu nome de usuário é `lysandre` e já utilizei o nome modelo `dummy`, então para mim o comando acaba parecendo o seguinte:

```
git clone https://huggingface.co/lysandre/dummy
```

Agora tenho uma pasta com o nome *dummy* em meu diretório de trabalho. Eu posso `cd` dentro da pasta e dar uma olhada no conteúdo:

```bash
cd dummy && ls
```

```bash
README.md
```

Se você acabou de criar seu repositório utilizando o método `create_repo` do Hugging Face Hub, esta pasta deve conter apenas um arquivo oculto `.gitattributes`. Se você seguiu as instruções da seção anterior para criar um repositório utilizando a interface web, a pasta deve conter um único arquivo *README.md* ao lado do arquivo oculto `.gitattributes`, como mostrado aqui.

Adicionar um arquivo de tamanho normal, como um arquivo de configuração, um arquivo de vocabulário, ou basicamente qualquer arquivo sob alguns megabytes, é feito exatamente como se faria em qualquer sistema baseado no gitattributes. Entretanto, arquivos maiores devem ser registrados através do git-lfs a fim de empurrá-los para *huggingface.co*. 

Vamos voltar a Python para gerar um modelo e tokenizer que gostaríamos de comprometer com nosso repositório dummy:

{#if fw === 'pt'}
```py
from transformers import AutoModelForMaskedLM, AutoTokenizer

checkpoint = "camembert-base"

model = AutoModelForMaskedLM.from_pretrained(checkpoint)
tokenizer = AutoTokenizer.from_pretrained(checkpoint)

# Do whatever with the model, train it, fine-tune it...

model.save_pretrained("<path_to_dummy_folder>")
tokenizer.save_pretrained("<path_to_dummy_folder>")
```
{:else}
```py
from transformers import TFAutoModelForMaskedLM, AutoTokenizer

checkpoint = "camembert-base"

model = TFAutoModelForMaskedLM.from_pretrained(checkpoint)
tokenizer = AutoTokenizer.from_pretrained(checkpoint)

# Do whatever with the model, train it, fine-tune it...

model.save_pretrained("<path_to_dummy_folder>")
tokenizer.save_pretrained("<path_to_dummy_folder>")
```
{/if}

Agora que salvamos alguns artefatos de modelo e tokenizer, vamos dar outra olhada na pasta *dummy*:

```bash
ls
```

{#if fw === 'pt'}
```bash
config.json  pytorch_model.bin  README.md  sentencepiece.bpe.model  special_tokens_map.json tokenizer_config.json  tokenizer.json
```

Se você olhar para os tamanhos de arquivo (por exemplo, com `ls -lh`), você deve ver que o arquivo de estado do modelo (*pytorch_model.bin*) é o único outlier, com mais de 400 MB.

{:else}
```bash
config.json  README.md  sentencepiece.bpe.model  special_tokens_map.json  tf_model.h5  tokenizer_config.json  tokenizer.json
```

Se você olhar para os tamanhos de arquivo (por exemplo, com `ls -lh`), você deve ver que o arquivo de estado do modelo (*t5_model.h5*) é o único outlier, com mais de 400 MB.

{/if}

<Tip>
✏️ Ao criar o repositório a partir da interface web, o arquivo *.gitattributes* é automaticamente configurado para considerar arquivos com certas extensões, como *.bin* e *.h5*, como arquivos grandes, e o git-lfs os rastreará sem nenhuma configuração necessária em seu lado.
</Tip> 

Agora podemos ir em frente e proceder como normalmente faríamos com os repositórios tradicionais da Git. Podemos adicionar todos os arquivos ao ambiente de encenação do Git utilizando o comando `git add`:

```bash
git add .
```

Podemos, então, dar uma olhada nos arquivos que estão atualmente em fase de montagem:

```bash
git status
```

{#if fw === 'pt'}
```bash
On branch main
Your branch is up to date with 'origin/main'.

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
  modified:   .gitattributes
	new file:   config.json
	new file:   pytorch_model.bin
	new file:   sentencepiece.bpe.model
	new file:   special_tokens_map.json
	new file:   tokenizer.json
	new file:   tokenizer_config.json
```
{:else}
```bash
On branch main
Your branch is up to date with 'origin/main'.

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
  modified:   .gitattributes
  	new file:   config.json
	new file:   sentencepiece.bpe.model
	new file:   special_tokens_map.json
	new file:   tf_model.h5
	new file:   tokenizer.json
	new file:   tokenizer_config.json
```
{/if}

Da mesma forma, podemos ter certeza de que o git-lfs está rastreando os arquivos corretos, utilizando seu comando `status`:

```bash
git lfs status
```

{#if fw === 'pt'}
```bash
On branch main
Objects to be pushed to origin/main:


Objects to be committed:

	config.json (Git: bc20ff2)
	pytorch_model.bin (LFS: 35686c2)
	sentencepiece.bpe.model (LFS: 988bc5a)
	special_tokens_map.json (Git: cb23931)
	tokenizer.json (Git: 851ff3e)
	tokenizer_config.json (Git: f0f7783)

Objects not staged for commit:


```

Podemos ver que todos os arquivos têm `Git` como manipulador, exceto *pytorch_model.bin* e *sentencepiece.bpe.model*, que têm `LFS`. Ótimo!

{:else}
```bash
On branch main
Objects to be pushed to origin/main:


Objects to be committed:

	config.json (Git: bc20ff2)
	sentencepiece.bpe.model (LFS: 988bc5a)
	special_tokens_map.json (Git: cb23931)
	tf_model.h5 (LFS: 86fce29)
	tokenizer.json (Git: 851ff3e)
	tokenizer_config.json (Git: f0f7783)

Objects not staged for commit:


```

Podemos ver que todos os arquivos têm `Git` como manipulador, exceto *t5_model.h5*, que tem `LFS`. Excelente!

{/if}

Vamos prosseguir para as etapas finais, comprometendo-nos e empurrando para o repositório remoto *huggingface.co*:

```bash
git commit -m "First model version"
```

{#if fw === 'pt'}
```bash
[main b08aab1] First model version
 7 files changed, 29027 insertions(+)
  6 files changed, 36 insertions(+)
 create mode 100644 config.json
 create mode 100644 pytorch_model.bin
 create mode 100644 sentencepiece.bpe.model
 create mode 100644 special_tokens_map.json
 create mode 100644 tokenizer.json
 create mode 100644 tokenizer_config.json
```
{:else}
```bash
[main b08aab1] First model version
 6 files changed, 36 insertions(+)
 create mode 100644 config.json
 create mode 100644 sentencepiece.bpe.model
 create mode 100644 special_tokens_map.json
 create mode 100644 tf_model.h5
 create mode 100644 tokenizer.json
 create mode 100644 tokenizer_config.json
```
{/if}

O push pode levar um pouco de tempo, dependendo da velocidade de sua conexão à Internet e do tamanho de seus arquivos:

```bash
git push
```

```bash
Uploading LFS objects: 100% (1/1), 433 MB | 1.3 MB/s, done.
Enumerating objects: 11, done.
Counting objects: 100% (11/11), done.
Delta compression using up to 12 threads
Compressing objects: 100% (9/9), done.
Writing objects: 100% (9/9), 288.27 KiB | 6.27 MiB/s, done.
Total 9 (delta 1), reused 0 (delta 0), pack-reused 0
To https://huggingface.co/lysandre/dummy
   891b41d..b08aab1  main -> main
```

{#if fw === 'pt'}
Se dermos uma olhada no repositório modelo quando este estiver terminado, podemos ver todos os arquivos recentemente adicionados:

<div class="flex justify-center">
<img src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter4/full_model.png" alt="The 'Files and versions' tab now contains all the recently uploaded files." width="80%"/>
</div>

A IU permite que você explore os arquivos modelo e os commits e veja as diferenças introduzidas por cada commit:

<div class="flex justify-center">
<img src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter4/diffs.gif" alt="The diff introduced by the recent commit." width="80%"/>
</div>
{:else}
Se dermos uma olhada no repositório modelo quando este estiver terminado, podemos ver todos os arquivos recentemente adicionados:

<div class="flex justify-center">
<img src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter4/full_model_tf.png" alt="The 'Files and versions' tab now contains all the recently uploaded files." width="80%"/>
</div>

A IU permite que você explore os arquivos modelo e os commits e veja as diferenças introduzidas por cada commit:

<div class="flex justify-center">
<img src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter4/diffstf.gif" alt="The diff introduced by the recent commit." width="80%"/>
</div>
{/if}


<EditOnGithub source="https://github.com/huggingface/course/blob/main/chapters/pt/chapter4/3.mdx" />

### Questionário de fim de capítulo
https://huggingface.co/learn/course/pt/chapter4/6.md

# Questionário de fim de capítulo

<CourseFloatingBanner
    chapter={4}
    classNames="absolute z-10 right-0 top-0"
/>

Vamos testar o que você aprendeu neste capítulo!
  
### 1. A que se limitam os modelos no Hub?

<Question
	choices={[
		{
			text: "Modelos da biblioteca de 🤗 transformers.",
			explain: "Embora os modelos da biblioteca de 🤗 transformers sejam suportados no Hugging Face Hub, eles não são os únicos!"
		},
		{
			text: "Todos os modelos com uma interface semelhante a🤗 Transformers.",
			explain: "Nenhum requisito de interface é definido ao carregar os modelos para o Hugging Face Hub. "
		},
		{
			text: "Não tem limitações.",
			explain: "Certo! Não há limites no carregamento de modelos para o Hub.",
            correct: true
		},
        {
			text: "Modelos que estão de alguma forma relacionados à PNL.",
			explain: "Nenhuma exigência é estabelecida em relação ao campo de aplicação"
		}
	]}
/>

### 2. Como você pode gerenciar modelos no Hub?

<Question
	choices={[
		{
			text: "Através de uma conta GCP.",
			explain: "Errado!"
		},
		{
			text: "Através de uma distribuição peer-to-peer.",
			explain: "Errado!"
		},
		{
			text: "Através do git e git-lfs.",
			explain: "Correto! Os modelos no Hub são repositórios Git simples, deixando o <code>git-lfs</code> para arquivos grandes.",
            correct: true
		}
	]}
/>

### 3. O que você pode fazer usando a interface web do Hugging Face Hub?

<Question
	choices={[
		{
			text: "Fazer um fork de um repositório existente.",
			explain: "Não é possível forkar um repositório no Hugging Face Hub."
		},
		{
			text: "Criar um repositório de um novo modelo.",
			explain: "Correto! Isso não é tudo que você pode fazer.",
            correct: true
		},
		{
			text: "Gerenciar e editar aquivos.",
			explain: "Correto! Isso não é a única resposta.",
            correct: true
		},
        {
			text: "Upload de arquivos.",
			explain: "Certo! Mas não é tudo.",
            correct: true
		},
        {
			text: "Ver as diferenças entre as versões.",
			explain: "Correto! Isso não é tudo que você pode fazer.",
            correct: true
		}
	]}
/>

### 4. O que é um model card (cartão de modelo)?

<Question
	choices={[
		{
			text: "Uma descrição aproximada do modelo, portanto menos importante do que o modelo e os arquivos do tokenizer.",
			explain: "É de fato uma descrição do modelo, mas é uma peça importante: se estiver incompleta ou ausente, a utilidade do modelo é drasticamente reduzida."
		},
		{
			text: "Uma maneira de garantir reprodutibilidade, reusabilidade e equidade.",
			explain: "Correto! Compartilhar as informações corretas no cartão modelo ajudará os usuários a utilizar seu modelo e estar ciente de seus limites e preconceitos.",
            correct: true
		},
		{
			text: "Um arquivo Python que pode ser executado para recuperar informações sobre o modelo.",
			explain: "Cartões de modelos são apenas arquivos Markdown."
		}
	]}
/>

### 5. Quais destes objetos da biblioteca 🤗 Transformers podem ser compartilhados diretamente no Hub com `push_to_hub()`?

{#if fw === 'pt'}
<Question
	choices={[
		{
			text: "Um tokenizer",
			explain: "Correto! Todos os tokenizers possuem o método <code>push_to_hub</code>, e usá-la enviara todos os arquivos tokenizer (vocabulário, arquitetura do tokenizer, etc.) para um determinado repo. Embora essa não seja a única resposta correta!",
            correct: true
		},
		{
			text: "Uma configuração de modelo",
			explain: "Certo! Todas configurações de modelos possuem o método <code>push_to_hub</code>, e usá-la enviara todas para um determinado repositório. O que mais você pode compartilhar?",
            correct: true
		},
		{
			text: "Um modelo",
			explain: "Correto! Todos modelos possuem o método <code>push_to_hub</code>, e usá-la enviara ele e suas configurações para um determinado repositório. Embora essa não seja a única resposta correta!",
            correct: true
		},
        {
			text: "Um Trainer",
			explain: "Está certa — o <code>Trainer</code> também implementa o método <code>push_to_hub</code>, e usa-lo ira enviar os arquivos do modelo, sua configuração, o tokenizer, eo rascunho do cartão de modelo para um repositório. Porém, não é a única resposta correta!",
            correct: true
		}
	]}
/>
{:else}
<Question
	choices={[
		{
			text: "Um tokenizer",
			explain: "Correto! Todos os tokenizers possuem o método <code>push_to_hub</code>, e usá-la enviara todos os arquivos tokenizer (vocabulário, arquitetura do tokenizer, etc.) para um determinado repo. Embora essa não seja a única resposta correta!",
            correct: true
		},
		{
			text: "Uma configuração de modelo",
			explain: "Certo! Todas configurações de modelos possuem o método <code>push_to_hub</code>, e usá-la enviara todas para um determinado repositório. O que mais você pode compartilhar?",
            correct: true
		},
		{
			text: "Um modelo",
			explain: "Correto! Todos modelos possuem o método <code>push_to_hub</code>, e usá-la enviara ele e suas configurações para um determinado repositório. Embora essa não seja a única resposta correta!",
            correct: true
		},
        {
			text: "Todas as opções com uma callback dedicado",
			explain: "Está certa — o <code>PushToHubCallback</code> ira enviar regularmente os arquivos do modelo, sua configuração, e o tokenizer durante o treinamento para um repositório. Porém, não é a única resposta correta!",
            correct: true
		}
	]}
/>
{/if}

### 6. Qual é o primeiro passo ao utilizar o método `push_to_hub()` ou as ferramentas CLI?

<Question
	choices={[
		{
			text: "Entrar no website.",
			explain: "Isto não ira ajudar você na sua máquina local."
		},
		{
			text: "Rodar 'huggingface-cli login' no terminal.",
			explain: "Correto — isto irá baixar e cachear seu token pessoal.",
            correct: true
		},
		{
			text: "Rodar 'notebook_login()' em um notebook.",
			explain: "Correto — isto irá exibir um widget para você se autenticar.",
            correct: true
		},
	]}
/>

### 7.  Você está usando um modelo e um tokenizer - como você pode envia eles para o Hub?

<Question
	choices={[
		{
			text: "Chamando diretamente o método push_to_hub no modelo e no tokenizer.",
			explain: "Correto!",
            correct: true
		},
		{
			text: "Dentro do tempo de execução Python, envolvendo-os em um <code>huggingface_hub</code> utilidade.",
			explain: "Modelos e tokenizers já se beneficiam de <code>huggingface_hub</code> utilidades: não há necessidade de wrappers adicionais!"
		},
		{
			text: "Salvando eles em disco e chamando <code>transformers-cli upload-model</code>",
			explain: "O comando <code>upload-model</code> não existe."
		}
	]}
/>

### 8. Que operações de git você pode fazer com a classe `Repository`?

<Question
	choices={[
		{
			text: "Um commit.",
			explain: "Correto, o método <code>git_commit()</code> é para isto!",
            correct: true
		},
		{
			text: "Um pull",
			explain: "Este é o proposito do método <code>git_pull()</code>.",
            correct: true
		},
		{
			text: "Um push",
			explain: "O método <code>git_push()</code> realiza isto.",
            correct: true
		},
		{
			text: "Um merge",
			explain: "Não, esta operação nunca será permitida nessa API."
		}
	]}
/>


<EditOnGithub source="https://github.com/huggingface/course/blob/main/chapters/pt/chapter4/6.mdx" />

### Construindo um cartão para o modelo
https://huggingface.co/learn/course/pt/chapter4/4.md

# Construindo um cartão para o modelo

<CourseFloatingBanner
    chapter={4}
    classNames="absolute z-10 right-0 top-0"
/>

O cartão para o modelo (model card) é um arquivo que é discutivelmente tão importante quanto os arquivos modelo e tokenizer em um repositório modelo. É a definição central do modelo, garantindo a reutilização pelos membros da comunidade e a reprodutibilidade dos resultados, e fornecendo uma plataforma sobre a qual outros membros podem construir seus artefatos. 

Documentar o processo de treinamento e avaliação ajuda outros a entender o que esperar de um modelo - e fornecer informações suficientes sobre os dados que foram utilizados e o pré e pós-processamento que foram feitos garante que as limitações, enviesamentos e contextos nos quais o modelo é e não é útil possam ser identificados e compreendidos.

Portanto, criar um model card que defina claramente seu modelo é um passo muito importante. Aqui, fornecemos algumas dicas que o ajudarão com isto. A criação do model card é feita através do arquivo *README.md* que você viu anteriormente, que é um arquivo Markdown.

O conceito de "model card" tem origem em uma direção de pesquisa do Google, primeiro compartilhada no artigo ["Model Cards for Model Reporting"](https://arxiv.org/abs/1810.03993) de Margaret Mitchell et al. Muitas das informações contidas aqui são baseadas nesse artigo, e recomendamos que você dê uma olhada nele para entender por que os cartões modelo são tão importantes em um mundo que valoriza a reprodutibilidade, a reusabilidade e a justiça.

O model card geralmente começa com uma visão geral muito breve e de alto nível do que o modelo serve, seguida por detalhes adicionais nas seções seguintes:

- Descrição do modelo
- Usos e limitações
- Como usar
- Dados de treinamento 
- Procedimento de treinamento
- Resultados da avaliação 

Vamos dar uma olhada no que cada uma dessas seções deve conter.

### Descrição do modelo

A descrição do modelo fornece detalhes básicos sobre o modelo. Isto inclui a arquitetura, versão, se foi introduzida em um artigo, se uma implementação original está disponível, o autor, e informações gerais sobre o modelo. Qualquer direito autoral deve ser atribuído aqui. Informações gerais sobre procedimentos de treinamento, parâmetros e renúncias importantes também podem ser mencionadas nesta seção.

### Usos e limitações

Aqui você descreve os casos de uso a que o modelo se destina, incluindo os idiomas, campos e domínios onde ele pode ser aplicado. Esta seção do cartão modelo também pode documentar áreas que são conhecidas por estarem fora do escopo do modelo, ou onde é provável que ele tenha um desempenho subótimo.

### Como usar

Esta seção deve incluir alguns exemplos de como utilizar o modelo. Isto pode mostrar a utilização da função `pipeline()`, utilização do modelo e classes de tokenizer, e qualquer outro código que você acha que possa ser útil.

### Dados de treinamento 

Esta parte deve indicar em que conjunto(s) de dados o modelo foi treinado. Uma breve descrição do(s) conjunto(s) de dados também é bem-vinda.

### Procedimento de treinamento

Nesta seção você deve descrever todos os aspectos relevantes do treinamento que são úteis a partir de uma perspectiva de reprodutibilidade. Isto inclui qualquer pré-processamento e pós-processamento que foram feitos nos dados, assim como detalhes como o número de épocas para as quais o modelo foi treinado, o tamanho do lote, a taxa de aprendizado, etc.

### Variáveis e métricas

Aqui você deve descrever as métricas que você usa para avaliação e os diferentes fatores que você está mensurando. A menção de qual(is) métrica(s) foi utilizada(s), em qual conjunto de dados e qual divisão de conjunto de dados facilita a comparação do desempenho do seu modelo em comparação com o de outros modelos. Estes devem ser informados pelas seções anteriores, tais como os usuários pretendidos e os casos de uso.

### Resultados da avaliação 

Finalmente, fornecer uma indicação de quão bem o modelo funciona no conjunto de dados de avaliação. Se o modelo utiliza um limiar de decisão, ou fornecer o limiar de decisão utilizado na avaliação, ou fornecer detalhes sobre a avaliação em diferentes limiares para os usos pretendidos.

## Exemplo

Confira a seguir alguns exemplos de model card bem elaborados:

- [`bert-base-cased`](https://huggingface.co/bert-base-cased)
- [`gpt2`](https://huggingface.co/gpt2)
- [`distilbert`](https://huggingface.co/distilbert-base-uncased)

Mais exemplos de diferentes organizações e empresas estão disponíveis [aqui](https://github.com/huggingface/model_card/blob/master/examples.md).

## Nota

Model cards are not a requirement when publishing models, and you don't need to include all of the sections described above when you make one. However, explicit documentation of the model can only benefit future users, so we recommend that you fill in as many of the sections as possible to the best of your knowledge and ability. 

## Model card metadata

Os model card não são uma exigência quando se publica modelos, e não é necessário incluir todas as seções descritas acima quando se faz um. Entretanto, a documentação explícita do modelo só pode beneficiar futuros usuários, por isso recomendamos que você preencha o maior número possível de seções com o melhor de seu conhecimento e capacidade. 


Por exemplo, se você der uma olhada no model card [`camembert-base`(https://huggingface.co/camembert-base/blob/main/README.md), você deve ver as seguintes linhas no cabeçalho do model card:

```
---
language: fr
license: mit
datasets:
- oscar
---

```
Estes metadados são analisados pelo Hugging Face Hub, que então identifica este modelo como sendo um modelo francês, com uma licença MIT, treinado no conjunto de dados Oscar. 

A [especificação completa do model card](https://github.com/huggingface/hub-docs/blame/main/modelcard.md) permite especificar idiomas, licenças, tags, conjuntos de dados, métricas, assim como os resultados da avaliação do modelo obtido no treinamento. 


<EditOnGithub source="https://github.com/huggingface/course/blob/main/chapters/pt/chapter4/4.mdx" />

### Usando modelos pré-treinados
https://huggingface.co/learn/course/pt/chapter4/2.md

# Usando modelos pré-treinados

{#if fw === 'pt'}

<CourseFloatingBanner chapter={4}
  classNames="absolute z-10 right-0 top-0"
  notebooks={[
    {label: "Google Colab", value: "https://colab.research.google.com/github/huggingface/notebooks/blob/master/course/pt/chapter4/section2_pt.ipynb"},
    {label: "Aws Studio", value: "https://studiolab.sagemaker.aws/import/github/huggingface/notebooks/blob/master/course/pt/chapter4/section2_pt.ipynb"},
]} />

{:else}

<CourseFloatingBanner chapter={4}
  classNames="absolute z-10 right-0 top-0"
  notebooks={[
    {label: "Google Colab", value: "https://colab.research.google.com/github/huggingface/notebooks/blob/master/course/pt/chapter4/section2_tf.ipynb"},
    {label: "Aws Studio", value: "https://studiolab.sagemaker.aws/import/github/huggingface/notebooks/blob/master/course/pt/chapter4/section2_tf.ipynb"},
]} />

{/if}

O Model Hub torna simples a seleção do modelo apropriado, de modo que o uso em qualquer biblioteca pode ser feito em algumas linhas de código. Vamos dar uma olhada em como realmente usar um desses modelos, e como contribuir de volta à comunidade.

Digamos que estamos à procura de um modelo baseado na língua francesa que possa realizar o enchimento de máscara.

<div class="flex justify-center">
<img src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter4/camembert.gif" alt="Selecting the Camembert model." width="80%"/>
</div>

Selecionamos o checkpoint `camembert-base` para experimentá-lo. O identificador `camembert-base` é tudo o que precisamos para começar a utilizá-lo! Como você já viu nos capítulos anteriores, podemos instanciá-lo utilizando a função `pipeline()`:

```py
from transformers import pipeline

camembert_fill_mask = pipeline("fill-mask", model="camembert-base")
results = camembert_fill_mask("Le camembert est <mask> :)")
```

```python out
[
  {'sequence': 'Le camembert est délicieux :)', 'score': 0.49091005325317383, 'token': 7200, 'token_str': 'délicieux'}, 
  {'sequence': 'Le camembert est excellent :)', 'score': 0.1055697426199913, 'token': 2183, 'token_str': 'excellent'}, 
  {'sequence': 'Le camembert est succulent :)', 'score': 0.03453313186764717, 'token': 26202, 'token_str': 'succulent'}, 
  {'sequence': 'Le camembert est meilleur :)', 'score': 0.0330314114689827, 'token': 528, 'token_str': 'meilleur'}, 
  {'sequence': 'Le camembert est parfait :)', 'score': 0.03007650189101696, 'token': 1654, 'token_str': 'parfait'}
]
```

Como você pode ver, carregar um modelo dentro de um pipeline é extremamente simples. A única coisa que você precisa estar atento é que o checkpoint escolhido é adequado para a tarefa para a qual ele será utilizado. Por exemplo, aqui estamos carregando o checkpoint `camembert-base` no pipeline `fill-mask`, o que é completamente bom. Mas se carregássemos este checkpoint no pipeline de `text-classification`, os resultados não fariam sentido porque a head da `camembert-base` não é adequado para esta tarefa! Recomendamos a utilização do seletor de tarefas na interface do Hub de abraço facial a fim de selecionar os checkpoints apropriados:

<div class="flex justify-center">
<img src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter4/tasks.png" alt="The task selector on the web interface." width="80%"/>
</div>

Você também pode instanciar o checkpoint usando diretamente a arquitetura modelo:

{#if fw === 'pt'}
```py
from transformers import CamembertTokenizer, CamembertForMaskedLM

tokenizer = CamembertTokenizer.from_pretrained("camembert-base")
model = CamembertForMaskedLM.from_pretrained("camembert-base")
```

No entanto, recomendamos a utilização das classes [`Auto*`](https://huggingface.co/transformers/model_doc/auto.html?highlight=auto#auto-classes), pois estas são por arquitetura de projeto - agnóstica. Enquanto a amostra de código anterior limita os usuários a checkpoint carregáveis na arquitetura CamemBERT, a utilização das classes `Auto*` torna a troca de checkpoint simples:

```py
from transformers import AutoTokenizer, AutoModelForMaskedLM

tokenizer = AutoTokenizer.from_pretrained("camembert-base")
model = AutoModelForMaskedLM.from_pretrained("camembert-base")
```
{:else}
```py
from transformers import CamembertTokenizer, TFCamembertForMaskedLM

tokenizer = CamembertTokenizer.from_pretrained("camembert-base")
model = TFCamembertForMaskedLM.from_pretrained("camembert-base")
```

No entanto, recomendamos a utilização das classes [`TFAuto*`](https://huggingface.co/transformers/model_doc/auto.html?highlight=auto#auto-classes), pois estas são por arquitetura de projeto - agnóstica. Enquanto a amostra de código anterior limita os usuários a checkpoint carregáveis na arquitetura CamemBERT, a utilização das classes `TFAuto*` torna a troca de checkpoint simples:


```py
from transformers import AutoTokenizer, TFAutoModelForMaskedLM

tokenizer = AutoTokenizer.from_pretrained("camembert-base")
model = TFAutoModelForMaskedLM.from_pretrained("camembert-base")
```
{/if}

<Tip>
Ao utilizar um modelo pré-treinado, certifique-se de verificar como ele foi treinado, em quais datasets, seus limites e seus enviesamentos. Todas estas informações devem ser indicadas em seu modelo de cartão.
</Tip>


<EditOnGithub source="https://github.com/huggingface/course/blob/main/chapters/pt/chapter4/2.mdx" />

### Introdução
https://huggingface.co/learn/course/pt/chapter3/1.md

# Introdução

<CourseFloatingBanner
    chapter={3}
    classNames="absolute z-10 right-0 top-0"
/>

No [Capítulo 2](/course/chapter2) exploramos como utilizar tokenizadores e modelos pré treinados para fazer previsões. Mas e se você quiser ajustar um modelo pré-treinado para seu próprio dataset? Esse é o tema deste capítulo! Você vai aprender:

{#if fw === 'pt'}
* Como preparar um datset grande do Hub
* Como usar a API de alto nível `Trainer` para ajustar um modelo
* Como usar um loop de treinamento personalizado
* Como usar a biblioteca 🤗 Accelerate para executar facilmente esse loop de treinamento personalizado em qualquer configuração distribuída
{#else}

{:else}
* Como preparar um dataset grande do Hub
* Como usar Keras para ajustar um modelo
* Como usar Keras para fazer previsões
* Como usar uma métrica personalizada

{/if}

Para fazer upload de seus checkpoints treinados para o Hugging Face Hub, você precisará de uma conta huggingface.co: [crie uma conta](https://huggingface.co/join)

<EditOnGithub source="https://github.com/huggingface/course/blob/main/chapters/pt/chapter3/1.mdx" />

### Introdução
https://huggingface.co/learn/course/pt/chapter8/1.md

# Introdução

<CourseFloatingBanner
    chapter={8}
    classNames="absolute z-10 right-0 top-0"
/>

Agora que você sabe como lidar com as tarefas mais comuns de PNL com 🤗 Transformers, você deve ser capaz de começar seus próprios projetos! Neste capítulo, exploraremos o que fazer quando você encontrar um problema. Você aprenderá como debugar com sucesso seu código ou seu treino e como pedir ajuda à comunidade se não conseguir resolver o problema sozinho. E se você acha que encontrou um bug em uma das bibliotecas do Hugging Face, mostraremos a melhor maneira de informa-lo para que o problema seja resolvido o mais rápido possível.

Mais precisamente, neste capítulo você aprenderá:

- A primeira coisa a fazer quando você recebe um erro
- Como pedir ajuda nos [fóruns](https://discuss.huggingface.co/)
- Como debugar sua pipeline de treinamento
- Como escrever uma boa issue

Nada disso está especificamente relacionado a 🤗 Transformers ou ao ecossistema Hugging Face, é claro; os tópicos deste capítulo são aplicáveis à maioria dos projetos de código aberto!

<EditOnGithub source="https://github.com/huggingface/course/blob/main/chapters/pt/chapter8/1.mdx" />

### Pedindo ajuda nos fóruns
https://huggingface.co/learn/course/pt/chapter8/3.md

# Pedindo ajuda nos fóruns
<CourseFloatingBanner chapter={8}
  classNames="absolute z-10 right-0 top-0"
  notebooks={[
    {label: "Google Colab", value: "https://colab.research.google.com/github/huggingface/notebooks/blob/master/course/pt/chapter8/section3.ipynb"},
    {label: "Aws Studio", value: "https://studiolab.sagemaker.aws/import/github/huggingface/notebooks/blob/master/course/pt/chapter8/section3.ipynb"},
]} />

<Youtube id="S2EEG3JIt2A"/>

Os [fóruns do Hugging Face](https://discuss.huggingface.co) são um ótimo lugar para obter ajuda da equipe de código aberto e da comunidade Hugging Face. Aqui está a aparência da página principal em um determinado dia:

<div class="flex justify-center">
<img src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter8/forums.png" alt="The Hugging Face forums." width="100%"/>
</div>

No lado esquerdo você pode ver todas as categorias em que os vários tópicos estão agrupados, enquanto o lado direito mostra os tópicos mais recentes. Um tópico é uma postagem que contém um título, categoria e descrição; é bastante semelhante ao formato de problemas do GitHub que vimos ao criar nosso próprio conjunto de dados no [Capítulo 5](/course/chapter5). Como o nome sugere, a categoria [Beginners](https://discuss.huggingface.co/c/beginners/5) destina-se principalmente a pessoas que estão começando com as bibliotecas e o ecossistema Hugging Face. Qualquer dúvida sobre qualquer uma das bibliotecas é bem-vinda, seja para depurar algum código ou pedir ajuda sobre como fazer algo. (Dito isso, se sua pergunta diz respeito a uma biblioteca em particular, você provavelmente deve ir para a categoria de biblioteca correspondente no fórum.)

Da mesma forma, as categorias [Intermediário](https://discuss.huggingface.co/c/intermediate/6) e [Pesquisa](https://discuss.huggingface.co/c/research/7) são para perguntas mais avançadas, por exemplo, sobre as bibliotecas ou alguma nova pesquisa interessante sobre PNL que você gostaria de discutir.

E, naturalmente, também devemos mencionar a categoria [Curso](https://discuss.huggingface.co/c/course/20), onde você pode tirar todas as suas dúvidas relacionadas ao curso Hugging Face!

Depois de selecionar uma categoria, você estará pronto para escrever seu primeiro tópico. Você pode encontrar algumas [diretrizes](https://discuss.huggingface.co/t/how-to-request-support/3128) no fórum sobre como fazer isso, e nesta seção veremos algumas características que compõem um bom tópico.

## Escrevendo uma boa postagem no fórum

Como exemplo de execução, vamos supor que estamos tentando gerar embeddings de artigos da Wikipedia para criar um mecanismo de pesquisa personalizado. Como de costume, carregamos o tokenizer e o model da seguinte forma:

```python
from transformers import AutoTokenizer, AutoModel

model_checkpoint = "distilbert-base-uncased"
tokenizer = AutoTokenizer.from_pretrained(model_checkpoint)
model = AutoModel.from_pretrained(model_checkpoint)
```

Agora suponha que tentamos incorporar uma seção inteira do [artigo da Wikipédia](https://en.wikipedia.org/wiki/Transformers) em Transformers (a franquia, não a biblioteca!):

```python
text = """
Generation One is a retroactive term for the Transformers characters that
appeared between 1984 and 1993. The Transformers began with the 1980s Japanese
toy lines Micro Change and Diaclone. They presented robots able to transform
into everyday vehicles, electronic items or weapons. Hasbro bought the Micro
Change and Diaclone toys, and partnered with Takara. Marvel Comics was hired by
Hasbro to create the backstory; editor-in-chief Jim Shooter wrote an overall
story, and gave the task of creating the characthers to writer Dennis O'Neil.
Unhappy with O'Neil's work (although O'Neil created the name "Optimus Prime"),
Shooter chose Bob Budiansky to create the characters.

The Transformers mecha were largely designed by Shōji Kawamori, the creator of
the Japanese mecha anime franchise Macross (which was adapted into the Robotech
franchise in North America). Kawamori came up with the idea of transforming
mechs while working on the Diaclone and Macross franchises in the early 1980s
(such as the VF-1 Valkyrie in Macross and Robotech), with his Diaclone mechs
later providing the basis for Transformers.

The primary concept of Generation One is that the heroic Optimus Prime, the
villainous Megatron, and their finest soldiers crash land on pre-historic Earth
in the Ark and the Nemesis before awakening in 1985, Cybertron hurtling through
the Neutral zone as an effect of the war. The Marvel comic was originally part
of the main Marvel Universe, with appearances from Spider-Man and Nick Fury,
plus some cameos, as well as a visit to the Savage Land.

The Transformers TV series began around the same time. Produced by Sunbow
Productions and Marvel Productions, later Hasbro Productions, from the start it
contradicted Budiansky's backstories. The TV series shows the Autobots looking
for new energy sources, and crash landing as the Decepticons attack. Marvel
interpreted the Autobots as destroying a rogue asteroid approaching Cybertron.
Shockwave is loyal to Megatron in the TV series, keeping Cybertron in a
stalemate during his absence, but in the comic book he attempts to take command
of the Decepticons. The TV series would also differ wildly from the origins
Budiansky had created for the Dinobots, the Decepticon turned Autobot Jetfire
(known as Skyfire on TV), the Constructicons (who combine to form
Devastator),[19][20] and Omega Supreme. The Marvel comic establishes early on
that Prime wields the Creation Matrix, which gives life to machines. In the
second season, the two-part episode The Key to Vector Sigma introduced the
ancient Vector Sigma computer, which served the same original purpose as the
Creation Matrix (giving life to Transformers), and its guardian Alpha Trion.
"""

inputs = tokenizer(text, return_tensors="pt")
logits = model(**inputs).logits
```

```python output
IndexError: index out of range in self
```

Uh-oh, encontramos um problema -- e a mensagem de erro é muito mais enigmática do que as que vimos na [seção 2](/curso/chapter8/section2)! Não podemos fazer cara ou coroa do traceback completo, então decidimos recorrer aos fóruns do Hugging Face para obter ajuda. Como podemos elaborar o tema?

Para começar, precisamos clicar no botão "Novo Tópico" (em inglês, **new topic**) no canto superior direito (observe que para criar um tópico, precisamos estar logados):

<div class="flex justify-center">
<img src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter8/forums-new-topic.png" alt="Creating a new forum topic." width="100%"/>
</div>

Isso traz uma interface de escrita onde podemos inserir o título do nosso tópico, selecionar uma categoria e redigir o conteúdo:

<div class="flex justify-center">
<img src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter8/forum-topic01.png" alt="The interface for creating a forum topic." width="100%"/>
</div>

Como o erro parece ser exclusivamente sobre 🤗 Transformers, selecionaremos isso para a categoria. Nossa primeira tentativa de explicar o problema pode ser algo assim:

<div class="flex justify-center">
<img src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter8/forum-topic02.png" alt="Drafting the content for a new forum topic." width="100%"/>
</div>

Embora este tópico contenha a mensagem de erro para a qual precisamos de ajuda, há alguns problemas com a forma como ela está escrita:

1. O título não é muito descritivo, então quem estiver navegando no fórum não poderá dizer do que se trata o tópico sem ler também o corpo.
2. O corpo não fornece informações suficientes sobre _onde_ o erro está vindo e _como_ reproduzi-lo.
3. O tópico marca algumas pessoas diretamente com um tom um tanto exigente.

Tópicos como este provavelmente não terão uma resposta rápida (se conseguirem), então vamos ver como podemos melhorá-lo. Vamos começar com a primeira questão de escolher um bom título.

### Escolhendo um título descritivo

Se você estiver tentando obter ajuda com um bug em seu código, uma boa regra geral é incluir informações suficientes no título para que outras pessoas possam determinar rapidamente se acham que podem responder à sua pergunta ou não. Em nosso exemplo em execução, sabemos o nome da exceção que está sendo levantada e temos algumas dicas de que ela é acionada na passagem direta do modelo, onde chamamos `model(**inputs)`. Para comunicar isso, um título possível poderia ser:

> Source of IndexError in the AutoModel forward pass?

Este título diz ao leitor _onde_ você acha que o bug está vindo, e se eles encontraram um `IndexError` antes, há uma boa chance de que eles saibam como depurá-lo. Claro, o título pode ser o que você quiser, e outras variações como:

> Why does my model produce an IndexError?

também pode ficar bem. Agora que temos um título descritivo, vamos dar uma olhada em como melhorar o corpo.

### Formatando seus trechos de código

Ler o código-fonte é bastante difícil em um IDE, mas é ainda mais difícil quando o código é copiado e colado como texto simples! Felizmente, os fóruns do Hugging Face suportam o uso de Markdown, então você deve sempre colocar seus blocos de código com três acentos graves (```) para que seja mais fácil de ler. Vamos fazer isso para embelezar a mensagem de erro - e enquanto estaomos nisso, vamos tornar o corpo um pouco mais educado do que a nossa versão original:

<div class="flex justify-center">
<img src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter8/forum-topic03.png" alt="Our revised forum topic, with proper code formatting." width="100%"/>
</div>

Como você pode ver na captura de tela, colocar os blocos de código em acentos graves converte o texto bruto em código formatado, completo com estilo de cores! Observe também que backticks simples podem ser usados ​​para formatar variáveis ​​inline, como fizemos para `distilbert-base-uncased`. Este tópico parece muito melhor e, com um pouco de sorte, podemos encontrar alguém na comunidade que possa adivinhar do que se trata o erro. No entanto, em vez de confiar na sorte, vamos facilitar a vida incluindo o rastreamento em todos os seus detalhes sangrentos!

### Incluindo o rastreamento completo

Como a última linha do traceback geralmente é suficiente para depurar seu próprio código, pode ser tentador apenas fornecer isso em seu tópico para "economizar espaço". Embora bem intencionado, isso na verdade torna _mais difícil_ para outros depurar o problema, já que as informações que estão mais acima no traceback também podem ser muito úteis. Portanto, uma boa prática é copiar e colar o traceback _inteiro_, certificando-se de que está bem formatado. Como esses rastreamentos podem ser bastante longos, algumas pessoas preferem mostrá-los depois de explicar o código-fonte. Vamos fazer isso. Agora, nosso tópico do fórum se parece com o seguinte:

<div class="flex justify-center">
<img src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter8/forum-topic04.png" alt="Our example forum topic, with the complete traceback." width="100%"/>
</div>

Isso é muito mais informativo, e um leitor cuidadoso pode apontar que o problema parece ser devido à passagem de uma entrada longa por causa desta linha no traceback:

> Token indices sequence length is longer than the specified maximum sequence length for this model (583 > 512).

No entanto, podemos tornar as coisas ainda mais fáceis para eles fornecendo o código real que acionou o erro. Vamos fazer isso agora.

### Fornecendo um exemplo reproduzível

Se você já tentou depurar o código de outra pessoa, provavelmente tentou primeiro recriar o problema relatado para poder começar a trabalhar no rastreamento para identificar o erro. Não é diferente quando se trata de obter (ou dar) assistência nos fóruns, então realmente ajuda se você puder fornecer um pequeno exemplo que reproduza o erro. Na metade do tempo, simplesmente fazer este exercício o ajudará a descobrir o que está acontecendo de errado. De qualquer forma, a parte que falta em nosso exemplo é mostrar as _inputs_ que fornecemos ao modelo. Fazer isso nos dá algo como o seguinte exemplo concluído:

<div class="flex justify-center">
<img src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter8/forum-topic05.png" alt="The final version of our forum topic." width="100%"/>
</div>

Este tópico agora contém muitas informações e foi escrito de uma forma que é muito mais provável de atrair a atenção da comunidade e obter uma resposta útil. Com essas diretrizes básicas, agora você pode criar ótimos tópicos para encontrar as respostas para suas dúvidas sobre 🤗 Transformers!



<EditOnGithub source="https://github.com/huggingface/course/blob/main/chapters/pt/chapter8/3.mdx" />

### O que fazer quando ocorrer um erro
https://huggingface.co/learn/course/pt/chapter8/2.md

# O que fazer quando ocorrer um erro

<CourseFloatingBanner chapter={8}
  classNames="absolute z-10 right-0 top-0"
  notebooks={[
    {label: "Google Colab", value: "https://colab.research.google.com/github/huggingface/notebooks/blob/master/course/pt/chapter8/section2.ipynb"},
    {label: "Aws Studio", value: "https://studiolab.sagemaker.aws/import/github/huggingface/notebooks/blob/master/course/pt/chapter8/section2.ipynb"},
]} />

Nesta seção, veremos alguns erros comuns que podem ocorrer ao tentar gerar previsões de seu modelo Transformer recém treinado. Isso irá prepará-lo para a [seção 4](/course/chapter8/section4), onde exploraremos como debugar a própria fase de treinamento.

<Youtube id="DQ-CpJn6Rc4"/>

Preparamos um [repositório modelo](https://huggingface.co/lewtun/distilbert-base-uncased-finetuned-squad-d5716d28) para esta seção e, se você quiser executar o código neste capítulo, Primeiro, você precisará copiar o modelo para sua conta no [Hugging Face Hub](https://huggingface.co). Para fazer isso, primeiro faça login executando o seguinte em um notebook Jupyter:

```python
from huggingface_hub import notebook_login

notebook_login()
```

ou usando seu terminal favorito:

```bash
huggingface-cli login
```

Isso solicitará que você insira seu nome de usuário e senha e salvará um token em *~/.cache/huggingface/*. Depois de fazer login, você pode copiar o repositório de modelos com a seguinte função:

```python
from distutils.dir_util import copy_tree
from huggingface_hub import Repository, snapshot_download, create_repo, get_full_repo_name


def copy_repository_template():
    # Clone the repo and extract the local path
    template_repo_id = "lewtun/distilbert-base-uncased-finetuned-squad-d5716d28"
    commit_hash = "be3eaffc28669d7932492681cd5f3e8905e358b4"
    template_repo_dir = snapshot_download(template_repo_id, revision=commit_hash)
    # Create an empty repo on the Hub
    model_name = template_repo_id.split("/")[1]
    create_repo(model_name, exist_ok=True)
    # Clone the empty repo
    new_repo_id = get_full_repo_name(model_name)
    new_repo_dir = model_name
    repo = Repository(local_dir=new_repo_dir, clone_from=new_repo_id)
    # Copy files
    copy_tree(template_repo_dir, new_repo_dir)
    # Push to Hub
    repo.push_to_hub()
```

Agora, quando você chamar `copy_repository_template()`, ele criará uma cópia do repositório de modelos em sua conta.

## Debugando o pipeline de 🤗 Transformers

Para iniciar nossa jornada no maravilhoso mundo de debug de modelos Transformer, considere o seguinte cenário: você está trabalhando com um colega em um projeto de resposta a perguntas para ajudar os clientes de um site de comércio eletrônico a encontrar respostas sobre produtos de consumo. Seu colega lhe envia uma mensagem como:

> Bom dia! Acabei de fazer um experimento usando as técnicas do [Capítulo 7](/course/chapter7/7) do curso Hugging Face e obtive ótimos resultados no SQuAD! Acho que podemos usar esse modelo como checkpoint para o nosso projeto. O ID do modelo no Hub é "lewtun/distillbert-base-uncased-finetuned-squad-d5716d28". Fique a vontade para testar :)

e a primeira coisa que você pensa é carregar o modelo usando o `pipeline` de 🤗 Transformers:

```python
from transformers import pipeline

model_checkpoint = get_full_repo_name("distillbert-base-uncased-finetuned-squad-d5716d28")
reader = pipeline("question-answering", model=model_checkpoint)
```

```python out
"""
OSError: Can't load config for 'lewtun/distillbert-base-uncased-finetuned-squad-d5716d28'. Make sure that:

- 'lewtun/distillbert-base-uncased-finetuned-squad-d5716d28' is a correct model identifier listed on 'https://huggingface.co/models'

- or 'lewtun/distillbert-base-uncased-finetuned-squad-d5716d28' is the correct path to a directory containing a config.json file
"""
```

Oh não, algo parece ter dado errado! Se você é novo em programação, esse tipo de erro pode parecer um pouco enigmático no começo (o que é mesmo um `OSError`?!). O erro exibido aqui é apenas a última parte de um relatório de erros muito maior chamado _Python traceback_ (também conhecido como **stack trace**). Por exemplo, se você estiver executando este código no Google Colab, deverá ver algo como a captura de tela a seguir:

<div class="flex justify-center">
<img src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter8/traceback.png" alt="A Python traceback." width="100%"/>
</div>

Há muitas informações contidas nesses relatórios, então vamos percorrer as partes principais juntos. A primeira coisa a notar é que os tracebacks devem ser lidos _de baixo para cima_. Isso pode soar estranho se você está acostumado a ler texto em inglês de cima para baixo, mas reflete o fato de que o traceback mostra a sequência de chamadas de função que o `pipeline` faz ao baixar o modelo e o tokenizer. (Confira o [Capítulo 2](/course/chapter2) para mais detalhes sobre como o `pipeline` funciona nos bastidores.)

<Tip>

🚨 Está vendo aquela caixa azul em torno de "6 frames" no traceback do Google Colab? Esse é um recurso especial do Colab, que compacta o traceback em "quadros". Se você não conseguir encontrar a fonte de um erro, certifique-se de expandir o rastreamento completo clicando nessas duas pequenas setas.

</Tip>

Isso significa que a última linha do traceback indica a última mensagem de erro e fornece o nome da exceção que foi gerada. Nesse caso, o tipo de exceção é `OSError`, que indica um erro relacionado ao sistema. Se lermos a mensagem de erro que a acompanha, veremos que parece haver um problema com o arquivo *config.json* do modelo e recebemos duas sugestões para corrigi-lo:

```python out
"""
Make sure that:

- 'lewtun/distillbert-base-uncased-finetuned-squad-d5716d28' is a correct model identifier listed on 'https://huggingface.co/models'

- or 'lewtun/distillbert-base-uncased-finetuned-squad-d5716d28' is the correct path to a directory containing a config.json file
"""
```

<Tip>

💡 Se você encontrar uma mensagem de erro difícil de entender, basta copiar e colar a mensagem na barra de pesquisa do Google ou [Stack Overflow](https://stackoverflow.com/) (sim, sério!). Há uma boa chance de você não ser a primeira pessoa a encontrar o erro, e essa é uma boa maneira de encontrar soluções que outras pessoas da comunidade postaram. Por exemplo, pesquisar por `OSError: Can't load config for` no Stack Overflow fornece vários [hits](https://stackoverflow.com/search?q=OSError%3A+Can%27t+load+config+for+) que poderia ser usado como ponto de partida para resolver o problema.

</Tip>

A primeira sugestão é nos pedir para verificar se o ID do modelo está realmente correto, então a primeira ordem do dia é copiar o identificador e colá-lo na barra de pesquisa do Hub:

<div class="flex justify-center">
<img src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter8/wrong-model-id.png" alt="The wrong model name." width="100%"/>
</div>

Hmm, realmente parece que o modelo do nosso colega não está no Hub... aha, mas há um erro de digitação no nome do modelo! DistilBERT tem apenas um "l" em seu nome, então vamos corrigir isso e procurar por "lewtun/distilbert-base-uncased-finetuned-squad-d5716d28":

<div class="flex justify-center">
<img src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter8/true-model-id.png" alt="The right model name." width="100%"/>
</div>

Ok, isso teve sucesso. Agora vamos tentar baixar o modelo novamente com o ID do modelo correto:

```python
model_checkpoint = get_full_repo_name("distilbert-base-uncased-finetuned-squad-d5716d28")
reader = pipeline("question-answering", model=model_checkpoint)
```

```python out
"""
OSError: Can't load config for 'lewtun/distilbert-base-uncased-finetuned-squad-d5716d28'. Make sure that:

- 'lewtun/distilbert-base-uncased-finetuned-squad-d5716d28' is a correct model identifier listed on 'https://huggingface.co/models'

- or 'lewtun/distilbert-base-uncased-finetuned-squad-d5716d28' is the correct path to a directory containing a config.json file
"""
```

Argh, frustrado novamente - bem-vindo ao cotidiano de um engenheiro de aprendizado de máquina! Como corrigimos o ID do modelo, o problema deve estar no próprio repositório. Uma maneira rápida de acessar o conteúdo de um repositório no 🤗 Hub é através da função `list_repo_files()` da biblioteca `huggingface_hub`:

```python
from huggingface_hub import list_repo_files

list_repo_files(repo_id=model_checkpoint)
```

```python out
['.gitattributes', 'README.md', 'pytorch_model.bin', 'special_tokens_map.json', 'tokenizer_config.json', 'training_args.bin', 'vocab.txt']
```

Interessante -- não parece haver um arquivo *config.json* no repositório! Não é à toa que nosso `pipeline` não conseguiu carregar o modelo; nosso colega deve ter esquecido de enviar este arquivo para o Hub depois de ajustá-lo. Nesse caso, o problema parece bem simples de corrigir: poderíamos pedir para adicionar o arquivo ou, como podemos ver no ID do modelo, que o modelo pré-treinado usado foi [`distilbert-base-uncased`](https:/ /huggingface.co/distilbert-base-uncased), podemos baixar a configuração para este modelo e enviá-la para nosso repositório para ver se isso resolve o problema. Vamos tentar isso. Usando as técnicas que aprendemos no [Capítulo 2](/course/chapter2), podemos baixar a configuração do modelo com a classe `AutoConfig`:


```python
from transformers import AutoConfig

pretrained_checkpoint = "distilbert-base-uncased"
config = AutoConfig.from_pretrained(pretrained_checkpoint)
```

<Tip warning={true}>

🚨 A abordagem que estamos tomando aqui não é infalível, já que nosso colega pode ter ajustado a configuração de `distilbert-base-uncased` antes de ajustar o modelo. Na vida real, gostaríamos de verificar com eles primeiro, mas para os propósitos desta seção, vamos supor que eles usaram a configuração padrão.

</Tip>

Podemos então enviar isso para o nosso repositório de modelos com a função `push_to_hub()` da configuração:

```python
config.push_to_hub(model_checkpoint, commit_message="Add config.json")
```

Agora podemos testar se funcionou carregando o modelo do último commit no branch `main`:

```python
reader = pipeline("question-answering", model=model_checkpoint, revision="main")

context = r"""
Extractive Question Answering is the task of extracting an answer from a text
given a question. An example of a question answering dataset is the SQuAD
dataset, which is entirely based on that task. If you would like to fine-tune a
model on a SQuAD task, you may leverage the
examples/pytorch/question-answering/run_squad.py script.

🤗 Transformers is interoperable with the PyTorch, TensorFlow, and JAX
frameworks, so you can use your favourite tools for a wide variety of tasks!
"""

question = "What is extractive question answering?"
reader(question=question, context=context)
```

```python out
{'score': 0.38669535517692566,
 'start': 34,
 'end': 95,
 'answer': 'the task of extracting an answer from a text given a question'}
```

Uhuuul, funcionou! Vamos recapitular o que você acabou de aprender:

- As mensagens de erro em Python são conhecidas como _tracebacks_ e são lidas de baixo para cima. A última linha da mensagem de erro geralmente contém as informações necessárias para localizar a origem do problema.
- Se a última linha não contiver informações suficientes, suba o traceback e veja se você consegue identificar onde no código-fonte o erro ocorre.
- Se nenhuma das mensagens de erro puder ajudá-lo a debugar o problema, tente pesquisar online uma solução para um problema semelhante.
- O `huggingface_hub`
// 🤗 Hub?
esta biblioteca fornece um conjunto de ferramentas que você pode usar para interagir e debugar repositórios no Hub.

Agora que você sabe como debugar um pipeline, vamos dar uma olhada em um exemplo mais complicado no forward pass do próprio modelo.

## Debugando o forward pass do seu modelo

Embora o `pipeline` seja ótimo para a maioria dos aplicativos em que você precisa gerar previsões rapidamente, às vezes você precisará acessar os logits do modelo (digamos, se você tiver algum pós-processamento personalizado que gostaria de aplicar). Para ver o que pode dar errado neste caso, vamos primeiro pegar o modelo e o tokenizer do nosso `pipeline`:

```python
tokenizer = reader.tokenizer
model = reader.model
```

Em seguida, precisamos de uma pergunta, então vamos ver se nossos frameworks favoritos são suportados:

```python
question = "Which frameworks can I use?"
```

Como vimos no [Capítulo 7](/course/chapter7), as etapas usuais que precisamos seguir são tokenizar as entradas, extrair os logits dos tokens de início e fim e, em seguida, decodificar o intervalo de resposta:

```python
import torch

inputs = tokenizer(question, context, add_special_tokens=True)
input_ids = inputs["input_ids"][0]
outputs = model(**inputs)
answer_start_scores = outputs.start_logits
answer_end_scores = outputs.end_logits
# Get the most likely beginning of answer with the argmax of the score
answer_start = torch.argmax(answer_start_scores)
# Get the most likely end of answer with the argmax of the score
answer_end = torch.argmax(answer_end_scores) + 1
answer = tokenizer.convert_tokens_to_string(
    tokenizer.convert_ids_to_tokens(input_ids[answer_start:answer_end])
)
print(f"Question: {question}")
print(f"Answer: {answer}")
```

```python out
"""
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
/var/folders/28/k4cy5q7s2hs92xq7_h89_vgm0000gn/T/ipykernel_75743/2725838073.py in <module>
      1 inputs = tokenizer(question, text, add_special_tokens=True)
      2 input_ids = inputs["input_ids"]
----> 3 outputs = model(**inputs)
      4 answer_start_scores = outputs.start_logits
      5 answer_end_scores = outputs.end_logits

~/miniconda3/envs/huggingface/lib/python3.8/site-packages/torch/nn/modules/module.py in _call_impl(self, *input, **kwargs)
   1049         if not (self._backward_hooks or self._forward_hooks or self._forward_pre_hooks or _global_backward_hooks
   1050                 or _global_forward_hooks or _global_forward_pre_hooks):
-> 1051             return forward_call(*input, **kwargs)
   1052         # Do not call functions when jit is used
   1053         full_backward_hooks, non_full_backward_hooks = [], []

~/miniconda3/envs/huggingface/lib/python3.8/site-packages/transformers/models/distilbert/modeling_distilbert.py in forward(self, input_ids, attention_mask, head_mask, inputs_embeds, start_positions, end_positions, output_attentions, output_hidden_states, return_dict)
    723         return_dict = return_dict if return_dict is not None else self.config.use_return_dict
    724
--> 725         distilbert_output = self.distilbert(
    726             input_ids=input_ids,
    727             attention_mask=attention_mask,

~/miniconda3/envs/huggingface/lib/python3.8/site-packages/torch/nn/modules/module.py in _call_impl(self, *input, **kwargs)
   1049         if not (self._backward_hooks or self._forward_hooks or self._forward_pre_hooks or _global_backward_hooks
   1050                 or _global_forward_hooks or _global_forward_pre_hooks):
-> 1051             return forward_call(*input, **kwargs)
   1052         # Do not call functions when jit is used
   1053         full_backward_hooks, non_full_backward_hooks = [], []

~/miniconda3/envs/huggingface/lib/python3.8/site-packages/transformers/models/distilbert/modeling_distilbert.py in forward(self, input_ids, attention_mask, head_mask, inputs_embeds, output_attentions, output_hidden_states, return_dict)
    471             raise ValueError("You cannot specify both input_ids and inputs_embeds at the same time")
    472         elif input_ids is not None:
--> 473             input_shape = input_ids.size()
    474         elif inputs_embeds is not None:
    475             input_shape = inputs_embeds.size()[:-1]

AttributeError: 'list' object has no attribute 'size'
"""
```

Oxii, parece que temos um bug em nosso código! Mas não temos medo de debugar um pouco. Você pode usar o debugger do Python em um notebook:

<Youtube id="rSPyvPw0p9k"/>

ou em um terminal:

<Youtube id="5PkZ4rbHL6c"/>

Aqui, a leitura da mensagem de erro nos diz que o objeto `'list' não tem atributo 'size'`, e podemos ver uma seta `-->` apontando para a linha onde o problema foi levantado em `model(**inputs) `. Você pode debugar isso interativamente usando o debugger Python, mas por enquanto vamos simplesmente imprimir uma fatia de `entradas` para ver o que temos:

```python
inputs["input_ids"][:5]
```

```python out
[101, 2029, 7705, 2015, 2064]
```

Isso certamente se parece com uma `lista` comum do Python, mas vamos verificar novamente o tipo:

```python
type(inputs["input_ids"])
```

```python out
list
```

Sim, isso é uma `lista` do Python com certeza. Então o que deu errado? Lembre-se do [Capítulo 2](/course/chapter2) que as classes `AutoModelForXxx` em 🤗 Transformers operam em _tensors_ (em PyTorch ou TensorFlow), e uma operação comum é extrair as dimensões de um tensor usando `Tensor.size( )` em, digamos, PyTorch. Vamos dar outra olhada no traceback, para ver qual linha acionou a exceção:

```
~/miniconda3/envs/huggingface/lib/python3.8/site-packages/transformers/models/distilbert/modeling_distilbert.py in forward(self, input_ids, attention_mask, head_mask, inputs_embeds, output_attentions, output_hidden_states, return_dict)
    471             raise ValueError("You cannot specify both input_ids and inputs_embeds at the same time")
    472         elif input_ids is not None:
--> 473             input_shape = input_ids.size()
    474         elif inputs_embeds is not None:
    475             input_shape = inputs_embeds.size()[:-1]

AttributeError: 'list' object has no attribute 'size'
```

Parece que nosso código tentou chamar `input_ids.size()`, mas isso claramente não funcionará para uma `list` Python, que é apenas um contêiner. Como podemos resolver este problema? Pesquisar a mensagem de erro no Stack Overflow fornece alguns [hits] relevantes (https://stackoverflow.com/search?q=AttributeError%3A+%27list%27+object+has+no+attribute+%27size%27&s=c15ec54c-63cb-481d-a749-408920073e8f). Clicar no primeiro exibe uma pergunta semelhante à nossa, com a resposta mostrada na captura de tela abaixo:


<div class="flex justify-center">
<img src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter8/stack-overflow.png" alt="An answer from Stack Overflow." width="100%"/>
</div>

A resposta recomenda que adicionemos `return_tensors='pt'` ao tokenizer, então vamos ver se isso funciona para nós:

```python out
inputs = tokenizer(question, context, add_special_tokens=True, return_tensors="pt")
input_ids = inputs["input_ids"][0]
outputs = model(**inputs)
answer_start_scores = outputs.start_logits
answer_end_scores = outputs.end_logits
# Get the most likely beginning of answer with the argmax of the score
answer_start = torch.argmax(answer_start_scores)
# Get the most likely end of answer with the argmax of the score
answer_end = torch.argmax(answer_end_scores) + 1
answer = tokenizer.convert_tokens_to_string(
    tokenizer.convert_ids_to_tokens(input_ids[answer_start:answer_end])
)
print(f"Question: {question}")
print(f"Answer: {answer}")
```

```python out
"""
Question: Which frameworks can I use?
Answer: pytorch, tensorflow, and jax
"""
```

Legal, funcionou! Este é um ótimo exemplo de como o Stack Overflow pode ser útil: ao identificar um problema semelhante, pudemos nos beneficiar da experiência de outras pessoas da comunidade. No entanto, uma pesquisa como essa nem sempre produz uma resposta relevante, então o que você pode fazer nesses casos? Felizmente, há uma comunidade acolhedora de desenvolvedores nos [fóruns do Hugging Face](https://discuss.huggingface.co/) que pode ajudá-lo! Na próxima seção, veremos como você pode criar boas perguntas no fórum que provavelmente serão respondidas.

<EditOnGithub source="https://github.com/huggingface/course/blob/main/chapters/pt/chapter8/2.mdx" />

### Evento de lançamento da Parte 2
https://huggingface.co/learn/course/pt/events/2.md

# Evento de lançamento da Parte 2

Para o lançamento da parte 2 do curso, organizamos um evento ao vivo com dois dias de palestras antes de um sprint de ajuste. Se você perdeu, pode acompanhar as palestras que estão listadas abaixo!

## Dia 1: Uma visão de alto nível dos Transformers e como treiná-los

**Thomas Wolf:** *Transfer Learning and the birth of the Transformers library*

<div class="flex justify-center">
<Youtube id="wCYVeahJES0"/>
</div>

<p align="center">
<img src="https://i.imgur.com/9eq8oUi.png" alt="A visual summary of Thom's talk" width="80%"/>
</p>

Thomas Wolf é cofundador e Chief Science Officer da Hugging Face. As ferramentas criadas por Thomas Wolf e a equipe Hugging Face são usadas em mais de 5.000 organizações de pesquisa, incluindo Facebook Artificial Intelligence Research, Google Research, DeepMind, Amazon Research, Apple, Allen Institute for Artificial Intelligence e na maioria dos departamentos universitários. Thomas Wolf é o iniciador e presidente sênior da maior colaboração de pesquisa que já existiu em Inteligência Artificial: [“BigScience”](https://bigscience.huggingface.co), bem como um conjunto de [bibliotecas e ferramentas amplamente utilizadas ](https://github.com/huggingface/). Thomas Wolf também é um educador prolífico, um líder de pensamento no campo de Inteligência Artificial e Processamento de Linguagem Natural e um orador convidado regular para conferências em todo o mundo [https://thomwolf.io](https://thomwolf.io ).

**Jay Alammar:** *A gentle visual intro to Transformers models*

<div class="flex justify-center">
<Youtube id="VzvG23gmcYU"/>
</div>

<p align="center">
<img src="https://i.imgur.com/rOZAuE9.png" alt="A visual summary of Jay's talk" width="80%"/>
</p>

Por meio de seu popular blog de ML, Jay ajudou milhões de pesquisadores e engenheiros a entender visualmente ferramentas e conceitos de aprendizado de máquina desde o básico (terminando em NumPy, Pandas docs) até o de ponta (Transformers, BERT, GPT-3).

**Margaret Mitchell:** *On Values in ML Development*

<div class="flex justify-center">
<Youtube id="8j9HRMjh_s8"/>
</div>

<p align="center">
<img src="https://i.imgur.com/NuIsnY3.png" alt="A visual summary of Margaret's talk" width="80%"/>
</p>

Margaret Mitchell é uma pesquisadora que trabalha em IA ética, atualmente focada nos meandros do desenvolvimento de IA informada pela ética em tecnologia. Ela publicou mais de 50 artigos sobre geração de linguagem natural, tecnologia assistiva, visão computacional e ética em IA, e possui várias patentes nas áreas de geração de conversas e classificação de sentimentos. Ela trabalhou anteriormente no Google AI como Staff Research Scientist, onde fundou e co-liderou o grupo Ethical AI do Google, focado na pesquisa básica de ética em IA e na operacionalização da ética de IA internamente no Google. Antes de ingressar no Google, ela foi pesquisadora da Microsoft Research, focada na geração de visão computacional para linguagem; e fez pós-doutorado na Johns Hopkins, com foco em modelagem bayesiana e extração de informações. Ela possui doutorado em Ciência da Computação pela Universidade de Aberdeen e mestrado em linguística computacional pela Universidade de Washington. Enquanto se formava, ela também trabalhou de 2005 a 2012 em aprendizado de máquina, distúrbios neurológicos e tecnologia assistiva na Oregon Health and Science University. Ela liderou uma série de workshops e iniciativas nas interseções de diversidade, inclusão, ciência da computação e ética. Seu trabalho recebeu prêmios do Secretário de Defesa Ash Carter e da Fundação Americana para Cegos e foi implementado por várias empresas de tecnologia. Ela gosta de jardinagem, cães e gatos.

**Matthew Watson and Chen Qian:** *NLP workflows with Keras*

<div class="flex justify-center">
<Youtube id="gZIP-_2XYMM"/>
</div>

<p align="center">
<img src="https://i.imgur.com/1vD2az8.png" alt="A visual summary of Matt and Chen's talk" width="80%"/>
</p>

Matthew Watson é engenheiro de aprendizado de máquina na equipe Keras, com foco em APIs de modelagem de alto nível. Ele estudou Computação Gráfica durante a graduação e mestrado na Universidade de Stanford. Um quase graduado em inglês que se voltou para a ciência da computação, ele é apaixonado por trabalhar em várias disciplinas e tornar a PNL acessível a um público mais amplo.

Chen Qian é engenheiro de software da equipe Keras, com foco em APIs de modelagem de alto nível. Chen obteve um mestrado em Engenharia Elétrica pela Universidade de Stanford e está especialmente interessado em simplificar as implementações de código de tarefas de ML e ML em larga escala.

**Mark Saroufim:** *How to Train a Model with Pytorch*

<div class="flex justify-center">
<Youtube id="KmvPlW2cbIo"/>
</div>

<p align="center">
<img src="https://i.imgur.com/TPmlkm8.png" alt="A visual summary of Mark's talk" width="80%"/>
</p>

Mark Saroufim é um engenheiro parceiro do Pytorch trabalhando em ferramentas de produção OSS, incluindo TorchServe e Pytorch Enterprise. Em suas vidas passadas, Mark foi Cientista Aplicado e Gerente de Produto na Graphcore, [yuri.ai](http://yuri.ai/), Microsoft e JPL da NASA. Sua principal paixão é tornar a programação mais divertida.

**Jakob Uszkoreit:** *It Ain't Broke So <del>Don't Fix</del> Let's Break It*

<div class="flex justify-center">
<Youtube id="C6jweXYFHSA"/>
</div>

<p align="center">
<img src="https://i.imgur.com/5dWQeNB.png" alt="A visual summary of Jakob's talk" width="80%"/>
</p>

Jakob Uszkoreit é o cofundador da Inceptive. A Inceptive projeta moléculas de RNA para vacinas e terapias usando aprendizado profundo em larga escala em um circuito fechado com experimentos de alto rendimento com o objetivo de tornar os medicamentos baseados em RNA mais acessíveis, mais eficazes e mais amplamente aplicáveis. Anteriormente, Jakob trabalhou no Google por mais de uma década, liderando equipes de pesquisa e desenvolvimento no Google Brain, Research and Search trabalhando em fundamentos de aprendizado profundo, visão computacional, compreensão de idiomas e tradução automática.

## Dia 2: As ferramentas a serem usadas

**Lewis Tunstall:** *Simple Training with the 🤗 Transformers Trainer*

<div class="flex justify-center">
<Youtube id="u--UVvH-LIQ"/>
</div>

Lewis é machine learning engineer no Hugging Face, focado em desenvolver ferramentas de código aberto e torná-las acessíveis para a comunidade em geral. Ele também é coautor do livro de O'Reilly [Natural Language Processing with Transformers](https://www.oreilly.com/library/view/natural-language-processing/9781098136789/). Você pode segui-lo no Twitter (@_lewtun) para dicas e truques de PNL!

**Matthew Carrigan:** *New TensorFlow Features for 🤗 Transformers and 🤗 Datasets*

<div class="flex justify-center">
<Youtube id="gQUlXp1691w"/>
</div>

Matt é responsável pela manutenção do TensorFlow em Transformers e, eventualmente, liderará um golpe contra a facção PyTorch, que provavelmente será coordenada por meio de sua conta no Twitter @carrigmat.

**Lysandre Debut:** *The Hugging Face Hub as a means to collaborate on and share Machine Learning projects*

<div class="flex justify-center">
<Youtube id="RBw1TmdEZp0"/>
</div>

<p align="center">
<img src="https://i.imgur.com/TarIPCz.png" alt="A visual summary of Lysandre's talk" width="80%"/>
</p>

Lysandre é machine learning engineer no Hugging Face, onde está envolvido em muitos projetos de código aberto. Seu objetivo é tornar o Machine Learning acessível a todos, desenvolvendo ferramentas poderosas com uma API muito simples.

**Lucile Saulnier:** *Get your own tokenizer with 🤗 Transformers & 🤗 Tokenizers*

<div class="flex justify-center">
<Youtube id="UkNmyTFKriI"/>
</div>

Lucile é engenheira de aprendizado de máquina na Hugging Face, desenvolvendo e dando suporte ao uso de ferramentas de código aberto. Ela também está ativamente envolvida em muitos projetos de pesquisa na área de Processamento de Linguagem Natural, como treinamento colaborativo e BigScience.

**Sylvain Gugger:** *Supercharge your PyTorch training loop with 🤗 Accelerate*

<div class="flex justify-center">
<Youtube id="t8Krzu-nSeY"/>
</div>

Sylvain é um Research Engineer no Hugging Face e um dos principais mantenedores do 🤗 Transformers e o desenvolvedor por trás do 🤗 Accelerate. Ele gosta de tornar o treinamento de modelo mais acessível.

**Merve Noyan:** *Showcase your model demos with 🤗 Spaces*

<div class="flex justify-center">
<Youtube id="vbaKOa4UXoM"/>
</div>

Merve é um desenvolvedor defensor da Hugging Face, trabalhando no desenvolvimento de ferramentas e na criação de conteúdo em torno delas para democratizar o aprendizado de máquina para todos.

**Abubakar Abid:** *Building Machine Learning Applications Fast*

<div class="flex justify-center">
<Youtube id="c7mle2yYpwQ"/>
</div>

<p align="center">
<img src="https://i.imgur.com/qWIFeiF.png" alt="A visual summary of Abubakar's talk" width="80%"/>
</p>

Abubakar Abid é o CEO da [Gradio](www.gradio.app). Ele recebeu seu bacharelado em Engenharia Elétrica e Ciência da Computação do MIT em 2015 e seu PhD em Aprendizado de Máquina Aplicado de Stanford em 2021. Em seu papel como CEO da Gradio, Abubakar trabalha para tornar os modelos de aprendizado de máquina mais fáceis de demonstrar, debugar, e implantar.

**Mathieu Desvé:** *AWS ML Vision: Making Machine Learning Accessible to all Customers*

<div class="flex justify-center">
<Youtube id="O2e3pXO4aRE"/>
</div>

<p align="center">
<img src="https://i.imgur.com/oLdZTKy.png" alt="A visual summary of Mathieu's talk" width="80%"/>
</p>

Entusiasta da tecnologia, maker nas horas vagas. Gosto de desafios e resolução de problemas de clientes e usuários, e trabalho com pessoas talentosas para aprender todos os dias. Desde 2004, atuo em várias posições alternando entre frontend, backend, infraestrutura, operações e gerenciamentos. Tente resolver problemas técnicos e gerenciais comuns de maneira ágil.

**Philipp Schmid:** *Managed Training with Amazon SageMaker and 🤗 Transformers*

<div class="flex justify-center">
<Youtube id="yG6J2Zfo8iw"/>
</div>

Philipp Schmid é Machine Learning Engineer and Tech Lead no Hugging Face, onde lidera a colaboração com a equipe do Amazon SageMaker. Ele é apaixonado por democratizar e produzir modelos de PNL de ponta e melhorar a facilidade de uso do Deep Learning.


<EditOnGithub source="https://github.com/huggingface/course/blob/main/chapters/pt/events/2.mdx" />

### Introdução
https://huggingface.co/learn/course/pt/chapter6/1.md

# Introdução

<CourseFloatingBanner
    chapter={6}
    classNames="absolute z-10 right-0 top-0"
/>

No [Capítulo 3](/course/chapter3), nós estudamos como realizar o ajuste fino em um modelo para uma dada tarefa. Quando nós fazemos isso, usamos o mesmo tokenizador utilizado pelo modelo pré-treinado -- mas o que podemos fazer quando queremos treinar um modelo do início? Nestes casos, utilizar um tokenizador que foi pré-treinado em um corpus de outro domínio ou linguagem é tipicamente subótimo. Por exemplo, um tokenizador que é treinado em um corpus de lingua inglesa terá um desempenho ruim em um corpus de textos em japonês, visto que o uso de espaços e pontuações é muito diferente nestes dois idiomas.

Neste capítulo, você aprenderá como treinar um novo tokenizador em um corpus de textos, para então ser usado no treinamento de um modelo de linguagem. Isto tudo será feito com ajuda da biblioteca [🤗 Tokenizers](https://github.com/huggingface/tokenizers), que provê o tokenizador rápido na biblioteca [🤗 Transformers](https://github.com/huggingface/transformers). Daremos uma olhada a fundo sobre as funcionalidades oferecidas pela biblioteca, e explorar como os tokenizadores rápidos diferem das versões "lentas".

Os tópicos que iremos cobrir incluem:

* Como treinar um novo tokenizador semelhante ao usado por um determinado checkpoint em um novo corpus de textos
* Os recursos especiais dos tokenizadores rápidos
* As diferenças entre os três principais algoritmos de tokenização de subpalavras usados ​​no processamento de linguagem natural hoje
* Como construir um tokenizador do zero com a biblioteca 🤗 Tokenizers e treiná-lo em alguns dados

As técnicas introduzidas neste capítulo irão te preparar para a seção no [Capítulo 7](/course/chapter7/6) onde iremos analisar a criação de um modelo de linguagem para a linguagem Python. Primeiramente, vamos começar analisando o que significa "treinar" um tokenizador.


<EditOnGithub source="https://github.com/huggingface/course/blob/main/chapters/pt/chapter6/1.mdx" />

### Os poderes especiais dos tokenizadores rápidos
https://huggingface.co/learn/course/pt/chapter6/3.md

# Os poderes especiais dos tokenizadores rápidos

{#if fw === 'pt'}

<CourseFloatingBanner chapter={6}
  classNames="absolute z-10 right-0 top-0"
  notebooks={[
    {label: "Google Colab", value: "https://colab.research.google.com/github/huggingface/notebooks/blob/master/course/pt/chapter6/section3_pt.ipynb"},
    {label: "Aws Studio", value: "https://studiolab.sagemaker.aws/import/github/huggingface/notebooks/blob/master/course/pt/chapter6/section3_pt.ipynb"},
]} />

{:else}

<CourseFloatingBanner chapter={6}
  classNames="absolute z-10 right-0 top-0"
  notebooks={[
    {label: "Google Colab", value: "https://colab.research.google.com/github/huggingface/notebooks/blob/master/course/pt/chapter6/section3_tf.ipynb"},
    {label: "Aws Studio", value: "https://studiolab.sagemaker.aws/import/github/huggingface/notebooks/blob/master/course/pt/chapter6/section3_tf.ipynb"},
]} />

{/if}

Nesta seção, examinaremos mais de perto os recursos dos tokenizadores em 🤗 Transformers. Até agora, só os usamos para tokenizar entradas ou decodificar IDs de volta em texto, mas tokenizadores - especialmente aqueles apoiados pela biblioteca 🤗 Tokenizers - podem fazer muito mais. Para ilustrar esses recursos adicionais, exploraremos como reproduzir os resultados dos pipelines `token-classification` (que chamamos de `ner`) e `question-answering` que encontramos pela primeira vez no [Capítulo 1](/course/chapter1).
<Youtube id="g8quOxoqhHQ"/>

Na discussão a seguir, muitas vezes faremos a distinção entre tokenizadores "lentos" e "rápidos". Tokenizadores lentos são aqueles escritos em Python dentro da biblioteca 🤗 Transformers, enquanto as versões rápidas são aquelas fornecidas por 🤗 Tokenizers, que são escritos em Rust. Se você se lembrar da tabela do [Capítulo 5](/course/chapter5/3) que informava quanto tempo levou um tokenizador rápido e um lento para tokenizar o conjunto de dados de revisão de medicamentos, você deve ter uma ideia do motivo pelo qual os chamamos de rápido e lento:

                | Fast tokenizer | Slow tokenizer
:--------------:|:--------------:|:-------------:
`batched=True`  | 10.8s          | 4min41s
`batched=False` | 59.2s          | 5min3s

<Tip warning={true}>

⚠️ Ao tokenizar uma única frase, você nem sempre verá uma diferença de velocidade entre as versões lenta e rápida do mesmo tokenizador. Na verdade, a versão rápida pode ser mais lenta! É somente ao tokenizar muitos textos em paralelo ao mesmo tempo que você poderá ver a diferença com maior nitidez.
</Tip>

## Codificação em lote

<Youtube id="3umI3tm27Vw"/>

A saída de um tokenizador não é um simples dicionário em Python; o que obtemos é, na verdade, um objeto especial chamado `BatchEncoding`. Este objeto é uma subclasse de um dicionário (e é por isso que conseguimos indexar esse resultado sem nenhum problema antes), mas com métodos adicionais que são usados ​​principalmente por tokenizadores rápidos.

Além de seus recursos de paralelização, uma funcionalidade importante dos tokenizadores rápidos é que eles sempre acompanham o intervalo original de textos dos quais os tokens finais vêm - um recurso que chamamos de *mapeamento de offset*. Isso, por sua vez, desbloqueia recursos como o mapeamento de cada palavra para os tokens gerados ou mapeamento de cada caractere do texto original para o token que está dentro e vice-versa.

Vamos analisar um exemplo:

```py
from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("bert-base-cased")
example = "My name is Sylvain and I work at Hugging Face in Brooklyn."
encoding = tokenizer(example)
print(type(encoding))
```

Como mencionado anteriormente, nós obtemos um objeto `BatchEncoding` na saída do tokenizador:

```python out
<class 'transformers.tokenization_utils_base.BatchEncoding'>
```

Como a classe `AutoTokenizer` escolhe o tokenizador rápido como padrão, podemos usar os métodos adicionais que o objeto `BatchEncoding` fornece. Temos duas formas de verificar se o nosso tokenizador é rápido ou lento. Podemos, por exemplo, avaliar o atributo `is_fast` do tokenizador:

```python
tokenizer.is_fast
```

```python out
True
```

ou checar o mesmo atributo do nosso `encoding`:

```python
encoding.is_fast
```

```python out
True
```

Vejamos o que um tokenizador rápido nos permite fazer. Primeiro, podemos acessar os tokens sem precisar converter os IDs de volta em tokens:

```py
encoding.tokens()
```

```python out
['[CLS]', 'My', 'name', 'is', 'S', '##yl', '##va', '##in', 'and', 'I', 'work', 'at', 'Hu', '##gging', 'Face', 'in',
 'Brooklyn', '.', '[SEP]']
```

No caso, o token no índice 5 é `##yl`, que faz parte da palavra "Sylvain" na sentença original. Nós podemos também usar o metodo `words_ids()` para obter o índice da palavra de onde cada palavra vem:

```py
encoding.word_ids()
```

```python out
[None, 0, 1, 2, 3, 3, 3, 3, 4, 5, 6, 7, 8, 8, 9, 10, 11, 12, None]
```

Podemos observar que as palavras especiais do tokenizador `[CLS]` e `[SEP]` são mapeados para `None`, e então cada token é mapeada para a palavra de onde se origina. Isso é especialmente útil para determinar se um token está no início da palavra ou se dois tokens estão em uma mesma palavra. Poderíamos contar com o prefix `##` para isso, mas apenas para tokenizadores do tipo BERT; este método funciona para qualquer tipo de tokenizador, desde que seja do tipo rápido. No próximo capítulo, nós veremos como podemos usar esse recurso para aplicar os rótulos que temos para cada palavra adequadamente aos tokens em tarefas como reconhecimento de entidade nomeada (em inglês, Named Entity Recognition, ou NER) e marcação de parte da fala (em inglês, part-of-speech, ou POS). Também podemos usá-lo para mascarar todos os tokens provenientes da mesma palavra na modelagem de linguagem mascarada (uma técnica chamada _mascaramento da palavra inteira_)

<Tip>

A noção do que é uma palavra é complicada. Por exemplo, "d'água" (uma contração de "da água") conta como uma ou duas palavras? Na verdade, depende do tokenizador e da operação de pré-tokenização que é aplicada. Alguns tokenizadores apenas dividem em espaços, então eles considerarão isso como uma palavra. Outros usam pontuação em cima dos espaços, então considerarão duas palavras.

✏️ **Experimente!** Crie um tokenizador a partir dos checkpoints de `bert-base-cased `e `roberta-base` e tokenize "81s" com eles. O que você observa? Quais são os IDs das palavras?

</Tip>

Da mesma forma, existe um método `sentence_ids()` que podemos usar para mapear um token para a sentença de onde veio (embora, neste caso, o `token_type_ids` retornado pelo tokenizador possa nos dar a mesma informação).

Por fim, podemos mapear qualquer palavra ou token para caracteres no texto original (e vice-versa) através dos métodos `word_to_chars()` ou `token_to_chars()` e `char_to_word()` ou `char_to_token()`. Por exemplo, o método `word_ids()` nos diz que `##yl` é parte da palavra no índice 3, mas qual palavra está na frase? Podemos descobrir da seguinte forma:

```py
start, end = encoding.word_to_chars(3)
example[start:end]
```

```python out
Sylvain
```

Como mencionamos anteriormente, isso é apoiado pelo fato de que o tokenizador rápido acompanha o intervalo de texto de cada token em uma lista de *offsets*. Para ilustrar seu uso, mostraremos a seguir como replicar manualmente os resultados do pipeline `token-classification`. 

<Tip>

✏️ **Experimente!** Crie seu próprio texto de exemplo e veja se você consegue entender quais tokens estão associados ao ID da palavra e também como extrair os intervalos de caracteres para uma única palavra. Como bônus, tente usar duas frases como entrada e veja se os IDs das frases fazem sentido para você.

</Tip>

## Dentro do pipeline `token-classification`

No [Capítulo 1](/course/chapter1) tivemos o primeiro gosto de aplicar o NER -- onde a tarefa é identificar quais partes do texto correspondem a entidades como pessoas, locais ou organizações -- com a função do 🤗 Transformers `pipeline()`. Então, no [Capítulo 2](/course/chapter2), vimos como um pipeline agrupa os três estágios necessários para obter as previsões de um texto: tokenização, passagem das entradas pelo modelo e pós-processamento. As duas primeiras etapas do pipeline `token-classification` são as mesmas de qualquer outro pipeline, mas o pós-processamento é um pouco mais complexo -- vejamos como! 


{#if fw === 'pt'}

<Youtube id="0E7ltQB7fM8"/>

{:else}

<Youtube id="PrX4CjrVnNc"/>

{/if}

### Obtendo os resultados básicos com o pipeline 

Primeiro, vamos usar um pipeline de classificação de token para que possamos obter alguns resultados para comparar manualmente. O modelo usado por padrão é [`dbmdz/bert-large-cased-finetuned-conll03-english`](https://huggingface.co/dbmdz/bert-large-cased-finetuned-conll03-english); ele executa NER em frases:

```py
from transformers import pipeline

token_classifier = pipeline("token-classification")
token_classifier("My name is Sylvain and I work at Hugging Face in Brooklyn.")
```

```python out
[{'entity': 'I-PER', 'score': 0.9993828, 'index': 4, 'word': 'S', 'start': 11, 'end': 12},
 {'entity': 'I-PER', 'score': 0.99815476, 'index': 5, 'word': '##yl', 'start': 12, 'end': 14},
 {'entity': 'I-PER', 'score': 0.99590725, 'index': 6, 'word': '##va', 'start': 14, 'end': 16},
 {'entity': 'I-PER', 'score': 0.9992327, 'index': 7, 'word': '##in', 'start': 16, 'end': 18},
 {'entity': 'I-ORG', 'score': 0.97389334, 'index': 12, 'word': 'Hu', 'start': 33, 'end': 35},
 {'entity': 'I-ORG', 'score': 0.976115, 'index': 13, 'word': '##gging', 'start': 35, 'end': 40},
 {'entity': 'I-ORG', 'score': 0.98879766, 'index': 14, 'word': 'Face', 'start': 41, 'end': 45},
 {'entity': 'I-LOC', 'score': 0.99321055, 'index': 16, 'word': 'Brooklyn', 'start': 49, 'end': 57}]
```

O modelo identificou corretamente cada token gerado por "Sylvain" como uma pessoa, cada token gerado por "Hugging Face" como uma organização e o token "Brooklyn" como um local. Também podemos pedir ao pipeline para agrupar os tokens que correspondem à mesma entidade:

```py
from transformers import pipeline

token_classifier = pipeline("token-classification", aggregation_strategy="simple")
token_classifier("My name is Sylvain and I work at Hugging Face in Brooklyn.")
```

```python out
[{'entity_group': 'PER', 'score': 0.9981694, 'word': 'Sylvain', 'start': 11, 'end': 18},
 {'entity_group': 'ORG', 'score': 0.97960204, 'word': 'Hugging Face', 'start': 33, 'end': 45},
 {'entity_group': 'LOC', 'score': 0.99321055, 'word': 'Brooklyn', 'start': 49, 'end': 57}]
```

O parâmetro `aggregation_strategy` escolhido mudará as pontuações calculadas para cada entidade agrupada. Com o valor `"simple"`, a pontuação é apenas a média das pontuações de cada token na entidade dada: por exemplo, a pontuação de "Sylvain" é a média das pontuações que vimos no exemplo anterior para os tokens `S`, `##yl`, `##va`, e `##in`. Outras estratégias disponíveis são: 

- `"first"`, onde a pontuação de cada entidade é a pontuação do primeiro token dessa entidade (portanto, para "Sylvain" seria 0.993828, a pontuação do token `S`)
- `"max"`, onde a pontuação de cada entidade é a pontuação máxima dos tokens naquela entidade (portanto, para "Hugging Face" seria 0.98879766, a pontuação do token `"Face"`)
- `"average"`, onde a pontuação de cada entidade é a média das pontuações das palavras que compõem aquela entidade (assim para "Sylvain" não haveria diferença da estratégia `"simple"`, mas `"Hugging Face"` teria uma pontuação de 0.9819, a média das pontuações para `"Hugging"`, 0.975, e `"Face"`, 0.98879)

Agora vejamos como obter esses resultados sem usar a função `pipeline()`!

### Das entradas às previsões

{#if fw === 'pt'}

Primeiro, precisamos tokenizar nossa entrada e passá-la pelo modelo. Isso é feito exatamente como no [Capítulo 2](/course/chapter3); instanciamos o tokenizador e o modelo usando as classes `AutoXxx` e depois as usamos em nosso exemplo:

```py
from transformers import AutoTokenizer, AutoModelForTokenClassification

model_checkpoint = "dbmdz/bert-large-cased-finetuned-conll03-english"
tokenizer = AutoTokenizer.from_pretrained(model_checkpoint)
model = AutoModelForTokenClassification.from_pretrained(model_checkpoint)

example = "My name is Sylvain and I work at Hugging Face in Brooklyn."
inputs = tokenizer(example, return_tensors="pt")
outputs = model(**inputs)
```

Como estamos usando `AutoModelForTokenClassification` neste caso, obtemos um conjunto de logits para cada token na sequência de entrada:

```py
print(inputs["input_ids"].shape)
print(outputs.logits.shape)
```

```python out
torch.Size([1, 19])
torch.Size([1, 19, 9])
```

{:else}

Primeiro, precisamos tokenizar nossa entrada e passá-la pelo modelo. Isso é feito exatamente como no [Capítulo 2](/course/chapter2); instanciamos o tokenizador e o modelo usando as classes `TFAutoXxx` e depois as usamos em nosso exemplo:

```py
from transformers import AutoTokenizer, TFAutoModelForTokenClassification

model_checkpoint = "dbmdz/bert-large-cased-finetuned-conll03-english"
tokenizer = AutoTokenizer.from_pretrained(model_checkpoint)
model = TFAutoModelForTokenClassification.from_pretrained(model_checkpoint)

example = "My name is Sylvain and I work at Hugging Face in Brooklyn."
inputs = tokenizer(example, return_tensors="tf")
outputs = model(**inputs)
```

Como estamos usando `TFAutoModelForTokenClassification` neste caso, obtemos um conjunto de logits para cada token na sequência de entrada:

```py
print(inputs["input_ids"].shape)
print(outputs.logits.shape)
```

```python out
(1, 19)
(1, 19, 9)
```

{/if}

Temos um lote com 1 sequência de 19 tokens e o modelo tem 9 rótulos diferentes, então a saída do modelo tem um tamanho de 1 x 19 x 9. Assim como para o pipeline de classificação de texto, usamos uma função softmax para converter esses logits para probabilidades, e pegamos o argmax para obter previsões (note que podemos pegar o argmax nos logits porque o softmax não altera a ordem): 

{#if fw === 'pt'}

```py
import torch

probabilities = torch.nn.functional.softmax(outputs.logits, dim=-1)[0].tolist()
predictions = outputs.logits.argmax(dim=-1)[0].tolist()
print(predictions)
```

{:else}

```py
import tensorflow as tf

probabilities = tf.math.softmax(outputs.logits, axis=-1)[0]
probabilities = probabilities.numpy().tolist()
predictions = tf.math.argmax(outputs.logits, axis=-1)[0]
predictions = predictions.numpy().tolist()
print(predictions)
```

{/if}

```python out
[0, 0, 0, 0, 4, 4, 4, 4, 0, 0, 0, 0, 6, 6, 6, 0, 8, 0, 0]
```

O atributo `model.config.id2label` contém o mapeamento de índices para rótulos que podemos usar para entender as previsões:

```py
model.config.id2label
```

```python out
{0: 'O',
 1: 'B-MISC',
 2: 'I-MISC',
 3: 'B-PER',
 4: 'I-PER',
 5: 'B-ORG',
 6: 'I-ORG',
 7: 'B-LOC',
 8: 'I-LOC'}
```

Como vimos anteriormente, existem 9 rótulos: `O` é o rótulo para os tokens que não estão em nenhuma entidade nomeada, e então temos dois rótulos para cada tipo de entidade (miscelânia, pessoa, organização e localização). O rótulo `B-XXX` indica que o token está no início de uma entidade `XXX` e o rótulo `I-XXX` indica que o token está dentro da entidade `XXX`. No caso do exemplo atual, esperaríamos que o nosso modelo classificasse o token `S` como `B-PER` (início de uma entidade pessoa) e os tokens `##yl`, `##va` e `##in` como `I-PER` (dentro da entidade pessoa).

Você pode pensar que o modelo estava errado neste caso, pois deu o rótulo `I-PER` a todos esses quatro tokens, mas isso não é totalmente verdade. Na realidade, existem dois formatos para esses rótulos: `B-` e `I-`: *IOB1* e *IOB2*. O formato IOB2 (em rosa abaixo), é o que introduzimos, enquanto que no formato IOB1 (em azul), os rótulos que começam com `B-` são usados apenas para separar duas entidades adjacentes do mesmo tipo. O modelo que estamos usando foi ajustado em um conjunto de dados usando esse formato, e é por isso que ele atribui o rótulo `I-PER` ao token `S`. 

<div class="flex justify-center">
<img class="block dark:hidden" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter6/IOB_versions.svg" alt="IOB1 vs IOB2 format"/>
<img class="hidden dark:block" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter6/IOB_versions-dark.svg" alt="IOB1 vs IOB2 format"/>
</div>

Com este mapa, estamos prontos para reproduzir (quase inteiramente) os resultados do primeiro pipeline -- podemos apenas pegar a pontuação e o rótulo de cada token que não foi classificado como `O`:

```py
results = []
tokens = inputs.tokens()

for idx, pred in enumerate(predictions):
    label = model.config.id2label[pred]
    if label != "O":
        results.append(
            {"entity": label, "score": probabilities[idx][pred], "word": tokens[idx]}
        )

print(results)
```

```python out
[{'entity': 'I-PER', 'score': 0.9993828, 'index': 4, 'word': 'S'},
 {'entity': 'I-PER', 'score': 0.99815476, 'index': 5, 'word': '##yl'},
 {'entity': 'I-PER', 'score': 0.99590725, 'index': 6, 'word': '##va'},
 {'entity': 'I-PER', 'score': 0.9992327, 'index': 7, 'word': '##in'},
 {'entity': 'I-ORG', 'score': 0.97389334, 'index': 12, 'word': 'Hu'},
 {'entity': 'I-ORG', 'score': 0.976115, 'index': 13, 'word': '##gging'},
 {'entity': 'I-ORG', 'score': 0.98879766, 'index': 14, 'word': 'Face'},
 {'entity': 'I-LOC', 'score': 0.99321055, 'index': 16, 'word': 'Brooklyn'}]
```

Isso é muito parecido com o que tínhamos antes, com uma exceção: o pipeline também nos dava informações sobre o `start` e `end` de cada entidade na frase original. É aqui que nosso mapeamento de offset entrará em ação. Para obter tais offsets, basta definir `return_offsets_mapping=True` quando aplicamos o tokenizador às nossas entradas:

```py
inputs_with_offsets = tokenizer(example, return_offsets_mapping=True)
inputs_with_offsets["offset_mapping"]
```

```python out
[(0, 0), (0, 2), (3, 7), (8, 10), (11, 12), (12, 14), (14, 16), (16, 18), (19, 22), (23, 24), (25, 29), (30, 32),
 (33, 35), (35, 40), (41, 45), (46, 48), (49, 57), (57, 58), (0, 0)]
```

Cada tupla é o intervalo de texto correspondente a cada token, onde `(0, 0)` é reservado para os tokens especiais. Vimos antes que o token no índice 5 é `##yl`, que tem `(12, 14)` como offset aqui. Se pegarmos a fatia correspondente em nosso exemplo:

```py
example[12:14]
```

obtemos o intervalo adequado de texto sem o `##`:

```python out
yl
```

Usando isso, agora podemos completar os resultados anteriores:

```py
results = []
inputs_with_offsets = tokenizer(example, return_offsets_mapping=True)
tokens = inputs_with_offsets.tokens()
offsets = inputs_with_offsets["offset_mapping"]

for idx, pred in enumerate(predictions):
    label = model.config.id2label[pred]
    if label != "O":
        start, end = offsets[idx]
        results.append(
            {
                "entity": label,
                "score": probabilities[idx][pred],
                "word": tokens[idx],
                "start": start,
                "end": end,
            }
        )

print(results)
```

```python out
[{'entity': 'I-PER', 'score': 0.9993828, 'index': 4, 'word': 'S', 'start': 11, 'end': 12},
 {'entity': 'I-PER', 'score': 0.99815476, 'index': 5, 'word': '##yl', 'start': 12, 'end': 14},
 {'entity': 'I-PER', 'score': 0.99590725, 'index': 6, 'word': '##va', 'start': 14, 'end': 16},
 {'entity': 'I-PER', 'score': 0.9992327, 'index': 7, 'word': '##in', 'start': 16, 'end': 18},
 {'entity': 'I-ORG', 'score': 0.97389334, 'index': 12, 'word': 'Hu', 'start': 33, 'end': 35},
 {'entity': 'I-ORG', 'score': 0.976115, 'index': 13, 'word': '##gging', 'start': 35, 'end': 40},
 {'entity': 'I-ORG', 'score': 0.98879766, 'index': 14, 'word': 'Face', 'start': 41, 'end': 45},
 {'entity': 'I-LOC', 'score': 0.99321055, 'index': 16, 'word': 'Brooklyn', 'start': 49, 'end': 57}]
```

Este é o mesmo resultado que obtivemos no primeiro pipeline!

### Agrupando entidades 

Usar os offsets para determinar as chaves inicial e final de cada entidade é útil, mas essa informação não é estritamente necessária. Quando queremos agrupar as entidades, no entanto, os offsets nos pouparão muito código confuso. Por exemplo, se quisermos agrupar os tokens `Hu`, `##gging` e `Face`, podemos fazer regras especiais que digam que os dois primeiros devem ser anexados e removido o `##`, e o `Face` deve ser adicionado com um espaço, pois não começa com `##` -- mas isso só funcionaria para esse tipo específico de tokenizador. Teríamos que escrever outro conjunto de regras para um tokenizador SentencePiece ou Byte-Pair-Encoding (discutido mais adiante neste capítulo).

Com os offsets, todo esse código personalizado desaparece: podemos apenas pegar o intervalo no texto original que começa com o primeiro token e termina com o último token. Então, no caso dos tokens `Hu`, `##ging` e `Face`, devemos começar no caractere 33 (o início de `Hu`) e terminar antes do caractere 45 (o final de `Face`):

```py
example[33:45]
```

```python out
Hugging Face
```

Para escrever o código para o pós-processamento das previsões ao agrupar entidades, agruparemos entidades consecutivas e rotuladas com `I-XXX`, excento a primeira, que pode ser rotulada como `B-XXX` ou `I-XXX` (portanto, paramos de agrupar uma entidade quando obtemos um `O`, um novo tipo de entidade ou um `B-XXX` que nos informa que uma entidade do mesmo tipo está iniciando):

```py
import numpy as np

results = []
inputs_with_offsets = tokenizer(example, return_offsets_mapping=True)
tokens = inputs_with_offsets.tokens()
offsets = inputs_with_offsets["offset_mapping"]

idx = 0
while idx < len(predictions):
    pred = predictions[idx]
    label = model.config.id2label[pred]
    if label != "O":
        # Removendo o B- ou I-
        label = label[2:]
        start, _ = offsets[idx]

        # Vamos pegar todos os tokens rotulados com I-
        all_scores = []
        while (
            idx < len(predictions)
            and model.config.id2label[predictions[idx]] == f"I-{label}"
        ):
            all_scores.append(probabilities[idx][pred])
            _, end = offsets[idx]
            idx += 1

        # A pontuação é a média de todas as pontuações dos tokens da entidade agrupada
        score = np.mean(all_scores).item()
        word = example[start:end]
        results.append(
            {
                "entity_group": label,
                "score": score,
                "word": word,
                "start": start,
                "end": end,
            }
        )
    idx += 1

print(results)
```

E obtemos os mesmos resultados do nosso segundo pipeline!

```python out
[{'entity_group': 'PER', 'score': 0.9981694, 'word': 'Sylvain', 'start': 11, 'end': 18},
 {'entity_group': 'ORG', 'score': 0.97960204, 'word': 'Hugging Face', 'start': 33, 'end': 45},
 {'entity_group': 'LOC', 'score': 0.99321055, 'word': 'Brooklyn', 'start': 49, 'end': 57}]
```

Outro exemplo de uma tarefa onde esses offsets são extremamente úteis é a resposta a perguntas. O conhecimento deste pipeline, que faremos na próxima seção, também nos permitirá dar uma olhada em um último recurso dos tokenizadores na biblioteca 🤗 Transformers: lidar com tokens em excesso quando truncamos uma entrada em um determinado comprimento.


<EditOnGithub source="https://github.com/huggingface/course/blob/main/chapters/pt/chapter6/3.mdx" />

### Treinando um novo tokenizador
https://huggingface.co/learn/course/pt/chapter6/2.md

# Treinando um novo tokenizador

<CourseFloatingBanner chapter={6}
  classNames="absolute z-10 right-0 top-0"
  notebooks={[
    {label: "Google Colab", value: "https://colab.research.google.com/github/huggingface/notebooks/blob/master/course/pt/chapter6/section2.ipynb"},
    {label: "Aws Studio", value: "https://studiolab.sagemaker.aws/import/github/huggingface/notebooks/blob/master/course/pt/chapter6/section2.ipynb"},
]} />

Se um modelo de linguagem não estiver disponível no idioma que você estiver interessado, ou se o seu corpus for muito diferente do que o seu modelo de linguagem foi treinado, você muito provavelmente desejará retreinar o modelo do zero usando um tokenizador adaptado para seus dados. Isto exigirá um treinamento de um novo tokenizador para seu conjunto de dados. Mas o que isso exatamente significa? Quando observamos os tokenizadores pela primeira vez no [Capítulo 2](/course/chapter2), nós vimos que a maioria dos modelos Transformer usa um algoritmo de tokenização de subpalavras. Para identificar quais subpalavras são de interesse e que ocorrem mais frequentemente no corpus em questão, o tokenizador precisa dar uma boa olhada em todos os textos no corpus -- processo que chamamos de *treinamento*. As regras exatas que governam o treinamento dependem do tipo de tokenizador usado, e veremos os três algoritmos principais mais adiante neste capítulo.

<Youtube id="DJimQynXZsQ"/>

<Tip warning={true}>

⚠️ Treinar um tokenizador não é o mesmo que treinar um modelo! O treinamento de um modelo usa o gradiente descendente estocástico para fazer a perda um pouquinho menor a cada batch. Portanto, é aleatório por natureza (o que significa que você deve definir seeds para obter o mesmo resultado quando estiver fazendo o mesmo treino novamente). Treinar um tokenizador é um processo estatístico que tenta identificar que subpalavras são as melhores para escolher dependendo do algoritmo de tokenização. Portanto, este processo é determinístico, o que significa que você terá sempre o mesmo resultado quando for treinar com o mesmo algoritmo no mesmo corpus.

</Tip>

## Montando um corpus

Existe uma API muito simples em 🤗 Transformers que você pode usar para treinar um novo tokenizador com as mesmas características de um já existente: `AutoTokenizer.train_new_from_iterator()`. Para ver isso em ação, vamos supor que queremos treinar o GPT-2 do zero, mas em um idioma diferente do inglês. Nossa primeira tarefa será obter muitos dados de um idioma em um corpus de treinamento. Para prover exemplos que todo mundo será capaz de entender, não usaremos um idioma como russo ou chinês aqui, mas sim in idiome inglês especializado: código Python.

A biblioteca [🤗 Datasets](https://github.com/huggingface/datasets) pode nos ajudar a montar um corpus de códigos em Python. Nós usaremos a função usual `load_dataset()` para baixar e armazenar em cache o dataset [CodeSearchNet](https://huggingface.co/datasets/code_search_net). Este dataset foi criado para o [CodeSearchNet challenge](https://wandb.ai/github/CodeSearchNet/benchmark) e contém milhões de funções de bibliotecas de código aberto no GitHub em diferentes linguagens de programação. Aqui, nós iremos carregar a parte Python deste dataset:

```py
from datasets import load_dataset

# Isto pode levar alguns minutos para carregar, então pegue um copo de café enquanto espera!
raw_datasets = load_dataset("code_search_net", "python")
```

Podemos dar uma olhada na divisão de treinamento para ver a quais colunas temos acesso:

```py
raw_datasets["train"]
```

```python out
Dataset({
    features: ['repository_name', 'func_path_in_repository', 'func_name', 'whole_func_string', 'language', 
      'func_code_string', 'func_code_tokens', 'func_documentation_string', 'func_documentation_tokens', 'split_name', 
      'func_code_url'
    ],
    num_rows: 412178
})
```
Podemos ver que o conjunto de dados separa as docstrings do código e sugere uma tokenização de ambos. Aqui, usaremos apenas a coluna `whole_func_string` para treinar o nosso tokenizador. Podemos observar um exemplo de uma dessas funções indexando na divisão `train`:

```py
print(raw_datasets["train"][123456]["whole_func_string"])
```

Que deve resultar na seguinte saída:

```out
def handle_simple_responses(
      self, timeout_ms=None, info_cb=DEFAULT_MESSAGE_CALLBACK):
    """Accepts normal responses from the device.

    Args:
      timeout_ms: Timeout in milliseconds to wait for each response.
      info_cb: Optional callback for text sent from the bootloader.

    Returns:
      OKAY packet's message.
    """
    return self._accept_responses('OKAY', info_cb, timeout_ms=timeout_ms)
```

A primeira coisa que precisamos fazer é transformar o dataset em um iterador) de listas de textos -- por exemplo, uma lista de lista de textos. Usando lista de textos irá habilitar o nosso tokenizador para funcionar mais rapidamente (treinando em lotes de textos ao invés de processar individualmente os textos, um por vez), e deve ser um iterador se quisermos evitar ter tudo na memória de uma vez. Se o teu corpus for grande, você vai querer aproveitar o fato de que 🤗 Datasets não carrega tudo na memória RAM, mas armazena os elementos do dataset no disco.

Executar o trecho abaixo criaria uma lista de listas de 1000 textos cada, mas carregaria tudo na memória:

```py
# Não remova o comentário da linha abaixo, a menos que o teu dataset seja pequeno!
# training_corpus = [raw_datasets["train"][i: i + 1000]["whole_func_string"] for i in range(0, len(raw_datasets["train"]), 1000)]
```

Usando um Python generator, nós podemos evitar que o Python carregue tudo na memória até que realmente seja necessário. Para criar tal generator, você precisa apenas substituir os colchetes por parênteses:   

```py
training_corpus = (
    raw_datasets["train"][i : i + 1000]["whole_func_string"]
    for i in range(0, len(raw_datasets["train"]), 1000)
)
```

Esta linha de código não busca nenhum elemento no dataset; ele apenas cria um objeto que você pode usar em um o loop `for` do Python. Os textos só serão carregados quando você precisar deles (ou seja, quando você estiver na etapa do loop `for` que os requer), e apenas 1000 textos por vez serão carregados. Desse modo, você não esgotará toda a sua memória, mesmo se você estiver processando um grande dataset.

O problema com um objeto gerador é que ele só pode ser usado uma vez. Então, em vez de nos dar a lista dos primeiros 10 dígitos duas vezes:

```py
gen = (i for i in range(10))
print(list(gen))
print(list(gen))
```

nós obtemos uma vez e, em seguida, uma lista vazia:

```python out
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[]
```

É por isso que definomos uma função que retorna um gerador:

```py
def get_training_corpus():
    return (
        raw_datasets["train"][i : i + 1000]["whole_func_string"]
        for i in range(0, len(raw_datasets["train"]), 1000)
    )


training_corpus = get_training_corpus()
```

Você também pode definir o seu gerador dentro de um loop `for` ao usar o comando `yield`:

```py
def get_training_corpus():
    dataset = raw_datasets["train"]
    for start_idx in range(0, len(dataset), 1000):
        samples = dataset[start_idx : start_idx + 1000]
        yield samples["whole_func_string"]
```

que irá produzir exatamente o mesmo gerador de antes, mas permite que você use uma lógica mais complexa do que você pode em um list comprehension.

## Treinando um novo tokenizador

Agora que nós temos o nosso corpus na forma de um iterador de lotes de texto, estamos prontos para treinar um novo tokenizador. Para fazer isso, primeiramente nós precisamos carregar o tokenizador que queremos emparelhar com o nosso modelo (neste caso, GPT-2):

```py
from transformers import AutoTokenizer

old_tokenizer = AutoTokenizer.from_pretrained("gpt2")
```
Por mais que iremos treinar um novo tokenizador, é uma boa ideia fazer isso para evitar começar do zero. Dessa forma, não precisaremos especificar nada sobre o algoritmo de tokenização ou tokens especiais que queremos usar; nosso novo tokenizador será exatamente igual ao GPT-2, e a única coisa que irá mudar é o vocabulário, que será determinado pelo treinamento em nosso corpus. 

Primeiramente, vamos dar uma olhada em como o tokenizador trataria um exemplo de função:

```py
example = '''def add_numbers(a, b):
    """Add the two numbers `a` and `b`."""
    return a + b'''

tokens = old_tokenizer.tokenize(example)
tokens
```

```python out
['def', 'Ġadd', '_', 'n', 'umbers', '(', 'a', ',', 'Ġb', '):', 'Ċ', 'Ġ', 'Ġ', 'Ġ', 'Ġ"""', 'Add', 'Ġthe', 'Ġtwo',
 'Ġnumbers', 'Ġ`', 'a', '`', 'Ġand', 'Ġ`', 'b', '`', '."', '""', 'Ċ', 'Ġ', 'Ġ', 'Ġ', 'Ġreturn', 'Ġa', 'Ġ+', 'Ġb']
```

O tokenizador possui alguns símbolos especiais, como `Ġ` e `Ċ`, que denotam espaços e novas linhas, respectivamente. Como podemos observar, isso não é tão eficiente: o tokenizador retorna tokens individuais para cada espaço, quando poderia agrupar níveis de indentação (já que ter conjuntos de quatro ou oito espaços será muito comum no código). O tokenizador também dividiu o nome da função de uma forma um pouco estranha, não sendo usado para ver palavras com o caractere `_`.

Vamos treinar um novo tokenizador e ver se isso resolve esses problemas. Para isso, iremos utilizar o método `train_new_from_iterator()`:

```py
tokenizer = old_tokenizer.train_new_from_iterator(training_corpus, 52000)
```

Este comando pode demorar um pouco se o seu corpus for muito grande, mas para este dataset contendo 1.6 GB de textos é extremamente rápido (1 minuto e 16 segundos em uma CPU AMD Ryzen 9 3900X com 12 núcleos). 

Observe que `AutoTokenizer.train_new_from_iterator()` funciona apenas se o tokenizador que você estiver usando é um tokenizador "rápido". Como você verá na próxima seção, a biblioteca 🤗 Transformers contém dois tipos de tokenizers: alguns são escritos puramente em Python e outros (os mais rápidos) são apoiados pela biblioteca 🤗 Tokenizers, que é escrita na linguagem de programação [Rust](https://www.rust-lang.org). Python é a linguagem de programação mais utilizada para Ciência de Dados e aplicações em Deep Learning, mas quando algo precisa ser paralelizado para ser rápido, é preciso ser escrito em uma outra linguagem. Por exemplo, as multiplicações de matrizes que estão na base de modelos de computação são escritos em CUDA, uma biblioteca em C otimizada para GPUs. 

Treinar um tokenizador totalmente novo usando apenas Python seria terrivelmente lento, e é por isso que nós desenvolvemos a biblioteca 🤗 Tokenizers. Observe que, assim como você não precisou aprender a linguagem CUDA para ser capaz de executar seu modelo em um lote de entradas em uma GPU, você não precisará aprender Rust para usar o tokenizador rápido. A biblioteca 🤗 Tokenizers fornece ligaçções para muitos métodos que internamente chamam algum trecho de código em Rust; por exemplo, para paralelizar o treinamento do seu novo tokenizador ou, como vimos no [Chapter 3](/course/chapter3), a tokenização de um lote de entradas.

A maioria dos modelos Transformer possui um tokenizador rápido disponível (existem algumas exceções que você pode checar [aqui](https://huggingface.co/transformers/#supported-frameworks)), e a API `AutoTokenizer` sempre seleciona o tokenizador rápido para você se estiver disponível. Na próxima seção, veremos alguns dos outros recursos especiais que os tokenizers rápidos possuem, que serão realmente úteis para tarefas como classificação de tokens e resposta a perguntas. Antes de aprofundarmos nisso, no entanto, vamos experimentar o nosso novo tokenizador no exemplo anterior:

```py
tokens = tokenizer.tokenize(example)
tokens
```

```python out
['def', 'Ġadd', '_', 'numbers', '(', 'a', ',', 'Ġb', '):', 'ĊĠĠĠ', 'Ġ"""', 'Add', 'Ġthe', 'Ġtwo', 'Ġnumbers', 'Ġ`',
 'a', '`', 'Ġand', 'Ġ`', 'b', '`."""', 'ĊĠĠĠ', 'Ġreturn', 'Ġa', 'Ġ+', 'Ġb']
```

Aqui vemos novamente os símbolos especiais `Ġ` and `Ċ` que denotam espaços e novas linhas, mas também podemos observar que o nosso tokenizador aprendeu alguns tokens que são altamente específicos em um corpus de funções em Python: por exemplo, existe um token `ĊĠĠĠ` que representa uma indentação, e um token `Ġ"""` que representa as três aspas que começam uma docstring. O tokenizador também divide corretamente o nome da função em `_`. Esta é uma representação bastante compacta; comparativamente, usando o tokenizador em inglês no mesmo exemplo nos dará uma frase mais longa:

```py
print(len(tokens))
print(len(old_tokenizer.tokenize(example)))
```

```python out
27
36
```
Vejamos outro exemplo:

```python
example = """class LinearLayer():
    def __init__(self, input_size, output_size):
        self.weight = torch.randn(input_size, output_size)
        self.bias = torch.zeros(output_size)

    def __call__(self, x):
        return x @ self.weights + self.bias
    """
tokenizer.tokenize(example)
```

```python out
['class', 'ĠLinear', 'Layer', '():', 'ĊĠĠĠ', 'Ġdef', 'Ġ__', 'init', '__(', 'self', ',', 'Ġinput', '_', 'size', ',',
 'Ġoutput', '_', 'size', '):', 'ĊĠĠĠĠĠĠĠ', 'Ġself', '.', 'weight', 'Ġ=', 'Ġtorch', '.', 'randn', '(', 'input', '_',
 'size', ',', 'Ġoutput', '_', 'size', ')', 'ĊĠĠĠĠĠĠĠ', 'Ġself', '.', 'bias', 'Ġ=', 'Ġtorch', '.', 'zeros', '(',
 'output', '_', 'size', ')', 'ĊĊĠĠĠ', 'Ġdef', 'Ġ__', 'call', '__(', 'self', ',', 'Ġx', '):', 'ĊĠĠĠĠĠĠĠ',
 'Ġreturn', 'Ġx', 'Ġ@', 'Ġself', '.', 'weights', 'Ġ+', 'Ġself', '.', 'bias', 'ĊĠĠĠĠ']
```

Além do token correpondente a uma indentação, aqui podemos ver um token para uma indentação dupla: `ĊĠĠĠĠĠĠĠ`. Palavras especiais em Python, como `class`, `init`, `call`, `self`, e `return` são tokenizadas como um token, e podemos ver que além de dividir em `_` e `.`, o tokenizador divide corretamente até mesmo nomes em CamelCase: `LinearLayer` é tokenizado como `["ĠLinear", "Layer"]`

## Salvando o tokenizador

Para garantir que podemos usá-lo mais tarde, precisamos salvar nosso novo tokenizador. Assim como é utilizado para modelos, isso é feito com o método `save_pretrained()`:

```py
tokenizer.save_pretrained("code-search-net-tokenizer")
```
Isso irá criar uma nova pasta chamada *code-search-net-tokenizer*, que irá conter todos os arquivos que o tokenizador precisa para ser recarregado. Se você quiser compartilhar este tokenizador com outros colegas e amigos, você pode carregá-lo no Hub fazendo login em sua conta. Se você estiver trabalhando em um notebook, há uma função conveniente para ajudá-lo com isso:

```python
from huggingface_hub import notebook_login

notebook_login()
```
Isso exibirá um widget onde você pode inserir suas credenciais de login do Hugging Face. Se você não estiver trabalhando em um notebook, basta digitar a seguinte linha em seu terminal:

```bash
huggingface-cli login
```

Depois de você logar, você pode enviar seu tokenizador executando o seguinte comando: 

```py
tokenizer.push_to_hub("code-search-net-tokenizer")
```

Isso criará um novo repositório em seu namespace com o nome `code-search-net-tokenizer`, contendo o arquivo do tokenizador. Você pode então carregar o tokenizador de qualquer lugar com o método `from_pretrained()`:

```py
# Substitua "huggingface-course" abaixo pelo seu namespace real para usar seu próprio tokenizador
tokenizer = AutoTokenizer.from_pretrained("huggingface-course/code-search-net-tokenizer")
```

Agora você está pronto para treinar um modelo de linguagem do zero e ajustá-lo para sua tarefa! Chegaremos a isso no [Chapter 7](/course/chapter7), mas primeiro, no resto do capítulo daremos uma olhada sobre tokenizers rápidos e explorar em detalhes o que realmente acontece quando chamamos o método `train_new_from_iterator()`.


<EditOnGithub source="https://github.com/huggingface/course/blob/main/chapters/pt/chapter6/2.mdx" />

### Criando seu próprio dataset
https://huggingface.co/learn/course/pt/chapter5/5.md

# Criando seu próprio dataset

<CourseFloatingBanner chapter={5}
  classNames="absolute z-10 right-0 top-0"
  notebooks={[
    {label: "Google Colab", value: "https://colab.research.google.com/github/huggingface/notebooks/blob/master/course/pt/chapter5/section5.ipynb"},
    {label: "Aws Studio", value: "https://studiolab.sagemaker.aws/import/github/huggingface/notebooks/blob/master/course/pt/chapter5/section5.ipynb"},
]} />

Às vezes, o conjunto de dados de que você precisa para criar um aplicativo de PLN não existe, portanto, você mesmo precisará criá-lo. Nesta seção, mostraremos como criar um corpus de [issues do GitHub](https://github.com/features/issues/), que são comumente usados ​​para rastrear bugs ou recursos nos repositórios do GitHub. Este corpus pode ser usado para vários fins, incluindo:

* Explorar quanto tempo leva para fechar as issues abertos ou pull requests
* Treinar um _classificador multilabel_ que pode marcar issues com metadados com base na descrição da issue (por exemplo, "bug", "melhoria" ou "pergunta")
* Criando um mecanismo de pesquisa semântica para descobrir quais issues correspondem à consulta de um usuário

Aqui nos concentraremos na criação do corpus e, na próxima seção, abordaremos o aplicativo de pesquisa semântica. Para manter a meta, usaremos as issues do GitHub associados a um projeto de código aberto popular: 🤗 Datasets! Vamos dar uma olhada em como obter os dados e explorar as informações contidas nessas edições.

## Obtendo os dados

Você pode encontrar todos as issues em 🤗 Datasets navegando até a [guia de issues](https://github.com/huggingface/datasets/issues) do repositório. Conforme mostrado na captura de tela a seguir, no momento da redação, havia 331 issues abertos e 668 fechados.

<div class="flex justify-center">
<img src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter5/datasets-issues.png" alt="The GitHub issues associated with 🤗 Datasets." width="80%"/>
</div>

Se você clicar em uma dessas issues, verá que ele contém um título, uma descrição e um conjunto de rótulos que caracterizam a issue. Um exemplo é mostrado na captura de tela abaixo.

<div class="flex justify-center">
<img src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter5/datasets-issues-single.png" alt="A typical GitHub issue in the 🤗 Datasets repository." width="80%"/>
</div>

Para baixar todos as issues do repositório, usaremos a [GitHub REST API](https://docs.github.com/en/rest) para pesquisar o [`Issues` endpoint](https://docs.github. com/en/rest/reference/issues#list-repository-issues). Esse endpoint retorna uma lista de objetos JSON, com cada objeto contendo um grande número de campos que incluem o título e a descrição, bem como metadados sobre o status da issue e assim por diante.

Uma maneira conveniente de baixar as issues é por meio da biblioteca `requests`, que é a maneira padrão de fazer solicitações HTTP em Python. Você pode instalar a biblioteca executando:

```python
!pip install requests
```

Uma vez que a biblioteca esteja instalada, você pode fazer solicitações GET para o endpoint `Issues` invocando a função `requests.get()`. Por exemplo, você pode executar o seguinte comando para recuperar a primeira issue na primeira página:

```py
import requests

url = "https://api.github.com/repos/huggingface/datasets/issues?page=1&per_page=1"
response = requests.get(url)
```

O objeto `response` contém muitas informações úteis sobre a solicitação, incluindo o código de status HTTP:

```py
response.status_code
```

```python out
200
```

onde um status `200` significa que a solicitação foi bem-sucedida (você pode encontrar uma lista de possíveis códigos de status HTTP [aqui](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes)). O que realmente nos interessa, porém, é o _payload_, que pode ser acessado em vários formatos como bytes, strings ou JSON. Como sabemos que nossas issues estão no formato JSON, vamos inspecionar o payload da seguinte forma:

```py
response.json()
```

```python out
[{'url': 'https://api.github.com/repos/huggingface/datasets/issues/2792',
  'repository_url': 'https://api.github.com/repos/huggingface/datasets',
  'labels_url': 'https://api.github.com/repos/huggingface/datasets/issues/2792/labels{/name}',
  'comments_url': 'https://api.github.com/repos/huggingface/datasets/issues/2792/comments',
  'events_url': 'https://api.github.com/repos/huggingface/datasets/issues/2792/events',
  'html_url': 'https://github.com/huggingface/datasets/pull/2792',
  'id': 968650274,
  'node_id': 'MDExOlB1bGxSZXF1ZXN0NzEwNzUyMjc0',
  'number': 2792,
  'title': 'Update GooAQ',
  'user': {'login': 'bhavitvyamalik',
   'id': 19718818,
   'node_id': 'MDQ6VXNlcjE5NzE4ODE4',
   'avatar_url': 'https://avatars.githubusercontent.com/u/19718818?v=4',
   'gravatar_id': '',
   'url': 'https://api.github.com/users/bhavitvyamalik',
   'html_url': 'https://github.com/bhavitvyamalik',
   'followers_url': 'https://api.github.com/users/bhavitvyamalik/followers',
   'following_url': 'https://api.github.com/users/bhavitvyamalik/following{/other_user}',
   'gists_url': 'https://api.github.com/users/bhavitvyamalik/gists{/gist_id}',
   'starred_url': 'https://api.github.com/users/bhavitvyamalik/starred{/owner}{/repo}',
   'subscriptions_url': 'https://api.github.com/users/bhavitvyamalik/subscriptions',
   'organizations_url': 'https://api.github.com/users/bhavitvyamalik/orgs',
   'repos_url': 'https://api.github.com/users/bhavitvyamalik/repos',
   'events_url': 'https://api.github.com/users/bhavitvyamalik/events{/privacy}',
   'received_events_url': 'https://api.github.com/users/bhavitvyamalik/received_events',
   'type': 'User',
   'site_admin': False},
  'labels': [],
  'state': 'open',
  'locked': False,
  'assignee': None,
  'assignees': [],
  'milestone': None,
  'comments': 1,
  'created_at': '2021-08-12T11:40:18Z',
  'updated_at': '2021-08-12T12:31:17Z',
  'closed_at': None,
  'author_association': 'CONTRIBUTOR',
  'active_lock_reason': None,
  'pull_request': {'url': 'https://api.github.com/repos/huggingface/datasets/pulls/2792',
   'html_url': 'https://github.com/huggingface/datasets/pull/2792',
   'diff_url': 'https://github.com/huggingface/datasets/pull/2792.diff',
   'patch_url': 'https://github.com/huggingface/datasets/pull/2792.patch'},
  'body': '[GooAQ](https://github.com/allenai/gooaq) dataset was recently updated after splits were added for the same. This PR contains new updated GooAQ with train/val/test splits and updated README as well.',
  'performed_via_github_app': None}]
```

Uau, é muita informação! Podemos ver campos úteis como `title`, `body` e `number` que descrevem a issue, bem como informações sobre o usuário do GitHub que abriu a issue.

<Tip>

✏️ **Experimente!** Clique em alguns dos URLs na carga JSON acima para ter uma ideia de que tipo de informação cada issue do GitHub está vinculado.

</Tip>

Conforme descrito na [documentação] do GitHub (https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting), as solicitações não autenticadas são limitadas a 60 solicitações por hora. Embora você possa aumentar o parâmetro de consulta `per_page` para reduzir o número de solicitações feitas, você ainda atingirá o limite de taxa em qualquer repositório que tenha mais do que alguns milhares de issues. Então, em vez disso, você deve seguir as [instruções] do GitHub (https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token) sobre como criar um _token de acesso pessoal_ para que você pode aumentar o limite de taxa para 5.000 solicitações por hora. Depois de ter seu token, você pode incluí-lo como parte do cabeçalho da solicitação:

```py
GITHUB_TOKEN = xxx  # Copy your GitHub token here
headers = {"Authorization": f"token {GITHUB_TOKEN}"}
```

<Tip warning={true}>

⚠️ Não compartilhe um notebook com seu `GITHUB_TOKEN` colado nele. Recomendamos que você exclua a última célula depois de executá-la para evitar o vazamento dessas informações acidentalmente. Melhor ainda, armazene o token em um arquivo *.env* e use a [`python-dotenv` library](https://github.com/theskumar/python-dotenv) para carregá-lo automaticamente para você como uma variável de ambiente.

</Tip>

Agora que temos nosso token de acesso, vamos criar uma função que possa baixar todas as issues de um repositório do GitHub:

```py
import time
import math
from pathlib import Path
import pandas as pd
from tqdm.notebook import tqdm


def fetch_issues(
    owner="huggingface",
    repo="datasets",
    num_issues=10_000,
    rate_limit=5_000,
    issues_path=Path("."),
):
    if not issues_path.is_dir():
        issues_path.mkdir(exist_ok=True)

    batch = []
    all_issues = []
    per_page = 100  # Number of issues to return per page
    num_pages = math.ceil(num_issues / per_page)
    base_url = "https://api.github.com/repos"

    for page in tqdm(range(num_pages)):
        # Query with state=all to get both open and closed issues
        query = f"issues?page={page}&per_page={per_page}&state=all"
        issues = requests.get(f"{base_url}/{owner}/{repo}/{query}", headers=headers)
        batch.extend(issues.json())

        if len(batch) > rate_limit and len(all_issues) < num_issues:
            all_issues.extend(batch)
            batch = []  # Flush batch for next time period
            print(f"Reached GitHub rate limit. Sleeping for one hour ...")
            time.sleep(60 * 60 + 1)

    all_issues.extend(batch)
    df = pd.DataFrame.from_records(all_issues)
    df.to_json(f"{issues_path}/{repo}-issues.jsonl", orient="records", lines=True)
    print(
        f"Downloaded all the issues for {repo}! Dataset stored at {issues_path}/{repo}-issues.jsonl"
    )
```

Agora, quando chamamos `fetch_issues()`, ele fará o download de todas as issues em lotes para evitar exceder o limite do GitHub no número de solicitações por hora; o resultado será armazenado em um arquivo _repository_name-issues.jsonl_, onde cada linha é um objeto JSON que representa uma issue. Vamos usar esta função para pegar todas as issues de 🤗 Datasets:

```py
# Depending on your internet connection, this can take several minutes to run...
fetch_issues()
```

Depois que as issues forem baixadas, podemos carregá-las localmente usando nossas novas habilidades da [seção 2](/course/chapter5/2):

```py
issues_dataset = load_dataset("json", data_files="datasets-issues.jsonl", split="train")
issues_dataset
```

```python out
Dataset({
    features: ['url', 'repository_url', 'labels_url', 'comments_url', 'events_url', 'html_url', 'id', 'node_id', 'number', 'title', 'user', 'labels', 'state', 'locked', 'assignee', 'assignees', 'milestone', 'comments', 'created_at', 'updated_at', 'closed_at', 'author_association', 'active_lock_reason', 'pull_request', 'body', 'timeline_url', 'performed_via_github_app'],
    num_rows: 3019
})
```

Ótimo, criamos nosso primeiro conjunto de dados do zero! Mas por que existem vários milhares de issues quando a [guia Issue](https://github.com/huggingface/datasets/issues) do repositório 🤗 Datasets mostra apenas cerca de 1.000 issues no total 🤔? Conforme descrito na [documentação] do GitHub (https://docs.github.com/en/rest/reference/issues#list-issues-assigned-to-the-authenticated-user), isso ocorre porque baixamos todos os pull request também:

> A API REST v3 do GitHub considera cada pull request como uma issue, mas nem toda issue é um pull request. Por esse motivo, os endpoints de "issues" podem retornar issues e solicitações de pull na resposta. Você pode identificar solicitações de pull pela chave `pull_request`. Esteja ciente de que o `id` de uma solicitação pull retornada de endpoints "issues" será um ID de issue.

Como o conteúdo das issues e dos pull request são bem diferentes, vamos fazer um pequeno pré-processamento para nos permitir distinguir entre eles.

## Limpando os dados

O trecho acima da documentação do GitHub nos diz que a coluna `pull_request` pode ser usada para diferenciar entre issues e solicitações de pull request. Vamos olhar para uma amostra aleatória para ver qual é a diferença. Como fizemos na [seção 3](/course/chapter5/3), vamos encadear `Dataset.shuffle()` e `Dataset.select()` para criar uma amostra aleatória e então compactar o `html_url` e ` pull_request` para que possamos comparar os vários URLs:


```py
sample = issues_dataset.shuffle(seed=666).select(range(3))

# Print out the URL and pull request entries
for url, pr in zip(sample["html_url"], sample["pull_request"]):
    print(f">> URL: {url}")
    print(f">> Pull request: {pr}\n")
```

```python out
>> URL: https://github.com/huggingface/datasets/pull/850
>> Pull request: {'url': 'https://api.github.com/repos/huggingface/datasets/pulls/850', 'html_url': 'https://github.com/huggingface/datasets/pull/850', 'diff_url': 'https://github.com/huggingface/datasets/pull/850.diff', 'patch_url': 'https://github.com/huggingface/datasets/pull/850.patch'}

>> URL: https://github.com/huggingface/datasets/issues/2773
>> Pull request: None

>> URL: https://github.com/huggingface/datasets/pull/783
>> Pull request: {'url': 'https://api.github.com/repos/huggingface/datasets/pulls/783', 'html_url': 'https://github.com/huggingface/datasets/pull/783', 'diff_url': 'https://github.com/huggingface/datasets/pull/783.diff', 'patch_url': 'https://github.com/huggingface/datasets/pull/783.patch'}
```

Aqui podemos ver que cada pull request está associado a vários URLs, enquanto as issues comuns têm uma entrada `None`. Podemos usar essa distinção para criar uma nova coluna `is_pull_request` que verifica se o campo `pull_request` é `None` ou não:

```py
issues_dataset = issues_dataset.map(
    lambda x: {"is_pull_request": False if x["pull_request"] is None else True}
)
```

<Tip>

✏️ **Experimente!** Calcule o tempo médio que leva para fechar as issues em 🤗 Datasets. Você pode achar a função `Dataset.filter()` útil para filtrar os pull requests e as issues abertas, e você pode usar a função `Dataset.set_format()` para converter o conjunto de dados em um `DataFrame` para que você possa manipular facilmente os timestamps `created_at` e `closed_at`. Para pontos de bônus, calcule o tempo médio que leva para fechar os pull requests.

</Tip>

Embora possamos continuar a limpar o conjunto de dados descartando ou renomeando algumas colunas, geralmente é uma boa prática manter o conjunto de dados o mais "bruto" possível neste estágio para que possa ser facilmente usado em vários aplicativos.

Antes de enviarmos nosso conjunto de dados para o Hugging Face Hub, vamos lidar com uma coisa que está faltando: os comentários associados a cada issue e pull request. Vamos adicioná-los a seguir - você adivinhou - a API REST do GitHub!

## Aumentando o conjunto de dados

Conforme mostrado na captura de tela a seguir, os comentários associados a uma issue ou a pull request fornecem uma rica fonte de informações, especialmente se estivermos interessados ​​em criar um mecanismo de pesquisa para responder às consultas dos usuários sobre a biblioteca.

<div class="flex justify-center">
<img src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter5/datasets-issues-comment.png" alt="Comments associated with an issue about 🤗 Datasets." width="80%"/>
</div>

A API REST do GitHub fornece um [endpoint `Comments`](https://docs.github.com/en/rest/reference/issues#list-issue-comments) que retorna todos os comentários associados a uma issue. Vamos testar o endpoint para ver o que ele retorna:

```py
issue_number = 2792
url = f"https://api.github.com/repos/huggingface/datasets/issues/{issue_number}/comments"
response = requests.get(url, headers=headers)
response.json()
```

```python out
[{'url': 'https://api.github.com/repos/huggingface/datasets/issues/comments/897594128',
  'html_url': 'https://github.com/huggingface/datasets/pull/2792#issuecomment-897594128',
  'issue_url': 'https://api.github.com/repos/huggingface/datasets/issues/2792',
  'id': 897594128,
  'node_id': 'IC_kwDODunzps41gDMQ',
  'user': {'login': 'bhavitvyamalik',
   'id': 19718818,
   'node_id': 'MDQ6VXNlcjE5NzE4ODE4',
   'avatar_url': 'https://avatars.githubusercontent.com/u/19718818?v=4',
   'gravatar_id': '',
   'url': 'https://api.github.com/users/bhavitvyamalik',
   'html_url': 'https://github.com/bhavitvyamalik',
   'followers_url': 'https://api.github.com/users/bhavitvyamalik/followers',
   'following_url': 'https://api.github.com/users/bhavitvyamalik/following{/other_user}',
   'gists_url': 'https://api.github.com/users/bhavitvyamalik/gists{/gist_id}',
   'starred_url': 'https://api.github.com/users/bhavitvyamalik/starred{/owner}{/repo}',
   'subscriptions_url': 'https://api.github.com/users/bhavitvyamalik/subscriptions',
   'organizations_url': 'https://api.github.com/users/bhavitvyamalik/orgs',
   'repos_url': 'https://api.github.com/users/bhavitvyamalik/repos',
   'events_url': 'https://api.github.com/users/bhavitvyamalik/events{/privacy}',
   'received_events_url': 'https://api.github.com/users/bhavitvyamalik/received_events',
   'type': 'User',
   'site_admin': False},
  'created_at': '2021-08-12T12:21:52Z',
  'updated_at': '2021-08-12T12:31:17Z',
  'author_association': 'CONTRIBUTOR',
  'body': "@albertvillanova my tests are failing here:\r\n```\r\ndataset_name = 'gooaq'\r\n\r\n    def test_load_dataset(self, dataset_name):\r\n        configs = self.dataset_tester.load_all_configs(dataset_name, is_local=True)[:1]\r\n>       self.dataset_tester.check_load_dataset(dataset_name, configs, is_local=True, use_local_dummy_data=True)\r\n\r\ntests/test_dataset_common.py:234: \r\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \r\ntests/test_dataset_common.py:187: in check_load_dataset\r\n    self.parent.assertTrue(len(dataset[split]) > 0)\r\nE   AssertionError: False is not true\r\n```\r\nWhen I try loading dataset on local machine it works fine. Any suggestions on how can I avoid this error?",
  'performed_via_github_app': None}]
```

Podemos ver que o comentário está armazenado no campo `body`, então vamos escrever uma função simples que retorna todos os comentários associados a uma issue selecionando o conteúdo do `body` para cada elemento em `response.json()`:

```py
def get_comments(issue_number):
    url = f"https://api.github.com/repos/huggingface/datasets/issues/{issue_number}/comments"
    response = requests.get(url, headers=headers)
    return [r["body"] for r in response.json()]


# Test our function works as expected
get_comments(2792)
```

```python out
["@albertvillanova my tests are failing here:\r\n```\r\ndataset_name = 'gooaq'\r\n\r\n    def test_load_dataset(self, dataset_name):\r\n        configs = self.dataset_tester.load_all_configs(dataset_name, is_local=True)[:1]\r\n>       self.dataset_tester.check_load_dataset(dataset_name, configs, is_local=True, use_local_dummy_data=True)\r\n\r\ntests/test_dataset_common.py:234: \r\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \r\ntests/test_dataset_common.py:187: in check_load_dataset\r\n    self.parent.assertTrue(len(dataset[split]) > 0)\r\nE   AssertionError: False is not true\r\n```\r\nWhen I try loading dataset on local machine it works fine. Any suggestions on how can I avoid this error?"]
```

Isso parece certo, então vamos usar `Dataset.map()` para adicionar uma nova coluna `comments` para cada issue em nosso conjunto de dados:

```py
# Depending on your internet connection, this can take a few minutes...
issues_with_comments_dataset = issues_dataset.map(
    lambda x: {"comments": get_comments(x["number"])}
)
```

A etapa final é salvar o conjunto de dados aumentado junto com nossos dados brutos para que possamos enviá-los para o Hub:

```py
issues_with_comments_dataset.to_json("issues-datasets-with-comments.jsonl")
```

## Carregando o conjunto de dados para o Hugging Face Hub

<Youtube id="HaN6qCr_Afc"/>

Agora que temos nosso conjunto de dados aumentado, é hora de enviá-lo para o Hub para que possamos compartilhá-lo com a comunidade! Para fazer o upload do conjunto de dados, usaremos a [🤗 Hub library](https://github.com/huggingface/huggingface_hub), que nos permite interagir com o Hugging Face Hub por meio de uma API Python. 🤗 Hub vem pré-instalado com 🤗 Transformers, para que possamos usá-lo diretamente. Por exemplo, podemos usar a função `list_datasets()` para obter informações sobre todos os conjuntos de dados públicos atualmente hospedados no Hub:

```py
from huggingface_hub import list_datasets

all_datasets = list_datasets()
print(f"Number of datasets on Hub: {len(all_datasets)}")
print(all_datasets[0])
```

```python out
Number of datasets on Hub: 1487
Dataset Name: acronym_identification, Tags: ['annotations_creators:expert-generated', 'language_creators:found', 'languages:en', 'licenses:mit', 'multilinguality:monolingual', 'size_categories:10K<n<100K', 'source_datasets:original', 'task_categories:structure-prediction', 'task_ids:structure-prediction-other-acronym-identification']
```

Podemos ver que atualmente existem cerca de 1.500 conjuntos de dados no Hub, e a função `list_datasets()` também fornece alguns metadados básicos sobre cada repositório de conjuntos de dados.

Para nossos propósitos, a primeira coisa que precisamos fazer é criar um novo repositório de conjunto de dados no Hub. Para fazer isso, precisamos de um token de autenticação, que pode ser obtido primeiro entrando no Hugging Face Hub com a função `notebook_login()`:

```py
from huggingface_hub import notebook_login

notebook_login()
```

Isso criará um widget onde você poderá inserir seu nome de usuário e senha, e um token de API será salvo em *~/.huggingface/token*. Se você estiver executando o código em um terminal, poderá fazer login via CLI:

```bash
huggingface-cli login
```

Feito isso, podemos criar um novo repositório de conjunto de dados com a função `create_repo()`:

```py
from huggingface_hub import create_repo

repo_url = create_repo(name="github-issues", repo_type="dataset")
repo_url
```

```python out
'https://huggingface.co/datasets/lewtun/github-issues'
```

Neste exemplo, criamos um repositório de conjunto de dados vazio chamado `github-issues` sob o nome de usuário `lewtun` (o nome de usuário deve ser seu nome de usuário do Hub quando você estiver executando este código!).

<Tip>

✏️ **Experimente!** Use seu nome de usuário e senha do Hugging Face Hub para obter um token e criar um repositório vazio chamado `github-issues`. Lembre-se de **nunca salvar suas credenciais** no Colab ou em qualquer outro repositório, pois essas informações podem ser exploradas por agentes mal-intencionados.

</Tip>

Em seguida, vamos clonar o repositório do Hub para nossa máquina local e copiar nosso arquivo de conjunto de dados para ele. O 🤗 Hub fornece uma classe `Repository` útil que envolve muitos dos comandos comuns do Git, portanto, para clonar o repositório remoto, basta fornecer o URL e o caminho local para o qual desejamos clonar:


```py
from huggingface_hub import Repository

repo = Repository(local_dir="github-issues", clone_from=repo_url)
!cp datasets-issues-with-comments.jsonl github-issues/
```

Por padrão, várias extensões de arquivo (como *.bin*, *.gz* e *.zip*) são rastreadas com o Git LFS para que arquivos grandes possam ser versionados no mesmo fluxo de trabalho do Git. Você pode encontrar uma lista de extensões de arquivos rastreados dentro do arquivo *.gitattributes* do repositório. Para incluir o formato JSON Lines na lista, podemos executar o seguinte comando:

```py
repo.lfs_track("*.jsonl")
```

Então podemos usar `Repository.push_to_hub()` para enviar o conjunto de dados para o Hub:

```py
repo.push_to_hub()
```

Se navegarmos para a URL contida em `repo_url`, veremos agora que nosso arquivo de conjunto de dados foi carregado.

<div class="flex justify-center">
<img src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter5/hub-repo.png" alt="Our dataset repository on the Hugging Face Hub." width="80%"/>
</div>

A partir daqui, qualquer um pode baixar o conjunto de dados simplesmente fornecendo `load_dataset()` com o ID do repositório como o argumento `path`:

```py
remote_dataset = load_dataset("lewtun/github-issues", split="train")
remote_dataset
```

```python out
Dataset({
    features: ['url', 'repository_url', 'labels_url', 'comments_url', 'events_url', 'html_url', 'id', 'node_id', 'number', 'title', 'user', 'labels', 'state', 'locked', 'assignee', 'assignees', 'milestone', 'comments', 'created_at', 'updated_at', 'closed_at', 'author_association', 'active_lock_reason', 'pull_request', 'body', 'performed_via_github_app', 'is_pull_request'],
    num_rows: 2855
})
```

Legal, nós enviamos nosso conjunto de dados para o Hub e está disponível para outros usarem! Há apenas uma coisa importante a fazer: adicionar um _cartão de conjunto de dados_ que explica como o corpus foi criado e fornece outras informações úteis para a comunidade.

<Tip>

💡 Você também pode enviar um conjunto de dados para o Hugging Face Hub diretamente do terminal usando `huggingface-cli` e um pouco de magia Git. Consulte o [guia do 🤗 Datasets](https://huggingface.co/docs/datasets/share#share-a-dataset-using-the-cli) para obter detalhes sobre como fazer isso.

</Tip>

## Criando um cartão do datasets

Conjuntos de dados bem documentados são mais propensos a serem úteis para outras pessoas (incluindo você mesmo no futuro!), pois fornecem o contexto para permitir que os usuários decidam se o conjunto de dados é relevante para sua tarefa e avaliem possíveis vieses ou riscos associados ao uso o conjunto de dados.

No Hugging Face Hub, essas informações são armazenadas no arquivo *README.md* de cada repositório de conjunto de dados. Há duas etapas principais que você deve seguir antes de criar este arquivo:

1. Use a aplicação [`datasets-tagging`](https://huggingface.co/datasets/tagging/) para criar tags de metadados no formato YAML. Essas tags são usadas para uma variedade de recursos de pesquisa no Hugging Face Hub e garantem que seu conjunto de dados possa ser facilmente encontrado pelos membros da comunidade. Como criamos um conjunto de dados personalizado aqui, você precisará clonar o repositório `datasets-tagging` e executar o aplicativo localmente. Veja como é a interface:

<div class="flex justify-center">
<img src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter5/datasets-tagger.png" alt="The 'datasets-tagging' interface." width="80%"/>
</div>

2. Leia o [guia do 🤗 datasets](https://github.com/huggingface/datasets/blob/master/templates/README_guide.md) sobre como criar cartões informativos de conjuntos de dados e use-os como modelo.

Você pode criar o arquivo *README.md* diretamente no Hub e encontrar um cartão de conjunto de dados de modelo no repositório de conjunto de dados `lewtun/github-issues`. Uma captura de tela do cartão de conjunto de dados preenchido é mostrada abaixo.

<div class="flex justify-center">
<img src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter5/dataset-card.png" alt="A dataset card." width="80%"/>
</div>

<Tip>

✏️ **Experimente!** Use o aplicativo `dataset-tagging` e [guia do 🤗 datasets](https://github.com/huggingface/datasets/blob/master/templates/README_guide.md) para concluir o *Arquivo README.md* para o conjunto de dados de issues do GitHub.

</Tip>

É isso! Vimos nesta seção que criar um bom conjunto de dados pode ser bastante complicado, mas felizmente carregá-lo e compartilhá-lo com a comunidade não é. Na próxima seção, usaremos nosso novo conjunto de dados para criar um mecanismo de pesquisa semântica com o 🤗 datasets que podem corresponder perguntas as issues e comentários mais relevantes.

<Tip>

✏️ **Experimente!** Siga as etapas que seguimos nesta seção para criar um conjunto de dados de issues do GitHub para sua biblioteca de código aberto favorita (escolha algo diferente do 🤗 datasets, é claro!). Para pontos de bônus, ajuste um classificador multilabel para prever as tags presentes no campo `labels`.

</Tip>




<EditOnGithub source="https://github.com/huggingface/course/blob/main/chapters/pt/chapter5/5.mdx" />

### Introdução
https://huggingface.co/learn/course/pt/chapter5/1.md

# Introdução

<CourseFloatingBanner
    chapter={5}
    classNames="absolute z-10 right-0 top-0"
/>

No [Capítulo 3](/course/chapter3) você teve seu primeiro gostinho da biblioteca 🤗 Datasets e viu que havia três passos principais quando se tratava de treinar para melhorar (fine-tuning) um modelo:

1. Carregar um conjunto de dados (dataset) do Hugging Face Hub.
2. Pré-processar os dados com `Dataset.map()`.
3. Carregar e calcular as métricas.

Mas isto está apenas arranhando a superfície do que 🤗 Dataset.map pode fazer! Neste capítulo, vamos dar um mergulho profundo na biblioteca. Ao longo do caminho, encontraremos respostas para as seguintes perguntas:

* O que você faz quando seu conjunto de dados não está no Hub?
* Como você pode separar um conjunto de dados? (E se você _necessário_ usar Pandas?)
* O que você faz quando seu conjunto de dados é enorme e derreterá a RAM de seu laptop?
* O que diabos são "mapeamento de memória" e Apache Arrow?
* Como você pode criar seu próprio conjunto de dados e enviar para o Hub?

As técnicas que você aprender aqui vão prepará-lo para as tarefas avançadas de tokenization e fine-tuning no [Capítulo 6](/course/chapter6) e [Capítulo 7](/course/chapter7) -- então pegue um café e vamos começar!



<EditOnGithub source="https://github.com/huggingface/course/blob/main/chapters/pt/chapter5/1.mdx" />

### Hora de fatiar e dividir os dados
https://huggingface.co/learn/course/pt/chapter5/3.md

# Hora de fatiar e dividir os dados

<CourseFloatingBanner chapter={5}
  classNames="absolute z-10 right-0 top-0"
  notebooks={[
    {label: "Google Colab", value: "https://colab.research.google.com/github/huggingface/notebooks/blob/master/course/pt/chapter5/section3.ipynb"},
    {label: "Aws Studio", value: "https://studiolab.sagemaker.aws/import/github/huggingface/notebooks/blob/master/course/pt/chapter5/section3.ipynb"},
]} />

Na maioria das vezes, os dados com os quais você trabalha não estarão perfeitamente preparados para treinamento de modelos. Nesta seção vamos explorar as várias características que o 🤗 Datasets fornece para limpar seus conjuntos de dados.

<Youtube id="tqfSFcPMgOI"/>

## Slicing and dicing our data

Semelhante ao Pandas, 🤗 Datasets fornece várias funções para manipular o conteúdo dos objetos `Dataset` e `DatasetDict`. Já encontramos o método `Dataset.map()` no [Capítulo 3](/course/chapter3), e nesta seção vamos explorar algumas das outras funções à nossa disposição.

Para este exemplo, usaremos o [Drug Review Dataset](https://archive.ics.uci.edu/ml/datasets/Drug+Review+Dataset+%28Drugs.com%29) que está hospedado na [UC Irvine Machine Learning Repository](https://archive.ics.uci.edu/ml/index.php), que contém avaliações de pacientes sobre vários medicamentos, juntamente com a condição a ser tratada e uma classificação de 10 estrelas da satisfação do paciente.

Primeiro precisamos baixar e extrair os dados, o que pode ser feito com os comandos `wget` e `unzip`:

```py
!wget "https://archive.ics.uci.edu/ml/machine-learning-databases/00462/drugsCom_raw.zip"
!unzip drugsCom_raw.zip
```

Como o TSV é apenas uma variante do CSV que usa tabulações em vez de vírgulas como separador, podemos carregar esses arquivos usando o script de carregamento `csv` e especificando o argumento `delimiter` na função `load_dataset()` da seguinte forma:

```py
from datasets import load_dataset

data_files = {"train": "drugsComTrain_raw.tsv", "test": "drugsComTest_raw.tsv"}
# \t is the tab character in Python
drug_dataset = load_dataset("csv", data_files=data_files, delimiter="\t")
```

Uma boa prática ao fazer qualquer tipo de análise de dados é pegar uma pequena amostra aleatória para ter uma ideia rápida do tipo de dados com os quais você está trabalhando. Em 🤗 Datasets, podemos criar uma amostra aleatória encadeando as funções `Dataset.shuffle()` e `Dataset.select()` juntas:

```py
drug_sample = drug_dataset["train"].shuffle(seed=42).select(range(1000))
# Peek at the first few examples
drug_sample[:3]
```

```python out
{'Unnamed: 0': [87571, 178045, 80482],
 'drugName': ['Naproxen', 'Duloxetine', 'Mobic'],
 'condition': ['Gout, Acute', 'ibromyalgia', 'Inflammatory Conditions'],
 'review': ['"like the previous person mention, I&#039;m a strong believer of aleve, it works faster for my gout than the prescription meds I take. No more going to the doctor for refills.....Aleve works!"',
  '"I have taken Cymbalta for about a year and a half for fibromyalgia pain. It is great\r\nas a pain reducer and an anti-depressant, however, the side effects outweighed \r\nany benefit I got from it. I had trouble with restlessness, being tired constantly,\r\ndizziness, dry mouth, numbness and tingling in my feet, and horrible sweating. I am\r\nbeing weaned off of it now. Went from 60 mg to 30mg and now to 15 mg. I will be\r\noff completely in about a week. The fibro pain is coming back, but I would rather deal with it than the side effects."',
  '"I have been taking Mobic for over a year with no side effects other than an elevated blood pressure.  I had severe knee and ankle pain which completely went away after taking Mobic.  I attempted to stop the medication however pain returned after a few days."'],
 'rating': [9.0, 3.0, 10.0],
 'date': ['September 2, 2015', 'November 7, 2011', 'June 5, 2013'],
 'usefulCount': [36, 13, 128]}
```

Observe que corrigimos a seed em `Dataset.shuffle()` para fins de reprodutibilidade. `Dataset.select()` espera um iterável de índices, então passamos `range(1000)` para pegar os primeiros 1.000 exemplos do conjunto de dados embaralhado. A partir desta amostra já podemos ver algumas peculiaridades em nosso conjunto de dados:

* A coluna  `Unnamed: 0` se parece com um ID anônimo para cada paciente.
* A coluna `condition` inclui uma combinação de rótulos em maiúsculas e minúsculas.
* As revisões são de tamanho variável e contêm uma mistura de separadores de linha Python (`\r\n`), bem como códigos de caracteres HTML como `&\#039;`.

Vamos ver como podemos usar 🤗 Datasets para lidar com cada um desses problemas. Para testar a hipótese de ID do paciente para a coluna `Unnamed: 0`, podemos usar a função `Dataset.unique()` para verificar se o número de IDs corresponde ao número de linhas em cada divisão:

```py
for split in drug_dataset.keys():
    assert len(drug_dataset[split]) == len(drug_dataset[split].unique("Unnamed: 0"))
```

Isso parece confirmar nossa hipótese, então vamos limpar um pouco o conjunto de dados renomeando a coluna `Unnamed: 0` para algo um pouco mais interpretável. Podemos usar a função `DatasetDict.rename_column()` para renomear a coluna em ambas as divisões de uma só vez:

```py
drug_dataset = drug_dataset.rename_column(
    original_column_name="Unnamed: 0", new_column_name="patient_id"
)
drug_dataset
```

```python out
DatasetDict({
    train: Dataset({
        features: ['patient_id', 'drugName', 'condition', 'review', 'rating', 'date', 'usefulCount'],
        num_rows: 161297
    })
    test: Dataset({
        features: ['patient_id', 'drugName', 'condition', 'review', 'rating', 'date', 'usefulCount'],
        num_rows: 53766
    })
})
```

<Tip>

✏️ **Experimente!** Use a função `Dataset.unique()` para encontrar o número de medicamentos e condições exclusivos nos conjuntos de treinamento e teste.

</Tip>

Em seguida, vamos normalizar todos os rótulos `condition` usando `Dataset.map()`. Como fizemos com a tokenização no [Capítulo 3](/course/chapter3), podemos definir uma função simples que pode ser aplicada em todas as linhas de cada divisão em `drug_dataset`:

```py
def lowercase_condition(example):
    return {"condition": example["condition"].lower()}


drug_dataset.map(lowercase_condition)
```

```python out
AttributeError: 'NoneType' object has no attribute 'lower'
```

Oh não, tivemos um problema com nossa função de mapa! A partir do erro, podemos inferir que algumas das entradas na coluna `condition` são `None`, que não podem ser minúsculas, pois não são strings. Vamos eliminar essas linhas usando `Dataset.filter()`, que funciona de maneira semelhante a `Dataset.map()` e espera uma função que receba um único exemplo do conjunto de dados. Em vez de escrever uma função explícita como:

```py
def filter_nones(x):
    return x["condition"] is not None
```

e então executando `drug_dataset.filter(filter_nones)`, podemos fazer isso em uma linha usando uma _função lambda_. Em Python, funções lambda são pequenas funções que você pode definir sem nomeá-las explicitamente. Eles assumem a forma geral:

```
lambda <arguments> : <expression>
```

onde `lambda` é uma das [palavras-chave] especiais do Python (https://docs.python.org/3/reference/lexical_analysis.html#keywords), `<arguments>` é uma lista/conjunto de valores separados por vírgula que defina as entradas para a função, e `<expressão>` representa as operações que você deseja executar. Por exemplo, podemos definir uma função lambda simples que eleva um número ao quadrado da seguinte forma:

```
lambda x : x * x
```

Para aplicar esta função a uma entrada, precisamos envolvê-la e a entrada entre parênteses:

```py
(lambda x: x * x)(3)
```

```python out
9
```

Da mesma forma, podemos definir funções lambda com vários argumentos, separando-os com vírgulas. Por exemplo, podemos calcular a área de um triângulo da seguinte forma:

```py
(lambda base, height: 0.5 * base * height)(4, 8)
```

```python out
16.0
```

As funções lambda são úteis quando você deseja definir funções pequenas e de uso único (para obter mais informações sobre elas, recomendamos a leitura do excelente [tutorial do Real Python](https://realpython.com/python-lambda/) de Andre Burgaud). No contexto 🤗 Datasets, podemos usar funções lambda para definir operações simples de mapa e filtro, então vamos usar este truque para eliminar as entradas `None` em nosso conjunto de dados:

```py
drug_dataset = drug_dataset.filter(lambda x: x["condition"] is not None)
```

Com as entradas `None` removidas, podemos normalizar nossa coluna `condition`:

```py
drug_dataset = drug_dataset.map(lowercase_condition)
# Check that lowercasing worked
drug_dataset["train"]["condition"][:3]
```

```python out
['left ventricular dysfunction', 'adhd', 'birth control']
```

Funciona! Agora que limpamos os rótulos, vamos dar uma olhada na limpeza dos próprios comentários.

## Criando novas colunas

Sempre que estiver lidando com avaliações de clientes, uma boa prática é verificar o número de palavras em cada avaliação. Uma avaliação pode ser apenas uma única palavra como "Ótimo!" ou um ensaio completo com milhares de palavras e, dependendo do caso de uso, você precisará lidar com esses extremos de maneira diferente. Para calcular o número de palavras em cada revisão, usaremos uma heurística aproximada baseada na divisão de cada texto por espaços em branco.

Vamos definir uma função simples que conta o número de palavras em cada revisão:

```py
def compute_review_length(example):
    return {"review_length": len(example["review"].split())}
```

Ao contrário de nossa função `lowercase_condition()`, `compute_review_length()` retorna um dicionário cuja chave não corresponde a um dos nomes de coluna no conjunto de dados. Nesse caso, quando `compute_review_length()` for passado para `Dataset.map()`, ele será aplicado a todas as linhas do conjunto de dados para criar uma nova coluna `review_length`:

```py
drug_dataset = drug_dataset.map(compute_review_length)
# Inspect the first training example
drug_dataset["train"][0]
```

```python out
{'patient_id': 206461,
 'drugName': 'Valsartan',
 'condition': 'left ventricular dysfunction',
 'review': '"It has no side effect, I take it in combination of Bystolic 5 Mg and Fish Oil"',
 'rating': 9.0,
 'date': 'May 20, 2012',
 'usefulCount': 27,
 'review_length': 17}
```

Como esperado, podemos ver que uma coluna `review_length` foi adicionada ao nosso conjunto de treinamento. Podemos classificar essa nova coluna com `Dataset.sort()` para ver como são os valores extremos:

```py
drug_dataset["train"].sort("review_length")[:3]
```

```python out
{'patient_id': [103488, 23627, 20558],
 'drugName': ['Loestrin 21 1 / 20', 'Chlorzoxazone', 'Nucynta'],
 'condition': ['birth control', 'muscle spasm', 'pain'],
 'review': ['"Excellent."', '"useless"', '"ok"'],
 'rating': [10.0, 1.0, 6.0],
 'date': ['November 4, 2008', 'March 24, 2017', 'August 20, 2016'],
 'usefulCount': [5, 2, 10],
 'review_length': [1, 1, 1]}
```

Como suspeitávamos, algumas revisões contêm apenas uma única palavra, que, embora possa ser boa para análise de sentimentos, não seria informativa se quisermos prever a condição.

<Tip>

🙋 Uma forma alternativa de adicionar novas colunas a um conjunto de dados é com a função `Dataset.add_column()`. Isso permite que você forneça a coluna como uma lista Python ou array NumPy e pode ser útil em situações em que `Dataset.map()` não é adequado para sua análise.

</Tip>

Vamos usar a função `Dataset.filter()` para remover comentários que contenham menos de 30 palavras. Da mesma forma que fizemos com a coluna "condição", podemos filtrar as reviews muito curtas exigindo que as reviews tenham um comprimento acima desse limite.

```py
drug_dataset = drug_dataset.filter(lambda x: x["review_length"] > 30)
print(drug_dataset.num_rows)
```

```python out
{'train': 138514, 'test': 46108}
```

Como você pode ver, isso removeu cerca de 15% das avaliações de nossos conjuntos de treinamento e teste originais.

<Tip>

✏️ **Experimente!** Use a função `Dataset.sort()` para inspecionar as resenhas com o maior número de palavras. Consulte a [documentação](https://huggingface.co/docs/datasets/package_reference/main_classes#datasets.Dataset.sort) para ver qual argumento você precisa usar para classificar as avaliações por tamanho em ordem decrescente.

</Tip>

A última coisa com a qual precisamos lidar é a presença de códigos de caracteres HTML em nossas análises. Podemos usar o módulo `html` do Python para liberar esses caracteres, assim:

```py
import html

text = "I&#039;m a transformer called BERT"
html.unescape(text)
```

```python out
"I'm a transformer called BERT"
```

Usaremos `Dataset.map()` para liberar todos os caracteres HTML em nosso corpus:

```python
drug_dataset = drug_dataset.map(lambda x: {"review": html.unescape(x["review"])})
```

Como você pode ver, o método `Dataset.map()` é bastante útil para o processamento de dados -- e ainda nem arranhamos a superfície de tudo o que ele pode fazer!

## Os superpoderes do método `map()`

O método `Dataset.map()` recebe um argumento `batched` que, se definido como `True`, faz com que ele envie um batch de exemplos para a função map de uma só vez (o tamanho do batch é configurável, mas o padrão é 1.000). Por exemplo, a função map anterior que não escapou de todo o HTML demorou um pouco para ser executada (você pode ler o tempo gasto nas barras de progresso). Podemos acelerar isso processando vários elementos ao mesmo tempo usando uma compreensão de lista.

Quando você especifica `batched=True` a função recebe um dicionário com os campos do conjunto de dados, mas cada valor agora é uma _lista de valores_, e não apenas um valor único. O valor de retorno de `Dataset.map()` deve ser o mesmo: um dicionário com os campos que queremos atualizar ou adicionar ao nosso conjunto de dados e uma lista de valores. Por exemplo, aqui está outra maneira de fazer o scape de todos os caracteres HTML, mas usando `batched=True`:

```python
new_drug_dataset = drug_dataset.map(
    lambda x: {"review": [html.unescape(o) for o in x["review"]]}, batched=True
)
```

Se você estiver executando esse código em um jupyter notebook, verá que esse comando é executado muito mais rápido que o anterior. E não é porque nossas revisões já foram sem escape em HTML -- se você reexecutar a instrução da seção anterior (sem `batched=True`), levará o mesmo tempo que antes. Isso ocorre porque as compreensões de lista geralmente são mais rápidas do que executar o mesmo código em um loop `for`, e também ganhamos algum desempenho acessando muitos elementos ao mesmo tempo em vez de um por um.

Usar `Dataset.map()` com `batched=True` será essencial para desbloquear a velocidade dos tokenizers "rápidos" que encontraremos no [Capítulo 6](/course/chapter6), que podem rapidamente tokenizar grandes listas de textos. Por exemplo, para tokenizar todas as análises de medicamentos com um tokenizer rápido, poderíamos usar uma função como esta:

```python
from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("bert-base-cased")


def tokenize_function(examples):
    return tokenizer(examples["review"], truncation=True)
```

Como você viu no [Capítulo 3](/course/chapter3), podemos passar um ou vários exemplos para o tokenizer, então podemos usar esta função com ou sem `batched=True`. Vamos aproveitar esta oportunidade para comparar o desempenho das diferentes opções. Em um notebook, você pode cronometrar uma instrução de uma linha adicionando `%time` antes da linha de código que deseja medir:

```python no-format
%time tokenized_dataset = drug_dataset.map(tokenize_function, batched=True)
```

Você também pode cronometrar uma célula inteira colocando `%%time` no início da célula. No hardware em que executamos isso, ele mostrava 10,8s para esta instrução (é o número escrito depois de "Wall time").

<Tip>

✏️ **Experimente!** Execute a mesma instrução com e sem `batched=True`, então tente com um tokenizer lento (adicione `use_fast=False` no método `AutoTokenizer.from_pretrained()`) para que você possa veja quais números você obtém em seu hardware.

</Tip>

Aqui estão os resultados que obtivemos com e sem batching, com um tokenizer rápido e lento:

Opções          | Tokenizador rápido | Tokenizador lento
:--------------:|:------------------:|:-------------:
`batched=True`  | 10.8s              | 4min41s
`batched=False` | 59.2s              | 5min3s

Isso significa que usar um tokenizer rápido com a opção `batched=True` é 30 vezes mais rápido do que seu equivalente lento sem batching -- isso é realmente incrível! Essa é a principal razão pela qual os tokenizers rápidos são o padrão ao usar o `AutoTokenizer` (e porque eles são chamados de "rápidos"). Eles são capazes de alcançar essa aceleração porque nos bastidores o código de tokenização é executado em Rust, que é uma linguagem que facilita a execução de código paralelizado.

A paralelização também é a razão para a aceleração de quase 6x que o tokenizer rápido alcança com o batching: você não pode paralelizar uma única operação de tokenização, mas quando você deseja tokenizar muitos textos ao mesmo tempo, você pode simplesmente dividir a execução em vários processos, cada um responsável por seus próprios textos.

`Dataset.map()` também possui alguns recursos de paralelização próprios. Como eles não são suportados pelo Rust, eles não permitem que um tokenizer lento alcance um rápido, mas ainda podem ser úteis (especialmente se você estiver usando um tokenizer que não possui uma versão rápida). Para ativar o multiprocessamento, use o argumento `num_proc` e especifique o número de processos a serem usados ​​em sua chamada para `Dataset.map()`:

```py
slow_tokenizer = AutoTokenizer.from_pretrained("bert-base-cased", use_fast=False)


def slow_tokenize_function(examples):
    return slow_tokenizer(examples["review"], truncation=True)


tokenized_dataset = drug_dataset.map(slow_tokenize_function, batched=True, num_proc=8)
```

Você pode experimentar um pouco o tempo para determinar o número ideal de processos a serem usados; no nosso caso, 8 pareceu produzir o melhor ganho de velocidade. Aqui estão os números que obtivemos com e sem multiprocessamento:

Opções                          | Tokenizador rápido | Tokenizador lento
:------------------------------:|:------------------:|:-------------:
`batched=True`                  | 10.8s              | 4min41s
`batched=False`                 | 59.2s              | 5min3s
`batched=True`, `num_proc=8`    | 6.52s              | 41.3s
`batched=False`, `num_proc=8`   | 9.49s              | 45.2s

Esses são resultados muito mais razoáveis ​​para o tokenizer lento, mas o desempenho do tokenizer rápido também foi substancialmente melhorado. Observe, no entanto, que nem sempre será o caso -- para valores de `num_proc` diferentes de 8, nossos testes mostraram que era mais rápido usar `batched=True` sem essa opção. Em geral, não recomendamos o uso de multiprocessamento Python para tokenizers rápidos com `batched=True`.

<Tip>

Usar `num_proc` para acelerar seu processamento geralmente é uma ótima idéia, desde que a função que você está usando não esteja fazendo algum tipo de multiprocessamento próprio.

</Tip>

Toda essa funcionalidade condensada em um único método já é incrível, mas tem mais! Com `Dataset.map()` e `batched=True` você pode alterar o número de elementos em seu conjunto de dados. Isso é super útil em muitas situações em que você deseja criar vários recursos de treinamento a partir de um exemplo, e precisaremos fazer isso como parte do pré-processamento de várias das tarefas de PNL que realizaremos no [Capítulo 7](/course/chapter7).

<Tip>

💡 No aprendizado de máquina, um _exemplo_ geralmente é definido como o conjunto de _recursos_ que alimentamos o modelo. Em alguns contextos, esses recursos serão o conjunto de colunas em um `Dataset`, mas em outros (como aqui e para resposta a perguntas), vários recursos podem ser extraídos de um único exemplo e pertencer a uma única coluna.

</Tip>

Vamos dar uma olhada em como funciona! Aqui vamos tokenizar nossos exemplos e truncá-los para um comprimento máximo de 128, mas pediremos ao tokenizer para retornar *todos* os pedaços dos textos em vez de apenas o primeiro. Isso pode ser feito com `return_overflowing_tokens=True`:
```py
def tokenize_and_split(examples):
    return tokenizer(
        examples["review"],
        truncation=True,
        max_length=128,
        return_overflowing_tokens=True,
    )
```

Vamos testar isso em um exemplo antes de usar `Dataset.map()` em todo o conjunto de dados:

```py
result = tokenize_and_split(drug_dataset["train"][0])
[len(inp) for inp in result["input_ids"]]
```

```python out
[128, 49]
```

Assim, nosso primeiro exemplo no conjunto de treinamento se tornou dois recursos porque foi tokenizado para mais do que o número máximo de tokens que especificamos: o primeiro de comprimento 128 e o segundo de comprimento 49. Agora vamos fazer isso para todos os elementos do conjunto de dados!

```py
tokenized_dataset = drug_dataset.map(tokenize_and_split, batched=True)
```

```python out
ArrowInvalid: Column 1 named condition expected length 1463 but got length 1000
```

Oh não! Isso não funcionou! Por que não? Observar a mensagem de erro nos dará uma pista: há uma incompatibilidade nos comprimentos de uma das colunas, sendo uma de comprimento 1.463 e a outra de comprimento 1.000. Se você consultou a [documentação] do `Dataset.map()` (https://huggingface.co/docs/datasets/package_reference/main_classes#datasets.Dataset.map), você deve se lembrar de que é o número de amostras passadas para a função que estamos mapeando; aqui, esses 1.000 exemplos forneceram 1.463 novos recursos, resultando em um erro de forma.

O problema é que estamos tentando misturar dois conjuntos de dados diferentes de tamanhos diferentes: as colunas `drug_dataset` terão um certo número de exemplos (os 1.000 em nosso erro), mas o `tokenized_dataset` que estamos construindo terá mais (o 1.463 na mensagem de erro). Isso não funciona para um `Dataset`, portanto, precisamos remover as colunas do conjunto de dados antigo ou torná-las do mesmo tamanho do novo conjunto de dados. Podemos fazer o primeiro com o argumento `remove_columns`:

```py
tokenized_dataset = drug_dataset.map(
    tokenize_and_split, batched=True, remove_columns=drug_dataset["train"].column_names
)
```

Agora isso funciona sem erro. Podemos verificar que nosso novo conjunto de dados tem muito mais elementos do que o conjunto de dados original comparando os comprimentos:

```py
len(tokenized_dataset["train"]), len(drug_dataset["train"])
```

```python out
(206772, 138514)
```

Mencionamos que também podemos lidar com o problema de comprimento incompatível tornando as colunas antigas do mesmo tamanho das novas. Para fazer isso, precisaremos do campo `overflow_to_sample_mapping` que o tokenizer retorna quando configuramos `return_overflowing_tokens=True`. Ele nos fornece um mapeamento de um novo índice de recurso para o índice da amostra da qual ele se originou. Usando isso, podemos associar cada chave presente em nosso conjunto de dados original a uma lista de valores do tamanho certo, repetindo os valores de cada exemplo quantas vezes ele gerar novos recursos:

```py
def tokenize_and_split(examples):
    result = tokenizer(
        examples["review"],
        truncation=True,
        max_length=128,
        return_overflowing_tokens=True,
    )
    # Extract mapping between new and old indices
    sample_map = result.pop("overflow_to_sample_mapping")
    for key, values in examples.items():
        result[key] = [values[i] for i in sample_map]
    return result
```

Podemos ver que funciona com `Dataset.map()` sem precisarmos remover as colunas antigas:

```py
tokenized_dataset = drug_dataset.map(tokenize_and_split, batched=True)
tokenized_dataset
```

```python out
DatasetDict({
    train: Dataset({
        features: ['attention_mask', 'condition', 'date', 'drugName', 'input_ids', 'patient_id', 'rating', 'review', 'review_length', 'token_type_ids', 'usefulCount'],
        num_rows: 206772
    })
    test: Dataset({
        features: ['attention_mask', 'condition', 'date', 'drugName', 'input_ids', 'patient_id', 'rating', 'review', 'review_length', 'token_type_ids', 'usefulCount'],
        num_rows: 68876
    })
})
```

Obtemos o mesmo número de recursos de treinamento de antes, mas aqui mantivemos todos os campos antigos. Se você precisar deles para algum pós-processamento após aplicar seu modelo, convém usar essa abordagem.

Agora você viu como 🤗 Datasets podem ser usados ​​para pré-processar um conjunto de dados de várias maneiras. Embora as funções de processamento de 🤗 Datasets cubram a maioria das suas necessidades de treinamento de modelo, pode haver momentos em que você precisará mudar para o Pandas para acessar recursos mais poderosos, como `DataFrame.groupby()` ou APIs de alto nível para visualização. Felizmente, 🤗 Datasets foi projetado para ser interoperável com bibliotecas como Pandas, NumPy, PyTorch, TensorFlow e JAX. Vamos dar uma olhada em como isso funciona.

## De `Dataset`s para `DataFrame`s e vice-versa

<Youtube id="tfcY1067A5Q"/>

Para habilitar a conversão entre várias bibliotecas de terceiros, 🤗 Datasets fornece uma função `Dataset.set_format()`. Essa função altera apenas o _formato de saída_ do conjunto de dados, para que você possa alternar facilmente para outro formato sem afetar o _formato de dados_ subjacente, que é o Apache Arrow. A formatação é feita no local. Para demonstrar, vamos converter nosso conjunto de dados para Pandas:

```py
drug_dataset.set_format("pandas")
```

Agora, quando acessamos os elementos do dataset, obtemos um `pandas.DataFrame` em vez de um dicionário:

```py
drug_dataset["train"][:3]
```

<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>patient_id</th>
      <th>drugName</th>
      <th>condition</th>
      <th>review</th>
      <th>rating</th>
      <th>date</th>
      <th>usefulCount</th>
      <th>review_length</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>95260</td>
      <td>Guanfacine</td>
      <td>adhd</td>
      <td>"My son is halfway through his fourth week of Intuniv..."</td>
      <td>8.0</td>
      <td>April 27, 2010</td>
      <td>192</td>
      <td>141</td>
    </tr>
    <tr>
      <th>1</th>
      <td>92703</td>
      <td>Lybrel</td>
      <td>birth control</td>
      <td>"I used to take another oral contraceptive, which had 21 pill cycle, and was very happy- very light periods, max 5 days, no other side effects..."</td>
      <td>5.0</td>
      <td>December 14, 2009</td>
      <td>17</td>
      <td>134</td>
    </tr>
    <tr>
      <th>2</th>
      <td>138000</td>
      <td>Ortho Evra</td>
      <td>birth control</td>
      <td>"This is my first time using any form of birth control..."</td>
      <td>8.0</td>
      <td>November 3, 2015</td>
      <td>10</td>
      <td>89</td>
    </tr>
  </tbody>
</table>

Vamos criar um `pandas.DataFrame` para todo o conjunto de treinamento selecionando todos os elementos de `drug_dataset["train"]`:

```py
train_df = drug_dataset["train"][:]
```

<Tip>

🚨 `Dataset.set_format()` altera o formato de retorno para o método dunder `__getitem__()` do conjunto de dados. Isso significa que quando queremos criar um novo objeto como `train_df` a partir de um `Dataset` no formato `"pandas"`, precisamos dividir todo o conjunto de dados para obter um `pandas.DataFrame`. Você pode verificar por si mesmo que o tipo de `drug_dataset["train"]` é `Dataset`, independentemente do formato de saída.

</Tip>


A partir daqui, podemos usar todas as funcionalidades do Pandas que queremos. Por exemplo, podemos fazer um encadeamento sofisticado para calcular a distribuição de classes entre as entradas `condition`:

```py
frequencies = (
    train_df["condition"]
    .value_counts()
    .to_frame()
    .reset_index()
    .rename(columns={"index": "condition", "count": "frequency"})
)
frequencies.head()
```

<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>condition</th>
      <th>frequency</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>birth control</td>
      <td>27655</td>
    </tr>
    <tr>
      <th>1</th>
      <td>depression</td>
      <td>8023</td>
    </tr>
    <tr>
      <th>2</th>
      <td>acne</td>
      <td>5209</td>
    </tr>
    <tr>
      <th>3</th>
      <td>anxiety</td>
      <td>4991</td>
    </tr>
    <tr>
      <th>4</th>
      <td>pain</td>
      <td>4744</td>
    </tr>
  </tbody>
</table>


E uma vez que terminamos nossa análise de Pandas, sempre podemos criar um novo objeto `Dataset` usando a função `Dataset.from_pandas()` da seguinte forma:


```py
from datasets import Dataset

freq_dataset = Dataset.from_pandas(frequencies)
freq_dataset
```

```python out
Dataset({
    features: ['condition', 'frequency'],
    num_rows: 819
})
```

<Tip>

✏️ **Experimente!** Calcule a classificação média por medicamento e armazene o resultado em um novo `Dataset`.

</Tip>

Isso encerra nosso tour pelas várias técnicas de pré-processamento disponíveis em 🤗 Datasets. Para completar a seção, vamos criar um conjunto de validação para preparar o conjunto de dados para treinar um classificador. Antes de fazer isso, vamos redefinir o formato de saída de `drug_dataset` de `"pandas"` para `"arrow"`:

```python
drug_dataset.reset_format()
```

## Criando um conjunto de validação

Embora tenhamos um conjunto de teste que poderíamos usar para avaliação, é uma boa prática deixar o conjunto de teste intocado e criar um conjunto de validação separado durante o desenvolvimento. Quando estiver satisfeito com o desempenho de seus modelos no conjunto de validação, você poderá fazer uma verificação final de sanidade no conjunto de teste. Esse processo ajuda a mitigar o risco de você se ajustar demais ao conjunto de teste e implantar um modelo que falha em dados do mundo real.

🤗 Datasets fornece uma função `Dataset.train_test_split()` que é baseada na famosa funcionalidade do `scikit-learn`. Vamos usá-lo para dividir nosso conjunto de treinamento em divisões `train` e `validation` (definimos o argumento `seed` para reprodutibilidade):

```py
drug_dataset_clean = drug_dataset["train"].train_test_split(train_size=0.8, seed=42)
# Rename the default "test" split to "validation"
drug_dataset_clean["validation"] = drug_dataset_clean.pop("test")
# Add the "test" set to our `DatasetDict`
drug_dataset_clean["test"] = drug_dataset["test"]
drug_dataset_clean
```

```python out
DatasetDict({
    train: Dataset({
        features: ['patient_id', 'drugName', 'condition', 'review', 'rating', 'date', 'usefulCount', 'review_length', 'review_clean'],
        num_rows: 110811
    })
    validation: Dataset({
        features: ['patient_id', 'drugName', 'condition', 'review', 'rating', 'date', 'usefulCount', 'review_length', 'review_clean'],
        num_rows: 27703
    })
    test: Dataset({
        features: ['patient_id', 'drugName', 'condition', 'review', 'rating', 'date', 'usefulCount', 'review_length', 'review_clean'],
        num_rows: 46108
    })
})
```

Ótimo, agora preparamos um conjunto de dados pronto para treinar alguns modelos! Na [seção 5](/course/chapter5/5), mostraremos como fazer upload de conjuntos de dados para o Hugging Face Hub, mas, por enquanto, vamos encerrar nossa análise analisando algumas maneiras de salvar conjuntos de dados em sua máquina local .

## Salvando um conjunto de dados

<Youtube id="blF9uxYcKHo"/>

Embora 🤗 Datasets armazene em cache todos os conjuntos de dados baixados e as operações realizadas nele, há momentos em que você deseja salvar um conjunto de dados em disco (por exemplo, caso o cache seja excluído). Conforme mostrado na tabela abaixo, 🤗 Datasets fornece três funções principais para salvar seu conjunto de dados em diferentes formatos:

| Formato dos dados | Função |
| :---------: | :-----------------------------------: |
|    Arrow    | `Dataset.save_to_disk()` |
|     CSV     |    `Dataset.to_csv()`    |
|    JSON     |   `Dataset.to_json()`    |

Por exemplo, vamos salvar nosso conjunto de dados limpo no formato Arrow:

```py
drug_dataset_clean.save_to_disk("drug-reviews")
```

Isso criará um diretório com a seguinte estrutura:

```
drug-reviews/
├── dataset_dict.json
├── test
│   ├── dataset.arrow
│   ├── dataset_info.json
│   └── state.json
├── train
│   ├── dataset.arrow
│   ├── dataset_info.json
│   ├── indices.arrow
│   └── state.json
└── validation
    ├── dataset.arrow
    ├── dataset_info.json
    ├── indices.arrow
    └── state.json
```

onde podemos ver que cada divisão está associada a sua própria tabela *dataset.arrow* e alguns metadados em *dataset_info.json* e *state.json*. Você pode pensar no formato Arrow como uma tabela sofisticada de colunas e linhas otimizada para criar aplicativos de alto desempenho que processam e transportam grandes conjuntos de dados.

Uma vez que o conjunto de dados é salvo, podemos carregá-lo usando a função `load_from_disk()` da seguinte forma:

```py
from datasets import load_from_disk

drug_dataset_reloaded = load_from_disk("drug-reviews")
drug_dataset_reloaded
```

```python out
DatasetDict({
    train: Dataset({
        features: ['patient_id', 'drugName', 'condition', 'review', 'rating', 'date', 'usefulCount', 'review_length'],
        num_rows: 110811
    })
    validation: Dataset({
        features: ['patient_id', 'drugName', 'condition', 'review', 'rating', 'date', 'usefulCount', 'review_length'],
        num_rows: 27703
    })
    test: Dataset({
        features: ['patient_id', 'drugName', 'condition', 'review', 'rating', 'date', 'usefulCount', 'review_length'],
        num_rows: 46108
    })
})
```

Para os formatos CSV e JSON, temos que armazenar cada divisão como um arquivo separado. Uma maneira de fazer isso é iterando as chaves e os valores no objeto `DatasetDict`:

```py
for split, dataset in drug_dataset_clean.items():
    dataset.to_json(f"drug-reviews-{split}.jsonl")
```

Isso salva cada divisão em [formato de linhas JSON](https://jsonlines.org), em que cada linha no conjunto de dados é armazenada como uma única linha de JSON. Veja como é o primeiro exemplo:

```py
!head -n 1 drug-reviews-train.jsonl
```

```python out
{"patient_id":141780,"drugName":"Escitalopram","condition":"depression","review":"\"I seemed to experience the regular side effects of LEXAPRO, insomnia, low sex drive, sleepiness during the day. I am taking it at night because my doctor said if it made me tired to take it at night. I assumed it would and started out taking it at night. Strange dreams, some pleasant. I was diagnosed with fibromyalgia. Seems to be helping with the pain. Have had anxiety and depression in my family, and have tried quite a few other medications that haven't worked. Only have been on it for two weeks but feel more positive in my mind, want to accomplish more in my life. Hopefully the side effects will dwindle away, worth it to stick with it from hearing others responses. Great medication.\"","rating":9.0,"date":"May 29, 2011","usefulCount":10,"review_length":125}
```

Podemos então usar as técnicas da [seção 2](/course/chapter5/2) para carregar os arquivos JSON da seguinte forma:

```py
data_files = {
    "train": "drug-reviews-train.jsonl",
    "validation": "drug-reviews-validation.jsonl",
    "test": "drug-reviews-test.jsonl",
}
drug_dataset_reloaded = load_dataset("json", data_files=data_files)
```

E é isso para nossa excursão em dados com 🤗 Datasets! Agora que temos um conjunto de dados limpo para treinar um modelo, aqui estão algumas ideias que você pode experimentar:

1. Use as técnicas do [Capítulo 3](/course/chapter3) para treinar um classificador que possa prever a condição do paciente com base na revisão do medicamento.
2. Use o pipeline `summarization` do [Capítulo 1](/course/chapter1) para gerar resumos das revisões.

A seguir, veremos como 🤗 Datasets pode permitir que você trabalhe com grandes conjuntos de dados sem explodir seu laptop!


<EditOnGithub source="https://github.com/huggingface/course/blob/main/chapters/pt/chapter5/3.mdx" />

### Busca semântica com o FAISS
https://huggingface.co/learn/course/pt/chapter5/6.md

# Busca semântica com o FAISS

{#if fw === 'pt'}

<CourseFloatingBanner chapter={5}
  classNames="absolute z-10 right-0 top-0"
  notebooks={[
    {label: "Google Colab", value: "https://colab.research.google.com/github/huggingface/notebooks/blob/master/course/pt/chapter5/section6_pt.ipynb"},
    {label: "Aws Studio", value: "https://studiolab.sagemaker.aws/import/github/huggingface/notebooks/blob/master/course/pt/chapter5/section6_pt.ipynb"},
]} />

{:else}

<CourseFloatingBanner chapter={5}
  classNames="absolute z-10 right-0 top-0"
  notebooks={[
    {label: "Google Colab", value: "https://colab.research.google.com/github/huggingface/notebooks/blob/master/course/pt/chapter5/section6_tf.ipynb"},
    {label: "Aws Studio", value: "https://studiolab.sagemaker.aws/import/github/huggingface/notebooks/blob/master/course/pt/chapter5/section6_tf.ipynb"},
]} />

{/if}

Na [seção 5](/course/chapter5/5), criamos um conjunto de dados de issues e comentários do GitHub do repositório 🤗 Datasets. Nesta seção, usaremos essas informações para construir um mecanismo de pesquisa que pode nos ajudar a encontrar respostas para nossas perguntas mais urgentes sobre a biblioteca!

<Youtube id="OATCgQtNX2o"/>

## Usando embeddings para pesquisa semântica

Como vimos no [Capítulo 1](/course/chapter1), os modelos de linguagem baseados em Transformer representam cada token em um intervalo de texto como um _vetor de incorporação_. Acontece que é possível "agrupar" as incorporações individuais para criar uma representação vetorial para frases inteiras, parágrafos ou (em alguns casos) documentos. Essas incorporações podem ser usadas para encontrar documentos semelhantes no corpus calculando a similaridade do produto escalar (ou alguma outra métrica de similaridade) entre cada incorporação e retornando os documentos com maior sobreposição.

Nesta seção, usaremos embeddings para desenvolver um mecanismo de pesquisa semântica. Esses mecanismos de pesquisa oferecem várias vantagens sobre as abordagens convencionais que se baseiam na correspondência de palavras-chave em uma consulta com os documentos.

<div class="flex justify-center">
<img class="block dark:hidden" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter5/semantic-search.svg" alt="Semantic search."/>
<img class="hidden dark:block" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter5/semantic-search-dark.svg" alt="Semantic search."/>
</div>

## Carregando e preparando o conjunto de dados

A primeira coisa que precisamos fazer é baixar nosso conjunto de dados de issues do GitHub, então vamos usar a biblioteca 🤗 Hub para resolver a URL onde nosso arquivo está armazenado no Hugging Face Hub:

```py
from huggingface_hub import hf_hub_url

data_files = hf_hub_url(
    repo_id="lewtun/github-issues",
    filename="datasets-issues-with-comments.jsonl",
    repo_type="dataset",
)
```

Com a URL armazenada em `data_files`, podemos carregar o conjunto de dados remoto usando o método apresentado na [seção 2](/course/chapter5/2):

```py
from datasets import load_dataset

issues_dataset = load_dataset("json", data_files=data_files, split="train")
issues_dataset
```

```python out
Dataset({
    features: ['url', 'repository_url', 'labels_url', 'comments_url', 'events_url', 'html_url', 'id', 'node_id', 'number', 'title', 'user', 'labels', 'state', 'locked', 'assignee', 'assignees', 'milestone', 'comments', 'created_at', 'updated_at', 'closed_at', 'author_association', 'active_lock_reason', 'pull_request', 'body', 'performed_via_github_app', 'is_pull_request'],
    num_rows: 2855
})
```

Aqui nós especificamos a divisão padrão `train` em `load_dataset()`, então ele retorna um `Dataset` em vez de um `DatasetDict`. A primeira ordem de negócios é filtrar os pull request, pois elas tendem a ser raramente usadas para responder a consultas de usuários e introduzirão ruído em nosso mecanismo de pesquisa. Como já deve ser familiar, podemos usar a função `Dataset.filter()` para excluir essas linhas em nosso conjunto de dados. Enquanto estamos nisso, também vamos filtrar as linhas sem comentários, pois elas não fornecem respostas às consultas dos usuários:

```py
issues_dataset = issues_dataset.filter(
    lambda x: (x["is_pull_request"] == False and len(x["comments"]) > 0)
)
issues_dataset
```

```python out
Dataset({
    features: ['url', 'repository_url', 'labels_url', 'comments_url', 'events_url', 'html_url', 'id', 'node_id', 'number', 'title', 'user', 'labels', 'state', 'locked', 'assignee', 'assignees', 'milestone', 'comments', 'created_at', 'updated_at', 'closed_at', 'author_association', 'active_lock_reason', 'pull_request', 'body', 'performed_via_github_app', 'is_pull_request'],
    num_rows: 771
})
```
Podemos ver que há muitas colunas em nosso conjunto de dados, a maioria das quais não precisamos para construir nosso mecanismo de pesquisa. De uma perspectiva de pesquisa, as colunas mais informativas são `title`, `body` e `comments`, enquanto `html_url` nos fornece um link de volta para a issue de origem. Vamos usar a função `Dataset.remove_columns()` para descartar o resto:

```py
columns = issues_dataset.column_names
columns_to_keep = ["title", "body", "html_url", "comments"]
columns_to_remove = set(columns_to_keep).symmetric_difference(columns)
issues_dataset = issues_dataset.remove_columns(columns_to_remove)
issues_dataset
```

```python out
Dataset({
    features: ['html_url', 'title', 'comments', 'body'],
    num_rows: 771
})
```

Para criar nossos embeddings, aumentaremos cada comentário com o título e o corpo da issue, pois esses campos geralmente incluem informações contextuais úteis. Como nossa coluna `comments` é atualmente uma lista de comentários para cada issue, precisamos "explodir" a coluna para que cada linha consista em uma tupla `(html_url, title, body, comment)`. No Pandas podemos fazer isso com a função [`DataFrame.explode()`](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.explode.html), que cria uma nova linha para cada elemento em uma coluna semelhante a uma lista, enquanto replica todos os outros valores de coluna. Para ver isso em ação, vamos primeiro mudar para o formato `DataFrame` do Pandas:

```py
issues_dataset.set_format("pandas")
df = issues_dataset[:]
```

Se inspecionarmos a primeira linha neste `DataFrame`, podemos ver que há quatro comentários associados a esta issue:

```py
df["comments"][0].tolist()
```

```python out
['the bug code locate in ：\r\n    if data_args.task_name is not None:\r\n        # Downloading and loading a dataset from the hub.\r\n        datasets = load_dataset("glue", data_args.task_name, cache_dir=model_args.cache_dir)',
 'Hi @jinec,\r\n\r\nFrom time to time we get this kind of `ConnectionError` coming from the github.com website: https://raw.githubusercontent.com\r\n\r\nNormally, it should work if you wait a little and then retry.\r\n\r\nCould you please confirm if the problem persists?',
 'cannot connect，even by Web browser，please check that  there is some  problems。',
 'I can access https://raw.githubusercontent.com/huggingface/datasets/1.7.0/datasets/glue/glue.py without problem...']
```

Quando explodimos `df`, esperamos obter uma linha para cada um desses comentários. Vamos verificar se é o caso:

```py
comments_df = df.explode("comments", ignore_index=True)
comments_df.head(4)
```

<table border="1" class="dataframe" style="table-layout: fixed; word-wrap:break-word; width: 100%;">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>html_url</th>
      <th>title</th>
      <th>comments</th>
      <th>body</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>https://github.com/huggingface/datasets/issues/2787</td>
      <td>ConnectionError: Couldn't reach https://raw.githubusercontent.com</td>
      <td>the bug code locate in ：\r\n    if data_args.task_name is not None...</td>
      <td>Hello,\r\nI am trying to run run_glue.py and it gives me this error...</td>
    </tr>
    <tr>
      <th>1</th>
      <td>https://github.com/huggingface/datasets/issues/2787</td>
      <td>ConnectionError: Couldn't reach https://raw.githubusercontent.com</td>
      <td>Hi @jinec,\r\n\r\nFrom time to time we get this kind of `ConnectionError` coming from the github.com website: https://raw.githubusercontent.com...</td>
      <td>Hello,\r\nI am trying to run run_glue.py and it gives me this error...</td>
    </tr>
    <tr>
      <th>2</th>
      <td>https://github.com/huggingface/datasets/issues/2787</td>
      <td>ConnectionError: Couldn't reach https://raw.githubusercontent.com</td>
      <td>cannot connect，even by Web browser，please check that  there is some  problems。</td>
      <td>Hello,\r\nI am trying to run run_glue.py and it gives me this error...</td>
    </tr>
    <tr>
      <th>3</th>
      <td>https://github.com/huggingface/datasets/issues/2787</td>
      <td>ConnectionError: Couldn't reach https://raw.githubusercontent.com</td>
      <td>I can access https://raw.githubusercontent.com/huggingface/datasets/1.7.0/datasets/glue/glue.py without problem...</td>
      <td>Hello,\r\nI am trying to run run_glue.py and it gives me this error...</td>
    </tr>
  </tbody>
</table>

Ótimo, podemos ver que as linhas foram replicadas, com a coluna `comments` contendo os comentários individuais! Agora que terminamos com o Pandas, podemos voltar rapidamente para um `Dataset` carregando o `DataFrame` na memória

```py
from datasets import Dataset

comments_dataset = Dataset.from_pandas(comments_df)
comments_dataset
```

```python out
Dataset({
    features: ['html_url', 'title', 'comments', 'body'],
    num_rows: 2842
})
```

Ok, isso nos deu alguns milhares de comentários para trabalhar!

<Tip>

✏️ **Experimente!** Veja se você pode usar `Dataset.map()` para explodir a coluna `comments` de `issues_dataset` _sem_ recorrer ao uso de Pandas. Isso é um pouco complicado; você pode achar útil para esta tarefa a seção ["Mapeamento em lote"](https://huggingface.co/docs/datasets/v1.12.1/about_map_batch#batch-mapping) da documentação do 🤗 Dataset.

</Tip>

Agora que temos um comentário por linha, vamos criar uma nova coluna `comments_length` que contém o número de palavras por comentário:

```py
comments_dataset = comments_dataset.map(
    lambda x: {"comment_length": len(x["comments"].split())}
)
```

Podemos usar essa nova coluna para filtrar comentários curtos, que normalmente incluem coisas como "cc @lewtun" ou "Obrigado!" que não são relevantes para o nosso motor de busca. Não há um número preciso para selecionar o filtro, mas cerca de 15 palavras parece um bom começo:

```py
comments_dataset = comments_dataset.filter(lambda x: x["comment_length"] > 15)
comments_dataset
```

```python out
Dataset({
    features: ['html_url', 'title', 'comments', 'body', 'comment_length'],
    num_rows: 2098
})
```

Depois de limpar um pouco nosso conjunto de dados, vamos concatenar o título, a descrição e os comentários da issue em uma nova coluna `text`. Como de costume, escreveremos uma função simples que podemos passar para `Dataset.map()`:

```py
def concatenate_text(examples):
    return {
        "text": examples["title"]
        + " \n "
        + examples["body"]
        + " \n "
        + examples["comments"]
    }


comments_dataset = comments_dataset.map(concatenate_text)
```

Finalmente estamos prontos para criar alguns embeddings! Vamos dar uma olhada.

## Criando embeddings de texto

Vimos no [Capítulo 2](/course/chapter2) que podemos obter tokens embeddings usando a classe `AutoModel`. Tudo o que precisamos fazer é escolher um checkpoint adequado para carregar o modelo. Felizmente, existe uma biblioteca chamada `sentence-transformers` dedicada à criação de embeddings. Conforme descrito na [documentação da biblioteca](https://www.sbert.net/examples/applications/semantic-search/README.html#symmetric-vs-asymmetric-semantic-search), nosso caso de uso é um exemplo de _asymmetric semantic search_ porque temos uma consulta curta cuja resposta gostaríamos de encontrar em um documento mais longo, como um comentário da issue. A útil [tabela de visão geral do modelo](https://www.sbert.net/docs/pretrained_models.html#model-overview) na documentação indica que o checkpoint `multi-qa-mpnet-base-dot-v1` tem o melhor desempenho para pesquisa semântica, então usaremos isso para nosso aplicativo. Também carregaremos o tokenizer usando o mesmo checkpoint:

{#if fw === 'pt'}

```py
from transformers import AutoTokenizer, AutoModel

model_ckpt = "sentence-transformers/multi-qa-mpnet-base-dot-v1"
tokenizer = AutoTokenizer.from_pretrained(model_ckpt)
model = AutoModel.from_pretrained(model_ckpt)
```

Para acelerar o processo de embedding, é útil colocar o modelo e as entradas em um dispositivo GPU, então vamos fazer isso agora:

```py
import torch

device = torch.device("cuda")
model.to(device)
```

{:else}

```py
from transformers import AutoTokenizer, TFAutoModel

model_ckpt = "sentence-transformers/multi-qa-mpnet-base-dot-v1"
tokenizer = AutoTokenizer.from_pretrained(model_ckpt)
model = TFAutoModel.from_pretrained(model_ckpt, from_pt=True)
```

Observe que definimos `from_pt=True` como um argumento do método `from_pretrained()`. Isso ocorre porque o checkpoint `multi-qa-mpnet-base-dot-v1` só tem pesos PyTorch, portanto, definir `from_pt=True` irá convertê-los automaticamente para o formato TensorFlow para nós. Como você pode ver, é muito simples alternar entre frameworks no 🤗 Transformers!

{/if}

Como mencionamos anteriormente, gostaríamos de representar cada entrada em nosso corpus de issues do GitHub como um único vetor, portanto, precisamos "pool" ou calcular a média de nossas incorporações de token de alguma forma. Uma abordagem popular é realizar *CLS pooling* nas saídas do nosso modelo, onde simplesmente coletamos o último estado oculto para o token especial `[CLS]`. A função a seguir faz o truque para nós:

```py
def cls_pooling(model_output):
    return model_output.last_hidden_state[:, 0]
```

Em seguida, criaremos uma função auxiliar que tokenizará uma lista de documentos, colocará os tensores na GPU, os alimentará no modelo e, finalmente, aplicará o agrupamento CLS às saídas:

{#if fw === 'pt'}

```py
def get_embeddings(text_list):
    encoded_input = tokenizer(
        text_list, padding=True, truncation=True, return_tensors="pt"
    )
    encoded_input = {k: v.to(device) for k, v in encoded_input.items()}
    model_output = model(**encoded_input)
    return cls_pooling(model_output)
```

Podemos testar o funcionamento da função alimentando-a com a primeira entrada de texto em nosso corpus e inspecionando a forma de saída:

```py
embedding = get_embeddings(comments_dataset["text"][0])
embedding.shape
```

```python out
torch.Size([1, 768])
```

Ótimo, convertemos a primeira entrada em nosso corpus em um vetor de 768 dimensões! Podemos usar `Dataset.map()` para aplicar nossa função `get_embeddings()` a cada linha em nosso corpus, então vamos criar uma nova coluna `embeddings` da seguinte forma:

```py
embeddings_dataset = comments_dataset.map(
    lambda x: {"embeddings": get_embeddings(x["text"]).detach().cpu().numpy()[0]}
)
```

{:else}

```py
def get_embeddings(text_list):
    encoded_input = tokenizer(
        text_list, padding=True, truncation=True, return_tensors="tf"
    )
    encoded_input = {k: v for k, v in encoded_input.items()}
    model_output = model(**encoded_input)
    return cls_pooling(model_output)
```

Podemos testar o funcionamento da função alimentando-a com a primeira entrada de texto em nosso corpus e inspecionando a forma de saída:

```py
embedding = get_embeddings(comments_dataset["text"][0])
embedding.shape
```

```python out
TensorShape([1, 768])
```

Ótimo, convertemos a primeira entrada em nosso corpus em um vetor de 768 dimensões! Podemos usar `Dataset.map()` para aplicar nossa função `get_embeddings()` a cada linha em nosso corpus, então vamos criar uma nova coluna `embeddings` da seguinte forma:

```py
embeddings_dataset = comments_dataset.map(
    lambda x: {"embeddings": get_embeddings(x["text"]).numpy()[0]}
)
```

{/if}

Observe que convertemos os embeddings em arrays NumPy -- isso porque 🤗 Datasets requer esse formato quando tentamos indexá-los com FAISS, o que faremos a seguir.


## Usando FAISS para busca de similaridade

Agora que temos um conjunto de dados de embeddings, precisamos de alguma maneira de pesquisá-los. Para fazer isso, usaremos uma estrutura de dados especial em 🤗 Datasets chamada _FAISS index_. [FAISS](https://faiss.ai/) (abreviação de Facebook AI Similarity Search) é uma biblioteca que fornece algoritmos eficientes para pesquisar rapidamente e agrupar vetores de incorporação.

A idéia básica por trás do FAISS é criar uma estrutura de dados especial chamada _index_ que permite descobrir quais embeddings são semelhantes a um embedding de entrada. Criar um índice FAISS em 🤗 Datasets é simples -- usamos a função `Dataset.add_faiss_index()` e especificamos qual coluna do nosso conjunto de dados gostaríamos de indexar:

```py
embeddings_dataset.add_faiss_index(column="embeddings")
```

Agora podemos realizar consultas neste índice fazendo uma pesquisa do vizinho mais próximo com a função `Dataset.get_nearest_examples()`. Vamos testar isso primeiro incorporando uma pergunta da seguinte forma:


{#if fw === 'pt'}

```py
question = "How can I load a dataset offline?"
question_embedding = get_embeddings([question]).cpu().detach().numpy()
question_embedding.shape
```

```python out
torch.Size([1, 768])
```

{:else}

```py
question = "How can I load a dataset offline?"
question_embedding = get_embeddings([question]).numpy()
question_embedding.shape
```

```python out
(1, 768)
```

{/if}

Assim como com os documentos, agora temos um vetor de 768 dimensões representando a consulta, que podemos comparar com todo o corpus para encontrar os embeddings mais semelhantes:

```py
scores, samples = embeddings_dataset.get_nearest_examples(
    "embeddings", question_embedding, k=5
)
```

A função `Dataset.get_nearest_examples()` retorna uma tupla de pontuações que classificam a sobreposição entre a consulta e o documento e um conjunto correspondente de amostras (aqui, as 5 melhores correspondências). Vamos coletá-los em um `pandas.DataFrame` para que possamos classificá-los facilmente:

```py
import pandas as pd

samples_df = pd.DataFrame.from_dict(samples)
samples_df["scores"] = scores
samples_df.sort_values("scores", ascending=False, inplace=True)
```

Agora podemos iterar nas primeiras linhas para ver como nossa consulta correspondeu aos comentários disponíveis:

```py
for _, row in samples_df.iterrows():
    print(f"COMMENT: {row.comments}")
    print(f"SCORE: {row.scores}")
    print(f"TITLE: {row.title}")
    print(f"URL: {row.html_url}")
    print("=" * 50)
    print()
```

```python out
"""
COMMENT: Requiring online connection is a deal breaker in some cases unfortunately so it'd be great if offline mode is added similar to how `transformers` loads models offline fine.

@mandubian's second bullet point suggests that there's a workaround allowing you to use your offline (custom?) dataset with `datasets`. Could you please elaborate on how that should look like?
SCORE: 25.505046844482422
TITLE: Discussion using datasets in offline mode
URL: https://github.com/huggingface/datasets/issues/824
==================================================

COMMENT: The local dataset builders (csv, text , json and pandas) are now part of the `datasets` package since #1726 :)
You can now use them offline
\`\`\`python
datasets = load_dataset("text", data_files=data_files)
\`\`\`

We'll do a new release soon
SCORE: 24.555509567260742
TITLE: Discussion using datasets in offline mode
URL: https://github.com/huggingface/datasets/issues/824
==================================================

COMMENT: I opened a PR that allows to reload modules that have already been loaded once even if there's no internet.

Let me know if you know other ways that can make the offline mode experience better. I'd be happy to add them :)

I already note the "freeze" modules option, to prevent local modules updates. It would be a cool feature.

----------

> @mandubian's second bullet point suggests that there's a workaround allowing you to use your offline (custom?) dataset with `datasets`. Could you please elaborate on how that should look like?

Indeed `load_dataset` allows to load remote dataset script (squad, glue, etc.) but also you own local ones.
For example if you have a dataset script at `./my_dataset/my_dataset.py` then you can do
\`\`\`python
load_dataset("./my_dataset")
\`\`\`
and the dataset script will generate your dataset once and for all.

----------

About I'm looking into having `csv`, `json`, `text`, `pandas` dataset builders already included in the `datasets` package, so that they are available offline by default, as opposed to the other datasets that require the script to be downloaded.
cf #1724
SCORE: 24.14896583557129
TITLE: Discussion using datasets in offline mode
URL: https://github.com/huggingface/datasets/issues/824
==================================================

COMMENT: > here is my way to load a dataset offline, but it **requires** an online machine
>
> 1. (online machine)
>
> ```
>
> import datasets
>
> data = datasets.load_dataset(...)
>
> data.save_to_disk(/YOUR/DATASET/DIR)
>
> ```
>
> 2. copy the dir from online to the offline machine
>
> 3. (offline machine)
>
> ```
>
> import datasets
>
> data = datasets.load_from_disk(/SAVED/DATA/DIR)
>
> ```
>
>
>
> HTH.


SCORE: 22.893993377685547
TITLE: Discussion using datasets in offline mode
URL: https://github.com/huggingface/datasets/issues/824
==================================================

COMMENT: here is my way to load a dataset offline, but it **requires** an online machine
1. (online machine)
\`\`\`
import datasets
data = datasets.load_dataset(...)
data.save_to_disk(/YOUR/DATASET/DIR)
\`\`\`
2. copy the dir from online to the offline machine
3. (offline machine)
\`\`\`
import datasets
data = datasets.load_from_disk(/SAVED/DATA/DIR)
\`\`\`

HTH.
SCORE: 22.406635284423828
TITLE: Discussion using datasets in offline mode
URL: https://github.com/huggingface/datasets/issues/824
==================================================
"""
```

Nada mal! Nosso segundo resultado parece corresponder à consulta.

<Tip>

✏️ **Experimente!** Crie sua própria consulta e veja se consegue encontrar uma resposta nos documentos recuperados. Você pode ter que aumentar o parâmetro `k` em `Dataset.get_nearest_examples()` para ampliar a pesquisa.

</Tip>

<EditOnGithub source="https://github.com/huggingface/course/blob/main/chapters/pt/chapter5/6.mdx" />

### Questionário de fim de capítulo
https://huggingface.co/learn/course/pt/chapter5/8.md

# Questionário de fim de capítulo

<CourseFloatingBanner
    chapter={5}
    classNames="absolute z-10 right-0 top-0"
/>
Este capítulo cobriu muita coisa! Não se preocupe se você não entendeu todos os detalhes; os próximos capítulos o ajudarão a entender como as coisas funcionam.

Antes de prosseguir, vamos testar o que você aprendeu neste capítulo.

### 1. A função `load_dataset()` em 🤗 Datasets permite carregar um dataset de qual dos seguintes locais?

<Question
	choices={[
		{
			text: "Localmente, por exemplo no seu laptop",
			explain: "Correto! Você pode passar os caminhos dos arquivos locais para o argumento <code>data_files</code> de <code>load_dataset()</code> para carregar conjuntos de dados localmente.",
			correct: true
		},
		{
			text: "Do Hugging Face Hub",
			explain: "Correto! Você pode carregar conjuntos de dados no Hub fornecendo o ID do conjunto de dados, por exemplo, <code>load_dataset('emotion')</code>.",
			correct: true
		},
		{
			text: "De um servidor remoto",
			explain: "Correto! Você pode passar URLs para o argumento <code>data_files</code> de <code>load_dataset()</code> para carregar arquivos remotos.",
			correct: true
		},
	]}
/>
### 2. Suponha que você carregue uma das tarefas GLUE da seguinte forma:

```py
from datasets import load_dataset

dataset = load_dataset("glue", "mrpc", split="train")
```

Qual dos seguintes comandos produzirá uma amostra aleatória de 50 elementos do `conjunto de dados`?

<Question
	choices={[
		{
			text: "<code>dataset.sample(50)</code>",
			explain: "Isso está incorreto -- não há método <code>Dataset.sample()</code>."
		},
		{
			text: "<code>dataset.shuffle().select(range(50))</code>",
			explain: "Correto! Como você viu neste capítulo, você primeiro embaralha o conjunto de dados e depois seleciona as amostras dele.",
			correct: true
		},
		{
			text: "<code>dataset.select(range(50)).shuffle()</code>",
			explain: "Isso está incorreto - embora o código seja executado, ele embaralha apenas os primeiros 50 elementos do conjunto de dados."
		}
	]}
/>

### 3. Suponha que você tenha um conjunto de dados sobre animais domésticos chamado `pets_dataset`, que tem uma coluna `name` que denota o nome de cada animal. Qual das seguintes abordagens permitiria filtrar o conjunto de dados para todos os animais de estimação cujos nomes começam com a letra "L"?

<Question
	choices={[
		{
			text: "<code>pets_dataset.filter(lambda x : x['name'].startswith('L'))</code>",
			explain: "Correto! Usar uma função lambda do Python para esses filtros rápidos é uma ótima ideia. Você consegue pensar em outra solução?",
			correct: true
		},
		{
			text: "<code>pets_dataset.filter(lambda x['name'].startswith('L'))</code>",
			explain: "Isso está incorreto -- uma função lambda assume a forma geral <code>lambda *arguments* : *expression*</code>, então você precisa fornecer argumentos neste caso."
		},
		{
			text: "Criar uma função assim <code>def filter_names(x): return x['name'].startswith('L')</code> e executa-la <code>pets_dataset.filter(filter_names)</code>.",
			explain: "Correto! Assim como com <code>Dataset.map()</code>, você pode passar funções explícitas para <code>Dataset.filter()</code>. Isso é útil quando você tem alguma lógica complexa que não é adequado para uma função lambda curta. Qual das outras soluções funcionaria?",
			correct: true
		}
	]}
/>

### 4. O que é mapeamento de memória?

<Question
	choices={[
		{
			text: "Um mapeamento entre CPU e GPU RAM",
			explain: "Não é isso - tente novamente!",
		},
		{
			text: "Um mapeamento entre RAM e armazenamento do sistema de arquivos",
			explain: "Correto! Os 🤗 Datasets tratam cada conjunto de dados como um arquivo mapeado na memória. Isso permite que a biblioteca acesse e opere em elementos do conjunto de dados sem precisar carregá-lo totalmente na memória.",
			correct: true
		},
		{
			text: "Um mapeamento entre dois arquivos no cache 🤗 Datasets",
			explain: "Isto não está correto - tente novamente!"
		}
	]}
/>

### 5. Quais dos seguintes são os principais benefícios do mapeamento de memória?

<Question
	choices={[
		{
			text: "Acessar arquivos mapeados na memória é mais rápido do que ler ou gravar no disco.",
			explain: "Correto! Isso permite que 🤗 Datasets sejam extremamente rápidos. Mas esse não é o único benefício.",
			correct: true
		},
		{
			text: "As aplicações podem acessar segmentos de dados em um arquivo extremamente grande sem precisar ler o arquivo inteiro na RAM primeiro.",
			explain: "Correto! Isso permite que 🤗 Datasets carregue conjuntos de dados de vários gigabytes em seu laptop sem explodir sua CPU. Que outra vantagem o mapeamento de memória oferece?",
			correct: true
		},
		{
			text: "Consome menos energia, então sua bateria dura mais.",
			explain: "Isto não está correto - tente novamente!"
		}
	]}
/>

### 6. Por que o código a seguir falha?

```py
from datasets import load_dataset

dataset = load_dataset("allocine", streaming=True, split="train")
dataset[0]
```

<Question
	choices={[
		{
			text: "Ele tenta fazer stream de um conjunto de dados grande demais para caber na RAM.",
			explain: "Isso não está correto - conjuntos de dados de streaming são descompactados em tempo real e você pode processar conjuntos de dados de terabytes com muito pouca RAM!",
		},
		{
			text: "Ele tenta acessar um <code>IterableDataset</code>.",
			explain: "Correto! Um <code>IterableDataset</code> é um gerador, não um contêiner, então você deve acessar seus elementos usando <code>next(iter(dataset))</code>.",
			correct: true
		},
		{
			text: "O conjunto de dados <code>allocine</code> não tem uma divisão <code>train</code>.",
			explain: "Isso está incorreto - confira o cartão de conjunto de dados [<code>allocine</code>](https://huggingface.co/datasets/allocine) no Hub para ver quais divisões ele contém."
		}
	]}
/>

### 7. Quais dos seguintes são os principais benefícios de criar um cartão de conjunto de dados?

<Question
	choices={[
		{
			text: "Ele fornece informações sobre o uso pretendido e as tarefas suportadas do conjunto de dados para que outras pessoas na comunidade possam tomar uma decisão informada sobre o uso.",
			explain: "Correto! Conjuntos de dados não documentados podem ser usados para treinar modelos que podem não refletir as intenções dos criadores do conjunto de dados ou podem produzir modelos cujo status legal é obscuro se forem treinados em dados que violam restrições de privacidade ou licenciamento. Este não é o único benefício, no entanto!",
			correct : true
		},
		{
			text: "Ajuda a chamar a atenção para os preconceitos que estão presentes em um corpus.",
			explain: "Correto! Quase todos os conjuntos de dados têm algum tipo de viés, o que pode produzir consequências negativas em contrapartida. Estar ciente disso ajuda os criadores de modelos a entender como lidar com os vieses. Em que mais os cartões de conjunto de dados ajudam?",
			correct : true
		},
		{
			text: "Melhora as chances de que outras pessoas da comunidade usem meu conjunto de dados.",
			explain: "Correto! Um cartão de conjunto de dados bem escrito tenderá a aumentar o uso de seu precioso conjunto de dados. Que outros benefícios ele oferece?",
			correct: true
		},
	]}
/>

### 8. O que é pesquisa semântica?

<Question
	choices={[
		{
			text: "Uma maneira de pesquisar correspondências exatas entre as palavras em uma consulta e os documentos em um corpus",
			explain: "Isso está incorreto - esse tipo de pesquisa é chamado de *pesquisa léxica* e é o que você normalmente vê nos mecanismos de pesquisa tradicionais."
		},
		{
			text: "Uma maneira de pesquisar documentos correspondentes entendendo o significado contextual de uma consulta",
			explain: "Correto! A pesquisa semântica usa vetores incorporados para representar consultas e documentos e usa uma métrica de similaridade para medir a quantidade de sobreposição entre eles. De que outra forma você poderia descrevê-la?",
			correct: true
		},
		{
			text: "Uma maneira de melhorar a precisão da pesquisa",
			explain: "Correto! Os mecanismos de pesquisa semântica podem capturar a intenção de uma consulta muito melhor do que a correspondência de palavras-chave e normalmente recuperam documentos com maior precisão. Mas essa não é a única resposta certa - o que mais a pesquisa semântica oferece?",
			correct: true
		}
	]}
/>

### 9. Para pesquisa semântica assimétrica, você geralmente tem:

<Question
	choices={[
		{
			text: "Uma consulta curta e um parágrafo mais longo que responde à consulta",
			explain: "Correto!",
			correct : true
		},
		{
			text: "Consultas e parágrafos com aproximadamente o mesmo tamanho",
			explain: "Este é realmente um exemplo de pesquisa semântica simétrica - tente novamente!"
		},
		{
			text: "Uma consulta longa e um parágrafo mais curto que responde à consulta",
			explain: "Isso está incorreto - tente novamente!"
		}
	]}
/>

### 10. Posso usar 🤗 Datasets para carregar dados para uso em outros domínios, como processamento de fala (audios)?

<Question
	choices={[
		{
			text: "Não",
			explain: "Isso está incorreto -- 🤗 Datasets atualmente suporta dados tabulares, áudio e de visão computacional. Confira o <a href='https://huggingface.co/datasets/mnist'>conjunto de dados MNIST</a> no Hub para um exemplo de visão computacional."
		},
		{
			text: "Sim",
			explain: "Correto! Confira os desenvolvimentos interessantes com fala e visão na biblioteca 🤗 Transformers para ver como 🤗 Datasets é usado nesses domínios.",
			correct : true
		},
	]}
/>


<EditOnGithub source="https://github.com/huggingface/course/blob/main/chapters/pt/chapter5/8.mdx" />

### Big data? 🤗 Datasets ao resgate
https://huggingface.co/learn/course/pt/chapter5/4.md

# Big data? 🤗 Datasets ao resgate

<CourseFloatingBanner chapter={5}
  classNames="absolute z-10 right-0 top-0"
  notebooks={[
    {label: "Google Colab", value: "https://colab.research.google.com/github/huggingface/notebooks/blob/master/course/pt/chapter5/section4.ipynb"},
    {label: "Aws Studio", value: "https://studiolab.sagemaker.aws/import/github/huggingface/notebooks/blob/master/course/pt/chapter5/section4.ipynb"},
]} />


Hoje em dia, não é incomum encontrar-se trabalhando com conjuntos de dados de vários gigabytes, especialmente se você planeja pré-treinar um transformer como BERT ou GPT-2 do zero. Nesses casos, até mesmo _carregar_ os dados pode ser um desafio. Por exemplo, o corpus WebText usado para pré-treinar o GPT-2 consiste em mais de 8 milhões de documentos e 40 GB de texto - carregar isso na RAM do seu laptop provavelmente lhe causará um ataque cardíaco!

Felizmente, 🤗 Datasets foram projetados para superar essas limitações. Ele libera você de problemas de gerenciamento de memória tratando conjuntos de dados como arquivos _memory-mapped_ e de limites de disco rígido por _streaming_ das entradas em um corpus.

<Youtube id="JwISwTCPPWo"/>

Nesta seção, exploraremos esses recursos de 🤗 Conjuntos de dados com um enorme corpus de 825 GB conhecido como [the Pile](https://pile.eleuther.ai). Vamos começar!

## O que é the Pile?

O `The Pile` é um corpus de texto em inglês que foi criado por [EleutherAI](https://www.eleuther.ai) para treinar modelos de linguagem em larga escala. Ele inclui uma gama diversificada de conjuntos de dados, abrangendo artigos científicos, repositórios de código do GitHub e texto da web filtrado. O corpus de treinamento está disponível em [blocos de 14 GB](https://the-eye.eu/public/AI/pile/), e você também pode baixar vários dos [componentes individuais](https://the-eye.eu/public/AI/pile_preliminary_components/). Vamos começar dando uma olhada no conjunto de dados PubMed Abstracts, que é um corpus de resumos de 15 milhões de publicações biomédicas no [PubMed](https://pubmed.ncbi.nlm.nih.gov/). O conjunto de dados está em [formato JSON Lines](https://jsonlines.org) e é compactado usando a biblioteca `zstandard`, então primeiro precisamos instalá-lo:

```py
!pip install zstandard
```

Em seguida, podemos carregar o conjunto de dados usando o método para arquivos remotos que aprendemos na [seção 2](/course/chapter5/2):

```py
from datasets import load_dataset

# This takes a few minutes to run, so go grab a tea or coffee while you wait :)
data_files = "https://the-eye.eu/public/AI/pile_preliminary_components/PUBMED_title_abstracts_2019_baseline.jsonl.zst"
pubmed_dataset = load_dataset("json", data_files=data_files, split="train")
pubmed_dataset
```

```python out
Dataset({
    features: ['meta', 'text'],
    num_rows: 15518009
})
```

Podemos ver que há 15.518.009 linhas e 2 colunas em nosso conjunto de dados - isso é muito!

<Tip>

✎ Por padrão, 🤗 Datasets descompactará os arquivos necessários para carregar um dataset. Se você quiser preservar espaço no disco rígido, você pode passar `DownloadConfig(delete_extracted=True)` para o argumento `download_config` de `load_dataset()`. Consulte a [documentação](https://huggingface.co/docs/datasets/package_reference/builder_classes#datasets.DownloadConfig) para obter mais detalhes.

</Tip>

Vamos inspecionar o conteúdo do primeiro exemplo:

```py
pubmed_dataset[0]
```

```python out
{'meta': {'pmid': 11409574, 'language': 'eng'},
 'text': 'Epidemiology of hypoxaemia in children with acute lower respiratory infection.\nTo determine the prevalence of hypoxaemia in children aged under 5 years suffering acute lower respiratory infections (ALRI), the risk factors for hypoxaemia in children under 5 years of age with ALRI, and the association of hypoxaemia with an increased risk of dying in children of the same age ...'}
```

Ok, isso parece o resumo de um artigo médico. Agora vamos ver quanta RAM usamos para carregar o conjunto de dados!

## A magia do mapeamento de memória

Uma maneira simples de medir o uso de memória em Python é com a biblioteca [`psutil`](https://psutil.readthedocs.io/en/latest/), que pode ser instalada com `pip` da seguinte forma:

```python
!pip install psutil
```

Ele fornece uma classe `Process` que nos permite verificar o uso de memória do processo atual da seguinte forma:

```py
import psutil

# Process.memory_info is expressed in bytes, so convert to megabytes
print(f"RAM used: {psutil.Process().memory_info().rss / (1024 * 1024):.2f} MB")
```

```python out
RAM used: 5678.33 MB
```

Aqui o atributo `rss` refere-se ao _tamanho do conjunto residente_, que é a fração de memória que um processo ocupa na RAM. Essa medida também inclui a memória usada pelo interpretador Python e as bibliotecas que carregamos, portanto, a quantidade real de memória usada para carregar o conjunto de dados é um pouco menor. Para comparação, vamos ver o tamanho do conjunto de dados no disco, usando o atributo `dataset_size`. Como o resultado é expresso em bytes como antes, precisamos convertê-lo manualmente para gigabytes:

```py
print(f"Number of files in dataset : {pubmed_dataset.dataset_size}")
size_gb = pubmed_dataset.dataset_size / (1024**3)
print(f"Dataset size (cache file) : {size_gb:.2f} GB")
```

```python out
Number of files in dataset : 20979437051
Dataset size (cache file) : 19.54 GB
```

Legal -- apesar de ter quase 20 GB de tamanho, podemos carregar e acessar o conjunto de dados com muito menos RAM!

<Tip>

✏️ **Experimente!** Escolha um dos [subconjuntos](https://the-eye.eu/public/AI/pile_preliminary_components/) da `The Pile` que é maior que a RAM do seu laptop ou desktop, carregue com 🤗 Datasets e meça a quantidade de RAM usada. Observe que, para obter uma medição precisa, você desejará fazer isso em um novo processo. Você pode encontrar os tamanhos descompactados de cada subconjunto na Tabela 1 do [artigo do `The Pile`](https://arxiv.org/abs/2101.00027).

</Tip>

Se você estiver familiarizado com Pandas, esse resultado pode ser uma surpresa por causa da famosa [regra de ouro] de Wes Kinney (https://wesmckinney.com/blog/apache-arrow-pandas-internals/) de que você normalmente precisa de 5 para 10 vezes mais RAM do que o tamanho do seu conjunto de dados. Então, como 🤗 Datasets resolve esse problema de gerenciamento de memória? 🤗 Os conjuntos de dados tratam cada conjunto de dados como um [arquivo mapeado em memória](https://en.wikipedia.org/wiki/Memory-mapped_file), que fornece um mapeamento entre RAM e armazenamento do sistema de arquivos que permite que a biblioteca acesse e opere em elementos do conjunto de dados sem precisar carregá-lo totalmente na memória.

Arquivos mapeados em memória também podem ser compartilhados em vários processos, o que permite que métodos como `Dataset.map()` sejam paralelizados sem a necessidade de mover ou copiar o conjunto de dados. Sob o capô, esses recursos são todos realizados pelo formato de memória [Apache Arrow](https://arrow.apache.org) e [`pyarrow`](https://arrow.apache.org/docs/python/index.html), que tornam o carregamento e o processamento de dados extremamente rápidos. (Para mais detalhes sobre o Apache Arrow e comparações com o Pandas, confira [post do blog de Dejan Simic](https://towardsdatascience.com/apache-arrow-read-dataframe-with-zero-memory-69634092b1a).) Para ver isso em ação, vamos executar um pequeno teste de velocidade iterando sobre todos os elementos no conjunto de dados PubMed Abstracts:

```py
import timeit

code_snippet = """batch_size = 1000

for idx in range(0, len(pubmed_dataset), batch_size):
    _ = pubmed_dataset[idx:idx + batch_size]
"""

time = timeit.timeit(stmt=code_snippet, number=1, globals=globals())
print(
    f"Iterated over {len(pubmed_dataset)} examples (about {size_gb:.1f} GB) in "
    f"{time:.1f}s, i.e. {size_gb/time:.3f} GB/s"
)
```

```python out
'Iterated over 15518009 examples (about 19.5 GB) in 64.2s, i.e. 0.304 GB/s'
```

Aqui usamos o módulo `timeit` do Python para medir o tempo de execução do `code_snippet`. Normalmente, você poderá iterar em um conjunto de dados a uma velocidade de alguns décimos de GB/s a vários GB/s. Isso funciona muito bem para a grande maioria dos aplicativos, mas às vezes você terá que trabalhar com um conjunto de dados grande demais para ser armazenado no disco rígido do seu laptop. Por exemplo, se tentássemos baixar o Pile por completo, precisaríamos de 825 GB de espaço livre em disco! Para lidar com esses casos, 🤗 Datasets fornece um recurso de streaming que nos permite baixar e acessar elementos em tempo real, sem a necessidade de baixar todo o conjunto de dados. Vamos dar uma olhada em como isso funciona.

<Tip>

💡 Nos notebooks Jupyter, você também pode cronometrar células usando a [`%%timeit` função mágica](https://ipython.readthedocs.io/en/stable/interactive/magics.html#magic-timeit).

</Tip>

## Conjuntos de dados em streaming

Para habilitar o streaming do conjunto de dados você só precisa passar o argumento `streaming=True` para a função `load_dataset()`. Por exemplo, vamos carregar o conjunto de dados PubMed Abstracts novamente, mas em modo streaming:

```py
pubmed_dataset_streamed = load_dataset(
    "json", data_files=data_files, split="train", streaming=True
)
```

Em vez do familiar `Dataset` que encontramos em outro lugar neste capítulo, o objeto retornado com `streaming=True` é um `IterableDataset`. Como o nome sugere, para acessar os elementos de um `IterableDataset` precisamos iterar sobre ele. Podemos acessar o primeiro elemento do nosso conjunto de dados transmitido da seguinte forma:


```py
next(iter(pubmed_dataset_streamed))
```

```python out
{'meta': {'pmid': 11409574, 'language': 'eng'},
 'text': 'Epidemiology of hypoxaemia in children with acute lower respiratory infection.\nTo determine the prevalence of hypoxaemia in children aged under 5 years suffering acute lower respiratory infections (ALRI), the risk factors for hypoxaemia in children under 5 years of age with ALRI, and the association of hypoxaemia with an increased risk of dying in children of the same age ...'}
```

Os elementos de um conjunto de dados transmitido podem ser processados dinamicamente usando `IterableDataset.map()`, o que é útil durante o treinamento se você precisar tokenizar as entradas. O processo é exatamente o mesmo que usamos para tokenizar nosso conjunto de dados no [Capítulo 3](/course/chapter3), com a única diferença de que as saídas são retornadas uma a uma:

```py
from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("distilbert-base-uncased")
tokenized_dataset = pubmed_dataset_streamed.map(lambda x: tokenizer(x["text"]))
next(iter(tokenized_dataset))
```

```python out
{'input_ids': [101, 4958, 5178, 4328, 6779, ...], 'attention_mask': [1, 1, 1, 1, 1, ...]}
```

<Tip>

💡 Para acelerar a tokenização com streaming você pode passar `batched=True`, como vimos na última seção. Ele processará os exemplos lote por lote; o tamanho do lote padrão é 1.000 e pode ser especificado com o argumento `batch_size`.

</Tip>

Você também pode embaralhar um conjunto de dados transmitido usando `IterableDataset.shuffle()`, mas, diferentemente de `Dataset.shuffle()`, isso apenas embaralha os elementos em um `buffer_size` predefinido:

```py
shuffled_dataset = pubmed_dataset_streamed.shuffle(buffer_size=10_000, seed=42)
next(iter(shuffled_dataset))
```

```python out
{'meta': {'pmid': 11410799, 'language': 'eng'},
 'text': 'Randomized study of dose or schedule modification of granulocyte colony-stimulating factor in platinum-based chemotherapy for elderly patients with lung cancer ...'}
```

Neste exemplo, selecionamos um exemplo aleatório dos primeiros 10.000 exemplos no buffer. Uma vez que um exemplo é acessado, seu lugar no buffer é preenchido com o próximo exemplo no corpus (ou seja, o 10.001º exemplo no caso acima). Você também pode selecionar elementos de um conjunto de dados transmitido usando as funções `IterableDataset.take()` e `IterableDataset.skip()`, que agem de maneira semelhante a `Dataset.select()`. Por exemplo, para selecionar os primeiros 5 exemplos no conjunto de dados PubMed Abstracts, podemos fazer o seguinte:

```py
dataset_head = pubmed_dataset_streamed.take(5)
list(dataset_head)
```

```python out
[{'meta': {'pmid': 11409574, 'language': 'eng'},
  'text': 'Epidemiology of hypoxaemia in children with acute lower respiratory infection ...'},
 {'meta': {'pmid': 11409575, 'language': 'eng'},
  'text': 'Clinical signs of hypoxaemia in children with acute lower respiratory infection: indicators of oxygen therapy ...'},
 {'meta': {'pmid': 11409576, 'language': 'eng'},
  'text': "Hypoxaemia in children with severe pneumonia in Papua New Guinea ..."},
 {'meta': {'pmid': 11409577, 'language': 'eng'},
  'text': 'Oxygen concentrators and cylinders ...'},
 {'meta': {'pmid': 11409578, 'language': 'eng'},
  'text': 'Oxygen supply in rural africa: a personal experience ...'}]
```

Da mesma forma, você pode usar a função `IterableDataset.skip()` para criar divisões de treinamento e validação de um conjunto de dados embaralhado da seguinte forma:

```py
# Skip the first 1,000 examples and include the rest in the training set
train_dataset = shuffled_dataset.skip(1000)
# Take the first 1,000 examples for the validation set
validation_dataset = shuffled_dataset.take(1000)
```

Vamos completar nossa exploração de streaming de conjuntos de dados com um aplicativo comum: combinar vários conjuntos de dados para criar um único corpus. 🤗 Datasets fornece uma função `interleave_datasets()` que converte uma lista de objetos `IterableDataset` em um único `IterableDataset`, onde os elementos do novo conjunto de dados são obtidos alternando entre os exemplos de origem. Essa função é especialmente útil quando você está tentando combinar grandes conjuntos de dados, então, como exemplo, vamos transmitir o subconjunto FreeLaw do Pile, que é um conjunto de dados de 51 GB de pareceres jurídicos dos tribunais dos EUA:

```py
law_dataset_streamed = load_dataset(
    "json",
    data_files="https://the-eye.eu/public/AI/pile_preliminary_components/FreeLaw_Opinions.jsonl.zst",
    split="train",
    streaming=True,
)
next(iter(law_dataset_streamed))
```

```python out
{'meta': {'case_ID': '110921.json',
  'case_jurisdiction': 'scotus.tar.gz',
  'date_created': '2010-04-28T17:12:49Z'},
 'text': '\n461 U.S. 238 (1983)\nOLIM ET AL.\nv.\nWAKINEKONA\nNo. 81-1581.\nSupreme Court of United States.\nArgued January 19, 1983.\nDecided April 26, 1983.\nCERTIORARI TO THE UNITED STATES COURT OF APPEALS FOR THE NINTH CIRCUIT\n*239 Michael A. Lilly, First Deputy Attorney General of Hawaii, argued the cause for petitioners. With him on the brief was James H. Dannenberg, Deputy Attorney General...'}
```

Esse conjunto de dados é grande o suficiente para sobrecarregar a RAM da maioria dos laptops, mas conseguimos carregá-lo e acessá-lo sem suar a camisa! Vamos agora combinar os exemplos dos conjuntos de dados FreeLaw e PubMed Abstracts com a função `interleave_datasets()`:

```py
from itertools import islice
from datasets import interleave_datasets

combined_dataset = interleave_datasets([pubmed_dataset_streamed, law_dataset_streamed])
list(islice(combined_dataset, 2))
```

```python out
[{'meta': {'pmid': 11409574, 'language': 'eng'},
  'text': 'Epidemiology of hypoxaemia in children with acute lower respiratory infection ...'},
 {'meta': {'case_ID': '110921.json',
   'case_jurisdiction': 'scotus.tar.gz',
   'date_created': '2010-04-28T17:12:49Z'},
  'text': '\n461 U.S. 238 (1983)\nOLIM ET AL.\nv.\nWAKINEKONA\nNo. 81-1581.\nSupreme Court of United States.\nArgued January 19, 1983.\nDecided April 26, 1983.\nCERTIORARI TO THE UNITED STATES COURT OF APPEALS FOR THE NINTH CIRCUIT\n*239 Michael A. Lilly, First Deputy Attorney General of Hawaii, argued the cause for petitioners. With him on the brief was James H. Dannenberg, Deputy Attorney General...'}]
```

Aqui usamos a função `islice()` do módulo `itertools` do Python para selecionar os dois primeiros exemplos do conjunto de dados combinado e podemos ver que eles correspondem aos primeiros exemplos de cada um dos dois conjuntos de dados de origem.

Por fim, se você quiser transmitir o Pile em sua totalidade de 825 GB, poderá pegar todos os arquivos preparados da seguinte maneira:

```py
base_url = "https://the-eye.eu/public/AI/pile/"
data_files = {
    "train": [base_url + "train/" + f"{idx:02d}.jsonl.zst" for idx in range(30)],
    "validation": base_url + "val.jsonl.zst",
    "test": base_url + "test.jsonl.zst",
}
pile_dataset = load_dataset("json", data_files=data_files, streaming=True)
next(iter(pile_dataset["train"]))
```

```python out
{'meta': {'pile_set_name': 'Pile-CC'},
 'text': 'It is done, and submitted. You can play “Survival of the Tastiest” on Android, and on the web...'}
```

<Tip>

✏️ **Experimente!** Use um dos grandes corpora Common Crawl como [`mc4`](https://huggingface.co/datasets/mc4) ou [`oscar`](https://huggingface.co/datasets/oscar) para criar um conjunto de dados multilíngue de streaming que represente as proporções faladas de idiomas em um país de sua escolha. Por exemplo, as quatro línguas nacionais na Suíça são alemão, francês, italiano e romanche, então você pode tentar criar um corpus suíço amostrando os subconjuntos do Oscar de acordo com sua proporção falada.

</Tip>

Agora você tem todas as ferramentas necessárias para carregar e processar conjuntos de dados de todas as formas e tamanhos, mas, a menos que tenha muita sorte, chegará um ponto em sua jornada de PNL em que você terá que criar um conjunto de dados para resolver o problema. problema em mãos. Esse é o tema da próxima seção!


<EditOnGithub source="https://github.com/huggingface/course/blob/main/chapters/pt/chapter5/4.mdx" />

### Confira o 🤗 Datasets!
https://huggingface.co/learn/course/pt/chapter5/7.md

# Confira o 🤗 Datasets!

<CourseFloatingBanner
    chapter={5}
    classNames="absolute z-10 right-0 top-0"
/>

Bem, esse foi um belo passeio pela biblioteca 🤗 Datasets - parabéns por chegar até aqui! Com o conhecimento que você adquiriu neste capítulo, você deve ser capaz de:

- Carregue conjuntos de dados de qualquer lugar, seja o Hugging Face Hub, seu laptop ou um servidor remoto em sua empresa.
- Organize seus dados usando uma combinação das funções `Dataset.map()` e `Dataset.filter()`.
- Alterne rapidamente entre formatos de dados como Pandas e NumPy usando `Dataset.set_format()`.
- Crie seu próprio conjunto de dados e envie-o para o Hugging Face Hub.
- Incorpore seus documentos usando um modelo Transformer e construa um mecanismo de pesquisa semântica usando o FAISS.

No [Capítulo 7](/course/chapter7), usaremos tudo isso para nos aprofundarmos nas principais tarefas de PNL para as quais os modelos Transformer são ótimos. Antes de avançar, no entanto, teste seu conhecimento de 🤗 Datasets com um teste rápido!

<EditOnGithub source="https://github.com/huggingface/course/blob/main/chapters/pt/chapter5/7.mdx" />

### E se o meu dataset não estiver no Hub?
https://huggingface.co/learn/course/pt/chapter5/2.md

# E se o meu dataset não estiver no Hub?

<CourseFloatingBanner chapter={5}
  classNames="absolute z-10 right-0 top-0"
  notebooks={[
    {label: "Google Colab", value: "https://colab.research.google.com/github/huggingface/notebooks/blob/master/course/pt/chapter5/section2.ipynb"},
    {label: "Aws Studio", value: "https://studiolab.sagemaker.aws/import/github/huggingface/notebooks/blob/master/course/pt/chapter5/section2.ipynb"},
]} />

Você sabe como usar o [Hugging Face Hub](https://huggingface.co/datasets) para baixar conjuntos de dados (**datasets**), mas muitas vezes você se encontrará trabalhando com dados que são armazenados em seu laptop ou em um servidor remoto. Nesta seção mostraremos como 🤗 Datasets podem ser usados para carregar conjuntos de dados que não estão disponíveis no Hugging Face Hub.

<Youtube id="HyQgpJTkRdE"/>

## Trabalhando com datasets locais e remotos


🤗 Datasets fornece scripts de carregamento para lidar com o carregamento de conjuntos de dados locais e remotos. Ele suporta vários formatos de dados comuns, como por exemplo:

|    Formato do dato  | script de carregamento |                         Exemplo                         |
| :----------------: | :------------: | :-----------------------------------------------------: |
|     CSV & TSV      |     `csv`      |     `load_dataset("csv", data_files="my_file.csv")`     |
|     Text files     |     `text`     |    `load_dataset("text", data_files="my_file.txt")`     |
| JSON & JSON Lines  |     `json`     |   `load_dataset("json", data_files="my_file.jsonl")`    |
| Pickled DataFrames |    `pandas`    | `load_dataset("pandas", data_files="my_dataframe.pkl")` |

Como mostrado na tabela, para cada formato de dados só precisamos especificar o tipo de script de carregamento na função `load_dataset()`, junto com um argumento `data_files` que especifica o caminho para um ou mais arquivos. Vamos começar carregando um conjunto de dados de arquivos locais; mais tarde veremos como fazer o mesmo com arquivos remotos.

## Carregando um conjunto de dados local

Para este exemplo usaremos o [SQuAD-it dataset] (https://github.com/crux82/squad-it/), que é um conjunto de dados em grande escala para resposta a perguntas em italiano.

As divisões de treinamento e testes são hospedadas no GitHub, para que possamos baixá-las com um simples comando `wget`:

```python
!wget https://github.com/crux82/squad-it/raw/master/SQuAD_it-train.json.gz
!wget https://github.com/crux82/squad-it/raw/master/SQuAD_it-test.json.gz
```

Isto irá baixar dois arquivos compactados chamados *SQuAD_it-train.json.gz* e *SQuAD_it-test.json.gz*, que podemos descomprimir com o comando Linux `gzip`:

```python
!gzip -dkv SQuAD_it-*.json.gz
```

```bash
SQuAD_it-test.json.gz:	   87.4% -- replaced with SQuAD_it-test.json
SQuAD_it-train.json.gz:	   82.2% -- replaced with SQuAD_it-train.json
```

Podemos ver que os arquivos compactados foram substituídos por _SQuAD_it-train.json_ e _SQuAD_it-text.json_, e que os dados são armazenados no formato JSON.

<Tip>

✎ Se você está se perguntando por que há um `!` nos comandos shell acima, é porque estamos executando-os dentro de um Jupyter notebook. Basta remover o prefixo se você quiser baixar e descompactar o conjunto de dados dentro de um terminal.
</Tip>

Para carregar um arquivo JSON com a função `load_dataset()`, só precisamos saber se estamos lidando com o JSON comum (semelhante a um dicionário aninhado) ou Linhas JSON (JSON line-separated JSON). Como muitos conjuntos de dados que respondem a perguntas, o SQuAD utiliza o formato aninhado, com todo o texto armazenado em um campo `data`. Isto significa que podemos carregar o conjunto de dados especificando o argumento  `field` da seguinte forma:

```py
from datasets import load_dataset

squad_it_dataset = load_dataset("json", data_files="SQuAD_it-train.json", field="data")
```

Por padrão, o carregamento de arquivos locais cria um objeto `DatasetDict` com uma divisão de treino (train). Podemos ver isso inspecionando o objeto `squad_it_dataset`:

```py
squad_it_dataset
```

```python out
DatasetDict({
    train: Dataset({
        features: ['title', 'paragraphs'],
        num_rows: 442
    })
})
```

Isto nos mostra o número de linhas e os nomes das colunas associadas ao conjunto de treinamento. Podemos ver um dos exemplos, indexando na divisão de treino da seguinte forma:

```py
squad_it_dataset["train"][0]
```

```python out
{
    "title": "Terremoto del Sichuan del 2008",
    "paragraphs": [
        {
            "context": "Il terremoto del Sichuan del 2008 o il terremoto...",
            "qas": [
                {
                    "answers": [{"answer_start": 29, "text": "2008"}],
                    "id": "56cdca7862d2951400fa6826",
                    "question": "In quale anno si è verificato il terremoto nel Sichuan?",
                },
                ...
            ],
        },
        ...
    ],
}
```

Ótimo, nós carregamos nosso primeiro conjunto de dados local! Mas enquanto isso funcionou para o conjunto de treinamento, o que realmente queremos é incluir tanto o conjunto de `treino` quanto o de `teste` divididos em um único objeto `DatasetDict` para que possamos aplicar as funções `Dataset.map()` em ambas as divisões de uma só vez. Para fazer isso, podemos fornecer um dicionário para o argumento `data_files` que mapeia cada nome de divisão para um arquivo associado a essa divisão:


```py
data_files = {"train": "SQuAD_it-train.json", "test": "SQuAD_it-test.json"}
squad_it_dataset = load_dataset("json", data_files=data_files, field="data")
squad_it_dataset
```

```python out
DatasetDict({
    train: Dataset({
        features: ['title', 'paragraphs'],
        num_rows: 442
    })
    test: Dataset({
        features: ['title', 'paragraphs'],
        num_rows: 48
    })
})
```

Isto é exatamente o que queríamos. Agora, podemos aplicar várias técnicas de pré-processamento para limpar os dados, assinalar as revisões, e assim por diante.


<Tip>

O argumento `data_files` da função `load_dataset()` é bastante flexível e pode ser um único caminho de arquivo ou uma lista de caminhos de arquivo, ou um dicionário que mapeia nomes divididos para caminhos de arquivo. Você também pode incluir arquivos que correspondam a um padrão especificado de acordo com as regras utilizadas pela Unix shell (por exemplo, você pode adicionar todos os arquivos JSON em um diretório como uma única divisão, definindo `data_files="*.json"`). Consulte a [documentação](https://huggingface.co/docs/datasets/loading#local-and-remote-files) do 🤗 Datasets para obter mais detalhes.

</Tip>

Os scripts de carregamento em 🤗 Datasets realmente suportam a descompressão automática dos arquivos de entrada, então poderíamos ter pulado o uso do `gzip` ao apontar o argumento `data_files` diretamente para os arquivos compactados:

```py
data_files = {"train": "SQuAD_it-train.json.gz", "test": "SQuAD_it-test.json.gz"}
squad_it_dataset = load_dataset("json", data_files=data_files, field="data")
```

Isto pode ser útil se você não quiser descomprimir manualmente muitos arquivos GZIP. A descompressão automática também se aplica a outros formatos comuns como ZIP e TAR, então você só precisa apontar `data_files` para os arquivos compactados e está pronto para seguir em frente!

Agora que você sabe como carregar arquivos locais em seu laptop ou desktop, vamos dar uma olhada no carregamento de arquivos remotos.

## Carregando um dataset remoto

Se você estiver trabalhando como cientista de dados ou programador em uma empresa, há uma boa chance de que os conjuntos de dados que você deseja analisar estejam armazenados em algum servidor remoto. Felizmente, o carregamento de arquivos remotos é tão simples quanto o carregamento de arquivos locais! Em vez de fornecer um caminho para arquivos locais, apontamos o argumento `data_files` de `load_dataset()` para uma ou mais URLs onde os arquivos remotos são armazenados. Por exemplo, para o conjunto de dados SQuAD-it hospedado no GitHub, podemos apenas apontar `data_files` para as URLs _SQuAD_it-*.json.gz_ da seguinte maneira:

```py
url = "https://github.com/crux82/squad-it/raw/master/"
data_files = {
    "train": url + "SQuAD_it-train.json.gz",
    "test": url + "SQuAD_it-test.json.gz",
}
squad_it_dataset = load_dataset("json", data_files=data_files, field="data")
```

Isto retorna o mesmo objeto `DatasetDict` obtido anteriormente, mas nos poupa o passo de baixar e descomprimir manualmente os arquivos _SQuAD_it-*.json.gz_. Isto envolve nas várias formas de carregar conjuntos de dados que não estão hospedados no Hugging Face Hub. Agora que temos um conjunto de dados para brincar, vamos sujar as mãos com várias técnicas de manipulação de dados!

<Tip>
✏️ **Tente fazer isso!** Escolha outro conjunto de dados hospedado no GitHub ou no [UCI Machine Learning Repository](https://archive.ics.uci.edu/ml/index.php) e tente carregá-lo tanto local como remotamente usando as técnicas introduzidas acima. Para pontos bônus, tente carregar um conjunto de dados que esteja armazenado em formato CSV ou texto (veja a [documentação](https://huggingface.co/docs/datasets/loading#local-and-remote-files) para mais informações sobre estes formatos).
</Tip>




<EditOnGithub source="https://github.com/huggingface/course/blob/main/chapters/pt/chapter5/2.mdx" />

### Tratando sequências múltiplas
https://huggingface.co/learn/course/pt/chapter2/5.md

# Tratando sequências múltiplas

{#if fw === 'pt'}

<CourseFloatingBanner chapter={2}
  classNames="absolute z-10 right-0 top-0"
  notebooks={[
    {label: "Google Colab", value: "https://colab.research.google.com/github/huggingface/notebooks/blob/master/course/pt/chapter2/section5_pt.ipynb"},
    {label: "Aws Studio", value: "https://studiolab.sagemaker.aws/import/github/huggingface/notebooks/blob/master/course/pt/chapter2/section5_pt.ipynb"},
]} />

{:else}

<CourseFloatingBanner chapter={2}
  classNames="absolute z-10 right-0 top-0"
  notebooks={[
    {label: "Google Colab", value: "https://colab.research.google.com/github/huggingface/notebooks/blob/master/course/pt/chapter2/section5_tf.ipynb"},
    {label: "Aws Studio", value: "https://studiolab.sagemaker.aws/import/github/huggingface/notebooks/blob/master/course/pt/chapter2/section5_tf.ipynb"},
]} />

{/if}

{#if fw === 'pt'}
<Youtube id="M6adb1j2jPI"/>
{:else}
<Youtube id="ROxrFOEbsQE"/>
{/if}

Na seção anterior, exploramos os casos mais simples de uso: fazer inferência sobre uma única sequência de pequeno comprimento. No entanto, surgem algumas questões:

- Como nós tratamos diversas sequências?
- Como nós tratamos diversas sequências *de diferentes tamanhos*?
- Os índices de vocabulário são as únicas entradas que permitem que um modelo funcione bem?
- Existe uma sequência muito longa?

Vamos ver que tipos de problemas estas questões colocam, e como podemos resolvê-los usando a API do 🤗 Transformers.

## Modelos esperam um batch de entradas

No exercício anterior, você viu como as sequências são traduzidas em listas de números. Vamos converter esta lista de números em um tensor e enviá-la para o modelo:

{#if fw === 'pt'}
```py
import torch
from transformers import AutoTokenizer, AutoModelForSequenceClassification

checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
model = AutoModelForSequenceClassification.from_pretrained(checkpoint)

sequence = "I've been waiting for a HuggingFace course my whole life."

tokens = tokenizer.tokenize(sequence)
ids = tokenizer.convert_tokens_to_ids(tokens)
input_ids = torch.tensor(ids)
# This line will fail.
model(input_ids)
```

```python out
IndexError: Dimension out of range (expected to be in range of [-1, 0], but got 1)
```
{:else}
```py
import tensorflow as tf
from transformers import AutoTokenizer, TFAutoModelForSequenceClassification

checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
model = TFAutoModelForSequenceClassification.from_pretrained(checkpoint)

sequence = "I've been waiting for a HuggingFace course my whole life."

tokens = tokenizer.tokenize(sequence)
ids = tokenizer.convert_tokens_to_ids(tokens)
input_ids = tf.constant(ids)
# This line will fail.
model(input_ids)
```

```py out
InvalidArgumentError: Input to reshape is a tensor with 14 values, but the requested shape has 196 [Op:Reshape]
```
{/if}

Oh não! Por que isso falhou? "Seguimos os passos do pipeline na seção 2.

O problema é que enviamos uma única sequência para o modelo, enquanto que os 🤗 transformers esperam várias sentenças por padrão. Aqui tentamos fazer tudo o que o tokenizer fez nos bastidores quando o aplicamos a uma `sequência`, mas se você olhar com atenção, verá que ele não apenas converteu a lista de IDs de entrada em um tensor, mas acrescentou uma dimensão em cima dele:

{#if fw === 'pt'}
```py
tokenized_inputs = tokenizer(sequence, return_tensors="pt")
print(tokenized_inputs["input_ids"])
```

```python out
tensor([[  101,  1045,  1005,  2310,  2042,  3403,  2005,  1037, 17662, 12172,
          2607,  2026,  2878,  2166,  1012,   102]])
```
{:else}
```py
tokenized_inputs = tokenizer(sequence, return_tensors="tf")
print(tokenized_inputs["input_ids"])
```

```py out
<tf.Tensor: shape=(1, 16), dtype=int32, numpy=
array([[  101,  1045,  1005,  2310,  2042,  3403,  2005,  1037, 17662,
        12172,  2607,  2026,  2878,  2166,  1012,   102]], dtype=int32)>
```
{/if}

Vamos tentar novamente e acrescentar uma nova dimensão:

{#if fw === 'pt'}
```py
import torch
from transformers import AutoTokenizer, AutoModelForSequenceClassification

checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
model = AutoModelForSequenceClassification.from_pretrained(checkpoint)

sequence = "I've been waiting for a HuggingFace course my whole life."

tokens = tokenizer.tokenize(sequence)
ids = tokenizer.convert_tokens_to_ids(tokens)

input_ids = torch.tensor([ids])
print("Input IDs:", input_ids)

output = model(input_ids)
print("Logits:", output.logits)
```
{:else}
```py
import tensorflow as tf
from transformers import AutoTokenizer, TFAutoModelForSequenceClassification

checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
model = TFAutoModelForSequenceClassification.from_pretrained(checkpoint)

sequence = "I've been waiting for a HuggingFace course my whole life."

tokens = tokenizer.tokenize(sequence)
ids = tokenizer.convert_tokens_to_ids(tokens)

input_ids = tf.constant([ids])
print("Input IDs:", input_ids)

output = model(input_ids)
print("Logits:", output.logits)
```
{/if}

Printamos os IDs de entrada assim como os logits resultantes - aqui está a saída:

{#if fw === 'pt'}
```python out
Input IDs: [[ 1045,  1005,  2310,  2042,  3403,  2005,  1037, 17662, 12172,  2607, 2026,  2878,  2166,  1012]]
Logits: [[-2.7276,  2.8789]]
```
{:else}
```py out
Input IDs: tf.Tensor(
[[ 1045  1005  2310  2042  3403  2005  1037 17662 12172  2607  2026  2878
   2166  1012]], shape=(1, 14), dtype=int32)
Logits: tf.Tensor([[-2.7276208  2.8789377]], shape=(1, 2), dtype=float32)
```
{/if}

*Batching* é o ato de enviar múltiplas sentenças através do modelo, todas de uma só vez. Se você tiver apenas uma frase, você pode apenas construir um lote com uma única sequência:

```
batched_ids = [ids, ids]
```

Este é um lote de duas sequências idênticas!

<Tip>

✏️ **Experimente!** Converta esta lista de `batched_ids` em um tensor e passe-a através de seu modelo. Verifique se você obtém os mesmos logits que antes (mas duas vezes)!

</Tip>

O Batching permite que o modelo funcione quando você o alimenta com várias frases. Usar várias sequências é tão simples quanto construir um lote com uma única sequência. Há uma segunda questão, no entanto. Quando você está tentando agrupar duas (ou mais) sentenças, elas podem ser de comprimentos diferentes. Se você já trabalhou com tensores antes, você sabe que eles precisam ser de forma retangular, então você não será capaz de converter a lista de IDs de entrada em um tensor diretamente. Para contornar este problema, normalmente realizamos uma *padronização* (padding) nas entradas.


## Realizando padding nas entradas

A seguinte lista de listas não pode ser convertida em um tensor:

```py no-format
batched_ids = [
    [200, 200, 200],
    [200, 200]
]
```

Para contornar isso, usaremos *padding* para fazer com que nossos tensores tenham uma forma retangular. O padding garante que todas as nossas frases tenham o mesmo comprimento, acrescentando uma palavra especial chamada *padding token* às frases com menos valores. Por exemplo, se você tiver 10 frases com 10 palavras e 1 frase com 20 palavras, o padding garantirá que todas as frases tenham 20 palavras. Em nosso exemplo, o tensor resultante se parece com isto:


```py no-format
padding_id = 100

batched_ids = [
    [200, 200, 200],
    [200, 200, padding_id],
]
```

O padding do ID token pode ser encontrada em `tokenizer.pad_token_id`. Vamos utilizá-lo e enviar nossas duas frases através do modelo individualmente e agrupadas em batches:

{#if fw === 'pt'}
```py no-format
model = AutoModelForSequenceClassification.from_pretrained(checkpoint)

sequence1_ids = [[200, 200, 200]]
sequence2_ids = [[200, 200]]
batched_ids = [
    [200, 200, 200],
    [200, 200, tokenizer.pad_token_id],
]

print(model(torch.tensor(sequence1_ids)).logits)
print(model(torch.tensor(sequence2_ids)).logits)
print(model(torch.tensor(batched_ids)).logits)
```

```python out
tensor([[ 1.5694, -1.3895]], grad_fn=<AddmmBackward>)
tensor([[ 0.5803, -0.4125]], grad_fn=<AddmmBackward>)
tensor([[ 1.5694, -1.3895],
        [ 1.3373, -1.2163]], grad_fn=<AddmmBackward>)
```
{:else}
```py no-format
model = TFAutoModelForSequenceClassification.from_pretrained(checkpoint)

sequence1_ids = [[200, 200, 200]]
sequence2_ids = [[200, 200]]
batched_ids = [
    [200, 200, 200],
    [200, 200, tokenizer.pad_token_id],
]

print(model(tf.constant(sequence1_ids)).logits)
print(model(tf.constant(sequence2_ids)).logits)
print(model(tf.constant(batched_ids)).logits)
```

```py out
tf.Tensor([[ 1.5693678 -1.3894581]], shape=(1, 2), dtype=float32)
tf.Tensor([[ 0.5803005  -0.41252428]], shape=(1, 2), dtype=float32)
tf.Tensor(
[[ 1.5693681 -1.3894582]
 [ 1.3373486 -1.2163193]], shape=(2, 2), dtype=float32)
```
{/if}

Há algo errado com os logits em nossas predições em batches: a segunda fileira deveria ser a mesma que os logits para a segunda frase, mas temos valores completamente diferentes!

Isto porque a característica chave dos Transformer são as camadas de atenção que *contextualizam* cada token. Estes levarão em conta os tokens de padding, uma vez que atendem a todos os tokens de uma sequência. Para obter o mesmo resultado ao passar frases individuais de diferentes comprimentos pelo modelo ou ao passar um batch com as mesmas frases e os paddings aplicados, precisamos dizer a essas camadas de atenção para ignorar os tokens de padding. Isto é feito com o uso de uma máscara de atenção (*attention mask*).

## Attention masks

*Attention masks* são tensores com a mesma forma exata do tensor de IDs de entrada, preenchidos com 0s e 1s: 1s indicam que os tokens correspondentes devem ser atendidas, e 0s indicam que os tokens correspondentes não devem ser atendidas (ou seja, devem ser ignoradas pelas camadas de atenção do modelo).

Vamos completar o exemplo anterior com uma máscara de atenção:

{#if fw === 'pt'}
```py no-format
batched_ids = [
    [200, 200, 200],
    [200, 200, tokenizer.pad_token_id],
]

attention_mask = [
    [1, 1, 1],
    [1, 1, 0],
]

outputs = model(torch.tensor(batched_ids), attention_mask=torch.tensor(attention_mask))
print(outputs.logits)
```

```python out
tensor([[ 1.5694, -1.3895],
        [ 0.5803, -0.4125]], grad_fn=<AddmmBackward>)
```
{:else}
```py no-format
batched_ids = [
    [200, 200, 200],
    [200, 200, tokenizer.pad_token_id],
]

attention_mask = [
    [1, 1, 1],
    [1, 1, 0],
]

outputs = model(tf.constant(batched_ids), attention_mask=tf.constant(attention_mask))
print(outputs.logits)
```

```py out
tf.Tensor(
[[ 1.5693681  -1.3894582 ]
 [ 0.5803021  -0.41252586]], shape=(2, 2), dtype=float32)
```
{/if}

Agora obtemos os mesmos logits para a segunda frase do batch.

Observe como o último valor da segunda sequência é um ID de padding, que é um valor 0 na máscara de atenção.

<Tip>

✏️ **Experimente!** Aplique a tokenização manualmente nas duas frases usadas na seção 2 ("I've been waiting for a HuggingFace course my whole life." e "I hate this so much!"). Passe-as através do modelo e verifique se você obtém os mesmos logits que na seção 2. Agora, agrupe-os usando o token de padding e depois crie a máscara de atenção adequada. Verifique que você obtenha os mesmos resultados ao passar pelo modelo!

</Tip>

## Sequências mais longas

Com os Transformer, há um limite para os comprimentos das sequências, podemos passar os modelos. A maioria dos modelos manipula sequências de até 512 ou 1024 tokens, e se chocará quando solicitados a processar sequências mais longas. Há duas soluções para este problema:

- Use um modelo com suporte a um comprimento mais longo de sequência.
- Trunque suas sequências.

Os modelos têm diferentes comprimentos de sequência suportados, e alguns são especializados no tratamento de sequências muito longas. O [Longformer](https://huggingface.co/transformers/model_doc/longformer.html) é um exemplo, e outro exemplo é o [LED](https://huggingface.co/transformers/model_doc/led.html). Se você estiver trabalhando em uma tarefa que requer sequências muito longas, recomendamos que você dê uma olhada nesses modelos.

Caso contrário, recomendamos que você trunque suas sequências, especificando o parâmetro `max_sequence_length`:

```py
sequence = sequence[:max_sequence_length]
```


<EditOnGithub source="https://github.com/huggingface/course/blob/main/chapters/pt/chapter2/5.mdx" />

### Introdução
https://huggingface.co/learn/course/pt/chapter2/1.md

# Introdução

<CourseFloatingBanner
    chapter={2}
    classNames="absolute z-10 right-0 top-0"
/>

Como você viu no [Capitulo 1](/course/pt/chapter1), normalmente modelos Transformers são muito grandes. Com milhões a dezenas de *bilhões* de parâmetros, o treinamento e o deploy destes modelos é uma tarefa complicado. Além disso, com novos modelos sendo lançados quase diariamente e cada um tendo sua própria implementação, experimentá-los a todos não é tarefa fácil.

A biblioteca 🤗 Transformers foi criado para resolver este problema. Seu objetivo é fornecer uma API única através do qual qualquer modelo Transformer possa ser carregado, treinado e salvo. As principais características da biblioteca são:

- **Fácil de usar**: Baixar, carregar e usar um modelo de processamento natural de linguagem (PNL) de última geração para inferência pode ser feito em apenas duas linhas de código
- **Flexibilidade**: Em sua essência, todos os modelos são uma simples classe PyTorch `nn.Module` ou TensorFlow `tf.keras.Model` e podem ser tratadas como qualquer outro modelo em seus respectivos frameworks de machine learning (ML).
- **Simplicidade**: Quase nenhuma abstração é feita em toda a biblioteca. O "Tudo em um arquivo" é um conceito principal: o "passe para frente" de um modelo é inteiramente definido em um único arquivo, de modo que o código em si seja compreensível e hackeável.

Esta última característica torna 🤗 Transformers bem diferente de outras bibliotecas ML que modelos e/ou configurações são compartilhados entre arquivos; em vez disso, cada modelo tem suas próprias camadas. Além de tornar os modelos mais acessíveis e compreensíveis, isto permite que você experimente facilmente um modelo sem afetar outros.

Este capítulo começará com um exemplo de ponta a ponta onde usamos um modelo e um tokenizer juntos para replicar a função `pipeline()` introduzida no [Capitulo 1](/course/pt/chapter1). A seguir, discutiremos o modelo da API: onde veremos profundamente as classes de modelo e configuração, além de mostrar como carregar um modelo e como ele processa as entradas numéricas para as previsões de saída. 

Depois veremos a API do tokenizer, que é o outro componente principal da função `pipeline()`. Os Tokenizers cuidam da primeira e da última etapa do processamento, cuidando da conversão de texto para entradas numéricas para a rede neural, e da conversão de volta ao texto quando for necessário. Por fim, mostraremos a você como lidar com o envio de várias frases através de um modelo em um batch preparado, depois olharemos tudo mais atentamente a função de alto nível `tokenizer()`.


<Tip>
⚠️ Para beneficiar-se de todos os recursos disponíveis com o Model Hub e 🤗 Transformers, recomendamos  <a href="https://huggingface.co/join"> criar uma conta</a>.
</Tip>

<EditOnGithub source="https://github.com/huggingface/course/blob/main/chapters/pt/chapter2/1.mdx" />

### Modelos
https://huggingface.co/learn/course/pt/chapter2/3.md

# Modelos

{#if fw === 'pt'}

<CourseFloatingBanner chapter={2}
  classNames="absolute z-10 right-0 top-0"
  notebooks={[
    {label: "Google Colab", value: "https://colab.research.google.com/github/huggingface/notebooks/blob/master/course/pt/chapter2/section3_pt.ipynb"},
    {label: "Aws Studio", value: "https://studiolab.sagemaker.aws/import/github/huggingface/notebooks/blob/master/course/pt/chapter2/section3_pt.ipynb"},
]} />

{:else}

<CourseFloatingBanner chapter={2}
  classNames="absolute z-10 right-0 top-0"
  notebooks={[
    {label: "Google Colab", value: "https://colab.research.google.com/github/huggingface/notebooks/blob/master/course/pt/chapter2/section3_tf.ipynb"},
    {label: "Aws Studio", value: "https://studiolab.sagemaker.aws/import/github/huggingface/notebooks/blob/master/course/pt/chapter2/section3_tf.ipynb"},
]} />

{/if}

{#if fw === 'pt'}
<Youtube id="AhChOFRegn4"/>
{:else}
<Youtube id="d3JVgghSOew"/>
{/if}

{#if fw === 'pt'}
Nesta seção, vamos analisar mais de perto a criação e a utilização de um modelo. Vamos utilizar a classe `AutoModel`, que é útil quando você quer instanciar qualquer modelo a partir de um checkpoint.

A classe `AutoModel` e todas as classes filhas são na verdade simples wrapper sobre a grande variedade de modelos disponíveis na biblioteca. É um wrapper inteligente, pois pode automaticamente "adivinhar" a arquitetura apropriada do modelo para seu checkpoint, e então instancia um modelo com esta arquitetura.

{:else}
Nesta seção, vamos analisar mais de perto a criação e a utilização de um modelo. Vamos utilizar a classe `TFAutoModel`, que é útil quando você quer instanciar qualquer modelo a partir de um checkpoint.

A classe `TFAutoModel` e todas as classes filhas são na verdade simples  wrapper sobre a grande variedade de modelos disponíveis na biblioteca. É um wrapper inteligente, pois pode automaticamente "adivinhar" a arquitetura apropriada do modelo para seu checkpoint, e então instancia um modelo com esta arquitetura.

{/if}

Entretanto, se você conhece o tipo de modelo que deseja usar, pode usar diretamente a classe que define sua arquitetura. Vamos dar uma olhada em como isto funciona com um modelo BERT.

## Criando um Transformer

A primeira coisa que precisamos fazer para inicializar um modelo BERT é carregar um objeto de configuração:

{#if fw === 'pt'}
```py
from transformers import BertConfig, BertModel

# Construindo a configuração
config = BertConfig()

# Construindo o modelo a partir da configuração
model = BertModel(config)
```
{:else}
```py
from transformers import BertConfig, TFBertModel

# Construindo a configuração
config = BertConfig()

# Construindo o modelo a partir da configuração
model = TFBertModel(config)
```
{/if}

A configuração contém muitos atributos que são usados para construir o modelo:

```py
print(config)
```

```python out
BertConfig {
  [...]
  "hidden_size": 768,
  "intermediate_size": 3072,
  "max_position_embeddings": 512,
  "num_attention_heads": 12,
  "num_hidden_layers": 12,
  [...]
}
```

Embora você ainda não tenha visto o que todos esses atributos fazem, você deve reconhecer alguns deles: o atributo `hidden_size` define o tamanho do vetor `hidden_states`, e o `num_hidden_layers`  define o número de camadas que o Transformer possui.


### Diferentes métodos de inicializar o modelo

A criação de um modelo a partir da configuração padrão o inicializa com valores aleatórios:

{#if fw === 'pt'}
```py
from transformers import BertConfig, BertModel

config = BertConfig()
model = BertModel(config)

# O modelo é inicializado aleatoriamente!
```
{:else}
```py
from transformers import BertConfig, TFBertModel

config = BertConfig()
model = TFBertModel(config)

# O modelo é inicializado aleatoriamente!
```
{/if}

O modelo pode ser utilizado neste estado, mas produzirá saídas errôneas; ele precisa ser treinado primeiro. Poderíamos treinar o modelo a partir do zero na tarefa em mãos, mas como você viu em [Capítulo 1](/course/pt/chapter1), isto exigiria muito tempo e muitos dados, e teria um impacto ambiental não negligenciável. Para evitar esforços desnecessários e duplicados, normalmente é possível compartilhar e reutilizar modelos que já foram treinados.

Carregar um Transformer já treinado é simples - podemos fazer isso utilizando o método `from_pretrained()`:

{#if fw === 'pt'}
```py
from transformers import BertModel

model = BertModel.from_pretrained("bert-base-cased")
```

Como você viu anteriormente, poderíamos substituir o `BertModel` pela classe equivalente ao `AutoModel`. Faremos isto de agora em diante, pois isto produz um código generalista a partir de um checkpoint; se seu código funciona para checkpoint, ele deve funcionar perfeitamente com outro. Isto se aplica mesmo que a arquitetura seja diferente, desde que o checkpoint tenha sido treinado para uma tarefa semelhante (por exemplo, uma tarefa de análise de sentimento).

{:else}
```py
from transformers import TFBertModel

model = TFBertModel.from_pretrained("bert-base-cased")
```

Como você viu anteriormente, poderíamos substituir o `TFBertModel` pela classe equivalente ao `TFAutoModel`. Faremos isto de agora em diante, pois isto produz um código generalista a partir de um checkpoint; se seu código funciona para checkpoint, ele deve funcionar perfeitamente com outro. Isto se aplica mesmo que a arquitetura seja diferente, desde que o checkpoint tenha sido treinado para uma tarefa semelhante (por exemplo, uma tarefa de análise de sentimento).


{/if}

No exemplo de código acima não utilizamos `BertConfig`, e em vez disso carregamos um modelo pré-treinado através do identificador `bert-base-cased`. Este é um checkpoint do modelo que foi treinado pelos próprios autores do BERT; você pode encontrar mais detalhes sobre ele em seu [model card](https://huggingface.co/bert-base-cased).

Este modelo agora é inicializado com todos os pesos do checkpoint. Ele pode ser usado diretamente para inferência sobre as tarefas nas quais foi treinado, e também pode ser *fine-tuned* (aperfeiçoado) em uma nova tarefa. Treinando com pesos pré-treinados e não do zero, podemos rapidamente alcançar bons resultados.

Os pesos foram baixados e armazenados em cache (logo, para as futuras chamadas do método `from_pretrained()` não será realizado o download novamente) em sua respectiva pasta, que tem como padrão o path *~/.cache/huggingface/transformers*. Você pode personalizar sua pasta de cache definindo a variável de ambiente `HF_HOME`.

O identificador usado para carregar o modelo pode ser o identificador de qualquer modelo no Model Hub, desde que seja compatível com a arquitetura BERT. A lista completa dos checkpoints BERT disponíveis podem ser encontrada [aqui].https://huggingface.co/models?filter=bert).

### Métodos para salvar/armazenar o modelo

Salvar um modelo é tão fácil quanto carregar um - utilizamos o método `save_pretrained()`, que é análogo ao método `from_pretrained()`:

```py
model.save_pretrained("path_no_seu_computador")
```

Isto salva dois arquivos em seu disco:

{#if fw === 'pt'}
```
ls path_no_seu_computador

config.json model.safetensors
```
{:else}
```
ls path_no_seu_computador

config.json tf_model.h5
```
{/if}

Se você der uma olhada no arquivo *config.json*, você reconhecerá os atributos necessários para construir a arquitetura modelo. Este arquivo também contém alguns metadados, como a origem do checkpoint e a versão 🤗 Transformers que você estava usando quando salvou o checkpoint pela última vez.

{#if fw === 'pt'}
O arquivo *model.safetensors* é conhecido como o *dicionário de estado*; ele contém todos os pesos do seu modelo. Os dois arquivos andam de mãos dadas; a configuração é necessária para conhecer a arquitetura de seu modelo, enquanto os pesos do modelo são os parâmetros de seu modelo.

{:else}
O arquivo *tf_model.h5* é conhecido como o *dicionário de estado*; ele contém todos os pesos do seu modelo. Os dois arquivos andam de mãos dadas; a configuração é necessária para conhecer a arquitetura de seu modelo, enquanto os pesos do modelo são os parâmetros de seu modelo.

{/if}

## Usando um modelo de Transformer para inferência

Agora que você sabe como carregar e salvar um modelo, vamos tentar usá-lo para fazer algumas predições. Os Transformers só podem processar números - números que o tokenizer gera. Mas antes de discutirmos os tokenizers, vamos explorar quais entradas o modelo aceita.

Os Tokenizers podem se encarregar de lançar as entradas nos tensores da estrutura apropriada, mas para ajudá-lo a entender o que está acontecendo, vamos dar uma rápida olhada no que deve ser feito antes de enviar as entradas para o modelo.

Digamos que temos um par de sequências:

```py
sequences = ["Hello!", "Cool.", "Nice!"]
```

O tokenizer os converte em índices de vocabulário que são normalmente chamados de *IDs de entrada*. Cada sequência é agora uma lista de números! A saída resultante é:

```py no-format
encoded_sequences = [
    [101, 7592, 999, 102],
    [101, 4658, 1012, 102],
    [101, 3835, 999, 102],
]
```

Esta é uma lista de sequências codificadas: uma lista de listas. Os tensores só aceitam shapes (tamanhos) retangulares (pense em matrizes). Esta "matriz" já é de forma retangular, portanto, convertê-la em um tensor é fácil:

{#if fw === 'pt'}
```py
import torch

model_inputs = torch.tensor(encoded_sequences)
```
{:else}
```py
import tensorflow as tf

model_inputs = tf.constant(encoded_sequences)
```
{/if}

### Usando os tensores como entradas para o modelo

Fazer uso dos tensores com o modelo é extremamente simples - chamamos apenas o modelo com os inputs:

```py
output = model(model_inputs)
```

Embora o modelo aceite muitos argumentos diferentes, apenas os IDs de entrada são necessários. Explicaremos o que os outros argumentos fazem e quando eles são necessários mais tarde, mas primeiro precisamos olhar mais de perto os tokenizers que constroem as entradas que um Transformer pode compreender.


<EditOnGithub source="https://github.com/huggingface/course/blob/main/chapters/pt/chapter2/3.mdx" />

### Colocando tudo junto
https://huggingface.co/learn/course/pt/chapter2/6.md

# Colocando tudo junto

{#if fw === 'pt'}

<CourseFloatingBanner chapter={2}
  classNames="absolute z-10 right-0 top-0"
  notebooks={[
    {label: "Google Colab", value: "https://colab.research.google.com/github/huggingface/notebooks/blob/master/course/pt/chapter2/section6_pt.ipynb"},
    {label: "Aws Studio", value: "https://studiolab.sagemaker.aws/import/github/huggingface/notebooks/blob/master/course/pt/chapter2/section6_pt.ipynb"},
]} />

{:else}

<CourseFloatingBanner chapter={2}
  classNames="absolute z-10 right-0 top-0"
  notebooks={[
    {label: "Google Colab", value: "https://colab.research.google.com/github/huggingface/notebooks/blob/master/course/pt/chapter2/section6_tf.ipynb"},
    {label: "Aws Studio", value: "https://studiolab.sagemaker.aws/import/github/huggingface/notebooks/blob/master/course/pt/chapter2/section6_tf.ipynb"},
]} />

{/if}

Nas últimas seções, temos feito o nosso melhor para fazer a maior parte do trabalho à mão. Exploramos como funcionam os tokenizers e analisamos a tokenização, conversão para IDs de entrada, padding, truncagem e máscaras de atenção.

Entretanto, como vimos na seção 2, a API dos 🤗 Transformers pode tratar de tudo isso para nós com uma função de alto nível, na qual mergulharemos aqui. Quando você chama seu `tokenizer` diretamente na frase, você recebe de volta entradas que estão prontas para passar pelo seu modelo:

```py
from transformers import AutoTokenizer

checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)

sequence = "I've been waiting for a HuggingFace course my whole life."

model_inputs = tokenizer(sequence)
```

Aqui, a variável `model_inputs` contém tudo o que é necessário para que um modelo funcione bem. Para DistilBERT, isso inclui os IDs de entrada, bem como a máscara de atenção. Outros modelos que aceitam entradas adicionais também terão essas saídas pelo objeto `tokenizer`.

Como veremos em alguns exemplos abaixo, este método é muito poderoso. Primeiro, ele pode simbolizar uma única sequência:

```py
sequence = "I've been waiting for a HuggingFace course my whole life."

model_inputs = tokenizer(sequence)
```

Também lida com várias sequências de cada vez, sem nenhuma mudança na API:

```py
sequences = ["I've been waiting for a HuggingFace course my whole life.", "So have I!"]

model_inputs = tokenizer(sequences)
```

Ela pode ser aplicada de acordo com vários objetivos:

```py
# Irá preencher as sequências até o comprimento máximo da sequência
model_inputs = tokenizer(sequences, padding="longest")

# Irá preencher as sequências até o comprimento máximo do modelo
# (512 para o modelo BERT ou DistilBERT)
model_inputs = tokenizer(sequences, padding="max_length")

# Irá preencher as sequências até o comprimento máximo especificado
model_inputs = tokenizer(sequences, padding="max_length", max_length=8)
```

Também pode truncar sequências:

```py
sequences = ["I've been waiting for a HuggingFace course my whole life.", "So have I!"]

# Irá preencher as sequências até o comprimento máximo do modelo
# (512 para o modelo BERT ou DistilBERT)
model_inputs = tokenizer(sequences, truncation=True)

# Truncará as sequências que são mais longas do que o comprimento máximo especificado
model_inputs = tokenizer(sequences, max_length=8, truncation=True)
```

O objeto `tokenizer` pode lidar com a conversão para tensores de estrutura específicos, que podem então ser enviados diretamente para o modelo. Por exemplo, na seguinte amostra de código, estamos solicitando que o tokenizer retorne tensores de diferentes estruturas - `"pt"` retorna tensores PyTorch, `"tf"` retorna tensores TensorFlow, e `"np"` retorna arrays NumPy:

```py
sequences = ["I've been waiting for a HuggingFace course my whole life.", "So have I!"]

# Retorna tensores PyTorch
model_inputs = tokenizer(sequences, padding=True, return_tensors="pt")

# Retorna tensores TensorFlow
model_inputs = tokenizer(sequences, padding=True, return_tensors="tf")

# Retorna NumPy arrays
model_inputs = tokenizer(sequences, padding=True, return_tensors="np")
```

## Tokens especiais

Se dermos uma olhada nos IDs de entrada devolvidos pelo tokenizer, veremos que eles são um pouco diferentes do que tínhamos anteriormente:

```py
sequence = "I've been waiting for a HuggingFace course my whole life."

model_inputs = tokenizer(sequence)
print(model_inputs["input_ids"])

tokens = tokenizer.tokenize(sequence)
ids = tokenizer.convert_tokens_to_ids(tokens)
print(ids)
```

```python out
[101, 1045, 1005, 2310, 2042, 3403, 2005, 1037, 17662, 12172, 2607, 2026, 2878, 2166, 1012, 102]
[1045, 1005, 2310, 2042, 3403, 2005, 1037, 17662, 12172, 2607, 2026, 2878, 2166, 1012]
```


Um token ID foi adicionada no início e uma no final. Vamos decodificar as duas sequências de IDs acima para ver do que se trata:


```py
print(tokenizer.decode(model_inputs["input_ids"]))
print(tokenizer.decode(ids))
```

```python out
"[CLS] i've been waiting for a huggingface course my whole life. [SEP]"
"i've been waiting for a huggingface course my whole life."
```

O tokenizer acrescentou a palavra especial `[CLS]` no início e a palavra especial `[SEP]` no final. Isto porque o modelo foi pré-treinado com esses, então para obter os mesmos resultados para inferência, precisamos adicioná-los também. Note que alguns modelos não acrescentam palavras especiais, ou acrescentam palavras diferentes; os modelos também podem acrescentar estas palavras especiais apenas no início, ou apenas no final. Em qualquer caso, o tokenizer sabe quais são as palavras que são esperadas e tratará disso para você.


## Do tokenizer ao modelo

Agora que já vimos todos os passos individuais que o objeto `tokenizer` utiliza quando aplicado em textos, vamos ver uma última vez como ele pode lidar com múltiplas sequências (padding!), sequências muito longas (truncagem!), e múltiplos tipos de tensores com seu API principal:

{#if fw === 'pt'}
```py
import torch
from transformers import AutoTokenizer, AutoModelForSequenceClassification

checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
model = AutoModelForSequenceClassification.from_pretrained(checkpoint)
sequences = ["I've been waiting for a HuggingFace course my whole life.", "So have I!"]

tokens = tokenizer(sequences, padding=True, truncation=True, return_tensors="pt")
output = model(**tokens)
```
{:else}
```py
import tensorflow as tf
from transformers import AutoTokenizer, TFAutoModelForSequenceClassification

checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
model = TFAutoModelForSequenceClassification.from_pretrained(checkpoint)
sequences = ["I've been waiting for a HuggingFace course my whole life.", "So have I!"]

tokens = tokenizer(sequences, padding=True, truncation=True, return_tensors="tf")
output = model(**tokens)
```
{/if}


<EditOnGithub source="https://github.com/huggingface/course/blob/main/chapters/pt/chapter2/6.mdx" />

### Questionário de fim de capítulo
https://huggingface.co/learn/course/pt/chapter2/8.md

# Questionário de fim de capítulo

<CourseFloatingBanner
    chapter={2}
    classNames="absolute z-10 right-0 top-0"
/>

### 1. Qual é a ordem do pipeline para a modelagem de linguagem?

<Question
	choices={[
		{
			text: "Primeiro, o modelo trata de textos e devolve previsões em bruto. O tokenizer, então, trás sentido a estas previsões e as converte de volta ao texto quando necessário.",
			explain: "O modelo não consegue entender o texto! O tokenizer deve primeiro simbolizar o texto e convertê-lo em IDs para que seja compreensível pelo modelo."
		},
		{
			text: "Primeiro, o tokenizer trata de textos e devolve as identificações (IDs). O modelo lida com estas identificações e produz uma predição, que pode ser algum texto.",
			explain: "A predição do modelo não pode ser feita de imediato. O tokenizer tem que ser usado para converter a predição de volta ao texto!"
		},
		{
			text: "O tokenizer trata de textos e devolve os IDs. O modelo lida com estes IDs e produz uma predição. O tokenizer pode então ser usado mais uma vez para converter estas previsões de volta para algum texto.",
			explain: "Correto! O tokenizer pode ser usado tanto para a tokenização quanto para a destokenização.",
            correct: true
		}
	]}
/>

### 2. Quantas dimensões tem o tensor do Transformer de base, e quais são elas?

<Question
	choices={[
		{
			text: "2: O comprimento da sequência e o tamanho do batch (lote)",
			explain: "Falso! A saída do tensor pelo modelo tem uma terceira dimensão: o tamanho das camadas ocultas"
		},
		{
			text: "2: O comprimento da sequência e o tamanho das camadas ocultas",
			explain: "Falso! Todos os Transformer lidam com batches, mesmo com uma única sequência; isso seria um tamanho de batch de 1!"
		},
		{
			text: "3: O comprimento da sequência, o tamanho do batch (lote) e o tamanho das camadas ocultas",
			explain: "Correto!",
            correct: true
		}
	]}
/>

### 3. Qual dos seguintes é um exemplo de Tokenização por sub-palavras?

<Question
	choices={[
		{
			text: "WordPiece",
			explain: "Exatamente, este é um exemplo de Tokenização por sub-palavra!",
            correct: true
		},
		{
			text: "Character-based tokenization",
			explain: "Character-based tokenization não é uma tokenização por sub-palavra!."
		},
		{
			text: "Divisão no espaço em branco e pontuação",
			explain: "Esse é um esquema de tokenization baseado em palavras!"
		},
		{
			text: "BPE",
			explain: "Exatamente, este é um exemplo de Tokenização por sub-palavra!",
            correct: true
        },
		{
			text: "Unigram",
			explain: "Exatamente, este é um exemplo de Tokenização por sub-palavra!",
            correct: true
        },
		{
			text: "Nenhuma das acimas",
			explain: "Errado!"
        }
	]}
/>

### 4. O que é uma *model head*?

<Question
	choices={[
		{
			text: "Um componente dos transformers de base que redireciona os tensores para suas camadas corretas",
			explain: "Incorreto! Não existe tal componente."
		},
		{
			text: "Também conhecido como mecanismo de auto-atenção (*self-attention*), ele adapta a representação de um símbolo de acordo com os outros tokens da sequência",
			explain: "Incorreto! A camada de auto-atenção contém 'attention heads', mas estas não são as heads de adaptação."
		},
		{
			text: "Um componente adicional, geralmente composto de uma ou poucas camadas, para converter as previsões do Transformer em uma saída específica de tarefa",
			explain: "É isso mesmo. As heads de adaptação, também conhecidos simplesmente como heads, surgem em diferentes formas: heads de modelagem de linguagem, heads de resposta a perguntas, heads de classificação de sequência.. ",
			correct: true
		} 
	]}
/>

{#if fw === 'pt'}
### 5. O que seria um `AutoModel`?

<Question
	choices={[
		{
			text: "Um modelo que treina automaticamente com seus dados",
			explain: "Incorreto. Você está confundindo isto com nosso produto de <a href='https://huggingface.co/autonlp'>AutoNLP</a>?"
		},
		{
			text: "Um objeto que devolve a arquitetura correta com base em um checkpoint",
			explain: "Exatamente: o <code>AutoModel</code> só precisa saber o checkpoint para saber como inicializar então devolver a arquitetura correta.",
			correct: true
		},
		{
			text: "Um modelo que detecta automaticamente a linguagem utilizada para suas entradas a fim de carregar os pesos corretos",
			explain: "Incorreto; embora alguns checkpoints e modelos sejam capazes de lidar com vários idiomas, não há ferramentas embutidas para seleção automática de checkpoints de acordo com o idioma. Você deve ir para o  <a href='https://huggingface.co/models'>Model Hub</a> para encontrar o melhor checkpoint para realizar sua tarefa!"
		} 
	]}
/>

{:else}
### 5. O que seria um `TFAutoModel`?

<Question
	choices={[
		{
			text: "Um modelo que treina automaticamente com seus dados",
			explain: "Incorreto. Você está confundindo isto com nosso produto de <a href='https://huggingface.co/autonlp'>AutoNLP</a>?"
		},
		{
			text: "Um objeto que devolve a arquitetura correta com base em um checkpoint",
			explain: "Exatamente: o <code>TFAutoModel</code> só precisa saber o checkpoint para saber como inicializar então devolver a arquitetura correta.",
			correct: true
		},
		{
			text: "Um modelo que detecta automaticamente a linguagem utilizada para suas entradas a fim de carregar os pesos corretos",
			explain: "Incorreto; embora alguns checkpoints e modelos sejam capazes de lidar com vários idiomas, não há ferramentas embutidas para seleção automática de checkpoints de acordo com o idioma. Você deve ir para o  <a href='https://huggingface.co/models'>Model Hub</a> para encontrar o melhor checkpoint para realizar sua tarefa!"
		} 
	]}
/>

{/if}

### 6. Quais são as técnicas a serem observadas quando realizar batches com sequências de diferentes tamanhos?

<Question
	choices={[
		{
			text: "Truncar",
			explain: "Sim, a truncagem é uma forma correta de sequências de saída noturna para que elas se encaixem em forma retangular.No entanto, seria a única?",
			correct: true
		},
		{
			text: "Retornar tensores",
			explain: "Enquanto as outras técnicas permitem retornar tensores retangulares, retornar tensores não é útil quando realizar batches de sequências juntas."
		},
		{
			text: "Padding",
			explain: "Sim, padding é uma forma correta para as sequências de saída para que elas se encaixem em uma forma retangular. No entanto, seria a única?",
			correct: true
		}, 
		{
			text: "Attention masking",
			explain: "Exatamente! As attention masks são de primordial importância quando se trata de sequências de diferentes tamanhos. No entanto, essa não é a única técnica a ser conhecida.",
			correct: true
		} 
	]}
/>

### 7. Qual é o objetivo de aplicar uma função SoftMax à saída de logits para um modelo de classificação sequencial??

<Question
	choices={[
		{
			text: "Suaviza os logits para que sejam mais confiáveis.",
			explain: "Não, a função SoftMax não afeta a confiabilidade dos resultados."
		},
		{
			text: "Aplica um limite inferior e um limite superior para que eles sejam compreensíveis.",
			explain: "Correto! Os valores resultantes estão vinculados entre 0 e 1. Mas essa não é a única razão pela qual usamos uma função SoftMax.",
            correct: true
		},
		{
			text: "A soma total da saída é 1, resultando em uma possível interpretação probabilística.",
			explain: "Correto! Mas essa não é a única razão pela qual usamos uma função SoftMax.",
            correct: true
		}
	]}
/>

### 8. Qual é o método core da API tokenizer?

<Question
	choices={[
		{
			text: "<code>encode</code>, pois pode codificar texto em IDs e IDs em predições",
			explain: "Errado! O método <code>encode</code> existe na tokenização, porém não existe nos modelos."
		},
		{
			text: "Chamando diretamente o objeto de tokenização (tokenizer).",
			explain: "Exatamente! O método <code>__call__</code> do tokenizer é um método muito poderoso que pode lidar com praticamente qualquer coisa. É também o método usado para recuperar as predições de um modelo.",
			correct: true
		},
		{
			text: "<code>padding</code>",
			explain: "Errado! O padding é muito útil, mas é apenas uma parte da API do tokenizer."
		},
		{
			text: "<code>tokenize</code>",
			explain: "O método <code>tokenize</code> é indiscutivelmente um dos métodos mais úteis, mas não é o núcleo do API do tokenizer."
		}
	]}
/>

### 9. O que a variável `result` contém nesta pedaço de código?

```py
from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("bert-base-cased")
result = tokenizer.tokenize("Hello!")
```

<Question
	choices={[
		{
			text: "Uma lista de strings, sendo cada uma delas um token",
			explain: "Exatamente! Converta isto em IDs, e envie-os para um modelo!",
            correct: true
		},
		{
			text: "Uma lista de IDs",
			explain: "Incorreto; isto é o para o os métodos <code>__call__</code> ou <code>convert_tokens_to_ids</code>!"
		},
		{
			text: "Uma string contendo todos os tokens ",
			explain: "Isto seria subótimo, pois o objetivo é dividir a string em vários tokens."
		}
	]}
/>

{#if fw === 'pt'}
### 10. Tem algo errado com o código abaixo?

```py
from transformers import AutoTokenizer, AutoModel

tokenizer = AutoTokenizer.from_pretrained("bert-base-cased")
model = AutoModel.from_pretrained("gpt2")

encoded = tokenizer("Hey!", return_tensors="pt")
result = model(**encoded)
```

<Question
	choices={[
		{
			text: "Não, parece correto.",
			explain: "Infelizmente, acoplar um modelo com um tokenizer que foi treinado com um checkpoint diferente raramente é uma boa ideia. O modelo não foi treinado para fazer sentido a partir da saída deste tokenizer, então a saída do modelo (isto se ele realmente funcionar!) não fará nenhum sentido."
		},
		{
			text: "O tokenizer e o modelo devem ser sempre a partir do mesmo checkpoint.",
			explain: "Correto!",
            correct: true
		},
		{
			text: "É uma boa prática realizar o padding e truncar com o tokenizer, pois cada entrada é um batch.",
			explain: "É verdade que cada entrada do modelo precisa ser um batch. Entretanto, truncando ou realizando o padding desta sequência não faria necessariamente sentido, pois existe apenas uma delas, e estas são técnicas para criar batches de uma lista de sentenças."
		}
	]}
/>

{:else}
### 10. Tem algo errado com o código abaixo?

```py
from transformers import AutoTokenizer, TFAutoModel

tokenizer = AutoTokenizer.from_pretrained("bert-base-cased")
model = TFAutoModel.from_pretrained("gpt2")

encoded = tokenizer("Hey!", return_tensors="pt")
result = model(**encoded)
```

<Question
	choices={[
		{
			text: "Não, parece correto.",
			explain: "Infelizmente, acoplar um modelo com um tokenizer que foi treinado com um checkpoint diferente raramente é uma boa ideia. O modelo não foi treinado para fazer sentido a partir da saída deste tokenizer, então a saída do modelo (isto se ele realmente funcionar!) não fará nenhum sentido."
		},
		{
			text: "O tokenizer e o modelo devem ser sempre a partir do mesmo checkpoint.",
			explain: "Correto!",
            correct: true
		},
		{
			text: "É uma boa prática realizar o padding e truncar com o tokenizer, pois cada entrada é um batch.",
			explain: "É verdade que cada entrada do modelo precisa ser um batch. Entretanto, truncando ou realizando o padding desta sequência não faria necessariamente sentido, pois existe apenas uma delas, e estas são técnicas para criar batches de uma lista de sentenças."
		}
	]}
/>

{/if}


<EditOnGithub source="https://github.com/huggingface/course/blob/main/chapters/pt/chapter2/8.mdx" />

### Tokenizers
https://huggingface.co/learn/course/pt/chapter2/4.md

# Tokenizers

{#if fw === 'pt'}

<CourseFloatingBanner chapter={2}
  classNames="absolute z-10 right-0 top-0"
  notebooks={[
    {label: "Google Colab", value: "https://colab.research.google.com/github/huggingface/notebooks/blob/master/course/pt/chapter2/section4_pt.ipynb"},
    {label: "Aws Studio", value: "https://studiolab.sagemaker.aws/import/github/huggingface/notebooks/blob/master/course/pt/chapter2/section4_pt.ipynb"},
]} />

{:else}

<CourseFloatingBanner chapter={2}
  classNames="absolute z-10 right-0 top-0"
  notebooks={[
    {label: "Google Colab", value: "https://colab.research.google.com/github/huggingface/notebooks/blob/master/course/pt/chapter2/section4_tf.ipynb"},
    {label: "Aws Studio", value: "https://studiolab.sagemaker.aws/import/github/huggingface/notebooks/blob/master/course/pt/chapter2/section4_tf.ipynb"},
]} />

{/if}

<Youtube id="VFp38yj8h3A"/>

Os Tokenizers são um dos componentes centrais do pipeline da PNL. Eles têm um propósito: traduzir texto em dados que podem ser processados pelo modelo. Os modelos só podem processar números, portanto os tokenizers precisam converter nossas entradas de texto em dados numéricos. Nesta seção, vamos explorar exatamente o que acontece no pipeline de tokenização. 

Nas tarefas de PNL, os dados que são geralmente processados são texto bruto. Aqui está um exemplo de tal texto:

```
Jim Henson was a puppeteer
```

Entretanto, os modelos só podem processar números, portanto, precisamos encontrar uma maneira de converter o texto bruto em números. Isto é o que os tokenizers fazem, e há muitas maneiras de se fazer isso. O objetivo é encontrar a representação mais significativa - ou seja, a que faz mais sentido para o modelo - e, se possível, a menor representação.

Vamos dar uma olhada em alguns exemplos de algoritmos de tokenização, e tentar responder algumas das perguntas que você possa ter sobre tokenização.

## Baseado em palavras (word-based)

<Youtube id="nhJxYji1aho"/>

O primeiro tipo de tokenizer que me vem à mente é _baseado em palavras_. É geralmente muito fácil de instalar e usar com apenas algumas regras, e muitas vezes produz resultados decentes. Por exemplo, na imagem abaixo, o objetivo é dividir o texto bruto em palavras e encontrar uma representação numérica para cada uma delas:

<div class="flex justify-center">
  <img class="block dark:hidden" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter2/word_based_tokenization.svg" alt="Um exemplo de tokenização baseado em palavras."/>
  <img class="hidden dark:block" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter2/word_based_tokenization-dark.svg" alt="Um exemplo de tokenização baseado em palavras."/>
</div>

Há diferentes maneiras de dividir o texto. Por exemplo, poderíamos utilizar o espaço em branco para simbolizar o texto em palavras, usando a função `split()` do Python:

```py
tokenized_text = "Jim Henson was a puppeteer".split()
print(tokenized_text)
```

```python out
['Jim', 'Henson', 'was', 'a', 'puppeteer']
```

Há também variações de tokenizers de palavras que têm regras extras para pontuação. Com este tipo de tokenizer, podemos terminar com alguns "vocabulários" bem grandes, onde um vocabulário é definido pelo número total de tokens independentes que tem no texto de exemplo.

A cada palavra é atribuída uma identificação, começando em 0 e indo até o tamanho do vocabulário. O modelo utiliza estas identificações para identificar cada palavra.

Se quisermos cobrir completamente um idioma com um tokenizer baseado em palavras, precisaremos ter um identificador para cada palavra no idioma, o que gerará uma enorme quantidade de tokens. Por exemplo, existem mais de 500.000 palavras no idioma inglês, portanto, para construir um mapa a partir de cada palavra para um ID de entrada, precisaríamos manter um registro desse grande número de IDs. Além disso, palavras como "dog" são representadas de forma diferente de palavras como "dogs", e o modelo inicialmente não terá como saber que "dog" e "dogs" são semelhantes: ele identificará as duas palavras como não relacionadas. O mesmo se aplica a outras palavras semelhantes, como "run" e "running", que o modelo não verá inicialmente como sendo semelhantes.


Finalmente, precisamos de token personalizada para representar palavras que não estão em nosso vocabulário. Isto é conhecido como o símbolo "unknown" (desconhecido), frequentemente representado como "[UNK]" ou "&lt;unk&gt;". Geralmente é um mau sinal se você vê que o tokenizer está produzindo muitos desses tokens, pois não foi capaz de recuperar uma representação sensata de uma palavra e você está perdendo informações ao longo do caminho. O objetivo ao elaborar o vocabulário é fazê-lo de tal forma que o tokenizer transforme o menor número possível de palavras no token desconhecido.

Uma maneira de reduzir a quantidade de tokens desconhecidas é ir um nível mais fundo, usando um tokenizer _baseado em caracteres_.

## Baseado em caracteres (Character-based)

<Youtube id="ssLq_EK2jLE"/>

Os tokenizers baseados em caracteres dividem o texto em caracteres, ao invés de palavras. Isto tem dois benefícios principais:

- O vocabulário será muito menor;
- Há muito menos tokes fora de vocabulário (desconhecidas), uma vez que cada palavra pode ser construída a partir de personagens.

Mas também aqui surgem algumas questões sobre os espaços e à pontuação:

<div class="flex justify-center">
  <img class="block dark:hidden" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter2/character_based_tokenization.svg" alt="Um exemplo de tokenização baseado em caracteres."/>
  <img class="hidden dark:block" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter2/character_based_tokenization-dark.svg" alt="Um exemplo de tokenização baseado em caracteres."/>
</div>

Esta abordagem também não é perfeita. Como a representação agora é baseada em caracteres e não em palavras, pode-se argumentar que, intuitivamente, ela é menos significativa: cada caractere não significa muito por si só, ao contrario do caso das palavras. No entanto, isto novamente difere de acordo com o idioma; em chinês, por exemplo, cada caractere traz mais informações do que um caractere em um idioma latino.

Outra coisa a considerar é que acabaremos com uma quantidade muito grande de tokens a serem processadas por nosso modelo: enquanto uma palavra seria apenas um único token com um tokenizer baseado em palavras, ela pode facilmente se transformar em 10 ou mais tokens quando convertida em caracteres.


Para obter o melhor dos dois mundos, podemos usar uma terceira técnica que combina as duas abordagens: *Tokenização por sub-palavras*.

## Tokenização por sub-palavras (Subword tokenization)

<Youtube id="zHvTiHr506c"/>

Algoritmos de tokenização de sub-palavras baseiam-se no princípio de que palavras frequentemente usadas não devem ser divididas em sub-palavras menores, mas palavras raras devem ser decompostas em sub-palavras significativas.

Por exemplo, "irritantemente" poderia ser considerado uma palavra rara e poderia ser decomposto em "irritante" e "mente". É provável que ambas apareçam mais frequentemente como sub-palavras isoladas, enquanto ao mesmo tempo o significado de "irritantemente" é mantido pelo significado composto de "irritante" e "mente".

Aqui está um exemplo que mostra como um algoritmo de tokenização de uma sub-palavra indicaria a sequência "Let's do tokenization!

<div class="flex justify-center">
  <img class="block dark:hidden" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter2/bpe_subword.svg" alt="Exemplo de algoritmo de tokenização por sub-palavras."/>
  <img class="hidden dark:block" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter2/bpe_subword-dark.svg" alt="Exemplo de algoritmo de tokenização por sub-palavras."/>
</div>

Estas sub-palavras acabam fornecendo muito significado semântico: por exemplo, no exemplo acima "tokenization" foi dividido em "token" e "ization", dois tokens que têm um significado semântico enquanto são eficientes em termos de espaço (apenas dois tokens são necessários para representar uma palavra longa). Isto nos permite ter uma cobertura relativamente boa com pequenos vocabulários, e perto de nenhum token desconhecido.


Esta abordagem é especialmente útil em idiomas aglutinativos como o turco, onde é possível formar palavras (quase) arbitrariamente longas e complexas, encadeando sub-palavras.

### E outros!

Sem surpresas, há muito mais técnicas por aí. Para citar algumas:

- Byte-level BPE, utilizada no GPT-2
- WordPiece, utilizada em BERT
- SentencePiece ou Unigram, como as utilizadas em vários modelos  multilíngue

Agora você deve ter conhecimento suficiente de como funcionam os tokenizers para começar a utilizar a API.

## Carregando e salvando

Carregando e salvando tokenizers é tão simples quanto com os modelos. Na verdade, ele se baseia nos mesmos dois métodos: `from_pretrained()` e `save_pretrained()`. Estes métodos irão carregar ou salvar o algoritmo utilizado pelo tokenizer (um pouco como a *arquitetura* do modelo), bem como seu vocabulário (um pouco como os *pesos* do modelo).

O carregamento do tokenizer BERT treinado com o mesmo checkpoint do BERT é feito da mesma forma que o carregamento do modelo, exceto que utilizamos a classe `BertTokenizer`:

```py
from transformers import BertTokenizer

tokenizer = BertTokenizer.from_pretrained("bert-base-cased")
```

{#if fw === 'pt'}
Similar ao `AutoModel`, a classe `AutoTokenizer` ira carregar a classe tokenizer apropriada na biblioteca com base no nome do checkpoint, e pode ser utilizada diretamente com qualquer checkpoint:

{:else}
Similar ao `TFAutoModel`, a classe `AutoTokenizer` ira carregar a classe tokenizer apropriada na biblioteca com base no nome do checkpoint, e pode ser utilizada diretamente com qualquer checkpoint:

{/if}

```py
from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("bert-base-cased")
```

Agora podemos usar o tokenizer, como mostrado na seção anterior:

```python
tokenizer("Using a Transformer network is simple")
```

```python out
{'input_ids': [101, 7993, 170, 11303, 1200, 2443, 1110, 3014, 102],
 'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0, 0],
 'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1]}
```

Salvar um tokenizer é idêntico a salvar um modelo:

```py
tokenizer.save_pretrained("directory_on_my_computer")
```


Falaremos mais sobre `token_type_ids' no [Capítulo 3](/course/pt/chapter3), e explicaremos a `attention_mask' um pouco mais tarde. Primeiro, vamos ver como os `input_ids` são gerados. Para fazer isso, precisaremos olhar os métodos intermediários do tokenizer.


## Encoding

<Youtube id="Yffk5aydLzg"/>

Traduzir texto para números é conhecido como _encoding_. O encoding é feito em um processo de duas etapas: a tokenização, seguida pela conversão para IDs de entrada.

Como vimos, o primeiro passo é dividir o texto em palavras (ou partes de palavras, símbolos de pontuação, etc.), normalmente chamadas de *tokens*. Há várias regras que podem guiar esse processo, e é por isso que precisamos instanciar o tokenizer usando o nome do modelo, para nos certificarmos de usar as mesmas regras que foram usadas quando o modelo foi pré-treinado.

O segundo passo é converter esses tokens em números, para que possamos construir um tensor a partir deles e alimentá-los com o modelo. Para isso, o tokenizer tem um *vocabulário* (vocabulary), que é a parte que realizamos o download quando o instanciamos com o método `from_pretrained()`. Mais uma vez, precisamos utilizar o mesmo vocabulário utilizado quando o modelo foi pré-treinado.

Para entender melhor os dois passos, vamos explorá-los separadamente. Note que usaremos alguns métodos que executam partes da pipeline de tokenização separadamente para mostrar os resultados intermediários dessas etapas, mas na prática, você deve chamar o tokenizer diretamente em suas entradas (como mostrado na seção 2).

### Tokenização

O processo de tokenization é feito através do método `tokenize()` do tokenizer:

```py
from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("bert-base-cased")

sequence = "Using a Transformer network is simple"
tokens = tokenizer.tokenize(sequence)

print(tokens)
```

A saída deste método é uma lista de strings, ou tokens:

```python out
['Using', 'a', 'transform', '##er', 'network', 'is', 'simple']
```

Este tokenizer é um tokenizer de sub-palavras: ele divide as palavras até obter tokens que podem ser representadas por seu vocabulário. É o caso aqui do "transformer", que é dividido em dois tokens: "transform" e "##er".

### Desde os tokens até IDs de entrada

A conversão para IDs de entrada é feita pelo método de tokenização `convert_tokens_to_ids()`:

```py
ids = tokenizer.convert_tokens_to_ids(tokens)

print(ids)
```

```python out
[7993, 170, 11303, 1200, 2443, 1110, 3014]
```

Estas saídas, uma vez convertidas no tensor com a estrutura apropriada, podem então ser usadas como entradas para um modelo como visto anteriormente neste capítulo.

<Tip>

✏️ **Experimente realizar isso!** Replicar os dois últimos passos (tokenização e conversão para IDs de entrada) nas frases de entrada que usamos na seção 2 ("I've been waiting for a HuggingFace course my whole life." e "I hate this so much!"). Verifique se você recebe os mesmos IDs de entrada que recebemos antes!

</Tip>

## Decoding

*Decoding* vai pela direção ao contrário: a partir de índices de vocabulário, queremos obter uma string. Isto pode ser feito com o método `decode()` da seguinte forma:


```py
decoded_string = tokenizer.decode([7993, 170, 11303, 1200, 2443, 1110, 3014])
print(decoded_string)
```

```python out
'Using a Transformer network is simple'
```

Observe que o método `decode` não apenas converte os índices em tokens, mas também agrupa os tokens que fizeram parte das mesmas palavras para produzir uma frase legível. Este comportamento será extremamente útil quando utilizamos modelos que preveem um novo texto (seja texto gerado a partir de um prompt, ou para problemas de _sequence-to-sequence_ como tradução ou sumarização).



Até agora você já deve entender as operações atômicas que um tokenizer pode lidar: tokenização, conversão para IDs, e conversão de IDs de volta para uma string. Entretanto, acabamos de começar a ver a ponta do iceberg. Na seção seguinte, vamos nos aproximar de seus limites e dar uma olhada em como superá-los.

<EditOnGithub source="https://github.com/huggingface/course/blob/main/chapters/pt/chapter2/4.mdx" />

### Uso básico concluído!
https://huggingface.co/learn/course/pt/chapter2/7.md

# Uso básico concluído!

<CourseFloatingBanner
    chapter={2}
    classNames="absolute z-10 right-0 top-0"
/>

Ótimo trabalho seguindo o curso até aqui! Recapitulando, neste capítulo, você:

- Aprendeu os elementos básicos de um modelo Transformer.
- Aprendeu que compõe o pipeline de tokenização.
- Vou como utilizar um transformer na prática.
- Aprendeu como aproveitar um tokenizer para converter texto em tensores que são compreensíveis pelo modelo.
- Montar um tokenizer e um modelo juntos para ir do texto às previsões.
- Aprendeu as limitações dos IDs de entrada e aprendeu sobre máscaras de atenção.
- Testou os métodos de tokenizer versáteis e configuráveis.

De agora em diante, você deve ser capaz de navegar livremente pelos documentos dos 🤗 transformers: o vocabulário soará familiar, e você já viu os métodos que utilizará na maior parte do tempo.


<EditOnGithub source="https://github.com/huggingface/course/blob/main/chapters/pt/chapter2/7.mdx" />

### Por dentro da função pipeline
https://huggingface.co/learn/course/pt/chapter2/2.md

# Por dentro da função pipeline

{#if fw === 'pt'}

<CourseFloatingBanner chapter={2}
  classNames="absolute z-10 right-0 top-0"
  notebooks={[
    {label: "Google Colab", value: "https://colab.research.google.com/github/huggingface/notebooks/blob/master/course/pt/chapter2/section2_pt.ipynb"},
    {label: "Aws Studio", value: "https://studiolab.sagemaker.aws/import/github/huggingface/notebooks/blob/master/course/pt/chapter2/section2_pt.ipynb"},
]} />

{:else}

<CourseFloatingBanner chapter={2}
  classNames="absolute z-10 right-0 top-0"
  notebooks={[
    {label: "Google Colab", value: "https://colab.research.google.com/github/huggingface/notebooks/blob/master/course/pt/chapter2/section2_tf.ipynb"},
    {label: "Aws Studio", value: "https://studiolab.sagemaker.aws/import/github/huggingface/notebooks/blob/master/course/pt/chapter2/section2_tf.ipynb"},
]} />

{/if}

<Tip>
Esta é a primeira seção onde o conteúdo é ligeiramente diferente, dependendo se você usa PyTorch e TensorFlow. Para selecionar a plataforma que você prefere, basta alterar no botão no topo.
</Tip>

{#if fw === 'pt'}
<Youtube id="1pedAIvTWXk"/>
{:else}
<Youtube id="wVN12smEvqg"/>
{/if}

Vamos começar com um exemplo completo, dando uma olhada no que acontece dentro da função quando executamos o seguinte código no [Capítulo 1](/course/pt/chapter1):

```python
from transformers import pipeline

classifier = pipeline("sentiment-analysis")
classifier(
    [
        "I've been waiting for a HuggingFace course my whole life.",
        "I hate this so much!",
    ]
)
```

tendo o resultado:

```python out
[{'label': 'POSITIVE', 'score': 0.9598047137260437},
 {'label': 'NEGATIVE', 'score': 0.9994558095932007}]
```

Como visto no [Capítulo 1](/course/pt/chapter1), este pipeline agrupa os três passos: o pré-processamento, passagem das entradas através do modelo, e o pós-processamento:

<div class="flex justify-center">
<img class="block dark:hidden" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter2/full_nlp_pipeline.svg" alt="O pipeline NLP completa: tokenização do texto, conversão para IDs, e inferência através do Transformer e pela 'cabeça' do modelo."/>
<img class="hidden dark:block" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter2/full_nlp_pipeline-dark.svg" alt="O pipeline NLP completa: tokenização do texto, conversão para IDs, e inferência através do Transformer e pela 'cabeça' do modelo."/>
</div>

Vamos rever rapidamente cada um deles.

## Pré-processamento com o tokenizer

Como outras redes neurais, os Transformers não podem processar texto bruto diretamente, portanto, o primeiro passo do nosso pipeline é converter as entradas de texto em números que o modelo possa fazer sentido. Para fazer isso, usamos um *tokenizer*, que será responsável por:

- Dividir a entrada em palavras, sub-palavras ou símbolos (como pontuação) que são chamados de *tokens*.
- Mapeando cada ficha para um número inteiro
- Adicionando entradas adicionais que podem ser úteis ao modelo

Todo esse pré-processamento precisa ser feito exatamente da mesma forma que quando o modelo foi pré-treinado, então precisamos primeiro baixar essas informações do [Model Hub](https://huggingface.co/models). Para isso, utilizamos a classe `AutoTokenizer` e seu método `from_pretrained()`. Utilizando o nome do ponto de verificação de nosso modelo, ele irá buscar automaticamente os dados associados ao tokenizer do modelo e armazená-los em cache (portanto, ele só é baixado na primeira vez que você executar o código abaixo).

Desde que o checkpoint default do pipeline `sentiment-analysis` é `distilbert-base-uncased-finetuned-sst-2-english` (você pode ver o card do modelo [aqui](https://huggingface.co/distilbert-base-uncased-finetuned-sst-2-english)), então executamos o seguinte:

```python
from transformers import AutoTokenizer

checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
```

Assim que tivermos o tokenizer, podemos passar diretamente nossas frases para ele e receberemos de volta um dicionário que está pronto para alimentar nosso modelo! A única coisa que falta fazer é converter a lista de identificações de entrada em tensores.

Você pode usar 🤗 Transformers sem ter que se preocupar com qual estrutura ML é usada como backend; pode ser PyTorch ou TensorFlow, ou Flax para alguns modelos. Entretanto, os Transformers só aceitam *tensores* como entrada. Se esta é a primeira vez que você ouve falar de tensores, você pode pensar neles como matrizes da NumPy. Uma matriz NumPy pode ser um escalar (0D), um vetor (1D), uma matriz (2D), ou ter mais dimensões. É efetivamente um tensor; os tensores de outras estruturas ML comportam-se de forma semelhante, e geralmente são tão simples de instanciar como os arrays da NumPy.

Para especificar o tipo de tensores que queremos recuperar (PyTorch, TensorFlow ou NumPy), utilizamos o argumento `return_tensors`:

{#if fw === 'pt'}
```python
raw_inputs = [
    "I've been waiting for a HuggingFace course my whole life.",
    "I hate this so much!",
]
inputs = tokenizer(raw_inputs, padding=True, truncation=True, return_tensors="pt")
print(inputs)
```
{:else}
```python
raw_inputs = [
    "I've been waiting for a HuggingFace course my whole life.",
    "I hate this so much!",
]
inputs = tokenizer(raw_inputs, padding=True, truncation=True, return_tensors="tf")
print(inputs)
```
{/if}

Não se preocupe ainda com o truncamento e o padding; explicaremos isso mais tarde. As principais coisas a lembrar aqui são que você pode passar uma frase ou uma lista de frases, bem como especificar o tipo de tensores que você quer recuperar (se nenhum tipo for passado, você receberá uma lista de listas como resultado).

{#if fw === 'pt'}

Eis como são os resultados como tensores PyTorch:

```python out
{
    'input_ids': tensor([
        [  101,  1045,  1005,  2310,  2042,  3403,  2005,  1037, 17662, 12172, 2607,  2026,  2878,  2166,  1012,   102],
        [  101,  1045,  5223,  2023,  2061,  2172,   999,   102,     0,     0,     0,     0,     0,     0,     0,     0]
    ]), 
    'attention_mask': tensor([
        [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
        [1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
    ])
}
```
{:else}

Eis como são os resultados como tensores TensorFlow:

```python out
{
    'input_ids': <tf.Tensor: shape=(2, 16), dtype=int32, numpy=
        array([
            [  101,  1045,  1005,  2310,  2042,  3403,  2005,  1037, 17662, 12172,  2607,  2026,  2878,  2166,  1012,   102],
            [  101,  1045,  5223,  2023,  2061,  2172,   999,   102,     0,     0,     0,     0,     0,     0,     0,     0]
        ], dtype=int32)>, 
    'attention_mask': <tf.Tensor: shape=(2, 16), dtype=int32, numpy=
        array([
            [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
            [1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
        ], dtype=int32)>
}
```
{/if}

A saída em si é um dicionário contendo duas chaves, `input_ids' e `attention_mask'. O `input_ids' contém duas linhas de inteiros (uma para cada frase) que são os identificadores únicos dos tokens em cada frase. Explicaremos o que é a "máscara de atenção" (attention mask) mais adiante neste capítulo. 

## Indo adianta pelo modelo

{#if fw === 'pt'}
Podemos baixar nosso modelo pré-treinado da mesma forma que fizemos com nosso tokenizer. 🤗 Transformers fornece uma classe `AutoModel` que também tem um método `from_pretrained()`:

```python
from transformers import AutoModel

checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
model = AutoModel.from_pretrained(checkpoint)
```
{:else}
Podemos baixar nosso modelo pré-treinado da mesma forma que fizemos com nosso tokenizer. 🤗 Transformers fornece uma classe "TFAutoModel" que também tem um método "from_pretrained":


```python
from transformers import TFAutoModel

checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
model = TFAutoModel.from_pretrained(checkpoint)
```
{/if}

Neste trecho de código, fizemos o download do mesmo checkpoint que usamos anteriormente em nosso pipeline (já deveria estar em cache) e instanciamos um modelo com ele.

Esta arquitetura contém apenas o módulo base do Transformer: dadas algumas entradas, ele produz o que chamaremos de *hidden states* (estados ocultos), também conhecidos como *features* (características). Para cada modelo de entrada, recuperaremos um vetor de alta dimensionalidade representando a **compreensão contextual dessa entrada pelo Transformer***.

Se isto não faz sentido, não se preocupe com isso. Explicaremos tudo isso mais tarde.

Embora estes hidden states possam ser úteis por si mesmos, eles geralmente são entradas para outra parte do modelo, conhecida como *head* (cabeça). No [Capítulo 1](/course/pt/chapter1), as diferentes tarefas poderiam ter sido realizadas com a mesma arquitetura, mas cada uma destas tarefas teria uma head diferente associada a ela.

### Um vetor de alta dimensionalidade?

A saída vetorial pelo módulo do Transformer é geralmente grande. Geralmente tem três dimensões:

- **Tamanho do lote** (Batch size): O número de sequências processadas de cada vez (2 em nosso exemplo).
- **Tamanho da sequencia** (Sequence length): O comprimento da representação numérica da sequência (16 em nosso exemplo).
- **Tamanho oculto** (Hidden size): A dimensão vetorial de cada modelo de entrada.

Diz-se que é "de alta dimensionalidade" por causa do último valor. O tamanho oculto pode ser muito grande (768 é comum para modelos menores, e em modelos maiores isto pode chegar a 3072 ou mais).

Podemos ver isso se alimentarmos os inputs que pré-processamos para nosso modelo:

{#if fw === 'pt'}
```python
outputs = model(**inputs)
print(outputs.last_hidden_state.shape)
```

```python out
torch.Size([2, 16, 768])
```
{:else}
```py
outputs = model(inputs)
print(outputs.last_hidden_state.shape)
```

```python out
(2, 16, 768)
```
{/if}

Observe que as saídas dos 🤗 Transformer se comportam como 'tuplas nomeadas' (namedtuple) ou dicionários. Você pode acessar os elementos por atributos (como fizemos) ou por chave (`outputs["last_hidden_state"]`), ou mesmo por índice se você souber exatamente onde o que está procurando (`outputs[0]`).

### Cabeça do modelo (model heads): Fazendo sentido a partir dos números

As *heads* do modelo usam o vetor de alta dimensionalidade dos hidden states como entrada e os projetam em uma dimensão diferente. Eles são geralmente compostos de uma ou algumas camadas lineares:

<div class="flex justify-center">
<img class="block dark:hidden" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter2/transformer_and_head.svg" alt="Uma rede Transformer ao lado de sua head."/>
<img class="hidden dark:block" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter2/transformer_and_head-dark.svg" alt="Uma rede Transformer ao lado de sua head."/>
</div>

A saída do Transformer é enviada diretamente para a *head* do modelo a ser processado.

Neste diagrama, o modelo é representado por sua camada de embeddings (vetores) e pelas camadas subsequentes. A camada de embeddings converte cada ID de entrada na entrada tokenizada em um vetor que representa o token associado. As camadas subsequentes manipulam esses vetores usando o mecanismo de atenção para produzir a representação final das sentenças.

Há muitas arquiteturas diferentes disponíveis no 🤗 Transformers, com cada uma projetada em torno de uma tarefa específica. Aqui está uma lista por **algumas** destas tarefas:

- `*Model` (recuperar os hidden states)
- `*ForCausalLM`
- `*ForMaskedLM`
- `*ForMultipleChoice`
- `*ForQuestionAnswering`
- `*ForSequenceClassification`
- `*ForTokenClassification`
- e outros 🤗

{#if fw === 'pt'}
Para nosso exemplo, precisaremos de um modelo com uma *head* de classificação em sequencia (para poder classificar as sentenças como positivas ou negativas). Portanto, não utilizaremos a classe `AutoModel`, mas sim, a classe `AutoModelForSequenceClassification`:

```python
from transformers import AutoModelForSequenceClassification

checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
model = AutoModelForSequenceClassification.from_pretrained(checkpoint)
outputs = model(**inputs)
```
{:else}
Para nosso exemplo, precisaremos de um modelo com uma *head* de classificação em sequencia (para poder classificar as sentenças como positivas ou negativas). Portanto, não utilizaremos a classe `TFAutoModel`, mas sim, a classe `TFAutoModelForSequenceClassification`:

```python
from transformers import TFAutoModelForSequenceClassification

checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
model = TFAutoModelForSequenceClassification.from_pretrained(checkpoint)
outputs = model(inputs)
```
{/if}

Agora se observarmos o tamanho dos nossos inputs, a dimensionalidade será muito menor: a *head* do modelo toma como entrada os vetores de alta dimensionalidade que vimos anteriormente, e os vetores de saída contendo dois valores (um por label):

```python
print(outputs.logits.shape)
```

{#if fw === 'pt'}
```python out
torch.Size([2, 2])
```
{:else}
```python out
(2, 2)
```
{/if}

Como temos apenas duas sentenças e duas labels, o resultado que obtemos de nosso modelo é de tamanho 2 x 2.

## Pós-processamento da saída

Os valores que obtemos como resultado de nosso modelo não fazem necessariamente sentido sozinhos. Vamos dar uma olhada:

```python
print(outputs.logits)
```

{#if fw === 'pt'}
```python out
tensor([[-1.5607,  1.6123],
        [ 4.1692, -3.3464]], grad_fn=<AddmmBackward>)
```
{:else}
```python out
<tf.Tensor: shape=(2, 2), dtype=float32, numpy=
    array([[-1.5606991,  1.6122842],
           [ 4.169231 , -3.3464472]], dtype=float32)>
```
{/if}

Nosso modelo previu `[-1.5607, 1.6123]` para a primeira frase e `[ 4.1692, -3.3464]` para a segunda. Essas não são probabilidades, mas *logits*, a pontuação bruta e não normalizada produzida pela última camada do modelo. Para serem convertidos em probabilidades, eles precisam passar por uma camada [SoftMax](https://en.wikipedia.org/wiki/Softmax_function) (todas saídas dos 🤗 Transformers produzem  *logits*, já que a função de *loss* (perda) para treinamento geralmente fundirá a última função de ativação, como SoftMax, com a função de *loss* real, por exemplo a *cross entropy*):

{#if fw === 'pt'}
```py
import torch

predictions = torch.nn.functional.softmax(outputs.logits, dim=-1)
print(predictions)
```
{:else}
```py
import tensorflow as tf

predictions = tf.math.softmax(outputs.logits, axis=-1)
print(predictions)
```
{/if}

{#if fw === 'pt'}
```python out
tensor([[4.0195e-02, 9.5980e-01],
        [9.9946e-01, 5.4418e-04]], grad_fn=<SoftmaxBackward>)
```
{:else}
```python out
tf.Tensor(
[[4.01951671e-02 9.59804833e-01]
 [9.9945587e-01 5.4418424e-04]], shape=(2, 2), dtype=float32)
```
{/if}

Agora podemos ver que o modelo previu `[0.0402, 0.9598]` para a primeira frase e `[0.9995, 0.0005]` para a segunda. Estas são pontuações de probabilidade reconhecíveis.

Para obter as etiquetas correspondentes a cada posição, podemos inspecionar o atributo `id2label` da configuração do modelo (mais sobre isso na próxima seção):

```python
model.config.id2label
```

```python out
{0: 'NEGATIVE', 1: 'POSITIVE'}
```

Agora podemos concluir que o modelo previu o seguinte:

- A primeira frase: NEGATIVE: 0.0402, POSITIVE: 0.9598
- Segunda frase: NEGATIVE: 0.9995, POSITIVE: 0.0005

Reproduzimos com sucesso as três etapas do pipeline: o pré-processamento, passagem das entradas através do modelo, e o pós-processamento! Agora, vamos levar algum tempo para mergulhar mais fundo em cada uma dessas etapas.

<Tip>

✏️ **Experimente!** Escolha duas (ou mais) textos próprios e passe-os através do pipeline `sentiment-analysis`. Em seguida, replique as etapas que você mesmo viu aqui e verifique se você obtém os mesmos resultados!

</Tip>


<EditOnGithub source="https://github.com/huggingface/course/blob/main/chapters/pt/chapter2/2.mdx" />

### Introdução
https://huggingface.co/learn/course/pt/chapter0/1.md

# Introdução

Bem-vindo(a) ao curso da Hugging Face! Essa introdução te guiará para a configuração do ambiente de trabalho. Se você está começando agora o curso, nós recomendamos que você primeiramente dê uma olhada no [Capítulo 1](/course/chapter1), para só então voltar aqui, configurar o ambiente e começar a por a mão no código.

Todas as bibliotecas que usaremos nesse curso estão disponíveis como pacotes do Python, então aqui iremos te mostrar como configurar o ambiente no Python e instalar as bibliotecas específicas que você precisará.

Abordaremos 2 modos de configurar o ambiente, usando um Colab notebook ou um ambiente virtual Python. Fique à vontade para escolher o que mais fizer sentido para você.  Para os iniciantes, recomendamos fortemente que vocês iniciem pelo Colab notebook.

Note que nós não iremos cobrir o básico sobre o Windows. Se você estiver usando o Windows, recomendamos seguir as instruções pelo Colab notebook. Se estiver usando Linux ou macOS, você pode escolher qualquer uma das abordagens descritas aqui.

A maior parte do curso depende de você ter uma conta na Hugging Face. Recomendamos criar uma agora [criar uma conta](https://huggingface.co/join).

## Usando um notebook Google Colab
Usar um notebook Colab é a maneira mais simples possível de configuração, coloque um notebook no seu navegador e se prepare para a codificação!

Se você não está familiarizado com o Colab, recomendamos seguir essa [introdução]
(https://colab.research.google.com/notebooks/intro.ipynb). O Colab permitirá você usar algumas acelerações de hardware, como GPUs ou TPUs, e é gratuito para ambientes de trabalho pequenos.

Uma vez que você estiver confortável com o ambiente do Colab, crie um novo notebook e comece com essa configuração:

<div class="flex justify-center">
<img src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter0/new_colab.png" alt="An empty colab notebook" width="80%"/>
</div>

O próximo passo é instalar as bibliotecas que serão usadas nesse curso. Usaremos `pip` para a instalação, que é o gerenciador de pacotes do Python. Nos notebooks, você pode rodar os comandos do sistema precedendo do caractere `!`, então você poderá instalar a biblioteca 🤗 Transformers da seguinte forma:

```
!pip install transformers
```

Você pode assegurar que o pacote foi instalado corretamente por meio de sua importação dentro do ambiente de execução do Python:

```
import transformers
```

<div class="flex justify-center">
<img src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter0/install.gif" alt="A gif showing the result of the two commands above: installation and import" width="80%"/>
</div>

Isso instalará uma versão bem leve da 🤗 Transformers. Em particular, nenhum framework de aprendizagem de máquina (como PyTorch ou TensorFlow) estão instalados. Desde que iremos usar bastante de suas features na biblioteca, recomendamos instalar a versão de desenvolvimento, que vem com todas as dependências requisitadas para cada caso de uso imaginável:

```
!pip install transformers[sentencepiece]
```

Isso levará um pouco de tempo, mas quando acabar você estará pronto/a para seguir o resto do curso!


## Usando um ambiente virtual Python

Se você perferir usar o ambiente virtual Python, o primeiro passo é instalar o Python no seu sistema. Nós recomendamos [esse guia](https://realpython.com/installing-python/) para começar.

Uma vez instalado o Python, você será capaz de rodar os comandos do Python em seu terminal. Você pode iniciar por rodar o seguinte comando para ter certeza que está instalado corretamente antes de iniciar os seguintes passos: `python --version`. Isso irá imprimir na tela a versão do Python disponível no seu sistema.

Quando você rodar um comando Python no seu terminal, como o `python --version`, você deve imaginar como um programa rodando seu comando como o "main" Python no seu sistema. Recomendamos manter essa instalação livre de qualquer pacote, e usando a para criar ambientes separados para cada aplicação que você for trabalhar - desse modo, cada aplicação pode ter suas próprias dependências e pacotes, e você não precisará se preocupar sobre potenciais problemas de compatibilidades com outras aplicações.

No Python isso é feito com [*ambientes virtuais*](https://docs.python.org/3/tutorial/venv.html), que é uma árvore de diretórios que contém a instalação do Python com uma versão particular do mesmo juntamente com todos os pacotes que a aplicação precisa. Criar um ambiente virtual como esse pode ser feito com inúmeras ferramentas, mas usaremos o pacote oficial do Python para esse propósito, que se chama [`venv`](https://docs.python.org/3/library/venv.html#module-venv).

Primeiro, crie o diretório que você gostaria que sua aplicação existisse - por exemplo, você pode querer criar um novo diretório chamado *curso-transformers* na raíz de seu diretório home:

```
mkdir ~/transformers-course
cd ~/transformers-course
```

Dentro desse diretório, crie um ambiente virtual usando o módulo Python `venv`:

```
python -m venv .env
```

Agora você deve ter dentro um diretório chamado *.env* em sua pasta vazia:

```
ls -a
```

```out
.      ..    .env
```

Você pode acessar e sair do seu ambiente virtual com os scripts `activate` e `deactivate`:

```
# Activate the virtual environment
source .env/bin/activate

# Deactivate the virtual environment
deactivate
```

Você pode ter certeza que seu ambiente virtual está ativado rodando o comando `which python`: se ele apontar para o ambiente virtual, então você conseguiu ativa-lo com sucesso!

```
which python
```

```out
/home/<user>/transformers-course/.env/bin/python
```

### Instalando dependências

Como na seção passada usando as instâncias do Google Colab, você precisará instalar os pacotes necessários para continuar. Novamente, você pode instalar a versão de desenvolvimento da 🤗 Transformers usando o gerenciador de pacotes `pip`:

```
pip install "transformers[sentencepiece]"
```

Você agora configurou tudo e está pronto para seguir!


<EditOnGithub source="https://github.com/huggingface/course/blob/main/chapters/pt/chapter0/1.mdx" />

### Resumo
https://huggingface.co/learn/course/pt/chapter1/9.md

# Resumo

<CourseFloatingBanner
    chapter={1}
    classNames="absolute z-10 right-0 top-0"
/>

Nesse capítulo, você viu como abordar diferentes tarefas de NLP usando a função de alto nível `pipeline()` da biblioteca 🤗 Transformers. Você também viu como pesquisar e usar modelos no Hub, bem como usar a API de inferência para testar os modelos diretamente em seu navegador.

Discutimos como os modelos Transformers funcionam em alto nível e falamos sobre a importância do aprendizado de transferência (transfer learning) e do ajuste fino. Um aspecto chave é que você pode usar a arquitetura completa ou apenas o codificador ou decodificador, dependendo do tipo de tarefa que você pretende resolver. A tabela a seguir resume isso:

| Modelo          | Exemplos                                   | Tarefas                                                                          |
|-----------------|--------------------------------------------|----------------------------------------------------------------------------------|
| Encoder         | ALBERT, BERT, DistilBERT, ELECTRA, RoBERTa | Classificação de sentenças, reconhecimento de entidades nomeadas, Q&A            |
| Decoder         | CTRL, GPT, GPT-2, Transformer XL           | Geração de texto                                                                 |
| Encoder-decoder | BART, T5, Marian, mBART                    | Sumarização, tradução, perguntas e respostas gerativas                           |


<EditOnGithub source="https://github.com/huggingface/course/blob/main/chapters/pt/chapter1/9.mdx" />

### Modelos codificadores
https://huggingface.co/learn/course/pt/chapter1/5.md

# Modelos codificadores

<CourseFloatingBanner
    chapter={1}
    classNames="absolute z-10 right-0 top-0"
/>

<Youtube id="MUqNwgPjJvQ" />

Os modelos de encoder (codificadores) usam apenas o encoder de um modelo Transformer. Em cada estágio, as camadas de atenção podem acessar todas as palavras da frase inicial. Esses modelos geralmente são caracterizados como tendo atenção "bidirecional" e são frequentemente chamados de *modelos de codificação automática*.

O pré-treinamento desses modelos geralmente gira em torno de corromper de alguma forma uma determinada frase (por exemplo, mascarando palavras aleatórias nela) e encarregando o modelo de encontrar ou reconstruir a frase inicial.

Os modelos de codificador são mais adequados para tarefas que exigem uma compreensão da sentença completa, como classificação de sentença, reconhecimento de entidade nomeada (e, mais geralmente, classificação de palavras) e resposta extrativa de perguntas.

Os representantes desta família de modelos incluem:

- [ALBERT](https://huggingface.co/transformers/model_doc/albert.html)
- [BERT](https://huggingface.co/transformers/model_doc/bert.html)
- [DistilBERT](https://huggingface.co/transformers/model_doc/distilbert.html)
- [ELECTRA](https://huggingface.co/transformers/model_doc/electra.html)
- [RoBERTa](https://huggingface.co/transformers/model_doc/roberta.html)


<EditOnGithub source="https://github.com/huggingface/course/blob/main/chapters/pt/chapter1/5.mdx" />

### Introdução
https://huggingface.co/learn/course/pt/chapter1/1.md

# Introdução

<CourseFloatingBanner
    chapter={1}
    classNames="absolute z-10 right-0 top-0"
/>

## Bem-vindo(a) ao Curso 🤗!

<Youtube id="00GKzGyWFEs" />

Esse curso te ensinará sobre processamento de linguagem natural (PLN, ou NLP em inglês) usando as bibliotecas do ecossistema [Hugging Face](https://huggingface.co/) — [🤗 Transformers](https://github.com/huggingface/transformers), [🤗 Datasets](https://github.com/huggingface/datasets), [🤗 Tokenizers](https://github.com/huggingface/tokenizers) e [🤗 Accelerate](https://github.com/huggingface/accelerate) — assim como a [Hugging Face Hub](https://huggingface.co/models). É completamente gratuito e sem anúncios!


## O que esperar?

Aqui uma visão geral do curso:

<div class="flex justify-center">
<img class="block dark:hidden" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter1/summary.svg" alt="Brief overview of the chapters of the course.">
<img class="hidden dark:block" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter1/summary-dark.svg" alt="Brief overview of the chapters of the course.">
</div>

- Capítulos 1 ao 4 dá uma introdução para os principais conceitos da biblioteca Transformers 🤗. No final dessa parte do curso, você se tornará familiar sobre como os modelos Transformers funcionam, saberá como usar o modelo da [Hugging Face Hub](https://huggingface.co/models), fazer um ajuste fino em um dataset e compartilhar os resultados no Hub!
- Capítulo 5 ao 8 ensina o básico dos 🤗 Datasets e 🤗 Tokenizadores antes de mergulhar nas tarefas clássicas de NLP. Ao final dessa parte, você será capaz de resolver por conta própria os problemas mais comuns de NLP. Ao longo do caminho, você aprenderá como construir e compartilhar demonstrações de seus modelos e otimiza-los para ambientes de produção. No final dessa parte, você será capaz de aplicar a 🤗 Transformers para (quase) qualquer problema de aprendizagem de máquina!

Esse curso:
* Requer um bom conhecimento de Python
* É melhor aproveitado depois de um curso de introdução ao deep learning (aprendizagem profunda), como o da [fast.ai](https://www.fast.ai/) [Practical Deep Learning for Coders](https://course.fast.ai/)  ou um dos programas desenvolvidos pela [DeepLearning.AI](https://www.deeplearning.ai/)
* Não se espera nenhum conhecimento prévio em [PyTorch](https://pytorch.org/)  ou em [TensorFlow](https://www.tensorflow.org/) , ainda que certa familiaridade com ambas as ferramentas seja proveitoso

Depois de você ter completado esse curso, nós recomendamos dar uma olhada na especialização da DeepLearning.AI de [Processamento de Linguagem Natural](https://www.coursera.org/specializations/natural-language-processing?utm_source=deeplearning-ai&utm_medium=institutions&utm_campaign=20211011-nlp-2-hugging_face-page-nlp-refresh), que cobre uma grande gama de modelos de NLP como naive Bayes e LSTMs que valem bastante a pena ter conhecimento!

## Quem nós somos?

Sobre os autores:

**Matthew Carrigan** é Engenheiro de Machine Learning na Hugging Face. Ele mora em Dublin na Irlanda e anteriormente trabalhou como Engenheiro de ML na Parse.ly e antes disso como pesquisador pós-doc na Trinity College Dublin. Ele não acredita que chegaremos a um rendimento anual bruto corrigido escalando as arquiteturas existentes, mas de qualquer forma ele tem grandes esperanças na imortalidade das máquinas.

**Lysandre Debut** é um Engenheiro de Machine Learning na Hugging Face e tem trabalhado para a biblioteca 🤗 Transformers desde seus estágios iniciais de desenvolvimento. Seu objetivo é fazer com que a área de NLP se torne acessível para qualquer pessoa através do desenvolvimento de ferramentas com uma API simples.

**Sylvain Gugger** é um Engenheiro Pesquisador na Hugging Face e um dos principais mantenedores da biblioteca 🤗 Transformers. Anteriormente ele foi Cientista Pesquisador na fast.ai, e co-escreveu _[Deep Learning for Coders with fastai and PyTorch](https://learning.oreilly.com/library/view/deep-learning-for/9781492045519/)_ com Jeremy Howard. O principal foco de sua pesquisa está em fazer o deep learning mais acessível, através de desenhos e técnicas de aprimoramento que permitam que modelos sejam treinados mais rápidos e com recursos limitados.

**Merve Noyan** é um desenvolvedor e evangelista na Hugging Face, trabalhando no desenvolvimento e construção de conteúdos envolta da temática de democratização do Machine Learning para todas as pessoas.

**Lucile Saulnier** é uma Engenheira de Machine Learning na Hugging Face, desenvolvendo e apoiando o uso de ferramentas de código aberto. Ela também é ativamente envolvida em muitos projetos de pesquisa no campo do Processamento de Linguagem natural assim como em treinamentos colaborativos e BigScience.

**Lewis Tunstall**  é um Engenheiro de Machine Learning na Hugging Face, focado no desenvolvimento de ferramentas open-source e em fazê-las amplamente acessíveis pela comunidade. Ele também é co-autor do livro que está pra lançar [O’Reilly book on Transformers](https://www.oreilly.com/library/view/natural-language-processing/9781098136789/).

**Leandro von Werra**  é um Engenheiro de Machine Learning no time de open-source na Hugging Face e também co-autor do livro [O’Reilly book on Transformers](https://www.oreilly.com/library/view/natural-language-processing/9781098136789/). Ele tem muitos anos de experiência na indústria trazendo projetos de NLP para produção trabalhando com várias stacks de Machine Learning.

Está pronto para seguir? Nesse capítulo, você aprenderá:
* Como usar a função `pipeline()`  para solucionar tarefas de NLP tais como geração de texto e classificação
* Sobre a arquitetura Transformer
* Como distinguir entre as arquiteturas encoder, decoder, encoder-decoder e seus casos de uso


<EditOnGithub source="https://github.com/huggingface/course/blob/main/chapters/pt/chapter1/1.mdx" />

### Transformers, o que eles podem fazer?
https://huggingface.co/learn/course/pt/chapter1/3.md

# Transformers, o que eles podem fazer?

<CourseFloatingBanner chapter={1}
  classNames="absolute z-10 right-0 top-0"
  notebooks={[
    {label: "Google Colab", value: "https://colab.research.google.com/github/huggingface/notebooks/blob/master/course/pt/chapter1/section3.ipynb"},
    {label: "Aws Studio", value: "https://studiolab.sagemaker.aws/import/github/huggingface/notebooks/blob/master/course/pt/chapter1/section3.ipynb"},
]} />

Nessa seção, observaremos sobre o que os modelos Transformers podem fazer e usar nossa primeira ferramenta da biblioteca 🤗 Transformers: a função `pipeline()` .

<Tip>
👀 Tá vendo o botão <em>Open in Colab</em> no topo direito? Clique nele e abra um notebook Google Colab notebook  com todas as amostras de códigos dessa seção. Esse botão estará presente em cada seção contendo exemplos de códigos. 

Se você deseja rodar os exemplos localmente, nós recomendamos dar uma olhada no <a href="/course/chapter0">setup</a>.
</Tip>

## Transformers estão por toda parte!

Os modelos Transformers são usados para resolver todos os tipos de tarefas de NLP, como algumas já mencionadas na seção anterior. Aqui estão algumas empresas e organizações usando a Hugging Face e os modelos Transformers, que também contribuem de volta para a comunidade compartilhando seus modelos:

<img src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter1/companies.PNG" alt="Empresas usando a Hugging Face" width="100%">

A [biblioteca 🤗 Transformers](https://github.com/huggingface/transformers) oferece a funcionalidade para criar e usar esses modelos compartilhados. O [Model Hub](https://huggingface.co/models) contém milhares de modelos pré-treinados que qualquer um pode baixar e usar. Você pode também dar upload nos seus próprios modelos no Hub!

<Tip>
⚠️ O Hugging Face Hub não é limitado aos modelos Transformers. Qualquer um pode compartilhar quaisquer tipos de modelos ou datasets que quiserem! <a href="https://huggingface.co/join">Crie uma conta na huggingface.co</a> para se beneficiar de todos os recursos disponíveis!
</Tip>

Antes de aprofundarmos sobre como os modelos Transformers funcionam por debaixo dos panos, vamos olhar alguns exemplos de como eles podem ser usados para solucionar alguns problemas de NLP interessantes.

## Trabalhando com pipelines

<Youtube id="tiZFewofSLM" />

O objeto mais básico na biblioteca 🤗 Transformers é a função `pipeline()` . Ela conecta o modelo com seus passos necessários de pré e pós-processamento, permitindo-nos a diretamente inserir qualquer texto e obter uma resposta inteligível:

```python
from transformers import pipeline

classifier = pipeline("sentiment-analysis")
classifier("I've been waiting for a HuggingFace course my whole life.")
```

```python out
[{'label': 'POSITIVE', 'score': 0.9598047137260437}]
```

Nós até podemos passar várias sentenças!

```python
classifier(
    ["I've been waiting for a HuggingFace course my whole life.", "I hate this so much!"]
)
```

```python out
[{'label': 'POSITIVE', 'score': 0.9598047137260437},
 {'label': 'NEGATIVE', 'score': 0.9994558095932007}]
```

Por padrão, esse pipeline seleciona particularmente um modelo pré-treinado que tem sido *ajustado* (fine-tuned) para análise de sentimentos em Inglês. O modelo é baixado e cacheado quando você criar o objeto `classifier`. Se você rodar novamente o comando, o modelo cacheado irá ser usado no lugar e não haverá necessidade de baixar o modelo novamente.

Há três principais passos envolvidos quando você passa algum texto para um pipeline:

1. O texto é pré-processado para um formato que o modelo consiga entender.
2. As entradas (*inputs*) pré-processados são passadas para o modelo.
3. As predições do modelo são pós-processadas, para que então você consiga atribuir sentido a elas.


Alguns dos [pipelines disponíveis](https://huggingface.co/transformers/main_classes/pipelines.html) atualmente, são:

- `feature-extraction` (pega a representação vetorial do texto)
- `fill-mask` (preenchimento de máscara)
- `ner` (reconhecimento de entidades nomeadas)
- `question-answering` (responder perguntas)
- `sentiment-analysis` (análise de sentimentos)
- `summarization` (sumarização)
- `text-generation` (geração de texto)
- `translation` (tradução)
- `zero-shot-classification` (classificação "zero-shot")

Vamos dar uma olhada em alguns desses!

## Classificação Zero-shot 

Nós começaremos abordando uma tarefa mais desafiadora da qual nós precisamos classificar texto que não tenham sido rotulados. Esse é um cenário comum nos projetos reais porque anotar texto geralmente consome bastante do nosso tempo e requer expertise no domínio. Para esse caso, o pipeline `zero-shot-classification` é muito poderoso: permite você especificar quais rótulos usar para a classificação, desse modo você não precisa "confiar" nos rótulos dos modelos pré-treinados. Você já viu como um modelo pode classificar uma sentença como positiva ou negativa usando esses dois rótulos - mas também pode ser classificado usando qualquer outro conjunto de rótulos que você quiser.

```python
from transformers import pipeline

classifier = pipeline("zero-shot-classification")
classifier(
    "This is a course about the Transformers library",
    candidate_labels=["education", "politics", "business"],
)
```

```python out
{'sequence': 'This is a course about the Transformers library',
 'labels': ['education', 'business', 'politics'],
 'scores': [0.8445963859558105, 0.111976258456707, 0.043427448719739914]}
```

Esse pipeline é chamado de _zero-shot_ porque você não precisa fazer o ajuste fino do modelo nos dados que você o utiliza. Pode diretamente retornar scores de probabilidade para qualquer lista de rótulos que você quiser!

<Tip>

✏️ **Experimente!** Brinque com suas próprias sequências e rótulos e veja como o modelo se comporta.

</Tip>


## Geração de Texto

Agora vamos ver como usar um pipeline para gerar uma porção de texto. A principal ideia aqui é que você coloque um pedaço de texto e o modelo irá autocompletá-lo ao gerar o texto restante. Isso é similar ao recurso de predição textual que é encontrado em inúmeros celulares. A geração de texto envolve aleatoriedade, então é normal se você não obter o mesmo resultado obtido mostrado abaixo.

```python
from transformers import pipeline

generator = pipeline("text-generation")
generator(
    "In this course, we will teach you how to"
)  # nesse curso, nós te mostraremos como você
```

```python out
[{'generated_text': 'In this course, we will teach you how to understand and use '
                    'data flow and data interchange when handling user data. We '
                    'will be working with one or more of the most commonly used '
                    'data flows — data flows of various types, as seen by the '
                    'HTTP'}] # nesse curso, nós te mostraremos como você pode entender e usar o fluxo de dados e a troca de dados quando for lidar com dados do usuário. Nós estaremos trabalhando com um ou um dos mais comuns fluxos de dados utilizados - fluxo de dados de vários tipos, como visto pelo 'HTTP'
```

Você pode controlar quão diferentes sequências são geradas com o argumento `num_return_sequences` e o tamanho total da saída de texto (*output*) com o argumento `max_length`.

<Tip>

✏️ **Experimente!** Use os argumentos `num_return_sequences` e `max_length` para gerar 2 textos com 15 palavras cada.

</Tip>


## Usando qualquer modelo do Hub em um pipeline

Nos exemplos passados, usamos o modelo padrão para a tarefa que executamos, mas você pode usar um modelo particular do Hub para usá-lo no pipeline em uma tarefa específica — exemplo, geração de texto. Vá ao [Model Hub](https://huggingface.co/models) e clique na tag correspondente na esquerda para mostrar apenas os modelos suportáveis para aquela tarefa. Você deverá ir a uma página como [essa](https://huggingface.co/models?pipeline_tag=text-generation).

Vamos tentar o  modelo [`distilgpt2`](https://huggingface.co/distilgpt2)! Aqui está como carrega-lo no mesmo pipeline como antes:

```python
from transformers import pipeline

generator = pipeline("text-generation", model="distilgpt2")
generator(
    "In this course, we will teach you how to",
    max_length=30,
    num_return_sequences=2,
)
```

```python out
[{'generated_text': 'In this course, we will teach you how to manipulate the world and '
                    'move your mental and physical capabilities to your advantage.'},
 {'generated_text': 'In this course, we will teach you how to become an expert and '
                    'practice realtime, and with a hands on experience on both real '
                    'time and real'}]
```

Você pode refinar sua pesquisa por um modelo clicando nas tags de linguagem, e pegando o modelo que gerará o texto em outra lingua. O Model Hub até mesmo contém checkpoints para modelos multilinguais que suportem várias linguas.

Uma vez que você seleciona o modelo clicando nele, você irá ver que há um widget que permite que você teste-o diretamente online. Desse modo você pode rapidamente testar as capacidades do modelo antes de baixa-lo.

<Tip>

✏️ **Experimente!** Use os filtros para encontrar um modelo de geração de texto em outra lingua. Fique à vontade para brincar com o widget e usa-lo em um pipeline!

</Tip>

### A API de Inferência

Todos os modelos podem ser testados diretamente de seu navegador usando a API de InferênciaI, que está disponível no website da [Hugging Face](https://huggingface.co/). Você pode brincar com o modelo diretamente pela página colocando textos customizados e observando como o modelo processa os dados inseridos.

A API de Inferência que alimenta o widget também está disponível como um produto pago, que serve como uma "mão na roda" se você precisa dela para seus workflows. Olhe a [página de preços](https://huggingface.co/pricing) para mais detalhes.

## Preenchimento de máscara (*Mask filling*) 

O próximo pipeline que você irá testar é o `fill-mask`.  A ideia dessa tarefa é preencher os espaços em branco com um texto dado:

```python
from transformers import pipeline

unmasker = pipeline("fill-mask")
unmasker("This course will teach you all about <mask> models.", top_k=2)
```

```python out
[{'sequence': 'This course will teach you all about mathematical models.',
  'score': 0.19619831442832947,
  'token': 30412,
  'token_str': ' mathematical'},
 {'sequence': 'This course will teach you all about computational models.',
  'score': 0.04052725434303284,
  'token': 38163,
  'token_str': ' computational'}]
```

O argumento `top_k` controla quantas possibilidades você quer que sejam geradas. Note que aqui o modelo preenche com uma palavra `<máscara>` especial, que é frequentemente referida como *mask token*.  Outros modelos de preenchimento de máscara podem ter diferentes *mask tokens*, então é sempre bom verificar uma palavra máscara apropriada quando explorar outros modelos. Um modo de checar isso é olhando para a palavra máscara usada no widget.

<Tip>

✏️ **Experimente!**  Pesquise pelo modelo `bert-base-cased` no Hub e identifique suas palavras máscara no widget da API de inferência. O que esse modelo prediz para a sentença em nosso `pipeline` no exemplo acima?

</Tip>

## Reconhecimento de entidades nomeadas

Reconhecimento de Entidades Nomeadas (NER) é uma tarefa onde o modelo tem de achar quais partes do texto correspondem a entidades como pessoas, locais, organizações. Vamos olhar em um exemplo:

```python
from transformers import pipeline

ner = pipeline("ner", grouped_entities=True)
ner("My name is Sylvain and I work at Hugging Face in Brooklyn.")
```

```python out
[{'entity_group': 'PER', 'score': 0.99816, 'word': 'Sylvain', 'start': 11, 'end': 18}, 
 {'entity_group': 'ORG', 'score': 0.97960, 'word': 'Hugging Face', 'start': 33, 'end': 45}, 
 {'entity_group': 'LOC', 'score': 0.99321, 'word': 'Brooklyn', 'start': 49, 'end': 57}
]
```

Aqui o modelo corretamente identificou que Sylvain é uma pessoa (PER), Hugging Face é uma organização (ORG), e Brooklyn é um local (LOC).

Nós passamos a opção `grouped_entities=True` na criação da função do pipelina para dize-lo para reagrupar juntos as partes da sentença que correspondem à mesma entidade: aqui o modelo agrupou corretamente "Hugging" e "Face" como única organização, ainda que o mesmo nome consista em múltiplas palavras. Na verdade, como veremos no próximo capítulo, o pré-processamento até mesmo divide algumas palavras em partes menores. Por exemplo, `Sylvain`  é dividido em 4 pedaços: `S`, `##yl`, `##va`, e `##in`. No passo de pós-processamento, o pipeline satisfatoriamente reagrupa esses pedaços.

<Tip>

✏️ **Experimente!** Procure no Model Hub por um modelo capaz de fazer o tageamento de partes do discurso (usualmente abreviado como POS) em inglês. O que o modelo prediz para a sentença no exemplo acima?

</Tip>

## Responder perguntas

O pipeline `question-answering` responde perguntas usando informações dado um contexto:

```python
from transformers import pipeline

question_answerer = pipeline("question-answering")
question_answerer(
    question="Where do I work?",
    context="My name is Sylvain and I work at Hugging Face in Brooklyn",
)
```

```python out
{'score': 0.6385916471481323, 'start': 33, 'end': 45, 'answer': 'Hugging Face'}
```

Note que o pipeline funciona através da extração da informação dado um contexto; não gera uma resposta.

## Sumarização

Sumarização é uma tarefa de reduzir um texto em um texto menor enquanto pega toda (ou boa parte) dos aspectos importantes do texto referenciado. Aqui um exemplo:

```python
from transformers import pipeline

summarizer = pipeline("summarization")
summarizer(
    """
    America has changed dramatically during recent years. Not only has the number of 
    graduates in traditional engineering disciplines such as mechanical, civil, 
    electrical, chemical, and aeronautical engineering declined, but in most of 
    the premier American universities engineering curricula now concentrate on 
    and encourage largely the study of engineering science. As a result, there 
    are declining offerings in engineering subjects dealing with infrastructure, 
    the environment, and related issues, and greater concentration on high 
    technology subjects, largely supporting increasingly complex scientific 
    developments. While the latter is important, it should not be at the expense 
    of more traditional engineering.

    Rapidly developing economies such as China and India, as well as other 
    industrial countries in Europe and Asia, continue to encourage and advance 
    the teaching of engineering. Both China and India, respectively, graduate 
    six and eight times as many traditional engineers as does the United States. 
    Other industrial countries at minimum maintain their output, while America 
    suffers an increasingly serious decline in the number of engineering graduates 
    and a lack of well-educated engineers.
"""
)
```

```python out
[{'summary_text': ' America has changed dramatically during recent years . The '
                  'number of engineering graduates in the U.S. has declined in '
                  'traditional engineering disciplines such as mechanical, civil '
                  ', electrical, chemical, and aeronautical engineering . Rapidly '
                  'developing economies such as China and India, as well as other '
                  'industrial countries in Europe and Asia, continue to encourage '
                  'and advance engineering .'}]
```

Como a geração de texto, você pode especificar o tamanho máximo `max_length` ou mínimo `min_length` para o resultado.


## Tradução

Para tradução, você pode usar o modelo default se você der um par de idiomas no nome da tarefa (tal como  `"translation_en_to_fr"`, para traduzir inglês para francês), mas a maneira mais fácil é pegar o moddelo que você quiser e usa-lo no [Model Hub](https://huggingface.co/models). Aqui nós iremos tentar traduzir do Francês para o Inglês:

```python
from transformers import pipeline

translator = pipeline("translation", model="Helsinki-NLP/opus-mt-fr-en")
translator("Ce cours est produit par Hugging Face.")
```

```python out
[{'translation_text': 'This course is produced by Hugging Face.'}]
```

Como a geração de texto e a sumarização, você pode especificar o tamanho máximo  `max_length`  e mínimo `min_length` para o resultado.

<Tip>

✏️ **Experimente!** Pesquise por modelos de tradução em outras línguas e experimente traduzir a sentença anterior em idiomas diferentes.

</Tip>

Os pipelines mostrados até agora são em sua maioria para propósitos demonstrativos. Eles foram programados para tarefas específicas e não podem performar variações delas. No próximo capítulo, você aprenderá o que está por dentro da função `pipeline()` e como customizar seu comportamento.


<EditOnGithub source="https://github.com/huggingface/course/blob/main/chapters/pt/chapter1/3.mdx" />

### Modelos decodificadores
https://huggingface.co/learn/course/pt/chapter1/6.md

# Modelos decodificadores

<CourseFloatingBanner
    chapter={1}
    classNames="absolute z-10 right-0 top-0"
/>

Os modelos de decodificador usam apenas o decodificador de um modelo Transformer. Em cada etapa, para uma determinada palavra, as camadas de atenção só podem acessar as palavras posicionadas antes dela na frase. Esses modelos geralmente são chamados de _modelos auto-regressivos_.

O pré-treinamento de modelos de decodificadores geralmente gira em torno de prever a próxima palavra na frase.

Esses modelos são mais adequados para tarefas que envolvem geração de texto.

Os representantes desta família de modelos incluem:

-   [CTRL](https://huggingface.co/transformers/model_doc/ctrl.html)
-   [GPT](https://huggingface.co/docs/transformers/model_doc/openai-gpt)
-   [GPT-2](https://huggingface.co/transformers/model_doc/gpt2.html)
-   [Transformer XL](https://huggingface.co/transformers/model_doc/transfo-xl.html)


<EditOnGithub source="https://github.com/huggingface/course/blob/main/chapters/pt/chapter1/6.mdx" />

### Questionário de fim de capítulo
https://huggingface.co/learn/course/pt/chapter1/10.md

# Questionário de fim de capítulo

<CourseFloatingBanner
    chapter={1}
    classNames="absolute z-10 right-0 top-0"
/>

Este capítulo cobriu muito terreno! Não se preocupe se você não entendeu todos os detalhes; os próximos capítulos o ajudarão a entender como as coisas funcionam debaixo do capô.

Primeiro, porém, vamos testar o que você aprendeu neste capítulo!

### 1. Explore o Hub e olhe para o checkpoint `roberta-large-mnli` . Que tarefa ele executa?

<Question
	choices={[
		{
			text: "Summarização",
			explain: "Olhe novamente na página <a href=\"https://huggingface.co/roberta-large-mnli\">roberta-large-mnli</a>."
		},
		{
			text: "Classificação de texto",
			explain: "Mais precisamente, ele classifica se duas ou mais sentenças estão logicamente conectadas entre três rótulos (contradição, neutro, vinculação) — uma tarefa também chamada de <em>inferência de linguagem natural</em>.",
			correct: true
		},
		{
			text: "Geração de texto",
			explain: "Olhe novamente na página <a href=\"https://huggingface.co/roberta-large-mnli\">roberta-large-mnli</a>."
		}
	]}
/>

### 2. O que o código a seguir retornará?

```py
from transformers import pipeline

ner = pipeline("ner", grouped_entities=True)
ner("My name is Sylvain and I work at Hugging Face in Brooklyn.")
```

<Question
	choices={[
		{
			text: "Ele retornará pontuações de classificação para esta frase, com rótulos 'positivo' ou 'negativo'.",
			explain: "Isso está incorreto - isso seria um pipeline de 'análise de sentimentos'."
		},
		{
			text: "Ele retornará um texto gerado completando esta frase.",
			explain: "Isso está incorreto - seria um pipeline de ``geração de texto`."
		},
		{
			text: "Ele retornará as palavras que representam pessoas, organizações ou locais.",
			explain: "Além disso, com `grouped_entities=True`, ele agrupará as palavras pertencentes à mesma entidade, como 'Hugging Face'.",
      			correct: true
		}
	]}
/>

### 3. O que deverá substituir ... nesse trecho de código?

```py
from transformers import pipeline

filler = pipeline("fill-mask", model="bert-base-cased")
result = filler("...")
```


<Question
	choices={[
		{
			text: "Esta <mask> está esperando por você.",
			explain: "Isso está incorreto. Confira o cartão modelo `bert-base-cased` e tente identificar seu erro."
		},
		{
			text: "Esta [MASK] está esperando por você.",
			explain: "Correto! O token de máscara deste modelo é [MASK]",
      			correct: true
		},
		{
			text: "Este homem está esperando por você.",
			explain: "Isso está incorreto. Esse pipeline preenche palavras mascaradas, portanto, precisa de um token de máscara em algum lugar."
		}
	]}
/>

### 4. Por que esse código irá dar erro?

```py
from transformers import pipeline

classifier = pipeline("zero-shot-classification")
result = classifier("This is a course about the Transformers library")
```


<Question
	choices={[
		{
			text: "Esse pipeline exige que sejam fornecidos rótulos para classificar esse texto.",
			explain: "Certo — o código correto precisa incluir `candidate_labels=[...]`.",
      			correct: true
		},
		{
			text: "Esse pipeline requer várias frases, não apenas uma.",
			explain: "Isso é incorreto, mas quando usado corretamente, esse pipeline pode levar uma lista de frases para processar (como todos os outros pipelines)."
		},
		{
			text: "A biblioteca 🤗 Transformers está quebrada, como sempre.",
			explain: "Não vamos dignificar esta resposta com um comentário!"
		},
    {
			text: "Esse pipeline requer entradas mais longas; esta é muito curta.",
			explain: "Isso está incorreto. Observe que um texto muito longo será truncado quando processado por esse pipeline."
		}
	]}
/>

### 5. O que "transfer learning" significa?

<Question
	choices={[
		{
			text: "Transferir o conhecimento de um modelo pré-treinado para um novo modelo treinando-o no mesmo conjunto de dados.",
			explain: "Não, seriam duas versões do mesmo modelo."
		},
		{
			text: "Transferir o conhecimento de um modelo pré-treinado para um novo modelo inicializando o segundo modelo com os pesos do primeiro modelo.",
			explain: "Correto: quando o segundo modelo é treinado em uma nova tarefa, ele _transfere_ o conhecimento do primeiro modelo.",
      			correct: true
		},
		{
			text: "Transferir o conhecimento de um modelo pré-treinado para um novo modelo construindo o segundo modelo com a mesma arquitetura do primeiro modelo",
			explain: "A arquitetura é apenas a forma como o modelo é construído; não há conhecimento compartilhado ou transferido neste caso."
		}
	]}
/>

### 6. Verdadeiro ou Falso? Um modelo de linguagem geralmente não precisa de rótulos para seu pré-treino.

<Question 
  	choices={[ 
    		{ 
      			text: "Verdadeiro",
      			explain: "O pré-treinamento geralmente é _autosupervisionado_, o que significa que os rótulos são criados automaticamente a partir das entradas (como prever a próxima palavra ou preencher algumas palavras mascaradas).", 
      			correct: true 
    		}, 
    		{ 
      			text: "Falso", 
      			explain:"Essa não é a resposta correta."
    		} 
  	]} 
/>

### 7. Selecione a sentença que melhor descreve os termos "modelo", "arquitetura" e "pesos".

<Question 
  	choices={[ 
    		{ 
      			text: "Se um modelo é um edifício, sua arquitetura é a planta e os pesos são as pessoas que vivem dentro dele.", 
      			explain: "Seguindo essa metáfora, os pesos seriam os tijolos e outros materiais utilizados na construção do edifício." 
    		}, 
    		{ 
      			text: "Uma arquitetura é um mapa para construir um modelo e seus pesos são as cidades representadas no mapa.", 
      			explain: "O problema com essa metáfora é que um mapa geralmente representa uma realidade existente (há apenas uma cidade na França chamada Paris). Para uma determinada arquitetura, vários pesos são possíveis." 
    		}, 
    		{ 
      			text: "Uma arquitetura é uma sucessão de funções matemáticas para construir um modelo e seus pesos são os parâmetros dessas funções.", 
      			explain: "O mesmo conjunto de funções matemáticas (arquitetura) pode ser usado para construir diferentes modelos usando diferentes parâmetros (pesos).", 
      			correct: true 
    		} 
  	]} 
/>

### 8. Quais desses tipos de modelos você usaria para completar comandos com textos gerados?

<Question 
  	choices={[ 
    		{ 
      			text: "Um modelo de codificador", 
      			explain: "Um modelo de codificador gera uma representação de toda a frase que é mais adequada para tarefas como classificação." 
    		}, 
    		{ 
      			text: "Um modelo de decodificador", 
      			explain: "Os modelos de decodificadores são perfeitamente adequados para geração de texto a partir de um prompt.", 
      			correct: true 
    		}, 
    		{ 
      			text: "Um modelo de sequência a sequência", 
      			explain: "Os modelos de sequência a sequência são mais adequados para tarefas em que você deseja gerar frases em relação às frases de entrada, não a um determinado prompt." 
    		} 
  	]} 
/>

### 9. Quais desses tipos de modelos você usaria para resumir textos?

<Question 
  choices={[ 
    		{ 
      			text: "Um modelo de codificador", 
      			explain: "Um modelo de codificador gera uma representação de toda a frase que é mais adequada para tarefas como classificação." 
    		}, 
    		{ 
      			text: "Um modelo de decodificador", 
      			explain: "Os modelos decodificadores são bons para gerar texto de saída (como resumos), mas não têm a capacidade de explorar um contexto como o texto inteiro para resumir."
    		},
    		{
      			text: "Um modelo de sequência a sequência",
      			explain: "Os modelos de sequência a sequência são perfeitamente adequados para uma tarefa de sumarização.", 
      			correct: true 
    		} 
  	]} 
/>

### 10. Quais desses tipos de modelos você usaria para classificar entradas de texto de acordo com determinados rótulos?

<Question 
  choices={[ 
    		{ 
      			text: "Um modelo de codificador", 
      			explain: "Um modelo de codificador gera uma representação de toda a frase que é perfeitamente adequada para uma tarefa como classificação.", 
      			correct: true 
    		}, 
    		{ 
      			text: "Um modelo de decodificador", 
      			explain: "Os modelos decodificadores são bons para gerar textos de saída, não para extrair um rótulo de uma frase." 
    		}, 
    		{
      			text: "Um modelo de sequência a sequência",
      			explain: "Os modelos de sequência a sequência são mais adequados para tarefas em que você deseja gerar texto com base em uma frase de entrada, não em um rótulo."
    		} 
  	]} 
/>

### 11. Que possível fonte o viés observado em um modelo pode ter?

<Question 
  choices={[ 
    		{ 
      			text: "O modelo é uma versão afinada de um modelo pré-treinado e pega seu viés a partir dele.", 
      			explain: "Ao aplicar o Transfer Learning, o viés no modelo pré-treinado usado persiste no modelo ajustado.", 
      			correct: true 
    		}, 
    		{ 
      			text: "Os dados em que o modelo foi treinado são enviesados.", 
      			explain: "Esta é a fonte mais óbvia de viés, mas não a única.", 
      			correct: true 
    		}, 
    		{ 
      			text: "A métrica para a qual o modelo estava otimizando é enviesada.", 
      			explain: "Uma fonte menos óbvia de viés é a forma como o modelo é treinado. Seu modelo será otimizado cegamente para qualquer métrica que você escolher, sem pensar duas vezes.", 
      			correct: true 
    		} 
  	]} 
/>


<EditOnGithub source="https://github.com/huggingface/course/blob/main/chapters/pt/chapter1/10.mdx" />

### Vieses e limitações
https://huggingface.co/learn/course/pt/chapter1/8.md

# Vieses e limitações

<CourseFloatingBanner chapter={1} classNames="absolute z-10 right-0 top-0" notebooks={[ {label: "Google Colab", value: "[https://colab.research.google.com/github/huggingface/notebooks/blob/master/course/pt/chapter1/section8.ipynb](https://colab.research.google.com/github/huggingface/notebooks/blob/master/course/pt/chapter1/section8.ipynb)"}, {label: "Aws Studio", value: "[https://studiolab.sagemaker.aws/import/github/huggingface/notebooks/blob/master/course/pt/chapter1/section8.ipynb](https://studiolab.sagemaker.aws/import/github/huggingface/notebooks/blob/master/course/pt/chapter1/section8.ipynb)"}, ]} />

Se sua intenção é usar um modelo pré-treinado ou uma versão ajustada em produção, esteja ciente de que, embora esses modelos sejam ferramentas poderosas, eles vêm com limitações. A maior delas é que, para possibilitar o pré-treinamento em grandes quantidades de dados, os pesquisadores muitas vezes raspam todo o conteúdo que encontram, tirando o melhor e o pior do que está disponível na internet.

Para dar uma ilustração rápida, vamos voltar ao exemplo de um pipeline `fill-mask` com o modelo BERT:
```py
from transformers import pipeline

unmasker = pipeline("fill-mask", model="bert-base-uncased")
result = unmasker("This man works as a [MASK].")
print([r["token_str"] for r in result])

result = unmasker("This woman works as a [MASK].")
print([r["token_str"] for r in result])

["lawyer", "carpenter", "doctor", "waiter", "mechanic"]
["nurse", "waitress", "teacher", "maid", "prostitute"]
```

Quando solicitado a preencher a palavra que falta nessas duas frases, o modelo dá apenas uma resposta livre de gênero (garçom/garçonete). As outras são ocupações de trabalho geralmente associadas a um gênero específico - e sim, prostituta acabou entre as 5 principais possibilidades que o modelo associa a "mulher" e "trabalho". Isso acontece mesmo que o BERT seja um dos raros modelos de Transformer não construídos por meio de coleta de dados de toda a Internet, mas usando dados aparentemente neutros (ele é treinado com datasets da [Wikipedia em inglês](https://huggingface.co/datasets/wikipedia ) e [BookCorpus](https://huggingface.co/datasets/bookcorpus)).

Quando você usa essas ferramentas, você precisa ter em mente que o modelo original que você está usando pode facilmente gerar conteúdo sexista, racista ou homofóbico. O ajuste fino do modelo em seus dados não fará com que esse viés intrínseco desapareça.


<EditOnGithub source="https://github.com/huggingface/course/blob/main/chapters/pt/chapter1/8.mdx" />

### Como os Transformers trabalham?
https://huggingface.co/learn/course/pt/chapter1/4.md

# Como os Transformers trabalham?

<CourseFloatingBanner
    chapter={1}
    classNames="absolute z-10 right-0 top-0"
/>

Nessa seção, nós olharemos para o alto nível de arquitetura dos modelos Transformers.

## Um pouco da história dos Transformers

Aqui alguns pontos de referência na (pequena) história dos modelos Transformers:

<div class="flex justify-center">
<img class="block dark:hidden" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter1/transformers_chrono.svg" alt="A brief chronology of Transformers models.">
<img class="hidden dark:block" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter1/transformers_chrono-dark.svg" alt="A brief chronology of Transformers models.">
</div>

A [arquitetura Transformer](https://arxiv.org/abs/1706.03762) foi introduzida em Junho de 2017. O foco de pesquisa original foi para tarefas de tradução. Isso foi seguido pela introdução de muitos modelos influentes, incluindo:

- **Junho de 2018**: [GPT](https://cdn.openai.com/research-covers/language-unsupervised/language_understanding_paper.pdf), o primeiro modelo Transformer pré-treinado, usado para ajuste-fino em várias tarefas de NLP e obtendo resultados estado-da-arte

- **Outubro de 2018**: [BERT](https://arxiv.org/abs/1810.04805), outro grande modelo pré-treinado, esse outro foi designado para produzir melhores resumos de sentenças(mais sobre isso no próximo capítulo!)

- **Fevereiro de 2019**: [GPT-2](https://cdn.openai.com/better-language-models/language_models_are_unsupervised_multitask_learners.pdf), uma melhor (e maior) versão da GPT que não foi imediatamente publicizado o seu lançamento devido a preocupações éticas [N.T.: não apenas por isso]

- **Outubro de 2019**: [DistilBERT](https://arxiv.org/abs/1910.01108), uma versão destilada do BERT que é 60% mais rápidam 40% mais leve em memória, e ainda retém 97% da performance do BERT

- **Outubro de 2019**: [BART](https://arxiv.org/abs/1910.13461) e [T5](https://arxiv.org/abs/1910.10683), dois grandes modelos pré-treinados usando a mesma arquitetura do modelo original Transformer (os primeiros a fazerem até então)

- **Maio de 2020**, [GPT-3](https://arxiv.org/abs/2005.14165), uma versão ainda maior da GPT-2 que é capaz de performar bem em uma variedade de tarefas sem a necessidade de ajuste-fino (chamado de aprendizagem_zero-shot_)

Esta lista está longe de ser abrangente e destina-se apenas a destacar alguns dos diferentes tipos de modelos de Transformers. Em linhas gerais, eles podem ser agrupados em três categorias:

- GPT-like (também chamados de modelos Transformers _auto-regressivos_)
- BERT-like (também chamados de modelos Transformers _auto-codificadores_) 
- BART/T5-like (também chamados de modelos Transformers _sequence-to-sequence_)

Vamos mergulhar nessas famílias com mais profundidade mais adiante

## Transformers são modelos de linguagem

Todos os modelos de Transformer mencionados acima (GPT, BERT, BART, T5, etc.) foram treinados como *modelos de linguagem*. Isso significa que eles foram treinados em grandes quantidades de texto bruto de forma auto-supervisionada. O aprendizado autossupervisionado é um tipo de treinamento no qual o objetivo é calculado automaticamente a partir das entradas do modelo. Isso significa que os humanos não são necessários para rotular os dados!

Este tipo de modelo desenvolve uma compreensão estatística da linguagem em que foi treinado, mas não é muito útil para tarefas práticas específicas. Por causa disso, o modelo geral pré-treinado passa por um processo chamado *aprendizagem de transferência*. Durante esse processo, o modelo é ajustado de maneira supervisionada - ou seja, usando rótulos anotados por humanos - em uma determinada tarefa.

Um exemplo de tarefa é prever a próxima palavra em uma frase depois de ler as *n* palavras anteriores. Isso é chamado de *modelagem de linguagem causal* porque a saída depende das entradas passadas e presentes, mas não das futuras.

<div class="flex justify-center">
<img class="block dark:hidden" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter1/causal_modeling.svg" alt="Example of causal language modeling in which the next word from a sentence is predicted.">
<img class="hidden dark:block" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter1/causal_modeling-dark.svg" alt="Example of causal language modeling in which the next word from a sentence is predicted.">
</div>

Outro exemplo é a *modelagem de linguagem mascarada*, na qual o modelo prevê uma palavra mascarada na frase.

<div class="flex justify-center">
<img class="block dark:hidden" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter1/masked_modeling.svg" alt="Example of masked language modeling in which a masked word from a sentence is predicted.">
<img class="hidden dark:block" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter1/masked_modeling-dark.svg" alt="Example of masked language modeling in which a masked word from a sentence is predicted.">
</div>

## Transformers são modelos grandes

Além de alguns outliers (como o DistilBERT), a estratégia geral para obter melhor desempenho é aumentar os tamanhos dos modelos, bem como a quantidade de dados em que são pré-treinados.

<div class="flex justify-center">
<img src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter1/model_parameters.png" alt="Number of parameters of recent Transformers models" width="90%">
</div>

Infelizmente, treinar um modelo, especialmente um grande, requer uma grande quantidade de dados. Isso se torna muito caro em termos de tempo e recursos de computação. Até se traduz em impacto ambiental, como pode ser visto no gráfico a seguir.

<div class="flex justify-center">
<img class="block dark:hidden" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter1/carbon_footprint.svg" alt="The carbon footprint of a large language model.">
<img class="hidden dark:block" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter1/carbon_footprint-dark.svg" alt="The carbon footprint of a large language model.">
</div>

<Youtube id="ftWlj4FBHTg"/>

E isso mostra um projeto para um modelo (muito grande) liderado por uma equipe que tenta conscientemente reduzir o impacto ambiental do pré-treinamento. Os gastos de executar muitos testes para obter os melhores hiperparâmetros seria ainda maior.

Imagine se cada vez que uma equipe de pesquisa, uma organização estudantil ou uma empresa quisesse treinar um modelo, o fizesse do zero. Isso levaria a custos globais enormes e desnecessários!

É por isso que compartilhar modelos de linguagem é fundamental: compartilhar os pesos treinados e construir em cima dos pesos já treinados reduz o custo geral de computação e os gastos de carbono da comunidade.


## Transferência de Aprendizagem

<Youtube id="BqqfQnyjmgg" />

*Pré-treinamento* é o ato de treinar um modelo do zero: os pesos são inicializados aleatoriamente e o treinamento começa sem nenhum conhecimento prévio.

<div class="flex justify-center">
<img class="block dark:hidden" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter1/pretraining.svg" alt="The pretraining of a language model is costly in both time and money.">
<img class="hidden dark:block" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter1/pretraining-dark.svg" alt="The pretraining of a language model is costly in both time and money.">
</div>

Esse pré-treinamento geralmente é feito em grandes quantidades de dados. Portanto, requer um corpus de dados muito grande e o treinamento pode levar várias semanas.

*Ajuste fino*, por outro lado, é o treinamento feito **após** um modelo ter sido pré-treinado. Para realizar o ajuste fino, primeiro você adquire um modelo de linguagem pré-treinado e, em seguida, realiza treinamento adicional com um conjunto de dados específico para sua tarefa. Espere - por que não simplesmente treinar diretamente para a tarefa final? Existem algumas razões:

*  O modelo pré-treinado já foi treinado em um conjunto de dados que possui algumas semelhanças com o conjunto de dados de ajuste fino. O processo de ajuste fino é, portanto, capaz de aproveitar o conhecimento adquirido pelo modelo inicial durante o pré-treinamento (por exemplo, com problemas de NLP, o modelo pré-treinado terá algum tipo de compreensão estatística da linguagem que você está usando para sua tarefa).
* Como o modelo pré-treinado já foi treinado com muitos dados, o ajuste fino requer muito menos dados para obter resultados decentes.
*  Pela mesma razão, a quantidade de tempo e recursos necessários para obter bons resultados são muito menores.

Por exemplo, pode-se alavancar um modelo pré-treinado treinado no idioma inglês e depois ajustá-lo em um corpus arXiv, resultando em um modelo baseado em ciência/pesquisa. O ajuste fino exigirá apenas uma quantidade limitada de dados: o conhecimento que o modelo pré-treinado adquiriu é "transferido", daí o termo *aprendizagem de transferência*.

<div class="flex justify-center">
<img class="block dark:hidden" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter1/finetuning.svg" alt="The fine-tuning of a language model is cheaper than pretraining in both time and money.">
<img class="hidden dark:block" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter1/finetuning-dark.svg" alt="The fine-tuning of a language model is cheaper than pretraining in both time and money.">
</div>

O ajuste fino de um modelo, portanto, tem menores custos de tempo, dados, financeiros e ambientais. Também é mais rápido e fácil iterar em diferentes esquemas de ajuste fino, pois o treinamento é menos restritivo do que um pré-treinamento completo.

Esse processo também alcançará melhores resultados do que treinar do zero (a menos que você tenha muitos dados), e é por isso que você deve sempre tentar alavancar um modelo pré-treinado - um o mais próximo possível da tarefa que você tem em mãos - e  então fazer seu ajuste fino.

## Arquitetura geral

Nesta seção, veremos a arquitetura geral do modelo Transformer. Não se preocupe se você não entender alguns dos conceitos; há seções detalhadas posteriormente cobrindo cada um dos componentes.

<Youtube id="H39Z_720T5s" />

## Introdução

O modelo é principalmente composto por dois blocos:

* **Codificador (esquerda)**: O codificador recebe uma entrada e constrói uma representação dela (seus recursos). Isso significa que o modelo é otimizado para adquirir entendimento da entrada.
* **Decodificador (à direita)**: O decodificador usa a representação do codificador (recursos) junto com outras entradas para gerar uma sequência de destino. Isso significa que o modelo é otimizado para gerar saídas.

<div class="flex justify-center">
<img class="block dark:hidden" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter1/transformers_blocks.svg" alt="Architecture of a Transformers models">
<img class="hidden dark:block" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter1/transformers_blocks-dark.svg" alt="Architecture of a Transformers models">
</div>

Cada uma dessas partes pode ser usada de forma independente, dependendo da tarefa:

* **Modelos somente de codificador**: bom para tarefas que exigem compreensão da entrada, como classificação de sentença e reconhecimento de entidade nomeada.
* **Modelos somente decodificadores**: bom para tarefas generativas, como geração de texto.
* **Modelos de codificador-decodificador** ou **modelos de sequência a sequência**: bom para tarefas generativas que exigem uma entrada, como tradução ou resumo. (corrigit sequence to sequence)

Vamos mergulhar nessas arquiteturas de forma independente em seções posteriores.

## Camadas de Atenção

Uma característica chave dos modelos Transformer é que eles são construídos com camadas especiais chamadas *camadas de atenção*. Na verdade, o título do artigo que apresenta a arquitetura do Transformer era ["Atenção é tudo que você precisa"](https://arxiv.org/abs/1706.03762)! Exploraremos os detalhes das camadas de atenção posteriormente no curso; por enquanto, tudo o que você precisa saber é que essa camada dirá ao modelo para prestar atenção específica a certas palavras na frase que você passou (e mais ou menos ignorar as outras) ao lidar com a representação de cada palavra.

Para contextualizar, considere a tarefa de traduzir o texto do português para o francês. Dada a entrada "Você gosta deste curso", um modelo de tradução precisará atender também à palavra adjacente "Você" para obter a tradução adequada para a palavra "gosta", pois em francês o verbo "gostar" é conjugado de forma diferente dependendo o sujeito. O resto da frase, no entanto, não é útil para a tradução dessa palavra. Na mesma linha, ao traduzir "deste" o modelo também precisará prestar atenção à palavra "curso", pois "deste" traduz-se de forma diferente dependendo se o substantivo associado é masculino ou feminino. Novamente, as outras palavras na frase não importarão para a tradução de "deste". Com frases mais complexas (e regras gramaticais mais complexas), o modelo precisaria prestar atenção especial às palavras que podem aparecer mais distantes na frase para traduzir adequadamente cada palavra.

O mesmo conceito se aplica a qualquer tarefa associada à linguagem natural: uma palavra por si só tem um significado, mas esse significado é profundamente afetado pelo contexto, que pode ser qualquer outra palavra (ou palavras) antes ou depois da palavra que está sendo estudada.

Agora que você tem uma ideia do que são as camadas de atenção, vamos dar uma olhada mais de perto na arquitetura do Transformer.

## A arquitetura original

A arquitetura Transformer foi originalmente projetada para tradução. Durante o treinamento, o codificador recebe entradas (frases) em um determinado idioma, enquanto o decodificador recebe as mesmas frases no idioma de destino desejado. No codificador, as camadas de atenção podem usar todas as palavras em uma frase (já que, como acabamos de ver, a tradução de uma determinada palavra pode ser dependente do que está depois e antes dela na frase). O decodificador, no entanto, funciona sequencialmente e só pode prestar atenção nas palavras da frase que ele já traduziu (portanto, apenas as palavras anteriores à palavra que está sendo gerada no momento). Por exemplo, quando previmos as três primeiras palavras do alvo traduzido, as entregamos ao decodificador que então usa todas as entradas do codificador para tentar prever a quarta palavra.

Para acelerar as coisas durante o treinamento (quando o modelo tem acesso às frases alvo), o decodificador é alimentado com todo o alvo, mas não é permitido usar palavras futuras (se teve acesso à palavra na posição 2 ao tentar prever a palavra na posição 2, o problema não seria muito difícil!). Por exemplo, ao tentar prever a quarta palavra, a camada de atenção só terá acesso às palavras nas posições 1 a 3.

A arquitetura original do Transformer ficou assim, com o codificador à esquerda e o decodificador à direita:

<div class="flex justify-center">
<img class="block dark:hidden" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter1/transformers.svg" alt="Architecture of a Transformers models">
<img class="hidden dark:block" src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter1/transformers-dark.svg" alt="Architecture of a Transformers models">
</div>

Observe que a primeira camada de atenção em um bloco decodificador presta atenção a todas as entradas (passadas) do decodificador, mas a segunda camada de atenção usa a saída do codificador. Ele pode, assim, acessar toda a frase de entrada para melhor prever a palavra atual. Isso é muito útil, pois diferentes idiomas podem ter regras gramaticais que colocam as palavras em ordens diferentes, ou algum contexto fornecido posteriormente na frase pode ser útil para determinar a melhor tradução de uma determinada palavra.

A *máscara de atenção* também pode ser usada no codificador/decodificador para evitar que o modelo preste atenção a algumas palavras especiais - por exemplo, a palavra de preenchimento especial usada para fazer com que todas as entradas tenham o mesmo comprimento ao agrupar frases.

##  Arquiteturas vs. checkpoints

À medida que nos aprofundarmos nos modelos do Transformer neste curso, você verá menções a *arquiteturas* e *checkpoints*, bem como *modelos*. Todos esses termos têm significados ligeiramente diferentes:

* **Arquitetura**: Este é o esqueleto do modelo -- a definição de cada camada e cada operação que acontece dentro do modelo.
* **Checkpoints**: Esses são os pesos que serão carregados em uma determinada arquitetura.
* **Modelos**: Este é um termo abrangente que não é tão preciso quanto "arquitetura" ou "checkpoint": pode significar ambos. Este curso especificará *arquitetura* ou *checkpoint* quando for necessário reduzir a ambiguidade.

Por exemplo, BERT é uma arquitetura enquanto `bert-base-cased`, um conjunto de pesos treinados pela equipe do Google para a primeira versão do BERT, é um checkpoint. No entanto, pode-se dizer "o modelo BERT" e "o modelo `bert-base-cased`".


<EditOnGithub source="https://github.com/huggingface/course/blob/main/chapters/pt/chapter1/4.mdx" />

### Modelos sequência a sequência
https://huggingface.co/learn/course/pt/chapter1/7.md

# Modelos sequência a sequência

<CourseFloatingBanner
    chapter={1}
    classNames="absolute z-10 right-0 top-0"
/>

Modelos encoder-decoder (também chamados de modelos _sequence-to-sequence_) usam ambas as partes da arquitetura Transformer. Em cada estágio, as camadas de atenção do codificador podem acessar todas as palavras da frase inicial, enquanto as camadas de atenção do decodificador podem acessar apenas as palavras posicionadas antes de uma determinada palavra na entrada.

O pré-treinamento desses modelos pode ser feito usando os objetivos dos modelos de codificador ou decodificador, mas geralmente envolve algo um pouco mais complexo. Por exemplo, [T5](https://huggingface.co/t5-base) é pré-treinado substituindo trechos aleatórios de texto (que podem conter várias palavras) por uma única palavra especial de máscara, e o objetivo é prever o texto que esta palavra de máscara substitui.

Os modelos de sequência a sequência são mais adequados para tarefas que envolvem a geração de novas frases dependendo de uma determinada entrada, como resumo, tradução ou resposta a perguntas generativas.

Os representantes desta família de modelos incluem:

-   [BART](https://huggingface.co/transformers/model_doc/bart.html)
-   [mBART](https://huggingface.co/transformers/model_doc/mbart.html)
-   [Marian](https://huggingface.co/transformers/model_doc/marian.html)
-   [T5](https://huggingface.co/transformers/model_doc/t5.html)


<EditOnGithub source="https://github.com/huggingface/course/blob/main/chapters/pt/chapter1/7.mdx" />

### Processamento de Linguagem Natural (NLP)
https://huggingface.co/learn/course/pt/chapter1/2.md

# Processamento de Linguagem Natural (NLP)

<CourseFloatingBanner
    chapter={1}
    classNames="absolute z-10 right-0 top-0"
/>

Antes de irmos direto para os modelos Transformers, vamos fazer um rápido esboço sobre o que é processamento de linguagem natural e o porquê nós nos importamos com isso.

## O que é NLP?

NLP é um campo da linguística e da Aprendizagem de Máquina (ML) focada em entender tudo relacionado a linguagem humana. O objetivo das tarefas de NLP não é apenas entender palavras soltas individualmente, mas ser capaz de entender o contexto dessas palavras.

A seguir uma lista de tarefas comuns de NLP, com alguns exemplos:

- **Classificação de sentenças completas**: Capturar o sentimento de uma revisão, detectar se um email é spam, determinar se a sentença é gramaticalmente correta ou onde duas sentenças são logicamente relacionadas ou não
- **Classificação de cada palavra em uma sentença**: Identificar os componentes gramaticais de uma sentença (substantivo, verbo, adjetivo), ou as entidades nomeadas (pessoa, local, organização)
- **Geração de conteúdo textual**:  Completar um trecho com autogeração textual, preenchendo as lacunas em um texto com palavras mascaradas
- **Extrair uma resposta de um texto**: Dada uma pergunta e um contexto, extrair a resposta baseada na informação passada no contexto
- **Gerar uma nova sentença a partir de uma entrada de texto**: Traduzir um texto para outro idioma, resumi-lo

NLP não se limita ao texto escrito. Também engloba desafios complexos nos campos de reconhecimento de discurso e visão computacional, tal como a geração de transcrição de uma amostra de áudio ou a descrição de uma imagem.

## Por que isso é desafiador?

Os computadores não processam a informação da mesma forma que os seres humanos. Por exemplo, quando nós lemos a sentença "Estou com fome", nós podemos facilmente entender seu significado. Similarmente, dada duas sentenças como "Estou com fome" e "Estou triste", nós somos capazes de facilmente determinar quão similares elas são. Para modelos de Aprendizagem de Máquina (ML), tarefas como essas são mais difíceis. O texto precisa ser processado de um modo que possibilite o modelo aprender por ele. E porque a linguagem é complexa, nós precisamos pensar cuidadosamente sobre como esse processamento tem que ser feito. Tem se feito muita pesquisa sobre como representar um texto e nós iremos observar alguns desses métodos no próximo capítulo.


<EditOnGithub source="https://github.com/huggingface/course/blob/main/chapters/pt/chapter1/2.mdx" />
