• Home
  • About
    • Yerim Oh photo

      Yerim Oh

      Happy and worthwhile day by day :)

    • Learn More
    • Email
    • LinkedIn
    • Instagram
    • Github
    • Youtube
  • Posts
    • All Posts
    • All Tags
  • Projects

[011] Deep learning 1: Pre-Trained Models

01 Mar 2020

Reading time ~6 minutes

Table of Contents
  • 목차
  • Pre-Trained Models
    • 우리가 시험할 모델
    • 목표
  • 개구멍 자동문
  • 모델로드
  • 이미지 사전처리
    • 이미지 표시
    • 사전처리
  • 예측 수행
    • 예측 해보기
  • 목표 완성
  • 메모리
  • 다음 학습
  • 목차

    • 사전 트레이닝된 모델 Pre-Trained Models
      • 우리가 시험할 모델
      • 목표
    • 개구멍 자동문
    • 모델로드
    • 이미지 사전처리
      • 이미지 표시
      • 사전처리
    • 예측 수행
      • 예측 해보기
    • 목표 완성
    • 메모리
    • 다음 학습

    Pre-Trained Models

    모델을 만들려면 많은 노력이 필요하다. 하지만 이런 노력이 필요없다면 어떨까?

    사전 트레이닝된 모델 Pre-Trained Models이 있다면 가능하다

    사전 트레이닝된 모델 Pre-Trained Models: 웹사이트에서 모델의 URL이 주어진 경우 모델을 Python으로 로드할 수 있는 모듈이 프레임워크 내에 존재

    우리가 시험할 모델

    VGG16: ‘Very Deep Convolutional Networks for Large-Scale Image Recognition’

    • 모델은 2014 ImageNet 챌린지에서 입상한 아키텍처.
    • ImageNet: 동물, 음식, 나무, 스포츠와 사람을 비롯한 수천 개의 범주로 분류된 수백만 장의 사진으로 이루어진 데이터베이스.
      VGG16 논문

    목표

    • Keras를 사용하여 아주 잘 사전 트레이닝된 모델 로드
    • 자체 이미지를 사전 처리하여 사전 트레이닝된 모델로 작업
    • 사전 트레이닝된 모델을 사용하여 자체 이미지에 대한 정확한 추론 수행

    개구멍 자동문

    목표: 다른 동물이 아닌 오직 개만 출입이 가능한 개구멍만들기


    모델로드

    트레이닝된 ImageNet 모델은 Keras 라이브러리 내에서 다운로드

    • 이용 가능한 모델과 세부 정보
      위에서 말했듯이 가장 일반적인 모델인 VGG16를 import할 것임
    from tensorflow.keras.applications import VGG16
      
    # load the VGG16 network *pre-trained* on the ImageNet dataset
    model = VGG16(weights="imagenet")
    

    모델의 입력레이어와 출력레이어를 살펴보겠다

    • 입력레이어: 모델이 예상하는 입력차원과 입력이미지를 일치시켜야하기 때문
    • 출력레이어: 모델이 무엇을 반환할 지 파악해야하기 때문
    from tensorflow.keras.applications import VGG16
      
    # load the VGG16 network *pre-trained* on the ImageNet dataset
    model = VGG16(weights="imagenet")
    
    👀 결과 보기
    Model: "vgg16"
    _________________________________________________________________
    Layer (type)                 Output Shape              Param #   
    =================================================================
    input_1 (InputLayer)         [(None, 224, 224, 3)]     0         
    _________________________________________________________________
    block1_conv1 (Conv2D)        (None, 224, 224, 64)      1792      
    _________________________________________________________________
    block1_conv2 (Conv2D)        (None, 224, 224, 64)      36928     
    _________________________________________________________________
    block1_pool (MaxPooling2D)   (None, 112, 112, 64)      0         
    _________________________________________________________________
    block2_conv1 (Conv2D)        (None, 112, 112, 128)     73856     
    _________________________________________________________________
    block2_conv2 (Conv2D)        (None, 112, 112, 128)     147584    
    _________________________________________________________________
    block2_pool (MaxPooling2D)   (None, 56, 56, 128)       0         
    _________________________________________________________________
    block3_conv1 (Conv2D)        (None, 56, 56, 256)       295168    
    _________________________________________________________________
    block3_conv2 (Conv2D)        (None, 56, 56, 256)       590080    
    _________________________________________________________________
    block3_conv3 (Conv2D)        (None, 56, 56, 256)       590080    
    _________________________________________________________________
    block3_pool (MaxPooling2D)   (None, 28, 28, 256)       0         
    _________________________________________________________________
    block4_conv1 (Conv2D)        (None, 28, 28, 512)       1180160   
    _________________________________________________________________
    block4_conv2 (Conv2D)        (None, 28, 28, 512)       2359808   
    _________________________________________________________________
    block4_conv3 (Conv2D)        (None, 28, 28, 512)       2359808   
    _________________________________________________________________
    block4_pool (MaxPooling2D)   (None, 14, 14, 512)       0         
    _________________________________________________________________
    block5_conv1 (Conv2D)        (None, 14, 14, 512)       2359808   
    _________________________________________________________________
    block5_conv2 (Conv2D)        (None, 14, 14, 512)       2359808   
    _________________________________________________________________
    block5_conv3 (Conv2D)        (None, 14, 14, 512)       2359808   
    _________________________________________________________________
    block5_pool (MaxPooling2D)   (None, 7, 7, 512)         0         
    _________________________________________________________________
    flatten (Flatten)            (None, 25088)             0         
    _________________________________________________________________
    fc1 (Dense)                  (None, 4096)              102764544 
    _________________________________________________________________
    fc2 (Dense)                  (None, 4096)              16781312  
    _________________________________________________________________
    predictions (Dense)          (None, 1000)              4097000   
    =================================================================
    Total params: 138,357,544
    Trainable params: 138,357,544
    Non-trainable params: 0
    _________________________________________________________________
    

    [결과 해석]
    입력데이터

    input_1 (InputLayer)         [(None, 224, 224, 3)]     0    
    
    • (224, 224, 3) : 224x224픽셀의 3색 채널의 이미지
    • None: Keras 모델은 예측을 위해 한 번에 2개 이상의 이미지를 허용가능
      • 한번에 예측을 수행하는 이미지 개수

    출력데이터

    predictions (Dense)          (None, 1000)              4097000   
    
    • (None, 1000) : 모델이 1000개의 출력값을 반환
      • 이미지가 1000개의 범주를 가지고 있다는 것 ➡ 1000마리의 동물로 분류할 수 있다
      • 범주는 151-268, 고양이 범주는 281-285: 어떤 종의 동물들이 개구멍에 출입할 수 있는지 확인가능

    이미지 사전처리

    저번에 했던 것과 같다

    이미지 표시

    먼저 입력이미지의 모양을 파악하기 위해 시각화

    • matplotlib 라이브러리를 사용
    import matplotlib.pyplot as plt
    import matplotlib.image as mpimg
    
    def show_image(image_path):
        image = mpimg.imread(image_path)
        print(image.shape)
        plt.imshow(image)
    
    show_image("data/doggy_door_images/happy_dog.jpg")
    # (1200, 1800, 3)
    

    image

    사전처리

    모델에 보낼 수 있도록 이미지를 사전 처리

    • preprocess_input매서드 활용: 사용자가 모델이 원래 트레이닝되었던 이미지의 품질에 맞게 자체 이미지를 사전 처리
    from tensorflow.keras.preprocessing import image as image_utils
    from tensorflow.keras.applications.vgg16 import preprocess_input
    
    def load_and_process_image(image_path):
        # Print image's original shape, for reference
        print('Original image shape: ', mpimg.imread(image_path).shape)
        
        # Load in the image with a target size of 224, 224
        image = image_utils.load_img(image_path, target_size=(224, 224))
        # Convert the image from a PIL format to a numpy array
        image = image_utils.img_to_array(image)
        # Add a dimension for number of images, in our case 1
        image = image.reshape(1,224,224,3)
        # Preprocess image to align with original ImageNet dataset 🤷‍♀️ 
        image = preprocess_input(image)
        # Print image's shape after processing
        print('Processed image shape: ', image.shape)
        return image
    
    processed_image = load_and_process_image("data/doggy_door_images/brown_bear.jpg")
    
    #Original image shape:  (2592, 3456, 3)
    #Processed image shape:  (1, 224, 224, 3)
    

    🤷‍♀️ 그런데 공부하던중 모르는게 생겼다.
    왜 preprocess_input를 사용할까?? 이걸 사용 하던 안하던 Processed image shape:은 같게 나온다
    그래서 더 공부해본 결과 ‘preprocess_input 함수는 모델에 필요한 형식에 이미지를 적절하게 맞추기위한 것’ 의 세부 뜻을 알 수 있었다.

    • 겉으로는 표시가 안나는 내부적인 요소들을 조정한다는 뜻이였다
      • 실제로 이 전에 이미지의 형식을 맞춰주기 않으면 이 코드가 실행되지 않는다
      • 즉 표면적인 차원은 맞춰줘야 한다는 것이다
    • 내부적인 요소의 예로는,
      • 일부 모델은 0에서 1까지의 값을 가진 이미지를 사용하고 다른 모델은 -1에서 +1까지를 사용한다
      • 다른 사람들은 정규화되지 않았지만 중앙에있는 “caffe”스타일을 사용한다 등이 있다

    예측 수행

    이미지가 올바른 형식으로 변환되었으니 이제 모델에 전달하여 예측 수행 가능 자 그럼 이제 코드를 직접 짜보자!!

    from tensorflow.keras.applications.vgg16 import decode_predictions
    
    def readable_prediction(image_path):
        # Show image
        FIXME
        # Load and pre-process image
        image = FIXME
        # Make predictions
        predictions = FIXME
        # Print predictions in readable form
        print('Predicted:', decode_predictions(predictions, top=3))
    
    👀 정답 코드 보기
    from tensorflow.keras.applications.vgg16 import decode_predictions
    
    def readable_prediction(image_path):
        # Show image
        show_image(image_path)
        # Load and pre-process image
        image = load_and_process_image(image_path)
        # Make predictions
        predictions = model.predict(image)
        # Print predictions in readable form
        print('Predicted:', decode_predictions(predictions, top=3))
    

    예측 해보기

    몇 개의 동물에 사용하여 결과를 확인해 보자!!

    readable_prediction("data/doggy_door_images/happy_dog.jpg")
    
    👀 결과 보기
    (1200, 1800, 3)
    Original image shape:  (1200, 1800, 3)
    Processed image shape:  (1, 224, 224, 3)
    Downloading data from https://storage.googleapis.com/download.tensorflow.org/data/imagenet_class_index.json
    40960/35363 [==================================] - 0s 0us/step
    Predicted: [[('n02093256', 'Staffordshire_bullterrier', 0.4509805), ('n02110958', 'pug', 0.32263243), ('n02099712', 'Labrador_retriever', 0.09343209)]]
    

    image ✔ Staffordshire_bullterrier 강아지 종류까지 잘 나온다!! 대박!!!

    readable_prediction("data/doggy_door_images/sleepy_cat.jpg")
    
    👀 결과 보기
    readable_prediction("data/doggy_door_images/sleepy_cat.jpg")
    readable_prediction("data/doggy_door_images/sleepy_cat.jpg")
    (1200, 1800, 3)
    Original image shape:  (1200, 1800, 3)
    Processed image shape:  (1, 224, 224, 3)
    Predicted: [[('n02123159', 'tiger_cat', 0.73654705), ('n02124075', 'Egyptian_cat', 0.17492658), ('n02123045', 'tabby', 0.045884028)]]
    

    image

    ✔ Egyptian_cat 고양이 까지 잘 나온다!! 대박!!!


    목표 완성

    이제 동물을 제대로 분류하는 것을 파악했으니 개구멍 자동문을 완성시켜보자

    • 개만 출입허용
    • 고양이는 내부에 있게 할 수 있음
    • 참고) 개는 범주 151 ~ 268
    • 참고) 고양이는 범주 281 ~ 285

    그럼 아래의 코드도 완성시겨보자

    import numpy as np
    
    def doggy_door(image_path):
        show_image(image_path)
        image = load_and_process_image(image_path)
        preds = model.predict(image)
        if FIXME:
            print("Doggy come on in!")
        elif FIXME:
            print("Kitty stay inside!")
        else:
            print("You're not a dog! Stay outside!")
    
    👀 정답 코드 보기
    import numpy as np
    
    def doggy_door(image_path):
        show_image(image_path)
        image = load_and_process_image(image_path)
        preds = model.predict(image)
        if 151 <= np.argmax(preds) <= 268:
            print("Doggy come on in!")
        elif 281 <= np.argmax(preds) <= 285:
            print("Kitty stay inside!")
        else:
            print("You're not a dog! Stay outside!")
    

    어렵지 않았다!!!

    자 그럼 위의 이미지로 실험해볼까??

    doggy_door("data/doggy_door_images/happy_dog.jpg")
    
    👀 결과 보기
    (1200, 1800, 3)
    Original image shape:  (1200, 1800, 3)
    Processed image shape:  (1, 224, 224, 3)
    Doggy come on in!]
    

    image

    readable_prediction("data/doggy_door_images/sleepy_cat.jpg")
    
    👀 결과 보기
    (1200, 1800, 3)
    Original image shape:  (1200, 1800, 3)
    Processed image shape:  (1, 224, 224, 3)
    Kitty stay inside!
    

    image

    역시 잘나온다


    메모리

    넘어가기 전에 다음 셀을 실행하여 GPU 메모리를 지우기
    이는 다음 노트북으로 넘어가기 위한 필수 작업

    import IPython
    app = IPython.Application.instance()
    app.kernel.do_shutdown(True)
    

    다음 학습

    • 위의 모델 모다 더 강력한 기술, 전이학습


    Deep Learning Share Tweet +1