language_modeling.md 17.4 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
<!--Copyright 2022 The HuggingFace Team. All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.
11
12
13
14

鈿狅笍 Note that this file is in Markdown but contain specific syntax for our doc-builder (similar to MDX) that may not be
rendered properly in your Markdown viewer.

15
16
17
18
19
20
21
22
23
24
25
26
27
28
-->

# Modelado de lenguaje

El modelado de lenguaje predice palabras en un enunciado. Hay dos formas de modelado de lenguaje.

<Youtube id="Vpjb1lu0MDk"/>

El modelado de lenguaje causal predice el siguiente token en una secuencia de tokens, y el modelo solo puede considerar los tokens a la izquierda.

<Youtube id="mqElG5QJWUg"/>

El modelado de lenguaje por enmascaramiento predice un token enmascarado en una secuencia, y el modelo puede considerar los tokens bidireccionalmente.

29
Esta gu铆a te mostrar谩 c贸mo realizar fine-tuning [DistilGPT2](https://huggingface.co/distilbert/distilgpt2) para modelos de lenguaje causales y [DistilRoBERTa](https://huggingface.co/distilbert/distilroberta-base) para modelos de lenguaje por enmascaramiento en el [r/askscience](https://www.reddit.com/r/askscience/) subdataset [ELI5](https://huggingface.co/datasets/eli5). 
30
31
32

<Tip>

33
Puedes realizar fine-tuning a otras arquitecturas para modelos de lenguaje como [GPT-Neo](https://huggingface.co/EleutherAI/gpt-neo-125M), [GPT-J](https://huggingface.co/EleutherAI/gpt-j-6B) y [BERT](https://huggingface.co/google-bert/bert-base-uncased) siguiendo los mismos pasos presentados en esta gu铆a!
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83

Mira la [p谩gina de tarea](https://huggingface.co/tasks/text-generation) para generaci贸n de texto y la [p谩gina de tarea](https://huggingface.co/tasks/fill-mask) para modelos de lenguajes por enmascaramiento para obtener m谩s informaci贸n sobre los modelos, datasets, y m茅tricas asociadas.

</Tip>

## Carga el dataset ELI5

Carga solo los primeros 5000 registros desde la biblioteca 馃 Datasets, dado que es bastante grande:

```py
>>> from datasets import load_dataset

>>> eli5 = load_dataset("eli5", split="train_asks[:5000]")
```

Divide este dataset en subdatasets para el entrenamiento y el test:

```py
eli5 = eli5.train_test_split(test_size=0.2)
```

Luego observa un ejemplo:

```py
>>> eli5["train"][0]
{'answers': {'a_id': ['c3d1aib', 'c3d4lya'],
  'score': [6, 3],
  'text': ["The velocity needed to remain in orbit is equal to the square root of Newton's constant times the mass of earth divided by the distance from the center of the earth. I don't know the altitude of that specific mission, but they're usually around 300 km. That means he's going 7-8 km/s.\n\nIn space there are no other forces acting on either the shuttle or the guy, so they stay in the same position relative to each other. If he were to become unable to return to the ship, he would presumably run out of oxygen, or slowly fall into the atmosphere and burn up.",
   "Hope you don't mind me asking another question, but why aren't there any stars visible in this photo?"]},
 'answers_urls': {'url': []},
 'document': '',
 'q_id': 'nyxfp',
 'selftext': '_URL_0_\n\nThis was on the front page earlier and I have a few questions about it. Is it possible to calculate how fast the astronaut would be orbiting the earth? Also how does he stay close to the shuttle so that he can return safely, i.e is he orbiting at the same speed and can therefore stay next to it? And finally if his propulsion system failed, would he eventually re-enter the atmosphere and presumably die?',
 'selftext_urls': {'url': ['http://apod.nasa.gov/apod/image/1201/freeflyer_nasa_3000.jpg']},
 'subreddit': 'askscience',
 'title': 'Few questions about this space walk photograph.',
 'title_urls': {'url': []}}
```

Observa que `text` es un subcampo anidado dentro del diccionario `answers`. Cuando preproceses el dataset, deber谩s extraer el subcampo `text` en una columna aparte.

## Preprocesamiento

<Youtube id="ma1TrR7gE7I"/>

Para modelados de lenguaje causales carga el tokenizador DistilGPT2 para procesar el subcampo `text`:

```py
>>> from transformers import AutoTokenizer

84
>>> tokenizer = AutoTokenizer.from_pretrained("distilbert/distilgpt2")
85
86
87
88
89
90
91
92
93
```

<Youtube id="8PmhEIXhBvI"/>

Para modelados de lenguaje por enmascaramiento carga el tokenizador DistilRoBERTa, en lugar de DistilGPT2:

```py
>>> from transformers import AutoTokenizer

94
>>> tokenizer = AutoTokenizer.from_pretrained("distilbert/distilroberta-base")
95
96
```

V.Prasanna kumar's avatar
V.Prasanna kumar committed
97
Extrae el subcampo `text` desde su estructura anidado con el m茅todo [`flatten`](https://huggingface.co/docs/datasets/process#flatten):
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124

```py
>>> eli5 = eli5.flatten()
>>> eli5["train"][0]
{'answers.a_id': ['c3d1aib', 'c3d4lya'],
 'answers.score': [6, 3],
 'answers.text': ["The velocity needed to remain in orbit is equal to the square root of Newton's constant times the mass of earth divided by the distance from the center of the earth. I don't know the altitude of that specific mission, but they're usually around 300 km. That means he's going 7-8 km/s.\n\nIn space there are no other forces acting on either the shuttle or the guy, so they stay in the same position relative to each other. If he were to become unable to return to the ship, he would presumably run out of oxygen, or slowly fall into the atmosphere and burn up.",
  "Hope you don't mind me asking another question, but why aren't there any stars visible in this photo?"],
 'answers_urls.url': [],
 'document': '',
 'q_id': 'nyxfp',
 'selftext': '_URL_0_\n\nThis was on the front page earlier and I have a few questions about it. Is it possible to calculate how fast the astronaut would be orbiting the earth? Also how does he stay close to the shuttle so that he can return safely, i.e is he orbiting at the same speed and can therefore stay next to it? And finally if his propulsion system failed, would he eventually re-enter the atmosphere and presumably die?',
 'selftext_urls.url': ['http://apod.nasa.gov/apod/image/1201/freeflyer_nasa_3000.jpg'],
 'subreddit': 'askscience',
 'title': 'Few questions about this space walk photograph.',
 'title_urls.url': []}
```

Cada subcampo es ahora una columna separada, como lo indica el prefijo `answers`. Observa que `answers.text` es una lista. En lugar de tokenizar cada enunciado por separado, convierte la lista en un string para tokenizarlos conjuntamente.

As铆 es como puedes crear una funci贸n de preprocesamiento para convertir la lista en una cadena y truncar las secuencias para que no superen la longitud m谩xima de input de DistilGPT2:

```py
>>> def preprocess_function(examples):
...     return tokenizer([" ".join(x) for x in examples["answers.text"]], truncation=True)
```

125
Usa de 馃 Datasets la funci贸n [`map`](https://huggingface.co/docs/datasets/process#map) para aplicar la funci贸n de preprocesamiento sobre el dataset en su totalidad. Puedes acelerar la funci贸n `map` configurando el argumento `batched=True` para procesar m煤ltiples elementos del dataset a la vez y aumentar la cantidad de procesos con `num_proc`. Elimina las columnas que no necesitas:
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147

```py
>>> tokenized_eli5 = eli5.map(
...     preprocess_function,
...     batched=True,
...     num_proc=4,
...     remove_columns=eli5["train"].column_names,
... )
```

Ahora necesitas una segunda funci贸n de preprocesamiento para capturar el texto truncado de cualquier ejemplo demasiado largo para evitar cualquier p茅rdida de informaci贸n. Esta funci贸n de preprocesamiento deber铆a:

- Concatenar todo el texto.
- Dividir el texto concatenado en trozos m谩s peque帽os definidos por un `block_size`.

```py
>>> block_size = 128


>>> def group_texts(examples):
...     concatenated_examples = {k: sum(examples[k], []) for k in examples.keys()}
...     total_length = len(concatenated_examples[list(examples.keys())[0]])
148
...     total_length = (total_length // block_size) * block_size
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
...     result = {
...         k: [t[i : i + block_size] for i in range(0, total_length, block_size)]
...         for k, t in concatenated_examples.items()
...     }
...     result["labels"] = result["input_ids"].copy()
...     return result
```

Aplica la funci贸n `group_texts` sobre todo el dataset:

```py
>>> lm_dataset = tokenized_eli5.map(group_texts, batched=True, num_proc=4)
```

Para modelados de lenguaje causales, usa [`DataCollatorForLanguageModeling`] para crear un lote de ejemplos. Esto tambi茅n *rellenar谩 din谩micamente* tu texto a la dimensi贸n del elemento m谩s largo del lote para que de esta manera tengan largo uniforme. Si bien es posible rellenar tu texto en la funci贸n `tokenizer` mediante el argumento `padding=True`, el rellenado din谩mico es m谩s eficiente. 

<frameworkcontent>
<pt>
Puedes usar el token de final de secuencia como el token de relleno y asignar `mlm=False`. Esto usar谩 los inputs como etiquetas movidas un elemento hacia la derecha:

```py
>>> from transformers import DataCollatorForLanguageModeling

>>> tokenizer.pad_token = tokenizer.eos_token
>>> data_collator = DataCollatorForLanguageModeling(tokenizer=tokenizer, mlm=False)
```

Para modelados de lenguaje por enmascaramiento usa el mismo [`DataCollatorForLanguageModeling`] excepto que deber谩s especificar `mlm_probability` para enmascarar tokens aleatoriamente cada vez que iteras sobre los datos.

```py
>>> from transformers import DataCollatorForLanguageModeling

>>> tokenizer.pad_token = tokenizer.eos_token
>>> data_collator = DataCollatorForLanguageModeling(tokenizer=tokenizer, mlm_probability=0.15)
```
</pt>
<tf>
Puedes usar el token de final de secuencia como el token de relleno y asignar `mlm=False`. Esto usar谩 los inputs como etiquetas movidas un elemento hacia la derecha:

```py
>>> from transformers import DataCollatorForLanguageModeling

>>> data_collator = DataCollatorForLanguageModeling(tokenizer=tokenizer, mlm=False, return_tensors="tf")
```

Para modelados de lenguajes por enmascaramiento usa el mismo [`DataCollatorForLanguageModeling`] excepto que deber谩s especificar `mlm_probability` para enmascarar tokens aleatoriamente cada vez que iteras sobre los datos.

```py
>>> from transformers import DataCollatorForLanguageModeling

>>> data_collator = DataCollatorForLanguageModeling(tokenizer=tokenizer, mlm=False, return_tensors="tf")
```
</tf>
</frameworkcontent>

## Modelado de lenguaje causal

206
El modelado de lenguaje causal es frecuentemente utilizado para generaci贸n de texto. Esta secci贸n te muestra c贸mo realizar fine-tuning a [DistilGPT2](https://huggingface.co/distilbert/distilgpt2) para generar nuevo texto.
207
208
209
210
211
212
213
214
215
216

### Entrenamiento

<frameworkcontent>
<pt>
Carga DistilGPT2 con [`AutoModelForCausalLM`]:

```py
>>> from transformers import AutoModelForCausalLM, TrainingArguments, Trainer

217
>>> model = AutoModelForCausalLM.from_pretrained("distilbert/distilgpt2")
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
```

<Tip>

Si no est谩s familiarizado con el proceso de realizar fine-tuning sobre un modelo con [`Trainer`], considera el tutorial b谩sico [aqu铆](../training#finetune-with-trainer)!

</Tip>

A este punto, solo faltan tres pasos:

1. Definir tus hiperpar谩metros de entrenamiento en [`TrainingArguments`].
2. Pasarle los argumentos de entrenamiento a [`Trainer`] junto con el modelo, dataset, y el data collator.
3. Realiza la llamada [`~Trainer.train`] para realizar el fine-tuning sobre tu modelo.

```py
>>> training_args = TrainingArguments(
...     output_dir="./results",
...     evaluation_strategy="epoch",
...     learning_rate=2e-5,
...     weight_decay=0.01,
... )

>>> trainer = Trainer(
...     model=model,
...     args=training_args,
...     train_dataset=lm_dataset["train"],
...     eval_dataset=lm_dataset["test"],
...     data_collator=data_collator,
... )

>>> trainer.train()
```
</pt>
<tf>
252
Para realizar el fine-tuning de un modelo en TensorFlow, comienza por convertir tus datasets al formato `tf.data.Dataset` con [`to_tf_dataset`](https://huggingface.co/docs/datasets/package_reference/main_classes#datasets.Dataset.to_tf_dataset). Especifica los inputs y etiquetas en `columns`, ya sea para mezclar el dataset, tama帽o de lote, y el data collator:
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290

```py
>>> tf_train_set = lm_dataset["train"].to_tf_dataset(
...     columns=["attention_mask", "input_ids", "labels"],
...     dummy_labels=True,
...     shuffle=True,
...     batch_size=16,
...     collate_fn=data_collator,
... )

>>> tf_test_set = lm_dataset["test"].to_tf_dataset(
...     columns=["attention_mask", "input_ids", "labels"],
...     dummy_labels=True,
...     shuffle=False,
...     batch_size=16,
...     collate_fn=data_collator,
... )
```

<Tip>

Si no est谩s familiarizado con realizar fine-tuning de tus modelos con Keras, considera el tutorial b谩sico [aqu铆](training#finetune-with-keras)!

</Tip>

Crea la funci贸n optimizadora, la tasa de aprendizaje, y algunos hiperpar谩metros de entrenamiento:

```py
>>> from transformers import create_optimizer, AdamWeightDecay

>>> optimizer = AdamWeightDecay(learning_rate=2e-5, weight_decay_rate=0.01)
```

Carga DistilGPT2 con [`TFAutoModelForCausalLM`]:

```py
>>> from transformers import TFAutoModelForCausalLM

291
>>> model = TFAutoModelForCausalLM.from_pretrained("distilbert/distilgpt2")
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
```

Configura el modelo para entrenamiento con [`compile`](https://keras.io/api/models/model_training_apis/#compile-method):

```py
>>> import tensorflow as tf

>>> model.compile(optimizer=optimizer)
```

Llama a [`fit`](https://keras.io/api/models/model_training_apis/#fit-method) para realizar el fine-tuning del modelo:

```py
>>> model.fit(x=tf_train_set, validation_data=tf_test_set, epochs=3)
```
</tf>
</frameworkcontent>

## Modelado de lenguaje por enmascaramiento

312
El modelado de lenguaje por enmascaramiento es tambi茅n conocido como una tarea de rellenar la m谩scara, pues predice un token enmascarado dada una secuencia. Los modelos de lenguaje por enmascaramiento requieren una buena comprensi贸n del contexto de una secuencia entera, en lugar de solo el contexto a la izquierda. Esta secci贸n te ense帽a como realizar el fine-tuning de [DistilRoBERTa](https://huggingface.co/distilbert/distilroberta-base) para predecir una palabra enmascarada.
313
314
315
316
317
318
319
320
321
322

### Entrenamiento

<frameworkcontent>
<pt>
Carga DistilRoBERTa con [`AutoModelForMaskedlM`]:

```py
>>> from transformers import AutoModelForMaskedLM

323
>>> model = AutoModelForMaskedLM.from_pretrained("distilbert/distilroberta-base")
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
```

<Tip>

Si no est谩s familiarizado con el proceso de realizar fine-tuning sobre un modelo con [`Trainer`], considera el tutorial b谩sico [aqu铆](../training#finetune-with-trainer)!

</Tip>

A este punto, solo faltan tres pasos:

1. Definir tus hiperpar谩metros de entrenamiento en [`TrainingArguments`].
2. Pasarle los argumentos de entrenamiento a [`Trainer`] junto con el modelo, dataset, y el data collator.
3. Realiza la llamada [`~Trainer.train`] para realizar el fine-tuning de tu modelo.

```py
>>> training_args = TrainingArguments(
...     output_dir="./results",
...     evaluation_strategy="epoch",
...     learning_rate=2e-5,
...     num_train_epochs=3,
...     weight_decay=0.01,
... )

>>> trainer = Trainer(
...     model=model,
...     args=training_args,
...     train_dataset=lm_dataset["train"],
...     eval_dataset=lm_dataset["test"],
...     data_collator=data_collator,
... )

>>> trainer.train()
```
</pt>
<tf>
359
Para realizar el fine-tuning de un modelo en TensorFlow, comienza por convertir tus datasets al formato `tf.data.Dataset` con [`to_tf_dataset`](https://huggingface.co/docs/datasets/package_reference/main_classes#datasets.Dataset.to_tf_dataset). Especifica los inputs y etiquetas en `columns`, ya sea para mezclar el dataset, tama帽o de lote, y el data collator:
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397

```py
>>> tf_train_set = lm_dataset["train"].to_tf_dataset(
...     columns=["attention_mask", "input_ids", "labels"],
...     dummy_labels=True,
...     shuffle=True,
...     batch_size=16,
...     collate_fn=data_collator,
... )

>>> tf_test_set = lm_dataset["test"].to_tf_dataset(
...     columns=["attention_mask", "input_ids", "labels"],
...     dummy_labels=True,
...     shuffle=False,
...     batch_size=16,
...     collate_fn=data_collator,
... )
```

<Tip>

Si no est谩s familiarizado con realizar fine-tuning de tus modelos con Keras, considera el tutorial b谩sico [aqu铆](training#finetune-with-keras)!

</Tip>

Crea la funci贸n optimizadora, la tasa de aprendizaje, y algunos hiperpar谩metros de entrenamiento:

```py
>>> from transformers import create_optimizer, AdamWeightDecay

>>> optimizer = AdamWeightDecay(learning_rate=2e-5, weight_decay_rate=0.01)
```

Carga DistilRoBERTa con [`TFAutoModelForMaskedLM`]:

```py
>>> from transformers import TFAutoModelForMaskedLM

398
>>> model = TFAutoModelForCausalLM.from_pretrained("distilbert/distilroberta-base")
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
```

Configura el modelo para entrenamiento con [`compile`](https://keras.io/api/models/model_training_apis/#compile-method):

```py
>>> import tensorflow as tf

>>> model.compile(optimizer=optimizer)
```

Llama a [`fit`](https://keras.io/api/models/model_training_apis/#fit-method) para realizar el fine-tuning del modelo:

```py
>>> model.fit(x=tf_train_set, validation_data=tf_test_set, epochs=3)
```
</tf>
</frameworkcontent>

<Tip>

Para un ejemplo m谩s profundo sobre c贸mo realizar el fine-tuning sobre un modelo de lenguaje causal, considera
[PyTorch notebook](https://colab.research.google.com/github/huggingface/notebooks/blob/main/examples/language_modeling.ipynb)
o [TensorFlow notebook](https://colab.research.google.com/github/huggingface/notebooks/blob/main/examples/language_modeling-tf.ipynb).

</Tip>