Chainer v2에서 SmoothGrad 구현

13646 단어 파이썬Chainer

소개



이미지 인식에서 식별자가 어디를 주목하고 인식했는지 시각화하는 것이 중요합니다.
CNN에서는 손실 함수의 기울기를 백 프로파게이션으로 입력 이미지까지 전파하고, 그 절대값의 강도를 가시화하는 방법이 제안되어 있지만, 노이즈가 많은 문제가 있었다.
SmoothGrad는 입력 이미지에 가우시안 노이즈를 부여하고 여러 그라디언트를 평균하는 것만으로 깨끗한 시각화로 할 수있는 매우 간단한 방법입니다.



평균화되는 모습


Smooth Grad


Vanilla Grad(종래 방법)


TensorFlow의 코드와 논문은 아래에서 다운로드 할 수있는 것 같습니다.
htps : // 천천히 rfぉw. 기주 b. 이오 / 사엔 cy /

Chainer v2의 공부를 겸해, SmoothGrad를 구현해 보았습니다.
모델은 학습된 VGG16 모델을 사용합니다.
환경은
Windows7 64bit
Python 3.5.2 | Anaconda 4.2.0 (64-bit)
chainer의 version은 '2.0.0'입니다.
GPU에는 대응하고 있지 않습니다.

구현



import



smoothgrad.py
import chainer
import chainer.functions as F
from chainer.variable import Variable
from chainer.links import VGG16Layers
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt

config



테스트 모드에서 수행하지만 백 프로퍼게이션이 필요하므로,
chainer.config를 다음과 같이 설정합니다.

smoothgrad.py
chainer.config.train=False
chainer.config.enable_backprop=True

VGG16 모델 로드



VGG16 모델을 로드합니다.
모델은 500MB 정도이므로, 미리 다운로드되어 있지 않은 경우는, 나름대로 시간이 걸립니다.

smoothgrad.py
model = VGG16Layers()

이미지 로드 및 전처리



VGG는 이미지 사이즈가 224x224이므로 리사이즈 해 둡니다.

smoothgrad.py
image = Image.open("cheetah.png")
image = image.resize((224,224))

매개변수



샘플링 수와 노이즈 레벨을 설정합니다.
샘플링 수는 100, 노이즈 레벨은 20%입니다.

smoothgrad.py
sampleSize = 100
noiseLevel = 0.2 # 20%
sigma = noiseLevel*255.0

기울기 계산



사용 메모리의 관계상, 이번은 1장씩 실시하기로 합니다.
우선, VGG16에서는 채널의 배열이 BGR이므로 변환해, 평균치를 뺍니다.
그런 다음 이미지 노이즈를 추가하면서 순방향 전파, 손실을 계산하고 역전파하여 기울기를 계산합니다.
원하는 기울기를 목록에 추가합니다.

smoothgrad.py
gradList = []
for _ in range(sampleSize):
    x = np.asarray(image, dtype=np.float32)
    # RGB to BGR
    x = x[:,:,::-1]
    # 平均を引く
    x -= np.array([103.939, 116.779, 123.68], dtype=np.float32)
    x = x.transpose((2, 0, 1))
    x = x[np.newaxis]
    # ノイズを追加
    x += sigma*np.random.randn(x.shape[0],x.shape[1],x.shape[2],x.shape[3])    
    x = Variable(np.asarray(x))
    # FPして最終層を取り出す
    y = model(x, layers=['prob'])['prob']
    # 予測が最大のラベルでBP
    t = np.zeros((x.data.shape[0]),dtype=np.int32)
    t[:] = np.argmax(y.data)
    t = Variable(np.asarray(t))
    loss = F.softmax_cross_entropy(y,t)
    loss.backward()
    # 勾配をリストに追加
    grad = np.copy(x.grad)
    gradList.append(grad)
    # 勾配をクリア
    model.cleargrads()

시각화



그라디언트의 각 채널에 대한 절대값의 최대값을 취하고 이미지에 대한 평균을 취합니다.

smoothgrad.py
G = np.array(gradList)
M = np.mean(np.max(np.abs(G),axis=2),axis=0)
M = np.squeeze(M)
plt.imshow(M,"gray")
plt.show()



결과



평균하는 매수를 늘리면서 원화상과 맵을 화소마다 가시화해 보았습니다.

1 샘플


2 샘플


3 샘플


10개 샘플


20 샘플


30개 샘플


50개 샘플


75 샘플


100개 샘플


노이즈를 주지 않고 한 장의 샘플에서 시각화하면 다음과 같이 노이즈가 많이 보입니다.

좋은 웹페이지 즐겨찾기