본문 바로가기

Python

MobileNet을 이용한 전이학습 모델생성


전이학습 : Transfer Learning


✅ 정적 전이 (Positive Transfer)

: A분야를 잘하면 B분야도 잘 하게 되는 전이

✅ 부적 전이 (Negative Transfer)

: A분야를 잘하면 B분야는 못 하게 되는 전이


전이학습은 한 분야에서 학습한 것을 바탕으로 다른 분야의 학습을 하는 것으로, 예를 들어, 피아노를 배우면 오르간도 잘 칠 수 있는 것과 같다. 머신러닝에서는 한 과제에 학습된 모형을 다른 과제에 적용하는 것이고, 딥러닝의 경우에는 대량의 데이터와 많은 계산이 필요하기 때문에 전이 학습을 통해 적은 데이터와 계산으로 높은 성능을 낼 수 있다. 즉, 대량의 데이터로 사전 학습(pretraining)을 해놓고 다음에 적용하고자 하는 과제에 미세 조정(fine-tuning)하면서 학습을 시키는 것을 말한다. 이미지 처리와 자연어 처리에서는 전이 학습이 보편적 전략이다.

✅ 자연어 모델 사이즈의 증가 추세






티처블머신 홈페이지에서 모델 생성



1. 내 PC에서 '개'와 '고양이' 학습용 이미지 데이터셋을 업로드 및 학습시키기

이미지 업로드 및 학습 -> class1 : cat, class2 : dog


2. 학습된 모델에 고양이 그림을 비춰서 개와 고양이 분류 잘하나 확인해 보기

고양이를 고양이라 인식하는가? Yes (cat : 100%)
멍멍이를 멍멍이로 인식하는가? Yes (dog : 100%)


3. 모델 저장하기

Teachable Machine으로부터 학습한 모델 다운로드 과정



• 모델 내보내기 → Tensorflow → 모델 변환 유형 Keras → 모델 다운로드
- tensorflow.js : 웹 브라우저에서 모델을 사용
- tensorflow : Python에서 모델을 사용
- tensorflow lite : 스마트폰 등 엣지 단말에서 사용

• Keras와 SavedModel 포맷 중 Keras 선택
- Keras : 케라스에서 사용되던 포맷, 텐서플로 지원
- SavedModel : 텐서플로 자체 포맷

• 다운로드된 모델 파일 이름

저장된 모델명 : keras_model.h5






티처블머신 홈페이지에서 만든 모델을 파이썬으로 가져와서 검증해보기


4. 검증(validation)할 때, 범위 조정
• 티처블 머신 모델은 이미지 데이터를 –1 ~ +1 사이의 실수로 받도록 만들어져 있다.
• 컬러 사진은 0~255 데이터 범위를 가지고 있다.
• dataset이 32 X 32 = 1024장이 있어서 한 번에 데이터를 불러오지 않고 그때그때 불러와서 실행한다.
• 검증 데이터셋에 lambda함수를 걸어 rescaling하여 모델에 넣으면 1세트(32장)씩 불러와서 모델 실행을 하게 된다.

# 필요한 라이브러리 불러오기
import tensorflow as tf
from PIL import Image
import numpy as np

# teachable machine에서 만든 모델 keras_model 불러오기
tm_model = tf.keras.models.load_model('keras_model.h5')
tm_model.compile(loss = 'sparse_categorical_crossentropy', metrics = ['accuracy'])

# 티처블머신 데이터는 -1 ~ 1 로 rescale 돼서 입력하여 모델이 만들어졌기 때문에
# 검증 데이터셋을 입력시 동일하게 rescale해줘야 함 ( 0 ~ 255 -> -1 ~ 1범위로 변경)
ds = validation_dataset.map(lambda x, y: (x / 127 - 1, y))
tm_model.evaluate(ds)
32/32 [==============================] - 18s 495ms/step - loss: 0.4337 - accuracy: 0.9400
[0.43372631072998047, 0.9399999976158142]

→ 티처블머신 통해 생성한 모델 정확도가 94%
→ 높은 정확도이지만 실제로 사용하는 데에는 더 좋은 모델로 업그레이드하여 사용해야 할 것이다.

 
 
5. 검증 데이터를 넣어서 예측해 보기
 
prob = tm_model.predict(ds)
prob
 
array([[9.9997747e-01, 2.2472590e-05],
       [1.0000000e+00, 2.7195232e-10],
       [9.9873561e-01, 1.2643822e-03],
       ...,
       [9.8399862e-05, 9.9990153e-01],
       [1.6877543e-16, 1.0000000e+00],
       [3.7060402e-21, 1.0000000e+00]], dtype=float32)

→ 검증 데이터를 모델에 넣고 예측한 결과이다. 0열은 고양이 확률, 1은 강아지 판단한 확률값이다.


6. 분류에 실패한 사진만 리스트로 저장하기

fail_dog = []
for x, y in ds:
    prob = tm_model.predict(x)
    y_pred = np.where(prob[:,1] > 0.5, 1, 0)  # 강아지예측 확률계산
    for i, (yp, yt) in enumerate(zip(y_pred, y)):
        if yp != yt.numpy():
            fail_dog.append(x[i])

fail_cat = []
for x, y in ds:
    prob = tm_model.predict(x)
    y_pred = np.where(prob[:,0] > 0.5, 1, 0)  # 고양이예측 확률계산
    for i, (yp, yt) in enumerate(zip(y_pred, y)):
        if yp != yt.numpy():
            fail_cat.append(x[i])



7. '강아지' 분류에 실패한 사진 한 장만 봐보기

Image.fromarray(((fail_dog[0]+1) * 127).numpy().astype('uint8'))

사람이 봐도 고양이인지 강아지인지 알아보기가 약간 애매하긴 하다.



8. 검증 이미지 1장 모델에 넣어서 확인해보기

멍멍이를 멍멍이로 인식하는가?

from PIL import Image

# 강아지 사진 1장 가져와 모델에 맞춰 넣기
IMG_SIZE = (224,224)
img = Image.open('cats_and_dogs_filtered/validation/dogs/dog.2000.jpg')
a = np.array(img.resize(IMG_SIZE))
x = a / 127 - 1
x = np.expand_dims(x, 0)
model.predict(x)
prob = model.predict(x)
pred = np.where(prob > 0.5, 1, 0)
pred
array([[0, 1]])

→ 왼쪽이 고양이 확률 : 0, 오른쪽이 강아지 확률 : 1 로 잘 예측하였다.


고양이를 고양이로 인식하는가?

from PIL import Image

# 고양이 사진 1장 가져와 모델에 맞춰 넣기
IMG_SIZE = (224,224)
img = Image.open('cats_and_dogs_filtered/validation/cats/cat.2000.jpg')
a = np.array(img.resize(IMG_SIZE))
x = a / 127 - 1
x = np.expand_dims(x, 0)
prob = model.predict(x)
pred = np.where(prob > 0.5, 1, 0)
pred
array([[1, 0]])

→ 왼쪽이 고양이 확률 : 1, 오른쪽이 강아지 확률 : 0 으로 잘 예측하였다.


그러나 분류에 실패한 이미지들이 많이 있기 때문에 정확도를 더 올리기 위해서 티처블머신 모델말고 다른 모델을 가져다가 이용해 보도록 하자. 텐서플로 허브라는 사이트에 가면 이미 이미지 분석 관련 알고리즘들이 많이 존재한다. 이것을 이용해 보는데, MobileNet을 이용하여 전이학습을 해보자.




TensorFlow Hub

TensorFlow Hub

tfhub.dev


MobileNet

• 구글 소속 연구자들이 2017년 발표한 이미지 처리 신경망 구조 (MobileNets : Efficient Convolutional Neural Networks for Mobile Vision Applications)
• 자동차, 드론, 스마트폰 등을 위해 용량과 연산량을 줄인 합성곱 신경망(Convolution Neural Network)
• 주요 모델에 비해 성능은 비슷하고 1001종류의 사물을 구별할 수 있음

TensorFlow Hub

tfhub.dev



텐서플로허브에서 모바일넷 v2를 파이썬으로 바로 불러와서 사용할 수 있게 해놓았다.

MobileNet V2 : 분류 모델, 학습데이터 : ImageNet
직접 다운로드를 받을 수도 있음
MobileNet V2 사용시 주의사항


MobileNet 모델은 이미지 데이터를 다음과 같이 전처리하여 적용해야 한다.

📌 사이즈 : 224 X 224
📌 컬러값 : 0 ~ 1 사이값




텐서플로허브에서 MobileNet 모델을 파이썬으로 가져오기


1. 아나콘다 prompt창에서 tensorflow_hub 설치

pip install tensorflow_hub


2. MobileNet 모델 가져오기

model_url = "https://tfhub.dev/google/tf2-preview/mobilenet_v2/classification/4"
mobilenet_model = tf.keras.Sequential([hub.KerasLayer(model_url)])


3. 1,001개의 동물이름 라벨 가져오기

label_file = \
tf.keras.utils.get_file(origin = 
                        'https://storage.googleapis.com/download.tensorflow.org/data/' +
                        'ImageNetLabels.txt')
labels = open(label_file).read().splitlines()



4. 고양이 사진이 어떤 종류 고양이인지 MobileNet 모델에 넣어서 예측결과 확인해 보기


😺 내 PC에 고양이 이미지 가져오기

IMG_SIZE = (224,224)
img = Image.open('cats_and_dogs_filtered/validation/cats/cat.2000.jpg')
img
테스트해 볼 고양이 이미지 1장



😸 MobileNet 모델에 이미지를 넣어서 확인

a = np.array(img.resize(IMG_SIZE))
x = a / 255
x = np.expand_dims(x, 0)

prob = mobilenet_model.predict(x)
print('')
print('* 1001의 자료를 대조한 확률 : \n',prob)
print('* 사이즈 : ',prob.shape)
print('* 1001 라벨중 가장 높은 확률을 가진 숫자 : ',prob.argmax())
print('* 동물 이름 : ',labels[prob.argmax()])
* 1001의 자료를 대조한 확률 : 
 [[ 0.1096383  -0.03066945  1.4477127  ... -2.047833   -0.00745085
   3.311554  ]]
* 사이즈 :  (1, 1001)
* 1001 라벨중 가장 높은 확률을 가진 숫자 :  286
* 동물 이름 : Egyptian cat

👉 'Eqyptian cat'으로 고양이 종류를 잘 맞춘다.


5. MobileNet를 수정하여 나만의 고유모델 생성

※ mobilenet 모델 맨 마지막에 개와 고양이를 맞추는 출력을 하는 부분만 넣고 compile함
→ tf.keras.layers.Dense(1, activation = 'sigmoid')

model_url = ('https://tfhub.dev/google/imagenet/'
             'mobilenet_v2_100_224/feature_vector/5')
mn2_model = tf.keras.Sequential([
    tf.keras.layers.Rescaling(1./255),
    hub.KerasLayer(model_url, trainable = False),
    tf.keras.layers.Dense(1, activation = 'sigmoid')
])
mn2_model.compile(loss = 'binary_crossentropy', metrics = ['accuracy'])



📔 모델 학습 : 개와 고양이 이미지 학습 데이터셋

mn2_model.fit(train_dataset)
63/63 [==============================] - 72s 1s/step - loss: 0.1754 - accuracy: 0.9540



📔 모델 검증 : 개와 고양이 이미지 검증 데이터셋

mn2_model.evaluate(validation_dataset)
32/32 [==============================] - 34s 1s/step - loss: 0.0641 - accuracy: 0.9850

👉 모델 검증 정확도가 티처블머신(94%)에서 모바일넷(98%)로 5%가 더 좋게 나왔다. 이렇게 알고리즘 몸통을 잘 갖다가 사용하면 정확도가 더 오르게 된다.

6. 모델을 가지고 개와 고양이 판정해 보기

😸 고양이 사진 판정

IMG_SIZE = (224,224)
img = Image.open('cats_and_dogs_filtered/validation/cats/cat.2000.jpg')
a = np.array(img.resize(IMG_SIZE))
x = np.expand_dims(a, 0)
prob = mn2_model.predict(x)
result = np.where(prob > 0.5,1,0)

if result[0][0] == 0:
    print('')
    print('* 결과값 : ', result[0][0])
    print('* 판정값 : 고양이')
else:
    print('')
    print('* 결과값 : ', result[0][0])
    print('* 판정값 : 강아지')

* 결과값 :  0
* 판정값 : 고양이


🐶 강아지 사진 판정

IMG_SIZE = (224,224)
img = Image.open('cats_and_dogs_filtered/validation/dogs/dog.2000.jpg')
a = np.array(img.resize(IMG_SIZE))
x = np.expand_dims(a, 0)
prob = mn2_model.predict(x)
result = np.where(prob > 0.5,1,0)

if result[0][0] == 0:
    print('')
    print('* 결과값 : ', result[0][0])
    print('* 판정값 : 고양이')
else:
    print('')
    print('* 결과값 : ', result[0][0])
    print('* 판정값 : 강아지')

* 결과값 :  1
* 판정값 : 강아지