주어진 문자열 포인터 data에서 쉼표로 구분된 각 데이터를 분석하여 float 배열 포인터 a에 저장한다.
n은 분석할 데이터 개수로, n보다 적은 개수의 데이터가 있을 경우 남은 배열 요소는 0으로 초기화된다.
설명:
parse_data 함수는 CSV(comma-separated values) 형식의 문자열 데이터를 분석하여 float 배열로 저장하는 함수이다. 입력으로는 분석할 데이터가 담긴 문자열 포인터 data와 이를 저장할 float 배열 포인터 a, 그리고 분석할 데이터 개수를 의미하는 정수형 변수 n을 받는다.
함수는 문자열 포인터 curr을 처음에는 data로 초기화하고, 다음으로 분석할 데이터를 가리키는 문자열 포인터 next를 curr로 초기화한다. done 변수는 모든 데이터를 분석했는지 여부를 나타내는 변수로, 처음에는 false로 초기화한다.
반복문을 이용하여 n개의 데이터를 분석한다. 분석할 데이터가 더 이상 없으면 done 변수를 true로 변경하고 반복문을 빠져나온다. 현재 분석하고 있는 데이터가 끝나는 위치(next)를 찾아, 해당 위치에 널 문자('\0')를 넣어 문자열을 종료시킨다. curr에는 분석한 데이터를 저장하기 위해 해당 데이터의 시작 위치를 가리키는 next의 다음 위치를 저장한다.
sscanf 함수를 이용하여 curr이 가리키는 위치에서부터 다음 널 문자 전까지의 문자열을 float 값으로 변환하여 a 배열에 저장한다. 분석한 데이터의 개수가 n개보다 적을 경우 남은 배열 요소는 0으로 초기화된다.
parse_local
local_layer parse_local(list *options, size_params params)
{
int n = option_find_int(options, "filters",1);
int size = option_find_int(options, "size",1);
int stride = option_find_int(options, "stride",1);
int pad = option_find_int(options, "pad",0);
char *activation_s = option_find_str(options, "activation", "logistic");
ACTIVATION activation = get_activation(activation_s);
int batch,h,w,c;
h = params.h;
w = params.w;
c = params.c;
batch=params.batch;
if(!(h && w && c)) error("Layer before local layer must output image.");
local_layer layer = make_local_layer(batch,h,w,c,n,size,stride,pad,activation);
return layer;
}
함수 이름: parse_local
입력:
options: 리스트 포인터, 레이어의 설정 정보
params: size_params 구조체, 레이어 입력 이미지의 크기 정보를 가지고 있음
동작:
options에서 필터 수(n), 필터 크기(size), 스트라이드(stride), 패딩(pad), 활성화 함수(activation) 정보를 파싱하여 local_layer 구조체를 생성하고 반환함
batch, h, w, c는 params에서 가져옴
h, w, c가 0이면 에러를 발생시킴
설명:
local_layer 구조체는 로컬 레이어를 표현하기 위한 구조체로, 필터 수(n), 필터 크기(size), 스트라이드(stride), 패딩(pad), 활성화 함수(activation) 등의 정보를 가지고 있음
make_local_layer 함수를 이용하여 local_layer 구조체를 생성함
option_find_int, option_find_str 함수를 이용하여 options에서 필요한 정보를 파싱함
get_activation 함수를 이용하여 activation_s 문자열에 해당하는 활성화 함수를 가져옴
local_layer 이전 레이어가 이미지를 출력하는 레이어인지 확인하기 위해 params에서 h, w, c 정보를 가져옴
h, w, c가 0이면 이미지를 출력하는 레이어가 아니므로 에러를 발생시킴
parse_deconvolutional
layer parse_deconvolutional(list *options, size_params params)
{
int n = option_find_int(options, "filters",1);
int size = option_find_int(options, "size",1);
int stride = option_find_int(options, "stride",1);
char *activation_s = option_find_str(options, "activation", "logistic");
ACTIVATION activation = get_activation(activation_s);
int batch,h,w,c;
h = params.h;
w = params.w;
c = params.c;
batch=params.batch;
if(!(h && w && c)) error("Layer before deconvolutional layer must output image.");
int batch_normalize = option_find_int_quiet(options, "batch_normalize", 0);
int pad = option_find_int_quiet(options, "pad",0);
int padding = option_find_int_quiet(options, "padding",0);
if(pad) padding = size/2;
layer l = make_deconvolutional_layer(batch,h,w,c,n,size,stride,padding, activation, batch_normalize, params.net->adam);
return l;
}
함수 이름: parse_deconvolutional
입력:
list *options (설정 리스트)
size_params params (크기 정보 구조체)
동작:
설정 리스트로부터 디컨볼루션 레이어를 파싱하여 생성한다.
설명:
설정 리스트로부터 필터 수, 커널 크기, 스트라이드, 활성화 함수 등을 파싱한다.
크기 정보 구조체에서 입력 이미지의 높이, 너비, 채널, 배치 크기 등을 가져온다.
입력 이미지의 높이, 너비, 채널이 정상적으로 출력되었는지 확인한다.
배치 정규화, 패딩, 패딩 크기 등의 옵션을 파싱한다.
make_deconvolutional_layer 함수를 호출하여 디컨볼루션 레이어를 생성하고 반환한다.
parse_convolutional
convolutional_layer parse_convolutional(list *options, size_params params)
{
int n = option_find_int(options, "filters",1);
int size = option_find_int(options, "size",1);
int stride = option_find_int(options, "stride",1);
int pad = option_find_int_quiet(options, "pad",0);
int padding = option_find_int_quiet(options, "padding",0);
int groups = option_find_int_quiet(options, "groups", 1);
if(pad) padding = size/2;
char *activation_s = option_find_str(options, "activation", "logistic");
ACTIVATION activation = get_activation(activation_s);
int batch,h,w,c;
h = params.h;
w = params.w;
c = params.c;
batch=params.batch;
if(!(h && w && c)) error("Layer before convolutional layer must output image.");
int batch_normalize = option_find_int_quiet(options, "batch_normalize", 0);
int binary = option_find_int_quiet(options, "binary", 0);
int xnor = option_find_int_quiet(options, "xnor", 0);
convolutional_layer layer = make_convolutional_layer(batch,h,w,c,n,groups,size,stride,padding,activation, batch_normalize, binary, xnor, params.net->adam);
layer.flipped = option_find_int_quiet(options, "flipped", 0);
layer.dot = option_find_float_quiet(options, "dot", 0);
return layer;
}
함수 이름: parse_convolutional
입력:
options: 컨볼루션 레이어를 파싱하기 위한 설정 값들이 들어있는 링크드 리스트
params: 네트워크의 사이즈 매개변수를 저장한 구조체
동작:
설정값들을 파싱하여 컨볼루션 레이어를 생성합니다.
파싱된 설정값들을 이용하여 컨볼루션 레이어의 필터 수, 필터 크기, 스트라이드, 패딩 등을 설정합니다.
컨볼루션 레이어에 적용할 활성화 함수를 설정합니다.
컨볼루션 레이어를 생성하고 반환합니다.
설명:
n: 필터의 개수입니다.
size: 필터의 크기입니다.
stride: 필터의 스트라이드입니다.
pad: 필터 패딩을 의미합니다. 이 값이 1이면 padding 값은 필터 크기의 절반으로 설정됩니다.
padding: 패딩 값입니다.
groups: 그룹 수입니다.
activation_s: 레이어의 활성화 함수입니다. "logistic"을 디폴트로 합니다.
noloss 옵션은 softmax 손실 계산에 영향을 미치며, spatial 옵션은 출력 크기에 대한 공간 가중치를 적용한다.
parse_yolo_mask
int *parse_yolo_mask(char *a, int *num)
{
int *mask = 0;
if(a){
int len = strlen(a);
int n = 1;
int i;
for(i = 0; i < len; ++i){
if (a[i] == ',') ++n;
}
mask = calloc(n, sizeof(int));
for(i = 0; i < n; ++i){
int val = atoi(a);
mask[i] = val;
a = strchr(a, ',')+1;
}
*num = n;
}
return mask;
}
함수 이름: parse_yolo_mask
입력:
char* a: YOLO 마스크 문자열
int* num: 마스크 배열의 요소 수를 저장할 포인터
동작:
YOLO 마스크 문자열을 구문 분석하여 정수 배열을 생성하고 반환
문자열에서 구분 기호(쉼표)를 사용하여 정수 배열의 각 요소를 구성
num 포인터를 통해 생성된 배열의 요소 수를 반환
설명:
이 함수는 YOLO 마스크 문자열을 입력 받아 해당 문자열에서 구분 기호(쉼표)를 사용하여 정수 배열을 생성하고 반환합니다.
이 함수는 문자열을 구문 분석하여 배열의 각 요소를 구성하기 위해 atoi 함수를 사용합니다.
문자열에서 구분 기호를 사용하여 각 요소를 구분합니다.
함수는 생성된 배열의 요소 수를 num 포인터를 통해 반환합니다.
parse_yolo
layer parse_yolo(list *options, size_params params)
{
int classes = option_find_int(options, "classes", 20);
int total = option_find_int(options, "num", 1);
int num = total;
char *a = option_find_str(options, "mask", 0);
int *mask = parse_yolo_mask(a, &num);
layer l = make_yolo_layer(params.batch, params.w, params.h, num, total, mask, classes);
assert(l.outputs == params.inputs);
l.max_boxes = option_find_int_quiet(options, "max",90);
l.jitter = option_find_float(options, "jitter", .2);
l.ignore_thresh = option_find_float(options, "ignore_thresh", .5);
l.truth_thresh = option_find_float(options, "truth_thresh", 1);
l.random = option_find_int_quiet(options, "random", 0);
char *map_file = option_find_str(options, "map", 0);
if (map_file) l.map = read_map(map_file);
a = option_find_str(options, "anchors", 0);
if(a){
int len = strlen(a);
int n = 1;
int i;
for(i = 0; i < len; ++i){
if (a[i] == ',') ++n;
}
for(i = 0; i < n; ++i){
float bias = atof(a);
l.biases[i] = bias;
a = strchr(a, ',')+1;
}
}
return l;
}
함수 이름: parse_yolo
입력:
options (list 포인터)
params (size_params 타입)
동작:
YOLO 레이어를 파싱하여 레이어를 만들고 반환합니다.
설명:
classes (int 타입): 클래스 수를 나타냅니다.
total (int 타입): Anchor Box의 수를 나타냅니다.
num (int 타입): Anchor Box의 수를 나타냅니다.
a (char 포인터): Mask 값으로, Anchor Box를 적용할 레이어를 선택합니다.
mask (int 포인터): Mask 값으로 선택된 Anchor Box를 저장합니다.
l (layer 타입): 만들어진 YOLO 레이어입니다.
max_boxes (int 타입): 최대 박스 수를 나타냅니다.
jitter (float 타입): Jitter 값으로, 이미지의 위치를 무작위로 이동시킵니다.
ignore_thresh (float 타입): Ignore Threshold 값으로, 박스와의 IoU 값이 이 값보다 작으면 무시합니다.
truth_thresh (float 타입): Truth Threshold 값으로, ground truth와 예측 값의 IoU 값이 이 값보다 크면 해당 예측 값을 ground truth로 취급합니다.
random (int 타입): Random 값으로, 이미지를 무작위로 변환할 때 사용하는 시드(seed) 값입니다.
flip(int): crop 영상을 수평으로 뒤집을 것인지 여부 (0: 안 뒤집음, 1: 뒤집음)
angle(float): crop 영상 회전 각도 (라디안 단위)
saturation(float): crop 영상의 채도 조절 (1이면 변경 없음)
exposure(float): crop 영상의 노출 조절 (1이면 변경 없음)
noadjust(int): crop 영상의 라벨과 경계상자를 자동으로 조절하지 않음 (0: 자동 조절, 1: 자동 조절 안 함)
shift(float): crop 영상의 RGB 색상 채널 값에 더해지는 값 (RGB 값이 0~1 범위를 벗어나지 않도록 제한해야 함)
parse_reorg
layer parse_reorg(list *options, size_params params)
{
int stride = option_find_int(options, "stride",1);
int reverse = option_find_int_quiet(options, "reverse",0);
int flatten = option_find_int_quiet(options, "flatten",0);
int extra = option_find_int_quiet(options, "extra",0);
int batch,h,w,c;
h = params.h;
w = params.w;
c = params.c;
batch=params.batch;
if(!(h && w && c)) error("Layer before reorg layer must output image.");
layer layer = make_reorg_layer(batch,w,h,c,stride,reverse, flatten, extra);
return layer;
}
함수 이름: parse_reorg
입력:
options (list 포인터)
params (size_params 구조체)
동작:
options에서 "stride", "reverse", "flatten", "extra"에 해당하는 정수 값을 찾아서, make_reorg_layer 함수를 사용하여 reorg layer를 만들고 반환합니다.
설명:
입력으로 options와 params를 받아, reorg layer를 생성하여 반환하는 함수입니다.
options에서는 stride, reverse, flatten, extra에 대한 값을 찾아서 해당 값들을 이용하여 reorg layer를 생성합니다.
params에서는 입력 이미지의 높이, 너비, 채널 수, 배치 크기를 받아옵니다.
parse_maxpool
maxpool_layer parse_maxpool(list *options, size_params params)
{
int stride = option_find_int(options, "stride",1);
int size = option_find_int(options, "size",stride);
int padding = option_find_int_quiet(options, "padding", size-1);
int batch,h,w,c;
h = params.h;
w = params.w;
c = params.c;
batch=params.batch;
if(!(h && w && c)) error("Layer before maxpool layer must output image.");
maxpool_layer layer = make_maxpool_layer(batch,h,w,c,size,stride,padding);
return layer;
}
함수 이름: parse_maxpool
입력:
options (list 포인터): 파싱할 maxpool 레이어의 옵션 리스트
params (size_params): maxpool 레이어의 입력 이미지 크기 및 배치 크기 정보가 담긴 size_params 구조체
동작:
파싱된 옵션을 기반으로 maxpool 레이어를 생성하고 반환함
설명:
입력 이미지에 대한 maxpool 연산을 수행하는 레이어를 생성하고 반환하는 함수입니다.
옵션 리스트에서 stride, size, padding 값을 읽어와 maxpool 레이어를 생성합니다.
입력 이미지 크기와 배치 크기 정보를 포함하는 size_params 구조체를 사용합니다.
반환값은 maxpool_layer 구조체입니다.
parse_avgpool
avgpool_layer parse_avgpool(list *options, size_params params)
{
int batch,w,h,c;
w = params.w;
h = params.h;
c = params.c;
batch=params.batch;
if(!(h && w && c)) error("Layer before avgpool layer must output image.");
avgpool_layer layer = make_avgpool_layer(batch,w,h,c);
return layer;
}
함수 이름: parse_avgpool
입력:
options (list): 옵션 리스트
params (size_params): 사이즈 파라미터 (w, h, c, batch)
동작:
입력으로 받은 사이즈 파라미터를 이용하여 avgpool_layer를 생성하고 반환한다.
설명:
이 함수는 options와 params를 입력으로 받아 avgpool_layer를 생성하는 함수이다.
함수 내부에서는 사이즈 파라미터를 이용하여 avgpool_layer를 만들고, 이를 반환한다.
만약 h, w, c가 0이라면 "Layer before avgpool layer must output image." 에러를 발생시킨다.
parse_upsample 함수는 옵션에서 지정한 stride 값을 사용하여 입력 레이어를 업샘플링하는 레이어를 생성하고 반환하는 함수이다.
options 리스트는 사용자가 지정한 옵션들을 저장하고 있으며, params는 입력 레이어의 파라미터를 저장한 구조체이다.
net은 전체 네트워크 구조체를 가리키는 포인터이다.
업샘플링 레이어를 생성하기 위해 make_upsample_layer 함수를 사용한다. 이때, params에서 읽어온 입력 레이어의 파라미터와 사용자가 지정한 stride 값을 사용한다.
l.scale은 사용자가 지정한 scale 값을 저장한다. 만약, 옵션에서 scale 값을 지정하지 않았으면 1.0으로 초기화된다.
생성된 업샘플링 레이어를 반환한다.
parse_route
route_layer parse_route(list *options, size_params params, network *net)
{
char *l = option_find(options, "layers");
int len = strlen(l);
if(!l) error("Route Layer must specify input layers");
int n = 1;
int i;
for(i = 0; i < len; ++i){
if (l[i] == ',') ++n;
}
int *layers = calloc(n, sizeof(int));
int *sizes = calloc(n, sizeof(int));
for(i = 0; i < n; ++i){
int index = atoi(l);
l = strchr(l, ',')+1;
if(index < 0) index = params.index + index;
layers[i] = index;
sizes[i] = net->layers[index].outputs;
}
int batch = params.batch;
route_layer layer = make_route_layer(batch, n, layers, sizes);
convolutional_layer first = net->layers[layers[0]];
layer.out_w = first.out_w;
layer.out_h = first.out_h;
layer.out_c = first.out_c;
for(i = 1; i < n; ++i){
int index = layers[i];
convolutional_layer next = net->layers[index];
if(next.out_w == first.out_w && next.out_h == first.out_h){
layer.out_c += next.out_c;
}else{
layer.out_h = layer.out_w = layer.out_c = 0;
}
}
return layer;
}
함수 이름: parse_route
입력:
options: 파라미터 설정 정보를 담은 리스트
params: size_params 구조체 변수
net: 네트워크 구조체 변수
동작:
라우팅 레이어를 파싱하여 레이어를 생성하고 반환한다.
설명:
"layers" 파라미터를 이용해 입력 레이어를 결정한다.
입력 레이어의 인덱스와 출력 크기를 저장하고, 이 정보를 이용하여 라우팅 레이어를 생성한다.
입력 레이어들 중 가장 처음 입력 레이어의 출력 크기로 라우팅 레이어의 출력 크기를 설정한다.
나머지 입력 레이어들의 출력 크기가 첫 번째 입력 레이어의 출력 크기와 일치하면, 출력 채널 수를 추가한다. 만약 일치하지 않으면, 출력 크기를 0으로 설정한다.
생성한 라우팅 레이어를 반환한다.
get_policy
typedef enum {
CONSTANT, STEP, EXP, POLY, STEPS, SIG, RANDOM
} learning_rate_policy;
learning_rate_policy get_policy(char *s)
{
if (strcmp(s, "random")==0) return RANDOM;
if (strcmp(s, "poly")==0) return POLY;
if (strcmp(s, "constant")==0) return CONSTANT;
if (strcmp(s, "step")==0) return STEP;
if (strcmp(s, "exp")==0) return EXP;
if (strcmp(s, "sigmoid")==0) return SIG;
if (strcmp(s, "steps")==0) return STEPS;
fprintf(stderr, "Couldn't find policy %s, going with constant\n", s);
return CONSTANT;
}
함수 이름: get_policy
입력:
char* s (문자열 포인터)
동작:
주어진 문자열 s가 나타내는 학습률 스케줄링 정책을 반환함
설명:
이 함수는 learning_rate_policy 열거형 타입을 사용하여 주어진 문자열 s가 나타내는 학습률 스케줄링 정책을 반환합니다.
문자열 s가 "random", "poly", "constant", "step", "exp", "sigmoid", "steps" 중 하나인 경우 해당 정책을 반환하고, 그렇지 않으면 "Couldn't find policy %s, going with constant" 메시지를 출력하고 기본값으로 CONSTANT를 반환합니다.
이 때, 전치 플래그(transpose)가 참이면 가중치를 전치한다. 또한 배치 정규화(batch normalization)를 사용하는 경우, 스케일(scale), 롤링 평균(rolling mean), 롤링 분산(rolling variance) 정보도 파일에서 읽어온다.
설명:
완전 연결 레이어의 편향과 가중치 정보를 파일에서 읽어오는 함수이다.
이 함수는 darknet 딥러닝 프레임워크의 구현체에서 사용되며, 파라미터로 전달된 layer 구조체에 편향과 가중치 정보를 채운다.
이 함수는 load_network 함수에서 호출되어, 모델의 파라미터를 파일에서 읽어오는 역할을 한다.
전치 플래그가 참이면 가중치를 전치하여 저장하며, 배치 정규화를 사용하는 경우, 해당 정보도 함께 읽어오는 역할을 한다.
transpose_matrix
void transpose_matrix(float *a, int rows, int cols)
{
float *transpose = calloc(rows*cols, sizeof(float));
int x, y;
for(x = 0; x < rows; ++x){
for(y = 0; y < cols; ++y){
transpose[y*rows + x] = a[x*cols + y];
}
}
memcpy(a, transpose, rows*cols*sizeof(float));
free(transpose);
}