본문 바로가기
AI-driven Methodology/XAI (eXplainable AI)

[eXplainable AI] Basic XAI with LIME for CNN Models

by goatlab 2022. 2. 10.
728x90
반응형
SMALL

LIME

 

LIME 또는 Local Interpretable Model-Agnostic Explanations는 해석 가능한 모델을 사용하여 로컬로 근사함으로써 모든 분류기 또는 회귀자의 예측을 충실하게 설명할 수 있는 알고리즘이다. 특성 값을 조정하여 단일 데이터 샘플을 수정하고 결과적으로 출력에 미치는 영향을 관찰한다. 각 데이터 샘플의 예측을 설명하는 "설명자"의 역할을 수행한다. LIME의 출력은 로컬 해석 가능성의 한 형태인 단일 샘플에 대한 예측에 대한 각 기능의 기여도를 나타내는 일련의 설명이다. 

 

 

Keras에는 mnist 모듈 의 load_data() 메서드를 사용하여 로드할 수 있는 배포의 일부로 mnist 데이터 세트가 있다. 이 메서드는 지도 학습을 위해 정렬된 train 및 test 데이터를 나타내는 두 개의 tuple을 반환하므로 코드 정보에서 각각 이미지와 대상 label을 나타내는 x 와 y를 사용했다.

 

 

이제 메서드에서 반환된 이미지는 각각 크기가 784인 1차원 numpy 벡터이다. 이미지는 int8 에서 float32 로 유형 변환 되고 크기가 28x28인 2차원 행렬로 변환된다. 이미지는 회색조이므로 픽셀 값의 범위는 0에서 255까지이므로 255.0으로 나누어 정규화한다. 이 단계는 숫자가 크면 훈련 복잡성이 증가하므로 중요하므로 0에서 1 사이에서 정규화하는 것이 좋다.

 

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
from tensorflow.keras.datasets import mnist

(x_train, y_train), (x_test, y_test) = mnist.load_data() 
x_train = x_train.reshape((-1,28,28,1)).astype('float32') / 255.0 
x_test = x_test.reshape(( -1,28,28,1)).astype('float32') / 255.0

 

Lime 모듈은 3차원 이미지, 즉 3개의 채널이 있는 이미지에서만 작동하므로 여기에서 회색조 평면을 복제한다. 아래의 코드는 사용 가능한 평면을 복제하여 회색조 이미지를 RGB로 변환한다.

 

import numpy as np
def to_rgb(x):
    x_rgb = np.zeros((x.shape[0], 28, 28, 3))
    for i in range(3):
        x_rgb[..., i] = x[..., 0]
    return x_rgb
    
x_train = to_rgb(x_train)
x_test = to_rgb(x_test)

 

keras의 순차 API는 모델을 빠르게 생성하는 데 도움이 되지만 유일한 단점은 매우 유연하지 않다는 것이다. 즉, 다중 입력과 다중 출력을 가질 수 있는 keras의 기능적 API와 달리 하나의 입력과 하나의 출력을 가질 수 있다.  이 예에서는 순차 API가 적합하다.

 

Make model

 

모델은 3차원 이미지를 가져와 ReLU 의 활성화 함수를 갖는 3x3 크기의 16개 filter가 있는 Conv2D layer에 전달하는 바닐라 CNN 모델이다. 이 layer는 컨볼루션 filter의 weight와 bias을 학습하고 직관적으로 모델의 "눈" 역할을 하고 기본적으로 최대 크기가 2x2인 최대 filter가 있는 MaxPooling2D에 전달되는 기능 맵을 반환하고 기능 맵의 차원만 축소한다. 관심 영역을 어느 정도 보존한다.

 

마지막으로 mnist 데이터 세트에 대해 0에서 9까지 10개의 대상 label이 있으므로 featuer map을 평면화하고 크기가 10인 벡터를 제공해야 하는 fully connected dense layer을 추가한다 .

 

model = keras.Sequential(
    [
     keras.Input(shape=(28,28,3)),
     layers.Conv2D(16, 3, activation='relu'),
     layers.MaxPooling2D(),
     layers.Flatten(),
     layers.Dense(10)
    ]
)

 

SparseCategoricalCrossentropy(from_logits=True)는 10개의 범주를 나타내는 10 크기의 벡터를 얻었고 여기에 softmax를 적용하여 one-hot encoded 벡터를 얻으려고 하기 때문에 사용한다. 여기에서 Adam 옵티마이저는 실제 및 예측된 one-hot 벡터의 오차를 기반으로 모델을 훈련하는 데 사용된다. 이 벡터는 index = label가 속한 이미지에서만 1을 가져야 한다.

 

model.compile( 
  loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True), 
  optimizer=keras.optimizers.Adam(), 
  metrics=['accuracy'] 
)

 

기본 CNN 모델은 batch_size가 32인 2 epoch에 대해 model.fit()을 사용하여 훈련되고 mnist 데이터를 로드하는 동안 이전에 분리된 validation 세트를 제공한다. Epoch는 모델 훈련을 위해 전체 train 데이터를 확인해야 하는 횟수이고 batch_size는 훈련의 순방향 및 역방향 전달에 대한 손실을 계산하기 위해 고려해야 하는 레코드 수이다.

 

model.fit(
        x_train, 
        y_train, 
        epochs=2, 
        batch_size=32, 
        validation_data = (x_test, y_test))
        
Epoch 1/2
1875/1875 [==============================] - 22s 12ms/step - loss: 0.4055 - accuracy: 0.8816 - val_loss: 0.0895 - val_accuracy: 0.9731
Epoch 2/2
1875/1875 [==============================] - 21s 11ms/step - loss: 0.0912 - accuracy: 0.9726 - val_loss: 0.0768 - val_accuracy: 0.9748

 

Explainable AI using LIME

 

!pip install lime

import lime
from lime import lime_image
from skimage.segmentation import mark_boundaries
import matplotlib.pyplot as plt
import random

 

Lime 패키지 의 lime_image 모듈을 사용하여 LimeImageExplainer class의 Explainer 객체를 생성한다. 이 객체에는 3차원 이미지 데이터와 여기서는 model.predict를 취하는 Explain_instance() 메서드가 있으며 함수의 예측을 기반으로 설명을 반환한다.

 

설명 객체에는 이전에 구문 분석된 3차원 이미지 데이터에 해당하는 예측된 label을 가져오고 (image, mask) tuple을 반환하하는 get_image_and_mask() 메서드가 있다. 여기서 이미지는 3차원 numpy 배열이고 마스크는

skimage.segmentation.mark_boundaries과 함께 사용할 수 있는 2차원 numpy 배열이다. 해당 마스크가 있는 반환된 이미지는 예측을 담당하는 이미지의 특징을 나타낸다.

 

explainer = lime_image.LimeImageExplainer(random_state=42)
explanation = explainer.explain_instance(
         x_train[10], 
         model.predict
)
plt.imshow(x_train[10])
image, mask = explanation.get_image_and_mask(
         model.predict(
              x_train[10].reshape((1,28,28,3))
         ).argmax(axis=1)[0],
         positive_only=True, 
         hide_rest=False)
plt.imshow(mark_boundaries(image, mask))

 

https://medium.datadriveninvestor.com/xai-with-lime-for-cnn-models-5560a486578

 

XAI with LIME for CNN Models

In this blog we’ll be using LIME to get an explanation as to why a particular prediction is being made by a basic MNIST handwritten digit…

medium.datadriveninvestor.com

 

728x90
반응형
LIST