์ด๋ฏธ์ง ๋ถ๋ฅ[[image-classification]]
[[open-in-colab]]
์ด๋ฏธ์ง ๋ถ๋ฅ๋ ์ด๋ฏธ์ง์ ๋ ์ด๋ธ ๋๋ ํด๋์ค๋ฅผ ํ ๋นํฉ๋๋ค. ํ ์คํธ ๋๋ ์ค๋์ค ๋ถ๋ฅ์ ๋ฌ๋ฆฌ ์ ๋ ฅ์ ์ด๋ฏธ์ง๋ฅผ ๊ตฌ์ฑํ๋ ํฝ์ ๊ฐ์ ๋๋ค. ์ด๋ฏธ์ง ๋ถ๋ฅ์๋ ์์ฐ์ฌํด ํ ํผํด ๊ฐ์ง, ๋์๋ฌผ ๊ฑด๊ฐ ๋ชจ๋ํฐ๋ง, ์๋ฃ ์ด๋ฏธ์ง์์ ์ง๋ณ์ ์งํ ๊ฒ์ฌ ์ง์ ๋ฑ ๋ค์ํ ์์ฉ ์ฌ๋ก๊ฐ ์์ต๋๋ค.
์ด ๊ฐ์ด๋์์๋ ๋ค์์ ์ค๋ช ํฉ๋๋ค:
- Food-101 ๋ฐ์ดํฐ ์ธํธ์์ ViT๋ฅผ ๋ฏธ์ธ ์กฐ์ ํ์ฌ ์ด๋ฏธ์ง์์ ์ํ ํญ๋ชฉ์ ๋ถ๋ฅํฉ๋๋ค.
- ์ถ๋ก ์ ์ํด ๋ฏธ์ธ ์กฐ์ ๋ชจ๋ธ์ ์ฌ์ฉํฉ๋๋ค.
์ด ์์ ๊ณผ ํธํ๋๋ ๋ชจ๋ ์ํคํ ์ฒ์ ์ฒดํฌํฌ์ธํธ๋ฅผ ๋ณด๋ ค๋ฉด ์์ ํ์ด์ง๋ฅผ ํ์ธํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
์์ํ๊ธฐ ์ ์, ํ์ํ ๋ชจ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์ค์น๋์ด ์๋์ง ํ์ธํ์ธ์:
pip install transformers datasets evaluate
Hugging Face ๊ณ์ ์ ๋ก๊ทธ์ธํ์ฌ ๋ชจ๋ธ์ ์ ๋ก๋ํ๊ณ ์ปค๋ฎค๋ํฐ์ ๊ณต์ ํ๋ ๊ฒ์ ๊ถ์ฅํฉ๋๋ค. ๋ฉ์์ง๊ฐ ํ์๋๋ฉด, ํ ํฐ์ ์ ๋ ฅํ์ฌ ๋ก๊ทธ์ธํ์ธ์:
>>> from huggingface_hub import notebook_login
>>> notebook_login()
Food-101 ๋ฐ์ดํฐ ์ธํธ ๊ฐ์ ธ์ค๊ธฐ[[load-food101-dataset]]
๐ค Datasets ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ Food-101 ๋ฐ์ดํฐ ์ธํธ์ ๋ ์์ ๋ถ๋ถ ์งํฉ์ ๊ฐ์ ธ์ค๋ ๊ฒ์ผ๋ก ์์ํฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ์ ์ฒด ๋ฐ์ดํฐ ์ธํธ์ ๋ํ ํ๋ จ์ ๋ง์ ์๊ฐ์ ํ ์ ํ๊ธฐ ์ ์ ์คํ์ ํตํด ๋ชจ๋ ๊ฒ์ด ์ ๋๋ก ์๋ํ๋์ง ํ์ธํ ์ ์์ต๋๋ค.
>>> from datasets import load_dataset
>>> food = load_dataset("food101", split="train[:5000]")
๋ฐ์ดํฐ ์ธํธ์ train์ [~datasets.Dataset.train_test_split] ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ํ๋ จ ๋ฐ ํ
์คํธ ์ธํธ๋ก ๋ถํ ํ์ธ์:
>>> food = food.train_test_split(test_size=0.2)
๊ทธ๋ฆฌ๊ณ ์์๋ฅผ ์ดํด๋ณด์ธ์:
>>> food["train"][0]
{'image': <PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=512x512 at 0x7F52AFC8AC50>,
'label': 79}
๋ฐ์ดํฐ ์ธํธ์ ๊ฐ ์์ ์๋ ๋ ๊ฐ์ ํ๋๊ฐ ์์ต๋๋ค:
image: ์ํ ํญ๋ชฉ์ PIL ์ด๋ฏธ์งlabel: ์ํ ํญ๋ชฉ์ ๋ ์ด๋ธ ํด๋์ค
๋ชจ๋ธ์ด ๋ ์ด๋ธ ID์์ ๋ ์ด๋ธ ์ด๋ฆ์ ์ฝ๊ฒ ๊ฐ์ ธ์ฌ ์ ์๋๋ก ๋ ์ด๋ธ ์ด๋ฆ์ ์ ์๋ก ๋งคํํ๊ณ , ์ ์๋ฅผ ๋ ์ด๋ธ ์ด๋ฆ์ผ๋ก ๋งคํํ๋ ์ฌ์ ์ ๋ง๋์ธ์:
>>> labels = food["train"].features["label"].names
>>> label2id, id2label = dict(), dict()
>>> for i, label in enumerate(labels):
... label2id[label] = str(i)
... id2label[str(i)] = label
์ด์ ๋ ์ด๋ธ ID๋ฅผ ๋ ์ด๋ธ ์ด๋ฆ์ผ๋ก ๋ณํํ ์ ์์ต๋๋ค:
>>> id2label[str(79)]
'prime_rib'
์ ์ฒ๋ฆฌ[[preprocess]]
๋ค์ ๋จ๊ณ๋ ์ด๋ฏธ์ง๋ฅผ ํ ์๋ก ์ฒ๋ฆฌํ๊ธฐ ์ํด ViT ์ด๋ฏธ์ง ํ๋ก์ธ์๋ฅผ ๊ฐ์ ธ์ค๋ ๊ฒ์ ๋๋ค:
>>> from transformers import AutoImageProcessor
>>> checkpoint = "google/vit-base-patch16-224-in21k"
>>> image_processor = AutoImageProcessor.from_pretrained(checkpoint)
์ด๋ฏธ์ง์ ๋ช ๊ฐ์ง ์ด๋ฏธ์ง ๋ณํ์ ์ ์ฉํ์ฌ ๊ณผ์ ํฉ์ ๋ํด ๋ชจ๋ธ์ ๋ ๊ฒฌ๊ณ ํ๊ฒ ๋ง๋ญ๋๋ค. ์ฌ๊ธฐ์ Torchvision์ [`transforms`](https://pytorch.org/vision/stable/transforms.html) ๋ชจ๋์ ์ฌ์ฉํ์ง๋ง, ์ํ๋ ์ด๋ฏธ์ง ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ ์๋ ์์ต๋๋ค.
์ด๋ฏธ์ง์ ์์ ๋ถ๋ถ์ ํฌ๋กญํ๊ณ ํฌ๊ธฐ๋ฅผ ์กฐ์ ํ ๋ค์, ์ด๋ฏธ์ง ํ๊ท ๊ณผ ํ์ค ํธ์ฐจ๋ก ์ ๊ทํํ์ธ์:
>>> from torchvision.transforms import RandomResizedCrop, Compose, Normalize, ToTensor
>>> normalize = Normalize(mean=image_processor.image_mean, std=image_processor.image_std)
>>> size = (
... image_processor.size["shortest_edge"]
... if "shortest_edge" in image_processor.size
... else (image_processor.size["height"], image_processor.size["width"])
... )
>>> _transforms = Compose([RandomResizedCrop(size), ToTensor(), normalize])
๊ทธ๋ฐ ๋ค์ ์ ์ฒ๋ฆฌ ํจ์๋ฅผ ๋ง๋ค์ด ๋ณํ์ ์ ์ฉํ๊ณ ์ด๋ฏธ์ง์ pixel_values(๋ชจ๋ธ์ ๋ํ ์
๋ ฅ)๋ฅผ ๋ฐํํ์ธ์:
>>> def transforms(examples):
... examples["pixel_values"] = [_transforms(img.convert("RGB")) for img in examples["image"]]
... del examples["image"]
... return examples
์ ์ฒด ๋ฐ์ดํฐ ์ธํธ์ ์ ์ฒ๋ฆฌ ๊ธฐ๋ฅ์ ์ ์ฉํ๋ ค๋ฉด ๐ค Datasets [~datasets.Dataset.with_transform]์ ์ฌ์ฉํฉ๋๋ค. ๋ฐ์ดํฐ ์ธํธ์ ์์๋ฅผ ๊ฐ์ ธ์ฌ ๋ ๋ณํ์ด ์ฆ์ ์ ์ฉ๋ฉ๋๋ค:
>>> food = food.with_transform(transforms)
์ด์ [DefaultDataCollator]๋ฅผ ์ฌ์ฉํ์ฌ ์์ ๋ฐฐ์น๋ฅผ ๋ง๋ญ๋๋ค. ๐ค Transformers์ ๋ค๋ฅธ ๋ฐ์ดํฐ ์ฝ๋ ์ดํฐ์ ๋ฌ๋ฆฌ, DefaultDataCollator๋ ํจ๋ฉ๊ณผ ๊ฐ์ ์ถ๊ฐ์ ์ธ ์ ์ฒ๋ฆฌ๋ฅผ ์ ์ฉํ์ง ์์ต๋๋ค.
>>> from transformers import DefaultDataCollator
>>> data_collator = DefaultDataCollator()
๊ณผ์ ํฉ์ ๋ฐฉ์งํ๊ณ ๋ชจ๋ธ์ ๋ณด๋ค ๊ฒฌ๊ณ ํ๊ฒ ๋ง๋ค๊ธฐ ์ํด ๋ฐ์ดํฐ ์ธํธ์ ํ๋ จ ๋ถ๋ถ์ ๋ฐ์ดํฐ ์ฆ๊ฐ์ ์ถ๊ฐํฉ๋๋ค.
์ฌ๊ธฐ์ Keras ์ ์ฒ๋ฆฌ ๋ ์ด์ด๋ก ํ๋ จ ๋ฐ์ดํฐ์ ๋ํ ๋ณํ(๋ฐ์ดํฐ ์ฆ๊ฐ ํฌํจ)๊ณผ
๊ฒ์ฆ ๋ฐ์ดํฐ์ ๋ํ ๋ณํ(์ค์ ํฌ๋กํ, ํฌ๊ธฐ ์กฐ์ , ์ ๊ทํ๋ง)์ ์ ์ํฉ๋๋ค.
tf.image ๋๋ ๋ค๋ฅธ ์ํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
>>> from tensorflow import keras
>>> from tensorflow.keras import layers
>>> size = (image_processor.size["height"], image_processor.size["width"])
>>> train_data_augmentation = keras.Sequential(
... [
... layers.RandomCrop(size[0], size[1]),
... layers.Rescaling(scale=1.0 / 127.5, offset=-1),
... layers.RandomFlip("horizontal"),
... layers.RandomRotation(factor=0.02),
... layers.RandomZoom(height_factor=0.2, width_factor=0.2),
... ],
... name="train_data_augmentation",
... )
>>> val_data_augmentation = keras.Sequential(
... [
... layers.CenterCrop(size[0], size[1]),
... layers.Rescaling(scale=1.0 / 127.5, offset=-1),
... ],
... name="val_data_augmentation",
... )
๋ค์์ผ๋ก ํ ๋ฒ์ ํ๋์ ์ด๋ฏธ์ง๊ฐ ์๋๋ผ ์ด๋ฏธ์ง ๋ฐฐ์น์ ์ ์ ํ ๋ณํ์ ์ ์ฉํ๋ ํจ์๋ฅผ ๋ง๋ญ๋๋ค.
>>> import numpy as np
>>> import tensorflow as tf
>>> from PIL import Image
>>> def convert_to_tf_tensor(image: Image):
... np_image = np.array(image)
... tf_image = tf.convert_to_tensor(np_image)
... # `expand_dims()` is used to add a batch dimension since
... # the TF augmentation layers operates on batched inputs.
... return tf.expand_dims(tf_image, 0)
>>> def preprocess_train(example_batch):
... """Apply train_transforms across a batch."""
... images = [
... train_data_augmentation(convert_to_tf_tensor(image.convert("RGB"))) for image in example_batch["image"]
... ]
... example_batch["pixel_values"] = [tf.transpose(tf.squeeze(image)) for image in images]
... return example_batch
... def preprocess_val(example_batch):
... """Apply val_transforms across a batch."""
... images = [
... val_data_augmentation(convert_to_tf_tensor(image.convert("RGB"))) for image in example_batch["image"]
... ]
... example_batch["pixel_values"] = [tf.transpose(tf.squeeze(image)) for image in images]
... return example_batch
๐ค Datasets [~datasets.Dataset.set_transform]๋ฅผ ์ฌ์ฉํ์ฌ ์ฆ์ ๋ณํ์ ์ ์ฉํ์ธ์:
food["train"].set_transform(preprocess_train)
food["test"].set_transform(preprocess_val)
์ต์ข
์ ์ฒ๋ฆฌ ๋จ๊ณ๋ก DefaultDataCollator๋ฅผ ์ฌ์ฉํ์ฌ ์์ ๋ฐฐ์น๋ฅผ ๋ง๋ญ๋๋ค. ๐ค Transformers์ ๋ค๋ฅธ ๋ฐ์ดํฐ ์ฝ๋ ์ดํฐ์ ๋ฌ๋ฆฌ
DefaultDataCollator๋ ํจ๋ฉ๊ณผ ๊ฐ์ ์ถ๊ฐ ์ ์ฒ๋ฆฌ๋ฅผ ์ ์ฉํ์ง ์์ต๋๋ค.
>>> from transformers import DefaultDataCollator
>>> data_collator = DefaultDataCollator(return_tensors="tf")
ํ๊ฐ[[evaluate]]
ํ๋ จ ์ค์ ํ๊ฐ ์งํ๋ฅผ ํฌํจํ๋ฉด ๋ชจ๋ธ์ ์ฑ๋ฅ์ ํ๊ฐํ๋ ๋ฐ ๋์์ด ๋๋ ๊ฒฝ์ฐ๊ฐ ๋ง์ต๋๋ค. ๐ค Evaluate ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก ํ๊ฐ ๋ฐฉ๋ฒ์ ๋น ๋ฅด๊ฒ ๊ฐ์ ธ์ฌ ์ ์์ต๋๋ค. ์ด ์์ ์์๋ accuracy ํ๊ฐ ์งํ๋ฅผ ๊ฐ์ ธ์ต๋๋ค. (๐ค Evaluate ๋น ๋ฅธ ๋๋ฌ๋ณด๊ธฐ๋ฅผ ์ฐธ์กฐํ์ฌ ํ๊ฐ ์งํ๋ฅผ ๊ฐ์ ธ์ค๊ณ ๊ณ์ฐํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์์ธํ ์์๋ณด์ธ์):
>>> import evaluate
>>> accuracy = evaluate.load("accuracy")
๊ทธ๋ฐ ๋ค์ ์์ธก๊ณผ ๋ ์ด๋ธ์ [~evaluate.EvaluationModule.compute]์ ์ ๋ฌํ์ฌ ์ ํ๋๋ฅผ ๊ณ์ฐํ๋ ํจ์๋ฅผ ๋ง๋ญ๋๋ค:
>>> import numpy as np
>>> def compute_metrics(eval_pred):
... predictions, labels = eval_pred
... predictions = np.argmax(predictions, axis=1)
... return accuracy.compute(predictions=predictions, references=labels)
์ด์ compute_metrics ํจ์๋ฅผ ์ฌ์ฉํ ์ค๋น๊ฐ ๋์์ผ๋ฉฐ, ํ๋ จ์ ์ค์ ํ๋ฉด ์ด ํจ์๋ก ๋๋์์ฌ ๊ฒ์
๋๋ค.
ํ๋ จ[[train]]
[Trainer]๋ฅผ ์ฌ์ฉํ์ฌ ๋ชจ๋ธ์ ๋ฏธ์ธ ์กฐ์ ํ๋ ๋ฐฉ๋ฒ์ ์ต์ํ์ง ์์ ๊ฒฝ์ฐ, ์ฌ๊ธฐ์์ ๊ธฐ๋ณธ ํํ ๋ฆฌ์ผ์ ํ์ธํ์ธ์!
์ด์ ๋ชจ๋ธ์ ํ๋ จ์ํฌ ์ค๋น๊ฐ ๋์์ต๋๋ค! [AutoModelForImageClassification]๋ก ViT๋ฅผ ๊ฐ์ ธ์ต๋๋ค. ์์๋๋ ๋ ์ด๋ธ ์, ๋ ์ด๋ธ ๋งคํ ๋ฐ ๋ ์ด๋ธ ์๋ฅผ ์ง์ ํ์ธ์:
>>> from transformers import AutoModelForImageClassification, TrainingArguments, Trainer
>>> model = AutoModelForImageClassification.from_pretrained(
... checkpoint,
... num_labels=len(labels),
... id2label=id2label,
... label2id=label2id,
... )
์ด์ ์ธ ๋จ๊ณ๋ง ๊ฑฐ์น๋ฉด ๋์ ๋๋ค:
- [
TrainingArguments]์์ ํ๋ จ ํ์ดํผํ๋ผ๋ฏธํฐ๋ฅผ ์ ์ํ์ธ์.image์ด์ด ์ญ์ ๋๊ธฐ ๋๋ฌธ์ ๋ฏธ์ฌ์ฉ ์ด์ ์ ๊ฑฐํ์ง ์๋ ๊ฒ์ด ์ค์ํฉ๋๋ค.image์ด์ด ์์ผ๋ฉดpixel_values์ ์์ฑํ ์ ์์ต๋๋ค. ์ด ๋์์ ๋ฐฉ์งํ๋ ค๋ฉดremove_unused_columns=False๋ก ์ค์ ํ์ธ์! ๋ค๋ฅธ ์ ์ผํ ํ์ ๋งค๊ฐ๋ณ์๋ ๋ชจ๋ธ ์ ์ฅ ์์น๋ฅผ ์ง์ ํ๋output_dir์ ๋๋ค.push_to_hub=True๋ก ์ค์ ํ๋ฉด ์ด ๋ชจ๋ธ์ ํ๋ธ์ ํธ์ํฉ๋๋ค(๋ชจ๋ธ์ ์ ๋ก๋ํ๋ ค๋ฉด Hugging Face์ ๋ก๊ทธ์ธํด์ผ ํฉ๋๋ค). ๊ฐ ์ํญ์ด ๋๋ ๋๋ง๋ค, [Trainer]๊ฐ ์ ํ๋๋ฅผ ํ๊ฐํ๊ณ ํ๋ จ ์ฒดํฌํฌ์ธํธ๋ฅผ ์ ์ฅํฉ๋๋ค. - [
Trainer]์ ๋ชจ๋ธ, ๋ฐ์ดํฐ ์ธํธ, ํ ํฌ๋์ด์ , ๋ฐ์ดํฐ ์ฝ๋ ์ดํฐ ๋ฐcompute_metricsํจ์์ ํจ๊ป ํ๋ จ ์ธ์๋ฅผ ์ ๋ฌํ์ธ์. - [
~Trainer.train]์ ํธ์ถํ์ฌ ๋ชจ๋ธ์ ๋ฏธ์ธ ์กฐ์ ํ์ธ์.
>>> training_args = TrainingArguments(
... output_dir="my_awesome_food_model",
... remove_unused_columns=False,
... eval_strategy="epoch",
... save_strategy="epoch",
... learning_rate=5e-5,
... per_device_train_batch_size=16,
... gradient_accumulation_steps=4,
... per_device_eval_batch_size=16,
... num_train_epochs=3,
... warmup_ratio=0.1,
... logging_steps=10,
... load_best_model_at_end=True,
... metric_for_best_model="accuracy",
... push_to_hub=True,
... )
>>> trainer = Trainer(
... model=model,
... args=training_args,
... data_collator=data_collator,
... train_dataset=food["train"],
... eval_dataset=food["test"],
... processing_class=image_processor,
... compute_metrics=compute_metrics,
... )
>>> trainer.train()
ํ๋ จ์ด ์๋ฃ๋๋ฉด, ๋ชจ๋ ์ฌ๋์ด ๋ชจ๋ธ์ ์ฌ์ฉํ ์ ์๋๋ก [~transformers.Trainer.push_to_hub] ๋ฉ์๋๋ก ๋ชจ๋ธ์ ํ๋ธ์ ๊ณต์ ํ์ธ์:
>>> trainer.push_to_hub()
Keras๋ฅผ ์ฌ์ฉํ์ฌ ๋ชจ๋ธ์ ๋ฏธ์ธ ์กฐ์ ํ๋ ๋ฐฉ๋ฒ์ ์ต์ํ์ง ์์ ๊ฒฝ์ฐ, ๋จผ์ ๊ธฐ๋ณธ ํํ ๋ฆฌ์ผ์ ํ์ธํ์ธ์!
TensorFlow์์ ๋ชจ๋ธ์ ๋ฏธ์ธ ์กฐ์ ํ๋ ค๋ฉด ๋ค์ ๋จ๊ณ๋ฅผ ๋ฐ๋ฅด์ธ์:
- ํ๋ จ ํ์ดํผํ๋ผ๋ฏธํฐ๋ฅผ ์ ์ํ๊ณ ์ตํฐ๋ง์ด์ ์ ํ์ต๋ฅ ์ค์ผ์ฅด์ ์ค์ ํฉ๋๋ค.
- ์ฌ์ ํ๋ จ๋ ๋ชจ๋ธ์ ์ธ์คํด์คํํฉ๋๋ค.
- ๐ค Dataset์
tf.data.Dataset์ผ๋ก ๋ณํํฉ๋๋ค. - ๋ชจ๋ธ์ ์ปดํ์ผํฉ๋๋ค.
- ์ฝ๋ฐฑ์ ์ถ๊ฐํ๊ณ ํ๋ จ์ ์ํํ๊ธฐ ์ํด
fit()๋ฉ์๋๋ฅผ ์ฌ์ฉํฉ๋๋ค. - ์ปค๋ฎค๋ํฐ์ ๊ณต์ ํ๊ธฐ ์ํด ๋ชจ๋ธ์ ๐ค Hub์ ์ ๋ก๋ํฉ๋๋ค.
ํ์ดํผํ๋ผ๋ฏธํฐ, ์ตํฐ๋ง์ด์ ๋ฐ ํ์ต๋ฅ ์ค์ผ์ฅด์ ์ ์ํ๋ ๊ฒ์ผ๋ก ์์ํฉ๋๋ค:
>>> from transformers import create_optimizer
>>> batch_size = 16
>>> num_epochs = 5
>>> num_train_steps = len(food["train"]) * num_epochs
>>> learning_rate = 3e-5
>>> weight_decay_rate = 0.01
>>> optimizer, lr_schedule = create_optimizer(
... init_lr=learning_rate,
... num_train_steps=num_train_steps,
... weight_decay_rate=weight_decay_rate,
... num_warmup_steps=0,
... )
๊ทธ๋ฐ ๋ค์ ๋ ์ด๋ธ ๋งคํ๊ณผ ํจ๊ป [TFAuto ModelForImageClassification]์ผ๋ก ViT๋ฅผ ๊ฐ์ ธ์ต๋๋ค:
>>> from transformers import TFAutoModelForImageClassification
>>> model = TFAutoModelForImageClassification.from_pretrained(
... checkpoint,
... id2label=id2label,
... label2id=label2id,
... )
๋ฐ์ดํฐ ์ธํธ๋ฅผ [~datasets.Dataset.to_tf_dataset]์ data_collator๋ฅผ ์ฌ์ฉํ์ฌ tf.data.Dataset ํ์์ผ๋ก ๋ณํํ์ธ์:
>>> # converting our train dataset to tf.data.Dataset
>>> tf_train_dataset = food["train"].to_tf_dataset(
... columns="pixel_values", label_cols="label", shuffle=True, batch_size=batch_size, collate_fn=data_collator
... )
>>> # converting our test dataset to tf.data.Dataset
>>> tf_eval_dataset = food["test"].to_tf_dataset(
... columns="pixel_values", label_cols="label", shuffle=True, batch_size=batch_size, collate_fn=data_collator
... )
compile()๋ฅผ ์ฌ์ฉํ์ฌ ํ๋ จ ๋ชจ๋ธ์ ๊ตฌ์ฑํ์ธ์:
>>> from tensorflow.keras.losses import SparseCategoricalCrossentropy
>>> loss = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)
>>> model.compile(optimizer=optimizer, loss=loss)
์์ธก์์ ์ ํ๋๋ฅผ ๊ณ์ฐํ๊ณ ๋ชจ๋ธ์ ๐ค Hub๋ก ํธ์ํ๋ ค๋ฉด Keras callbacks๋ฅผ ์ฌ์ฉํ์ธ์.
compute_metrics ํจ์๋ฅผ KerasMetricCallback์ ์ ๋ฌํ๊ณ ,
PushToHubCallback์ ์ฌ์ฉํ์ฌ ๋ชจ๋ธ์ ์
๋ก๋ํฉ๋๋ค:
>>> from transformers.keras_callbacks import KerasMetricCallback, PushToHubCallback
>>> metric_callback = KerasMetricCallback(metric_fn=compute_metrics, eval_dataset=tf_eval_dataset)
>>> push_to_hub_callback = PushToHubCallback(
... output_dir="food_classifier",
... tokenizer=image_processor,
... save_strategy="no",
... )
>>> callbacks = [metric_callback, push_to_hub_callback]
์ด์ ๋ชจ๋ธ์ ํ๋ จํ ์ค๋น๊ฐ ๋์์ต๋๋ค! ํ๋ จ ๋ฐ ๊ฒ์ฆ ๋ฐ์ดํฐ ์ธํธ, ์ํญ ์์ ํจ๊ป fit()์ ํธ์ถํ๊ณ ,
์ฝ๋ฐฑ์ ์ฌ์ฉํ์ฌ ๋ชจ๋ธ์ ๋ฏธ์ธ ์กฐ์ ํฉ๋๋ค:
>>> model.fit(tf_train_dataset, validation_data=tf_eval_dataset, epochs=num_epochs, callbacks=callbacks)
Epoch 1/5
250/250 [==============================] - 313s 1s/step - loss: 2.5623 - val_loss: 1.4161 - accuracy: 0.9290
Epoch 2/5
250/250 [==============================] - 265s 1s/step - loss: 0.9181 - val_loss: 0.6808 - accuracy: 0.9690
Epoch 3/5
250/250 [==============================] - 252s 1s/step - loss: 0.3910 - val_loss: 0.4303 - accuracy: 0.9820
Epoch 4/5
250/250 [==============================] - 251s 1s/step - loss: 0.2028 - val_loss: 0.3191 - accuracy: 0.9900
Epoch 5/5
250/250 [==============================] - 238s 949ms/step - loss: 0.1232 - val_loss: 0.3259 - accuracy: 0.9890
์ถํํฉ๋๋ค! ๋ชจ๋ธ์ ๋ฏธ์ธ ์กฐ์ ํ๊ณ ๐ค Hub์ ๊ณต์ ํ์ต๋๋ค. ์ด์ ์ถ๋ก ์ ์ฌ์ฉํ ์ ์์ต๋๋ค!
์ด๋ฏธ์ง ๋ถ๋ฅ๋ฅผ ์ํ ๋ชจ๋ธ์ ๋ฏธ์ธ ์กฐ์ ํ๋ ์์ธํ ์์ ๋ ๋ค์ PyTorch notebook์ ์ฐธ์กฐํ์ธ์.
์ถ๋ก [[inference]]
์ข์์, ์ด์ ๋ชจ๋ธ์ ๋ฏธ์ธ ์กฐ์ ํ์ผ๋ ์ถ๋ก ์ ์ฌ์ฉํ ์ ์์ต๋๋ค!
์ถ๋ก ์ ์ํํ๊ณ ์ ํ๋ ์ด๋ฏธ์ง๋ฅผ ๊ฐ์ ธ์๋ด ์๋ค:
>>> ds = load_dataset("food101", split="validation[:10]")
>>> image = ds["image"][0]
๋ฏธ์ธ ์กฐ์ ๋ชจ๋ธ๋ก ์ถ๋ก ์ ์๋ํ๋ ๊ฐ์ฅ ๊ฐ๋จํ ๋ฐฉ๋ฒ์ [pipeline]์ ์ฌ์ฉํ๋ ๊ฒ์
๋๋ค. ๋ชจ๋ธ๋ก ์ด๋ฏธ์ง ๋ถ๋ฅ๋ฅผ ์ํ pipeline์ ์ธ์คํด์คํํ๊ณ ์ด๋ฏธ์ง๋ฅผ ์ ๋ฌํฉ๋๋ค:
>>> from transformers import pipeline
>>> classifier = pipeline("image-classification", model="my_awesome_food_model")
>>> classifier(image)
[{'score': 0.31856709718704224, 'label': 'beignets'},
{'score': 0.015232225880026817, 'label': 'bruschetta'},
{'score': 0.01519392803311348, 'label': 'chicken_wings'},
{'score': 0.013022331520915031, 'label': 'pork_chop'},
{'score': 0.012728818692266941, 'label': 'prime_rib'}]
์ํ๋ค๋ฉด, pipeline์ ๊ฒฐ๊ณผ๋ฅผ ์๋์ผ๋ก ๋ณต์ ํ ์๋ ์์ต๋๋ค:
>>> from transformers import AutoImageProcessor
>>> import torch
>>> image_processor = AutoImageProcessor.from_pretrained("my_awesome_food_model")
>>> inputs = image_processor(image, return_tensors="pt")
์ ๋ ฅ์ ๋ชจ๋ธ์ ์ ๋ฌํ๊ณ logits์ ๋ฐํํฉ๋๋ค:
>>> from transformers import AutoModelForImageClassification
>>> model = AutoModelForImageClassification.from_pretrained("my_awesome_food_model")
>>> with torch.no_grad():
... logits = model(**inputs).logits
ํ๋ฅ ์ด ๊ฐ์ฅ ๋์ ์์ธก ๋ ์ด๋ธ์ ๊ฐ์ ธ์ค๊ณ , ๋ชจ๋ธ์ id2label ๋งคํ์ ์ฌ์ฉํ์ฌ ๋ ์ด๋ธ๋ก ๋ณํํฉ๋๋ค:
>>> predicted_label = logits.argmax(-1).item()
>>> model.config.id2label[predicted_label]
'beignets'
์ด๋ฏธ์ง๋ฅผ ์ ์ฒ๋ฆฌํ๊ธฐ ์ํด ์ด๋ฏธ์ง ํ๋ก์ธ์๋ฅผ ๊ฐ์ ธ์ค๊ณ `input`์ TensorFlow ํ
์๋ก ๋ฐํํฉ๋๋ค:
>>> from transformers import AutoImageProcessor
>>> image_processor = AutoImageProcessor.from_pretrained("MariaK/food_classifier")
>>> inputs = image_processor(image, return_tensors="tf")
์ ๋ ฅ์ ๋ชจ๋ธ์ ์ ๋ฌํ๊ณ logits์ ๋ฐํํฉ๋๋ค:
>>> from transformers import TFAutoModelForImageClassification
>>> model = TFAutoModelForImageClassification.from_pretrained("MariaK/food_classifier")
>>> logits = model(**inputs).logits
ํ๋ฅ ์ด ๊ฐ์ฅ ๋์ ์์ธก ๋ ์ด๋ธ์ ๊ฐ์ ธ์ค๊ณ , ๋ชจ๋ธ์ id2label ๋งคํ์ ์ฌ์ฉํ์ฌ ๋ ์ด๋ธ๋ก ๋ณํํฉ๋๋ค:
>>> predicted_class_id = int(tf.math.argmax(logits, axis=-1)[0])
>>> model.config.id2label[predicted_class_id]
'beignets'