목차
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)
사전처리
모델에 보낼 수 있도록 이미지를 사전 처리
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)]]
✔ 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)]]
✔ 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!]
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!
역시 잘나온다
메모리
넘어가기 전에 다음 셀을 실행하여 GPU 메모리를 지우기
이는 다음 노트북으로 넘어가기 위한 필수 작업
import IPython
app = IPython.Application.instance()
app.kernel.do_shutdown(True)
다음 학습
- 위의 모델 모다 더 강력한 기술, 전이학습