👩‍💻LEARN : ML&Data/Book Study

[모두의 딥러닝] #5-21. 설명가능한 딥러닝 (CAM, 오클루전)

쟈니유 2023. 2. 27. 23:53
728x90

 

왜 이렇게 분류하게 되었는지 이유를 알기 위해서 시작되었다는 CAM과 오클루젼...

하지만 저는 설명 없어도 괜찮을거같아요 정말루...흑흑...

이해된거같다가 정리하려고 보면 다시 이해가 안되는 일들의 연속 ㅇㅅ< 

 


#5-21. 설명가능한 딥러닝 (CAM, 오클루전)

 

1. CAM (Class Activation Map) 

딥러닝 중간에 나온 특징맵을 사용하여 해당 예측/분류 근거가 무엇인지 히트맵으로 보여주는 것 

 

  • 컨볼루션신경망으로 분류를 수행할 때, 다양한 컨볼루션 레이어와 풀링을 지난 데이터(각 채널들, 중간맵)는 입력데이터의 특징을 가짐
  • 이런 데이터 (채널*가로*세로*) 를 flatten 과정을 통해 2차원으로 전환 (채널*가로세로를 배열로 전환한 특징)하여 분류하게 됨 
  • 분류할 때는 Fully connected layer 들을 지난 다음 마지막 분류 layer에서 분류를 수행하게 됨 

 

  • 이러한 flatten, 분류 단계에서 기존 입력데이터의 특징이 소실되므로 flatten 과정 이전에 아래 단계를 수행하려고 함 

 

 

  • 입력 데이터의 특징을 갖고 있는 중간맵(채널)을 따로 모음 
  • 각 중간맵 각각에 GAP(평균값, Global Max Pooling)을 적용하여 각 채널의 특징을 획득함
  • 이 특징값들과 최종 예측 사이에 한번 더 학습(기존 FC Layer를 없애고 분류 layer만 남김?) > 각 중간맵마다의 가중치를 알 수 있음
  • 이 가중치를 중간맵에 곱해서 히트맵을 만들 수 있음 
  • 이게 맞나...? 한번 더 찾아봐야겠다..책에선 이정도가 최선이었음..

2. 오클루전 

  • 이미지의 일부를 가리면서 가려진 부분이 결과에 얼마나 영향을 미치는 지 계산하는 방식 

3. 실습 

 

!pip install tf-explain

from tensorflow.keras.preprocessing.image import load_img, img_to_array
from tensorflow.keras.applications import VGG16

# XAI 알고리즘을 불러오는 부분입니다.
from tf_explain.core.grad_cam import GradCAM
from tf_explain.core.occlusion_sensitivity import OcclusionSensitivity

import glob
import matplotlib.pyplot as plt
import matplotlib.image as mpimg

# 깃허브에 준비된 데이터를 가져옵니다.

# 원본 이미지가 들어갈 리스트 만들기
images_originals = []

# 원본 이미지가 저장된 폴더에서 하나씩 불러와 리스트에 넣기
for img_path in glob.glob('./data/img/*_0.jpg'):
  images_originals.append(mpimg.imread(img_path))

# 코랩에서 보여 줄 이미지의 크기
plt.figure(figsize=(20,20))

# 원본 이미지를 코랩에서 보이게 하기                            #enumerate 은 인덱스/원소에 동시 접근하며 루프를 돌릴 수 있게 해줌 
for i, image_o in enumerate(images_originals):
  plt.subplot(5, 5, i + 1)                                            # i번째 사진을 루프 돌리며 보여주는 것 
  plt.imshow(image_o)
 

고양이 최고!

# 사전에 학습된 딥러닝 모델 불러오기
model = VGG16(weights="imagenet", include_top=True)

# 원본 이미지 이름과 Imagenet에서의 해당 이미지 인덱스
input_list = ["maltese", "persian_cat", "squirrel_monkey", "grand_piano", "yawl"]
imagenet_index = ["153", "283", "382", "579", "914"]

# 그레이디언트 CAM 알고리즘 선택
explainer = GradCAM()

# 그레이디언트 CAM 알고리즘이 적용된 이미지가 들어갈 빈 리스트 만들기
images_cams = []

# 그레이디언트 CAM 알고리즘 실행
for l, i in zip(input_list, imagenet_index):
   img = load_img('./data/img/{}_0.jpg'.format(l), target_size=(224, 224)) # 이미지를 불러오고 내부에서 처리될 이미지의 크기를 설정합니다.
   img = img_to_array(img) # 이미지를 넘파이 배열로 바꾸어 줍니다.
   data = ([img], None)
   grid = explainer.explain(data, model, int(i)) # 그레이디언트 CAM이 실행되는 부분입니다.
   explainer.save(grid, ".", './data/img/{}_cam.jpg'.format(l)) # 실행 후 저장되는 이름입니다.

# 그레이디언트 CAM 알고리즘이 적용된 이미지를 불러오는 부분의 시작입니다.
plt.figure(figsize=(20,20))

for img_path in glob.glob('./data/img/*_cam.jpg'):
  images_cams.append(mpimg.imread(img_path))

for i, image_c in enumerate(images_cams):
  plt.subplot(5, 5, i + 1)
  plt.imshow(image_c)