์ด๋ฏธ์ง ๋ถ๋ฅ[[image-classification]]
[[open-in-colab]]
์ด๋ฏธ์ง ๋ถ๋ฅ๋ ์ด๋ฏธ์ง์ ๋ ์ด๋ธ ๋๋ ํด๋์ค๋ฅผ ํ ๋นํฉ๋๋ค. ํ ์คํธ ๋๋ ์ค๋์ค ๋ถ๋ฅ์ ๋ฌ๋ฆฌ ์ ๋ ฅ์ ์ด๋ฏธ์ง๋ฅผ ๊ตฌ์ฑํ๋ ํฝ์ ๊ฐ์ ๋๋ค. ์ด๋ฏธ์ง ๋ถ๋ฅ์๋ ์์ฐ์ฌํด ํ ํผํด ๊ฐ์ง, ๋์๋ฌผ ๊ฑด๊ฐ ๋ชจ๋ํฐ๋ง, ์๋ฃ ์ด๋ฏธ์ง์์ ์ง๋ณ์ ์งํ ๊ฒ์ฌ ์ง์ ๋ฑ ๋ค์ํ ์์ฉ ์ฌ๋ก๊ฐ ์์ต๋๋ค.
์ด ๊ฐ์ด๋์์๋ ๋ค์์ ์ค๋ช ํฉ๋๋ค:
- Food-101 ๋ฐ์ดํฐ ์ธํธ์์ ViT๋ฅผ ๋ฏธ์ธ ์กฐ์ ํ์ฌ ์ด๋ฏธ์ง์์ ์ํ ํญ๋ชฉ์ ๋ถ๋ฅํฉ๋๋ค.
- ์ถ๋ก ์ ์ํด ๋ฏธ์ธ ์กฐ์ ๋ชจ๋ธ์ ์ฌ์ฉํฉ๋๋ค.
BEiT, BiT, ConvNeXT, ConvNeXTV2, CvT, Data2VecVision, DeiT, DiNAT, EfficientFormer, EfficientNet, FocalNet, ImageGPT, LeViT, MobileNetV1, MobileNetV2, MobileViT, NAT, Perceiver, PoolFormer, RegNet, ResNet, SegFormer, Swin Transformer, Swin Transformer V2, VAN, ViT, ViT Hybrid, ViTMSN
์์ํ๊ธฐ ์ ์, ํ์ํ ๋ชจ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์ค์น๋์ด ์๋์ง ํ์ธํ์ธ์:
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,
... evaluation_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"],
... tokenizer=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'