Paper

Learning Spatiotemporal Featurescti with 3D Convolutional Networks(+code review)

Kim_sang_hyeob 2023. 8. 3. 21:04



Abstract

본 논문에서는 3-dimensional convolutional networks 를 통해 video dataset 에서 좋은 성능을 이끌어냈다.
본문에서 크게 3가지를 소개한다.
1. 3D ConvNet 이 spatiotemporal ( video )  에 2D 보다 적합하다는 점
2. 3 x 3 x 3 Convolution kernel 을 통해서 모델을 구성했다는 점.      ( 기존 2d 에서는 3 x 3 )
3. C3D ( convolutional 3d) 가 단순히 linear classifier outperform 을 통해서 SOTA 성능을 4가지 다른 밴치마크에서 발견했다는 점 , 당시 SOTA급 성능과 비슷한 밴치마크가 2개 있다는 점

추가적으로 C3D 모델은 매우 쉽고 간단한 학습과 사용이 가능하다.


1. Introduction

본 논문에서는 video descriptor 가 효율적이기 위해서는 4가지 조건을 갖추어야 한다고 생각한다.

1. generic      : 여러 종류의 비디오를 분석 할 수 있어야 한다.
2. compact.  : video 는 데이터가 크고 많은 비디오를 처리해야 하기 때문에 scalable 해야한다. ( Figure 5에 자세히 나온다.)
3. effcient.    : 많은 양의 video 를 처리해야 하기 때문에 효율적이여야 한다.
4. simple.      : 좋은 descriptor 는 구조가 복잡하지 않고 simple 하면서 잘 작동되어야 한다. ( 본 논문에서는 SVM 사용했다 )

이전 까지는 image 를 활용한 방법들이여서 video 에서의 temporal 을 잊어버리는것이 문제점이 였는데,
본 논문에서는 그걸 해결하고자(spatio-temporal 한) 3D ConvNet 을 소개한다.

(cf. 저번 논문부터 지금까지 image 에서 video 로 넘어가면서 temporal 한 정보가 소실되는게 계속해서 문제가 되었던 것 같고 이걸 해결하는게 당시 video 처리에 가장 중요한 핵심이였던 것 같다. )


2. Related Work


이전 연구에서 부터 video descriptor 에 대해서 각 task 에 맞는 모델들이 생겨났지만 computationally intensive 하고 large scale datasets 을 처리하기 어려운 문제점이 있었다.

본 논문의 모델은 다른 pre-processing 을 거치지 않고(end-to-end 로 처리한다는 의미로 받아드리면 될 듯) full video frame 을 input 으로 받아 쉽게 large dataset 을 scaling 할 수 있다.
이전 논문 (two stream conv) 은 2d conv & pooling 을 사용해서 모델을 구성한 반면에
본 논문에서는 3d conv & pooling 을 사용해서 space & time information을 모든 layer 에 전달 할 수 있도록 하였습니다.

3. Learning Features with 3D ConvNets


3.1. 3D convolution and pooling




기존의 2D ConvNet 은 spatially 한 정보만 담았다면, 3D ConvNet 에서는 spatio-temporally 한 정보를 가질 수 있도록 설계하였습니다 .
(a) 는 기존 2d image 를 처리할때 2d conv 모습이고
(b) 는 이전 논문 (two stream conv) 모델인데 , 2d ConvNet 으로 video 의 temporal 한 정보를 이용하기 위해서 고안된 모델이지만 2d conv 한계에 의해 3d 모델에 비해서
temporal information 을 잃어버린다는 단점이 존재했습니다.

Conv 에서는 temporal 한 정보가 소실 되어 버립니다. 그 이유가 본 논문에서 직접적으로 언급되어 있지는 않지만 추론해보자면 그림(b)에서 보듯이 input 값들은 temporal 한 정보들을 가지고 있지만
2d conv 를 거치고 나서 output 은 1dim 으로 temporal 한 정보를 잃어버립니다.
(부가설명)
- 이전 논문에서는 temporal 한 정보를 이용하기 위해 optical flow 를 이용하여 two stream 방법을 통해서 모델을 학습시켰습니다. 하지만 이 방법 역시 conv 에 들어간 후에 output 자체는 3d conv 과는 다르게  depth 자체가 1이기 때문입니다. ( 그림 b/c output 을 보시면 될 것 같습니다)


temporal information 을 최대한 보존해 사용하고자
본 논문에서는 새롭게 고안한 3d conv 모델입니다. ( c 그림이 보기 어려워 보기 쉬운 그림 아래 그림으로 대체했습니다 )



(c) 3D ConvNet



3d conv 은 2d conv 과 다르게 kernel 을 d x k x k ( d = depth , k = spatial size) 로 나타냅니다.
주목해야 할 점은 본 논문에서 k 는 3x3 로 고정을 해두고 depth 를 변경해가면서 최적의 depth 를 찾는 시도를 했을때 depth = 3 ( 즉 , 3x3x3 kernel ) 에서 가장 좋은 성능을 나타내었습니다.

notation
C x l x h x w
C: channels
L: length in number of frames
H,w: height , weight

Kernel size : d x k x k
d : kernel temporal depth
K: kernel spatial size

depth 를 바꿔가면서 실험했는데, depth = 1 일때는 2d conv 과 동일 하기 때문에 다른 depth ( 3,5,7 ) 일때보다 성능이 현저히 좋지 않았습니다.
이건 제 사견인데 depth = 3 일때 가장 좋은 성능을 내는게 컴퓨팅 능력을 사용하기도 하고 ( depth 5,7 일때는 당연히 계산하는 횟수가 줄어들기 때문에)
기존 kernel 에서도 3x3 일때 가장 좋은 성능을 내는 것으로 보아 depth 도 3 일때 가장 정보를 잘 담을 수 있지 않나 싶습니다.
뒤에서 실험 결과가 함께 다시 한번 설명 하겠습니다.

오버랩 되지 않은 16 frame 들을 하나의 clip 으로 사용했고
좀 더 자세한 모델에 자세한 수치들은 뒤에 코드 보면서 좀 더 자세히 살펴 보도록 하겠습니다.






3.3 spatiotemporal feature learning


C3D architecture.

import torch.nn as nn


class C3D(nn.Module):
    """
    The C3D network as described in [1].
    """

    def __init__(self):
        super(C3D, self).__init__()

        self.conv1 = nn.Conv3d(3, 64, kernel_size=(3, 3, 3), padding=(1, 1, 1))
        self.pool1 = nn.MaxPool3d(kernel_size=(1, 2, 2), stride=(1, 2, 2))

        self.conv2 = nn.Conv3d(64, 128, kernel_size=(3, 3, 3), padding=(1, 1, 1))
        self.pool2 = nn.MaxPool3d(kernel_size=(2, 2, 2), stride=(2, 2, 2))

        self.conv3a = nn.Conv3d(128, 256, kernel_size=(3, 3, 3), padding=(1, 1, 1))
        self.conv3b = nn.Conv3d(256, 256, kernel_size=(3, 3, 3), padding=(1, 1, 1))
        self.pool3 = nn.MaxPool3d(kernel_size=(2, 2, 2), stride=(2, 2, 2))

        self.conv4a = nn.Conv3d(256, 512, kernel_size=(3, 3, 3), padding=(1, 1, 1))
        self.conv4b = nn.Conv3d(512, 512, kernel_size=(3, 3, 3), padding=(1, 1, 1))
        self.pool4 = nn.MaxPool3d(kernel_size=(2, 2, 2), stride=(2, 2, 2))

        self.conv5a = nn.Conv3d(512, 512, kernel_size=(3, 3, 3), padding=(1, 1, 1))
        self.conv5b = nn.Conv3d(512, 512, kernel_size=(3, 3, 3), padding=(1, 1, 1))
        self.pool5 = nn.MaxPool3d(kernel_size=(2, 2, 2), stride=(2, 2, 2), padding=(0, 1, 1))

        self.fc6 = nn.Linear(8192, 4096)
        self.fc7 = nn.Linear(4096, 4096)
        self.fc8 = nn.Linear(4096, 487)

        self.dropout = nn.Dropout(p=0.5)

        self.relu = nn.ReLU()
        self.softmax = nn.Softmax()

    def forward(self, x):

        h = self.relu(self.conv1(x))
        h = self.pool1(h)

        h = self.relu(self.conv2(h))
        h = self.pool2(h)

        h = self.relu(self.conv3a(h))
        h = self.relu(self.conv3b(h))
        h = self.pool3(h)

        h = self.relu(self.conv4a(h))
        h = self.relu(self.conv4b(h))
        h = self.pool4(h)

        h = self.relu(self.conv5a(h))
        h = self.relu(self.conv5b(h))
        h = self.pool5(h)

        h = h.view(-1, 8192)
        h = self.relu(self.fc6(h))
        h = self.dropout(h)
        h = self.relu(self.fc7(h))
        h = self.dropout(h)

        logits = self.fc8(h)
        probs = self.softmax(logits)

        return probs

"""
References
----------
[1] Tran, Du, et al. "Learning spatiotemporal features with 3d convolutional networks." 
Proceedings of the IEEE international conference on computer vision. 2015.
"""



(모델)
Video frame resize —> 128 x 171
Video are split into non-overlapped 16-frame clips are then used as input to networks
Jittering by using random crops with a size of 3 x 16 x 112 x 112
Input dimnesions   —> 3 x 16 x 128 x 171

5 convolution layers —> 64 128 256 256 256
5 pooling layers
2 fc layers & softmax

Kernel size : d x k x k
2 x 2 x 2 —> max pooling iwth kernel size 2x2x2 —> reduce input size
1 x 2 x 2 —> first layer —> temporal 한 정보를 너무 빨리 잃지 않기 위함.

fc layer —> 2048

모델에서 주의깊게 볼 부분은 맨처음 kernel 만 1 x 2 x 2 형태(2d conv )를 가지고 있다는 점 입니다.
이는 temporal 한 정보를 너무 빠르게 합치지 않기 위함이라고만 나와있는데
설명을 좀 더 붙여보자면 아마 2x2x2 형태는 3d conv 이기 때문에 temporal 한 정보를 합치게 되지만
2d conv 는 spatial 한 정보만 가지고 활용하기 때문에 이런 설명을 해준 것 같습니다. ( 사실 저자들이 처음부터 이런 모델을 구성했다기 보다는 실험을 하다보니 알아냈을 것이므로 .. )



varying network architectures


- depth 가 1,3,5,7 일때 실험을 진행하였습니다.
- depth가 1 일때 ( 1x2x2 —> 2d conv kernel과 동일) 다른 depth(3,5,7) 일때 보다 성능이 제일 떨어지는 것을 확인 할 수 있었습니다. 이를 통해 2d conv 보다 3d conv 이 temporal 한 정보를 더 잘 활용하고 있다고 볼 수 있습니다.
- 2d , 3d conv 커널 차이에도 불구하고 전체 parameter 수의 0.3 % 차이 밖에 나지 않았는데 논문에서 직접 언급되어 있지는 않았지만, 설명 맨 처음 모델이 갖춰야할 조건 4가지중 3.effeicent 와 연관이 여기 있지 않나 싶습니다.


- depth 1 << depth ( 3,5,7)
- 3x3x3 kernel —> best perform

-sprot-1m dataset 사용해 training —> 많은 양의 데이터 존재 / ucf-101 보다 많은 비디오 카테고리 존재
-SGD mini batch 30 사용


(~ 실험 결과들 ~ 추후 추가 )


what does c3d learn?

- 본 논문에서 C3D 가 무얼 보고 판단하는지 알기 위해서 deconvolution method 방법을 통해서 알아보았습니다.
- 처음 몇 frame 에서는 appearance  —>  이후 motion
즉,  ( 모양—>움직임 ) 을 보고 video 를 판단합니다.



사진이 잘 안보이기는 하는데 위쪽 그림에서는
( 전체 사람 모습 —> 사람 움직임 ) 가중치가 활성화 되었고
아래 그림에서는
( 눈—>motion( around the eyes while applying the makeup) , 눈 움직임   ) 에서 가중치가 활성화 된 걸 확인할 수 있었습니다.


4. action recognition


- test data set : UCF-101
- classification model : linear SVM 사용
- 기존 모델과 비교했을때 성능이 좋다 ( 논문의 table 3 참조 )

C3D is compact
-  앞서 말씀드렸던 video descriptor 조건 4가지중 2. compact 에 대해서 소개하고있다.
- C3D feature 의 compactness 를 살펴보기 위해 PCA 를 사용하여 낮은 차원으로 projection 해서 linear SVM 사용하여 확인합니다.






- 그래프를 살펴보면 낮은 차원에서 C3D 가 성능이 더 월등히 좋은걸 확인 할 수 있습니다.
- 뿐만 아니라 높은 dim 에서도 좋은 성능을 내는데 이는 본 논문의 모델이 compact 하면서 discriminative 한 걸 확인 할 수 있습니다.
- 이번에는 fc6 에서 나온 feature 들을 가지고 와 얼마나 모델이 잘 학습하고 있는지 실험 해보았습니다.








- t-SNE 를 사용하여 시각화한 모습입니다.
- 결과를 확인해보면 C3D 모델의 feautre 들이 더 잘 clustering 되어 있는 걸 확인 할 수 있고, 이는 C3D 모델이 더 의미를 잘 파악하는 쪽으로 학습 한다고 볼 수 있습니다.









- 테스트 셋에서 쓰인 데이터가 아니라 아예 다른 데이터를 예측하도록 하였습니다.
-





Conclusion

- spatiotemporal feature 을 학습하기 위해 3d conv net 을 trian 하였다.
- 가장 적절한 kernel depth 를 찾음
-  모델이 외형 & 움직임 정보를 동시에 모델링 가능
- 다른 비디오 분석에서도 좋은 성능을 보임






느낀점

- 이전 논문과 엮어서 비교해보려고 했는데 3d conv 이다 보니까 거의 대부분 다 다달라서 아마
다음 논문에서 집중적으로 비교 할 듯 싶다 (kinetics data set 논문 )
- 마지막 부분 5.6.7 파트는 결과부분이라 좀 대충 읽고 넘겼는데 다시 확인해보아야한다.
- 이번 코드리뷰는 이미 pytorch 에서 con3d 모듈이 존재하기 때문에 … 자세한건 생략했는데 시간이 남으면 con3d 구현하는 방법도 알아두면 좋을 듯하다 , 생각보다 3차원으로 kernel 이 움직인다는게
구현하기 어려울 것 같은 느낌이 든다.
-  컴퓨터로 작성을 못하다보니 사진 크기가 어떤지 모르겠다
- 첫 리뷰보다는 괜찮아진거같은데 아직도 좀 말로 정리가 어렵다


다음 리뷰 kinetics data set 에서는 전 논문(two-stream conv) 와 이번 논문(3 conv) 논문을 모두 비교하면서, 새로운 모델 을 소개 할 것이다.