Q1
Q. Data Augmentation 도중 transforms.ToTensor( ) 이전에 transforms.Normalize( )를 하면 오류가 왜 생겨?
A.
transforms.ToTensor(): 이 변환은 Image(0~255)를 PyTorch tensor(0~1)로 변환한다.
이미지는 일반적으로 0에서 255 사이의 값을 가지는 정수형 픽셀로 구성되어 있다.
ToTensor 변환은 이 값을 0.0에서 1.0 사이의 부동소수점 값으로 변환하여 모델이 처리할 수 있도록 한다.
즉, 각 픽셀 값을 255로 나누는 행위이다.
즉, transforms.ToTensor( )는 [0, 255]의 value와 $H \times W \times C$의 Shape을 가지는 np.ndarray나 PIL Image를 [0.0, 1.0] 사이의 value와 $C \times H \times W$의 Shape을 가지는 torch.FloatTensor로 변환한다.
transforms.Normalize(mean, std): 이 변환은 데이터를 정규화하여 평균을 mean으로, 표준편차를 std로 조정한다.
이 과정은 데이터의 분포를 변경하여 모델의 학습이 더 잘 이루어질 수 있도록 돕는다.
정규화는 tensor 형태의 데이터에 대해 수행되어야 하며, 각 채널에 대해 '(채널 값 - 평균) / 표준편차'의 계산을 수행한다.
순서를 바꾸면 발생하는 문제는 다음과 같다:
만약 transforms.Normalize(0.5, 1.0)을 transforms.ToTensor()보다 먼저 적용한다면, Normalize 변환은 정수 픽셀 값들에 대해 작동하게 된다. 이는 의도한 동작이 아니다.
Normalize는 0에서 1 사이의 부동소수점 값들에 대해 설계되었으며, 원래의 이미지 데이터에 적용하면 비정상적인 결과를 초래할 수 있다. 예를 들어, 원본 이미지 데이터가 0에서 255 사이의 값으로 구성되어 있을 때, 이를 Normalize하는 과정이 의미가 없거나 잘못된 변환을 적용하게 되는 것이다.
따라서, 데이터를 tensor로 변환하는 transforms.ToTensor()를 먼저 적용한 후, 그 결과에 대해 Normalization를 수행하는 transforms.Normalize(0.5, 1.0)를 적용하는 것이 올바른 순서이다.
0~255 값을 먼저 정규화하지 않는 이유
정규화는 이미 0에서 1 사이로 스케일링된 데이터에 대해 주로 적용된다.
이유는 정규화 과정에서 사용되는 평균과 표준편차가 0, 1 스케일에 기반한 값이기 때문이다.
일반적으로 이미지 데이터에 대한 평균과 표준편차는 이미 0, 1 사이로 스케일링된 상태에서 계산된다. 예를 들어, ImageNet 데이터셋을 사용할 때, 사전에 계산된 평균과 표준편차 값은 0~1 범위의 데이터를 기준으로 한다.
만약 0에서 255의 값을 직접 정규화하려고 한다면, 이는 훨씬 큰 범위의 값을 기준으로 평균과 표준편차를 계산하게 되므로, 기존에 널리 사용되는 평균과 표준편차 값과는 매우 다른 결과를 가져올 것이다.
이는 모델 학습에 부정적인 영향을 미칠 수 있으며, 학습 프로세스의 효율성과 효과성을 떨어뜨릴 수 있다.
따라서 일반적인 접근 방식은 이미지 데이터를 먼저 0에서 1 사이의 값으로 스케일링한 후, 해당 데이터에 대해 정규화를 적용하는 것이다. 이 과정은 데이터를 모델이 더 잘 이해하고 처리할 수 있는 형태로 만들어 주므로, 결국 더 나은 학습 결과를 얻는 데 도움이 된다.
Q2
Q. 그럼 transforms.ToTensor( ) 이전 / 이후에 적용해야 하는 Data Augmentation에 대해 정리해줘
A.
transforms.ToTensor() 이전에 적용 가능한 변환들:
대부분의 이미지 증강 기법들은 픽셀 값이 정수형인 PIL 이미지나 NumPy 배열 형태에서 작동한다.
예를 들어, 회전(transforms.Rotate), 반전(transforms.HorizontalFlip, transforms.VerticalFlip), 크기 조정(transforms.Resize), 잘라내기(transforms.Crop) 등의 변환은 transforms.ToTensor() 전에 적용된다.
transforms.ToTensor() 이후에 적용해야 하는 변환들:
transforms.Normalize(): 이미 언급했듯이, 이 변환은 이미지 데이터가 0과 1 사이의 부동 소수점 값으로 변환된 후에 적용되어야 하므로transforms.ToTensor() 다음에 와야 한다.
tensor 기반 변환: 일부 변환은 직접적으로 텐서에 적용되어야 한다.
예를 들어, transforms.RandomErasing()는 이미지 내의 임의의 부분을 삭제하여 데이터 증강을 수행하는데, 이는 tensor 형태의 데이터에 적용되어야 하므로 transforms.ToTensor( ) 이후에 와야 한다.
요약하면, transforms.ToTensor()는 일반적으로 다른 증강 방법 전에 적용되지 않기에 뒷 부분에 위치하지만,
transforms.Normalize( )와 같이 tensor에 직접적으로 적용되는 변환들보다는 앞에 있어야 한다.