Pytorch_Activation_plot

conv layer의 output을 그려보자

  • 파이토치를 메모리를 아끼기위해 모델에서 나오는 마지막 output만을 저장한다.

  • 그렇다면, 각 conv layer를 통과한 output이 궁금하다면 어떻게 해야할까??

  • hook을 이용하면 forward와 backward에서 각 레이어의 output을 가져올 수 있다.

  • 여기서는 forward hook을 이용하는 class를 만들어서 이용해보고자 한다.

  • 사용할 모델은 pretrain vgg16모델이며 input으로는 인터넷에서 아무 고양이 사진을 사용해보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
# 이미지 불러와서 tensor로 변환 및 사이즈 조정
simple_transform = transforms.Compose([transforms.Resize((224,224))
,transforms.ToTensor()
,transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
])
img = Image.open('../image/cat_1.jpg')
img = simple_transform(img)

# unsqueeze_를 통해 shape에 (1,3,224,224) 로 변경 --> batch_size를 추가한것 --> 모델에 넣기위해
img.unsqueeze_(0)

# pretrained 모델을 불러와서 사용한다. --> 직접 train시킨 모델도 상관없지만 현재 목표는 모델 학습이 아니기 때문에 pretrained모델 사용
vgg = models.vgg16(pretrained=True).cuda()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class LayerActivations():
# layer의 output을 저장할 공간을 만들자.
features=None

# hook을 정의하고 정한 layer_num에 hook을 등록할 수 있게 만든다.
def __init__(self,model,layer_num):
self.hook = model[layer_num].register_forward_hook(self.hook_fn)

# 정해진 layer에서 forward함수가 실행되면 output을 저장할 수 있는 함수를 만든다.
def hook_fn(self,module,input,output):
self.features = output.cpu().data.numpy()

# 등록된 hook을 없애줄 수 있는 함수를 만든다.
def remove(self):
self.hook.remove()
  • 이제 모델에서 첫번째 conv layer를 통과한 후 나오는 output을 LayerActivations객체에 저장하고 이미지를 그려보자
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# vgg.features의 첫번째(0) 에 hook을 등록하고 output을 conv_out에 받도록 한다.
conv_out = LayerActivations(vgg.features,0)

# 가장 처음 가져온 이미지를 vgg모델에 넣어보자.
# 이미지가 모델을 통과할때 위에서 정의한 conv_out에 첫번째 conv layer를 통과하며 내놓은 output을 저장했을 것이다.
o = vgg(Variable(img.cuda()))

# 등록된 hook을 제거해준다.
conv_out.remove()

# conv_out객체의 features값을 가져오면 우리가 알고싶은 첫번째 conv layer를 통과했을때의 output을 알 수 있다.
act = conv_out.features

# 30개의 채널만을 plot으로 그려보자.
fig = plt.figure(figsize=(20,50))
fig.subplots_adjust(left=0,right=1,bottom=0,top=0.8,hspace=0,wspace=0.2)
for i in range(30):
ax = fig.add_subplot(12,5,i+1,xticks=[],yticks=[])
ax.imshow(act[0][i])
  • 첫번째 conv layer를 통과한 output을 그려보면 다음과 같다.

  • output conv first

  • 첫 번째 conv layer는 윤곽선에 집중되는 모습을 확인할 수 있다.

  • 이를 이용해 마지막 conv layer 통과한 결과도 확인해보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 마지막 conv layer는 28번째 feature이다.
# 모든 feature를 확인해보고자 한다면 vgg.features 를 입력해서 확인해보자.
conv_out = LayerActivations(vgg.features,28)

o = vgg(Variable(img.cuda()))

conv_out.remove()

act = conv_out.features

fig = plt.figure(figsize=(20,50))
fig.subplots_adjust(left=0,right=1,bottom=0,top=0.8,hspace=0,wspace=0.2)
for i in range(30):
ax = fig.add_subplot(12,5,i+1,xticks=[],yticks=[])
ax.imshow(act[0][i])
  • output conv last

  • 위는 마지막 conv layer를 통과한 output을 시각화한 것이다.

  • 마지막 레이어는 첫번째 레이어와 다르게 해석하기 어려운 특성을 학습하는 것으로 파악할 수 있었다.

  • 이처럼 필요에 따라서 각 레이어의 output을 hook을 이용해 시각화하는 방법을 공부해 볼 수 있었으며 이를 통해 모델의 각 layer가 집중하는 부분도 확인할 수 있을것이라 생각한다.

Full Code

Full Code

Comments

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×