From f30834f7e69944b23305d77ecf87061190c26576 Mon Sep 17 00:00:00 2001 From: Yi Zhang Date: Fri, 25 Oct 2024 10:27:08 +0800 Subject: [PATCH] update --- lib/optimization/loss_func.cpp | 18 ++++++--- lib/optimization/loss_func.h | 68 ++++++++++++++++++++++++++++++++-- 2 files changed, 78 insertions(+), 8 deletions(-) diff --git a/lib/optimization/loss_func.cpp b/lib/optimization/loss_func.cpp index 063171d..004977f 100644 --- a/lib/optimization/loss_func.cpp +++ b/lib/optimization/loss_func.cpp @@ -121,11 +121,14 @@ double gctl::loss_func::evaluate(const array &x, array &g) double gctl::loss_func::evaluate(double inp, int id) { + if (!init_) throw std::runtime_error("[gctl::loss_func] Not initialized."); + double val = (inp - tars_[id])/us_[id]; if (ntype_ == L1) val = fabs(val); if (ntype_ == L2) val = val*val; - + if (ntype_ == Lp) val = pow(val*val + eps_*eps_, 0.5*p_); + loss_ += val; return val/tnum_; @@ -133,6 +136,8 @@ double gctl::loss_func::evaluate(double inp, int id) double gctl::loss_func::get_loss() { + if (!init_) throw std::runtime_error("[gctl::loss_func] Not initialized."); + double l = loss_; loss_ = 0.0; @@ -141,10 +146,13 @@ double gctl::loss_func::get_loss() double gctl::loss_func::gradient(double inp, int id) { - double val; - if (ntype_ == L1 && val >= 0) val = 1.0/(us_[id]*tnum_); - if (ntype_ == L1 && val < 0) val = -1.0/(us_[id]*tnum_); - if (ntype_ == L2) val = 2.0*(inp - tars_[id])/(us_[id]*us_[id]*tnum_); + if (!init_) throw std::runtime_error("[gctl::loss_func] Not initialized."); + + double val = (inp - tars_[id])/us_[id]; + if (ntype_ == L1 && val >= 0) val = 1.0/tnum_; + if (ntype_ == L1 && val < 0) val = -1.0/tnum_; + if (ntype_ == L2) val = 2.0*val/(us_[id]*tnum_); + if (ntype_ == Lp) val = p_*pow(val*val + eps_*eps_, 0.5*p_ - 1)*val/(us_[id]*tnum_); return val; } \ No newline at end of file diff --git a/lib/optimization/loss_func.h b/lib/optimization/loss_func.h index 1c1cd54..a448212 100644 --- a/lib/optimization/loss_func.h +++ b/lib/optimization/loss_func.h @@ -33,21 +33,83 @@ namespace gctl { + /** + * @brief 损失函数对象,可计算L1范数, L2范数平方,Lp范数定义的数据拟合差及相应的模型偏导数(按数据个数归一化)。 + * 损失函数的定义为:Phi = Lp(d - d^tar)^2/num(d) + */ class loss_func { public: - loss_func(); - loss_func(const array &tar, norm_type_e n_type, double p = 2.0, double eps = 1e-16); - virtual ~loss_func(); + loss_func(); ///< 构造函数 + /** + * @brief 构造函数 + * + * @param tar 数据拟合差目标 + * @param n_type 拟合差函数范数类型 + * @param p Lp范数的阶次 + * @param eps Lp范数分母内的小值(防止分母变为奇异值) + */ + loss_func(const array &tar, norm_type_e n_type, double p = 2.0, double eps = 1e-16); + + virtual ~loss_func(); ///< 析构函数 + + /** + * @brief 初始化函数 + * + * @param tar 数据拟合差目标 + * @param n_type 拟合差函数范数类型 + * @param p Lp范数的阶次 + * @param eps Lp范数分母内的小值(防止分母变为奇异值) + */ void init(const array &tar, norm_type_e n_type, double p = 2.0, double eps = 1e-16); + + /** + * @brief 设置目标数据的不确定度 + * + * @param uncer 不确定度 + */ void set_uncertainty(double uncer); + + /** + * @brief 设置目标数据的不确定度 + * + * @param uncer 不确定度数组,长度与目标数据一致 + */ void set_uncertainty(const array &uncer); + /** + * @brief 计算单个输入模型数据的拟合差,同时将计算值累计至内部变量 + * + * @param inp 输入数据值 + * @param id 输入数据的索引 + * @return 单个数据拟合差值 + */ double evaluate(double inp, int id); + + /** + * @brief 计算输入模型的数据拟合差与模型梯度 + * + * @param x 输入模型,长度与目标数据相等 + * @param g 数据拟合差相对于模型的梯度 + * @return 数据拟合差值 + */ double evaluate(const array &x, array &g); + /** + * @brief 返回内置的数据拟合差函数值,然后将值重设为0 + * + * @return 累计的数据拟合差 + */ double get_loss(); + + /** + * @brief 计算数据拟合差函数相对于单个输入模型数据的梯度 + * + * @param inp 输入数据值 + * @param id 输入数据的索引 + * @return 单个数据拟合差函数的梯度 + */ double gradient(double inp, int id); private: