| | |
| | | #include "image.h" |
| | | #include "data.h" |
| | | #include "utils.h" |
| | | #include "blas.h" |
| | | |
| | | #include "crop_layer.h" |
| | | #include "connected_layer.h" |
| | | #include "gru_layer.h" |
| | | #include "rnn_layer.h" |
| | | #include "crnn_layer.h" |
| | | #include "local_layer.h" |
| | | #include "convolutional_layer.h" |
| | | #include "activation_layer.h" |
| | | #include "deconvolutional_layer.h" |
| | | #include "detection_layer.h" |
| | | #include "normalization_layer.h" |
| | | #include "batchnorm_layer.h" |
| | | #include "maxpool_layer.h" |
| | | #include "avgpool_layer.h" |
| | | #include "cost_layer.h" |
| | | #include "softmax_layer.h" |
| | | #include "dropout_layer.h" |
| | | #include "route_layer.h" |
| | | #include "shortcut_layer.h" |
| | | |
| | | int get_current_batch(network net) |
| | | { |
| | | int batch_num = (*net.seen)/(net.batch*net.subdivisions); |
| | | return batch_num; |
| | | } |
| | | |
| | | void reset_momentum(network net) |
| | | { |
| | | if (net.momentum == 0) return; |
| | | net.learning_rate = 0; |
| | | net.momentum = 0; |
| | | net.decay = 0; |
| | | #ifdef GPU |
| | | if(gpu_index >= 0) update_network_gpu(net); |
| | | #endif |
| | | } |
| | | |
| | | float get_current_rate(network net) |
| | | { |
| | | int batch_num = get_current_batch(net); |
| | | int i; |
| | | float rate; |
| | | switch (net.policy) { |
| | | case CONSTANT: |
| | | return net.learning_rate; |
| | | case STEP: |
| | | return net.learning_rate * pow(net.scale, batch_num/net.step); |
| | | case STEPS: |
| | | rate = net.learning_rate; |
| | | for(i = 0; i < net.num_steps; ++i){ |
| | | if(net.steps[i] > batch_num) return rate; |
| | | rate *= net.scales[i]; |
| | | if(net.steps[i] > batch_num - 1) reset_momentum(net); |
| | | } |
| | | return rate; |
| | | case EXP: |
| | | return net.learning_rate * pow(net.gamma, batch_num); |
| | | case POLY: |
| | | return net.learning_rate * pow(1 - (float)batch_num / net.max_batches, net.power); |
| | | case RANDOM: |
| | | return net.learning_rate * pow(rand_uniform(0,1), net.power); |
| | | case SIG: |
| | | return net.learning_rate * (1./(1.+exp(net.gamma*(batch_num - net.step)))); |
| | | default: |
| | | fprintf(stderr, "Policy is weird!\n"); |
| | | return net.learning_rate; |
| | | } |
| | | } |
| | | |
| | | char *get_layer_string(LAYER_TYPE a) |
| | | { |
| | | switch(a){ |
| | | case CONVOLUTIONAL: |
| | | return "convolutional"; |
| | | case ACTIVE: |
| | | return "activation"; |
| | | case LOCAL: |
| | | return "local"; |
| | | case DECONVOLUTIONAL: |
| | | return "deconvolutional"; |
| | | case CONNECTED: |
| | | return "connected"; |
| | | case RNN: |
| | | return "rnn"; |
| | | case GRU: |
| | | return "gru"; |
| | | case CRNN: |
| | | return "crnn"; |
| | | case MAXPOOL: |
| | | return "maxpool"; |
| | | case AVGPOOL: |
| | |
| | | return "cost"; |
| | | case ROUTE: |
| | | return "route"; |
| | | case SHORTCUT: |
| | | return "shortcut"; |
| | | case NORMALIZATION: |
| | | return "normalization"; |
| | | case BATCHNORM: |
| | | return "batchnorm"; |
| | | default: |
| | | break; |
| | | } |
| | |
| | | network net = {0}; |
| | | net.n = n; |
| | | net.layers = calloc(net.n, sizeof(layer)); |
| | | net.seen = calloc(1, sizeof(int)); |
| | | #ifdef GPU |
| | | net.input_gpu = calloc(1, sizeof(float *)); |
| | | net.truth_gpu = calloc(1, sizeof(float *)); |
| | |
| | | |
| | | void forward_network(network net, network_state state) |
| | | { |
| | | state.workspace = net.workspace; |
| | | int i; |
| | | for(i = 0; i < net.n; ++i){ |
| | | state.index = i; |
| | | layer l = net.layers[i]; |
| | | if(l.delta){ |
| | | scal_cpu(l.outputs * l.batch, 0, l.delta, 1); |
| | |
| | | forward_convolutional_layer(l, state); |
| | | } else if(l.type == DECONVOLUTIONAL){ |
| | | forward_deconvolutional_layer(l, state); |
| | | } else if(l.type == ACTIVE){ |
| | | forward_activation_layer(l, state); |
| | | } else if(l.type == LOCAL){ |
| | | forward_local_layer(l, state); |
| | | } else if(l.type == NORMALIZATION){ |
| | | forward_normalization_layer(l, state); |
| | | } else if(l.type == BATCHNORM){ |
| | | forward_batchnorm_layer(l, state); |
| | | } else if(l.type == DETECTION){ |
| | | forward_detection_layer(l, state); |
| | | } else if(l.type == CONNECTED){ |
| | | forward_connected_layer(l, state); |
| | | } else if(l.type == RNN){ |
| | | forward_rnn_layer(l, state); |
| | | } else if(l.type == GRU){ |
| | | forward_gru_layer(l, state); |
| | | } else if(l.type == CRNN){ |
| | | forward_crnn_layer(l, state); |
| | | } else if(l.type == CROP){ |
| | | forward_crop_layer(l, state); |
| | | } else if(l.type == COST){ |
| | |
| | | forward_dropout_layer(l, state); |
| | | } else if(l.type == ROUTE){ |
| | | forward_route_layer(l, net); |
| | | } else if(l.type == SHORTCUT){ |
| | | forward_shortcut_layer(l, state); |
| | | } |
| | | state.input = l.output; |
| | | } |
| | |
| | | { |
| | | int i; |
| | | int update_batch = net.batch*net.subdivisions; |
| | | float rate = get_current_rate(net); |
| | | for(i = 0; i < net.n; ++i){ |
| | | layer l = net.layers[i]; |
| | | if(l.type == CONVOLUTIONAL){ |
| | | update_convolutional_layer(l, update_batch, net.learning_rate, net.momentum, net.decay); |
| | | update_convolutional_layer(l, update_batch, rate, net.momentum, net.decay); |
| | | } else if(l.type == DECONVOLUTIONAL){ |
| | | update_deconvolutional_layer(l, net.learning_rate, net.momentum, net.decay); |
| | | update_deconvolutional_layer(l, rate, net.momentum, net.decay); |
| | | } else if(l.type == CONNECTED){ |
| | | update_connected_layer(l, update_batch, net.learning_rate, net.momentum, net.decay); |
| | | update_connected_layer(l, update_batch, rate, net.momentum, net.decay); |
| | | } else if(l.type == RNN){ |
| | | update_rnn_layer(l, update_batch, rate, net.momentum, net.decay); |
| | | } else if(l.type == GRU){ |
| | | update_gru_layer(l, update_batch, rate, net.momentum, net.decay); |
| | | } else if(l.type == CRNN){ |
| | | update_crnn_layer(l, update_batch, rate, net.momentum, net.decay); |
| | | } else if(l.type == LOCAL){ |
| | | update_local_layer(l, update_batch, rate, net.momentum, net.decay); |
| | | } |
| | | } |
| | | } |
| | | |
| | | float *get_network_output(network net) |
| | | { |
| | | #ifdef GPU |
| | | return get_network_output_gpu(net); |
| | | #endif |
| | | int i; |
| | | for(i = net.n-1; i > 0; --i) if(net.layers[i].type != COST) break; |
| | | return net.layers[i].output; |
| | |
| | | float sum = 0; |
| | | int count = 0; |
| | | for(i = 0; i < net.n; ++i){ |
| | | if(net.layers[net.n-1].type == COST){ |
| | | sum += net.layers[net.n-1].output[0]; |
| | | if(net.layers[i].type == COST){ |
| | | sum += net.layers[i].cost[0]; |
| | | ++count; |
| | | } |
| | | if(net.layers[net.n-1].type == DETECTION){ |
| | | sum += net.layers[net.n-1].cost[0]; |
| | | if(net.layers[i].type == DETECTION){ |
| | | sum += net.layers[i].cost[0]; |
| | | ++count; |
| | | } |
| | | } |
| | |
| | | int i; |
| | | float *original_input = state.input; |
| | | float *original_delta = state.delta; |
| | | state.workspace = net.workspace; |
| | | for(i = net.n-1; i >= 0; --i){ |
| | | state.index = i; |
| | | if(i == 0){ |
| | | state.input = original_input; |
| | | state.delta = original_delta; |
| | |
| | | backward_convolutional_layer(l, state); |
| | | } else if(l.type == DECONVOLUTIONAL){ |
| | | backward_deconvolutional_layer(l, state); |
| | | } else if(l.type == ACTIVE){ |
| | | backward_activation_layer(l, state); |
| | | } else if(l.type == NORMALIZATION){ |
| | | backward_normalization_layer(l, state); |
| | | } else if(l.type == BATCHNORM){ |
| | | backward_batchnorm_layer(l, state); |
| | | } else if(l.type == MAXPOOL){ |
| | | if(i != 0) backward_maxpool_layer(l, state); |
| | | } else if(l.type == AVGPOOL){ |
| | |
| | | if(i != 0) backward_softmax_layer(l, state); |
| | | } else if(l.type == CONNECTED){ |
| | | backward_connected_layer(l, state); |
| | | } else if(l.type == RNN){ |
| | | backward_rnn_layer(l, state); |
| | | } else if(l.type == GRU){ |
| | | backward_gru_layer(l, state); |
| | | } else if(l.type == CRNN){ |
| | | backward_crnn_layer(l, state); |
| | | } else if(l.type == LOCAL){ |
| | | backward_local_layer(l, state); |
| | | } else if(l.type == COST){ |
| | | backward_cost_layer(l, state); |
| | | } else if(l.type == ROUTE){ |
| | | backward_route_layer(l, net); |
| | | } else if(l.type == SHORTCUT){ |
| | | backward_shortcut_layer(l, state); |
| | | } |
| | | } |
| | | } |
| | | |
| | | float train_network_datum(network net, float *x, float *y) |
| | | { |
| | | *net.seen += net.batch; |
| | | #ifdef GPU |
| | | if(gpu_index >= 0) return train_network_datum_gpu(net, x, y); |
| | | #endif |
| | | network_state state; |
| | | state.index = 0; |
| | | state.net = net; |
| | | state.input = x; |
| | | state.delta = 0; |
| | | state.truth = y; |
| | |
| | | forward_network(net, state); |
| | | backward_network(net, state); |
| | | float error = get_network_cost(net); |
| | | if((net.seen/net.batch)%net.subdivisions == 0) update_network(net); |
| | | if(((*net.seen)/net.batch)%net.subdivisions == 0) update_network(net); |
| | | return error; |
| | | } |
| | | |
| | |
| | | int i; |
| | | float sum = 0; |
| | | for(i = 0; i < n; ++i){ |
| | | net.seen += batch; |
| | | get_random_batch(d, batch, X, y); |
| | | float err = train_network_datum(net, X, y); |
| | | sum += err; |
| | |
| | | float sum = 0; |
| | | for(i = 0; i < n; ++i){ |
| | | get_next_batch(d, batch, i*batch, X, y); |
| | | net.seen += batch; |
| | | float err = train_network_datum(net, X, y); |
| | | sum += err; |
| | | } |
| | |
| | | { |
| | | int i,j; |
| | | network_state state; |
| | | state.index = 0; |
| | | state.net = net; |
| | | state.train = 1; |
| | | state.delta = 0; |
| | | float sum = 0; |
| | |
| | | //if(w == net->w && h == net->h) return 0; |
| | | net->w = w; |
| | | net->h = h; |
| | | int inputs = 0; |
| | | size_t workspace_size = 0; |
| | | //fprintf(stderr, "Resizing to %d x %d...", w, h); |
| | | //fflush(stderr); |
| | | for (i = 0; i < net->n; ++i){ |
| | | layer l = net->layers[i]; |
| | | if(l.type == CONVOLUTIONAL){ |
| | | resize_convolutional_layer(&l, w, h); |
| | | }else if(l.type == CROP){ |
| | | resize_crop_layer(&l, w, h); |
| | | }else if(l.type == MAXPOOL){ |
| | | resize_maxpool_layer(&l, w, h); |
| | | }else if(l.type == AVGPOOL){ |
| | | resize_avgpool_layer(&l, w, h); |
| | | break; |
| | | }else if(l.type == NORMALIZATION){ |
| | | resize_normalization_layer(&l, w, h); |
| | | }else if(l.type == COST){ |
| | | resize_cost_layer(&l, inputs); |
| | | }else{ |
| | | error("Cannot resize this type of layer"); |
| | | } |
| | | if(l.workspace_size > workspace_size) workspace_size = l.workspace_size; |
| | | inputs = l.outputs; |
| | | net->layers[i] = l; |
| | | w = l.out_w; |
| | | h = l.out_h; |
| | | if(l.type == AVGPOOL) break; |
| | | } |
| | | #ifdef GPU |
| | | cuda_free(net->workspace); |
| | | net->workspace = cuda_make_array(0, (workspace_size-1)/sizeof(float)+1); |
| | | #else |
| | | free(net->workspace); |
| | | net->workspace = calloc(1, (workspace_size-1)/sizeof(float)+1); |
| | | #endif |
| | | //fprintf(stderr, " Done!\n"); |
| | | return 0; |
| | | } |
| | |
| | | #endif |
| | | |
| | | network_state state; |
| | | state.net = net; |
| | | state.index = 0; |
| | | state.input = input; |
| | | state.truth = 0; |
| | | state.train = 0; |
| | |
| | | return acc; |
| | | } |
| | | |
| | | float *network_accuracies(network net, data d) |
| | | float *network_accuracies(network net, data d, int n) |
| | | { |
| | | static float acc[2]; |
| | | matrix guess = network_predict_data(net, d); |
| | | acc[0] = matrix_topk_accuracy(d.y, guess,1); |
| | | acc[1] = matrix_topk_accuracy(d.y, guess,5); |
| | | acc[0] = matrix_topk_accuracy(d.y, guess, 1); |
| | | acc[1] = matrix_topk_accuracy(d.y, guess, n); |
| | | free_matrix(guess); |
| | | return acc; |
| | | } |
| | |
| | | return acc; |
| | | } |
| | | |
| | | |
| | | void free_network(network net) |
| | | { |
| | | int i; |
| | | for(i = 0; i < net.n; ++i){ |
| | | free_layer(net.layers[i]); |
| | | } |
| | | free(net.layers); |
| | | #ifdef GPU |
| | | if(*net.input_gpu) cuda_free(*net.input_gpu); |
| | | if(*net.truth_gpu) cuda_free(*net.truth_gpu); |
| | | if(net.input_gpu) free(net.input_gpu); |
| | | if(net.truth_gpu) free(net.truth_gpu); |
| | | #endif |
| | | } |