>> 본 과제는 학부연구생을 진행하며 수행한 내용을 복습 및 기록 하기 위해 작성 하였습니다.
Im2col >
https://arxiv.org/abs/1410.0759 - cuDNN: Efficient Primitives for Deep Learning
본 논문은 nvidia 에서 발표한 논문으로 nvidia에서 제공하는 cuDNN ( DNN primitives)를 설명한다. introduction 에서 CNN 은 기존 선형대수 라이브러리와는 달리 dense kernel 을 이용해 계산하는 점을 지적하며, 이를 위해 최적화된 primitives를 어떻게 만들었는지에 대해 서술한다.
여기서 말하는 최적화된 promitives 는 3가지 방법으로 서술되고 그중 im2col 의 대한 접근이 있다. im2col 은 3d-tensor 인 input image 를 1d-tensor 로 만드는 방법이다. im2col 를 풀어서 말하자면 'image to column' 으로 쉽게 말해 image를 column 으로 만들겠다는 의도이다. 이를 수행하면 3d 이미지를 2d matrix 로 표현할 수 있다. 2d matrix를 통해 GEMM 연산을 진행하겠다는 것인데 GEMM 에 대해선 다음 포스팅에 자세히 다룰려고 하지만, 간단히 말하자면, convolution( 합성곱 / 이하 conv ) 대신 matrix multiplication (이하 matmul) 을 진행 하겠다는 것이다. conv 대신 matmul을 진행하면 연산시간이 떨어진것을 확인할 수 있다. matmul은 전송된 데이터 당 부동 소수점 연산 비율이 높기 때문에 연산이 빠른 성격을 가지고 있기 때문이다.
따라서 matmul 을 위해 input image 를 matrix 로 만드는 것이라 할 수 있다.
그럼 어떻게 진행되는지 그림을 통해 확인해 보자.
위와 같이 input image 3x3 과 2x2 kernel 이 있을 때, output 으로 나오게 되는데 width 는 k * k , height 는 out_x * out_y 가 된다. 본 그림은 chanel 을 포함 하지 않았는데 chanel 을 포함한다면 width 는 c * k * k, height 는 그대로 out_x * out_y 가 된다.
논문에 삽입된 상태도는 이렇다.
위와 같이 image 와 filter 를 matrix 로 표현 한 다음 두 개의 matrix 를 연산하는것이 gemm 이다.
본 포스팅은 im2col 을 중점으로 다루기 때문에 image를 어떻게 c 언어를 통해 matrix 로 코딩하는지 알아보자.
Im2col code>
void im2col(float *in, float *out, int h, int w, int c, int k, int stride, int pad){
int rs = 0;
int hw = 0;
int height, width, in_ch, r, s;
for(height = 0; height < h; height += stride){
for(width = 0; width < w; width += stride){
for(in_ch = 0; in_ch < c; in_ch++){
for(r = 0; r < k; r++){
for(s = 0; s < k ; s++){
int out_index = hw * c * k * k + in_ch * k * k + rs;
int in_index = in_ch * h * w + ( height + (r-pad) ) * w + ( width + (s-pad) );
if( height + (r-pad) < 0 || width + (s-pad) < 0 || height + (r-pad) >= h || width + (s-pad) >= w ){
out[out_index] = 0;
rs += 1;
continue;
}
out[out_index] = in[ in_index];
rs += 1;
}
}
rs=0;
}
hw++;
}
}
}
input image 에 대하여 각각의 prameter 를 접근해야 하기 때문에 5중 for 문을 사용한다. h - w - c - r(k) - s(k) 로 이동하며 커널의 parameter 만큼 1patch 를 해주기 때문에 커널이 변경 될때 마다 hw 값을 이동해 준다. hw값은 ( out_x * out_y) 의 값으로 처음 그림을 통해 알 수 있듯이 height 값을 옮겨 주는 역할을 한다.
pad 가 있는 경우가 있어 이 경우 exception 작업으로 if 문을 통해 0으로 삽입 후 걸러준다.
코드를 보면 그렇게 어렵지 않다. 사각형 네모 박스를 채우는 과정을 진행 한 것 뿐이다.
본 구현의 전체적인 코드
https://github.com/sangho0804/darknet-based-CNN/tree/master/Convolution%20Lowering
GitHub - sangho0804/darknet-based-CNN: for deep Learning CNN study
for deep Learning CNN study. Contribute to sangho0804/darknet-based-CNN development by creating an account on GitHub.
github.com
'학부생의학부연구생 > _deep_learning' 카테고리의 다른 글
GEMM : C로 구현해보자! (0) | 2022.06.24 |
---|---|
Convolutional layer : C로 구현 해보자! (2) (0) | 2022.03.30 |
Convolutional layer : C로 구현 해보자! (1) (4) | 2022.03.17 |
CNN이 뭐야? (0) | 2022.02.03 |
딥러닝이 뭐야? (0) | 2022.01.20 |
댓글