Support multi-target, fit intercept for hinge. (#9850)
This commit is contained in:
@@ -23,7 +23,7 @@ void TestElementWiseKernel() {
|
||||
ElementWiseTransformDevice(t, [] __device__(size_t i, float) { return i; });
|
||||
// CPU view
|
||||
t = l.View(DeviceOrd::CPU()).Slice(linalg::All(), 1, linalg::All());
|
||||
size_t k = 0;
|
||||
std::size_t k = 0;
|
||||
for (size_t i = 0; i < l.Shape(0); ++i) {
|
||||
for (size_t j = 0; j < l.Shape(2); ++j) {
|
||||
ASSERT_EQ(k++, t(i, j));
|
||||
@@ -31,7 +31,15 @@ void TestElementWiseKernel() {
|
||||
}
|
||||
|
||||
t = l.View(device).Slice(linalg::All(), 1, linalg::All());
|
||||
ElementWiseKernelDevice(t, [] XGBOOST_DEVICE(size_t i, float v) { SPAN_CHECK(v == i); });
|
||||
cuda_impl::ElementWiseKernel(
|
||||
t, [=] XGBOOST_DEVICE(std::size_t i, std::size_t j) mutable { t(i, j) = i + j; });
|
||||
|
||||
t = l.Slice(linalg::All(), 1, linalg::All());
|
||||
for (size_t i = 0; i < l.Shape(0); ++i) {
|
||||
for (size_t j = 0; j < l.Shape(2); ++j) {
|
||||
ASSERT_EQ(i + j, t(i, j));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
@@ -31,12 +31,10 @@ inline void TestMetaInfoStridedData(DeviceOrd device) {
|
||||
auto const& h_result = info.labels.View(DeviceOrd::CPU());
|
||||
ASSERT_EQ(h_result.Shape().size(), 2);
|
||||
auto in_labels = labels.View(DeviceOrd::CPU());
|
||||
linalg::ElementWiseKernelHost(h_result, omp_get_max_threads(), [&](size_t i, float& v_0) {
|
||||
auto tup = linalg::UnravelIndex(i, h_result.Shape());
|
||||
auto i0 = std::get<0>(tup);
|
||||
auto i1 = std::get<1>(tup);
|
||||
linalg::ElementWiseKernelHost(h_result, omp_get_max_threads(), [&](size_t i, std::size_t j) {
|
||||
// Sliced at second dimension.
|
||||
auto v_1 = in_labels(i0, 0, i1);
|
||||
auto v_0 = h_result(i, j);
|
||||
auto v_1 = in_labels(i, 0, j);
|
||||
CHECK_EQ(v_0, v_1);
|
||||
});
|
||||
}
|
||||
@@ -65,14 +63,13 @@ inline void TestMetaInfoStridedData(DeviceOrd device) {
|
||||
auto const& h_result = info.base_margin_.View(DeviceOrd::CPU());
|
||||
ASSERT_EQ(h_result.Shape().size(), 2);
|
||||
auto in_margin = base_margin.View(DeviceOrd::CPU());
|
||||
linalg::ElementWiseKernelHost(h_result, omp_get_max_threads(), [&](size_t i, float v_0) {
|
||||
auto tup = linalg::UnravelIndex(i, h_result.Shape());
|
||||
auto i0 = std::get<0>(tup);
|
||||
auto i1 = std::get<1>(tup);
|
||||
// Sliced at second dimension.
|
||||
auto v_1 = in_margin(i0, 0, i1);
|
||||
CHECK_EQ(v_0, v_1);
|
||||
});
|
||||
linalg::ElementWiseKernelHost(h_result, omp_get_max_threads(),
|
||||
[&](std::size_t i, std::size_t j) {
|
||||
// Sliced at second dimension.
|
||||
auto v_0 = h_result(i, j);
|
||||
auto v_1 = in_margin(i, 0, j);
|
||||
CHECK_EQ(v_0, v_1);
|
||||
});
|
||||
}
|
||||
}
|
||||
} // namespace xgboost
|
||||
|
||||
@@ -1,28 +1,55 @@
|
||||
// Copyright by Contributors
|
||||
/**
|
||||
* Copyright 2018-2023, XGBoost Contributors
|
||||
*/
|
||||
#include <xgboost/objective.h>
|
||||
#include <xgboost/context.h>
|
||||
#include <limits>
|
||||
|
||||
#include "../helpers.h"
|
||||
#include "../../../src/common/linalg_op.h"
|
||||
namespace xgboost {
|
||||
TEST(Objective, DeclareUnifiedTest(HingeObj)) {
|
||||
Context ctx = MakeCUDACtx(GPUIDX);
|
||||
std::unique_ptr<ObjFunction> obj{ObjFunction::Create("binary:hinge", &ctx)};
|
||||
|
||||
float eps = std::numeric_limits<xgboost::bst_float>::min();
|
||||
CheckObjFunction(obj,
|
||||
{-1.0f, -0.5f, 0.5f, 1.0f, -1.0f, -0.5f, 0.5f, 1.0f},
|
||||
{ 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f},
|
||||
{ 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f},
|
||||
{ 0.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f, 0.0f},
|
||||
{ eps, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, eps });
|
||||
CheckObjFunction(obj,
|
||||
{-1.0f, -0.5f, 0.5f, 1.0f, -1.0f, -0.5f, 0.5f, 1.0f},
|
||||
{ 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f},
|
||||
{}, // Empty weight.
|
||||
{ 0.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f, 0.0f},
|
||||
{ eps, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, eps });
|
||||
std::vector<float> predt{-1.0f, -0.5f, 0.5f, 1.0f, -1.0f, -0.5f, 0.5f, 1.0f};
|
||||
std::vector<float> label{ 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f};
|
||||
std::vector<float> grad{0.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f, 0.0f};
|
||||
std::vector<float> hess{eps, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, eps};
|
||||
|
||||
ASSERT_NO_THROW(obj->DefaultEvalMetric());
|
||||
CheckObjFunction(obj, predt, label, {1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f}, grad, hess);
|
||||
CheckObjFunction(obj, predt, label, {/* Empty weight. */}, grad, hess);
|
||||
|
||||
ASSERT_EQ(obj->DefaultEvalMetric(), StringView{"error"});
|
||||
|
||||
MetaInfo info;
|
||||
info.num_row_ = label.size();
|
||||
info.labels.Reshape(info.num_row_, 3);
|
||||
ASSERT_EQ(obj->Targets(info), 3);
|
||||
auto h_labels = info.labels.HostView();
|
||||
for (std::size_t j = 0; j < obj->Targets(info); ++j) {
|
||||
for (std::size_t i = 0; i < info.num_row_; ++i) {
|
||||
h_labels(i, j) = label[i];
|
||||
}
|
||||
}
|
||||
linalg::Tensor<float, 2> t_predt{};
|
||||
t_predt.Reshape(info.labels.Shape());
|
||||
for (std::size_t j = 0; j < obj->Targets(info); ++j) {
|
||||
for (std::size_t i = 0; i < info.num_row_; ++i) {
|
||||
t_predt(i, j) = predt[i];
|
||||
}
|
||||
}
|
||||
linalg::Matrix<GradientPair> out_gpair;
|
||||
obj->GetGradient(*t_predt.Data(), info, 0, &out_gpair);
|
||||
|
||||
for (std::size_t j = 0; j < obj->Targets(info); ++j) {
|
||||
auto gh = out_gpair.Slice(linalg::All(), j);
|
||||
ASSERT_EQ(gh.Size(), info.num_row_);
|
||||
for (std::size_t i = 0; i < gh.Size(); ++i) {
|
||||
ASSERT_EQ(gh(i).GetGrad(), grad[i]);
|
||||
ASSERT_EQ(gh(i).GetHess(), hess[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace xgboost
|
||||
|
||||
Reference in New Issue
Block a user