- Published on
Eigen で N 次の多項式の係数を求める
- Authors
- Name
- Daisuke Kobayashi
- https://twitter.com
Numpy, Matlab の polyval のように,Eigen で多項式近似の係数を求めるプログラムを書きました.
#include <Eigen/Dense>
#include <cmath>
#include <iostream>
bool PolyVal(const Eigen::VectorXd& x, const Eigen::VectorXd& y, int order,
Eigen::VectorXd& p, double* r2) {
using namespace Eigen;
if (order < 1)
return false;
int N = order + 1;
MatrixXd W(y.rows(), N);
VectorXd w(N);
for (int row = 0; row < W.rows(); row++) {
for (int i = 0; i < N; i++)
w(i) = std::pow(x(row), order - i);
W.row(row) = w;
}
p = W.jacobiSvd(ComputeThinU | ComputeThinV).solve(y);
VectorXd pred(y.rows());
pred = W * p;
VectorXd mean = VectorXd::Constant(y.rows(), y.mean());
double ss_res = ((y - pred).transpose() * (y - pred)).sum();
double ss_tot = ((y - mean).transpose() * (y - mean)).sum();
*r2 = 1.0 - ss_res / ss_tot;
return true;
}
int main() {
using namespace Eigen;
VectorXd x(13);
x << 0.1,
1.0,
5.0,
10.0,
20.0,
40.0,
60.0,
80.0,
100.0,
150.0,
200.0,
250.0,
300.0;
VectorXd y(13);
y << 7569.9,
7609.6,
7684.4,
7778.6,
8007.3,
8619.8,
9461.2,
10482.6,
11572.4,
15021.0,
19210.4,
23777.2,
28426.9;
VectorXd p;
double r2;
if (PolyVal(x, y, 2, p, &r2)) {
std::cout << "p = " << p.transpose() << std::endl;
std::cout << "R2 = " << r2 << std::endl;
}
if (PolyVal(x, y, 1, p, &r2)) {
std::cout << "p = " << p.transpose() << std::endl;
std::cout << "R2 = " << r2 << std::endl;
}
return 0;
}
サンプルでは 1 次と 2 次の近似を行うようにしています.実行すると下記のように出力されます.
$ clang++ -I/usr/local/Cellar/eigen/3.3.1/include/eigen3 -o main main.cc
$ ./main
p = 0.139124 29.4058 7420.85
R2 = 0.99904
p = 67.3193 6411.87
R2 = 0.972701