본문 바로가기
AI/딥러닝

08. 간단한 CNN 모델 만들기

by 사라리24 2024. 6. 20.
SMALL

 

1.  간단한 CNN 모델 만들기 

 

 

  • import

       
        import torch
        import torch.nn as nn
        import torch.optim as optim


 

 

  • PyTorch의 Tensor를 생성하고 그 형태(shape)를 출력

       
        # 배치크기 * 채널(1: 그레이스케일, 3: 컬러) * 높이 * 너비
        inputs= torch.Tensor(1,1,28,28)
        print(inputs.shape)


torch.Size([1, 1, 28, 28])
========================
1x1x28x28인 4차원 텐서

  • 첫 번째 차원(batch dimension): 배치 크기(batch size)는 1
  • 두 번째 차원(channel dimension): 채널 수는 1, 이미지가 그레이스케일
  • 세 번째 차원(height dimension): 높이는 28
  • 네 번째 차원(width dimension): 너비는 28

 

  • PyTorch를 사용하여 첫 번째 Convolutional Layer를 정의하고 입력 데이터에 대해 적용

       

        # 첫번째 Conv2D
        conv1 = nn. Conv2d(in_channels=1, out_channels=32, kernel_size=3,padding='same')
        out = conv1(inputs)
        print(out.shape)


  1. Conv2d 정의
    • nn.Conv2d: PyTorch의 2차원 Convolutional Layer를 정의하는 클래스입니다.
    • in_channels=1: 입력 이미지의 채널 수입니다. 여기서는 흑백 이미지이므로 채널 수가 1입니다.
    • out_channels=32: Convolutional Layer에서 생성할 필터(또는 채널)의 수입니다.즉, 출력 이미지의 채널 수가 32개입니다.
    • kernel_size=3: 필터(커널)의 크기입니다. 3x3 크기의 필터를 사용합니다.
    • padding='same': 입력 이미지와 출력 이미지의 크기를 동일하게 유지하는 패딩 방식입니다.
      이 경우 자동으로 적절한 패딩이 적용됩니다.
  2. 입력 데이터 적용
    • conv1(inputs)
      정의한 Conv2d 레이어에 입력 데이터 inputs를 적용하여 출력을 계산합니다.
      여기서 inputs는 Convolutional Layer에 입력될 이미지 데이터입니다.
  3. 출력 형태 출력
    • out.shape
      Convolutional Layer를 거친 후의 출력 텐서의 형태를 출력합니다.
      이를 통해 출력 이미지의 크기와 채널 수를 확인할 수 있습니다.

결과 해석

이 코드는 입력 이미지에 대해 첫 번째 Convolutional Layer를 정의하고 적용한 결과를 보여줍니다.
Conv2d 레이어는 입력 이미지를 필터를 이용해 특징 맵으로 변환하는 역할을 수행하며,
이를 통해 이미지에서의 패턴 인식 및 특징 추출이 가능해집니다.
torch.Size([1, 32, 28, 28])

: 출력된 out 텐서의 모양입니다.
  • 배치 크기(batch size)는 1입니다.
  • 출력 채널 수는 32입니다. 이는 컨볼루션 필터(커널) 개수에 해당합니다.
  • 높이는 28입니다. 입력 이미지의 높이와 같습니다.
  • 너비는 28입니다. 입력 이미지의 너비와 같습니다

 

 

 

  • PyTorch를 사용하여 첫 번째 MaxPooling Layer를 정의하고 이전에 정의한 Convolutional Layer의 출력에 적용

       
        # 첫번째 MaxPool2D
        pool = nn.MaxPool2d(kernel_size=2)
        out = pool(out)
        print(out.shape)


  1. MaxPool2d 정의
    • nn.MaxPool2d: PyTorch의 2차원 MaxPooling Layer를 정의하는 클래스입니다.
    • kernel_size=2: 풀링 연산을 수행할 영역의 크기입니다. 여기서는 2x2 크기의 영역에서 최댓값을 추출하여 풀링합니다.
  2. 이전 Convolutional Layer의 출력에 MaxPooling 적용
    • pool(out): 이전에 정의한 Convolutional Layer의 출력 out에 MaxPooling을 적용합니다. 이를 통해 특성 맵의 크기가 축소됩니다.
  3. 출력 형태 출력
    • out.shape: MaxPooling Layer를 거친 후의 출력 텐서의 형태를 출력합니다. 이를 통해 출력 특성 맵의 크기가 어떻게 변화했는지 확인할 수 있습니다.

결과 해석

MaxPooling은 Convolutional Layer를 거친 후 특성 맵의 크기를 줄이는 역할을 합니다.
주로 합성곱 신경망(Convolutional Neural Network, CNN)에서 사용되며,
특성 맵의 공간적 크기를 줄이고 계산량을 감소시키며 추출된 특징의 위치 변화에 대한 불변성을 제공합니다.
이 코드에서는 MaxPooling을 적용하여 특성 맵의 크기를 절반으로 줄인 예시를 보여줍니다.
torch.Size([1, 32, 14, 14])

  • 배치 크기: 1 (변하지 않음)
  • 채널 수: 32  (변하지 않음)
  • 높이: 14 ( 맥스 풀링에 의해 반으로 줄어듦, 32 -> 14 )
  • 너비: 14 ( 맥스 풀링에 의해 반으로 줄어듦, 32 -> 14 )

 

 

  • PyTorch를 사용하여 두 번째 2D 컨볼루션 레이어를 정의하고 적용한 후 출력 텐서의 형태를 출력

       
        # 두번째 Conv2D
        conv2 = nn. Conv2d(in_channels=32, out_channels=64, kernel_size=3,padding='same')
        out = conv2(out)
        print(out.shape)

 
  1. in_channels의 변경
    • 첫 번째 Conv2d 레이어에서는 in_channels=1로 설정되어 있었습니다. 이는 입력 이미지의 채널 수가 1임을 의미합니다.
    • 두 번째 Conv2d 레이어에서는 in_channels=32로 설정되어 있습니다. 이는 이전 Conv2d 레이어에서 출력된 특성 맵의 채널 수가 32임을 의미합니다. 즉, 첫 번째 레이어의 출력을 두 번째 레이어의 입력으로 사용합니다.
  2. out_channels의 변경
    • 첫 번째 Conv2d 레이어에서는 out_channels=32로 설정되어 있었습니다. 이는 첫 번째 레이어에서 생성할 출력 이미지의 채널 수가 32임을 의미합니다.
    • 두 번째 Conv2d 레이어에서는 out_channels=64로 설정되어 있습니다. 이는 두 번째 레이어에서 생성할 출력 이미지의 채널 수가 64임을 의미합니다. 따라서 두 번째 레이어는 입력 이미지의 특성을 더 다양하게 추출할 수 있습니다.
이와 같이 in_channels와 out_channels의 값은 Conv2d 레이어에서 입력 이미지와 출력 이미지의 채널 수를 결정하는 중요한 매개변수입니다. 처음의 Conv2d 레이어에서 생성된 32개의 채널을 가진 출력 특성 맵이 두 번째 Conv2d 레이어의 입력으로 제공되고, 두 번째 레이어에서는 64개의 채널을 가진 출력 특성 맵이 생성됩니다.
torch.Size([1, 64, 14, 14])

  • 배치 크기: 1 (변하지 않음)
  • 채널 수: 64 (32 -> 64로 변경)
  • 높이: 14 (변하지 않음)
  • 너비: 14  (변하지 않음)
 

 

 

 

  • 두 번째 2D 맥스 풀링 레이어를 정의하고 적용한 후 출력 텐서의 형태를 출력

      

        # 두번째 MaxPool2D
        pool = nn.MaxPool2d(kernel_size=2)
        out = pool(out)
        print(out.shape)


  1. MaxPooling 적용 시점
    • 이전 코드에서는 첫 번째 Conv2d 레이어와 두 번째 Conv2d 레이어 사이에 MaxPooling을 적용했습니다.
    • 이 코드에서는 두 번째 Conv2d 레이어 이후에 MaxPooling을 적용합니다. 즉, 두 번째 Conv2d 레이어를 거친 후의 출력 특성 맵에 MaxPooling을 적용하여 크기를 줄입니다.
따라서 이 코드에서는 두 번째 Conv2d 레이어에서 생성된 출력 특성 맵에 MaxPooling을 적용하여, 특성 맵의 공간적 크기를 절반으로 줄이고 있습니다. 이로 인해 계산 효율성이 높아지고, 추출된 특징의 위치 변화에 대한 불변성을 제공합니다.
 
 
torch.Size([1, 64, 7, 7])

  • 배치 크기: 1 (변하지 않음)
  • 채널 수: 64 (변하지 않음)
  • 높이: 7 (맥스 풀링에 의해 반으로 줄어듦, 14 -> 7)
  • 너비: 7 (맥스 풀링에 의해 반으로 줄어듦, 14 -> 7)



 

 

  • PyTorch에서 3차원 데이터를 1차원으로 펼치는 과정
    Convolutional Neural Network (CNN)에서 Convolutional Layer와 MaxPooling Layer를 거친 후에
    Fully Connected Layer (Linear Layer)에 입력하기 위해 필요한 작업

       

        # Flatten
        # 배치를 제외한 3차원 데이터를 1차원으로 펼침
        # 1차원으로 만들어야 nn.LInear() 레이어에 넣을 수 있음
        flatten = nn.Flatten()
        out = flatten(out)
        print(out.shape)


  1. Flatten 레이어 정의
    • nn.Flatten(): PyTorch에서 제공하는 클래스로, 다차원 데이터를 1차원으로 평평하게 만드는 레이어입니다.
    • 3차원의 이미지나 특성 맵을 1차원으로 변환하여, 이후에 사용될 Fully Connected Layer에 입력할 수 있도록 합니다.
  2. 입력 데이터에 Flatten 적용
    • flatten(out): 이전 단계에서 생성된 출력 특성 맵 out에 Flatten 레이어를 적용합니다.
    • 3차원의 특성 맵을 1차원으로 변환하여, 이후에 Linear Layer에 입력할 수 있도록 준비합니다.
  3. 출력 형태 출력
    • out.shape: Flatten 레이어를 거친 후의 출력 텐서의 형태를 출력합니다. 이를 통해 1차원으로 펼쳐진 데이터의 크기를 확인할 수 있습니다.

결과 해석

Flatten 레이어는 CNN에서 Convolutional Layer와 MaxPooling Layer를 거친 후에 사용되며, 다차원의 특성 맵을 1차원의 벡터로 변환합니다. 이 과정은 이미지 처리와 같은 작업에서 추출된 특징을 Fully Connected Layer로 전달하여 분류 등의 작업을 수행할 수 있도록 합니다. 위의 코드에서는 Flatten 레이어를 이용해 64개의 채널을 가진 출력 특성 맵을 1차원으로 변환하는 과정을 보여줍니다.
torch.Size([1, 3136])

  • 배치 크기: 1 (변하지 않음)
  • 평탄화된 크기: 64 * 7 * 7 = 3136 (64개의 채널에 각 채널이 7x7 크기)

 

 

  • PyTorch에서 Fully Connected Layer (선형 회귀) 레이어에 통과시킨 후 , Flatten된 데이터를 이 레이어에 입력하는 과정

       
        # Dance(Fully Connected)
        # 선형 회귀
        fc = nn.Linear(3136,10)
        out = fc(out)
        print(out.shape)


  1. Fully Connected Layer 정의
    • nn.Linear(3136, 10): PyTorch에서 제공하는 클래스로, 입력 크기가 3136이고 출력 크기가 10인 Fully Connected Layer를 정의합니다.
    • 이는 Flatten된 데이터를 받아들여 3136개의 입력 특성을 10개의 출력 클래스로 변환하는 선형 변환을 수행합니다.
  2. 입력 데이터에 Fully Connected Layer 적용
    • fc(out): 이전 단계에서 Flatten된 데이터 out에 Fully Connected Layer를 적용합니다.
    • Flatten된 1차원 벡터인 out을 받아들여, 선형 변환을 거친 후 10개의 출력을 생성합니다.
  3. 출력 형태 출력
    • out.shape: Fully Connected Layer를 거친 후의 출력 텐서의 형태를 출력합니다. 이를 통해 10개의 출력 클래스를 가진 벡터의 크기를 확인할 수 있습니다.

결과 해석

Fully Connected Layer는 Convolutional Neural Network (CNN)의 마지막 단계로, 이미지 처리에서 추출된 특성을 이용해 최종적으로 클래스를 예측하는 역할을 합니다. 위의 코드에서는 Flatten된 데이터를 입력으로 받아들여 3136개의 입력을 처리하고, 10개의 클래스로 출력하는 Fully Connected Layer를 정의하고 있습니다. 이러한 구조는 주로 이미지 분류 문제에서 사용되며, 출력 레이어로 Softmax를 추가하여 확률 분포를 얻을 수 있습니다.
torch.Size([1, 10])


이전 Flatten 레이어 후의 출력 형태가 torch.Size([1, 3136])였습니다. 이를 Fully Connected 레이어에 입력하면:

  • 배치 크기: 1 (변하지 않음)
  • 출력 크기: 10 (nn.Linear의 출력 차원)
따라서 출력 형태는 torch.Size([1, 10])가 됩니다.

왜 필요한가?

  • Fully Connected Layer (FC Layer):
    • FC Layer는 입력 텐서의 모든 요소를 다음 레이어의 모든 뉴런에 연결합니다.
    • 이는 주로 신경망의 마지막 단계에서 클래스 점수나 회귀 값을 계산하는 데 사용됩니다.
    • 이 경우, 3136개의 입력 값을 10개의 출력 값으로 변환하여 10개의 클래스에 대한 점수를 계산합니다.

정리

이 코드는 3136차원의 입력 텐서를 10차원의 출력 텐서로 변환하는 Fully Connected 레이어를 정의하고 적용하여 출력 텐서의 형태를 확인합니다. 여기서 출력 형태 torch.Size([1, 10])는 배치 크기 1에 대해 10개의 클래스 점수를 나타냅니다.
 

 

 

2.  CNN으로 MNIST 분류하기

 

 

  • import

       
          import torch
          import torchvision.datasets as datasets
          import torchvision.transforms as transforms
          import matplotlib.pyplot as plt
          from torch.utils.data import DataLoader


 

 

  • GPU가 사용 가능하면 device 변수를 'cuda'로 설정

       
        device = 'cuda' if torch.cuda.is_available() else 'cpu'
        print(device)


cpu ---> cuda

 

 




  • PyTorch에서 MNIST 데이터셋을 로드하는 과정

       
          train_data = datasets.MNIST(
              root ='data',
              train = True,
              transform=transforms.ToTensor(),
              download=True
          )
          test_data = datasets.MNIST(
              root ='data',
              train = False,
              transform=transforms.ToTensor(),
              download=True
          )

 
  1. train_data 정의
    • datasets.MNIST: PyTorch에서 제공하는 MNIST 데이터셋을 로드하는 함수입니다.
    • root='data': 데이터셋이 저장될 경로를 지정합니다. 여기서는 'data' 폴더에 저장됩니다.
    • train=True: 학습 데이터셋을 로드하도록 지정합니다.
    • transform=transforms.ToTensor(): 데이터를 Tensor 형태로 변환하는 전처리 함수를 지정합니다.
      MNIST 데이터셋은 PIL 이미지 형태로 제공되므로, 이를 Tensor로 변환합니다.
    • download=True: 데이터셋이 로컬에 없을 경우 인터넷에서 다운로드합니다.
  2. test_data 정의
    • train=False: 테스트 데이터셋을 로드하도록 지정합니다.
    • 나머지 인자들은 train_data와 동일하게 설정됩니다.

데이터셋 설명

  • MNIST 데이터셋: 손으로 쓴 숫자(0부터 9까지)의 흑백 이미지로 구성된 데이터셋입니다.
  • train_data: 학습에 사용할 MNIST 데이터셋을 로드합니다. 총 60,000장의 학습 이미지와 각 이미지에 대한 레이블이 포함됩니다.
  • test_data: 모델 평가에 사용할 MNIST 데이터셋을 로드합니다. 총 10,000장의 테스트 이미지와 각 이미지에 대한 레이블이 포함됩니다.

사용된 전처리

  • transforms.ToTensor(): PIL 이미지를 PyTorch Tensor로 변환합니다. 이미지의 픽셀 값을 [0, 1] 범위로 정규화하고 Tensor 형태로 반환합니다.
이렇게 정의된 train_data와 test_data는 DataLoader를 통해 신경망 학습 및 평가에 사용될 수 있습니다.
 
Downloading http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz
Failed to download (trying next):
HTTP Error 403: Forbidden

Downloading https://ossci-datasets.s3.amazonaws.com/mnist/train-images-idx3-ubyte.gz
Downloading https://ossci-datasets.s3.amazonaws.com/mnist/train-images-idx3-ubyte.gz to data/MNIST/raw/train-images-idx3-ubyte.gz
100%|██████████| 9912422/9912422 [00:00<00:00, 13769231.05it/s]
Extracting data/MNIST/raw/train-images-idx3-ubyte.gz to data/MNIST/raw

......

Downloading http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz
Failed to download (trying next):
HTTP Error 403: Forbidden

Downloading https://ossci-datasets.s3.amazonaws.com/mnist/t10k-labels-idx1-ubyte.gz
Downloading https://ossci-datasets.s3.amazonaws.com/mnist/t10k-labels-idx1-ubyte.gz to data/MNIST/raw/t10k-labels-idx1-ubyte.gz
100%|██████████| 4542/4542 [00:00<00:00, 6820812.31it/s]Extracting data/MNIST/raw/t10k-labels-idx1-ubyte.gz to data/MNIST/raw

 

 

  • 각각 학습 데이터셋과 테스트 데이터셋에 대한 정보를 출력

       
        print(train_data)
        print(test_data)

 
Dataset MNIST
    Number of datapoints: 60000
    Root location: data
    Split: Train
    StandardTransform
Transform: ToTensor()
Dataset MNIST
    Number of datapoints: 10000
    Root location: data
    Split: Test
    StandardTransform
Transform: ToTensor()

 

 

 

  • MNIST 학습 데이터셋 DataLoader를 사용하여 미니배치로 나눈 후
    이미지를 시각화하는 과정

       
            # DataLoader를 사용하여 MNIST 학습 데이터셋을 미니배치로 나누기
            loader = DataLoader(
                dataset=train_data,   # 학습 데이터셋을 DataLoader에 전달
                batch_size=64,        # 미니배치 크기를 64로 설정
                shuffle=True          # 데이터를 섞어서 가져올지 여부 (True로 설정하여 데이터를 섞음)
            )

            # 첫 번째 미니배치 가져오기
            imgs, labels = next(iter(loader))

            # 시각화를 위한 서브플롯 설정
            fig, axes = plt.subplots(8, 8, figsize=(16, 16))

            # 각 서브플롯에 이미지와 레이블 표시
            for ax, img, label in zip(axes.flatten(), imgs, labels):
                ax.imshow(img.reshape((28, 28)), cmap='gray')  # 이미지를 28x28 크기로 변형하여 흑백으로 표시
                ax.set_title(label.item())  # 레이블을 제목으로 설정
                ax.axis('off')  # 축 숨기기 (눈금을 표시하지 않음)



 

 

  • PyTorch를 사용하여 간단한 컨볼루션 신경망(Convolutional Neural Network, CNN) 모델을 정의

       
            from torch.nn.modules.pooling import MaxPool2d

            model = nn.Sequential(
                nn.Conv2d(1, 32, kernel_size=3, padding='same'),
                nn.ReLU(),
                nn.MaxPool2d(kernel_size=2),

                nn.Conv2d(32, 64, kernel_size=3, padding='same'),
                nn.ReLU(),
                nn.MaxPool2d(kernel_size=2),
               
                nn.Flatten(),
                nn.Linear(7*7*64, 10)
            ).to(device)

            print(model)

 
  1. 모델 정의:
    • nn.Sequential: 순차적으로 모듈을 쌓아서 신경망 모델을 만듭니다.
    • nn.Conv2d(in_channels, out_channels, kernel_size, padding): 2D 컨볼루션 레이어를 정의합니다. 여기서는 입력 채널이 1, 출력 채널이 32인 3x3 커널을 사용하고, 'same' 패딩을 적용합니다. 이후에는 출력 채널이 32인 입력 채널이 필요합니다.
    • nn.ReLU(): ReLU(Rectified Linear Unit) 활성화 함수를 적용합니다.
    • nn.MaxPool2d(kernel_size): 최대 풀링 레이어를 정의합니다. 이 경우 2x2 크기의 풀링을 사용합니다.
    • nn.Flatten(): 2D 이미지를 1D 벡터로 변환합니다. 이는 컨볼루션 레이어와 풀링 레이어 뒤에 fully connected 레이어를 사용할 때 필요합니다.
    • nn.Linear(in_features, out_features): fully connected 레이어를 정의합니다. 여기서는 7x7 크기의 이미지가 64개 있으므로 입력 차원은 7764이고, 출력 차원은 10입니다 (MNIST 데이터셋의 클래스 수).
  2. 장치 설정:
    • .to(device): 모델을 GPU나 CPU로 옮기기 위해 사용합니다. device는 미리 설정된 장치 (예: cuda 또는 cpu)입니다.
  3. 모델 출력:
    • print(model): 정의된 모델의 구조를 출력합니다.

모델 설명

이 모델은 두 개의 컨볼루션 레이어와 최대 풀링 레이어를 거친 후에 fully connected 레이어로 이어집니다. 각 컨볼루션 레이어 다음에는 ReLU 활성화 함수가 적용됩니다. 마지막으로, 2D 이미지를 1D 벡터로 평탄화한 후 fully connected 레이어에 입력됩니다. 이 모델은 MNIST 손글씨 숫자 분류를 위해 설계되었으며, 이미지를 입력으로 받아 각 클래스(0에서 9까지의 숫자)에 대한 확률을 출력합니다.
 
 
Sequential(
  (0): Conv2d(1, 32, kernel_size=(3, 3), stride=(1, 1), padding=same)
  (1): ReLU()
  (2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  (3): Conv2d(32, 64, kernel_size=(3, 3), stride=(1, 1), padding=same)
  (4): ReLU()
  (5): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  (6): Flatten(start_dim=1, end_dim=-1)
  (7): Linear(in_features=3136, out_features=10, bias=True)
)
-----------------------------------------------------------------------
GPU로 다시 실행

 

 

  • PyTorch를 사용하여 CNN 모델을 MNIST 데이터셋으로 학습하는 과정

       
       
          # 학습
          optimizer = optim.Adam(model.parameters(), lr=0.001)

          epochs = 10

          for epoch in range(epochs):
              sum_losses = 0
              sum_accs = 0

              for x_batch, y_batch in loader:
                  x_batch = x_batch.to(device)
                  y_batch = y_batch.to(device)
                  y_pred = model(x_batch)
                  loss = nn.CrossEntropyLoss()(y_pred, y_batch)
                  optimizer.zero_grad()
                  loss.backward()
                  optimizer.step()
                  sum_losses = sum_losses + loss
                  y_prob = nn.Softmax(1)(y_pred)
                  y_pred_index = torch.argmax(y_prob, axis=1)
                  acc = (y_batch == y_pred_index).float().sum() / len(y_batch) * 100
                  sum_accs = sum_accs + acc
                 
              avg_loss = sum_losses / len(loader)
              avg_acc = sum_accs / len(loader)
              print(f'Epoch {epoch:4d}/{epochs} Loss: {avg_loss:.6f} Accuracy: {avg_acc:.2f}%')



  1. 옵티마이저 설정:
    • optim.Adam: Adam 최적화 알고리즘을 사용하여 모델의 파라미터를 업데이트합니다. model.parameters()로 모델의 학습 가능한 모든 파라미터를 전달하고, lr=0.001로 학습률(learning rate)을 설정합니다.
  2. 학습 루프 설정:
    • epochs: 전체 데이터셋을 몇 번 반복해서 학습할지 결정하는 변수입니다.
    • for epoch in range(epochs):: 주어진 epoch 수만큼 반복합니다.
    • for x_batch, y_batch in loader:: loader를 사용하여 데이터셋을 미니배치로 나누어 학습합니다.
    • x_batch.to(device), y_batch.to(device): 데이터를 GPU 또는 CPU로 옮깁니다 (device는 미리 설정된 장치입니다).
    • y_pred = model(x_batch): 모델을 사용하여 입력 데이터를 예측합니다.
    • loss = nn.CrossEntropyLoss()(y_pred, y_batch): 크로스 엔트로피 손실 함수를 사용하여 예측값과 실제값 사이의 손실을 계산합니다.
    • optimizer.zero_grad(), loss.backward(), optimizer.step(): 옵티마이저를 사용하여 역전파를 수행하고 모델 파라미터를 업데이트합니다.
    • sum_losses와 sum_accs: 각 배치의 손실과 정확도를 누적합니다.
    • avg_loss와 avg_acc: 전체 epoch에 대한 평균 손실과 정확도를 계산하고 출력합니다.
  3. 출력:
    • 각 epoch마다 손실과 정확도를 출력하여 학습 진행 상황을 모니터링합니다.

요약

이 코드는 MNIST 데이터셋을 사용하여 정의한 CNN 모델을 학습하는 과정을 보여줍니다.
Adam 옵티마이저를 사용하여 역전파와 파라미터 업데이트를 수행하며,
각 epoch 마다 손실과 정확도를 출력하여 모델의 학습 진행 상황을 확인합니다.
Epoch    0/10 Loss: 0.009623 Accuracy: 99.66%
Epoch    1/10 Loss: 0.006494 Accuracy: 99.80%
Epoch    2/10 Loss: 0.006753 Accuracy: 99.80%
Epoch    3/10 Loss: 0.005891 Accuracy: 99.80%
Epoch    4/10 Loss: 0.004189 Accuracy: 99.87%
Epoch    5/10 Loss: 0.003984 Accuracy: 99.87%
Epoch    6/10 Loss: 0.003420 Accuracy: 99.88%
Epoch    7/10 Loss: 0.003456 Accuracy: 99.89%
Epoch    8/10 Loss: 0.003008 Accuracy: 99.88%
Epoch    9/10 Loss: 0.004352 Accuracy: 99.85%

 

 

  • 테스트 데이터셋(test_data)을 사용하여 DataLoader를 생성하고, 첫 번째 미니배치 데이터를 시각화하는 과정

       
          test_loader= DataLoader(
              dataset=test_data,
              batch_size=64,
              shuffle=True
          )
          imgs, labels = next(iter(loader))
          fig, axes = plt.subplots(8, 8, figsize=(16, 16))
          for ax, img, label in zip(axes.flatten(), imgs, labels):
              ax.imshow(img.reshape((28, 28)), cmap='gray')
              ax.set_title(label.item())
              ax.axis('off')

 
  1. 데이터 로딩 설정:
    • DataLoader: PyTorch의 데이터 로딩 유틸리티로, 데이터셋을 미니배치로 나누어 준비합니다.
    • dataset=test_data: 로딩할 데이터셋으로서, 여기서는 테스트 데이터셋(test_data)을 사용합니다.
    • batch_size=64: 한 번에 로딩할 미니배치의 크기를 설정합니다. 여기서는 64로 설정했으므로, 각 미니배치에는 64개의 이미지가 포함됩니다.
    • shuffle=True: 데이터셋을 섞어서 무작위로 로딩할지 여부를 설정합니다. 테스트 시에는 섞는 것이 일반적으로 권장되지 않지만, 여기서는 섞었습니다.
  2. 미니배치 데이터 시각화:
    • next(iter(test_loader)): test_loader에서 첫 번째 미니배치를 가져옵니다. iter() 함수로 반복자(iterator)를 만들고, next() 함수로 첫 번째 요소를 가져옵니다.
    • imgs: 미니배치의 이미지 데이터입니다.
    • labels: 미니배치의 레이블 데이터입니다.
    • fig, axes = plt.subplots(8, 8, figsize=(16, 16)): 8x8 격자 형태의 서브플롯을 생성합니다. 각 서브플롯은 28x28 크기의 이미지를 표시할 준비가 되어 있습니다.
    • for ax, img, label in zip(axes.flatten(), imgs, labels):: 모든 서브플롯을 반복하면서 각각의 이미지와 레이블을 설정합니다.
      • ax.imshow(img.reshape((28, 28)), cmap='gray'): 각 서브플롯(ax)에 이미지를 28x28 크기로 흑백 이미지로 표시합니다.
      • ax.set_title(label.item()): 서브플롯의 제목(title)을 해당 이미지의 레이블 값으로 설정합니다.
      • ax.axis('off'): 서브플롯의 축(axis)을 표시하지 않습니다.

요약

이 코드는 테스트 데이터셋에서 데이터를 로드하고, 첫 번째 미니배치의 이미지를 8x8 격자로 시각화하여 표시합니다. 각 이미지는 흑백으로, 해당 이미지의 레이블 값이 제목으로 설정됩니다. 이를 통해 데이터셋이 제대로 로드되었는지와 이미지가 정확히 시각화되었는지를 확인할 수 있습니다.


 

 

  • 테스트 데이터셋을 사용하여 학습된 모델의 정확도를 평가하기

       
          from torchvision.transforms.functional import accimage

          model.eval() # 모델을 테스트 모드로 전환

          sum_accs=0

          for x_batch, y_batch in test_loader:
              x_batch = x_batch.to(device)
              y_batch = y_batch.to(device)
              y_pred = model(x_batch)

              y_prob = nn.Softmax(1)(y_pred)
              y_pred_index = torch.argmax(y_prob, axis=1)
              acc = (y_batch == y_pred_index).float().sum() / len(y_batch) * 100

              sum_accs = sum_accs + acc

          avg_acc = sum_accs / len(test_loader)

          print(f'테스트 정확도는 {avg_acc:.2f}%입니다!')

 
  1. 모델 평가 준비:
    • model.eval(): 모델을 평가(test) 모드로 설정합니다.
      이는 주로 드롭아웃(dropout)과 배치 정규화(batch normalization)와 같은 층들이
      테스트 중에 동작하는 방식을 변경하기 위해 사용
  2. 평가 반복문:
    • sum_accs = 0: 정확도의 합계를 초기화합니다.
    • for x_batch, y_batch in test_loader:  test_loader에서 미니배치를 반복합니다.
      • x_batch = x_batch.to(device), y_batch = y_batch.to(device):
        GPU로 데이터를 전송합니다 (잠재적으로, 만약 GPU가 사용 가능하고 device가 GPU를 가리킨다면).
      • y_pred = model(x_batch): 모델을 사용하여 입력 데이터 x_batch에 대한 예측을 수행합니다.
      • y_prob = nn.Softmax(1)(y_pred): 소프트맥스 함수를 사용하여 예측 확률을 계산합니다.
      • y_pred_index = torch.argmax(y_prob, axis=1): 가장 높은 확률을 가진 클래스의 인덱스를 가져옵니다.
      • acc = (y_batch == y_pred_index).float().sum() / len(y_batch) * 100: 미니배치 내에서 정확도를 계산합니다.
      • sum_accs = sum_accs + acc.item(): 정확도의 합계를 업데이트합니다.
  3. 평균 정확도 계산 및 출력:
    • avg_acc = sum_accs / len(test_loader): 모든 미니배치에 대한 평균 정확도를 계산합니다.
    • print(f'테스트 정확도는 {avg_acc:.2f}%입니다!'): 평균 정확도를 출력합니다.

요약

이 코드는 테스트 데이터셋을 사용하여 학습된 모델의 정확도를 평가합니다. 각 미니배치를 모델에 전달하고 예측을 수행한 후, 정확도를 계산하여 전체 테스트 데이터셋에 대한 평균 정확도를 출력합니다. 이를 통해 모델이 얼마나 잘 동작하는지를 확인할 수 있습니다.
테스트 정확도는 98.84%입니다!

 

 



3. 과제

○, X,△를 그림판에 여러가지 이미지를 저장 후 CNN으로 학습을 시켜 해당 데이터를 분류하는 모델을 만들어보자

 

'AI > 딥러닝' 카테고리의 다른 글

10. 포켓몬 분류  (0) 2024.06.21
09. 전이학습  (0) 2024.06.21
07. CNN 기초  (0) 2024.06.20
06. 비선형 활성화 함수  (0) 2024.06.20
05. 딥러닝  (0) 2024.06.20