提交 3841983a 编写于 作者: D dengkaipeng

fix division error in mean process. test=develop

上级 192d2938
...@@ -57,7 +57,7 @@ class Yolov3LossOp : public framework::OperatorWithKernel { ...@@ -57,7 +57,7 @@ class Yolov3LossOp : public framework::OperatorWithKernel {
PADDLE_ENFORCE_GT(class_num, 0, PADDLE_ENFORCE_GT(class_num, 0,
"Attr(class_num) should be an integer greater then 0."); "Attr(class_num) should be an integer greater then 0.");
std::vector<int64_t> dim_out({1}); std::vector<int64_t> dim_out({dim_x[0]});
ctx->SetOutputDim("Loss", framework::make_ddim(dim_out)); ctx->SetOutputDim("Loss", framework::make_ddim(dim_out));
} }
...@@ -93,7 +93,7 @@ class Yolov3LossOpMaker : public framework::OpProtoAndCheckerMaker { ...@@ -93,7 +93,7 @@ class Yolov3LossOpMaker : public framework::OpProtoAndCheckerMaker {
"box class id."); "box class id.");
AddOutput("Loss", AddOutput("Loss",
"The output yolov3 loss tensor, " "The output yolov3 loss tensor, "
"This is a 1-D tensor with shape of [1]"); "This is a 1-D tensor with shape of [N]");
AddAttr<int>("class_num", "The number of classes to predict."); AddAttr<int>("class_num", "The number of classes to predict.");
AddAttr<std::vector<int>>("anchors", AddAttr<std::vector<int>>("anchors",
......
...@@ -33,99 +33,102 @@ static inline bool isZero(T x) { ...@@ -33,99 +33,102 @@ static inline bool isZero(T x) {
} }
template <typename T> template <typename T>
static inline T CalcMSEWithWeight(const Tensor& x, const Tensor& y, static inline void CalcMSEWithWeight(const Tensor& x, const Tensor& y,
const Tensor& weight, const T mf) { const Tensor& weight, const T loss_weight,
int numel = static_cast<int>(x.numel()); T* loss) {
int n = x.dims()[0];
int stride = x.numel() / n;
const T* x_data = x.data<T>(); const T* x_data = x.data<T>();
const T* y_data = y.data<T>(); const T* y_data = y.data<T>();
const T* weight_data = weight.data<T>(); const T* weight_data = weight.data<T>();
T error_sum = 0.0; for (int i = 0; i < n; i++) {
for (int i = 0; i < numel; i++) { for (int j = 0; j < stride; j++) {
T xi = x_data[i]; loss[i] += pow(y_data[j] - x_data[j], 2) * weight_data[j] * loss_weight;
T yi = y_data[i]; }
T weighti = weight_data[i]; x_data += stride;
error_sum += pow(yi - xi, 2) * weighti; y_data += stride;
weight_data += stride;
} }
return error_sum / mf;
} }
template <typename T> template <typename T>
static void CalcMSEGradWithWeight(Tensor* grad, const Tensor& x, static void CalcMSEGradWithWeight(const T* loss_grad, Tensor* grad,
const Tensor& y, const Tensor& weight, const Tensor& x, const Tensor& y,
const T mf) { const Tensor& weight) {
int numel = static_cast<int>(grad->numel()); int n = x.dims()[0];
int stride = x.numel() / n;
T* grad_data = grad->data<T>(); T* grad_data = grad->data<T>();
const T* x_data = x.data<T>(); const T* x_data = x.data<T>();
const T* y_data = y.data<T>(); const T* y_data = y.data<T>();
const T* weight_data = weight.data<T>(); const T* weight_data = weight.data<T>();
for (int i = 0; i < numel; i++) { for (int i = 0; i < n; i++) {
grad_data[i] = 2.0 * weight_data[i] * (x_data[i] - y_data[i]) / mf; for (int j = 0; j < stride; j++) {
} grad_data[j] =
} 2.0 * weight_data[j] * (x_data[j] - y_data[j]) * loss_grad[i];
template <typename T>
struct SigmoidCrossEntropyForward {
T operator()(const T& x, const T& label) const {
T term1 = (x > 0) ? x : 0;
T term2 = x * label;
T term3 = std::log(static_cast<T>(1.0) + std::exp(-(std::abs(x))));
return term1 - term2 + term3;
} }
}; grad_data += stride;
x_data += stride;
template <typename T> y_data += stride;
struct SigmoidCrossEntropyBackward { weight_data += stride;
T operator()(const T& x, const T& label) const {
T sigmoid_x =
static_cast<T>(1.0) / (static_cast<T>(1.0) + std::exp(-1.0 * x));
return sigmoid_x - label;
} }
}; }
template <typename T> template <typename T>
static inline T CalcSCEWithWeight(const Tensor& x, const Tensor& labels, static inline void CalcSCEWithWeight(const Tensor& x, const Tensor& label,
const Tensor& weight, const T mf) { const Tensor& weight, const T loss_weight,
int numel = x.numel(); T* loss) {
int n = x.dims()[0];
int stride = x.numel() / n;
const T* x_data = x.data<T>(); const T* x_data = x.data<T>();
const T* labels_data = labels.data<T>(); const T* label_data = label.data<T>();
const T* weight_data = weight.data<T>(); const T* weight_data = weight.data<T>();
T loss = 0.0; for (int i = 0; i < n; i++) {
for (int i = 0; i < numel; i++) { for (int j = 0; j < stride; j++) {
T xi = x_data[i]; T term1 = (x_data[j] > 0) ? x_data[j] : 0;
T labeli = labels_data[i]; T term2 = x_data[j] * label_data[j];
T weighti = weight_data[i]; T term3 = std::log(1.0 + std::exp(-std::abs(x_data[j])));
loss += ((xi > 0.0 ? xi : 0.0) - xi * labeli + loss[i] += (term1 - term2 + term3) * weight_data[j] * loss_weight;
std::log(1.0 + std::exp(-1.0 * std::abs(xi)))) * }
weighti; x_data += stride;
label_data += stride;
weight_data += stride;
} }
return loss / mf;
} }
template <typename T> template <typename T>
static inline void CalcSCEGradWithWeight(Tensor* grad, const Tensor& x, static inline void CalcSCEGradWithWeight(const T* loss_grad, Tensor* grad,
const Tensor& labels, const Tensor& x, const Tensor& label,
const Tensor& weight, const T mf) { const Tensor& weight) {
int numel = grad->numel(); int n = x.dims()[0];
int stride = x.numel() / n;
T* grad_data = grad->data<T>(); T* grad_data = grad->data<T>();
const T* x_data = x.data<T>(); const T* x_data = x.data<T>();
const T* labels_data = labels.data<T>(); const T* label_data = label.data<T>();
const T* weight_data = weight.data<T>(); const T* weight_data = weight.data<T>();
for (int i = 0; i < numel; i++) { // LOG(ERROR) << "SCE grad start";
grad_data[i] = (1.0 / (1.0 + std::exp(-1.0 * x_data[i])) - labels_data[i]) * for (int i = 0; i < n; i++) {
weight_data[i] / mf; for (int j = 0; j < stride; j++) {
grad_data[j] = (1.0 / (1.0 + std::exp(-x_data[j])) - label_data[j]) *
weight_data[j] * loss_grad[i];
// if (j == 18) LOG(ERROR) << x_data[j] << " " << label_data[j] << " " <<
// weight_data[j] << " " << loss_grad[i];
}
grad_data += stride;
x_data += stride;
label_data += stride;
weight_data += stride;
} }
} }
template <typename T> template <typename T>
static void CalcPredResult(const Tensor& input, Tensor* pred_conf, static void SplitPredResult(const Tensor& input, Tensor* pred_conf,
Tensor* pred_class, Tensor* pred_x, Tensor* pred_y, Tensor* pred_class, Tensor* pred_x, Tensor* pred_y,
Tensor* pred_w, Tensor* pred_h, const int anchor_num, Tensor* pred_w, Tensor* pred_h,
const int class_num) { const int anchor_num, const int class_num) {
const int n = input.dims()[0]; const int n = input.dims()[0];
const int h = input.dims()[2]; const int h = input.dims()[2];
const int w = input.dims()[3]; const int w = input.dims()[3];
...@@ -255,39 +258,20 @@ static void PreProcessGTBox(const Tensor& gt_box, const Tensor& gt_label, ...@@ -255,39 +258,20 @@ static void PreProcessGTBox(const Tensor& gt_box, const Tensor& gt_label,
} }
} }
static void ExpandObjMaskByClassNum(Tensor* obj_mask_expand,
const Tensor& obj_mask) {
const int n = obj_mask_expand->dims()[0];
const int an_num = obj_mask_expand->dims()[1];
const int h = obj_mask_expand->dims()[2];
const int w = obj_mask_expand->dims()[3];
const int class_num = obj_mask_expand->dims()[4];
auto obj_mask_expand_t = EigenTensor<int, 5>::From(*obj_mask_expand);
auto obj_mask_t = EigenTensor<int, 4>::From(obj_mask);
obj_mask_expand_t = obj_mask_t.reshape(Array5(n, an_num, h, w, 1))
.broadcast(Array5(1, 1, 1, 1, class_num));
}
template <typename T> template <typename T>
static void AddAllGradToInputGrad( static void AddAllGradToInputGrad(
Tensor* grad, T loss, const Tensor& pred_x, const Tensor& pred_y, Tensor* grad, const Tensor& grad_x, const Tensor& grad_y,
const Tensor& pred_conf, const Tensor& pred_class, const Tensor& grad_x, const Tensor& grad_w, const Tensor& grad_h, const Tensor& grad_conf_target,
const Tensor& grad_y, const Tensor& grad_w, const Tensor& grad_h, const Tensor& grad_conf_notarget, const Tensor& grad_class,
const Tensor& grad_conf_target, const Tensor& grad_conf_notarget, const int class_num, const float loss_weight_xy, const float loss_weight_wh,
const Tensor& grad_class, const int class_num, const float loss_weight_xy, const float loss_weight_conf_target, const float loss_weight_conf_notarget,
const float loss_weight_wh, const float loss_weight_conf_target, const float loss_weight_class) {
const float loss_weight_conf_notarget, const float loss_weight_class) { const int n = grad_x.dims()[0];
const int n = pred_x.dims()[0]; const int an_num = grad_x.dims()[1];
const int an_num = pred_x.dims()[1]; const int h = grad_x.dims()[2];
const int h = pred_x.dims()[2]; const int w = grad_x.dims()[3];
const int w = pred_x.dims()[3];
const int attr_num = class_num + 5; const int attr_num = class_num + 5;
auto grad_t = EigenTensor<T, 4>::From(*grad).setConstant(0.0); auto grad_t = EigenTensor<T, 4>::From(*grad).setConstant(0.0);
auto pred_x_t = EigenTensor<T, 4>::From(pred_x);
auto pred_y_t = EigenTensor<T, 4>::From(pred_y);
auto pred_conf_t = EigenTensor<T, 4>::From(pred_conf);
auto pred_class_t = EigenTensor<T, 5>::From(pred_class);
auto grad_x_t = EigenTensor<T, 4>::From(grad_x); auto grad_x_t = EigenTensor<T, 4>::From(grad_x);
auto grad_y_t = EigenTensor<T, 4>::From(grad_y); auto grad_y_t = EigenTensor<T, 4>::From(grad_y);
auto grad_w_t = EigenTensor<T, 4>::From(grad_w); auto grad_w_t = EigenTensor<T, 4>::From(grad_w);
...@@ -300,23 +284,21 @@ static void AddAllGradToInputGrad( ...@@ -300,23 +284,21 @@ static void AddAllGradToInputGrad(
for (int j = 0; j < an_num; j++) { for (int j = 0; j < an_num; j++) {
for (int k = 0; k < h; k++) { for (int k = 0; k < h; k++) {
for (int l = 0; l < w; l++) { for (int l = 0; l < w; l++) {
grad_t(i, j * attr_num, k, l) = grad_t(i, j * attr_num, k, l) = grad_x_t(i, j, k, l) * loss_weight_xy;
grad_x_t(i, j, k, l) * loss * loss_weight_xy;
grad_t(i, j * attr_num + 1, k, l) = grad_t(i, j * attr_num + 1, k, l) =
grad_y_t(i, j, k, l) * loss * loss_weight_xy; grad_y_t(i, j, k, l) * loss_weight_xy;
grad_t(i, j * attr_num + 2, k, l) = grad_t(i, j * attr_num + 2, k, l) =
grad_w_t(i, j, k, l) * loss * loss_weight_wh; grad_w_t(i, j, k, l) * loss_weight_wh;
grad_t(i, j * attr_num + 3, k, l) = grad_t(i, j * attr_num + 3, k, l) =
grad_h_t(i, j, k, l) * loss * loss_weight_wh; grad_h_t(i, j, k, l) * loss_weight_wh;
grad_t(i, j * attr_num + 4, k, l) = grad_t(i, j * attr_num + 4, k, l) =
grad_conf_target_t(i, j, k, l) * loss * loss_weight_conf_target; grad_conf_target_t(i, j, k, l) * loss_weight_conf_target;
grad_t(i, j * attr_num + 4, k, l) += grad_t(i, j * attr_num + 4, k, l) +=
grad_conf_notarget_t(i, j, k, l) * loss * grad_conf_notarget_t(i, j, k, l) * loss_weight_conf_notarget;
loss_weight_conf_notarget;
for (int c = 0; c < class_num; c++) { for (int c = 0; c < class_num; c++) {
grad_t(i, j * attr_num + 5 + c, k, l) = grad_t(i, j * attr_num + 5 + c, k, l) =
grad_class_t(i, j, k, l, c) * loss * loss_weight_class; grad_class_t(i, j, k, l, c) * loss_weight_class;
} }
} }
} }
...@@ -356,7 +338,7 @@ class Yolov3LossKernel : public framework::OpKernel<T> { ...@@ -356,7 +338,7 @@ class Yolov3LossKernel : public framework::OpKernel<T> {
pred_h.mutable_data<T>({n, an_num, h, w}, ctx.GetPlace()); pred_h.mutable_data<T>({n, an_num, h, w}, ctx.GetPlace());
pred_conf.mutable_data<T>({n, an_num, h, w}, ctx.GetPlace()); pred_conf.mutable_data<T>({n, an_num, h, w}, ctx.GetPlace());
pred_class.mutable_data<T>({n, an_num, h, w, class_num}, ctx.GetPlace()); pred_class.mutable_data<T>({n, an_num, h, w, class_num}, ctx.GetPlace());
CalcPredResult<T>(*input, &pred_conf, &pred_class, &pred_x, &pred_y, SplitPredResult<T>(*input, &pred_conf, &pred_class, &pred_x, &pred_y,
&pred_w, &pred_h, an_num, class_num); &pred_w, &pred_h, an_num, class_num);
Tensor obj_mask, noobj_mask; Tensor obj_mask, noobj_mask;
...@@ -388,25 +370,24 @@ class Yolov3LossKernel : public framework::OpKernel<T> { ...@@ -388,25 +370,24 @@ class Yolov3LossKernel : public framework::OpKernel<T> {
obj_mask_expand_t = obj_mask_t.reshape(Array5(n, an_num, h, w, 1)) obj_mask_expand_t = obj_mask_t.reshape(Array5(n, an_num, h, w, 1))
.broadcast(Array5(1, 1, 1, 1, class_num)); .broadcast(Array5(1, 1, 1, 1, class_num));
T box_f = static_cast<T>(an_num * h * w); T* loss_data = loss->mutable_data<T>({n}, ctx.GetPlace());
T class_f = static_cast<T>(an_num * h * w * class_num); memset(loss_data, 0, n * sizeof(T));
T loss_x = CalcSCEWithWeight<T>(pred_x, tx, obj_weight, box_f); CalcSCEWithWeight<T>(pred_x, tx, obj_weight, loss_weight_xy, loss_data);
T loss_y = CalcSCEWithWeight<T>(pred_y, ty, obj_weight, box_f); CalcSCEWithWeight<T>(pred_y, ty, obj_weight, loss_weight_xy, loss_data);
T loss_w = CalcMSEWithWeight<T>(pred_w, tw, obj_weight, box_f); CalcMSEWithWeight<T>(pred_w, tw, obj_weight, loss_weight_wh, loss_data);
T loss_h = CalcMSEWithWeight<T>(pred_h, th, obj_weight, box_f); CalcMSEWithWeight<T>(pred_h, th, obj_weight, loss_weight_wh, loss_data);
T loss_conf_target = CalcSCEWithWeight<T>(pred_conf, tconf, obj_mask, loss_weight_conf_target,
CalcSCEWithWeight<T>(pred_conf, tconf, obj_mask, box_f); loss_data);
T loss_conf_notarget = CalcSCEWithWeight<T>(pred_conf, tconf, noobj_mask,
CalcSCEWithWeight<T>(pred_conf, tconf, noobj_mask, box_f); loss_weight_conf_notarget, loss_data);
T loss_class = CalcSCEWithWeight<T>(pred_class, tclass, obj_mask_expand, loss_weight_class,
CalcSCEWithWeight<T>(pred_class, tclass, obj_mask_expand, class_f); loss_data);
auto* loss_data = loss->mutable_data<T>({1}, ctx.GetPlace()); // loss_data[0] = (loss_weight_xy * (loss_x + loss_y) +
loss_data[0] = loss_weight_xy * (loss_x + loss_y) + // loss_weight_wh * (loss_w + loss_h) +
loss_weight_wh * (loss_w + loss_h) + // loss_weight_conf_target * loss_conf_target +
loss_weight_conf_target * loss_conf_target + // loss_weight_conf_notarget * loss_conf_notarget +
loss_weight_conf_notarget * loss_conf_notarget + // loss_weight_class * loss_class) / n;
loss_weight_class * loss_class;
} }
}; };
...@@ -421,8 +402,8 @@ class Yolov3LossGradKernel : public framework::OpKernel<T> { ...@@ -421,8 +402,8 @@ class Yolov3LossGradKernel : public framework::OpKernel<T> {
int class_num = ctx.Attr<int>("class_num"); int class_num = ctx.Attr<int>("class_num");
float ignore_thresh = ctx.Attr<float>("ignore_thresh"); float ignore_thresh = ctx.Attr<float>("ignore_thresh");
auto* input_grad = ctx.Output<Tensor>(framework::GradVarName("X")); auto* input_grad = ctx.Output<Tensor>(framework::GradVarName("X"));
auto* output_grad = ctx.Input<Tensor>(framework::GradVarName("Loss")); auto* loss_grad = ctx.Input<Tensor>(framework::GradVarName("Loss"));
const T loss = output_grad->data<T>()[0]; const T* loss_grad_data = loss_grad->data<T>();
int input_size = ctx.Attr<int>("input_size"); int input_size = ctx.Attr<int>("input_size");
float loss_weight_xy = ctx.Attr<float>("loss_weight_xy"); float loss_weight_xy = ctx.Attr<float>("loss_weight_xy");
float loss_weight_wh = ctx.Attr<float>("loss_weight_wh"); float loss_weight_wh = ctx.Attr<float>("loss_weight_wh");
...@@ -445,7 +426,7 @@ class Yolov3LossGradKernel : public framework::OpKernel<T> { ...@@ -445,7 +426,7 @@ class Yolov3LossGradKernel : public framework::OpKernel<T> {
pred_h.mutable_data<T>({n, an_num, h, w}, ctx.GetPlace()); pred_h.mutable_data<T>({n, an_num, h, w}, ctx.GetPlace());
pred_conf.mutable_data<T>({n, an_num, h, w}, ctx.GetPlace()); pred_conf.mutable_data<T>({n, an_num, h, w}, ctx.GetPlace());
pred_class.mutable_data<T>({n, an_num, h, w, class_num}, ctx.GetPlace()); pred_class.mutable_data<T>({n, an_num, h, w, class_num}, ctx.GetPlace());
CalcPredResult<T>(*input, &pred_conf, &pred_class, &pred_x, &pred_y, SplitPredResult<T>(*input, &pred_conf, &pred_class, &pred_x, &pred_y,
&pred_w, &pred_h, an_num, class_num); &pred_w, &pred_h, an_num, class_num);
Tensor obj_mask, noobj_mask; Tensor obj_mask, noobj_mask;
...@@ -470,6 +451,8 @@ class Yolov3LossGradKernel : public framework::OpKernel<T> { ...@@ -470,6 +451,8 @@ class Yolov3LossGradKernel : public framework::OpKernel<T> {
auto tweight_t = EigenTensor<T, 4>::From(tweight); auto tweight_t = EigenTensor<T, 4>::From(tweight);
obj_weight_t = obj_mask_t * tweight_t; obj_weight_t = obj_mask_t * tweight_t;
// LOG(ERROR) << obj_mask_t;
Tensor obj_mask_expand; Tensor obj_mask_expand;
obj_mask_expand.mutable_data<T>({n, an_num, h, w, class_num}, obj_mask_expand.mutable_data<T>({n, an_num, h, w, class_num},
ctx.GetPlace()); ctx.GetPlace());
...@@ -486,25 +469,23 @@ class Yolov3LossGradKernel : public framework::OpKernel<T> { ...@@ -486,25 +469,23 @@ class Yolov3LossGradKernel : public framework::OpKernel<T> {
grad_conf_target.mutable_data<T>({n, an_num, h, w}, ctx.GetPlace()); grad_conf_target.mutable_data<T>({n, an_num, h, w}, ctx.GetPlace());
grad_conf_notarget.mutable_data<T>({n, an_num, h, w}, ctx.GetPlace()); grad_conf_notarget.mutable_data<T>({n, an_num, h, w}, ctx.GetPlace());
grad_class.mutable_data<T>({n, an_num, h, w, class_num}, ctx.GetPlace()); grad_class.mutable_data<T>({n, an_num, h, w, class_num}, ctx.GetPlace());
T box_f = static_cast<T>(an_num * h * w); CalcSCEGradWithWeight<T>(loss_grad_data, &grad_x, pred_x, tx, obj_weight);
T class_f = static_cast<T>(an_num * h * w * class_num); CalcSCEGradWithWeight<T>(loss_grad_data, &grad_y, pred_y, ty, obj_weight);
CalcSCEGradWithWeight<T>(&grad_x, pred_x, tx, obj_weight, box_f); CalcMSEGradWithWeight<T>(loss_grad_data, &grad_w, pred_w, tw, obj_weight);
CalcSCEGradWithWeight<T>(&grad_y, pred_y, ty, obj_weight, box_f); CalcMSEGradWithWeight<T>(loss_grad_data, &grad_h, pred_h, th, obj_weight);
CalcMSEGradWithWeight<T>(&grad_w, pred_w, tw, obj_weight, box_f); CalcSCEGradWithWeight<T>(loss_grad_data, &grad_conf_target, pred_conf,
CalcMSEGradWithWeight<T>(&grad_h, pred_h, th, obj_weight, box_f); tconf, obj_mask);
CalcSCEGradWithWeight<T>(&grad_conf_target, pred_conf, tconf, obj_mask, CalcSCEGradWithWeight<T>(loss_grad_data, &grad_conf_notarget, pred_conf,
box_f); tconf, noobj_mask);
CalcSCEGradWithWeight<T>(&grad_conf_notarget, pred_conf, tconf, noobj_mask, CalcSCEGradWithWeight<T>(loss_grad_data, &grad_class, pred_class, tclass,
box_f); obj_mask_expand);
CalcSCEGradWithWeight<T>(&grad_class, pred_class, tclass, obj_mask_expand,
class_f);
input_grad->mutable_data<T>({n, c, h, w}, ctx.GetPlace()); input_grad->mutable_data<T>({n, c, h, w}, ctx.GetPlace());
AddAllGradToInputGrad<T>( AddAllGradToInputGrad<T>(input_grad, grad_x, grad_y, grad_w, grad_h,
input_grad, loss, pred_x, pred_y, pred_conf, pred_class, grad_x, grad_y, grad_conf_target, grad_conf_notarget, grad_class,
grad_w, grad_h, grad_conf_target, grad_conf_notarget, grad_class, class_num, loss_weight_xy, loss_weight_wh,
class_num, loss_weight_xy, loss_weight_wh, loss_weight_conf_target, loss_weight_conf_target, loss_weight_conf_notarget,
loss_weight_conf_notarget, loss_weight_class); loss_weight_class);
} }
}; };
......
...@@ -470,6 +470,8 @@ class OpTest(unittest.TestCase): ...@@ -470,6 +470,8 @@ class OpTest(unittest.TestCase):
] ]
analytic_grads = self._get_gradient(inputs_to_check, place, analytic_grads = self._get_gradient(inputs_to_check, place,
output_names, no_grad_set) output_names, no_grad_set)
# print(numeric_grads[0][0, 4, :, :])
# print(analytic_grads[0][0, 4, :, :])
self._assert_is_close(numeric_grads, analytic_grads, inputs_to_check, self._assert_is_close(numeric_grads, analytic_grads, inputs_to_check,
max_relative_error, max_relative_error,
......
...@@ -23,15 +23,23 @@ from op_test import OpTest ...@@ -23,15 +23,23 @@ from op_test import OpTest
from paddle.fluid import core from paddle.fluid import core
def mse(x, y, weight, num): def mse(x, y, weight):
return ((y - x)**2 * weight).sum() / num n = x.shape[0]
x = x.reshape((n, -1))
y = y.reshape((n, -1))
def sce(x, label, weight, num): weight = weight.reshape((n, -1))
return ((y - x)**2 * weight).sum(axis=1)
def sce(x, label, weight):
n = x.shape[0]
x = x.reshape((n, -1))
label = label.reshape((n, -1))
weight = weight.reshape((n, -1))
sigmoid_x = expit(x) sigmoid_x = expit(x)
term1 = label * np.log(sigmoid_x) term1 = label * np.log(sigmoid_x)
term2 = (1.0 - label) * np.log(1.0 - sigmoid_x) term2 = (1.0 - label) * np.log(1.0 - sigmoid_x)
return ((-term1 - term2) * weight).sum() / num return ((-term1 - term2) * weight).sum(axis=1)
def box_iou(box1, box2): def box_iou(box1, box2):
...@@ -131,18 +139,24 @@ def YoloV3Loss(x, gtbox, gtlabel, attrs): ...@@ -131,18 +139,24 @@ def YoloV3Loss(x, gtbox, gtlabel, attrs):
tx, ty, tw, th, tweight, tconf, tcls, obj_mask, noobj_mask = build_target( tx, ty, tw, th, tweight, tconf, tcls, obj_mask, noobj_mask = build_target(
gtbox, gtlabel, attrs, x.shape[2]) gtbox, gtlabel, attrs, x.shape[2])
# print("obj_mask: ", obj_mask[0, 0, :, :])
# print("noobj_mask: ", noobj_mask[0, 0, :, :])
obj_weight = obj_mask * tweight obj_weight = obj_mask * tweight
obj_mask_expand = np.tile( obj_mask_expand = np.tile(
np.expand_dims(obj_mask, 4), (1, 1, 1, 1, int(attrs['class_num']))) np.expand_dims(obj_mask, 4), (1, 1, 1, 1, int(attrs['class_num'])))
box_f = an_num * h * w loss_x = sce(pred_x, tx, obj_weight)
class_f = an_num * h * w * class_num loss_y = sce(pred_y, ty, obj_weight)
loss_x = sce(pred_x, tx, obj_weight, box_f) loss_w = mse(pred_w, tw, obj_weight)
loss_y = sce(pred_y, ty, obj_weight, box_f) loss_h = mse(pred_h, th, obj_weight)
loss_w = mse(pred_w, tw, obj_weight, box_f) loss_conf_target = sce(pred_conf, tconf, obj_mask)
loss_h = mse(pred_h, th, obj_weight, box_f) loss_conf_notarget = sce(pred_conf, tconf, noobj_mask)
loss_conf_target = sce(pred_conf, tconf, obj_mask, box_f) loss_class = sce(pred_cls, tcls, obj_mask_expand)
loss_conf_notarget = sce(pred_conf, tconf, noobj_mask, box_f)
loss_class = sce(pred_cls, tcls, obj_mask_expand, class_f) # print("loss_xy: ", loss_x + loss_y)
# print("loss_wh: ", loss_w + loss_h)
# print("loss_conf_target: ", loss_conf_target)
# print("loss_conf_notarget: ", loss_conf_notarget)
# print("loss_class: ", loss_class)
return attrs['loss_weight_xy'] * (loss_x + loss_y) \ return attrs['loss_weight_xy'] * (loss_x + loss_y) \
+ attrs['loss_weight_wh'] * (loss_w + loss_h) \ + attrs['loss_weight_wh'] * (loss_w + loss_h) \
...@@ -178,10 +192,7 @@ class TestYolov3LossOp(OpTest): ...@@ -178,10 +192,7 @@ class TestYolov3LossOp(OpTest):
} }
self.inputs = {'X': x, 'GTBox': gtbox, 'GTLabel': gtlabel} self.inputs = {'X': x, 'GTBox': gtbox, 'GTLabel': gtlabel}
self.outputs = { self.outputs = {'Loss': YoloV3Loss(x, gtbox, gtlabel, self.attrs)}
'Loss': np.array(
[YoloV3Loss(x, gtbox, gtlabel, self.attrs)]).astype('float32')
}
def test_check_output(self): def test_check_output(self):
place = core.CPUPlace() place = core.CPUPlace()
...@@ -193,20 +204,20 @@ class TestYolov3LossOp(OpTest): ...@@ -193,20 +204,20 @@ class TestYolov3LossOp(OpTest):
place, ['X'], place, ['X'],
'Loss', 'Loss',
no_grad_set=set(["GTBox", "GTLabel"]), no_grad_set=set(["GTBox", "GTLabel"]),
max_relative_error=0.3) max_relative_error=0.31)
def initTestCase(self): def initTestCase(self):
self.anchors = [10, 13, 12, 12] self.anchors = [12, 12]
self.class_num = 10 self.class_num = 5
self.ignore_thresh = 0.7 self.ignore_thresh = 0.3
self.input_size = 416 self.input_size = 416
self.x_shape = (5, len(self.anchors) // 2 * (5 + self.class_num), 7, 7) self.x_shape = (3, len(self.anchors) // 2 * (5 + self.class_num), 5, 5)
self.gtbox_shape = (5, 10, 4) self.gtbox_shape = (3, 5, 4)
self.loss_weight_xy = 1.4 self.loss_weight_xy = 1.2
self.loss_weight_wh = 0.8 self.loss_weight_wh = 0.8
self.loss_weight_conf_target = 1.1 self.loss_weight_conf_target = 2.0
self.loss_weight_conf_notarget = 0.9 self.loss_weight_conf_notarget = 1.0
self.loss_weight_class = 1.2 self.loss_weight_class = 1.5
if __name__ == "__main__": if __name__ == "__main__":
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册