과제3. Network Visualization
Network Visualization 코드 구현
1. Introduce
그럼 뉴런 네트워크가 어떻게 훈련이 정상적으로 되었는지 확인하는 방법으로는 Network 시각화를 통해 공부를 해보겠다.

이미지 분류 train 끝내고 각각에 feature 보고싶은 일이 생길 수 있다.
그럴때는 각각에 feature map 마다 시각화를 해서 보여주면 된다.

여기서 검은 색은 높은 값을 나타내며, 흰색에 가까울수록 낮은 값을 나타냅니다. 엣지(경계) 성분은 검/흰으로 표시된다.
첫 번째로는 Saliency Map, 두 번째로는 Pooling Image, 그리고 마지막으로 Class Visualization입니다. 이번 과제에서 이러한 방법들을 사용하여 분석할 것이다.

2.Saliency Map
계산하기 위해서는 이미지의 픽셀에 대한 정답 클래스에 해당하는 정규화되지 않은 점수의 기울기를 구하게 된다.
만약 이미지가 (3, H, W) 모양을 가진다면, 똑같이 역전파 기울기는 (3, H, W) 모양을 가질것이다.
그럼 각 이미지의 필셀은 분류하는데 얼마나 영향을 끼쳤는지 알 수 있다.
saliency map 계산하기 위해 기울기의 절댓값을 취한다음에 3개의 채널에 최댓값을 얻습니다.
따라서 (H,W) 모든 값은 양수를 가지게 된다.

2.1 train
def compute_saliency_maps(X, y, model):
model.eval()
X.requires_grad_()
saliency = None
scores = model(X)
loss = scores[range(len(y)), y].sum() / len(y)
loss.backward()
#최댓값과, _ : 인덱스
saliency, _ = X.grad.abs().max(axis=1)
return saliency
- scores = model(X) 이미지의 분류를 예측하고
- loss = scores[range(len(y)), y].sum() / len(y) : Loss 값을 구한다음 backward 시킨다
- saliency, _ = X.grad.abs().max(axis=1) : X의 기울기만 구한다음에 절댓값을 씌운다음 최대값을구한다.
- 절댓값을 씌우는 이유는 만약 필요 없는 부분이 정답 픽셀이든 입력 픽셀이든 0으로 수렴할 것이다. 만약 중요한 픽셀 값이 있다면, dx는 정답 픽셀로 가기 위해 많은 변화가 있을 것이다. 이러한 변화를 얻기 위해 절댓값을 씌워서 체크하게 된다.

3. Pooling Image
이미지와 대상 클래스가 주어지면, 네트워크가 이미지를 대상 클래스로 분류할 때 중지하고, 대상 클래스를 최대화하기 위해 이미지에 대해 그래디언트 ascent를 수행할 수 있습니다.
속임 이미지를 생성하기 위해 다음 기능을 구현합니다.

3.1 train
def make_fooling_image(X, target_y, model):
X_fooling = X.clone()
X_fooling = X_fooling.requires_grad_()
learning_rate = 1
while True:
scores = model(X_fooling)
target = scores.argmax(axis=1)
print(target)
if target == target_y:
break
loss = scores[0, target_y]
loss.backward()
X_fooling.data += learning_rate * X_fooling.grad
return X_fooling
- 계속해서 X_fooling 이미지를 주고 정답을 찾아갈 때 까지 반복문을 돌면서 이미지를 업데이트한다.

Additional references
- https://cs231n.github.io