diff --git a/include/deepworks/metrics.hpp b/include/deepworks/metrics.hpp new file mode 100644 index 00000000000000..7abe50cacfbd3a --- /dev/null +++ b/include/deepworks/metrics.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include + +namespace deepworks { +namespace metric { + +float accuracy(const Tensor& y_pred, const Tensor& y_true); + +float sparse_accuracy(const Tensor& y_pred, const Tensor& y_true); + +} // namespace metric +} // namespace deepworks diff --git a/include/deepworks/tensor.hpp b/include/deepworks/tensor.hpp index cc89272d24b1c3..118abfef76b0a8 100644 --- a/include/deepworks/tensor.hpp +++ b/include/deepworks/tensor.hpp @@ -18,6 +18,7 @@ class Tensor { void copyTo(Tensor tensor); Type *data(); + const Type *data() const; size_t total() const; void allocate(const Shape& shape); bool empty() const; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bcf6aec0261dfa..d04629cf914d19 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -13,6 +13,8 @@ set(SRC_FILES # Runtime entities ${CMAKE_CURRENT_LIST_DIR}/runtime/tensor.cpp ${CMAKE_CURRENT_LIST_DIR}/runtime/cpu/kernels/kernels.cpp + + ${CMAKE_CURRENT_LIST_DIR}/metrics.cpp ) set(DeepWorks_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/include/") diff --git a/src/metrics.cpp b/src/metrics.cpp new file mode 100644 index 00000000000000..a23381fee3e880 --- /dev/null +++ b/src/metrics.cpp @@ -0,0 +1,53 @@ +#include +#include + +#include +#include +#include "util/assert.hpp" + + +using ConstMatrix = Eigen::Map>; +using ConstVector = Eigen::Map>; + +float deepworks::metric::accuracy(const deepworks::Tensor& y_pred, + const deepworks::Tensor& y_true) { + const auto& shape = y_pred.shape(); + DeepWorks_Assert(shape.size() == 2); + int rows = shape[0]; + int cols = shape[1]; + DeepWorks_Assert(y_true.total() == rows); + + ConstMatrix y_pred_mat(y_pred.data(), rows, cols); + ConstVector y_true_vec(y_true.data(), rows); + + float acc = 0; + ConstMatrix::Index pred_col; + // FIXME: Calculate without loop + for (int i = 0; i < rows; i++) { + y_pred_mat.row(i).maxCoeff(&pred_col); + auto label = y_true_vec[i]; + acc += pred_col == label; + } + return acc / rows; +} + +float deepworks::metric::sparse_accuracy(const deepworks::Tensor& y_pred, + const deepworks::Tensor& y_true) { + const auto& shape = y_pred.shape(); + DeepWorks_Assert(y_true.shape() == shape); + DeepWorks_Assert(shape.size() == 2); + int rows = shape[0]; + int cols = shape[1]; + + ConstMatrix y_pred_mat(y_pred.data(), rows, cols); + ConstMatrix y_true_mat(y_true.data(), rows, cols); + float acc = 0; + ConstMatrix::Index pred_col, label_col; + // FIXME: Calculate without loop + for (int i = 0; i < rows; i++) { + y_pred_mat.row(i).maxCoeff(&pred_col); + y_true_mat.row(i).maxCoeff(&label_col); + acc += pred_col == label_col; + } + return acc / rows; +} diff --git a/src/runtime/tensor.cpp b/src/runtime/tensor.cpp index 5d1509a7abc85d..dda3f04be96e85 100644 --- a/src/runtime/tensor.cpp +++ b/src/runtime/tensor.cpp @@ -76,6 +76,10 @@ Tensor::Type *Tensor::data() { return m_descriptor->m_data; } +const Tensor::Type *Tensor::data() const { + return m_descriptor->m_data; +} + size_t Tensor::total() const { return m_descriptor->m_total; } diff --git a/tests/unit/test_metrics.cpp b/tests/unit/test_metrics.cpp new file mode 100644 index 00000000000000..9a79210fde8aa6 --- /dev/null +++ b/tests/unit/test_metrics.cpp @@ -0,0 +1,51 @@ +#include + +#include +#include + +namespace dw = deepworks; + +TEST(TestMetrics, accuracy) { + std::vector labels = {0, 1, 0, 0}; + std::vector predict = { + 0.56, 0.44, + 0.03, 0.97, + 0.57, 0.43, + 0.18, 0.82, + }; + + dw::Tensor y_pred(dw::Shape{4, 2}); + dw::Tensor y_true(dw::Shape{4}); + + std::copy(labels.begin(), labels.end(), y_true.data()); + std::copy(predict.begin(), predict.end(), y_pred.data()); + + float expected = 0.75; + float acc = dw::metric::accuracy(y_pred, y_true); + EXPECT_FLOAT_EQ(expected, acc); +} + +TEST(TestMetrics, sparse_accuracy) { + std::vector labels = { + 1, 0, + 0, 1, + 0, 1, + 1, 0, + }; + std::vector predict = { + 0.56, 0.44, + 0.03, 0.97, + 0.57, 0.43, + 0.18, 0.82, + }; + + dw::Tensor y_pred(dw::Shape{4, 2}); + dw::Tensor y_true(dw::Shape{4, 2}); + + std::copy(labels.begin(), labels.end(), y_true.data()); + std::copy(predict.begin(), predict.end(), y_pred.data()); + + float expected = 0.5; + float acc = dw::metric::sparse_accuracy(y_pred, y_true); + EXPECT_FLOAT_EQ(expected, acc); +}