/******************************************************************** ** Image Component Library (ICL) ** ** ** ** Copyright (C) 2006-2013 CITEC, University of Bielefeld ** ** Neuroinformatics Group ** ** Website: www.iclcv.org and ** ** http://opensource.cit-ec.de/projects/icl ** ** ** ** File : ICLMath/src/ICLMath/PolynomialRegression.cpp ** ** Module : ICLMath ** ** Authors: Christof Elbrechter ** ** ** ** ** ** GNU LESSER GENERAL PUBLIC LICENSE ** ** This file may be used under the terms of the GNU Lesser General ** ** Public License version 3.0 as published by the ** ** ** ** Free Software Foundation and appearing in the file LICENSE.LGPL ** ** included in the packaging of this file. Please review the ** ** following information to ensure the license requirements will ** ** be met: http://www.gnu.org/licenses/lgpl-3.0.txt ** ** ** ** The development of this software was supported by the ** ** Excellence Cluster EXC 277 Cognitive Interaction Technology. ** ** The Excellence Cluster EXC 277 is a grant of the Deutsche ** ** Forschungsgemeinschaft (DFG) in the context of the German ** ** Excellence Initiative. ** ** ** ********************************************************************/ #include #include #include using namespace icl::utils; namespace icl{ namespace math{ namespace{ template struct ConstAttrib : public PolynomialRegressionAttrib{ T t; ConstAttrib(const T &t):t(t){} virtual T compute(const T *) const{ return t; } virtual std::string toString() const{ return str(t); } virtual PolynomialRegressionAttrib *copy() const{ return new ConstAttrib(t); } }; template struct GenPowerAttrib : public PolynomialRegressionAttrib{ int idx; T exponent; GenPowerAttrib(int idx, const T &exponent):idx(idx),exponent(exponent){} virtual T compute(const T *row) const{ return ::pow(row[idx], exponent); } virtual std::string toString() const{ return "x"+str(idx)+"^"+str(exponent); } virtual PolynomialRegressionAttrib *copy() const{ return new GenPowerAttrib(idx,exponent); } }; template struct PowerAttrib : public PolynomialRegressionAttrib{ int idx; PowerAttrib(int idx):idx(idx){} virtual T compute(const T *row) const{ return icl::utils::power(row[idx]); } virtual std::string toString() const{ return "x"+str(idx)+"^"+str(EXPONENT); } virtual PolynomialRegressionAttrib *copy() const{ return new PowerAttrib(idx); } }; template struct GenMixedAttrib : public PolynomialRegressionAttrib{ std::vector idxs; GenMixedAttrib(const std::vector &idxs):idxs(idxs){} virtual T compute(const T *row) const{ float product = 1; for(size_t i=0;i *copy() const{ return new GenMixedAttrib(idxs); } }; template struct MixedAttrib : public PolynomialRegressionAttrib{ int idxs[N]; MixedAttrib(const int idxs[N]){ std::copy(idxs,idxs+N,this->idxs); } virtual T compute(const T *row) const{ if(N == 1) return row[idxs[0]]; if(N == 2) return row[idxs[0]] * row[idxs[1]]; if(N == 3) return row[idxs[0]] * row[idxs[1]] * row[idxs[2]]; if(N == 4) return row[idxs[0]] * row[idxs[1]] * row[idxs[2]] * row[idxs[3]]; if(N == 5) return row[idxs[0]] * row[idxs[1]] * row[idxs[2]] * row[idxs[3]] * row[idxs[4]]; float product = 1; for(size_t i=0;i *copy() const{ return new MixedAttrib(idxs); } }; inline std::string remove_spaces(const std::string s){ std::ostringstream stream; for(size_t i=0;i(s.substr(1)); } inline bool is_int(float f){ return !(f - (int)f); } template void apply_params(const std::vector*> &ps, const T *xrow, T *xs){ for(size_t i=0;icompute(xrow); } } } template PolynomialRegression::PolynomialRegression(const std::string &function){ m_result.setup(function); } template PolynomialRegression::Result::Result(const PolynomialRegression::Result &r){ *this = r; } template typename PolynomialRegression::Result &PolynomialRegression::Result::operator=(const PolynomialRegression::Result &r){ for(size_t i=0;icopy(); } m_function = r.m_function; m_params = r.m_params; m_xbuf = r.m_xbuf; m_resultBuf = r.m_resultBuf; m_attribMaxIndex = r.m_attribMaxIndex; return *this; } template const typename PolynomialRegression::Result & PolynomialRegression::apply(const typename PolynomialRegression::Matrix &xs, const typename PolynomialRegression::Matrix &ys,bool useSVD){ ICLASSERT_THROW(xs.rows() == ys.rows(),ICLException("PolynomialRegression::apply: xs.rows() must be equal to ys.rows()")); const int &M = m_result.m_attribMaxIndex; ICLASSERT_THROW((int)xs.cols() > M,ICLException("PolynomialRegression::apply: maximum attribute index found is " + str(M) + " but the given data matrix (xs) has only " + str(xs.cols()) + " columns")); m_buf.setBounds(m_result.m_attribs.size(), xs.rows()); for(unsigned int i=0;i const typename PolynomialRegression::Matrix &PolynomialRegression::Result::operator() (const typename PolynomialRegression::Matrix &xs) const{ m_xbuf.setBounds(m_attribs.size(), xs.rows()); for(unsigned i=0;i std::string PolynomialRegression::getFunctionString() const{ std::ostringstream stream; for(size_t i=0;itoString(); if(i < m_result.m_attribs.size()-1) stream << " + "; } return stream.str(); } template std::string PolynomialRegression::Result::toString(const std::vector &rowLabels) const { std::ostringstream stream; std::cout << "Polyonomial Regression Result:" << std::endl; for(unsigned int y=0;y y){ stream << rowLabels[y] << " = "; }else{ stream << "y[" << y << "] = "; } std::vector*> atts = getAttribs(); for(size_t x=0;xtoString() == "1"){ stream << (x ? fabs(getParams()(y,x)) : getParams()(x,y) )<< " "; }else{ stream << (x ? fabs(getParams()(y,x)) : getParams()(x,y) )<< " * " << atts[x]->toString(); } if(x < atts.size()-1){ if(getParams()(x,y) < 0){ stream << " - "; }else{ stream << " - "; } } } stream << std::endl; } stream << std::endl; return stream.str(); } template void PolynomialRegression::Result::setup(const std::string &function){ m_function = function; std::vector ts = icl::utils::tok(remove_spaces(function),"+"); int maxIdx = -1; for(size_t i=0;i ab = icl::utils::tok(s,"^"); ICLASSERT_THROW(ab.size() == 2, ICLException("PolynomialRegression: error in token: " + s)); int idx = get_idx(ab[0]); if(idx > maxIdx) maxIdx = idx; float exponent = parse(ab[1]); if(is_int(exponent) && exponent < 6){ int e = exponent; switch(e){ case 1: m_attribs.push_back(new PowerAttrib(idx)); break; case 2: m_attribs.push_back(new PowerAttrib(idx)); break; case 3: m_attribs.push_back(new PowerAttrib(idx)); break; case 4: m_attribs.push_back(new PowerAttrib(idx)); break; case 5: m_attribs.push_back(new PowerAttrib(idx)); break; default: m_attribs.push_back(new GenPowerAttrib(idx,e)); break; } }else{ m_attribs.push_back(new GenPowerAttrib(idx,exponent)); break; } }else if(s.find('*') != std::string::npos){ std::vector vars = tok(s,"*"); std::vector idxs(vars.size()); for(size_t j=0;j maxIdx) maxIdx = idxs[j]; } switch(idxs.size()){ case 2: m_attribs.push_back(new MixedAttrib(&*idxs.begin())); break; case 3: m_attribs.push_back(new MixedAttrib(&*idxs.begin())); break; case 4: m_attribs.push_back(new MixedAttrib(&*idxs.begin())); break; case 5: m_attribs.push_back(new MixedAttrib(&*idxs.begin())); break; default: m_attribs.push_back(new GenMixedAttrib(idxs)); break; } }else if(s[0] == 'x'){ int idx = get_idx(s); if(idx > maxIdx) maxIdx = idx; m_attribs.push_back(new MixedAttrib(&idx)); }else{ m_attribs.push_back(new ConstAttrib(parse(s))); } } m_attribMaxIndex = maxIdx; } template void PolynomialRegression::Result::save(const std::string &xmlFileName) const { DEBUG_LOG(toString()); ConfigFile cfg; cfg.setPrefix("config.polynomial-regression-result."); cfg["function"] = m_function; cfg["parameters.dim.cols"] = (int)m_params.cols(); cfg["parameters.dim.rows"] = (int)m_params.rows(); cfg["parameters.values"] = str(m_params); cfg.save(xmlFileName); } template PolynomialRegression::Result::Result(const std::string &xmlFileName){ ConfigFile cfg(xmlFileName); cfg.setPrefix("config.polynomial-regression-result."); setup(cfg["function"].as()); m_params.setBounds(cfg["parameters.dim.cols"].as(), cfg["parameters.dim.rows"].as()); std::istringstream stream(cfg["parameters.values"].as()); stream >> m_params; } template class ICLMath_API PolynomialRegression; template class ICLMath_API PolynomialRegression; } }