diff --git a/mlpp/cost/cost.cpp b/mlpp/cost/cost.cpp index 9456325..9ae1450 100644 --- a/mlpp/cost/cost.cpp +++ b/mlpp/cost/cost.cpp @@ -10,6 +10,582 @@ #include #include +real_t MLPPCost::msev(const Ref &y_hat, const Ref &y) { + int y_hat_size = y_hat->size(); + + ERR_FAIL_COND_V(y_hat_size != y->size(), 0); + + const real_t *y_hat_ptr = y_hat->ptr(); + const real_t *y_ptr = y->ptr(); + + real_t sum = 0; + for (int i = 0; i < y_hat_size; ++i) { + sum += (y_hat_ptr[i] - y_ptr[i]) * (y_hat_ptr[i] - y_ptr[i]); + } + + return sum / 2 * y_hat_size; +} +real_t MLPPCost::msem(const Ref &y_hat, const Ref &y) { + int y_hat_data_size = y_hat->data_size(); + + ERR_FAIL_COND_V(y_hat_data_size != y->data_size(), 0); + + const real_t *y_hat_ptr = y_hat->ptr(); + const real_t *y_ptr = y->ptr(); + + real_t sum = 0; + for (int i = 0; i < y_hat_data_size; ++i) { + sum += (y_hat_ptr[i] - y_ptr[i]) * (y_hat_ptr[i] - y_ptr[i]); + } + + return sum / 2.0 * static_cast(y_hat_data_size); +} + +Ref MLPPCost::mse_derivv(const Ref &y_hat, const Ref &y) { + MLPPLinAlg alg; + return alg.subtractionnv(y_hat, y); +} + +Ref MLPPCost::mse_derivm(const Ref &y_hat, const Ref &y) { + MLPPLinAlg alg; + return alg.subtractionm(y_hat, y); +} + +real_t MLPPCost::rmsev(const Ref &y_hat, const Ref &y) { + int y_hat_size = y_hat->size(); + + ERR_FAIL_COND_V(y_hat_size != y->size(), 0); + + const real_t *y_hat_ptr = y_hat->ptr(); + const real_t *y_ptr = y->ptr(); + + real_t sum = 0; + for (int i = 0; i < y_hat_size; ++i) { + sum += (y_hat_ptr[i] - y_ptr[i]) * (y_hat_ptr[i] - y_ptr[i]); + } + + return Math::sqrt(sum / static_cast(y_hat_size)); +} +real_t MLPPCost::rmsem(const Ref &y_hat, const Ref &y) { + int y_hat_data_size = y_hat->data_size(); + + ERR_FAIL_COND_V(y_hat_data_size != y->data_size(), 0); + + const real_t *y_hat_ptr = y_hat->ptr(); + const real_t *y_ptr = y->ptr(); + + real_t sum = 0; + for (int i = 0; i < y_hat_data_size; ++i) { + sum += (y_hat_ptr[i] - y_ptr[i]) * (y_hat_ptr[i] - y_ptr[i]); + } + + return Math::sqrt(sum / static_cast(y_hat->size().y)); +} + +Ref MLPPCost::rmse_derivv(const Ref &y_hat, const Ref &y) { + MLPPLinAlg alg; + + return alg.scalar_multiplynv(1 / (2.0 * Math::sqrt(msev(y_hat, y))), mse_derivv(y_hat, y)); +} +Ref MLPPCost::rmse_derivm(const Ref &y_hat, const Ref &y) { + MLPPLinAlg alg; + + return alg.scalar_multiplym(1 / (2.0 / Math::sqrt(msem(y_hat, y))), mse_derivm(y_hat, y)); +} + +real_t MLPPCost::maev(const Ref &y_hat, const Ref &y) { + int y_hat_size = y_hat->size(); + + ERR_FAIL_COND_V(y_hat_size != y->size(), 0); + + const real_t *y_hat_ptr = y_hat->ptr(); + const real_t *y_ptr = y->ptr(); + + real_t sum = 0; + for (int i = 0; i < y_hat_size; i++) { + sum += ABS((y_hat_ptr[i] - y_ptr[i])); + } + return sum / static_cast(y_hat_size); +} +real_t MLPPCost::maem(const Ref &y_hat, const Ref &y) { + int y_hat_data_size = y_hat->data_size(); + + ERR_FAIL_COND_V(y_hat_data_size != y->data_size(), 0); + + const real_t *y_hat_ptr = y_hat->ptr(); + const real_t *y_ptr = y->ptr(); + + real_t sum = 0; + for (int i = 0; i < y_hat_data_size; ++i) { + sum += ABS((y_hat_ptr[i] - y_ptr[i])); + } + + return sum / static_cast(y_hat_data_size); +} + +Ref MLPPCost::mae_derivv(const Ref &y_hat, const Ref &y) { + int y_hat_size = y_hat->size(); + + const real_t *y_hat_ptr = y_hat->ptr(); + + Ref deriv; + deriv.instance(); + deriv->resize(y_hat_size); + real_t *deriv_ptr = deriv->ptrw(); + + for (int i = 0; i < y_hat_size; ++i) { + int y_hat_ptr_i = y_hat_ptr[i]; + + if (y_hat_ptr_i < 0) { + deriv_ptr[i] = -1; + } else if (y_hat_ptr_i == 0) { + deriv_ptr[i] = 0; + } else { + deriv_ptr[i] = 1; + } + } + + return deriv; +} +Ref MLPPCost::mae_derivm(const Ref &y_hat, const Ref &y) { + int y_hat_data_size = y_hat->data_size(); + + const real_t *y_hat_ptr = y_hat->ptr(); + + Ref deriv; + deriv.instance(); + deriv->resize(y_hat->size()); + real_t *deriv_ptr = deriv->ptrw(); + + for (int i = 0; i < y_hat_data_size; ++i) { + int y_hat_ptr_i = y_hat_ptr[i]; + + if (y_hat_ptr_i < 0) { + deriv_ptr[i] = -1; + } else if (y_hat_ptr_i == 0) { + deriv_ptr[i] = 0; + } else { + deriv_ptr[i] = 1; + } + } + + return deriv; +} + +real_t MLPPCost::mbev(const Ref &y_hat, const Ref &y) { + int y_hat_size = y_hat->size(); + + ERR_FAIL_COND_V(y_hat_size != y->size(), 0); + + const real_t *y_hat_ptr = y_hat->ptr(); + const real_t *y_ptr = y->ptr(); + + real_t sum = 0; + for (int i = 0; i < y_hat_size; ++i) { + sum += (y_hat_ptr[i] - y_ptr[i]); + } + + return sum / static_cast(y_hat_size); +} +real_t MLPPCost::mbem(const Ref &y_hat, const Ref &y) { + int y_hat_data_size = y_hat->data_size(); + + ERR_FAIL_COND_V(y_hat_data_size != y->data_size(), 0); + + const real_t *y_hat_ptr = y_hat->ptr(); + const real_t *y_ptr = y->ptr(); + + real_t sum = 0; + for (int i = 0; i < y_hat_data_size; ++i) { + sum += (y_hat_ptr[i] - y_ptr[i]); + } + + return sum / static_cast(y_hat_data_size); +} + +Ref MLPPCost::mbe_derivv(const Ref &y_hat, const Ref &y) { + MLPPLinAlg alg; + return alg.onevecv(y_hat->size()); +} +Ref MLPPCost::mbe_derivm(const Ref &y_hat, const Ref &y) { + MLPPLinAlg alg; + return alg.onematm(y_hat->size().x, y_hat->size().y); +} + +// Classification Costs +real_t MLPPCost::log_lossv(const Ref &y_hat, const Ref &y) { + int y_hat_size = y_hat->size(); + + ERR_FAIL_COND_V(y_hat_size != y->size(), 0); + + const real_t *y_hat_ptr = y_hat->ptr(); + const real_t *y_ptr = y->ptr(); + + real_t sum = 0; + real_t eps = 1e-8; + for (int i = 0; i < y_hat_size; ++i) { + sum += -(y_ptr[i] * Math::log(y_hat_ptr[i] + eps) + (1 - y_ptr[i]) * Math::log(1 - y_hat_ptr[i] + eps)); + } + + return sum / static_cast(y_hat_size); +} + +real_t MLPPCost::log_lossm(const Ref &y_hat, const Ref &y) { + int y_hat_data_size = y_hat->data_size(); + + ERR_FAIL_COND_V(y_hat_data_size != y->data_size(), 0); + + const real_t *y_hat_ptr = y_hat->ptr(); + const real_t *y_ptr = y->ptr(); + + real_t sum = 0; + real_t eps = 1e-8; + for (int i = 0; i < y_hat_data_size; ++i) { + sum += -(y_ptr[i] * Math::log(y_hat_ptr[i] + eps) + (1 - y_ptr[i]) * Math::log(1 - y_hat_ptr[i] + eps)); + } + + return sum / static_cast(y_hat_data_size); +} + +Ref MLPPCost::log_loss_derivv(const Ref &y_hat, const Ref &y) { + MLPPLinAlg alg; + return alg.additionnv( + alg.scalar_multiplynv(-1, alg.element_wise_division(y, y_hat)), + alg.element_wise_division(alg.scalar_multiplynv(-1, alg.scalar_addnv(-1, y)), alg.scalar_multiplynv(-1, alg.scalar_addnv(-1, y_hat)))); +} + +Ref MLPPCost::log_loss_derivm(const Ref &y_hat, const Ref &y) { + MLPPLinAlg alg; + return alg.additionm( + alg.scalar_multiplym(-1, alg.element_wise_divisionm(y, y_hat)), + alg.element_wise_divisionm(alg.scalar_multiplym(-1, alg.scalar_addm(-1, y)), alg.scalar_multiplym(-1, alg.scalar_addm(-1, y_hat)))); +} + +real_t MLPPCost::cross_entropyv(const Ref &y_hat, const Ref &y) { + int y_hat_size = y_hat->size(); + + ERR_FAIL_COND_V(y_hat_size != y->size(), 0); + + const real_t *y_hat_ptr = y_hat->ptr(); + const real_t *y_ptr = y->ptr(); + + real_t sum = 0; + for (int i = 0; i < y_hat_size; ++i) { + sum += y_ptr[i] * Math::log(y_hat_ptr[i]); + } + + return -1 * sum; +} +real_t MLPPCost::cross_entropym(const Ref &y_hat, const Ref &y) { + int y_hat_data_size = y_hat->data_size(); + + ERR_FAIL_COND_V(y_hat_data_size != y->data_size(), 0); + + const real_t *y_hat_ptr = y_hat->ptr(); + const real_t *y_ptr = y->ptr(); + + real_t sum = 0; + for (int i = 0; i < y_hat_data_size; ++i) { + sum += y_ptr[i] * Math::log(y_hat_ptr[i]); + } + + return -1 * sum; +} + +Ref MLPPCost::cross_entropy_derivv(const Ref &y_hat, const Ref &y) { + MLPPLinAlg alg; + return alg.scalar_multiplynv(-1, alg.element_wise_division(y, y_hat)); +} +Ref MLPPCost::cross_entropy_derivm(const Ref &y_hat, const Ref &y) { + MLPPLinAlg alg; + return alg.scalar_multiplym(-1, alg.element_wise_divisionm(y, y_hat)); +} + +real_t MLPPCost::huber_lossv(const Ref &y_hat, const Ref &y, real_t delta) { + int y_hat_size = y_hat->size(); + + ERR_FAIL_COND_V(y_hat_size != y->size(), 0); + + const real_t *y_hat_ptr = y_hat->ptr(); + const real_t *y_ptr = y->ptr(); + + MLPPLinAlg alg; + real_t sum = 0; + for (int i = 0; i < y_hat_size; ++i) { + if (ABS(y_ptr[i] - y_hat_ptr[i]) <= delta) { + sum += (y_ptr[i] - y_hat_ptr[i]) * (y_ptr[i] - y_hat_ptr[i]); + } else { + sum += 2 * delta * ABS(y_ptr[i] - y_hat_ptr[i]) - delta * delta; + } + } + + return sum; +} +real_t MLPPCost::huber_lossm(const Ref &y_hat, const Ref &y, real_t delta) { + int y_hat_data_size = y_hat->data_size(); + + ERR_FAIL_COND_V(y_hat_data_size != y->data_size(), 0); + + const real_t *y_hat_ptr = y_hat->ptr(); + const real_t *y_ptr = y->ptr(); + + MLPPLinAlg alg; + real_t sum = 0; + for (int i = 0; i < y_hat_data_size; ++i) { + if (ABS(y_ptr[i] - y_hat_ptr[i]) <= delta) { + sum += (y_ptr[i] - y_hat_ptr[i]) * (y_ptr[i] - y_hat_ptr[i]); + } else { + sum += 2 * delta * ABS(y_ptr[i] - y_hat_ptr[i]) - delta * delta; + } + } + + return sum; +} + +Ref MLPPCost::huber_loss_derivv(const Ref &y_hat, const Ref &y, real_t delta) { + int y_hat_size = y_hat->size(); + + ERR_FAIL_COND_V(y_hat_size != y->size(), 0); + + const real_t *y_hat_ptr = y_hat->ptr(); + const real_t *y_ptr = y->ptr(); + + MLPPLinAlg alg; + real_t sum = 0; + + Ref deriv; + deriv.instance(); + deriv->resize(y_hat->size()); + + real_t *deriv_ptr = deriv->ptrw(); + + for (int i = 0; i < y_hat_size; ++i) { + if (ABS(y_ptr[i] - y_hat_ptr[i]) <= delta) { + deriv_ptr[i] = (-(y_ptr[i] - y_hat_ptr[i])); + } else { + if (y_hat_ptr[i] > 0 || y_hat_ptr[i] < 0) { + deriv_ptr[i] = (2 * delta * (y_hat_ptr[i] / ABS(y_hat_ptr[i]))); + } else { + deriv_ptr[i] = (0); + } + } + } + + return deriv; +} +Ref MLPPCost::huber_loss_derivm(const Ref &y_hat, const Ref &y, real_t delta) { + int y_hat_data_size = y_hat->data_size(); + + ERR_FAIL_COND_V(y_hat_data_size != y->data_size(), 0); + + const real_t *y_hat_ptr = y_hat->ptr(); + const real_t *y_ptr = y->ptr(); + + MLPPLinAlg alg; + real_t sum = 0; + + Ref deriv; + deriv.instance(); + deriv->resize(y_hat->size()); + + real_t *deriv_ptr = deriv->ptrw(); + + for (int i = 0; i < y_hat_data_size; ++i) { + if (ABS(y_ptr[i] - y_hat_ptr[i]) <= delta) { + deriv_ptr[i] = (-(y_ptr[i] - y_hat_ptr[i])); + } else { + if (y_hat_ptr[i] > 0 || y_hat_ptr[i] < 0) { + deriv_ptr[i] = (2 * delta * (y_hat_ptr[i] / ABS(y_hat_ptr[i]))); + } else { + deriv_ptr[i] = (0); + } + } + } + + return deriv; +} + +real_t MLPPCost::hinge_lossv(const Ref &y_hat, const Ref &y) { + int y_hat_size = y_hat->size(); + + ERR_FAIL_COND_V(y_hat_size != y->size(), 0); + + const real_t *y_hat_ptr = y_hat->ptr(); + const real_t *y_ptr = y->ptr(); + + real_t sum = 0; + for (int i = 0; i < y_hat_size; ++i) { + sum += MAX(0, 1 - y_ptr[i] * y_hat_ptr[i]); + } + + return sum / static_cast(y_hat_size); +} +real_t MLPPCost::hinge_lossm(const Ref &y_hat, const Ref &y) { + int y_hat_data_size = y_hat->data_size(); + + ERR_FAIL_COND_V(y_hat_data_size != y->data_size(), 0); + + const real_t *y_hat_ptr = y_hat->ptr(); + const real_t *y_ptr = y->ptr(); + + real_t sum = 0; + for (int i = 0; i < y_hat_data_size; ++i) { + sum += MAX(0, 1 - y_ptr[i] * y_hat_ptr[i]); + } + + return sum / static_cast(y_hat_data_size); +} + +Ref MLPPCost::hinge_loss_derivv(const Ref &y_hat, const Ref &y) { + int y_hat_size = y_hat->size(); + + ERR_FAIL_COND_V(y_hat_size != y->size(), 0); + + const real_t *y_hat_ptr = y_hat->ptr(); + const real_t *y_ptr = y->ptr(); + + Ref deriv; + deriv.instance(); + deriv->resize(y_hat->size()); + + real_t *deriv_ptr = deriv->ptrw(); + + for (int i = 0; i < y_hat_size; ++i) { + if (1 - y_ptr[i] * y_hat_ptr[i] > 0) { + deriv_ptr[i] = -y_ptr[i]; + } else { + deriv_ptr[i] = 0; + } + } + + return deriv; +} +Ref MLPPCost::hinge_loss_derivm(const Ref &y_hat, const Ref &y) { + int y_hat_data_size = y_hat->data_size(); + + ERR_FAIL_COND_V(y_hat_data_size != y->data_size(), 0); + + const real_t *y_hat_ptr = y_hat->ptr(); + const real_t *y_ptr = y->ptr(); + + Ref deriv; + deriv.instance(); + deriv->resize(y_hat->size()); + + real_t *deriv_ptr = deriv->ptrw(); + + for (int i = 0; i < y_hat_data_size; ++i) { + if (1 - y_ptr[i] * y_hat_ptr[i] > 0) { + deriv_ptr[i] = -y_ptr[i]; + } else { + deriv_ptr[i] = 0; + } + } + + return deriv; +} + +real_t MLPPCost::hinge_losswv(const Ref &y_hat, const Ref &y, const Ref &weights, real_t C) { + MLPPLinAlg alg; + MLPPReg regularization; + + return C * hinge_lossv(y_hat, y) + regularization.reg_termv(weights, 1, 0, MLPPReg::REGULARIZATION_TYPE_RIDGE); +} +real_t MLPPCost::hinge_losswm(const Ref &y_hat, const Ref &y, const Ref &weights, real_t C) { + MLPPLinAlg alg; + MLPPReg regularization; + + return C * hinge_lossm(y_hat, y) + regularization.reg_termv(weights, 1, 0, MLPPReg::REGULARIZATION_TYPE_RIDGE); +} + +Ref MLPPCost::hinge_loss_derivwv(const Ref &y_hat, const Ref &y, real_t C) { + MLPPLinAlg alg; + MLPPReg regularization; + + return alg.scalar_multiplynv(C, hinge_loss_derivv(y_hat, y)); +} +Ref MLPPCost::hinge_loss_derivwm(const Ref &y_hat, const Ref &y, real_t C) { + MLPPLinAlg alg; + MLPPReg regularization; + + return alg.scalar_multiplym(C, hinge_loss_derivm(y_hat, y)); +} + +real_t MLPPCost::wasserstein_lossv(const Ref &y_hat, const Ref &y) { + int y_hat_size = y_hat->size(); + + ERR_FAIL_COND_V(y_hat_size != y->size(), 0); + + const real_t *y_hat_ptr = y_hat->ptr(); + const real_t *y_ptr = y->ptr(); + + real_t sum = 0; + for (int i = 0; i < y_hat_size; ++i) { + sum += y_hat_ptr[i] * y_ptr[i]; + } + + return -sum / static_cast(y_hat_size); +} +real_t MLPPCost::wasserstein_lossm(const Ref &y_hat, const Ref &y) { + int y_hat_data_size = y_hat->data_size(); + + ERR_FAIL_COND_V(y_hat_data_size != y->data_size(), 0); + + const real_t *y_hat_ptr = y_hat->ptr(); + const real_t *y_ptr = y->ptr(); + + real_t sum = 0; + for (int i = 0; i < y_hat_data_size; ++i) { + sum += y_hat_ptr[i] * y_ptr[i]; + } + + return -sum / static_cast(y_hat_data_size); +} + +Ref MLPPCost::wasserstein_loss_derivv(const Ref &y_hat, const Ref &y) { + MLPPLinAlg alg; + + return alg.scalar_multiplynv(-1, y); // Simple. +} +Ref MLPPCost::wasserstein_loss_derivm(const Ref &y_hat, const Ref &y) { + MLPPLinAlg alg; + + return alg.scalar_multiplym(-1, y); // Simple. +} + +real_t MLPPCost::dual_form_svm(const Ref &alpha, const Ref &X, const Ref &y) { + MLPPLinAlg alg; + + Ref Y = alg.diagm(y); // Y is a diagnoal matrix. Y[i][j] = y[i] if i = i, else Y[i][j] = 0. Yt = Y. + Ref K = alg.matmultm(X, alg.transposem(X)); // TO DO: DON'T forget to add non-linear kernelizations. + Ref Q = alg.matmultm(alg.matmultm(alg.transposem(Y), K), Y); + + Ref alpha_m; + alpha_m.instance(); + alpha_m->resize(Size2i(alpha->size(), 1)); + alpha_m->set_row_mlpp_vector(0, alpha); + + Ref alpha_m_res = alg.matmultm(alg.matmultm(alpha_m, Q), alg.transposem(alpha_m)); + + real_t alphaQ = alpha_m_res->get_element(0, 0); + Ref one = alg.onevecv(alpha->size()); + + return -alg.dotv(one, alpha) + 0.5 * alphaQ; +} + +Ref MLPPCost::dual_form_svm_deriv(const Ref &alpha, const Ref &X, const Ref &y) { + MLPPLinAlg alg; + + Ref Y = alg.diagm(y); // Y is a diagnoal matrix. Y[i][j] = y[i] if i = i, else Y[i][j] = 0. Yt = Y. + Ref K = alg.matmultm(X, alg.transposem(X)); // TO DO: DON'T forget to add non-linear kernelizations. + Ref Q = alg.matmultm(alg.matmultm(alg.transposem(Y), K), Y); + Ref alphaQDeriv = alg.mat_vec_multv(Q, alpha); + Ref one = alg.onevecv(alpha->size()); + + return alg.subtractionm(alphaQDeriv, one); +} + +// ====== OLD ====== real_t MLPPCost::MSE(std::vector y_hat, std::vector y) { real_t sum = 0; diff --git a/mlpp/cost/cost.h b/mlpp/cost/cost.h index dcfd180..aa5ce26 100644 --- a/mlpp/cost/cost.h +++ b/mlpp/cost/cost.h @@ -10,11 +10,85 @@ #include "core/math/math_defs.h" +#include "core/object/reference.h" + #include +#include "../lin_alg/mlpp_matrix.h" +#include "../lin_alg/mlpp_vector.h" + +//void set_weights(const Ref &val); +//void set_bias(const Ref &val); + +class MLPPCost : public Reference { + GDCLASS(MLPPCost, Reference); -class MLPPCost { public: + real_t msev(const Ref &y_hat, const Ref &y); + real_t msem(const Ref &y_hat, const Ref &y); + + Ref mse_derivv(const Ref &y_hat, const Ref &y); + Ref mse_derivm(const Ref &y_hat, const Ref &y); + + real_t rmsev(const Ref &y_hat, const Ref &y); + real_t rmsem(const Ref &y_hat, const Ref &y); + + Ref rmse_derivv(const Ref &y_hat, const Ref &y); + Ref rmse_derivm(const Ref &y_hat, const Ref &y); + + real_t maev(const Ref &y_hat, const Ref &y); + real_t maem(const Ref &y_hat, const Ref &y); + + Ref mae_derivv(const Ref &y_hat, const Ref &y); + Ref mae_derivm(const Ref &y_hat, const Ref &y); + + real_t mbev(const Ref &y_hat, const Ref &y); + real_t mbem(const Ref &y_hat, const Ref &y); + + Ref mbe_derivv(const Ref &y_hat, const Ref &y); + Ref mbe_derivm(const Ref &y_hat, const Ref &y); + + // Classification Costs + real_t log_lossv(const Ref &y_hat, const Ref &y); + real_t log_lossm(const Ref &y_hat, const Ref &y); + + Ref log_loss_derivv(const Ref &y_hat, const Ref &y); + Ref log_loss_derivm(const Ref &y_hat, const Ref &y); + + real_t cross_entropyv(const Ref &y_hat, const Ref &y); + real_t cross_entropym(const Ref &y_hat, const Ref &y); + + Ref cross_entropy_derivv(const Ref &y_hat, const Ref &y); + Ref cross_entropy_derivm(const Ref &y_hat, const Ref &y); + + real_t huber_lossv(const Ref &y_hat, const Ref &y, real_t delta); + real_t huber_lossm(const Ref &y_hat, const Ref &y, real_t delta); + + Ref huber_loss_derivv(const Ref &y_hat, const Ref &y, real_t delta); + Ref huber_loss_derivm(const Ref &y_hat, const Ref &y, real_t delta); + + real_t hinge_lossv(const Ref &y_hat, const Ref &y); + real_t hinge_lossm(const Ref &y_hat, const Ref &y); + + Ref hinge_loss_derivv(const Ref &y_hat, const Ref &y); + Ref hinge_loss_derivm(const Ref &y_hat, const Ref &y); + + real_t hinge_losswv(const Ref &y_hat, const Ref &y, const Ref &weights, real_t C); + real_t hinge_losswm(const Ref &y_hat, const Ref &y, const Ref &weights, real_t C); + + Ref hinge_loss_derivwv(const Ref &y_hat, const Ref &y, real_t C); + Ref hinge_loss_derivwm(const Ref &y_hat, const Ref &y, real_t C); + + real_t wasserstein_lossv(const Ref &y_hat, const Ref &y); + real_t wasserstein_lossm(const Ref &y_hat, const Ref &y); + + Ref wasserstein_loss_derivv(const Ref &y_hat, const Ref &y); + Ref wasserstein_loss_derivm(const Ref &y_hat, const Ref &y); + + real_t dual_form_svm(const Ref &alpha, const Ref &X, const Ref &y); // TO DO: DON'T forget to add non-linear kernelizations. + + Ref dual_form_svm_deriv(const Ref &alpha, const Ref &X, const Ref &y); + // Regression Costs real_t MSE(std::vector y_hat, std::vector y); real_t MSE(std::vector> y_hat, std::vector> y); @@ -80,9 +154,6 @@ public: real_t dualFormSVM(std::vector alpha, std::vector> X, std::vector y); // TO DO: DON'T forget to add non-linear kernelizations. std::vector dualFormSVMDeriv(std::vector alpha, std::vector> X, std::vector y); - -private: }; - #endif /* Cost_hpp */ diff --git a/mlpp/lin_alg/lin_alg.cpp b/mlpp/lin_alg/lin_alg.cpp index da635cf..5832232 100644 --- a/mlpp/lin_alg/lin_alg.cpp +++ b/mlpp/lin_alg/lin_alg.cpp @@ -1867,6 +1867,21 @@ real_t MLPPLinAlg::dot(std::vector a, std::vector b) { return c; } +real_t MLPPLinAlg::dotv(const Ref &a, const Ref &b) { + int a_size = a->size(); + + ERR_FAIL_COND_V(a_size != b->size(), 0); + + const real_t *a_ptr = a->ptr(); + const real_t *b_ptr = b->ptr(); + + real_t c = 0; + for (int i = 0; i < a_size; ++i) { + c += a_ptr[i] * b_ptr[i]; + } + return c; +} + std::vector MLPPLinAlg::cross(std::vector a, std::vector b) { // Cross products exist in R^7 also. Though, I will limit it to R^3 as Wolfram does this. std::vector> mat = { onevec(3), a, b }; @@ -1905,6 +1920,25 @@ std::vector> MLPPLinAlg::diag(std::vector a) { return B; } +Ref MLPPLinAlg::diagm(const Ref &a) { + int a_size = a->size(); + + Ref B; + B.instance(); + + B->resize(Size2i(a_size, a_size)); + B->fill(0); + + const real_t *a_ptr = a->ptr(); + real_t *b_ptr = B->ptrw(); + + for (int i = 0; i < a_size; ++i) { + b_ptr[B->calculate_index(i, i)] = a_ptr[i]; + } + + return B; +} + std::vector MLPPLinAlg::full(int n, int k) { std::vector full; full.resize(n); diff --git a/mlpp/lin_alg/lin_alg.h b/mlpp/lin_alg/lin_alg.h index 1f4acf6..26e02bb 100644 --- a/mlpp/lin_alg/lin_alg.h +++ b/mlpp/lin_alg/lin_alg.h @@ -213,6 +213,7 @@ public: Ref cbrtv(const Ref &a); real_t dot(std::vector a, std::vector b); + real_t dotv(const Ref &a, const Ref &b); std::vector cross(std::vector a, std::vector b); @@ -229,6 +230,7 @@ public: Ref fullv(int n, int k); std::vector> diag(std::vector a); + Ref diagm(const Ref &a); std::vector sin(std::vector a); std::vector cos(std::vector a);