huggingface--transformers
e06fe8e8c6
Secret Leaks / trufflehog (push) Failing after 1s
Build documentation / build (push) Failing after 1s
Build documentation / build_other_lang (push) Failing after 0s
CodeQL Security Analysis / CodeQL Analysis (push) Failing after 0s
PR CI / pr-ci (push) Failing after 1s
Slow tests on important models (on Push - A10) / Get all modified files (push) Failing after 1s
Slow tests on important models (on Push - A10) / Model CI (push) Has been skipped
Self-hosted runner (benchmark) / Benchmark (aws-g5-4xlarge-cache) (push) Has been cancelled
New model PR merged notification / Notify new model (push) Has been cancelled
Update Transformers metadata / build_and_package (push) Has been cancelled
264 ่ก
11 KiB
Markdown
264 ่ก
11 KiB
Markdown
<!--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.
|
|
|
|
โ ๏ธ 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.
|
|
|
|
-->
|
|
|
|
# ๋ฒ์ญ[[translation]]
|
|
|
|
[[open-in-colab]]
|
|
|
|
<Youtube id="1JvfrvZgi6c"/>
|
|
|
|
๋ฒ์ญ์ ํ ์ธ์ด๋ก ๋ ์ํ์ค๋ฅผ ๋ค๋ฅธ ์ธ์ด๋ก ๋ณํํฉ๋๋ค. ๋ฒ์ญ์ด๋ ์์ฝ์ ์
๋ ฅ์ ๋ฐ์ ์ผ๋ จ์ ์ถ๋ ฅ์ ๋ฐํํ๋ ๊ฐ๋ ฅํ ํ๋ ์์ํฌ์ธ ์ํ์ค-ํฌ-์ํ์ค ๋ฌธ์ ๋ก ๊ตฌ์ฑํ ์ ์๋ ๋ํ์ ์ธ ํ์คํฌ์
๋๋ค. ๋ฒ์ญ ์์คํ
์ ์ผ๋ฐ์ ์ผ๋ก ๋ค๋ฅธ ์ธ์ด๋ก ๋ ํ
์คํธ ๊ฐ์ ๋ฒ์ญ์ ์ฌ์ฉ๋์ง๋ง, ์์ฑ ๊ฐ์ ํต์ญ์ด๋ ํ
์คํธ-์์ฑ ๋๋ ์์ฑ-ํ
์คํธ์ ๊ฐ์ ์กฐํฉ์๋ ์ฌ์ฉ๋ ์ ์์ต๋๋ค.
|
|
|
|
์ด ๊ฐ์ด๋์์ ํ์ตํ ๋ด์ฉ์:
|
|
|
|
1. ์์ด ํ
์คํธ๋ฅผ ํ๋์ค์ด๋ก ๋ฒ์ญํ๊ธฐ ์ํด [T5](https://huggingface.co/google-t5/t5-small) ๋ชจ๋ธ์ OPUS Books ๋ฐ์ดํฐ์ธํธ์ ์์ด-ํ๋์ค์ด ํ์ ์งํฉ์ผ๋ก ํ์ธํ๋ํ๋ ๋ฐฉ๋ฒ๊ณผ
|
|
2. ํ์ธํ๋๋ ๋ชจ๋ธ์ ์ถ๋ก ์ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์
๋๋ค.
|
|
|
|
<Tip>
|
|
|
|
์ด ์์
๊ณผ ํธํ๋๋ ๋ชจ๋ ์ํคํ
์ฒ์ ์ฒดํฌํฌ์ธํธ๋ฅผ ๋ณด๋ ค๋ฉด [์์
ํ์ด์ง](https://huggingface.co/tasks/translation)๋ฅผ ํ์ธํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
|
|
|
|
</Tip>
|
|
|
|
์์ํ๊ธฐ ์ ์ ํ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ๋ชจ๋ ์ค์น๋์ด ์๋์ง ํ์ธํ์ธ์:
|
|
|
|
```bash
|
|
pip install transformers datasets evaluate sacrebleu
|
|
```
|
|
|
|
๋ชจ๋ธ์ ์
๋ก๋ํ๊ณ ์ปค๋ฎค๋ํฐ์ ๊ณต์ ํ ์ ์๋๋ก Hugging Face ๊ณ์ ์ ๋ก๊ทธ์ธํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ์๋ก์ด ์ฐฝ์ด ํ์๋๋ฉด ํ ํฐ์ ์
๋ ฅํ์ฌ ๋ก๊ทธ์ธํ์ธ์.
|
|
|
|
```py
|
|
>>> from huggingface_hub import notebook_login
|
|
|
|
>>> notebook_login()
|
|
```
|
|
|
|
## OPUS Books ๋ฐ์ดํฐ์ธํธ ๊ฐ์ ธ์ค๊ธฐ[[load-opus-books-dataset]]
|
|
|
|
๋จผ์ ๐ค Datasets ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ [OPUS Books](https://huggingface.co/datasets/opus_books) ๋ฐ์ดํฐ์ธํธ์ ์์ด-ํ๋์ค์ด ํ์ ์งํฉ์ ๊ฐ์ ธ์ค์ธ์.
|
|
|
|
```py
|
|
>>> from datasets import load_dataset
|
|
|
|
>>> books = load_dataset("opus_books", "en-fr")
|
|
```
|
|
|
|
๋ฐ์ดํฐ์ธํธ๋ฅผ [`~datasets.Dataset.train_test_split`] ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ํ๋ จ ๋ฐ ํ
์คํธ ๋ฐ์ดํฐ๋ก ๋ถํ ํ์ธ์.
|
|
|
|
```py
|
|
>>> books = books["train"].train_test_split(test_size=0.2)
|
|
```
|
|
|
|
ํ๋ จ ๋ฐ์ดํฐ์์ ์์๋ฅผ ์ดํด๋ณผ๊น์?
|
|
|
|
```py
|
|
>>> books["train"][0]
|
|
{'id': '90560',
|
|
'translation': {'en': 'But this lofty plateau measured only a few fathoms, and soon we reentered Our Element.',
|
|
'fr': 'Mais ce plateau รฉlevรฉ ne mesurait que quelques toises, et bientรดt nous fรปmes rentrรฉs dans notre รฉlรฉment.'}}
|
|
```
|
|
|
|
๋ฐํ๋ ๋์
๋๋ฆฌ์ `translation` ํค๊ฐ ํ
์คํธ์ ์์ด, ํ๋์ค์ด ๋ฒ์ ์ ํฌํจํ๊ณ ์๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค.
|
|
|
|
## ์ ์ฒ๋ฆฌ[[preprocess]]
|
|
|
|
<Youtube id="XAR8jnZZuUs"/>
|
|
|
|
๋ค์ ๋จ๊ณ๋ก ์์ด-ํ๋์ค์ด ์์ ์ฒ๋ฆฌํ๊ธฐ ์ํด T5 ํ ํฌ๋์ด์ ๋ฅผ ๊ฐ์ ธ์ค์ธ์.
|
|
|
|
```py
|
|
>>> from transformers import AutoTokenizer
|
|
|
|
>>> checkpoint = "google-t5/t5-small"
|
|
>>> tokenizer = AutoTokenizer.from_pretrained(checkpoint)
|
|
```
|
|
|
|
๋ง๋ค ์ ์ฒ๋ฆฌ ํจ์๋ ์๋ ์๊ตฌ์ฌํญ์ ์ถฉ์กฑํด์ผ ํฉ๋๋ค:
|
|
|
|
1. T5๊ฐ ๋ฒ์ญ ํ์คํฌ์์ ์ธ์งํ ์ ์๋๋ก ์
๋ ฅ ์์ ํ๋กฌํํธ๋ฅผ ์ถ๊ฐํ์ธ์. ์ฌ๋ฌ NLP ํ์คํฌ๋ฅผ ํ ์ ์๋ ๋ชจ๋ธ ์ค ์ผ๋ถ๋ ์ด๋ ๊ฒ ํ์คํฌ ํ๋กฌํํธ๋ฅผ ๋ฏธ๋ฆฌ ์ค์ผํฉ๋๋ค.
|
|
2. ์์ด(์์ด)๊ณผ ๋ฒ์ญ์ด(ํ๋์ค์ด)๋ฅผ ๋ณ๋๋ก ํ ํฐํํ์ธ์. ์์ด ์ดํ๋ก ์ฌ์ ํ์ต๋ ํ ํฌ๋์ด์ ๋ก ํ๋์ค์ด ํ
์คํธ๋ฅผ ํ ํฐํํ ์๋ ์๊ธฐ ๋๋ฌธ์
๋๋ค.
|
|
3. `max_length` ๋งค๊ฐ๋ณ์๋ก ์ค์ ํ ์ต๋ ๊ธธ์ด๋ณด๋ค ๊ธธ์ง ์๋๋ก ์ํ์ค๋ฅผ truncateํ์ธ์.
|
|
|
|
```py
|
|
>>> source_lang = "en"
|
|
>>> target_lang = "fr"
|
|
>>> prefix = "translate English to French: "
|
|
|
|
|
|
>>> def preprocess_function(examples):
|
|
... inputs = [prefix + example[source_lang] for example in examples["translation"]]
|
|
... targets = [example[target_lang] for example in examples["translation"]]
|
|
... model_inputs = tokenizer(inputs, text_target=targets, max_length=128, truncation=True)
|
|
... return model_inputs
|
|
```
|
|
|
|
์ ์ฒด ๋ฐ์ดํฐ์ธํธ์ ์ ์ฒ๋ฆฌ ํจ์๋ฅผ ์ ์ฉํ๋ ค๋ฉด ๐ค Datasets์ [`~datasets.Dataset.map`] ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ธ์. `map` ํจ์์ ์๋๋ฅผ ๋์ด๋ ค๋ฉด `batched=True`๋ฅผ ์ค์ ํ์ฌ ๋ฐ์ดํฐ์ธํธ์ ์ฌ๋ฌ ์์๋ฅผ ํ ๋ฒ์ ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค.
|
|
|
|
```py
|
|
>>> tokenized_books = books.map(preprocess_function, batched=True)
|
|
```
|
|
|
|
์ด์ [`DataCollatorForSeq2Seq`]๋ฅผ ์ฌ์ฉํ์ฌ ์์ ๋ฐฐ์น๋ฅผ ์์ฑํฉ๋๋ค. ๋ฐ์ดํฐ์ธํธ์ ์ต๋ ๊ธธ์ด๋ก ์ ๋ถ๋ฅผ paddingํ๋ ๋์ , ๋ฐ์ดํฐ ์ ๋ ฌ ์ค ๊ฐ ๋ฐฐ์น์ ์ต๋ ๊ธธ์ด๋ก ๋ฌธ์ฅ์ *๋์ ์ผ๋ก padding*ํ๋ ๊ฒ์ด ๋ ํจ์จ์ ์
๋๋ค.
|
|
|
|
```py
|
|
>>> from transformers import DataCollatorForSeq2Seq
|
|
|
|
>>> data_collator = DataCollatorForSeq2Seq(tokenizer=tokenizer, model=checkpoint)
|
|
```
|
|
|
|
## ํ๊ฐ[[evalulate]]
|
|
|
|
ํ๋ จ ์ค์ ๋ฉํธ๋ฆญ์ ํฌํจํ๋ฉด ๋ชจ๋ธ์ ์ฑ๋ฅ์ ํ๊ฐํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค. ๐ค [Evaluate](https://huggingface.co/docs/evaluate/index) ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก ํ๊ฐ ๋ฐฉ๋ฒ(evaluation method)์ ๋น ๋ฅด๊ฒ ๊ฐ์ ธ์ฌ ์ ์์ต๋๋ค. ํ์ฌ ํ์คํฌ์ ์ ํฉํ SacreBLEU ๋ฉํธ๋ฆญ์ ๊ฐ์ ธ์ค์ธ์. (๋ฉํธ๋ฆญ์ ๊ฐ์ ธ์ค๊ณ ๊ณ์ฐํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์์ธํ ์์๋ณด๋ ค๋ฉด ๐ค Evaluate [๋๋ฌ๋ณด๊ธฐ](https://huggingface.co/docs/evaluate/a_quick_tour)๋ฅผ ์ฐธ์กฐํ์ธ์):
|
|
|
|
```py
|
|
>>> import evaluate
|
|
|
|
>>> metric = evaluate.load("sacrebleu")
|
|
```
|
|
|
|
๊ทธ๋ฐ ๋ค์ [`~evaluate.EvaluationModule.compute`]์ ์์ธก๊ฐ๊ณผ ๋ ์ด๋ธ์ ์ ๋ฌํ์ฌ SacreBLEU ์ ์๋ฅผ ๊ณ์ฐํ๋ ํจ์๋ฅผ ์์ฑํ์ธ์:
|
|
|
|
```py
|
|
>>> import numpy as np
|
|
|
|
|
|
>>> def postprocess_text(preds, labels):
|
|
... preds = [pred.strip() for pred in preds]
|
|
... labels = [[label.strip()] for label in labels]
|
|
|
|
... return preds, labels
|
|
|
|
|
|
>>> def compute_metrics(eval_preds):
|
|
... preds, labels = eval_preds
|
|
... if isinstance(preds, tuple):
|
|
... preds = preds[0]
|
|
... decoded_preds = tokenizer.batch_decode(preds, skip_special_tokens=True)
|
|
|
|
... labels = np.where(labels != -100, labels, tokenizer.pad_token_id)
|
|
... decoded_labels = tokenizer.batch_decode(labels, skip_special_tokens=True)
|
|
|
|
... decoded_preds, decoded_labels = postprocess_text(decoded_preds, decoded_labels)
|
|
|
|
... result = metric.compute(predictions=decoded_preds, references=decoded_labels)
|
|
... result = {"bleu": result["score"]}
|
|
|
|
... prediction_lens = [np.count_nonzero(pred != tokenizer.pad_token_id) for pred in preds]
|
|
... result["gen_len"] = np.mean(prediction_lens)
|
|
... result = {k: round(v, 4) for k, v in result.items()}
|
|
... return result
|
|
```
|
|
|
|
์ด์ `compute_metrics` ํจ์๋ ์ค๋น๋์๊ณ , ํ๋ จ ๊ณผ์ ์ ์ค์ ํ ๋ ๋ค์ ์ดํด๋ณผ ์์ ์
๋๋ค.
|
|
|
|
## ํ๋ จ[[train]]
|
|
|
|
<Tip>
|
|
|
|
[`Trainer`]๋ก ๋ชจ๋ธ์ ํ์ธํ๋ํ๋ ๋ฐฉ๋ฒ์ ์ต์ํ์ง ์๋ค๋ฉด [์ฌ๊ธฐ](../training#train-with-pytorch-trainer)์์ ๊ธฐ๋ณธ ํํ ๋ฆฌ์ผ์ ์ดํด๋ณด์๊ธฐ ๋ฐ๋๋๋ค!
|
|
|
|
</Tip>
|
|
|
|
๋ชจ๋ธ์ ํ๋ จ์ํฌ ์ค๋น๊ฐ ๋์๊ตฐ์! [`AutoModelForSeq2SeqLM`]์ผ๋ก T5๋ฅผ ๋ก๋ํ์ธ์:
|
|
|
|
```py
|
|
>>> from transformers import AutoModelForSeq2SeqLM, Seq2SeqTrainingArguments, Seq2SeqTrainer
|
|
|
|
>>> model = AutoModelForSeq2SeqLM.from_pretrained(checkpoint)
|
|
```
|
|
|
|
์ด์ ์ธ ๋จ๊ณ๋ง ๊ฑฐ์น๋ฉด ๋์
๋๋ค:
|
|
|
|
1. [`Seq2SeqTrainingArguments`]์์ ํ๋ จ ํ์ดํผํ๋ผ๋ฏธํฐ๋ฅผ ์ ์ํ์ธ์. ์ ์ผํ ํ์ ๋งค๊ฐ๋ณ์๋ ๋ชจ๋ธ์ ์ ์ฅํ ์์น์ธ `output_dir`์
๋๋ค. ๋ชจ๋ธ์ Hub์ ํธ์ํ๊ธฐ ์ํด `push_to_hub=True`๋ก ์ค์ ํ์ธ์. (๋ชจ๋ธ์ ์
๋ก๋ํ๋ ค๋ฉด Hugging Face์ ๋ก๊ทธ์ธํด์ผ ํฉ๋๋ค.) [`Trainer`]๋ ์ํญ์ด ๋๋ ๋๋ง๋ค SacreBLEU ๋ฉํธ๋ฆญ์ ํ๊ฐํ๊ณ ํ๋ จ ์ฒดํฌํฌ์ธํธ๋ฅผ ์ ์ฅํฉ๋๋ค.
|
|
2. [`Seq2SeqTrainer`]์ ํ๋ จ ์ธ์๋ฅผ ์ ๋ฌํ์ธ์. ๋ชจ๋ธ, ๋ฐ์ดํฐ ์ธํธ, ํ ํฌ๋์ด์ , data collator ๋ฐ `compute_metrics` ํจ์๋ ๋ฉ๋ฌ์ ์ ๋ฌํด์ผ ํฉ๋๋ค.
|
|
3. [`~Trainer.train`]์ ํธ์ถํ์ฌ ๋ชจ๋ธ์ ํ์ธํ๋ํ์ธ์.
|
|
|
|
```py
|
|
>>> training_args = Seq2SeqTrainingArguments(
|
|
... output_dir="my_awesome_opus_books_model",
|
|
... eval_strategy="epoch",
|
|
... learning_rate=2e-5,
|
|
... per_device_train_batch_size=16,
|
|
... per_device_eval_batch_size=16,
|
|
... weight_decay=0.01,
|
|
... save_total_limit=3,
|
|
... num_train_epochs=2,
|
|
... predict_with_generate=True,
|
|
... fp16=True,
|
|
... push_to_hub=True,
|
|
... )
|
|
|
|
>>> trainer = Seq2SeqTrainer(
|
|
... model=model,
|
|
... args=training_args,
|
|
... train_dataset=tokenized_books["train"],
|
|
... eval_dataset=tokenized_books["test"],
|
|
... processing_class=tokenizer,
|
|
... data_collator=data_collator,
|
|
... compute_metrics=compute_metrics,
|
|
... )
|
|
|
|
>>> trainer.train()
|
|
```
|
|
|
|
ํ์ต์ด ์๋ฃ๋๋ฉด [`~transformers.Trainer.push_to_hub`] ๋ฉ์๋๋ก ๋ชจ๋ธ์ Hub์ ๊ณต์ ํ์ธ์. ์ด๋ฌ๋ฉด ๋๊ตฌ๋ ๋ชจ๋ธ์ ์ฌ์ฉํ ์ ์๊ฒ ๋ฉ๋๋ค:
|
|
|
|
```py
|
|
>>> trainer.push_to_hub()
|
|
```
|
|
|
|
<Tip>
|
|
|
|
๋ฒ์ญ์ ์ํด ๋ชจ๋ธ์ ํ์ธํ๋ํ๋ ๋ฐฉ๋ฒ์ ๋ํ ๋ณด๋ค ์์ธํ ์์ ๋ ํด๋น [PyTorch ๋
ธํธ๋ถ](https://colab.research.google.com/github/huggingface/notebooks/blob/main/examples/translation.ipynb) ๋๋ [TensorFlow ๋
ธํธ๋ถ](https://colab.research.google.com/github/huggingface/notebooks/blob/main/examples/translation-tf.ipynb)์ ์ฐธ์กฐํ์ธ์.
|
|
|
|
</Tip>
|
|
|
|
## ์ถ๋ก [[inference]]
|
|
|
|
์ข์์, ์ด์ ๋ชจ๋ธ์ ํ์ธํ๋ํ์ผ๋ ์ถ๋ก ์ ์ฌ์ฉํ ์ ์์ต๋๋ค!
|
|
|
|
๋ค๋ฅธ ์ธ์ด๋ก ๋ฒ์ญํ๊ณ ์ถ์ ํ
์คํธ๋ฅผ ์จ๋ณด์ธ์. T5์ ๊ฒฝ์ฐ ์ํ๋ ํ์คํฌ๋ฅผ ์
๋ ฅ์ ์ ๋์ฌ๋ก ์ถ๊ฐํด์ผ ํฉ๋๋ค. ์๋ฅผ ๋ค์ด ์์ด์์ ํ๋์ค์ด๋ก ๋ฒ์ญํ๋ ๊ฒฝ์ฐ, ์๋์ ๊ฐ์ ์ ๋์ฌ๊ฐ ์ถ๊ฐ๋ฉ๋๋ค:
|
|
|
|
```py
|
|
>>> text = "translate English to French: Legumes share resources with nitrogen-fixing bacteria."
|
|
```
|
|
|
|
ํ
์คํธ๋ฅผ ํ ํฐํํ๊ณ `input_ids`๋ฅผ PyTorch ํ
์๋ก ๋ฐํํ์ธ์:
|
|
|
|
```py
|
|
>>> from transformers import AutoTokenizer
|
|
|
|
>>> tokenizer = AutoTokenizer.from_pretrained("my_awesome_opus_books_model")
|
|
>>> inputs = tokenizer(text, return_tensors="pt").input_ids
|
|
```
|
|
|
|
[`~generation.GenerationMixin.generate`] ๋ฉ์๋๋ก ๋ฒ์ญ์ ์์ฑํ์ธ์. ๋ค์ํ ํ
์คํธ ์์ฑ ์ ๋ต ๋ฐ ์์ฑ์ ์ ์ดํ๊ธฐ ์ํ ๋งค๊ฐ๋ณ์์ ๋ํ ์์ธํ ๋ด์ฉ์ [Text Generation](../main_classes/text_generation) API๋ฅผ ์ดํด๋ณด์๊ธฐ ๋ฐ๋๋๋ค.
|
|
|
|
```py
|
|
>>> from transformers import AutoModelForSeq2SeqLM
|
|
|
|
>>> model = AutoModelForSeq2SeqLM.from_pretrained("my_awesome_opus_books_model")
|
|
>>> outputs = model.generate(inputs, max_new_tokens=40, do_sample=True, top_k=30, top_p=0.95)
|
|
```
|
|
|
|
์์ฑ๋ ํ ํฐ ID๋ค์ ๋ค์ ํ
์คํธ๋ก ๋์ฝ๋ฉํ์ธ์:
|
|
|
|
```py
|
|
>>> tokenizer.decode(outputs[0], skip_special_tokens=True)
|
|
'Les lignรฉes partagent des ressources avec des bactรฉries enfixant l'azote.'
|
|
```
|