Pytorch #4

갱갱·2025년 3월 3일

ZB_TensorFlow & pyTorch

목록 보기
7/7
post-thumbnail

2025.03.03

Chapter 6. Transfer Learning

  • 41. 식물잎의 사진으로 질병분류 - 파일정리
  • 42. 식물잎의 사진으로 질병분류 - 학습하기




식물잎 사진으로 질병분류

데이터 불러오기

주 의
병든 작물잎 사진을 이용한 분류문제
kaggle에서 좋은 평가를 받은 코드로 해설. 좀 어려울 수 있지만.. 세미나 느낌으로 접근..



데이터는 kaggle에도 있고, 강사님이 공유해주신 google Drive에서도 받을 수 있었다.

  • 질병을 어떻게 판정해야 하는지 모르지만... 일단 질병의 이름별로 사진이 폴더별로 분류가 되어있다.


colab에서 압축푸는 것..



  • 폴더이름을 이용해서 class_list 생성



  • test, train, validation 데이터를 나눌 폴더 생성




데이터 정리 (목록, 폴더생성)

  • 폴더 추가생성하기




데이터 현황 확인

처음에 원본 데이터가 저장되어 있는 dataset 폴더 내 각각의 폴더에서, 사진데이터를 splitted 폴더로 복사해야 한다.
다만, 전체를 일괄복사가 아닌, train(60%), test(20%), val(20%) 정도로 나누어서 이동복사 한다.

import math

for cls in classes_list:
    path = os.path.join(origin_dataset_dir, cls)
    fnames = os.listdir(path)
    # 각 폴더안에 있는 파일의 목록이 저장된다.
    # Sick_plant 폴더안에 dataset 폴더안에 Apple_Applt_scab 폴더 안의
    # image(1).JPG... 파일들의 이름이 fnames에 저장된다.
    # 위 폴더는 fnames에는 첫 반복문에서 630개의 이름이 저장된다 (list 형태태)

    train_size = math.floor(len(fnames) * 0.6)
    test_size = math.floor(len(fnames) * 0.2)
    val_size = math.floor(len(fnames) * 0.2)
    # 630개 중에서 60%는 train data로, 나머지 각 20% 씩 test, val 데이터로 사용
    # size만 설정
    # math.floor = 주어진 숫자보다 작거나 같은 가장 큰 정수 반환


    '''train 데이터 복사사'''
    train_fnames = fnames[:train_size]
    print('Train size (',cls,') : ', len(train_fnames))
    for fname in train_fnames:
        scr = os.path.join(path, fname)
        # train으로 사용한 사진파일 경로
        
        dst = os.path.join(os.path.join(train_dir, cls), fname)
        # splitted 폴더에 train 폴더에 apple.. 폴더에 파일이름으로 경로생성

        shutil.copyfile(scr, dst)
        # scr 경로파일을 dst로 복사
        # src(원본 파일)에서 dst(대상 파일)로 파일 내용을 그대로 복사합니다.


    '''val 데이터 복사사'''
    val_fnames = fnames[train_size:(val_size + train_size)]
    # 60부터 80까지 해서 20개가 선택된다 (20%)
    print('val size (',cls,') : ', len(val_fnames))
    for fname in val_fnames:
        scr = os.path.join(path, fname)
        # train으로 사용한 사진파일 경로
        
        dst = os.path.join(os.path.join(val_dir, cls), fname)
        # splitted 폴더에 train 폴더에 apple.. 폴더에 파일이름으로 경로생성

        shutil.copyfile(scr, dst)
        # scr 경로파일을 dst로 복사
        # src(원본 파일)에서 dst(대상 파일)로 파일 내용을 그대로 복사합니다.

    '''test 데이터 복사사'''
    test_fnames = fnames[(val_size + train_size):(val_size + test_size + train_size)]

    print('test size (',cls,') : ', len(test_fnames))
    for fname in test_fnames:
        scr = os.path.join(path, fname)
        # train으로 사용한 사진파일 경로
        
        dst = os.path.join(os.path.join(test_dir, cls), fname)
        # splitted 폴더에 train 폴더에 apple.. 폴더에 파일이름으로 경로생성

        shutil.copyfile(scr, dst)
        # scr 경로파일을 dst로 복사
        # src(원본 파일)에서 dst(대상 파일)로 파일 내용을 그대로 복사합니다.

  • 위 코드를 실행하게 되면.. 결국 train, test, val 폴더에 사진파일이 지정된 크기(개수)만큼 저장되는 것을 알 수 있다.
  • 이번 프로젝트는 일단 60%, 20%, 20% 정도 비율로 나누어서 진행한다.



학습 준비

  • 관련 모듈, 라이브러리 import
  • GPU 사용 설정

  • batch-size가 클수록 속도가 개선된다. 다만, GPU 메모리 내에서 크게할 수 있다.


🔹 ImageFolder의 역할

  • 지정한 디렉터리(root) 내의 이미지 파일을 자동으로 로드합니다.
  • 폴더명을 클래스(label)로 인식하여 자동으로 라벨링을 해줍니다.
  • transform 인자를 통해 이미지 전처리(transformations)를 적용할 수 있습니다.


  • DataLoader -> batch 학습 적용하기 위한..
  • num_workers 는 GPU 또는 CPU 사용갯수 지정

  • 처음 지정한 batch_size와 같이 256개의 데이터가 있는것을 확인할 수 있다.



학습위한 class 생성

  • 너무 길어서 코드자체 복사.
  • class 정의
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim


class Net(nn.Module):

    def __init__(self):

        super(Net, self).__init__()

        self.conv1 = nn.Conv2d(3, 32, 3, padding=1)
        self.pool = nn.MaxPool2d(2,2)
        self.conv2 = nn.Conv2d(32, 64, 3, padding=1)
        self.conv2 = nn.Conv2d(64, 64, 3, padding=1)

        self.fc1 = nn.Linear(4096, 512)
        # 64 X 64 를 2X2 pooling -> 32, 16, 8
        # (8 X 8)  X 64 (출력채널널) = 4096
        self.fc2 = nn.Linear(512, 33)
        # 512는 그냥 잡은듯
        # 33는 폴더 숫자. 즉, class 숫자.
    
    def forward(self, x):

        x = self.conv1(x)
        x = F.relu(x)
        x = self.pool(x)
        x = F.dropout(x, p=0.25, training=self.training)
        # training = self.training 은 model.train() 때만 사용하겟다는 의미

        x = self.conv2(x)
        x = F.relu(x)
        x = self.pool(x)
        x = F.dropout(x, p=0.25, training=self.training)

        x = self.conv3(x)
        x = F.relu(x)
        x = self.pool(x)
        x = F.dropout(x, p=0.25, training=self.training)

        x = x.view(-1, 4096)
        x = self.fc1(x)
        x = F.relu(x)
        x = F.dropout(x, p=0.25, training=self.training)
        x = self.fc2(x)

        return F.log_softmax(x, dim=1)




  • train하는 것도 함수로 만들기



  • 전체과정 함수로 설정




학습

--------------------- epoch 30 ----------------------
train Loss : 0.0270, Accuracy : 99.32 %
val Loss : 0.2267, Accuracy : 93.08 %
Completed in 0m 43s

profile
(hellow. world)

0개의 댓글