본문 바로가기

Data_Analysis_Track_33/Python

Python_Deeplearning_pytorch_09(VGGNet Pretrained 모델을 이용해 이미지 분류)

Pretrained Model

  • 다른 목적을 위해 미리 학습된 모델.
  • Pretrained model을 현재 해결하려는 문제에 이용한다.
  • 대부분 내가 만들려는 네트워크 모델에 pretrained model을 포함시켜 사용한다.
        - 이런 방식을 Transfer Learning (전이 학습)이라고 한다.
        - 보통 Feature Extractor block을 재사용한다.

 

Pytorch에서 제공하는 Pretrained Model 

  • 분야별 라이브러리에서 제공
        - torchvision: https://pytorch.org/vision/stable/models.html
  • torch hub 를 이용해 모델과 학습된 parameter를 사용할 수 있다.
        - https://pytorch.org/hub/
  • 이외에도 많은 모델과 학습된 paramter가 인터넷상에 공개되 있다.    
        - 딥러닝 모델기반 application을 개발 할 때는 대부분 Transfer Learning을 한다.  
        - 다양한 분야에서 연구된 많은 딥러닝 모델들이 구현되어 공개 되어 있으며 학습된 Parameter들도 제공되고             있다.  
        - paperswithcode(https://paperswithcode.com/)에서 State Of The Art(SOTA) 논문들과 그 구현된 모델을 확인           할 수 있다. 
        
    >  State Of The Art(SOTA): 특정 시점에 특정 분야에서 가장 성능이 좋은 모델을 말한다.

 

VGGNet Pretrained 모델을 이용해 이미지 분류

  • Pytorch가 제공하는 VGG 모델은 ImageNet dataset으로 학습시킨 weight를 제공한다.
        - 120만장의 transet, 1000개의 class로 구성된 데이터셋.
        - Output으로 1000개의 카테고리에 대한 확률을 출력한다. 

 

wget

# ImageNet 1000개의 class 목록
!pip install wget
import wget
url = 'https://gist.github.com/yrevar/942d3a0ac09ec9e5eb3a/raw/238f720ff059c1f82f368259d1ca4ffa5dd8f9f5/imagenet1000_clsidx_to_labels.txt'
imagenet_filepath = wget.download(url) # 다운로드 받고 받은 경로를 반환.

 

eval

# eval("파이썬코드") # 파이썬 코드를 문자열로 넣으면 알아서 해석해서 실행
r = eval("1 + 3")
print(type(r))
r

r1 = eval("[1, 2, 3]")
print(r1, type(r1))

r2 = eval("{0: '사람', 1:'물통'}")
print(r2, type(r2))

with open(imagenet_filepath, "rt") as fr:
    index_to_class = eval(fr.read())

print(type(index_to_class))

 

예측할 이미지 다운로드

- 이미지의 주소를 복사하여 img_url로 선언

# 추론할 이미지 다운로드
import requests
from io import BytesIO
from PIL import Image

img_url = 'https://upload.wikimedia.org/wikipedia/commons/thumb/2/25/Common_goldfish.JPG/800px-Common_goldfish.JPG'
# img_url = 'https://cdn.download.ams.birds.cornell.edu/api/v1/asset/169231441/1800'
# img_url = 'https://blogs.ifas.ufl.edu/news/files/2021/10/anole-FB.jpg'

res = requests.get(img_url) # url로 요청 -> 응답 받기.
test_img = Image.open(BytesIO(res.content)) # 응답받은 것이 binary 파일일 경우. BytesIO(binary) => bytes타입 입출력이 가능한 객체.
test_img

 

import

# import

import torch
from torchvision import models, transforms
from torchinfo import summary

device = "cuda" if torch.cuda.is_available() else "cpu"
device

 

  • torchvision에서 제공하는 Pretrained 모델을 다운로드
  • VGG19 모델.
     - weights: 학습된 파라미터들을 같이 다운로드 받는다. => Image Net 데이터셋으로 학습한 파라미터를 받는다.
    - IMAGENET1K_V1 : Image net 버전 1로 학습된 파라미터
    - IMAGENET1K_V2 : 버전 2로 학습된 파라미터
  • 모델에 따라서 V2는 없을 수도 있다.
  • models.VGG19_Weights.DEFAULT - 둘 중에 기본 데이터셋으로 설정된 것을 받는다.

 

vgg19, alexnet 모델

load_model_vgg = models.vgg19(weights=models.VGG19_Weights.IMAGENET1K_V1)

load_model_alex = models.alexnet(weights=models.AlexNet_Weights.DEFAULT)

 

summary

summary(load_model_vgg, (100, 3, 224, 224))

summary(load_model_alex, (1, 3, 224, 224))

 

alex모델로 추론

- device 설정

model = load_model_alex.to(device)
i = torch.randn(1, 3, 224, 224).to(device)
p = model(i)
p.shape

 

index_to_class로 이미지에 대한 추론 결과 확인

label = p[0].argmax(dim=-1).item()
index_to_class[label]

 

Softmax

torch.nn.Softmax(dim=-1)(p[0]).max(dim=-1).values

 

새로운 이미지 추가

# img_url = 'https://upload.wikimedia.org/wikipedia/commons/thumb/2/25/Common_goldfish.JPG/800px-Common_goldfish.JPG'
# img_url = 'https://cdn.download.ams.birds.cornell.edu/api/v1/asset/169231441/1800'
# img_url = 'https://blogs.ifas.ufl.edu/news/files/2021/10/anole-FB.jpg'
img_url = 'https://i.namu.wiki/i/ULEPOWPdbcmUlLgfR3if48VFAcqiwdya-LVBipi6HAYUZDVa0YeVbqpCnCsLoHSdQmpEYwBEAL1yQQxPXgBu_w.webp'

res = requests.get(img_url) # url로 요청 -> 응답 받기.
test_img = Image.open(BytesIO(res.content)) # 응답받은 것이 binary 파일일 경우. BytesIO(binary) => bytes타입 입출력이 가능한 객체.
test_img

 

이미지에 대한 전처리

- ToTensor() -> Tensor 타입으로 변환

# 전처리
test_transform = transforms.Compose([
    transforms.Resize((224, 224), antialias=True),
    transforms.ToTensor() # PIL.Image -> torch.Tensor, 0 ~ 1 scaling, channel first 처리
])

 

test_img를 test_transform에 적용 -> input_data

input_data = test_transform(test_img)
print(type(input_data), input_data.shape, input_data.min(), input_data.max())

 

unsqueeze

# batch 축을 추가.
input_data = input_data.unsqueeze(dim=0)
input_data.shape

 

추론

# 모델을 device로 이동
model = load_model_vgg.to(device)

# 추론
pred1 = model(input_data.to(device))

 

추론결과를 가지고 확률로 변환 등 조회

# 추론결과를 확률로 변환
pred_prob1 = torch.nn.Softmax(dim=-1)(pred1)
# 추론 label, 확률값을 조회
label1 = pred_prob1.max(dim=-1).indices
prob1 = pred_prob1.max(dim=-1).values
# 추론 label을 이용해서 label name을 조회
labelname1 = index_to_class[label1.item()]

 

추론 결과값 확인

print(label1.item(), labelname1)
print("확률:", prob1.item())