Pré-processamento de dados do Transformers: pré-processamento de dados

Pré-processamento de dados Pré-processamento de dados

Nos transformadores, a principal ferramenta para processamento de dados é o text tokenizer tokenizer. Podemos usar o tipo de tokenizador de texto correspondente ao modelo ou podemos usar a AutoTokenizerclassificação automática diretamente.

Um tokenizador de texto primeiro divide o texto em palavras, sinais de pontuação, etc. Esses elementos de divisão são chamados de token. Em seguida, ele será tokenconvertido em um número para que possa ser convertido em um tensor para treinamento tensor. CLSAlém disso, alguns tokenizadores de texto específicos também adicionarão algumas tags especiais exigidas pelo modelo, como , em BERT SEP.

Observação:
se você quiser usar um modelo pré-treinado, precisará usar o tokenizador de texto correspondente do modelo. Como o tokenizador de texto correspondente transforma o texto da mesma forma que seu modelo foi treinado, o vocabulário correspondente também é o mesmo. Se o tokenizador de texto estiver errado, ele terá um grande impacto na previsão ou ajuste fino do modelo. Por exemplo, o índice original da palavra "I" é 1, e o índice do "I" em outro tokenizador de texto é 100, o que faz com que os dados recebidos pelo modelo sejam completamente diferentes do que você pensa.

Para baixar automaticamente o tokenizador de texto usado ao treinar ou ajustar o modelo, você pode usar from_pretrained()o método:

from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained('bert-base-cased')

uso básico

pré-processando

Os tokenizadores de texto em transformadores têm muitos métodos, mas há apenas um método para pré-processamento, ou seja __call__: você apenas alimenta o texto diretamente no objeto tokenizador de texto. do seguinte modo:

encoded_input = tokenizer("Hello, I'm a single sentence!")
print(encoded_input)

输出:
{
    
    'input_ids': [101, 8667, 117, 146, 112, 182, 170, 1423, 5650, 106, 102], 
'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]}

Este método retorna um dicionário. input_idsé tokeno índice de cada um no texto de entrada. attention_maskO uso de e será discutido posteriormente token_type_ids.

decodificação

Além de codificar o texto, os tokenizadores de texto também podem decodificar índices:

print(tokenizer.decode(encoded_input["input_ids"]))

输出:
[CLS] Hello, I'm a single sentence! [SEP]

Podemos ver que o tagger de texto adicionou automaticamente as tags especiais exigidas pelo BERT durante o pré-processamento.

gtp2-mediumNem todos os modelos requerem marcação especial, se não usarmos bert-base-cased, podemos obter o mesmo resultado do texto original ao decodificar.

Ao decodificar, também podemos adicionar parâmetros ao método add_special_tokens=Falsepara remover tags especiais (algumas versões são skip_special_tokens=True).

dados múltiplos

Se você deseja processar vários textos de uma só vez, pode combiná-los em uma matriz, dentro e fora do tokenizador de texto de uma só vez, da seguinte maneira:

batch_sentences = ["Hello I'm a single sentence",
                   "And another sentence",
                   "And the very very last one"]
encoded_inputs = tokenizer(batch_sentences)
print(encoded_inputs)

输出:
{
    
    'input_ids': [[101, 8667, 146, 112, 182, 170, 1423, 5650, 102],
               [101, 1262, 1330, 5650, 102],
               [101, 1262, 1103, 1304, 1304, 1314, 1141, 102]],
 'token_type_ids': [[0, 0, 0, 0, 0, 0, 0, 0, 0],
                    [0, 0, 0, 0, 0],
                    [0, 0, 0, 0, 0, 0, 0, 0]],
 'attention_mask': [[1, 1, 1, 1, 1, 1, 1, 1, 1],
                    [1, 1, 1, 1, 1],
                    [1, 1, 1, 1, 1, 1, 1, 1]]}

Preencher, truncar, retornar tipos específicos

Ao processar várias declarações de uma só vez, também podemos ter os seguintes requisitos:

  • preencha cada frase com o comprimento máximo do lote
  • Truncar cada frase para o comprimento máximo que o modelo pode aceitar
  • tensordados do tipo de retorno

Você pode atingir todos os requisitos com as seguintes operações:

batch = tokenizer(batch_sentences, max_length=7, padding=True, truncation=True, return_tensors="pt", )
print(batch)

结果:
{
    
    'input_ids': tensor([
				[ 101, 8667,  146,  112,  182,  170,  102],
        [ 101, 1262, 1330, 5650,  102,    0,    0],
        [ 101, 1262, 1103, 1304, 1304, 1314,  102]]), 
'token_type_ids': tensor([
				[0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0]]), 
'attention_mask': tensor([
				[1, 1, 1, 1, 1, 1, 1],
        [1, 1, 1, 1, 1, 0, 0],
        [1, 1, 1, 1, 1, 1, 1]])}

pytorch.tensorDesta vez, um dicionário de strings para tipos é retornado . Agora podemos ver o uso com base nos resultados retornados attention_mask: ele dirá ao modelo quais tokendevem ser prestados atenção e quais não devem ser ignorados, porque alguns não têm sentido para o preenchimento token.

Observe que o código acima emitirá um aviso quando executado se for usado um modelo que não tenha um comprimento máximo associado a ele. Isso é bom e pode ser ignorado, ou parâmetros podem ser adicionados verbose=Falsepara evitar que o tokenizador de texto lance essas exceções.

processamento de pares de frases

Às vezes pode ser necessário inserir um par de frases no modelo. Por exemplo, precisamos julgar se duas frases são semelhantes; ou estamos usando um modelo de resposta a perguntas e precisamos inserir texto e perguntas no modelo. Para BERTo modelo, os pares de sentenças precisam ser transformados na seguinte forma:[CLS] Sequence A [SEP] Sequence B [SEP]

Ao usar Transformers para processar pares de sentenças, precisamos passar as duas sentenças para o tokenizador de texto como variáveis ​​diferentes (observe que ele não está integrado em uma lista como antes, mas em duas variáveis ​​separadas). Em seguida, obteremos um dicionário correspondente, como no exemplo a seguir:

encoded_input = tokenizer("How old are you?", "I'm 6 years old")
print(encoded_input)
print(tokenizer.decode(encoded_input["input_ids"]))
for i in encoded_input["input_ids"]:
    print(tokenizer.decode(i))

结果:
{
    
    'input_ids': [101, 1731, 1385, 1132, 1128, 136, 102, 146, 112, 182, 127, 1201, 1385, 102], 'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1], 'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]}
[CLS] How old are you? [SEP] I'm 6 years old [SEP]
[ C L S ]
H o w
o l d
a r e
y o u
?
[ S E P ]
I
'
m
6
y e a r s
o l d
[ S E P ]

A partir dos resultados podemos ver token_type_idso efeito: eles informam ao modelo qual parte da entrada pertence à primeira sentença e qual parte pertence à segunda sentença. Observe que nem todos os modelos exigem isso token_tyoe_ids. Por padrão, os tokenizadores de texto retornarão apenas a entrada desejada em relação ao modelo. Você pode passar alguns parâmetros como return_token_type_idsou return_lengthpara alterar a saída do tokenizador de texto.

encoded_input = tokenizer("How old are you?", "I'm 6 years old",
                        return_token_type_ids=False, 
                        return_length=True,
                        )
print(encoded_input)

输出:
{
    
    'input_ids': [101, 1731, 1385, 1132, 1128, 136, 102, 146, 112, 182, 127, 1201, 1385, 102], 'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 'length': 14}

Além disso, se você deseja processar várias instruções de uma só vez, pode passar duas listas de texto separadamente. do seguinte modo:

batch_sentences = ["Hello I'm a single sentence",
                   "And another sentence",
                   "And the very very last one"]
batch_of_second_sentences = ["I'm a sentence that goes with the first sentence",
                             "And I should be encoded with the second sentence",
                             "And I go with the very last one"]
encoded_inputs = tokenizer(batch_sentences, batch_of_second_sentences)
print(encoded_inputs)

结果:
{
    
    'input_ids': [[101, 8667, 146, 112, 182, 170, 1423, 5650, 102, 146, 112, 182, 170, 5650, 1115, 2947, 1114, 1103, 1148, 5650, 102],
               [101, 1262, 1330, 5650, 102, 1262, 146, 1431, 1129, 12544, 1114, 1103, 1248, 5650, 102],
               [101, 1262, 1103, 1304, 1304, 1314, 1141, 102, 1262, 146, 1301, 1114, 1103, 1304, 1314, 1141, 102]],
'token_type_ids': [[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
                   [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
                   [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1]],
'attention_mask': [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
                   [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
                   [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]}

input_idsPodemos verificar nossa entrada percorrendo a lista decodificada , como segue:

for ids in encoded_inputs["input_ids"]:
    print(tokenizer.decode(ids))

结果:
[CLS] Hello I'm a single sentence [SEP] I'm a sentence that goes with the first sentence [SEP]
[CLS] And another sentence [SEP] And I should be encoded with the second sentence [SEP]
[CLS] And the very very last one [SEP] And I go with the very last one [SEP]

E você ainda pode inserir alguns parâmetros para preencher ou interceptar o texto, ou convertê-lo para um tipo específico na hora da codificação, como segue:

batch = tokenizer(batch_sentences, batch_of_second_sentences, padding=True, truncation=True, return_tensors="pt")

algo sobre preenchimento e truncamento

As instruções aplicáveis ​​na maioria dos casos foram apresentadas acima. Mas o Transformers também fornece mais métodos, que giram em torno de três parâmetros padding, truncation, max_lengthpara expandir.

  • paddingUsado para controlar o preenchimento. Pode ser do tipo booleano ou do tipo string, conforme abaixo:
    • Trueou ”longest”para preencher todas as sentenças até o comprimento máximo na lista de sequências, ou não fazer nada se você fornecer apenas uma sentença.
    • “max_length”É utilizado para preencher a sequência até o comprimento do parâmetro , caso não max_lengthseja informado nenhum max_lengthparâmetro ( ) max_length=None, será preenchido até o comprimento máximo que o modelo pode aceitar. E também funciona quando você fornece apenas uma frase.
    • Falseou ”do_not_pad”para definir como sem preenchimento. E este é o valor padrão do parâmetro.
  • truncationUsado para controlar o truncamento. Pode ser booleano ou string.
    • TrueOu “only_first”a sentença é truncada para o comprimento do parâmetro, se nenhum parâmetro ( ) max_lengthfor fornecido , a sentença é truncada para o comprimento máximo aceitável para o modelo. Se os dados fornecidos forem um par de sentenças ou um lote de pares de sentenças, somente a primeira sentença será truncada.max_lengthmax_length=None
    • “only_sceond”Trunque a frase para max_lengtho comprimento do parâmetro, se nenhum max_lengthparâmetro ( max_length=None) for fornecido, ela será truncada para o comprimento máximo que o modelo pode aceitar. Quando os dados de entrada são um par de frases, apenas o segundo dado será truncado.
    • FalseOu ”do_not_truncate”indicar que a sentença não deve ser interceptada. E este é o valor padrão do parâmetro.
  • max_lengthUsado para controlar o comprimento do preenchimento ou truncamento. Pode ser 整数ou None, o padrão é o grau máximo que o modelo pode aceitar. Se o modelo não tiver um comprimento de entrada máximo específico, ele será truncado ou preenchido para max_length.

Alguns resumos de uso

Se no exemplo a seguir, a entrada for um par de frases, você pode truncation=Truesubstituir ** por STRATEGY, as opções são as seguintes:['only_first', 'only_second', 'longest_first'] **.

  • não trunque
    • Não preenchido:**tokenizer(batch_sentences)**
    • pad até o comprimento máximo do lote atual: **tokenizer(batch_sentences, padding=True)**ou**tokenizer(batch_sentences, padding=’longest’)**
    • Almofada até o comprimento máximo aceitável do modelo:**tokenizer(batch_sentences, padding='max_length')**
    • Preenchimento para um comprimento específico:**tokenizer(batch_sentences, padding='max_length', max_length=42)**
  • Truncar para o comprimento máximo da entrada do modelo
    • Sem preenchimento: tokenizer(batch_sentences, truncation=True)ou tokenizer(batch_sentences, padding=True, truncation=STRATEGY)****
    • pad até o comprimento máximo do lote atual: tokenizer(batch_sentences, padding=True, truncation=True)outokenizer(batch_sentences, padding=True, truncation=STRATEGY)
    • Preenchimento até o comprimento máximo aceitável do modelo: tokenizer(batch_sentences, padding='max_length', truncation=True)outokenizer(batch_sentences, padding='max_length', truncation=STRATEGY)
    • Preencher até um comprimento específico: não pode ser feito porque a adição de max_lengthparâmetros não pode preencher e truncar a entrada máxima.
  • truncar para um comprimento específico
    • sem preenchimento: outokenizer(batch_sentences, truncation=True, max_length=42)
      tokenizer(batch_sentences, truncation=STRATEGY, max_length=42)
    • Pad até o comprimento máximo do lote atual: outokenizer(batch_sentences, padding=True, truncation=True, max_length=42)
      tokenizer(batch_sentences, padding=True, truncation=STRATEGY, max_length=42)
    • Preenchimento até o comprimento máximo aceitável do modelo: não é possível
    • almofada para um comprimento específico: outokenizer(batch_sentences, padding='max_length', truncation=True, max_length=42)
      tokenizer(batch_sentences, padding='max_length', truncation=STRATEGY, max_length=42)

entrada pré-rotulada

Os tokenizadores também podem aceitar entrada pré-tokenizada. Isso é importante em tarefas de reconhecimento de entidade nomeada e marcação de parte da fala.

Deve-se notar que a entrada pré-rotulada não é uma entrada indexada, mas apenas divide as palavras,

Para usar a entrada pré-marcada, basta definir o parâmetro como is_split_into_words=True. Os exemplos são os seguintes:

encoded_input = tokenizer(["Hello", "I'm", "a", "single", "sentence"], is_split_into_words=True)
print(encoded_input)

结果:
{
    
    'input_ids': [101, 8667, 146, 112, 182, 170, 1423, 5650, 102], 
'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0, 0], 
'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1]}

Nota: A entrada pré-identificada também adicionará tags especiais relacionadas ao modelo, a menos que o parâmetro de atributo seja add_special_tokens=False.

Digite várias frases

As frases múltiplas de entrada pré-token são exatamente as mesmas de antes, você pode codificar várias frases como esta:

batch_sentences = [["Hello", "I'm", "a", "single", "sentence"],
                   ["And", "another", "sentence"],
                   ["And", "the", "very", "very", "last", "one"]]
encoded_inputs = tokenizer(batch_sentences, is_split_into_words=True)

par de frases de entrada

Os pares de frases também podem ser inseridos assim:

batch_of_second_sentences = [["I'm", "a", "sentence", "that", "goes", "with", "the", "first", "sentence"],
                             ["And", "I", "should", "be", "encoded", "with", "the", "second", "sentence"],
                             ["And", "I", "go", "with", "the", "very", "last", "one"]]
encoded_inputs = tokenizer(batch_sentences, batch_of_second_sentences, is_split_into_words=True)

preenchimento e truncamento

Também é possível preencher e truncar como antes:

batch = tokenizer(batch_sentences,
                  batch_of_second_sentences,
                  is_split_into_words=True,
                  padding=True,
                  truncation=True,
                  return_tensors="pt")

Acho que você gosta

Origin blog.csdn.net/qq_42464569/article/details/123239558
Recomendado
Clasificación