본문 바로가기
학부생의학부연구생/_deep_learning

Convolutional layer : C로 구현 해보자! (1)

by 호상 🐧 2022. 3. 17.

학부연구생 과제로 convolutional layer 를 구현을 진행했었는데 구현한지는 꽤 되었지만 그동안 미루고 미룬탓에 지금 작성하게 된다. (⊙_⊙;)

assign 에 대한 자세한 내용은 저작권이 걸려있기 때문에 혼자 복습용으로 코드를 작성하였고, 참고가 될진 모르겠으나 후에 어떤일이 발생할지 알수 없으므로 열심히 작성해 본다.

 

convolutional layer 가 뭐야?

라고 생각 하실수 있는데 나보다 더 정확하고 자세하게 설명 해주시는 분들이 구글에 널리고 널렸기에 조심스레 링크만 투척해 본다.

 

http://taewan.kim/post/cnn/

 

CNN, Convolutional Neural Network 요약

Convolutional Neural Network, CNN을 정리합니다.

taewan.kim

https://tensorflow.blog/a-guide-to-convolution-arithmetic-for-deep-learning/

 

A guide to convolution arithmetic for deep learning

이 글은 원 저자들의 허락하에 번역되어 게재 되었습니다. 이 글의 원문은 여기에서 다운 받을 수 있습니다. 딥 러닝을 위한 콘볼루션 계산 가이드 Vincent Dumoulin(MILA, 몬트리올 대학), Francesco Visin(

tensorflow.blog

 

 

convolutional layer 위 블로그들을 통해서 필자 역시 도움을 받았기에 천천히 쭉 읽어보시는것을 추천한다.

CNN 을 이미 알고 계신 분들 께서는 굳이 읽지 않아도 될지도 모른다. 

 

 

convolutional layer 구현하기

필자는 input image , kennel , output 으로 나누어 구현하였고, 

image size : 256 * 256 * 3

kernel size : 3 * 3 * 3

output size : 256 * 256 * 16

stride : 1

pad : 1

input chennel : 3

output chennel : 16

으로 설정 하였다.

int main() {
	//set value
	int x = 256;
	int y = 256;
	int in_ch = 3;
	int out_ch = 16;
	int k_size = 3;
	int stride = 1;
	int pad = 1;

 

그리고 malloc 을 통해 각각의 메모리 할당을 진행 

input image에 pad 를 씌우기 위해 pad_contain_in 변수를 새로 메모리 할당을 진행 하였다. 

 

	float input_image =
		(float*)calloc(x * y * in_ch, sizeof(float));

	float output =
		(float*)calloc(x * y * out_ch, sizeof(float));

	float pad_contain_in =
		(float*)calloc((x + (2 * pad)) * (y + (2 * pad)) * in_ch, sizeof(float));

	float weight =
		(float*)calloc(out_ch * in_ch * k_size * k_size	, sizeof(float));

위 weight 은 kernel 이라 봐도 무방하고, 사실상 커널이다.

 

필자는 weight 의 사이즈를 16 * 3 * 3 * 3 으로 할당하는것에 의문을 가졌었는데 이는 output size 를 보면 알수 있다. 

output size : 256*256*16 -> 즉슨 width * height * output chennel 이므로 그렇다.

 

그림으로 쉽게 설명 하자면 

 

https://towardsdatascience.com/understanding-1d-and-3d-convolution-neural-network-keras-9d8f76e29610

 

Understanding 1D and 3D Convolution Neural Network | Keras

When we say Convolution Neural Network (CNN), generally we refer to a 2 dimensional CNN which is used for image classification. But there…

towardsdatascience.com

 

위 그림을 설명하자면 파란색 input image 에서 주황색 filter / kernnel 를 통해  초록색 output 을 형성하는데 위 과정을 convolution 하는것이고 , ( 위의 링크를 충분히 읽었다면 이해가 되실겁니다! ) 빨간색 칸 하나가 output feature 를 이루고 저 빨간색이 모여 output feature map 을 형성한다.

 

결국 왜 커널의 사이즈가 16 * 3 * 3 * 3 이되는가를 확인하자면 3 * 3 * 3 커널 하나가 output feature 의 한 chennel 을 형성하게 되고 output feature map 은 총 16장  ( output size : 256*256*16 -> 즉슨 width * height * output chennel) 이므로 커널 사이즈를 output chennel * input chennel * kernnel size * kernnel size = 16 * 3 * 3 * 3 가 되는것이다.  

 

필자의 설명이 부족할 수 있으니 다음 링크를 통해 자세히 알아보는것도 하나의 방법이다.

 

https://omicro03.medium.com/%EC%9E%90%EC%97%B0%EC%96%B4%EC%B2%98%EB%A6%AC-nlp-25%EC%9D%BC%EC%B0%A8-cnn-%EC%A0%95%EB%A6%AC-230263720d15

 

자연어처리(NLP) 25일차 (CNN 정리)

2019.07.28

omicro03.medium.com

또한 위에 코드에서 모드 calloc 으로 할당 했지만, malloc 을 사용해도 무방하고 , pad_contain_in 변수는 calloc 으로 할당 받는것을 추천한다. 

 

calloc 의 기능은 할당한 메모리에 모드 0으로 채워놓는데 padding 과정을 보면 주위에 0으로 채워 넣는다. 

 

비루하지만 태블릿이 없는 관계로 pc 그림판으로 열심히 그려보았다!

 

위와같이 padding 작업을 하는데 왜 padding 작업 해야 하는지에 대해서 설명하자면, 

 

https://deepestdocs.readthedocs.io/en/latest/004_deep_learning_part_2/0043/

 

0043 Convolutional Neural Network (CNN) - Deepest Documentation

What is CNN? 합성곱 인공신경망(convolutional neural network, CNN)은 인공신경망의 여러 층 중 convolution 연산을 사용하는 층이 있는 NN을 의미합니다. 보통 convolution 연산을 수행하는 convolution 층이 아래쪽에

deepestdocs.readthedocs.io

 

위 링크에서 자세히 설명되어 있고, 나머지 올린 링크에도 설명 되있을것이다.

 

하지만 필자가 간략 하게 설명하자면 convolution 과정에서 padding 을 하지 않는다면 본래의 image 크기가 손상되기때문에 본래의 크기를 유지하기 위함에 있다고 생각한다.

여기서 또 왜? 크기가 왜 손상돼?  라고 물어볼 수있는데 

간단하게 설명하면

예를 들어 256 * 256 * 3 의 크기를 갖는 input 에 3 * 3 * 3 커널을 가지고 convolution 작업을 진행하면, output은 254 * 254 *3 이 되기 때문이다. 

사실 output size 가 어떻게 되는지 공식도 있다.

 

output_x = ( x + 2 * pad - kernnel size) / stride + 1

output_y = ( y + 2 * pad - kernnel size) / stride + 1

 

그래도 이해가 안된다면 댓글 남겨주세요......ㅎㅎ

 

할당이 끝난 다음에는 inpiut에 padding 을 해준다.

 

	//Extend to include pad
	//and copy input image
	for (int insert_index = 0; insert_index < y; insert_index++)
	{
		int pad_contain_index =
			(insert_index + pad) * (x + (2 * pad)) * in_ch + in_ch;

		int input_image_index =
			(insert_index)*x * in_ch;

		memcpy(&pad_contain_in[pad_contain_index]
			, &input_image[input_image_index]
			, sizeof(float) * (x * in_ch));
	}

코드 이해를 돕기 위해 작성해보자면 !

 

0 부터 height = y 까지 이동하는데 위에서 아래로 쭉쭉 이동한다고 생각하시면 됩니다.

좀 이해가 안될수도 있는데 저도 이해하는데 꽤나 고생했습니다 ㅎㅎ 그림으로 만나보죠.

 

 

제가 직접 그려보았는데요! 포인트를 빨간색으로 잡고 쭉쭉 내려가며 채워 줍니다. 

 

int pad_contain_index =
			(insert_index + pad) * (x + (2 * pad)) * in_ch + in_ch;

위 부분에서

(insert_index + pad) * (x + (2 * pad)) * in_ch

이 부분을 살펴 보면 insert_index 는 y좌표를 이동하는데 사용되며, + pad 는 실제 값이 있는곳 즉 input[0] 에서 을 가리키게 됩니다. 또한 padcontain 에서 0 ~ 258 * 3 은 전부 0 으로 채워져 있기에 ( padding 을 했기 때문) 다음 줄인 (insert_index + pad) * (x + (2 * pad)) * in_ch 으로 되는것입니다. 즉 이것은 줄바꿈이 되겠네요. 그리고 + in_ch 는 padcontain의 첫번째 y줄은 모두 0으로 채워져있고, input chennel 만큼 이동하여 빨간색으로 포인트를 잡게 됩니다.  

 

결국 for 문을 통해 빨간색 포인트만 이동하게 되죠. 

 

조금더 이해가 쉽게 알려드리기 위해 그림을 그려보았는데요 , 천천히 생각해 보셔도 됩니다.

 

위 처럼 형성된  input 을 

 

 

요렇게 바꿔 주는것입니다! 빨간색은 전부 pad 이므로 0으로 채워져 있습니다.

 

다만 글을 읽으면서 계속 갸우뚱 하실 수 있는데 본 구현은 3차원 이미지를 1차원 배열을 사용하여 구현 하였습니다.

 

이것에 대해 저도 궁금증이 있어 여쭈어 보았는데 c 에서 3차원 배열을 사용하면 메모리 할당시 주솟값 접근이 모호해 질수 있기 때문이라고 하네요..

 

아무튼 따라서 위 2그림을 보면 좀 더 이해가 쉬울거라고 생각합니다! (❁´◡`❁) (저만 그런가요.....?)

 

 

자! 아무튼 인덱스 설정을 해주셨다면 복사를 해봅시다.

memcpy(&pad_contain_in[pad_contain_index]
			, &input_image[input_image_index]
			, sizeof(float) * (x * in_ch));

저는 memcpy 함수를 사용하여 복사를 하였는데 뒷부분이 궁금하실수 있겠죠...?

그래서 설명 해보자면 x * in_ch 의 상태를 일단 봅시다. 

x * in_ch 은 256 * 3 이 됩니다. 이 사이즈는 input image 의 첫번째 줄이 됩니다. 위 이미지를 보시면 chennel 이 width 만큼 채워져 있는것이 보이시죠? 그만큼을 복사 붙여넣기를 시행하는 것입니다. 

 

전체적인 코드를 보자면 y좌표로 한칸씩 이동하며 한줄씩 복사하는 형태가 되겠죠?? 

 

이렇게 padding을 진행 하였습니다!

 

다음으로는 본격적인 convolution 작업이 될텐데요 다음 2편에서 만나뵙죠!

 

 

/* 점점 말투가 바뀌지만 너그러히 용서해 주십시오.*/

 

본 구현의 전체적인 코드는 git 에 올렸읍니다. 궁금하시면 보셔도 좋습니다... 좀 뭔가 창피 하네요....(❁´◡`❁)

 

https://github.com/rofe12/CNN/blob/master/Convolution%20Layer/Convolution_Layer.c

 

GitHub - rofe12/CNN: for deep Learning CNN study

for deep Learning CNN study. Contribute to rofe12/CNN development by creating an account on GitHub.

github.com

 

댓글