#include "neuroflow/adamw.hpp" #include #include namespace neuroflow { AdamW::AdamW(float lr, float beta1, float beta2, float eps, float weight_decay) : lr_(lr), beta1_(beta1), beta2_(beta2), eps_(eps), weight_decay_(weight_decay), step_(0) {} void AdamW::add_param_group(const ParamGroup& group) { param_groups_.push_back(group); std::vector group_states; for (size_t i = 0; i < group.params.size(); ++i) { ParamState ps; ps.m = Tensor(group.params[i]->shape_, QuantType::FP32); ps.v = Tensor(group.params[i]->shape_, QuantType::FP32); memset(ps.m.as_fp32(), 0, ps.m.data_size_); memset(ps.v.as_fp32(), 0, ps.v.data_size_); group_states.push_back(std::move(ps)); } states_.push_back(std::move(group_states)); } void AdamW::step() { step_++; double bias_corr1 = 1.0 - std::pow(static_cast(beta1_), static_cast(step_)); double bias_corr2 = 1.0 - std::pow(static_cast(beta2_), static_cast(step_)); for (size_t g = 0; g < param_groups_.size(); ++g) { auto& group = param_groups_[g]; auto& gstates = states_[g]; float group_lr = group.lr > 0 ? group.lr : lr_; float group_wd = group.weight_decay; for (size_t i = 0; i < group.params.size(); ++i) { Tensor* param = group.params[i]; Tensor* grad = group.grads[i]; if (!param || !grad || param->numel() == 0 || grad->numel() == 0) continue; float* p = param->as_fp32(); const float* g = grad->as_fp32(); float* m = gstates[i].m.as_fp32(); float* v = gstates[i].v.as_fp32(); size_t n = param->numel(); for (size_t j = 0; j < n; ++j) { if (!std::isfinite(g[j])) continue; p[j] -= group_lr * group_wd * p[j]; m[j] = beta1_ * m[j] + (1.0f - beta1_) * g[j]; v[j] = beta2_ * v[j] + (1.0f - beta2_) * g[j] * g[j]; float m_hat = static_cast(static_cast(m[j]) / bias_corr1); float v_hat = static_cast(static_cast(v[j]) / bias_corr2); p[j] -= group_lr * m_hat / (std::sqrt(v_hat) + eps_); } } } } void AdamW::set_lr(float lr) { lr_ = lr; } } // namespace neuroflow