Cry*_*ckx 7 c++ statistics performance machine-learning c++17
我有一些类允许复合协方差函数(也称为内核参见https://stats.stackexchange.com/questions/228552/covariance-functions-or-kernels-what-exactly-are-they),然后计算给出的协方差以新内核为例:
auto C = GaussianKernel(50,60) + GaussianKernel(100,200);
auto result = C.covarianceFunction(30.0,40.0);
Run Code Online (Sandbox Code Playgroud)
但问题是,std::function
当我想计算协方差时,我会调用,是否有一种简单的方法可以避免它?
请注意,我想计算一个大的协方差矩阵(大约50K*50K),这意味着性能很重要.
这是代码
class Kernel {
public:
/*
Covariance function : return the covariance between two R.V. for the entire kernel's domain definition.
*/
virtual double covarianceFunction(
double X,
double Y
)const = 0 ;
~Kernel() = default;
};
class FooKernel : public Kernel {
public:
FooKernel(std::function<double(double, double)> fun) : fun_(fun) {}
double covarianceFunction(
double X,
double Y
) const {
return fun_(X, Y);
}
template<class T>
auto operator+(const T b) const {
return FooKernel([b, this](double X, double Y) -> double {
return this->covarianceFunction(X, Y) + b.covarianceFunction(X, Y);
});
}
FooKernel operator=(const FooKernel other) const {
return other;
}
private:
std::function<double(double, double)> fun_;
};
class GaussianKernel : public Kernel {
public:
GaussianKernel(double sigma, double scale) : m_sigma(sigma), m_scale(scale) {}
GaussianKernel(double sigma) : m_sigma(sigma), m_scale(1) {}
/*
A well known covariance function that enforces smooth deformations
Ref : Shape modeling using Gaussian process Morphable Models, Luethi et al.
*/
double covarianceFunction(
double X,
double Y
) const
{
//use diagonal matrix
doulbe result;
result = m_scale * exp(-std::norm(X - Y) / (m_sigma*m_sigma));
return result;
}
template<class T>
auto operator+(const T b) const {
return FooKernel([b, this](double X, double Y) -> double {
auto debugBval = b.covarianceFunction(X, Y);
auto debugAval = this->covarianceFunction(X, Y);
auto test = debugBval + debugAval;
return test;
});
}
private:
double m_sigma;
double m_scale;
};
Run Code Online (Sandbox Code Playgroud)
通过模板化FooKernel,您可以避免使用std :: function.
#include <iostream>
#include <complex>
#include <functional>
class Kernel {
public:
/*
Covariance function : return the covariance between two R.V. for the entire kernel's domain definition.
*/
virtual double covarianceFunction(
double X,
double Y
)const = 0 ;
~Kernel() = default;
};
template <typename Func>
class FooKernel : public Kernel {
public:
FooKernel(Func&& fun) : fun_(std::forward<Func>(fun)) {}
double covarianceFunction(
double X,
double Y
) const {
return fun_(X, Y);
}
template<class T>
auto operator+(const T b) const {
return make_foo_kernel([b, this](double X, double Y) -> double {
return this->covarianceFunction(X, Y) + b.covarianceFunction(X, Y);
});
}
FooKernel operator=(const FooKernel other) const {
return other;
}
private:
Func fun_;
};
template <typename Func>
auto make_foo_kernel(Func&& fun)
{
return FooKernel<Func>(std::forward<Func>(fun));
}
class GaussianKernel : public Kernel {
public:
GaussianKernel(double sigma, double scale) : m_sigma(sigma), m_scale(scale) {}
GaussianKernel(double sigma) : m_sigma(sigma), m_scale(1) {}
/*
A well known covariance function that enforces smooth deformations
Ref : Shape modeling using Gaussian process Morphable Models, Luethi et al.
*/
double covarianceFunction(
double X,
double Y
) const
{
//use diagonal matrix
double result;
result = m_scale * exp(-std::norm(X - Y) / (m_sigma*m_sigma));
return result;
}
template<class T>
auto operator+(const T b) const {
return make_foo_kernel([b, this](double X, double Y) -> double {
auto debugBval = b.covarianceFunction(X, Y);
auto debugAval = this->covarianceFunction(X, Y);
auto test = debugBval + debugAval;
return test;
});
}
private:
double m_sigma;
double m_scale;
};
int main()
{
auto C = GaussianKernel(50,60) + GaussianKernel(100,200);
auto result = C.covarianceFunction(30.0,40.0);
return 0;
}
Run Code Online (Sandbox Code Playgroud)