Added param counters_per_class=100,200,... <for each class> to [yolo] and [Gaussian_yolo] to solve class-imbalance-problem

pull/4540/head
AlexeyAB 6 years ago
parent 63396082d7
commit e33ecb785e
  1. 1
      include/darknet.h
  2. 10
      src/gaussian_yolo_layer.c
  3. 2
      src/image_opencv.cpp
  4. 1
      src/layer.c
  5. 2
      src/network_kernels.cu
  6. 30
      src/parser.c
  7. 10
      src/yolo_layer.c

@ -261,6 +261,7 @@ struct layer {
float learning_rate_scale;
float clip;
int focal_loss;
float *classes_multipliers;
float label_smooth_eps;
int noloss;
int softmax;

@ -330,16 +330,18 @@ void averages_gaussian_yolo_deltas(int class_index, int box_index, int stride, i
}
}
void delta_gaussian_yolo_class(float *output, float *delta, int index, int class_id, int classes, int stride, float *avg_cat, float label_smooth_eps)
void delta_gaussian_yolo_class(float *output, float *delta, int index, int class_id, int classes, int stride, float *avg_cat, float label_smooth_eps, float *classes_multipliers)
{
int n;
if (delta[index]){
delta[index + stride*class_id] = (1 - label_smooth_eps) - output[index + stride*class_id];
if (classes_multipliers) delta[index + stride*class_id] *= classes_multipliers[class_id];
if(avg_cat) *avg_cat += output[index + stride*class_id];
return;
}
for(n = 0; n < classes; ++n){
delta[index + stride*n] = ((n == class_id) ? (1 - label_smooth_eps) : (0 + label_smooth_eps/classes)) - output[index + stride*n];
if (classes_multipliers) delta[index + stride*class_id] *= classes_multipliers[class_id];
if(n == class_id && avg_cat) *avg_cat += output[index + stride*n];
}
}
@ -452,7 +454,7 @@ void forward_gaussian_yolo_layer(const layer l, network_state state)
int class_id = state.truth[best_t*(4 + 1) + b*l.truths + 4];
if (l.map) class_id = l.map[class_id];
int class_index = entry_gaussian_index(l, b, n*l.w*l.h + j*l.w + i, 9);
delta_gaussian_yolo_class(l.output, l.delta, class_index, class_id, l.classes, l.w*l.h, 0, l.label_smooth_eps);
delta_gaussian_yolo_class(l.output, l.delta, class_index, class_id, l.classes, l.w*l.h, 0, l.label_smooth_eps, l.classes_multipliers);
box truth = float_to_box_stride(state.truth + best_t*(4 + 1) + b*l.truths, 1);
delta_gaussian_yolo_box(truth, l.output, l.biases, l.mask[n], box_index, i, j, l.w, l.h, state.net.w, state.net.h, l.delta, (2-truth.w*truth.h), l.w*l.h, l.iou_normalizer, l.iou_loss, l.uc_normalizer, 1, l.yolo_point);
}
@ -504,7 +506,7 @@ void forward_gaussian_yolo_layer(const layer l, network_state state)
int class_id = state.truth[t*(4 + 1) + b*l.truths + 4];
if (l.map) class_id = l.map[class_id];
int class_index = entry_gaussian_index(l, b, mask_n*l.w*l.h + j*l.w + i, 9);
delta_gaussian_yolo_class(l.output, l.delta, class_index, class_id, l.classes, l.w*l.h, &avg_cat, l.label_smooth_eps);
delta_gaussian_yolo_class(l.output, l.delta, class_index, class_id, l.classes, l.w*l.h, &avg_cat, l.label_smooth_eps, l.classes_multipliers);
++count;
++class_count;
@ -535,7 +537,7 @@ void forward_gaussian_yolo_layer(const layer l, network_state state)
int class_id = state.truth[t*(4 + 1) + b*l.truths + 4];
if (l.map) class_id = l.map[class_id];
int class_index = entry_gaussian_index(l, b, mask_n*l.w*l.h + j*l.w + i, 9);
delta_gaussian_yolo_class(l.output, l.delta, class_index, class_id, l.classes, l.w*l.h, &avg_cat, l.label_smooth_eps);
delta_gaussian_yolo_class(l.output, l.delta, class_index, class_id, l.classes, l.w*l.h, &avg_cat, l.label_smooth_eps, l.classes_multipliers);
++count;
++class_count;

@ -1125,7 +1125,7 @@ extern "C" void draw_train_loss(char *windows_name, mat_cv* img_src, int img_siz
else
cv::putText(img, "- Saved", cv::Point(260, img_size - 10), cv::FONT_HERSHEY_COMPLEX_SMALL, 0.7, CV_RGB(255, 255, 255), 1, CV_AA);
if (mjpeg_port > 0) send_mjpeg((mat_cv *)&img, mjpeg_port, 500000, 100);
if (mjpeg_port > 0) send_mjpeg((mat_cv *)&img, mjpeg_port, 500000, 70);
}
catch (...) {
cerr << "OpenCV exception: draw_train_loss() \n";

@ -60,6 +60,7 @@ void free_layer_custom(layer l, int keep_cudnn_desc)
return;
}
if (l.mask) free(l.mask);
if (l.classes_multipliers)free(l.classes_multipliers);
if (l.cweights) free(l.cweights);
if (l.indexes) free(l.indexes);
if (l.input_layers) free(l.input_layers);

@ -144,7 +144,7 @@ void update_network_gpu(network net)
for(i = 0; i < net.n; ++i){
layer l = net.layers[i];
l.t = get_current_batch(net);
if (iteration_num > (net.max_batches * 2 / 3)) l.deform = 0;
if (iteration_num > (net.max_batches * 1 / 2)) l.deform = 0;
if(l.update_gpu){
l.update_gpu(l, update_batch, rate, net.momentum, net.decay);
}

@ -363,12 +363,34 @@ int *parse_yolo_mask(char *a, int *num)
return mask;
}
float *get_classes_multipliers(char *cpc, const int classes)
{
float *classes_multipliers = NULL;
if (cpc) {
int classes_counters = classes;
int *counters_per_class = parse_yolo_mask(cpc, &classes_counters);
if (classes_counters != classes) {
printf(" number of values in counters_per_class = %d doesn't match with classes = %d \n", classes_counters, classes);
exit(0);
}
float max_counter = 0;
int i;
for (i = 0; i < classes_counters; ++i) if (max_counter < counters_per_class[i]) max_counter = counters_per_class[i];
classes_multipliers = (float *)calloc(classes_counters, sizeof(float));
for (i = 0; i < classes_counters; ++i) classes_multipliers[i] = max_counter / counters_per_class[i];
free(counters_per_class);
printf(" classes_multipliers: ");
for (i = 0; i < classes_counters; ++i) printf("%.1f, ", classes_multipliers[i]);
printf("\n");
}
return classes_multipliers;
}
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);
int max_boxes = option_find_int_quiet(options, "max", 90);
@ -380,6 +402,9 @@ layer parse_yolo(list *options, size_params params)
}
//assert(l.outputs == params.inputs);
char *cpc = option_find_str(options, "counters_per_class", 0);
l.classes_multipliers = get_classes_multipliers(cpc, classes);
l.label_smooth_eps = option_find_float_quiet(options, "label_smooth_eps", 0.0f);
l.scale_x_y = option_find_float_quiet(options, "scale_x_y", 1);
l.iou_normalizer = option_find_float_quiet(options, "iou_normalizer", 0.75);
@ -472,6 +497,9 @@ layer parse_gaussian_yolo(list *options, size_params params) // Gaussian_YOLOv3
}
//assert(l.outputs == params.inputs);
char *cpc = option_find_str(options, "counters_per_class", 0);
l.classes_multipliers = get_classes_multipliers(cpc, classes);
l.label_smooth_eps = option_find_float_quiet(options, "label_smooth_eps", 0.0f);
l.scale_x_y = option_find_float_quiet(options, "scale_x_y", 1);
l.uc_normalizer = option_find_float_quiet(options, "uc_normalizer", 1.0);

@ -217,11 +217,12 @@ void averages_yolo_deltas(int class_index, int box_index, int stride, int classe
}
}
void delta_yolo_class(float *output, float *delta, int index, int class_id, int classes, int stride, float *avg_cat, int focal_loss, float label_smooth_eps)
void delta_yolo_class(float *output, float *delta, int index, int class_id, int classes, int stride, float *avg_cat, int focal_loss, float label_smooth_eps, float *classes_multipliers)
{
int n;
if (delta[index + stride*class_id]){
delta[index + stride*class_id] = (1 - label_smooth_eps) - output[index + stride*class_id];
if (classes_multipliers) delta[index + stride*class_id] *= classes_multipliers[class_id];
if(avg_cat) *avg_cat += output[index + stride*class_id];
return;
}
@ -249,6 +250,7 @@ void delta_yolo_class(float *output, float *delta, int index, int class_id, int
// default
for (n = 0; n < classes; ++n) {
delta[index + stride*n] = ((n == class_id) ? (1 - label_smooth_eps) : (0 + label_smooth_eps/classes)) - output[index + stride*n];
if (classes_multipliers) delta[index + stride*class_id] *= classes_multipliers[class_id];
if (n == class_id && avg_cat) *avg_cat += output[index + stride*n];
}
}
@ -359,7 +361,7 @@ void forward_yolo_layer(const layer l, network_state state)
int class_id = state.truth[best_t*(4 + 1) + b*l.truths + 4];
if (l.map) class_id = l.map[class_id];
int class_index = entry_index(l, b, n*l.w*l.h + j*l.w + i, 4 + 1);
delta_yolo_class(l.output, l.delta, class_index, class_id, l.classes, l.w*l.h, 0, l.focal_loss, l.label_smooth_eps);
delta_yolo_class(l.output, l.delta, class_index, class_id, l.classes, l.w*l.h, 0, l.focal_loss, l.label_smooth_eps, l.classes_multipliers);
box truth = float_to_box_stride(state.truth + best_t*(4 + 1) + b*l.truths, 1);
delta_yolo_box(truth, l.output, l.biases, l.mask[n], box_index, i, j, l.w, l.h, state.net.w, state.net.h, l.delta, (2 - truth.w*truth.h), l.w*l.h, l.iou_normalizer, l.iou_loss, 1);
}
@ -421,7 +423,7 @@ void forward_yolo_layer(const layer l, network_state state)
int class_id = state.truth[t*(4 + 1) + b*l.truths + 4];
if (l.map) class_id = l.map[class_id];
int class_index = entry_index(l, b, mask_n*l.w*l.h + j*l.w + i, 4 + 1);
delta_yolo_class(l.output, l.delta, class_index, class_id, l.classes, l.w*l.h, &avg_cat, l.focal_loss, l.label_smooth_eps);
delta_yolo_class(l.output, l.delta, class_index, class_id, l.classes, l.w*l.h, &avg_cat, l.focal_loss, l.label_smooth_eps, l.classes_multipliers);
++count;
++class_count;
@ -463,7 +465,7 @@ void forward_yolo_layer(const layer l, network_state state)
int class_id = state.truth[t*(4 + 1) + b*l.truths + 4];
if (l.map) class_id = l.map[class_id];
int class_index = entry_index(l, b, mask_n*l.w*l.h + j*l.w + i, 4 + 1);
delta_yolo_class(l.output, l.delta, class_index, class_id, l.classes, l.w*l.h, &avg_cat, l.focal_loss, l.label_smooth_eps);
delta_yolo_class(l.output, l.delta, class_index, class_id, l.classes, l.w*l.h, &avg_cat, l.focal_loss, l.label_smooth_eps, l.classes_multipliers);
++count;
++class_count;

Loading…
Cancel
Save