Copy #include "darknet.h"
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
extern void predict_classifier(char *datacfg, char *cfgfile, char *weightfile, char *filename, int top);
extern void test_detector(char *datacfg, char *cfgfile, char *weightfile, char *filename, float thresh, float hier_thresh, char *outfile, int fullscreen);
extern void run_yolo(int argc, char **argv);
extern void run_detector(int argc, char **argv);
extern void run_coco(int argc, char **argv);
extern void run_nightmare(int argc, char **argv);
extern void run_classifier(int argc, char **argv);
extern void run_regressor(int argc, char **argv);
extern void run_segmenter(int argc, char **argv);
extern void run_isegmenter(int argc, char **argv);
extern void run_char_rnn(int argc, char **argv);
extern void run_tag(int argc, char **argv);
extern void run_cifar(int argc, char **argv);
extern void run_go(int argc, char **argv);
extern void run_art(int argc, char **argv);
extern void run_super(int argc, char **argv);
extern void run_lsd(int argc, char **argv);
average
Copy void average(int argc, char *argv[])
{
char *cfgfile = argv[2];
char *outfile = argv[3];
gpu_index = -1;
network *net = parse_network_cfg(cfgfile);
network *sum = parse_network_cfg(cfgfile);
char *weightfile = argv[4];
load_weights(sum, weightfile);
int i, j;
int n = argc - 5;
for(i = 0; i < n; ++i){
weightfile = argv[i+5];
load_weights(net, weightfile);
for(j = 0; j < net->n; ++j){
layer l = net->layers[j];
layer out = sum->layers[j];
if(l.type == CONVOLUTIONAL){
int num = l.n*l.c*l.size*l.size;
axpy_cpu(l.n, 1, l.biases, 1, out.biases, 1);
axpy_cpu(num, 1, l.weights, 1, out.weights, 1);
if(l.batch_normalize){
axpy_cpu(l.n, 1, l.scales, 1, out.scales, 1);
axpy_cpu(l.n, 1, l.rolling_mean, 1, out.rolling_mean, 1);
axpy_cpu(l.n, 1, l.rolling_variance, 1, out.rolling_variance, 1);
}
}
if(l.type == CONNECTED){
axpy_cpu(l.outputs, 1, l.biases, 1, out.biases, 1);
axpy_cpu(l.outputs*l.inputs, 1, l.weights, 1, out.weights, 1);
}
}
}
n = n+1;
for(j = 0; j < net->n; ++j){
layer l = sum->layers[j];
if(l.type == CONVOLUTIONAL){
int num = l.n*l.c*l.size*l.size;
scal_cpu(l.n, 1./n, l.biases, 1);
scal_cpu(num, 1./n, l.weights, 1);
if(l.batch_normalize){
scal_cpu(l.n, 1./n, l.scales, 1);
scal_cpu(l.n, 1./n, l.rolling_mean, 1);
scal_cpu(l.n, 1./n, l.rolling_variance, 1);
}
}
if(l.type == CONNECTED){
scal_cpu(l.outputs, 1./n, l.biases, 1);
scal_cpu(l.outputs*l.inputs, 1./n, l.weights, 1);
}
}
save_weights(sum, outfile);
}
함수 이름: average
입력:
argc (int 타입): 프로그램 실행 시 전달되는 인자의 개수
argv (char* 타입): 프로그램 실행 시 전달되는 인자들의 배열
argv[2] (char* 타입): configuration 파일의 경로
argv[3] (char* 타입): 결과 파일의 경로
argv[4] (char* 타입): 가중치(weight) 파일의 경로
argv[5]부터 (char* 타입): 가중치(weight) 파일들의 경로들
동작:
configuration 파일(cfgfile)을 파싱하여 network 구조체를 만든다.
결과를 저장할 network 구조체(sum)도 만든다. (cfgfile로부터 파싱한 것과 같은 구조)
argv[4]를 가중치 파일로 읽어들여 sum에 저장한다.
argv[5]부터 끝까지 반복하며 가중치 파일을 읽어들인 후, sum과 더한다.
sum을 n+1로 나눠 평균값을 구한다. (n은 가중치 파일의 개수)
설명:
이 함수는 딥러닝 모델의 가중치(weight) 파일들을 입력으로 받아, 이들의 평균값을 구한 후, 하나의 가중치 파일로 저장하는 기능을 수행한다.
이 함수는 Darknet 딥러닝 프레임워크의 일부분으로, C 언어로 작성되었다.
이 함수는 CLI(Command-Line Interface) 환경에서 실행되며, argc와 argv를 통해 프로그램 실행 시 전달되는 인자들을 받는다.
이 함수는 입력으로 받은 가중치 파일들의 평균을 구하므로, 모델의 성능을 평가하는 데에 유용하게 사용될 수 있다.
numops
Copy long numops(network *net)
{
int i;
long ops = 0;
for(i = 0; i < net->n; ++i){
layer l = net->layers[i];
if(l.type == CONVOLUTIONAL){
ops += 2l * l.n * l.size*l.size*l.c/l.groups * l.out_h*l.out_w;
} else if(l.type == CONNECTED){
ops += 2l * l.inputs * l.outputs;
} else if (l.type == RNN){
ops += 2l * l.input_layer->inputs * l.input_layer->outputs;
ops += 2l * l.self_layer->inputs * l.self_layer->outputs;
ops += 2l * l.output_layer->inputs * l.output_layer->outputs;
} else if (l.type == GRU){
ops += 2l * l.uz->inputs * l.uz->outputs;
ops += 2l * l.uh->inputs * l.uh->outputs;
ops += 2l * l.ur->inputs * l.ur->outputs;
ops += 2l * l.wz->inputs * l.wz->outputs;
ops += 2l * l.wh->inputs * l.wh->outputs;
ops += 2l * l.wr->inputs * l.wr->outputs;
} else if (l.type == LSTM){
ops += 2l * l.uf->inputs * l.uf->outputs;
ops += 2l * l.ui->inputs * l.ui->outputs;
ops += 2l * l.ug->inputs * l.ug->outputs;
ops += 2l * l.uo->inputs * l.uo->outputs;
ops += 2l * l.wf->inputs * l.wf->outputs;
ops += 2l * l.wi->inputs * l.wi->outputs;
ops += 2l * l.wg->inputs * l.wg->outputs;
ops += 2l * l.wo->inputs * l.wo->outputs;
}
}
return ops;
}
함수 이름: numops
입력:
network 구조체 포인터: 네트워크 구조를 저장하는 구조체에 대한 포인터입니다.
동작:
네트워크에 있는 모든 레이어의 총 연산 횟수를 계산하여 반환합니다.
설명:
network 구조체는 Darknet 라이브러리에서 사용하는 네트워크 구조를 저장합니다.
레이어의 타입에 따라 연산 횟수가 다르기 때문에, CONVOLUTIONAL, CONNECTED, RNN, GRU, LSTM 레이어 타입에 따라 계산을 수행합니다.
CONVOLUTIONAL 레이어의 경우, 컨볼루션 연산과 덧셈 연산이 이루어지므로, 2 * 필터 총 원소 수 * 출력 크기 만큼의 연산 횟수가 더해집니다.
CONNECTED 레이어의 경우, 행렬 곱셈과 덧셈 연산이 이루어지므로, 2 * 입력 크기 * 출력 크기 만큼의 연산 횟수가 더해집니다.
RNN, GRU, LSTM 레이어의 경우, 입력 게이트, 출력 게이트, 삭제 게이트와 같은 각 게이트마다 연산 횟수를 계산합니다. 이들 레이어의 총 연산 횟수는 각각 3개, 6개, 8개 입니다.
최종적으로 모든 레이어의 연산 횟수를 더한 값을 반환합니다.
speed
Copy void speed(char *cfgfile, int tics)
{
if (tics == 0) tics = 1000;
network *net = parse_network_cfg(cfgfile);
set_batch_network(net, 1);
int i;
double time=what_time_is_it_now();
image im = make_image(net->w, net->h, net->c*net->batch);
for(i = 0; i < tics; ++i){
network_predict(net, im.data);
}
double t = what_time_is_it_now() - time;
long ops = numops(net);
printf("\n%d evals, %f Seconds\n", tics, t);
printf("Floating Point Operations: %.2f Bn\n", (float)ops/1000000000.);
printf("FLOPS: %.2f Bn\n", (float)ops/1000000000.*tics/t);
printf("Speed: %f sec/eval\n", t/tics);
printf("Speed: %f Hz\n", tics/t);
}
함수 이름: speed 입력:
동작:
-m주어진 설정 파일(cfgfile)을 파싱하여 네트워크를 생성하고, 입력 이미지를 생성한 후 반복 횟수(tics)만큼 네트워크에 입력을 주어 예측을 수행합니다.
그리고 수행 시간과 부동 소수점 연산 횟수(Floating Point Operations)를 계산하여 출력합니다.
설명:
이 함수는 입력 이미지를 생성한 후 반복 횟수만큼 네트워크를 실행하여 처리 속도와 연산량(FLOPS)을 출력합니다.
먼저, 설정 파일(cfgfile)을 파싱하여 네트워크를 생성한 다음, 입력 이미지를 만듭니다.
그리고, 반복 횟수(tics)만큼 네트워크에 입력을 주어 예측을 수행합니다. 이 때, 처리에 걸린 시간과 부동 소수점 연산 횟수를 계산합니다.
마지막으로, 이 정보들을 출력합니다. 출력 정보에는 총 수행 시간, 부동 소수점 연산 횟수, FLOPS, 처리 속도(sec/eval), 처리 속도(Hz)가 포함됩니다.
operations
Copy void operations(char *cfgfile)
{
gpu_index = -1;
network *net = parse_network_cfg(cfgfile);
long ops = numops(net);
printf("Floating Point Operations: %ld\n", ops);
printf("Floating Point Operations: %.2f Bn\n", (float)ops/1000000000.);
}
함수 이름: operations
입력:
cfgfile (문자열 포인터): 네트워크 구성 파일 경로
동작:
주어진 네트워크 구성 파일을 파싱하여 해당 네트워크가 수행하는 총 부동 소수점 연산 횟수를 계산하고 출력합니다.
설명:
주어진 cfgfile을 파싱하여 네트워크를 생성합니다.
numops 함수를 사용하여 해당 네트워크가 수행하는 총 부동 소수점 연산 횟수를 계산합니다.
계산된 부동 소수점 연산 횟수를 출력합니다. 출력할 때, 단위를 10억(Billion)으로 나누어 GFLOPs(Giga Floating Point Operations Per Second) 단위로 출력합니다.
oneoff
Copy void oneoff(char *cfgfile, char *weightfile, char *outfile)
{
gpu_index = -1;
network *net = parse_network_cfg(cfgfile);
int oldn = net->layers[net->n - 2].n;
int c = net->layers[net->n - 2].c;
scal_cpu(oldn*c, .1, net->layers[net->n - 2].weights, 1);
scal_cpu(oldn, 0, net->layers[net->n - 2].biases, 1);
net->layers[net->n - 2].n = 11921;
net->layers[net->n - 2].biases += 5;
net->layers[net->n - 2].weights += 5*c;
if(weightfile){
load_weights(net, weightfile);
}
net->layers[net->n - 2].biases -= 5;
net->layers[net->n - 2].weights -= 5*c;
net->layers[net->n - 2].n = oldn;
printf("%d\n", oldn);
layer l = net->layers[net->n - 2];
copy_cpu(l.n/3, l.biases, 1, l.biases + l.n/3, 1);
copy_cpu(l.n/3, l.biases, 1, l.biases + 2*l.n/3, 1);
copy_cpu(l.n/3*l.c, l.weights, 1, l.weights + l.n/3*l.c, 1);
copy_cpu(l.n/3*l.c, l.weights, 1, l.weights + 2*l.n/3*l.c, 1);
*net->seen = 0;
save_weights(net, outfile);
}
함수 이름: oneoff
입력:
cfgfile (char*): 네트워크 구성 파일 경로
weightfile (char*): 가중치 파일 경로 (옵션)
outfile (char*): 저장할 가중치 파일 경로
동작:
주어진 네트워크 구성 파일(cfgfile)을 파싱하여 네트워크(net)를 생성하고, 이를 이용하여 가중치를 초기화한 후 일회성(one-off)으로 훈련시킨 결과를 저장한다.
이 과정에서 가중치 파일(weightfile)을 제공하면 해당 파일에서 가중치를 로드하여 초기화하고, outfile에서 지정한 경로에 최종 가중치 파일을 저장한다.
설명:
주어진 네트워크 구성 파일(cfgfile)을 파싱하여 네트워크(net)를 생성한다.
oldn은 net의 뒤에서 두 번째 레이어의 뉴런 수이며, c는 채널 수이다. 이 레이어의 가중치와 편향을 0.1과 0으로 초기화한다.
net의 뒤에서 두 번째 레이어의 뉴런 수를 11921로 변경한다.
net의 뒤에서 두 번째 레이어의 가중치와 편향에 대한 포인터를 각각 5와 5*c만큼 옮긴다.
weightfile이 주어진 경우 해당 파일에서 가중치를 로드하여 초기화한다.
가중치와 편향에 대한 포인터를 원래 위치로 되돌린다.
net의 뒤에서 두 번째 레이어의 뉴런 수를 이전 값으로 복원한다.
l은 net의 뒤에서 두 번째 레이어이며, 이 레이어의 1/3 지점과 2/3 지점에서의 편향과 가중치 값을 서로 복사한다.
최종 가중치 파일을 outfile에서 지정한 경로에 저장한다.
oneoff2
Copy void oneoff2(char *cfgfile, char *weightfile, char *outfile, int l)
{
gpu_index = -1;
network *net = parse_network_cfg(cfgfile);
if(weightfile){
load_weights_upto(net, weightfile, 0, net->n);
load_weights_upto(net, weightfile, l, net->n);
}
*net->seen = 0;
save_weights_upto(net, outfile, net->n);
}
함수 이름: oneoff2
입력:
char *weightfile (가중치 파일 경로)
char *outfile (저장할 가중치 파일 경로)
동작:
주어진 구성 파일(cfgfile)을 사용하여 네트워크를 만들고, 주어진 가중치 파일(weightfile)에서 가중치를 로드합니다.
그리고 로드한 가중치 중 l 번째 레이어까지의 가중치를 사용하여 네트워크를 업데이트합니다.
마지막으로 변경된 가중치를 주어진 파일(outfile)에 저장합니다.
설명:
parse_network_cfg 함수는 주어진 구성 파일(cfgfile)에서 네트워크를 만듭니다.
load_weights_upto 함수는 주어진 가중치 파일(weightfile)에서 가중치를 로드합니다. 마지막 인자로 지정한 레이어까지의 가중치를 로드합니다.
save_weights_upto 함수는 변경된 가중치를 주어진 파일(outfile)에 저장합니다. 마지막 인자로 지정한 레이어까지의 가중치를 저장합니다.
partial
Copy void partial(char *cfgfile, char *weightfile, char *outfile, int max)
{
gpu_index = -1;
network *net = load_network(cfgfile, weightfile, 1);
save_weights_upto(net, outfile, max);
}
함수 이름: partial
입력:
char *cfgfile: 네트워크 구성 파일 경로
char *weightfile: 가중치 파일 경로
char *outfile: 저장될 가중치 파일 경로
동작:
cfgfile과 weightfile을 사용하여 네트워크를 로드한다.
max 레이어까지의 가중치만 저장하여 outfile에 저장한다.
설명:
주어진 cfgfile과 weightfile을 사용하여 네트워크를 로드한 후, max 레이어까지의 가중치만 저장하여 outfile에 저장하는 함수이다.
이때, gpu_index는 -1로 설정되며, load_network 함수를 사용하여 네트워크를 로드하고, save_weights_upto 함수를 사용하여 일부 레이어의 가중치만 저장한다.
print_weights
Copy void print_weights(char *cfgfile, char *weightfile, int n)
{
gpu_index = -1;
network *net = load_network(cfgfile, weightfile, 1);
layer l = net->layers[n];
int i, j;
//printf("[");
for(i = 0; i < l.n; ++i){
//printf("[");
for(j = 0; j < l.size*l.size*l.c; ++j){
//if(j > 0) printf(",");
printf("%g ", l.weights[i*l.size*l.size*l.c + j]);
}
printf("\n");
//printf("]%s\n", (i == l.n-1)?"":",");
}
//printf("]");
}
함수 이름: print_weights
입력:
char *cfgfile (네트워크 구성 파일 경로)
char *weightfile (가중치 파일 경로)
동작:
주어진 네트워크 구성 파일과 가중치 파일을 로드하고, 지정된 레이어의 가중치를 출력하는 함수입니다.
출력 형식은 해당 레이어의 크기와 채널 수에 따라 2차원 배열의 형태로 출력합니다.
설명:
cfgfile: 네트워크 구성 파일 경로를 지정하는 문자열 포인터입니다.
weightfile: 가중치 파일 경로를 지정하는 문자열 포인터입니다.
n: 출력할 레이어의 번호를 지정하는 정수값입니다.
net: 주어진 cfgfile과 weightfile을 이용해 로드한 네트워크를 가리키는 포인터입니다.
l: 지정된 레이어를 가리키는 layer 구조체입니다.
i, j: 반복문에서 사용되는 정수값으로, l의 크기에 따라 가중치 배열을 출력합니다.
출력 형식: 지정된 레이어의 가중치를 해당 레이어의 크기와 채널 수에 따라 2차원 배열 형태로 출력합니다.
rescale_net
Copy void rescale_net(char *cfgfile, char *weightfile, char *outfile)
{
gpu_index = -1;
network *net = load_network(cfgfile, weightfile, 0);
int i;
for(i = 0; i < net->n; ++i){
layer l = net->layers[i];
if(l.type == CONVOLUTIONAL){
rescale_weights(l, 2, -.5);
break;
}
}
save_weights(net, outfile);
}
함수 이름: rescale_net
입력:
cfgfile: char 포인터 형식. YOLO 모델의 구성 파일 경로.
weightfile: char 포인터 형식. YOLO 모델의 가중치 파일 경로.
outfile: char 포인터 형식. 변경된 가중치를 저장할 파일 경로.
동작:
주어진 YOLO 모델의 구성 파일과 가중치 파일을 불러와서, 가장 처음 발견된 컨볼루션 레이어의 가중치를 2배로 확장하고 -0.5를 뺀다.
설명:
이 함수는 YOLO 모델의 구성 파일과 가중치 파일을 불러온 후, 가장 처음 발견된 컨볼루션 레이어의 가중치를 rescale하는 작업을 수행한다.
rescale_weights() 함수를 사용하여 가중치를 2배로 확장하고 -0.5를 뺀다.
변경된 가중치는 save_weights() 함수를 사용하여 지정된 파일 경로에 저장된다.
rgbgr_net
Copy void rgbgr_net(char *cfgfile, char *weightfile, char *outfile)
{
gpu_index = -1;
network *net = load_network(cfgfile, weightfile, 0);
int i;
for(i = 0; i < net->n; ++i){
layer l = net->layers[i];
if(l.type == CONVOLUTIONAL){
rgbgr_weights(l);
break;
}
}
save_weights(net, outfile);
}
함수 이름: rgbgr_net
입력:
cfgfile (char*): 모델 구성 파일 경로
weightfile (char*): 모델 가중치 파일 경로
outfile (char*): 변경된 가중치를 저장할 파일 경로
동작:
입력으로 받은 모델 구성 파일과 가중치 파일을 로드하여, CONVOLUTIONAL 레이어에서 사용되는 가중치들을 RGB 이미지 채널에서 BGR 이미지 채널로 변경합니다.
변경된 가중치를 저장할 파일 경로를 입력받아 저장합니다.
설명:
RGB 이미지와 BGR 이미지는 색상 채널의 순서가 서로 다릅니다.
따라서 RGB 이미지 채널로 학습된 모델을 BGR 이미지 채널로 변경하여 사용할 때는 가중치를 변경해주어야 합니다.
이 함수는 입력으로 받은 모델에서 CONVOLUTIONAL 레이어에서 사용되는 가중치들을 RGB에서 BGR로 변경하고, 변경된 가중치를 지정된 파일 경로에 저장합니다.
reset_normalize_net
Copy void reset_normalize_net(char *cfgfile, char *weightfile, char *outfile)
{
gpu_index = -1;
network *net = load_network(cfgfile, weightfile, 0);
int i;
for (i = 0; i < net->n; ++i) {
layer l = net->layers[i];
if (l.type == CONVOLUTIONAL && l.batch_normalize) {
denormalize_convolutional_layer(l);
}
if (l.type == CONNECTED && l.batch_normalize) {
denormalize_connected_layer(l);
}
if (l.type == GRU && l.batch_normalize) {
denormalize_connected_layer(*l.input_z_layer);
denormalize_connected_layer(*l.input_r_layer);
denormalize_connected_layer(*l.input_h_layer);
denormalize_connected_layer(*l.state_z_layer);
denormalize_connected_layer(*l.state_r_layer);
denormalize_connected_layer(*l.state_h_layer);
}
}
save_weights(net, outfile);
}
함수 이름: reset_normalize_net
입력:
cfgfile: char 포인터. 네트워크 구성 파일 경로.
weightfile: char 포인터. 가중치 파일 경로.
outfile: char 포인터. 출력 파일 경로.
동작:
입력된 cfgfile과 weightfile을 이용하여 네트워크를 로드한다.
모든 레이어를 반복하면서, CONVOLUTIONAL 레이어이고 batch_normalize가 설정된 경우, denormalize_convolutional_layer() 함수를 호출하여 가중치와 스케일, 평균, 분산 값을 원래 값으로 복원한다.
CONNECTED 레이어이고 batch_normalize가 설정된 경우, denormalize_connected_layer() 함수를 호출하여 가중치와 스케일, 평균, 분산 값을 원래 값으로 복원한다.
GRU 레이어이고 batch_normalize가 설정된 경우, 입력 게이트, 잊어버리는 게이트, 상태 게이트의 가중치와 스케일, 평균, 분산 값을 복원한다.
save_weights() 함수를 호출하여 outfile 경로에 가중치를 저장한다.
설명:
이 함수는 YOLOv3 딥러닝 프레임워크에서 사용되는 함수 중 하나로, 네트워크의 가중치를 denormalize하는 함수이다.
각 레이어의 가중치와 스케일, 평균, 분산 값을 denormalize_convolutional_layer() 함수, denormalize_connected_layer() 함수, denormalize_gru_layer() 함수를 이용하여 원래 값으로 복원하고, 이를 저장하는 기능을 수행한다.
이 함수는 네트워크를 fine-tuning할 때, batch_normalize 레이어를 사용하지 않는 경우 등에 활용된다.
normalize_layer
Copy layer normalize_layer(layer l, int n)
{
int j;
l.batch_normalize=1;
l.scales = calloc(n, sizeof(float));
for(j = 0; j < n; ++j){
l.scales[j] = 1;
}
l.rolling_mean = calloc(n, sizeof(float));
l.rolling_variance = calloc(n, sizeof(float));
return l;
}
함수 이름: normalize_layer
입력:
동작:
입력된 레이어 구조체에 대해 배치 정규화(batch normalization)를 수행하는 함수이다.
배치 정규화를 위해 스케일(scales), 이동(rolling mean), 분산(rolling variance)을 저장할 메모리를 할당하고, 스케일을 1로 초기화한다.
설명:
배치 정규화는 인공 신경망에서 입력 데이터나 출력 데이터의 분포를 정규 분포로 만들어 학습의 안정성과 수렴 속도를 향상시키는 방법이다.
이 함수는 단일 레이어에 대한 배치 정규화를 수행한다.
스케일은 출력 채널의 개수(n)만큼의 메모리를 동적으로 할당하고 1로 초기화한다.
이동과 분산은 스케일과 마찬가지로 출력 채널의 개수(n)만큼의 메모리를 동적으로 할당하고 0으로 초기화한다. 이후 학습 과정에서 이동과 분산 값이 업데이트된다.
l.batch_normalize 변수를 1로 설정하여 해당 레이어가 배치 정규화를 사용하도록 설정한다.
입력으로 전달된 레이어 구조체 l을 반환한다.
normalize_net
Copy void normalize_net(char *cfgfile, char *weightfile, char *outfile)
{
gpu_index = -1;
network *net = load_network(cfgfile, weightfile, 0);
int i;
for(i = 0; i < net->n; ++i){
layer l = net->layers[i];
if(l.type == CONVOLUTIONAL && !l.batch_normalize){
net->layers[i] = normalize_layer(l, l.n);
}
if (l.type == CONNECTED && !l.batch_normalize) {
net->layers[i] = normalize_layer(l, l.outputs);
}
if (l.type == GRU && l.batch_normalize) {
*l.input_z_layer = normalize_layer(*l.input_z_layer, l.input_z_layer->outputs);
*l.input_r_layer = normalize_layer(*l.input_r_layer, l.input_r_layer->outputs);
*l.input_h_layer = normalize_layer(*l.input_h_layer, l.input_h_layer->outputs);
*l.state_z_layer = normalize_layer(*l.state_z_layer, l.state_z_layer->outputs);
*l.state_r_layer = normalize_layer(*l.state_r_layer, l.state_r_layer->outputs);
*l.state_h_layer = normalize_layer(*l.state_h_layer, l.state_h_layer->outputs);
net->layers[i].batch_normalize=1;
}
}
save_weights(net, outfile);
}
함수 이름: normalize_net
입력:
cfgfile (char *): 네트워크 구성 파일 경로
weightfile (char *): 네트워크 가중치 파일 경로
outfile (char *): 저장될 가중치 파일 경로
동작:
네트워크를 로드하고, 각 층에서 배치 정규화가 적용되지 않은 경우 배치 정규화 층을 추가하여 네트워크를 정규화하고, 모든 가중치를 저장한다.
설명:
normalize_layer() 함수는 입력 층을 정규화하는 함수이다. 이 함수는 l의 배치 정규화 플래그를 설정하고, 스케일을 모두 1로 초기화한 다음, rolling_mean과 rolling_variance 배열을 할당한다.
이 normalize_net() 함수는 네트워크를 로드하고 각 층을 검사하여 배치 정규화가 적용되지 않은 경우 normalize_layer() 함수를 사용하여 층을 정규화한다.
GRU 층에 대해서는, 각각의 연산을 위해 입력 층과 상태 층을 정규화한다. 마지막으로, save_weights() 함수를 사용하여 정규화된 네트워크의 가중치를 저장한다.
statistics_net
Copy void statistics_net(char *cfgfile, char *weightfile)
{
gpu_index = -1;
network *net = load_network(cfgfile, weightfile, 0);
int i;
for (i = 0; i < net->n; ++i) {
layer l = net->layers[i];
if (l.type == CONNECTED && l.batch_normalize) {
printf("Connected Layer %d\n", i);
statistics_connected_layer(l);
}
if (l.type == GRU && l.batch_normalize) {
printf("GRU Layer %d\n", i);
printf("Input Z\n");
statistics_connected_layer(*l.input_z_layer);
printf("Input R\n");
statistics_connected_layer(*l.input_r_layer);
printf("Input H\n");
statistics_connected_layer(*l.input_h_layer);
printf("State Z\n");
statistics_connected_layer(*l.state_z_layer);
printf("State R\n");
statistics_connected_layer(*l.state_r_layer);
printf("State H\n");
statistics_connected_layer(*l.state_h_layer);
}
printf("\n");
}
}
함수 이름: statistics_net
입력:
cfgfile: 네트워크 구성 파일 경로를 나타내는 문자열 포인터
weightfile: 학습된 가중치 파일 경로를 나타내는 문자열 포인터
동작:
지정된 네트워크 구성 파일(cfgfile)과 가중치 파일(weightfile)을 로드하여 네트워크를 생성한다.
생성된 네트워크의 각 레이어를 반복하면서,
현재 레이어가 CONNECTED 레이어이고 batch_normalize 속성이 True인 경우, statistics_connected_layer() 함수를 호출하여 연결된 레이어의 통계 정보를 출력한다.
현재 레이어가 GRU 레이어이고 batch_normalize 속성이 True인 경우, 연결된 레이어의 각각의 input_z_layer, input_r_layer, input_h_layer, state_z_layer, state_r_layer, state_h_layer에 대해 statistics_connected_layer() 함수를 호출하여 통계 정보를 출력한다.
모든 레이어의 통계 정보 출력을 마친 후, 함수 실행 종료한다.
설명:
지정된 네트워크(cfgfile와 weightfile)를 로드하여 생성된 네트워크에서 각 레이어의 통계 정보(평균, 분산, 표준편차 등)를 계산하고 출력하는 함수이다.
출력되는 통계 정보는 연결된 레이어의 입력값과 가중치의 분포를 확인하는 데 유용하다.
denormalize_net
Copy void denormalize_net(char *cfgfile, char *weightfile, char *outfile)
{
gpu_index = -1;
network *net = load_network(cfgfile, weightfile, 0);
int i;
for (i = 0; i < net->n; ++i) {
layer l = net->layers[i];
if ((l.type == DECONVOLUTIONAL || l.type == CONVOLUTIONAL) && l.batch_normalize) {
denormalize_convolutional_layer(l);
net->layers[i].batch_normalize=0;
}
if (l.type == CONNECTED && l.batch_normalize) {
denormalize_connected_layer(l);
net->layers[i].batch_normalize=0;
}
if (l.type == GRU && l.batch_normalize) {
denormalize_connected_layer(*l.input_z_layer);
denormalize_connected_layer(*l.input_r_layer);
denormalize_connected_layer(*l.input_h_layer);
denormalize_connected_layer(*l.state_z_layer);
denormalize_connected_layer(*l.state_r_layer);
denormalize_connected_layer(*l.state_h_layer);
l.input_z_layer->batch_normalize = 0;
l.input_r_layer->batch_normalize = 0;
l.input_h_layer->batch_normalize = 0;
l.state_z_layer->batch_normalize = 0;
l.state_r_layer->batch_normalize = 0;
l.state_h_layer->batch_normalize = 0;
net->layers[i].batch_normalize=0;
}
}
save_weights(net, outfile);
}
함수 이름: denormalize_net
입력:
char *cfgfile: 모델 구성 파일 경로
char *weightfile: 학습된 가중치 파일 경로
char *outfile: 가중치를 저장할 파일 경로
동작:
입력으로 주어진 모델 구성 파일과 학습된 가중치 파일을 이용하여 모델을 로드하고, 각 레이어의 batch normalization을 되돌린 후, 가중치를 저장하는 기능을 수행한다.
설명:
주어진 cfgfile과 weightfile을 이용하여 모델을 로드한다.
모든 레이어에 대해서, l.type이 CONVOLUTIONAL 또는 DECONVOLUTIONAL인 경우에는 batch normalization을 되돌린다. 이를 위해 denormalize_convolutional_layer 함수를 호출하고, l.batch_normalize를 0으로 설정한다.
l.type이 CONNECTED인 경우에는 denormalize_connected_layer 함수를 호출하고, l.batch_normalize를 0으로 설정한다.
l.type이 GRU인 경우에는 input_z_layer, input_r_layer, input_h_layer, state_z_layer, state_r_layer, state_h_layer 각각에 대해서 denormalize_connected_layer 함수를 호출하고, 각 레이어의 batch_normalize를 0으로 설정한다.
처리가 끝난 모델 가중치를 outfile에 저장한다.
mkimg
Copy void mkimg(char *cfgfile, char *weightfile, int h, int w, int num, char *prefix)
{
network *net = load_network(cfgfile, weightfile, 0);
image *ims = get_weights(net->layers[0]);
int n = net->layers[0].n;
int z;
for(z = 0; z < num; ++z){
image im = make_image(h, w, 3);
fill_image(im, .5);
int i;
for(i = 0; i < 100; ++i){
image r = copy_image(ims[rand()%n]);
rotate_image_cw(r, rand()%4);
random_distort_image(r, 1, 1.5, 1.5);
int dx = rand()%(w-r.w);
int dy = rand()%(h-r.h);
ghost_image(r, im, dx, dy);
free_image(r);
}
char buff[256];
sprintf(buff, "%s/gen_%d", prefix, z);
save_image(im, buff);
free_image(im);
}
}
함수 이름: mkimg
입력:
cfgfile: YOLO 모델 구성 파일 경로
weightfile: 학습된 YOLO 모델 가중치 파일 경로
prefix: 생성된 이미지 파일명에 추가될 prefix 문자열
동작:
주어진 YOLO 모델의 첫번째 레이어의 가중치로부터 이미지를 생성하는 함수입니다.
생성할 이미지 개수(num)만큼 반복하면서 각 이미지를 랜덤한 배치와 왜곡을 적용하여 생성합니다.
생성된 이미지는 prefix와 이미지 번호를 조합하여 파일명을 만들고 저장합니다.
설명:
이 함수는 YOLO 모델의 가중치로부터 이미지를 생성하는 함수입니다. 먼저 입력받은 cfgfile과 weightfile을 이용하여 YOLO 모델을 로드합니다.
그 다음 모델의 첫번째 레이어의 가중치를 가져와 ims에 저장합니다.
그 후, num만큼 이미지를 생성하면서 각 이미지를 랜덤한 배치와 왜곡을 적용합니다.
생성된 이미지는 prefix와 이미지 번호를 조합하여 파일명을 만들고 저장합니다.
visualize
Copy void visualize(char *cfgfile, char *weightfile)
{
network *net = load_network(cfgfile, weightfile, 0);
visualize_network(net);
}
함수 이름: visualize
입력:
cfgfile: YOLO 모델 구성 파일 경로
weightfile: 학습된 YOLO 모델의 가중치 파일 경로
동작:
입력된 YOLO 모델을 불러와서 시각화합니다.
시각화된 모델은 graph.png 파일로 저장됩니다.
설명:
입력된 cfgfile과 weightfile 경로에서 YOLO 모델을 불러와 시각화합니다.
시각화된 모델은 레이어, 필터, 차원 등 다양한 정보를 그래프로 나타내어 모델 구조를 쉽게 이해할 수 있도록 돕습니다.
main
Copy int main(int argc, char **argv)
{
//test_resize("data/bad.jpg");
//test_box();
//test_convolutional_layer();
if(argc < 2){
fprintf(stderr, "usage: %s <function>\n", argv[0]);
return 0;
}
gpu_index = find_int_arg(argc, argv, "-i", 0);
if(find_arg(argc, argv, "-nogpu")) {
gpu_index = -1;
}
#ifndef GPU
gpu_index = -1;
#else
if(gpu_index >= 0){
cuda_set_device(gpu_index);
}
#endif
if (0 == strcmp(argv[1], "average")){
average(argc, argv);
} else if (0 == strcmp(argv[1], "yolo")){
run_yolo(argc, argv);
} else if (0 == strcmp(argv[1], "super")){
run_super(argc, argv);
} else if (0 == strcmp(argv[1], "lsd")){
run_lsd(argc, argv);
} else if (0 == strcmp(argv[1], "detector")){
run_detector(argc, argv);
} else if (0 == strcmp(argv[1], "detect")){
float thresh = find_float_arg(argc, argv, "-thresh", .5);
char *filename = (argc > 4) ? argv[4]: 0;
char *outfile = find_char_arg(argc, argv, "-out", 0);
int fullscreen = find_arg(argc, argv, "-fullscreen");
test_detector("cfg/coco.data", argv[2], argv[3], filename, thresh, .5, outfile, fullscreen);
} else if (0 == strcmp(argv[1], "cifar")){
run_cifar(argc, argv);
} else if (0 == strcmp(argv[1], "go")){
run_go(argc, argv);
} else if (0 == strcmp(argv[1], "rnn")){
run_char_rnn(argc, argv);
} else if (0 == strcmp(argv[1], "coco")){
run_coco(argc, argv);
} else if (0 == strcmp(argv[1], "classify")){
predict_classifier("cfg/imagenet1k.data", argv[2], argv[3], argv[4], 5);
} else if (0 == strcmp(argv[1], "classifier")){
run_classifier(argc, argv);
} else if (0 == strcmp(argv[1], "regressor")){
run_regressor(argc, argv);
} else if (0 == strcmp(argv[1], "isegmenter")){
run_isegmenter(argc, argv);
} else if (0 == strcmp(argv[1], "segmenter")){
run_segmenter(argc, argv);
} else if (0 == strcmp(argv[1], "art")){
run_art(argc, argv);
} else if (0 == strcmp(argv[1], "tag")){
run_tag(argc, argv);
} else if (0 == strcmp(argv[1], "3d")){
composite_3d(argv[2], argv[3], argv[4], (argc > 5) ? atof(argv[5]) : 0);
} else if (0 == strcmp(argv[1], "test")){
test_resize(argv[2]);
} else if (0 == strcmp(argv[1], "nightmare")){
run_nightmare(argc, argv);
} else if (0 == strcmp(argv[1], "rgbgr")){
rgbgr_net(argv[2], argv[3], argv[4]);
} else if (0 == strcmp(argv[1], "reset")){
reset_normalize_net(argv[2], argv[3], argv[4]);
} else if (0 == strcmp(argv[1], "denormalize")){
denormalize_net(argv[2], argv[3], argv[4]);
} else if (0 == strcmp(argv[1], "statistics")){
statistics_net(argv[2], argv[3]);
} else if (0 == strcmp(argv[1], "normalize")){
normalize_net(argv[2], argv[3], argv[4]);
} else if (0 == strcmp(argv[1], "rescale")){
rescale_net(argv[2], argv[3], argv[4]);
} else if (0 == strcmp(argv[1], "ops")){
operations(argv[2]);
} else if (0 == strcmp(argv[1], "speed")){
speed(argv[2], (argc > 3 && argv[3]) ? atoi(argv[3]) : 0);
} else if (0 == strcmp(argv[1], "oneoff")){
oneoff(argv[2], argv[3], argv[4]);
} else if (0 == strcmp(argv[1], "oneoff2")){
oneoff2(argv[2], argv[3], argv[4], atoi(argv[5]));
} else if (0 == strcmp(argv[1], "print")){
print_weights(argv[2], argv[3], atoi(argv[4]));
} else if (0 == strcmp(argv[1], "partial")){
partial(argv[2], argv[3], argv[4], atoi(argv[5]));
} else if (0 == strcmp(argv[1], "average")){
average(argc, argv);
} else if (0 == strcmp(argv[1], "visualize")){
visualize(argv[2], (argc > 3) ? argv[3] : 0);
} else if (0 == strcmp(argv[1], "mkimg")){
mkimg(argv[2], argv[3], atoi(argv[4]), atoi(argv[5]), atoi(argv[6]), argv[7]);
} else if (0 == strcmp(argv[1], "imtest")){
test_resize(argv[2]);
} else {
fprintf(stderr, "Not an option: %s\n", argv[1]);
}
return 0;
}
함수 이름: main
입력:
int argc, char **argv (인자의 개수와 값)
동작:
argv[1]의 값에 따라 다른 함수를 호출하는 분기문
설명:
입력으로 받은 인자의 개수와 값들을 나타내는 int argc, char **argv를 받는다.
argv[1]에 해당하는 값으로 분기하여 다른 함수를 호출한다.
아래는 argv[1]에 따른 호출할 함수들이다.
"average": average(argc, argv) 함수 호출
"yolo": run_yolo(argc, argv) 함수 호출
"super": run_super(argc, argv) 함수 호출
"lsd": run_lsd(argc, argv) 함수 호출
"detector": test_detector 함수 호출
"detect": test_detector 함수 호출
"cifar": run_cifar(argc, argv) 함수 호출
"go": run_go(argc, argv) 함수 호출
"rnn": run_char_rnn(argc, argv) 함수 호출
"coco": run_coco(argc, argv) 함수 호출
"classify": predict_classifier 함수 호출
"classifier": run_classifier(argc, argv) 함수 호출
"regressor": run_regressor(argc, argv) 함수 호출
"isegmenter": run_isegmenter(argc, argv) 함수 호출
"segmenter": run_segmenter(argc, argv) 함수 호출
"art": run_art(argc, argv) 함수 호출
"tag": run_tag(argc, argv) 함수 호출
"test": test_resize 함수 호출
"nightmare": run_nightmare(argc, argv) 함수 호출
"reset": reset_normalize_net 함수 호출
"denormalize": denormalize_net 함수 호출
"statistics": statistics_net 함수 호출
"normalize": normalize_net 함수 호출
"rescale": rescale_net 함수 호출
"print": print_weights 함수 호출
"visualize": visualize 함수 호출
"imtest": test_resize 함수 호출
입력이 위에서 언급한 경우가 아닐 경우, 에러 메시지 출력