import clip
clip
라이브러리를 임포트한다.
CLIP은 OpenAI에서 개발했다.
이미지와 텍스트를 함께 이해하는 모델이다.
clip.available_models()
clip.available_models()
는 사용 가능한 CLIP 모델의 이름을 리스트로 반환한다.
반환된 모델 목록:
['RN50', 'RN101', 'RN50x4', 'RN50x16', 'RN50x64', 'ViT-B/32', 'ViT-B/16', 'ViT-L/14', 'ViT-L/14@336px']
각 항목은 CLIP 모델의 이름을 나타낸다.
RN50
는 ResNet-50 기반 모델을 의미한다.
ViT-B/32
는 Vision Transformer 기반 모델을 의미한다.
model, preprocess = clip.load("ViT-B/32")
clip.load("ViT-B/32")
는 ViT-B/32
모델을 로드하고 모델과 전처리 함수를 반환한다.
model
변수에는 모델 객체가 저장된다.
preprocess
변수에는 입력 데이터를 모델에 맞게 전처리하는 함수가 저장된다.
model.cuda().eval()
model.cuda()
는 모델을 GPU로 이동시킨다.
model.eval()
은 모델을 평가 모드로 설정한다. 평가모드란 모델을 학습이 아닌 추론 모드로 사용하겠다는 의미다.
input_resolution = model.visual.input_resolution
context_length = model.context_length
vocab_size = model.vocab_size
model.visual.input_resolution
: 모델의 시각적 입력 해상도를 반환한다.
model.context_length
: 텍스트 입력의 최대 길이를 반환한다.
model.vocab_size
는 모델의 어휘 크기를 반환한다.
print("Model parameters:", f"{np.sum([int(np.prod(p.shape)) for p in model.parameters()]):,}")
model.parameters()
: 모델의 모든 파라미터를 반환한다.
각 파라미터의 shape을 곱해서 전체 파라미터 수를 계산하고, 이를 모두 더한 값을 출력한다.
np.prod(p.shape)
: 파라미터의 shape의 모든 값을 곱하여 파라미터의 수를 계산한다.
np.sum(...)
: 모든 파라미터 수를 더한다.
f"{...:,}"
는 숫자를 쉼표로 구분된 형식으로 출력한다.
print("Input resolution:", input_resolution)
print("Context length:", context_length)
print("Vocab size:", vocab_size)
모델의 입력 해상도, 텍스트 문맥 길이, 어휘 크기를 출력한다.
Model parameters: 151,277,313
Input resolution: 224
Context length: 77
Vocab size: 49408
이 출력은 로드한 ViT-B/32
모델의 파라미터 수가 151,277,313개, 입력 해상도가 224x224, 문맥 길이가 77, 어휘 크기가 49,408임을 나타낸다.
CLIP 라이브러리와 이미지 전처리 객체 로드
preprocess
preprocess
객체는 clip.load()
함수의 두 번째 반환 값으로, 이미지를 모델이 기대하는 형태로 전처리하기 위해 사용하는 torchvision.transforms
객체이다.전처리 단계 나열
Compose(
Resize(size=224, interpolation=bicubic, max_size=None, antialias=True)
CenterCrop(size=(224, 224))
<function _convert_image_to_rgb at 0x79e73f943250>
ToTensor()
Normalize(mean=(0.48145466, 0.4578275, 0.40821073), std=(0.26862954, 0.26130258, 0.27577711))
)
Resize(size=224, interpolation=bicubic, max_size=None, antialias=True)
: 이미지를 224x224 크기로 리사이즈한다. bicubic
보간법을 사용합니다.CenterCrop(size=(224, 224))
: 이미지의 중심을 기준으로 224x224 크기로 자른다.<function _convert_image_to_rgb at 0x79e73f943250>
: 이미지를 RGB 형식으로 변환한다.ToTensor()
: 이미지를 텐서 형식으로 변환한다.Normalize(mean=(0.48145466, 0.4578275, 0.40821073), std=(0.26862954, 0.26130258, 0.27577711))
: 이미지 픽셀 값을 주어진 평균 및 표준편차로 정규화한다.텍스트 토크나이징
clip.tokenize("Hello World!")
clip.tokenize()
는 문자열을 토큰으로 변환하는 함수이다. CLIP 모델이 기대하는 입력 형식으로 변환한다.토큰화된 출력 확인
tensor([[49406, 3306, 1002, 256, 49407, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0]], dtype=torch.int32)
필요한 라이브러리 임포트
import os
import skimage
import IPython.display
import matplotlib.pyplot as plt
from PIL import Image
import numpy as np
from collections import OrderedDict
import torch
%matplotlib inline
%config InlineBackend.figure_format = 'retina'
skimage
와 PIL
: 이미지 처리matplotlib
: 이미지 시각화torch
: 텐서 연산이미지와 텍스트 설명 설정
descriptions = {
"page": "a page of text about segmentation",
"chelsea": "a facial photo of a tabby cat",
"astronaut": "a portrait of an astronaut with the American flag",
"rocket": "a rocket standing on a launchpad",
"motorcycle_right": "a red motorcycle standing in a garage",
"camera": "a person looking at a camera on a tripod",
"horse": "a black-and-white silhouette of a horse",
"coffee": "a cup of coffee on a saucer"
}
descriptions
딕셔너리는 이미지 파일 이름과 그에 대응하는 텍스트 설명을 저장한다.skimage 데이터 확인 및 필터링
original_images = [] # skimage의 원본 image
images = [] # preprocessed image가 들어감
texts = [] # description(prompt)가 들어감, 만약 image의 이름이 coffee면 "a cup of coffee on a saucer"
plt.figure(figsize=(16, 5))
for filename in [filename for filename in os.listdir(skimage.data_dir) if filename.endswith(".png") or filename.endswith(".jpg")]:
name = os.path.splitext(filename)[0]
if name not in descriptions:
continue
image = Image.open(os.path.join(skimage.data_dir, filename)).convert("RGB")
plt.subplot(2, 4, len(images) + 1)
plt.imshow(image)
plt.title(f"{filename}\n{descriptions[name]}")
plt.xticks([])
plt.yticks([])
original_images.append(image)
images.append(preprocess(image))
texts.append(descriptions[name])
plt.tight_layout()
original_images
, images
, texts
리스트를 초기화한다.plt.figure(figsize=(16, 5))
는 16x5 크기의 시각화 영역을 설정한다.for
루프는 skimage.data_dir
디렉터리에서 .png
또는 .jpg
확장자를 가진 파일들을 반복한다.name
변수에 저장한다.name
이 descriptions
딕셔너리에 없는 경우 continue
로 다음 파일로 넘어간다.RGB
형식으로 열고 image
변수에 저장한다.plt.subplot(2, 4, len(images) + 1)
는 2행 4열의 서브플롯 중 현재 이미지 인덱스에 맞는 위치를 선택한다.xticks
와 yticks
를 빈 리스트로 설정하여 축 눈금을 제거한다.original_images
리스트에 추가한다.images
리스트에 추가한다.texts
리스트에 추가한다.plt.tight_layout()
: 플롯의 레이아웃을 자동으로 조정하여 겹치지 않게 만든다.