DarkNet 시리즈 - Short Layer
shortcut_layer
shortcut layer 란?
ResNet에서 제안된 skip connection과 유사합니다.
잠시 출력을 저장하고 그 후에 layer의 출력과 합치는 작업에서 사용 됩니다.
shortcut.c
forward_shortcut_layer
1
2
3
4
5
6
void forward_shortcut_layer(const layer l, network net)
{
copy_cpu(l.outputs*l.batch, net.input, 1, l.output, 1); // network input -> layer output
shortcut_cpu(l.batch, l.w, l.h, l.c, net.layers[l.index].output, l.out_w, l.out_h, l.out_c, l.alpha, l.beta, l.output); // layer output += i-th layer output
activate_array(l.output, l.outputs*l.batch, l.activation);
}
함수 이름: forward_shortcut_layer
입력:
- const layer l: 현재 layer 정보
- network net: 현재 network 정보
동작:
- 현재 layer의 출력값으로 네트워크 입력값을 복사
- 현재 layer의 출력값에 shortcut 연결된 이전 layer의 출력값을 더해줌
- 현재 layer의 출력값에 활성화 함수를 적용
설명:
- shortcut 연결을 통해 다른 layer의 출력값을 현재 layer의 출력값에 더해줌으로써, 네트워크의 학습 효율성을 높이기 위한 레이어
- forward_shortcut_layer 함수는 해당 layer의 forward propagation을 수행하며, 입력값을 현재 layer의 출력값으로 복사하고 shortcut 연결된 이전 layer의 출력값을 더해주며 활성화 함수를 적용하는 역할을 수행함
backward_shortcut_layer
1
2
3
4
5
6
void backward_shortcut_layer(const layer l, network net)
{
gradient_array(l.output, l.outputs*l.batch, l.activation, l.delta); // layer delta -> activation grad
axpy_cpu(l.outputs*l.batch, l.alpha, l.delta, 1, net.delta, 1); // network delta += alpha * layer delta
shortcut_cpu(l.batch, l.out_w, l.out_h, l.out_c, l.delta, l.w, l.h, l.c, 1, l.beta, net.layers[l.index].delta); // i-th layer delta += layer delta
}
함수 이름: backward_shortcut_layer
입력:
- const layer l: shortcut layer의 정보를 담고 있는 구조체
- network net: 신경망을 구성하는 layer들의 정보를 담고 있는 구조체
동작:
- layer output의 activation gradient를 계산하여 layer delta에 저장한다.
- network delta에 alpha값과 layer delta값을 곱하여 더해준다.
- i-th layer delta에는 beta값과 layer delta값을 곱하여 더해준다.
설명:
- Shortcut layer는 입력값과 이전 layer의 출력값을 더하여 출력값을 만들어낸다.
- 따라서 forward pass에서는 이전 layer의 출력값을 현재 layer의 입력값과 더하여 출력값을 계산하게 된다.
- Backward pass에서는 현재 layer의 출력값에 대한 activation gradient를 계산하고, 이전 layer의 delta값에도 현재 layer의 delta값을 더하여 전파하게 된다.
resize_shortcut_layer
1
2
3
4
5
6
7
8
9
10
11
void resize_shortcut_layer(layer *l, int w, int h)
{
assert(l->w == l->out_w);
assert(l->h == l->out_h);
l->w = l->out_w = w;
l->h = l->out_h = h;
l->outputs = w*h*l->out_c;
l->inputs = l->outputs;
l->delta = realloc(l->delta, l->outputs*l->batch*sizeof(float));
l->output = realloc(l->output, l->outputs*l->batch*sizeof(float));
}
함수 이름: resize_shortcut_layer
입력:
- layer *l: 크기를 조정할 shortcut layer의 포인터
- int w: 새로운 너비
- int h: 새로운 높이
동작:
- l의 w와 out_w가 같아야 함을 확인(assert)
- l의 h와 out_h가 같아야 함을 확인(assert)
- l의 w와 out_w를 w로 업데이트
- l의 h와 out_h를 h로 업데이트
- l의 outputs를 w, h, out_c의 곱으로 업데이트
- l의 inputs를 outputs와 같게 업데이트
- l의 delta 메모리를 outputs * batch 크기만큼 재할당
- l의 output 메모리를 outputs * batch 크기만큼 재할당
설명:
- 이 함수는 shortcut layer의 크기를 조정하는 역할을 한다.
- shortcut layer는 input과 output의 크기가 같아야 하기 때문에 l의 w와 out_w, h와 out_h가 같은지 확인하고 같지 않으면 에러를 발생시킨다.
- 그 후 w와 h로 각각 크기를 조정해주고, outputs와 inputs를 업데이트한다.
- 마지막으로, delta와 output 메모리를 새로운 outputs * batch 크기로 재할당한다.
make_shortcut_layer
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
layer make_shortcut_layer(int batch, int index, int w, int h, int c, int w2, int h2, int c2)
{
fprintf(stderr, "res %3d %4d x%4d x%4d -> %4d x%4d x%4d\n",index, w2,h2,c2, w,h,c);
layer l = {0};
l.type = SHORTCUT;
l.batch = batch;
l.w = w2;
l.h = h2;
l.c = c2;
l.out_w = w;
l.out_h = h;
l.out_c = c;
l.outputs = w*h*c;
l.inputs = l.outputs;
l.index = index;
l.delta = calloc(l.outputs*batch, sizeof(float));
l.output = calloc(l.outputs*batch, sizeof(float));;
l.forward = forward_shortcut_layer;
l.backward = backward_shortcut_layer;
return l;
}
함수 이름: make_shortcut_layer
입력:
- batch: 배치 크기
- index: 레이어 인덱스
- w: 입력 이미지 가로 크기
- h: 입력 이미지 세로 크기
- c: 입력 이미지 채널 수
- w2: shortcut 연결되는 레이어의 가로 크기
- h2: shortcut 연결되는 레이어의 세로 크기
- c2: shortcut 연결되는 레이어의 채널 수
동작:
- shortcut 레이어를 생성하고, 필드 값들을 초기화한다.
설명:
- shortcut 레이어는 skip connection을 구현하는 데 사용되는 레이어이다.
- 입력 이미지의 크기와 shortcut으로 연결되는 레이어의 출력 크기가 같은 경우에 사용된다.
- 출력 크기는 입력 이미지의 크기와 같고, 입력 이미지와 shortcut으로 연결되는 레이어의 출력을 더한 결과가 출력값이 된다.
- l.delta와 l.output은 모두 출력값을 저장하는 배열이다.
- l.forward와 l.backward는 해당 레이어에서의 순전파와 역전파 연산을 수행하는 함수 포인터이다.
- fprintf 함수를 사용하여 현재 shortcut 레이어의 정보를 출력한다.
This post is licensed under CC BY 4.0 by the author.