기존의 transforms v1 최적화가 부족하여 느리다.
v2는 텐서기반으로 훨씬 빠르게 작동한다.
일부 메소드는 PIL형태의 이미지를 그대로 넣어도 작동하나 ToImage 메소드를 통해 텐서로 변환 후 사용하는 것을 권장한다.
import torchvision.transforms.v2 as v2
import torch
transform = v2.Compose([
v2.ToImage(),
v2.ToDtype(torch.float32, scale=True),
v2.Resize((224, 224))
])
transformed_image = transform(image)
plt.imshow(transformed_image.permute(1, 2, 0))

transforms: 적용할 변환 리스트p: 변환을 적용할 확률(기본값 0.5)transform = v2.RandomApply([
v2.ColorJitter(brightness=0.5)
], p=0.3)
transformed_image = transform(image)
transform = v2.RandomChoice([
v2.RandomHorizontalFlip(p=1.0),
v2.RandomVerticalFlip(p=1.0)
])
transformed_image = transform(image)
transform = v2.Compose([
v2.ToImage(),
v2.Resize((128, 128))
])
transformed_image = transform(image)
dtype: 변경할 데이터 타입(예: torch.float32, torch.uint8 등)scale: 정수형 이미지를 float으로 변환할 때 0~1로 정규화할지 여부(기본값 False)#ToDtype
import torch
transform = v2.Compose([
v2.ToImage(),
v2.ToDtype(torch.float32, scale=True)
])
transformed_image = transform(image)
#ToPILImage
transform = v2.Compose([
v2.ToImage(),
v2.ToPILImage()
])
pil_image = transform(image)
mean: 각 채널별 평균값(리스트 또는 튜플, 예: [0.485, 0.456, 0.406])std: 각 채널별 표준편차(리스트 또는 튜플, 예: [0.229, 0.224, 0.225])transform = v2.Compose([
v2.ToImage(),
v2.ToDtype(torch.float32, scale=True),
v2.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
normalized_image = transform(image)
plt.imshow(normalized_image.permute(1, 2, 0))

size: 원하는 출력 크기(튜플 또는 정수)interpolation: 보간 방법(기본값은 bilinear)transform = v2.Compose([
v2.ToImage(),
v2.Resize((32, 32))
])
resized_image = transform(image)
plt.imshow(resized_image.permute(1, 2, 0))

size: 잘라낼 크기(정수 또는 튜플)transform = v2.Compose([
v2.ToImage(),
v2.CenterCrop(200)
])
cropped_image = transform(image)
plt.imshow(cropped_image.permute(1, 2, 0))

size: 잘라낼 크기(정수 또는 튜플)transform = v2.Compose([
v2.ToImage(),
v2.RandomCrop(128)
])
cropped_image = transform(image)
plt.imshow(cropped_image.permute(1, 2, 0))

size: 출력(리사이즈) 크기(정수 또는 튜플)scale: 원본 가로/잘라낼 영역 가로, 원본 세로/잘라낼 영역 세로, 기본값 (0.08, 1.0)ratio: 잘라낼 영역의 가로/세로 비율의 범위, 기본값 (3/4, 4/3) : 가로/세로 = 3/4 ~ 4/3from torchvision.transforms.functional import InterpolationMode
transform = v2.Compose([
v2.ToImage(),
v2.RandomResizedCrop(
size=(224, 224),
scale=(0.5, 0.5),
ratio=(0.75, 1.25),
interpolation=InterpolationMode.BILINEAR,
antialias=True
)
])
cropped_image = transform(image)
plt.imshow(cropped_image.permute(1, 2, 0))

padding: 패딩 크기(정수, 튜플)fill: 패딩 영역의 색상(기본값 0)padding_mode: 패딩 방식('constant', 'edge', 'reflect', 'symmetric' 등)transform = v2.Compose([
v2.ToImage(),
v2.Pad(padding=50, fill=128)
])
padded_image = transform(image)
plt.imshow(padded_image.permute(1, 2, 0))

degrees: 회전 각도 범위(정수 또는 튜플, 예: 30이면 -30도~+30도 사이에서 랜덤)interpolation: 보간 방법(기본값 'nearest')expand: True로 설정하면 회전 후 이미지 크기를 확장해서 잘림을 방지한다(기본값 False)center: 회전 중심(기본값은 이미지 중앙)fill: 회전으로 생긴 빈 영역의 색상(기본값 0)transform = v2.Compose([
v2.ToImage(),
v2.RandomRotation(
degrees=45,
interpolation=InterpolationMode.BILINEAR,
expand=True,
fill=128
)
])
rotated_image = transform(image)
plt.imshow(rotated_image.permute(1, 2, 0))

p: 뒤집을 확률(기본값 0.5)transform = v2.Compose([
v2.ToImage(),
v2.RandomHorizontalFlip(p=0.7)
])
flipped_image = transform(image)
plt.imshow(flipped_image.permute(1, 2, 0))
p: 뒤집을 확률(기본값 0.5)transform = v2.Compose([
v2.ToImage(),
v2.RandomVerticalFlip(p=0.3)
])
flipped_image = transform(image)
plt.imshow(flipped_image.permute(1, 2, 0))
degrees: 회전 각도 범위(필수)translate: 가로, 세로의 이동 범위 비율scale: 확대/축소 범위shear: 기울임 각의 최대값(혹은 범위)interpolation: 보간 방법(기본값 'nearest')fill: 변환 후 생긴 빈 영역의 색상(기본값 0)center: 변환 중심(기본값 이미지 중앙)transform = v2.Compose([
v2.ToImage(),
v2.RandomAffine(
degrees=30,
translate=(0.5, 0.5),
scale=(0.8, 1.2),
shear=30,
interpolation=InterpolationMode.BILINEAR,
fill=100
)
])
affined_image = transform(image)
plt.imshow(affined_image.permute(1, 2, 0))

distortion_scale: 모서리의 최대 이동 거리(0~1, 기본값 0.5)p: 변환 적용 확률(기본값 0.5)interpolation: 보간 방법(기본값 'bilinear')fill: 변환 후 생긴 빈 영역의 색상(기본값 0)transform = v2.Compose([
v2.ToImage(),
v2.RandomPerspective(
distortion_scale=0.7,
p=1.0,
fill=255
)
])
perspective_image = transform(image)
plt.imshow(perspective_image.permute(1, 2, 0))

brightness: 밝기 배율 범위(0이상, n 이면 1-n배 ~ 1+n배)contrast: 대비 조절 배율 범위(0~)saturation: 채도 조절 배율 범위hue: 색조 조절 배율 범위(-0.5 ~ +0.5)transform = v2.Compose([
v2.ToImage(),
v2.ColorJitter(brightness=0.0, contrast=0.9, saturation=0.9, hue=0.5)
])
jittered_image = transform(image)
plt.imshow(jittered_image.permute(1, 2, 0))

num_output_channels: 출력 채널 수(1 또는 3, 기본값 1)transform = v2.Compose([
v2.ToImage(),
v2.Grayscale(num_output_channels=1)
])
gray_image = transform(image)
plt.imshow(gray_image.squeeze(), cmap='gray')

p: 반전 적용 확률(기본값 0.5)transform = v2.Compose([
v2.ToImage(),
v2.RandomInvert(p=1)
])
inverted_image = transform(image)
plt.imshow(inverted_image.permute(1, 2, 0))

bits: 유지할 비트 수(예: 4)p: 적용 확률(기본값 0.5)transform = v2.Compose([
v2.ToImage(),
v2.RandomPosterize(bits=1, p=1)
])
posterized_image = transform(image)
plt.imshow(posterized_image.permute(1, 2, 0))

threshold: 임계값(예: 128)p: 적용 확률(기본값 0.5)transform = v2.Compose([
v2.ToImage(),
v2.RandomSolarize(threshold=72, p=1)
])
solarized_image = transform(image)
plt.imshow(solarized_image.permute(1, 2, 0))

p: 적용 확률(기본값 0.5)transform = v2.Compose([
v2.ToImage(),
v2.RandomAutocontrast(p=1)
])
autocontrasted_image = transform(image)
plt.imshow(autocontrasted_image.permute(1, 2, 0))

p: 적용 확률(기본값 0.5)transform = v2.Compose([
v2.ToImage(),
v2.RandomAutocontrast(p=1)
])
autocontrasted_image = transform(image)
plt.imshow(autocontrasted_image.permute(1, 2, 0))
kernel_size: 커널 크기(정수 또는 튜플)sigma: 표준편차 범위(튜플, 기본값 (0.1, 2.0))transform = v2.Compose([
v2.ToImage(),
v2.GaussianBlur(kernel_size=21, sigma=(5, 10))
])
blurred_image = transform(image)
plt.imshow(blurred_image.permute(1, 2, 0))

p: 적용 확률(기본값 0.5)scale: 사각형 영역의 크기 비율 범위(기본값 (0.02, 0.33))ratio: 사각형 영역의 가로세로 비율 범위(기본값 (0.3, 3.3))value: 지운 영역에 채울 값transform = v2.Compose([
v2.ToImage(),
v2.RandomErasing(p=1, scale=(0.02, 0.2), ratio=(0.3, 3.3), value=0)
])
erased_image = transform(image)
plt.imshow(erased_image.permute(1, 2, 0))

데이터 로더로 배치 단위의 이미지를 입력받는다.
분포에서 λ(lambda) 값을 샘플링한다.
배치에서 원본이미지와 섞을 이미지를 1장씩 고른다.
섞을 이미지를 잘라서 원본 이미지에 붙여 새로운 이미지를 만든다.
이때 새로운 이미지에서 섞인 이미지 넓이는 이다.
타겟값은 이다.
배치 내의 모든 이미지를 한 번은 원본이미지로 한 번은 섞을 이미지로 선택하여 배치 수 만큼의 이미지를 만든다.
결국 배치 사이즈와 같은 합성된 이미지를 반환한다.
파라미터 설명:
- num_classes: 클래스의 갯수
alpha: 베타 분포의 alpha 값(혼합 비율 결정)PIL 이미지를 지원하지 않기에 ToTenser를 사용 후 적용한다.
#컷믹스 객체 생성
cutmix = v2.CutMix(num_classes=NUM_CLASSES, alpha=1.0)
...
#학습루프
for images, labels in dataloader:
# CutMix는 배치 단위로 적용
images, labels = cutmix(images, labels)
outputs = model(images)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
optimizer.zero_grad()
break # 예시로 한 배치만
배치단위로 합성되기에 실제론 여러장이 합성되지만
임의로 2장만 섞어서 출력해보면 아래와 같다.

alpha: 베타 분포의 alpha 값(혼합 비율 결정)#믹스업 객체 생성
mixup = MixUp(num_classes=10, alpha=1.0)
...
#학습루프
for images, labels in dataloader:
# images: (batch, C, H, W), labels: (batch,)
images, labels = mixup(images, labels) # 또는 cutmix(images, labels)
outputs = model(images)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
