수달이네 기술 블로그

7. Multi-class weather dataset(날씨 이미지 데이터셋) + 이미지 데이터 처리 본문

AI공부/딥러닝

7. Multi-class weather dataset(날씨 이미지 데이터셋) + 이미지 데이터 처리

슬픈 수달이 2026. 2. 3. 23:40

Multi-class weather dataset

다양한 기상 조건을 포함하는 이미지 데이터셋

  • 맑음, 비, 눈, 흐림의 4가지 클래스로 이루어진 다중 클래스 분류 문제
  • 다양한 시간, 계절, 지역에서 촬영된 이미지.
  • 날씨 조건을 정확히 분류, 기상관측, 자동화된 날씨 보고, 자율주행 차량의 환경인식 시스템등의 응용분야에 활용 가능함.

데이터셋 준비

import os
import zipfile
import random
from shutil import copyfile, rmtree
train_dir = './train'
test_dir = './test'
base_dir = './Multi-class Weather Dataset'
  • train 데이터셋과 test 데이터셋이 담길 디렉토리 위치를 준비한다.
categories = ['Cloudy', 'Rain','Shine','Sunrise']
  • 실제 카테고리별로 변수를 저장하고.
if os.path.exists(train_dir):
    rmtree(train_dir)       #폴더가 있으면 지워짐.
if os.path.exists(test_dir):
    rmtree(test_dir)
    
os.makedirs(train_dir, exist_ok=True)
os.makedirs(test_dir, exist_ok=True)
  • 원래 있는 폴더를 지우고 새로 생성해준다.
for category in categories:
    os.makedirs(os.path.join(train_dir, category), exist_ok=True)
    os.makedirs(os.path.join(test_dir, category), exist_ok=True)

    category_path = os.path.join(base_dir, category)
    images = os.listdir(category_path)
    random.shuffle(images)

    split_index = int(0.8 * len(images))
    train_images = images[:split_index]
    test_images = images[split_index:]

    for image in train_images:
        src = os.path.join(category_path, image)
        dst = os.path.join(train_dir, category, image)
        copyfile(src, dst)

    for image in test_images:
        src = os.path.join(category_path, image)
        dst = os.path.join(test_dir, category, image)
        copyfile(src, dst)
  • 이후 카테고리 별로 이미지를 무작위로 섞어 해당 이미지들을 카테고리 별로 분류시킨다.
  • 80%는 train, 20%는 test데이터로 사용
  • 이후 해당 데이터 셋을 원래 데이터셋에서 가져와 분류시킴

시작전 import

import torch
import time
import torchvision
import torchvision.transforms as transforms
import torchvision.models as models
import torchvision.datasets as datasets
from torchvision.utils import make_grid
import torch.optim as optim
import torch.nn as nn
import torch.nn.functional as F
from torch.utils.data import random_split, DataLoader
import matplotlib.pyplot as plt
import matplotlib.image as image
import numpy as np

데이터 셋

데이터 전처리

transform_train = transforms.Compose([
    transforms.Resize((256, 256)),
    transforms.RandomHorizontalFlip(),
    transforms.ToTensor(),
    transforms.Normalize(
		    mean = [0.5, 0.5, 0.5], 
		    std = [0.5, 0.5, 0.5]
    )
])
  • Resize(): 사이즈 변환
  • RandomHorizontalFlip(): 좌우 반전(데이터 증강)
  • ToTensor(): 정규화 + 모델에서 연산이 가능하도록 텐서형으로 변환
  • Normalize(): 평균과 표준편차를 0.5에 맞춰줌. (정규화, 실제로 논문에서 평균, 표준편차를 0.5로 맞추면 성능이 좋아짐을 알았음)
transform_test = transforms.Compose([
    transforms.Resize((256, 256)),
    transforms.ToTensor(),
    transforms.Normalize(
		    mean = [0.5, 0.5, 0.5], 
		    std = [0.5, 0.5, 0.5]
    )
])
  • 위는 test를 transform해준다. RandomHorizontalFlip()만 지워줌
    • 검증을 해야하기 때문에 증강을 할 필요없다.

ToTensor

  • 이미지를 PyTorch 텐서로 변환
  • 픽셀값을 [0,255] > [0.0,1.0]의 범위로 정규화
  • 이미지의 차원을 (H[높이],W[너비],C[채널]) > (C, H, W): 파이토치 지원

Normalize

  • 텐서로 변환된 이미지의 픽셀값을 정규화(mean: 각 채널의 평균, std: 각 채널의 표준편차)
  • 위에선 0.5로 설정(R,G,B채널 각각)
  • 해당 정규화 메서드는 일반적으로 픽셀값의 범위를 [-1,1][-1,1][-1,1]로 조정하려고 사용한다.
    • 이전에 픽셀값을[0,1][0,1][0,1]로 변환된 상태에서 변환.

데이터셋 구축

train_dataset = datasets.ImageFolder(
    root= 'train/',
    transform=transform_train
)
  • 위에서 만든 데이터 전처리 과정으로 데이터셋을 구축한다.

ImageFolder(): 이미지 데이터를 특정 디렉터리 구조에서 로드하는 클래스

  • 데이터 셋을 만들때 레이블의 경우 데이터셋 폴더의 순서에 따라 자동으로 레이블이 저장된다.
  • 지금은 Cloudy: 0, Rain: 1, Shine: 2, Sunrise: 3 으로 알파벳 순으로 정렬됨.
dataset_size = len(train_dataset)
train_size = int(0.8 * dataset_size)
val_size = dataset_size - train_size
train_dataset, val_dataset = random_split(train_dataset, [train_size, val_size])
  • train_dataset에서 80%를 온전한 traindata로 사용하고, 20%를 valid(검증용)데이터셋으로 사용한다.
test_dataset = datasets.ImageFolder(
    root= 'test/',
    transform=transform_test
)
  • test데이터셋도 구축한 후
train_dataloader = DataLoader(train_dataset, batch_size=64, shuffle=True)
val_dataloader = DataLoader(val_dataset, batch_size=64, shuffle=True)
test_dataloader = DataLoader(test_dataset, batch_size=64, shuffle=False)
  • 데이터 로더를 만든다.
plt.rcParams['figure.figsize'] = [12, 8]
plt.rcParams['figure.dpi'] = 60
plt.rcParams.update({'font.size': 20})
def imshow(img):
    input = input.numpy().transpose((1, 2, 0))
    mean = np.array([0.5, 0.5, 0.5])
    std = np.array([0.5, 0.5, 0.5])
    input = std * input + mean
    input = np.clip(input, 0, 1)
    plt.imshow(input)
    plt.show()

imshow():역정규화 함수

  • 이전 ToTensor로 이미지를 0.0~0.1범위로 정규화+순서를 (C,H,W)로 변환했다.
    • input = input.numpy().transpose((1, 2, 0)): 다시 (H, W, C로 변환한다)
    • input = std * input + mean: 다시 원래 이미지로 변환한다.
    • input = np.clip(input, 0, 1): 0보다 작으면 0, 1보다 크면 1로 변환
      • 255로 변환하지 않고, 다시 0~1로 만들어줌
class_names = {
    0: 'Cloudy',
    1: 'Rain',
    2: 'Shine',
    3: 'Sunrise'
}
iterator = iter(train_dataloader)
images, labels = next(iterator)
out = make_grid(images[:4])
imshow(out)
  • batch_size = 64로 설정했으므로 images와 labels는 모두 64개씩 삽입된다.

  • 위와같이 격자형태로 4개가 보인다.
print([class_names[labels[i].item()]for i in range(4)])

# ['Cloudy', 'Sunrise', 'Cloudy', 'Cloudy']
  • 위와 같이 라벨을 숫자에서 영문으로 바꿔서 보여줄수 있다.
이후엔 이미지 데이터 셋을 처리했으니 모델을 구축하여 데이터를 학습 할 것이다.