본문 바로가기

IT/Deeplearning

[CNN classifier / YOLO DARKNET] classifier code review :: load_network- [2.3]

1. [CNN classifier / YOLO DARKNET] classifier code review :: Intro- [1]

2. [CNN classifier / YOLO DARKNET] classifier code review :: load_network- [2.1]

3. [CNN classifier / YOLO DARKNET] classifier code review :: load_network- [2.2]


저번 포스팅에서는 load_network함수에서 parse_network_cfg 함수의 read_cfg함수를 살펴보았습니다.


이번 포스팅은 make_network함수, is_network함수, parse_net_options함수까지 살펴보도록 하겠습니다.


1. make_network, is_network, parse_net_options :: src/network.c, parse.c


해당 함수들은 parse_network_cfg 함수내에서 다음과 같은 위치에 있습니다.


1. node 구조체 포인터에 section이라는 리스트 구조체의 제일 앞 node 포인터를 대입합니다.

2. netwrok구조체를 초기화합니다.

3. gpu index에 대한 값을 설정합니다.

4. size_params구조체 변수를 만듭니다.

5. section구조체 포인터에 (1)에서 만들어둔 node의 val값을 대입합니다.

6. 리스트 구조체 options에 (5)에서 만든 section구조체의 멤버변수 options을 대입합니다.

7. 해당 네트워크 구조체를 validation합니다.

8. network구조체에 해당 options을 parsing합니다.


network *parse_network_cfg(char *filename)
{
    ...

    node *n = sections->front;
    if(!n) error("Config file has no sections");
    network *net = make_network(sections->size - 1);
    net->gpu_index = gpu_index;
    size_params params;

    section *s = (section *)n->val;
    list *options = s->options;
    if(!is_network(s)) error("First section must be [net] or [network]");
    parse_net_options(options, net);

...

}


2. make_network :: src/network.c

make_network함수의 코드 구성은 아래와 같습니다.

1. network 구조체를 동적할당합니다.
2. network 구조체 멤버 변수 n에 인자 n을 대입합니다.

3. network 구조체 멤버 변수 layer에 layer의 갯수 * layer구조체만큼 동적할당을 합닏나.

4. network 구조체 멤버 변수 seen에  size_t만큼의 동적할당을 합니다.

5. network 구조체 멤버 변수 t에 int만큼의 동적할당을 합니다.

6. network 구조체 멤버 변수 cost에 float만큼의 동적할당을 합니다.

7. network 구조체를 반환합니다.


network *make_network(int n)
{
    network *net = calloc(1, sizeof(network));
    net->n = n;
    net->layers = calloc(net->n, sizeof(layer));
    net->seen = calloc(1, sizeof(size_t));
    net->t    = calloc(1, sizeof(int));
    net->cost = calloc(1, sizeof(float));
    return net;
}


3. is_network :: src/parse.c

is_network함수의 코드 구성은 아래와 같습니다.

1. section 구조체 s의 type과 문자열"[net]"이 같은지 확인합니다.
2. section 구조체 s의 type과 문자열"[network]"이 같은지 확인합니다.
3. (1),(2)의 값을 or연산해서 boolean값을 반환합니다.


int is_network(section *s)
{
    return (strcmp(s->type, "[net]")==0
            || strcmp(s->type, "[network]")==0);
}


4. parse_net_options :: src/parse.c

parse_net_options 함수의 코드 구성은 아래와 같습니다.


1. 각종 옵션들의 내용을 해당 데이터 타입에 맞춰서 {key, value} pair를 찾아서 network 구조체에 대입합니다.


void parse_net_options(list *options, network *net)
{
    net->batch = option_find_int(options, "batch",1);
    net->learning_rate = option_find_float(options, "learning_rate", .001);
    net->momentum = option_find_float(options, "momentum", .9);
    net->decay = option_find_float(options, "decay", .0001);
    int subdivs = option_find_int(options, "subdivisions",1);
    net->time_steps = option_find_int_quiet(options, "time_steps",1);
    net->notruth = option_find_int_quiet(options, "notruth",0);
    net->batch /= subdivs;
    net->batch *= net->time_steps;
    net->subdivisions = subdivs;
    net->random = option_find_int_quiet(options, "random", 0);

    net->adam = option_find_int_quiet(options, "adam", 0);
    if(net->adam){
        net->B1 = option_find_float(options, "B1", .9);
        net->B2 = option_find_float(options, "B2", .999);
        net->eps = option_find_float(options, "eps", .0000001);
    }

    net->h = option_find_int_quiet(options, "height",0);
    net->w = option_find_int_quiet(options, "width",0);
    net->c = option_find_int_quiet(options, "channels",0);
    net->inputs = option_find_int_quiet(options, "inputs", net->h * net->w * net->c);
    net->max_crop = option_find_int_quiet(options, "max_crop",net->w*2);
    net->min_crop = option_find_int_quiet(options, "min_crop",net->w);
    net->max_ratio = option_find_float_quiet(options, "max_ratio", (float) net->max_crop / net->w);
    net->min_ratio = option_find_float_quiet(options, "min_ratio", (float) net->min_crop / net->w);
    net->center = option_find_int_quiet(options, "center",0);

    net->angle = option_find_float_quiet(options, "angle", 0);
    net->aspect = option_find_float_quiet(options, "aspect", 1);
    net->saturation = option_find_float_quiet(options, "saturation", 1);
    net->exposure = option_find_float_quiet(options, "exposure", 1);
    net->hue = option_find_float_quiet(options, "hue", 0);

    if(!net->inputs && !(net->h && net->w && net->c)) error("No input parameters supplied");

    char *policy_s = option_find_str(options, "policy", "constant");
    net->policy = get_policy(policy_s);
    net->burn_in = option_find_int_quiet(options, "burn_in", 0);
    net->power = option_find_float_quiet(options, "power", 4);
    if(net->policy == STEP){
        net->step = option_find_int(options, "step", 1);
        net->scale = option_find_float(options, "scale", 1);
    } else if (net->policy == STEPS){
        char *l = option_find(options, "steps");
        char *p = option_find(options, "scales");
        if(!l || !p) error("STEPS policy must have steps and scales in cfg file");

        int len = strlen(l);
        int n = 1;
        int i;
        for(i = 0; i < len; ++i){
            if (l[i] == ',') ++n;
        }
        int *steps = calloc(n, sizeof(int));
        float *scales = calloc(n, sizeof(float));
        for(i = 0; i < n; ++i){
            int step    = atoi(l);
            float scale = atof(p);
            l = strchr(l, ',')+1;
            p = strchr(p, ',')+1;
            steps[i] = step;
            scales[i] = scale;
        }
        net->scales = scales;
        net->steps = steps;
        net->num_steps = n;
    } else if (net->policy == EXP){
        net->gamma = option_find_float(options, "gamma", 1);
    } else if (net->policy == SIG){
        net->gamma = option_find_float(options, "gamma", 1);
        net->step = option_find_int(options, "step", 1);
    } else if (net->policy == POLY || net->policy == RANDOM){
    }
    net->max_batches = option_find_int(options, "max_batches", 0);
}