์ด๋ฏธ์ง ํน์ง ์ถ์ถ[[image-feature-extraction]]
[[open-in-colab]]
์ด๋ฏธ์ง ํน์ง ์ถ์ถ์ ์ฃผ์ด์ง ์ด๋ฏธ์ง์์ ์๋ฏธ๋ก ์ ์ผ๋ก ์๋ฏธ ์๋ ํน์ง์ ์ถ์ถํ๋ ์์ ์ ๋๋ค. ์ด๋ ์ด๋ฏธ์ง ์ ์ฌ์ฑ ๋ฐ ์ด๋ฏธ์ง ๊ฒ์ ๋ฑ ๋ค์ํ ์ฌ์ฉ ์ฌ๋ก๊ฐ ์์ต๋๋ค. ๊ฒ๋ค๊ฐ ๋๋ถ๋ถ์ ์ปดํจํฐ ๋น์ ๋ชจ๋ธ์ ์ด๋ฏธ์ง ํน์ง ์ถ์ถ์ ์ฌ์ฉํ ์ ์์ผ๋ฉฐ, ์ฌ๊ธฐ์ ์์ ํนํ ํค๋(์ด๋ฏธ์ง ๋ถ๋ฅ, ๋ฌผ์ฒด ๊ฐ์ง ๋ฑ)๋ฅผ ์ ๊ฑฐํ๊ณ ํน์ง์ ์ป์ ์ ์์ต๋๋ค. ์ด๋ฌํ ํน์ง์ ๊ฐ์ฅ์๋ฆฌ ๊ฐ์ง, ๋ชจ์๋ฆฌ ๊ฐ์ง ๋ฑ ๊ณ ์ฐจ์ ์์ค์์ ๋งค์ฐ ์ ์ฉํฉ๋๋ค. ๋ํ ๋ชจ๋ธ์ ๊น์ด์ ๋ฐ๋ผ ์ค์ ์ธ๊ณ์ ๋ํ ์ ๋ณด(์: ๊ณ ์์ด๊ฐ ์ด๋ป๊ฒ ์๊ฒผ๋์ง)๋ฅผ ํฌํจํ ์๋ ์์ต๋๋ค. ๋ฐ๋ผ์ ์ด๋ฌํ ์ถ๋ ฅ์ ํน์ ๋ฐ์ดํฐ ์ธํธ์ ๋ํ ์๋ก์ด ๋ถ๋ฅ๊ธฐ๋ฅผ ํ๋ จํ๋ ๋ฐ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ด ๊ฐ์ด๋์์๋:
image-feature-extractionํ์ดํ๋ผ์ธ์ ํ์ฉํ์ฌ ๊ฐ๋จํ ์ด๋ฏธ์ง ์ ์ฌ์ฑ ์์คํ ์ ๊ตฌ์ถํ๋ ๋ฐฉ๋ฒ์ ๋ฐฐ์๋๋ค.- ๊ธฐ๋ณธ ๋ชจ๋ธ ์ถ๋ก ์ผ๋ก ๋์ผํ ์์ ์ ์ํํฉ๋๋ค.
image-feature-extraction ํ์ดํ๋ผ์ธ์ ์ด์ฉํ ์ด๋ฏธ์ง ์ ์ฌ์ฑ[[image-similarity-using-image-feature-extraction-pipeline]]
๋ฌผ๊ณ ๊ธฐ ๊ทธ๋ฌผ ์์ ์์ ์๋ ๋ ์ฅ์ ๊ณ ์์ด ์ฌ์ง์ด ์์ต๋๋ค. ์ด ์ค ํ๋๋ ์์ฑ๋ ์ด๋ฏธ์ง์ ๋๋ค.
from PIL import Image
import requests
img_urls = ["https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/cats.png", "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/cats.jpeg"]
image_real = Image.open(requests.get(img_urls[0], stream=True).raw).convert("RGB")
image_gen = Image.open(requests.get(img_urls[1], stream=True).raw).convert("RGB")
ํ์ดํ๋ผ์ธ์ ์คํํด ๋ด
์๋ค. ๋จผ์ ํ์ดํ๋ผ์ธ์ ์ด๊ธฐํํ์ธ์. ๋ชจ๋ธ์ ์ง์ ํ์ง ์์ผ๋ฉด, ํ์ดํ๋ผ์ธ์ ์๋์ผ๋ก google/vit-base-patch16-224 ๋ชจ๋ธ๋ก ์ด๊ธฐํ๋ฉ๋๋ค. ์ ์ฌ๋๋ฅผ ๊ณ์ฐํ๋ ค๋ฉด pool์ True๋ก ์ค์ ํ์ธ์.
import torch
from transformers import pipeline
DEVICE = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
pipe = pipeline(task="image-feature-extraction", model_name="google/vit-base-patch16-384", device=DEVICE, pool=True)
pipe๋ฅผ ์ฌ์ฉํ์ฌ ์ถ๋ก ํ๋ ค๋ฉด ๋ ์ด๋ฏธ์ง๋ฅผ ๋ชจ๋ ์ ๋ฌํ์ธ์.
outputs = pipe([image_real, image_gen])
์ถ๋ ฅ์๋ ๋ ์ด๋ฏธ์ง์ ํ๋ง๋(pooled) ์๋ฒ ๋ฉ์ด ํฌํจ๋์ด ์์ต๋๋ค.
# ๋จ์ผ ์ถ๋ ฅ์ ๊ธธ์ด ๊ตฌํ๊ธฐ
print(len(outputs[0][0]))
# ์ถ๋ ฅ ๊ฒฐ๊ณผ ํ์ํ๊ธฐ
print(outputs)
# 768
# [[[-0.03909236937761307, 0.43381670117378235, -0.06913255900144577,
์ ์ฌ๋ ์ ์๋ฅผ ์ป์ผ๋ ค๋ฉด, ์ด๋ค์ ์ ์ฌ๋ ํจ์์ ์ ๋ฌํด์ผ ํฉ๋๋ค.
from torch.nn.functional import cosine_similarity
similarity_score = cosine_similarity(torch.Tensor(outputs[0]),
torch.Tensor(outputs[1]), dim=1)
print(similarity_score)
# tensor([0.6043])
ํ๋ง ์ด์ ์ ๋ง์ง๋ง ์๋ ์ํ๋ฅผ ์ป๊ณ ์ถ๋ค๋ฉด, pool ๋งค๊ฐ๋ณ์์ ์๋ฌด ๊ฐ๋ ์ ๋ฌํ์ง ๋ง์ธ์. ๋ํ, ๊ธฐ๋ณธ๊ฐ์ False๋ก ์ค์ ๋์ด ์์ต๋๋ค. ์ด ์๋ ์ํ๋ ๋ชจ๋ธ์ ํน์ง์ ๊ธฐ๋ฐ์ผ๋ก ์๋ก์ด ๋ถ๋ฅ๊ธฐ๋ ๋ชจ๋ธ์ ํ๋ จ์ํค๋ ๋ฐ ์ ์ฉํฉ๋๋ค.
pipe = pipeline(task="image-feature-extraction", model_name="google/vit-base-patch16-224", device=DEVICE)
output = pipe(image_real)
์์ง ์ถ๋ ฅ์ด ํ๋ง๋์ง ์์๊ธฐ ๋๋ฌธ์, ์ฒซ ๋ฒ์งธ ์ฐจ์์ ๋ฐฐ์น ํฌ๊ธฐ์ด๊ณ ๋ง์ง๋ง ๋ ์ฐจ์์ ์๋ฒ ๋ฉ ํํ์ธ ๋ง์ง๋ง ์๋ ์ํ๋ฅผ ์ป์ ์ ์์ต๋๋ค.
import numpy as np
print(np.array(outputs).shape)
# (1, 197, 768)
AutoModel์ ์ฌ์ฉํ์ฌ ํน์ง๊ณผ ์ ์ฌ์ฑ ์ป๊ธฐ[[getting-features-and-similarities-using-automodel]]
transformers์ AutoModel ํด๋์ค๋ฅผ ์ฌ์ฉํ์ฌ ํน์ง์ ์ป์ ์๋ ์์ต๋๋ค. AutoModel์ ์์
ํนํ ํค๋ ์์ด ๋ชจ๋ transformers ๋ชจ๋ธ์ ๋ก๋ํ ์ ์์ผ๋ฉฐ, ์ด๋ฅผ ํตํด ํน์ง์ ์ถ์ถํ ์ ์์ต๋๋ค.
from transformers import AutoImageProcessor, AutoModel
processor = AutoImageProcessor.from_pretrained("google/vit-base-patch16-224")
model = AutoModel.from_pretrained("google/vit-base-patch16-224").to(DEVICE)
์ถ๋ก ์ ์ํ ๊ฐ๋จํ ํจ์๋ฅผ ์์ฑํด ๋ณด๊ฒ ์ต๋๋ค. ๋จผ์ ์
๋ ฅ๊ฐ์ processor์ ์ ๋ฌํ ๋ค์, ๊ทธ ์ถ๋ ฅ๊ฐ์ model์ ์ ๋ฌํ ๊ฒ์
๋๋ค.
def infer(image):
inputs = processor(image, return_tensors="pt").to(DEVICE)
outputs = model(**inputs)
return outputs.pooler_output
์ด ํจ์์ ์ด๋ฏธ์ง๋ฅผ ์ง์ ์ ๋ฌํ์ฌ ์๋ฒ ๋ฉ์ ์ป์ ์ ์์ต๋๋ค.
embed_real = infer(image_real)
embed_gen = infer(image_gen)
๊ทธ๋ฆฌ๊ณ ์ด ์๋ฒ ๋ฉ์ ์ฌ์ฉํ์ฌ ๋ค์ ์ ์ฌ๋๋ฅผ ๊ณ์ฐํ ์ ์์ต๋๋ค.
from torch.nn.functional import cosine_similarity
similarity_score = cosine_similarity(embed_real, embed_gen, dim=1)
print(similarity_score)
# tensor([0.6061], device='cuda:0', grad_fn=<SumBackward1>)