[50일차]이미지 분류 실습

김준석·2024년 2월 2일

이미지 분류 실습

문제 설정

학습된 이미지 분류 모델을 활용해 이미지 분류 실습을 진행

이미지 분류란,
이미지의 대부분을 차지하는 객체의 종류를 예측하는 문제를 의미함

  • 입력으로 하나의 이미지를 제공하고
  • 해당 이미지의 종류(클래스)를 예측
  • 일반적으로 선택 가능한 모든 클래스에 대한 정답 점수값을 예측
    따라서 최종 결과는 그 점수 중 가장 큰 값을 선택하면서 얻을 수 있음
    또한, 이 점수들을 활용해 확률 값을 취할 수 있음

모델 설명

ResNet 이라는 모델을 사용할 예정.

  • 해당 모델은 연구적으로도 많이 사용되며
    • 현업에서도 기본 모델로 많아 사용하는 유명한 모델
  • 2015년에 제안된 딥러닝 모델로
    • 당시 사람의 이미지 인식 능력을 넘어선 최초의 이미지 인식 모델
  • 모델의 깊이인 Layer에 따라 18, 34, 50, 101, 152 이라는 5가지 종류가 존재
    • 깊이가 얕을수록 성능이 낮지만 빠르게 결과를 얻을 수 있음
    • 깊이가 깊을수록 성능이 높아지지만 결과를 도출하기 위한 시간이 오래 걸림

딥러닝 모델을 학습하는 시간은 이전 머신러닝 모델 대비 상당히 오래 걸림
• 따라서 Pytorch 내부에서 이미 학습 된 모델을 가져다가 활용!


실습 시작!

1. 데이터 가져오기

시작 전 GPU 연결하기

딥러닝은 리소스를 많이 사용하기 때문에 GPU로 연결해준다.

웹 상의 데이터 불러오기

  • 인터넷으로부터 이미지 url을 통해 이미지를 가져옴
    • 단, webp 포멧의 데이터는 request 요청 거부 에러가 뜰 가능성이 있음
    • 웹 상 이미지 링크 복사 후 url 변수에 할당!
url = 'https://img.freepik.com/premium-photo/cute-puppy-of-maltipoo-dog-posing-running-isolated-over-white-studio-background-playful-animal_756748-85193.jpg'
url = 'https://cdn.newsquest.co.kr/news/photo/202305/206197_97856_1244.jpg'
import requests
from PIL import Image
import matplotlib.pyplot as plt

# 이미지를 웹에서 불러오는 함수
def load_image_from_web(url):
    response = requests.get(url, stream=True).raw
    img = Image.open(response).convert('RGB')
    if img is None :
        raise ValueError('url로부터 데이터를 가져오지 못했습니다. 다른 url을 사용해보세요!')
    return img

# 이미지 시각화 코드
def imshow(img):
    plt.imshow(img)
    plt.axis('off')
image = load_image_from_web(url)
imshow(image)

이미지가 나오는 모습!

2. 이미지 전처리

• 머신러닝 모델은 학습 과정과 똑같은 전처리를 진행한 뒤 추론을 진행해야 함
• ResNet 모델도 마찬가지

• ResNet 모델이 학습할 당시의 전처리 과정이 저장된 class가 존재
• ResNet 모델의 학습 결과물이 저장된 객체

• 만약 resnet18 모델을 사용한다면
• ResNet18_Weights 라는 이름의 클래스에 담겨있음

• 따라서 전처리 코드를 가져와 사용할 이미지에 적용해야 함

코드는 아래와 같이 사용한다.

weight_name = : 클래스를 사용할 때 ‘ResNet18_Weights’ 이런식으로 작성해 줘야 되기 때문에 숫자에 해당하는 부분을 찾아주는 코드 작성

타깃 이미지 분류 모델과 전처리 과정 불러오기

• 옵션 : resnet18, resnet34, resnet50, resnet101, resnet152

import re
import torchvision.models as models

# 모델 선택 및 로드
def get_model_and_trans(model_name):
    if model_name not in ['resnet18', 'resnet34', 'resnet50', 'resnet101', 'resnet152']:
        raise ValueError("model name을 확인해주세요.  옵션 : 'resnet18', 'resnet34', 'resnet50', 'resnet101', 'resnet152'")

    weight_name = 'ResNet' + re.findall(r'\d+', model_name)[0] +'_Weights'
    weights = getattr(models, weight_name).DEFAULT

    transforms = weights.transforms()

    model = getattr(models, model_name)(weights=weights)
    model.eval()

    meta_data = weights.meta
    return model, transforms, meta_data
# 타깃 모델을 선택하고
model_name='resnet18'
# 모델과 그에 맞는 전처리 과정을 불러온다(파일토치에서 가져옴.)
myModel, transform, meta_data = get_model_and_trans(model_name)

가져온 데이터를 출력해보면 아래와 같이나온다.

myModel

transform에서는 사이즈 등이 변환된 모습을 볼 수 있다.

transform

낙타 이미지에 적용 해보자

import torch

# 이미지 전처리 진행
trans_image = transform(image)
trans_image = torch.unsqueeze(trans_image, 0)
def imshow_from_tensor(tensor):
    image = tensor.cpu().clone()  # 텐서 복제
    image = image.squeeze(0)      # 배치 차원 제거
    image = image.permute(1, 2, 0)  # 차원 재배열
    image = image.numpy()

    plt.imshow(image)
    plt.axis('off')
    plt.show()
# 전처리가 진행되면 원본 이미지의 형태가 많이 훼손됨
# 하지만 딥러닝 모델은 이런 형태를 더욱 잘 알아본다고!
imshow_from_tensor(trans_image)

그럼 이런식으로 이미지가 짤리고 색감도 바뀜.

색감이 변한 이유는
RGB 색깔의 분포가 컴퓨터가 더 잘 볼 수 있는 형태로 바뀌기 때문.

이제 모델에 이미지를 넣어주고 결과를 분석하자.

# 모델에 입력하고 결과를 출력
output = myModel(trans_image)
# 1000개의 결과값을 출력
# 이들 중 최고 값을 갖는 값이 출력의 결과값!
print(output)

각 클래스들의 점수가 나온다.

이제 각 부분의 MAX점수 부분을 확률 형태로 추출하면 확률이 가장 큰 부분이 나옴.

import torch.nn.functional as F

# 출력 결과로부터 출력 결과 도출하기
conf, predicted = F.softmax(output, dim=1).max(1)#F.softmax:점수를 확률의 형태로 변경.
total_class = meta_data["categories"]
cls = total_class[predicted.item()]

print(f'최종 결과 입력 이미지는 {conf.item()*100:.2f} % 의 확률로 {cls} 이라고 예측됩니다.')

출력결과:

최종 결과 입력 이미지는 99.99 % 의 확률로 Arabian camel 이라고 예측됩니다.

0개의 댓글