본문 바로가기

딥러닝/개인구현 정리

[DeepLearning] MobileNet_V2를 사용한 이미지 추론

320x100
IRB기법이 사용됩니다

 

지난 시간에는 IRB의 개념과 IRB를 사용한 모델, Mobilenet_V2에 대해서 살펴보았습니다.

이번에는 개념만 알고 넘어가기에는 실용적인 부분이 부족한 감이 있어서, 이 Mobilenet_v2를 직접 구동해보고

몇가지 이미지를 입력해서 맞추는지 확인해 보고자 합니다.

 


먼저 필수 라이브러리를 불러왔습니다.

 

# 필수 라이브러리
import torch

# 이미지 파일 오픈하는 데 사용
from PIL import Image
from torchvision import transforms

import urllib

 

이미지 파일은 풍경, 생명체(객체), 생명체 풍경이 혼합된 객체, 도시 이미지 등을 사용했습니다.

 

url, filename = ('https://raw.githubusercontent.com/dla9944/2023_God_damn_deeplearning/master/MobileNet/dataset/axe-5151655_1920.jpg', 'axe.jpg')
try: urllib.URLopener().retrieve(url, filename)
except: urllib.request.urlretrieve(url, filename)

url, filename = ('https://raw.githubusercontent.com/dla9944/2023_God_damn_deeplearning/master/MobileNet/dataset/cat-2934720_1280.jpg', 'cat.jpg')
try: urllib.URLopener().retrieve(url, filename)
except: urllib.request.urlretrieve(url, filename)

url, filename = ('https://raw.githubusercontent.com/dla9944/2023_God_damn_deeplearning/master/MobileNet/dataset/dog-3277416_1280.jpg', 'dog2.jpg')
try: urllib.URLopener().retrieve(url, filename)
except: urllib.request.urlretrieve(url, filename)

url, filename = ('https://raw.githubusercontent.com/dla9944/2023_God_damn_deeplearning/master/MobileNet/dataset/japan.jpg', 'japan.jpg')
try: urllib.URLopener().retrieve(url, filename)
except: urllib.request.urlretrieve(url, filename)

url, filename = ('https://raw.githubusercontent.com/dla9944/2023_God_damn_deeplearning/master/MobileNet/dataset/las-vegas-3988__480.jpg', 'las_vegas.jpg')
try: urllib.URLopener().retrieve(url, filename)
except: urllib.request.urlretrieve(url, filename)

 

filename은 테스트를 진행함에 따라 순차적으로 바꿔주었습니다.

 

# 이미지는 개별적으로 구글 드라이브에 업로드하고
# filename에 자유롭게 이미지 첨부해도 무방
filename = '/content/japan.jpg'

 

모바일넷을 불러옵니다. 버전은 pytorch/vision:v0.10.0을 통해서 불러올 수 있습니다.

 

model = torch.hub.load('pytorch/vision:v0.10.0', 'mobilenet_v2', pretrained=True)

바로 모델의 형태에 대해서 살펴보겠습니다.

 

model.eval()
MobileNetV2(
  (features): Sequential(
    (0): Conv2dNormActivation(
      (0): Conv2d(3, 32, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
      (1): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (2): ReLU6(inplace=True)
    )
    (1): InvertedResidual(
      (conv): Sequential(
        (0): Conv2dNormActivation(
          (0): Conv2d(32, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=32, bias=False)
          (1): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (2): ReLU6(inplace=True)
        )
        (1): Conv2d(32, 16, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (2): BatchNorm2d(16, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
    )
    (2): InvertedResidual(
      (conv): Sequential(
        (0): Conv2dNormActivation(
          (0): Conv2d(16, 96, kernel_size=(1, 1), stride=(1, 1), bias=False)
          (1): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (2): ReLU6(inplace=True)
        )
        (1): Conv2dNormActivation(
          (0): Conv2d(96, 96, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), groups=96, bias=False)
          (1): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (2): ReLU6(inplace=True)
        )
        (2): Conv2d(96, 24, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (3): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
    )
    (3): InvertedResidual(
      (conv): Sequential(
        (0): Conv2dNormActivation(
          (0): Conv2d(24, 144, kernel_size=(1, 1), stride=(1, 1), bias=False)
          (1): BatchNorm2d(144, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (2): ReLU6(inplace=True)
        )
        (1): Conv2dNormActivation(
          (0): Conv2d(144, 144, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=144, bias=False)
          (1): BatchNorm2d(144, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (2): ReLU6(inplace=True)
        )
        (2): Conv2d(144, 24, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (3): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
    )
    (4): InvertedResidual(
      (conv): Sequential(
        (0): Conv2dNormActivation(
          (0): Conv2d(24, 144, kernel_size=(1, 1), stride=(1, 1), bias=False)
          (1): BatchNorm2d(144, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (2): ReLU6(inplace=True)
        )
        (1): Conv2dNormActivation(
          (0): Conv2d(144, 144, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), groups=144, bias=False)
          (1): BatchNorm2d(144, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (2): ReLU6(inplace=True)
        )
        (2): Conv2d(144, 32, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (3): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
    )
    (5): InvertedResidual(
      (conv): Sequential(
        (0): Conv2dNormActivation(
          (0): Conv2d(32, 192, kernel_size=(1, 1), stride=(1, 1), bias=False)
          (1): BatchNorm2d(192, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (2): ReLU6(inplace=True)
        )
        (1): Conv2dNormActivation(
          (0): Conv2d(192, 192, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=192, bias=False)
          (1): BatchNorm2d(192, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (2): ReLU6(inplace=True)
        )
        (2): Conv2d(192, 32, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (3): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
    )
    (6): InvertedResidual(
      (conv): Sequential(
        (0): Conv2dNormActivation(
          (0): Conv2d(32, 192, kernel_size=(1, 1), stride=(1, 1), bias=False)
          (1): BatchNorm2d(192, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (2): ReLU6(inplace=True)
        )
        (1): Conv2dNormActivation(
          (0): Conv2d(192, 192, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=192, bias=False)
          (1): BatchNorm2d(192, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (2): ReLU6(inplace=True)
        )
        (2): Conv2d(192, 32, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (3): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
    )
    (7): InvertedResidual(
      (conv): Sequential(
        (0): Conv2dNormActivation(
          (0): Conv2d(32, 192, kernel_size=(1, 1), stride=(1, 1), bias=False)
          (1): BatchNorm2d(192, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (2): ReLU6(inplace=True)
        )
        (1): Conv2dNormActivation(
          (0): Conv2d(192, 192, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), groups=192, bias=False)
          (1): BatchNorm2d(192, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (2): ReLU6(inplace=True)
        )
        (2): Conv2d(192, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (3): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
    )
    (8): InvertedResidual(
      (conv): Sequential(
        (0): Conv2dNormActivation(
          (0): Conv2d(64, 384, kernel_size=(1, 1), stride=(1, 1), bias=False)
          (1): BatchNorm2d(384, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (2): ReLU6(inplace=True)
        )
        (1): Conv2dNormActivation(
          (0): Conv2d(384, 384, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=384, bias=False)
          (1): BatchNorm2d(384, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (2): ReLU6(inplace=True)
        )
        (2): Conv2d(384, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (3): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
    )
    (9): InvertedResidual(
      (conv): Sequential(
        (0): Conv2dNormActivation(
          (0): Conv2d(64, 384, kernel_size=(1, 1), stride=(1, 1), bias=False)
          (1): BatchNorm2d(384, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (2): ReLU6(inplace=True)
        )
        (1): Conv2dNormActivation(
          (0): Conv2d(384, 384, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=384, bias=False)
          (1): BatchNorm2d(384, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (2): ReLU6(inplace=True)
        )
        (2): Conv2d(384, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (3): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
    )
    (10): InvertedResidual(
      (conv): Sequential(
        (0): Conv2dNormActivation(
          (0): Conv2d(64, 384, kernel_size=(1, 1), stride=(1, 1), bias=False)
          (1): BatchNorm2d(384, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (2): ReLU6(inplace=True)
        )
        (1): Conv2dNormActivation(
          (0): Conv2d(384, 384, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=384, bias=False)
          (1): BatchNorm2d(384, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (2): ReLU6(inplace=True)
        )
        (2): Conv2d(384, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (3): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
    )
    (11): InvertedResidual(
      (conv): Sequential(
        (0): Conv2dNormActivation(
          (0): Conv2d(64, 384, kernel_size=(1, 1), stride=(1, 1), bias=False)
          (1): BatchNorm2d(384, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (2): ReLU6(inplace=True)
        )
        (1): Conv2dNormActivation(
          (0): Conv2d(384, 384, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=384, bias=False)
          (1): BatchNorm2d(384, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (2): ReLU6(inplace=True)
        )
        (2): Conv2d(384, 96, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (3): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
    )
    (12): InvertedResidual(
      (conv): Sequential(
        (0): Conv2dNormActivation(
          (0): Conv2d(96, 576, kernel_size=(1, 1), stride=(1, 1), bias=False)
          (1): BatchNorm2d(576, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (2): ReLU6(inplace=True)
        )
        (1): Conv2dNormActivation(
          (0): Conv2d(576, 576, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=576, bias=False)
          (1): BatchNorm2d(576, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (2): ReLU6(inplace=True)
        )
        (2): Conv2d(576, 96, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (3): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
    )
    (13): InvertedResidual(
      (conv): Sequential(
        (0): Conv2dNormActivation(
          (0): Conv2d(96, 576, kernel_size=(1, 1), stride=(1, 1), bias=False)
          (1): BatchNorm2d(576, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (2): ReLU6(inplace=True)
        )
        (1): Conv2dNormActivation(
          (0): Conv2d(576, 576, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=576, bias=False)
          (1): BatchNorm2d(576, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (2): ReLU6(inplace=True)
        )
        (2): Conv2d(576, 96, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (3): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
    )
    (14): InvertedResidual(
      (conv): Sequential(
        (0): Conv2dNormActivation(
          (0): Conv2d(96, 576, kernel_size=(1, 1), stride=(1, 1), bias=False)
          (1): BatchNorm2d(576, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (2): ReLU6(inplace=True)
        )
        (1): Conv2dNormActivation(
          (0): Conv2d(576, 576, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), groups=576, bias=False)
          (1): BatchNorm2d(576, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (2): ReLU6(inplace=True)
        )
        (2): Conv2d(576, 160, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (3): BatchNorm2d(160, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
    )
    (15): InvertedResidual(
      (conv): Sequential(
        (0): Conv2dNormActivation(
          (0): Conv2d(160, 960, kernel_size=(1, 1), stride=(1, 1), bias=False)
          (1): BatchNorm2d(960, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (2): ReLU6(inplace=True)
        )
        (1): Conv2dNormActivation(
          (0): Conv2d(960, 960, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=960, bias=False)
          (1): BatchNorm2d(960, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (2): ReLU6(inplace=True)
        )
        (2): Conv2d(960, 160, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (3): BatchNorm2d(160, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
    )
    (16): InvertedResidual(
      (conv): Sequential(
        (0): Conv2dNormActivation(
          (0): Conv2d(160, 960, kernel_size=(1, 1), stride=(1, 1), bias=False)
          (1): BatchNorm2d(960, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (2): ReLU6(inplace=True)
        )
        (1): Conv2dNormActivation(
          (0): Conv2d(960, 960, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=960, bias=False)
          (1): BatchNorm2d(960, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (2): ReLU6(inplace=True)
        )
        (2): Conv2d(960, 160, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (3): BatchNorm2d(160, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
    )
    (17): InvertedResidual(
      (conv): Sequential(
        (0): Conv2dNormActivation(
          (0): Conv2d(160, 960, kernel_size=(1, 1), stride=(1, 1), bias=False)
          (1): BatchNorm2d(960, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (2): ReLU6(inplace=True)
        )
        (1): Conv2dNormActivation(
          (0): Conv2d(960, 960, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=960, bias=False)
          (1): BatchNorm2d(960, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (2): ReLU6(inplace=True)
        )
        (2): Conv2d(960, 320, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (3): BatchNorm2d(320, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
    )
    (18): Conv2dNormActivation(
      (0): Conv2d(320, 1280, kernel_size=(1, 1), stride=(1, 1), bias=False)
      (1): BatchNorm2d(1280, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (2): ReLU6(inplace=True)
    )
  )
  (classifier): Sequential(
    (0): Dropout(p=0.2, inplace=False)
    (1): Linear(in_features=1280, out_features=1000, bias=True)
  )
)

 

 

한 시퀀셜에 feature ▶ Conv2dNormActivation 블록 1개, InvertedResidual 블록 18개가 존재하는 식입니다.

이 19개의 블록을 지나가 Classifier(분류기)에 도착하고, Dropout까지 진행합니다.

 

Conv2dNormActivation : 일종의 블록입니다. 입력물을 Convolution2d-Normalization-Activation 블록으로 바꿔주는 역할을 해줍니다.

 

Inverted Residual : 바로 전시간에 언급했던 블록입니다. 채널 크기를 증가 → 학습 → 다시 채널 크기를 감소하는 방식으로 레이어가 흘러갑니다.

 

 

그리고 이미지 분류에 사용되는 imagenet_classes 텍스트파일을 불러옵니다.

 

이미지넷 클래스 파일은 ILSVRC 2012-2017 경진대회에 사용되었던 1000개 가량의 데이터 라벨을 

모아놓은 것입니다. 저명한 이미지 분류 모델에 자주 사용됩니다.

 

구글 클라우드 참조

https://cloud.google.com/tpu/docs/imagenet-setup?hl=ko 

 

ImageNet 데이터 세트 다운로드, 사전 처리, 업로드  |  Cloud TPU  |  Google Cloud

의견 보내기 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. ImageNet 데이터 세트 다운로드, 사전 처리, 업로드 이 항목에서는 Cloud TPU에서 사용할 ImageNet 데이

cloud.google.com

 

아래 show 함수를 통해 전처리와 모델 GPU사용, 가능도가 높은 이미지들을 불러올 수 있는 기능을 구현합니다.

 

def show (filename):
    input_image = Image.open(filename)
    preprocess = transforms.Compose([
        transforms.Resize(256),
        transforms.CenterCrop(224),
        transforms.ToTensor(),
        transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
    ])
    input_tensor = preprocess(input_image)
    input_batch = input_tensor.unsqueeze(0) # 모델에 의해 형상가능한 미니 배치 제작

    # 입력물과 모델을 GPU로 이동시킴
    
    if torch.cuda.is_available():
        input_batch = input_batch.to('cuda')
        model.to('cuda')

    with torch.no_grad():
        output = model(input_batch)

    # 1000 사이즈 텐서를 이미지넷'1000 클래스의 가장 높은 점수를 갖는 것으로 배출
    # 출력물은 정규화가 안되어 있습니다. 가능도를 가질려면 소프트맥스 함수를 사용
    probabilities = torch.nn.functional.softmax(output[0], dim=0)

    # "imagenet 클래스'의 범주를 사용
    with open("imagenet_classes.txt", "r") as f:
        categories = [s.strip() for s in f.readlines()]
    # 가장 정확도 높은 5개의 범주 출력
    top5_prob, top5_catid = torch.topk(probabilities, 5)
    toplist = []

    for i in range(top5_prob.size(0)):
        print(categories[top5_catid[i]], top5_prob[i].item())

 

probabilities는 output에 대한 정규화를 진행, 이미지넷 클래스 중 가장 높은 점수를 갖는 것을 가져옵니다.

함수는 소프트맥스 함수를 사용합니다.

 

open을 통해 이미지넷의 카테고리를 읽어오는 것입니다. 그리고 topk를 통해 상위 5개를 남깁니다.

- torch.topk는 input 에 주어지는 차원에 따라 가장 큰 원소들을 k 만큼 남깁니다.

torch.topk(input, k, dim=None, largest=True, sorted=True, *, out=None)

 

torch.topk — PyTorch 1.13 documentation

 

torch.topk — PyTorch 1.13 documentation

Shortcuts

pytorch.org

 

아래 코드로 필자의 구글 드라이브에 있는 일본 야경 이미지를 분석하여 가장 높은 확률을 지닌 카테고리를 불러오게 됩니다.

 

show('/content/japan.jpg')
carousel 0.42576882243156433
throne 0.08446047455072403
restaurant 0.06909944862127304
comic book 0.03633029758930206
cinema 0.03498294577002525

 

단어에 대해 설명하기 전에, 입력했던 이미지를 보여드리겠습니다.

 

Image.open(filename)

 

비에 젖은 운치있는 야경 풍경이 나옵니다.

 

일단 carousel과 throne이 가장 높게 나왔습니다.

헌데 carousel과 throne은 무엇일까요?

 

 

1) 회전목마입니다.

2) 왕관입니다.

 

아마 색상이 반짝인다는 점과 어두운 골목과 불빛이 동시에 존재한다는 점에서 회전목마의 특성을 살핀 것 같네요.

이번에는 이름처럼 라스베가스의 사례입니다.

 

show('/content/las_vegas.jpg')
carousel 0.1998308151960373
slot 0.17013509571552277
palace 0.10078047960996628
restaurant 0.09870009124279022
fountain 0.054885175079107285

 

동일하게 회전목마가 나왔네요.

 

las vegas 원본 사진입니다.

 

 

지난번에 GPUNet 강아지 품종 분류를 진행했을 때도 시도했었던, 헝가리 사냥견 viszla에 대한 이미지

 

show('/content/dog2.jpg')
vizsla 0.9574761986732483
Rhodesian ridgeback 0.030998392030596733
Weimaraner 0.00820436142385006
redbone 0.0017119958065450191
bloodhound 0.0007580203237012029

 

1순위로 비슬라가 도출됩니다.

이부분은 동일합니다.

 

 

이후부터는 Image로 함수를 제작하여 경로의 이미지를 뽑는 함수로 넣었습니다.

 

def imageshow(filename):
    return Image.open(filename)

 

도끼이미지 입니다. 영어로는 axe, hatchet 등이 존재합니다.

 

imageshow('/content/axe.jpg')

 

이미지 가능도를 확인해보겠습니다.

show('/content/axe.jpg')
hatchet 0.159746453166008
padlock 0.13026492297649384
chain saw 0.06623504310846329
matchstick 0.06519460678100586
hammer 0.0593089833855629

 

이미지 호출

imageshow('/content/cat.jpg')

show('/content/cat.jpg')
tabby 0.49559304118156433
tiger cat 0.35435229539871216
Egyptian cat 0.13743379712104797
tiger 0.007698290515691042
remote control 0.0010309171630069613

 

tabby는 줄무늬 고양이라는 뜻이었습니다. 다만 tiger cat이 높은 순위로 나옵니다.

 

주로 생명체만 확인했던것 같아, 

무생물의 경우를 하나만 더 추가해보았습니다.

맛있는 치킨 이미지입니다.

 

imageshow('/content/chicken.jpg')

show('/content/chicken.jpg')
French loaf 0.5248016119003296
hotdog 0.19065548479557037
pretzel 0.07154688984155655
cheeseburger 0.05124257877469063
plate 0.03858712315559387

 

French loaf(프렌치 바게트)...가 도출됩니다.

이미지넷 클래스가 적었던 탓일까요? 다른 테스트의 필요성을 느낍니다.


모바일넷의 가장 큰 유효점은 이름에서 볼 수 있는 Mobile 모바일 환경에서 적용할 수 있을 정도로

경량화한 모델이라는 점입니다. Inverted Residual 블록을 사용한 덕분이라고 할 수 있겠습니다.

 

다음 시간에는 mobile net 이후의 다른 신규 기술을 접목한 모델도 살펴보도록 하겠습니다.

 

 

728x90