From 6ce0245787c1111aa2d014b2d26fc8220da3adae Mon Sep 17 00:00:00 2001 From: Tomasz Sobczyk Date: Sun, 29 Nov 2020 01:37:07 +0100 Subject: [PATCH] Basic autograd --- src/learn/autograd.h | 350 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 350 insertions(+) create mode 100644 src/learn/autograd.h diff --git a/src/learn/autograd.h b/src/learn/autograd.h new file mode 100644 index 00000000..8a4df2ab --- /dev/null +++ b/src/learn/autograd.h @@ -0,0 +1,350 @@ +#ifndef LEARNER_AUTOGRAD_H +#define LEARNER_AUTOGRAD_H + +#include +#include +#include +#include +#include + +namespace Learner::Autograd::UnivariateStatic +{ + + template + struct Identity + { + using type = T; + }; + + template + using Id = typename Identity::type; + + template + struct VariableParameter + { + using ValueType = T; + + VariableParameter() + { + } + + template + T value(const std::tuple& args) const + { + return std::get(args); + } + + template + T grad(const std::tuple&) const + { + return T(1.0); + } + }; + + template + struct ConstantParameter + { + using ValueType = T; + + ConstantParameter() + { + } + + template + T value(const std::tuple& args) const + { + return std::get(args); + } + + template + T grad(const std::tuple&) const + { + return T(0.0); + } + }; + + template + struct Constant + { + using ValueType = T; + + Constant(T x) : + m_x(std::move(x)) + { + } + + template + T value(const std::tuple&) const + { + return m_x; + } + + template + T grad(const std::tuple&) const + { + return T(0.0); + } + + private: + T m_x; + }; + + template + struct Sum + { + using ValueType = T; + + Sum(LhsT lhs, RhsT rhs) : + m_lhs(std::move(lhs)), + m_rhs(std::move(rhs)) + { + } + + template + T value(const std::tuple& args) const + { + return m_lhs.value(args) + m_rhs.value(args); + } + + template + T grad(const std::tuple& args) const + { + return m_lhs.grad(args) + m_rhs.grad(args); + } + + private: + LhsT m_lhs; + RhsT m_rhs; + }; + + template + auto operator+(LhsT lhs, RhsT rhs) + { + return Sum(std::move(lhs), std::move(rhs)); + } + + template + auto operator+(LhsT lhs, Id rhs) + { + return Sum(std::move(lhs), Constant(rhs)); + } + + template + auto operator+(Id lhs, RhsT rhs) + { + return Sum(Constant(lhs), std::move(rhs)); + } + + template + struct Difference + { + using ValueType = T; + + Difference(LhsT lhs, RhsT rhs) : + m_lhs(std::move(lhs)), + m_rhs(std::move(rhs)) + { + } + + template + T value(const std::tuple& args) const + { + return m_lhs.value(args) - m_rhs.value(args); + } + + template + T grad(const std::tuple& args) const + { + return m_lhs.grad(args) - m_rhs.grad(args); + } + + private: + LhsT m_lhs; + RhsT m_rhs; + }; + + template + auto operator-(LhsT lhs, RhsT rhs) + { + return Difference(std::move(lhs), std::move(rhs)); + } + + template + auto operator-(LhsT lhs, Id rhs) + { + return Difference(std::move(lhs), Constant(rhs)); + } + + template + auto operator-(Id lhs, RhsT rhs) + { + return Difference(Constant(lhs), std::move(rhs)); + } + + template + struct Product + { + using ValueType = T; + + Product(LhsT lhs, RhsT rhs) : + m_lhs(std::move(lhs)), + m_rhs(std::move(rhs)) + { + } + + template + T value(const std::tuple& args) const + { + return m_lhs.value(args) * m_rhs.value(args); + } + + template + T grad(const std::tuple& args) const + { + return m_lhs.grad(args) * m_rhs.value(args) + m_lhs.value(args) * m_rhs.grad(args); + } + + private: + LhsT m_lhs; + RhsT m_rhs; + }; + + template + auto operator*(LhsT lhs, RhsT rhs) + { + return Product(std::move(lhs), std::move(rhs)); + } + + template + auto operator*(LhsT lhs, Id rhs) + { + return Product(std::move(lhs), Constant(rhs)); + } + + template + auto operator*(Id lhs, RhsT rhs) + { + return Product(Constant(lhs), std::move(rhs)); + } + + template + struct Sigmoid + { + using ValueType = T; + + explicit Sigmoid(ArgT x) : + m_x(std::move(x)) + { + } + + template + T value(const std::tuple& args) const + { + return value_(m_x.value(args)); + } + + template + T grad(const std::tuple& args) const + { + return m_x.grad(args) * grad_(m_x.value(args)); + } + + private: + ArgT m_x; + + T value_(T x) const + { + return 1.0 / (1.0 + std::exp(-x)); + } + + T grad_(T x) const + { + return value_(x) * (1.0 - value_(x)); + } + }; + + template + auto sigmoid(ArgT x) + { + return Sigmoid(std::move(x)); + } + + template + struct Pow + { + using ValueType = T; + + explicit Pow(ArgT x, Id exponent) : + m_x(std::move(x)), + m_exponent(std::move(exponent)) + { + } + + template + T value(const std::tuple& args) const + { + return std::pow(m_x.value(args), m_exponent); + } + + template + T grad(const std::tuple& args) const + { + return m_exponent * std::pow(m_x.value(args), m_exponent - T(1.0)) * m_x.grad(args); + } + + private: + ArgT m_x; + T m_exponent; + }; + + template + auto pow(ArgT x, Id exp) + { + return Pow(std::move(x), std::move(exp)); + } + + template + struct Log + { + using ValueType = T; + + explicit Log(ArgT x) : + m_x(std::move(x)) + { + } + + template + T value(const std::tuple& args) const + { + return value_(m_x.value(args)); + } + + template + T grad(const std::tuple& args) const + { + return m_x.grad(args) * grad_(m_x.value(args)); + } + + private: + ArgT m_x; + + T value_(T x) const + { + return std::log(x); + } + + T grad_(T x) const + { + return 1.0 / x; + } + }; + + template + auto log(ArgT x) + { + return Log(std::move(x)); + } + +} + +#endif \ No newline at end of file