nn.Conv2d 와 nn.Functional.conv2d 차이

잠만보 석사생·2022년 7월 20일
0

코드를 짤 때 torch.nn 과 torch.nn.functional 이 있는것은 알았지만 평소에는 nn.Conv2d를 이용해 CNN layer를 쌓는다. 그런데 torch.nn.functional에서도 conv2d가 있어서 궁금해서 차이를 알아보았다.

nn.Conv2d 와 nn.functional.conv2d 에 제일 큰 차이는 weight이다. F.conv2d (nn.functional을 편의상 F.conv2d라 부르겠다)에서 보면 input,weight을 입력으로 받는다. 또한, 다른 filter을 사용하여 weight을 따로 만들어 다른 weight을 적용해주는 기법이다. 예시로 Dynamic Region Aware Convolution [CVPR 2021] 논문에서도 input image에 따라 adaptive 하게 weight을 Feature module을 사용하여 생성한다.


위 그림은 convolution 연산이며 nn.conv2d 와 F.conv2d가 코드와 output에서 어떻게 차이가 나는지 보자.

nn.Conv2d

import torch 
import torch.nn.functional as F
import torch.nn as nn
from torch.autograd import Variable
import numpy as np

input = torch.Tensor(np.array([[[  
[0,1,0,1,0],  
[0,1,0,0,1],  
[0,1,0,1,1],  
[1,0,1,1,1],  
[0,0,1,0,0]  
]]]))

input = Variable(input, requires_grad=True)
conv1 = nn.Conv2d(in_channels=1, out_channels=1, kernel_size=(3,3))
print('conv1:', conv1)
print('conv1 weight:', conv1.weight)

output = conv1(input)
print(output)

Result for nn.Conv2d

weight이 매번 실행할때마다 바뀌기때문에 weight 출력을 따로 해주었으며 nn.Conv2d 는 weight을 따로 입력으로 안받기에 filter이 따로 없다.

conv1: Conv2d(1, 1, kernel_size=(3, 3), stride=(1, 1))
conv1 weight: Parameter containing:
tensor([[[[ 0.0674, -0.1552,  0.1951],
          [-0.2577, -0.1085,  0.1606],
          [-0.2145, -0.0488, -0.3306]]]], requires_grad=True)
tensor([[[[-0.4153, -0.6430, -0.4768],
          [-0.9116, -0.5119, -0.4495],
          [-0.6858,  0.1631, -0.4830]]]], grad_fn=<ThnnConv2DBackward>)

F.Conv2d


import torch 
import torch.nn.functional as F
import torch.nn as nn
from torch.autograd import Variable
import numpy as np

input = torch.Tensor(np.array([[[  
[0,1,0,1,0],  
[0,1,0,0,1],  
[0,1,0,1,1],  
[1,0,1,1,1],  
[0,0,1,0,0]  
]]]))

input = Variable(input, requires_grad=True)
filter = torch.randn(1,1,3,3) # weight in this case.
filter = Variable(filter)

fconv1 = F.conv2d(input, filter, padding=0, bias=None)
print('fconv1 output', fconv1)

Result for F.Conv2d

input과 filter (weight) 텐서를 random으로 뽑고 F.Conv2d로 연산한 결과이다.


fconv1 output tensor([[[[ 0.1745,  2.6804,  0.0466],
          [ 1.2668, -0.1850,  2.2837],
          [ 0.4173,  2.7320,  3.3201]]]], grad_fn=<ThnnConv2DBackward>)

F.Conv2d를 사용하게되면 filter (weight) 을 다양하게 사용할수있으며 만약에 nn.Conv2d랑 weight이 같다면 결과값도 같을 것 이다.


출처:

profile
생명공학을 전공했지만 AI에 관심있는 사람

0개의 댓글