SVM勉強メモ2
LS-SVM
前回、SVMをFOBOSを使って解いた。今回はLeast squares support vector machine(LS-SVM)というSVMの派生アルゴリズムを試してみる。これは最小化問題を
としたアルゴリズム。なお、括弧と,は内積を表している。
この式のラグラジアンを微分した結果をまとめると、
で表すことができ、出力は以下のようにカーネルを使用する。
実装
ガウシアンカーネル
double kernel_gaussian(const VectorXd& a, const VectorXd& b, const double sigma) { return exp( -(a - b).squaredNorm() / (2.0 * sigma * sigma) ); }
データ準備
std::vector<double> ori_x; // x座標 std::vector<double> ori_y; // y座標 std::vector<double> label; // -1 or 1 loadData(ori_x, ori_y, label); //PRMLのclassification.txt const int n = label.size(); VectorXd Y(n); for (int i = 0; i < n; ++i) { Y(i) = label.at(i); }
LS-SVMの計算
double gamma = 100.0; // C double sigma = 1.5; MatrixXd K(n, n); for (int i = 0; i < n; ++i) { for (int j = i; j < n; ++j) { VectorXd x1(2); x1 << ori_x.at(i), ori_y.at(i); VectorXd x2(2); x2 << ori_x.at(j), ori_y.at(j); K(i, j) = kernel_gaussian(x1, x2, sigma); K(j, i) = K(i, j); } } MatrixXd E(n + 1, n + 1); E << K+(1.0/gamma)*MatrixXd::Identity(n, n), VectorXd::Ones(n), VectorXd::Ones(n).transpose(), 0.0; VectorXd g(n + 1); g << Y , 0.0; VectorXd f = E.colPivHouseholderQr().solve(g); VectorXd alpha = f.head(n); double b = f.tail(1)(0); // f(n)
出力値の計算
double value(double _x, double _y) { VectorXd x(2); x << _x, _y; double sum = 0.0; const int n = alpha_.size(); for (int i = 0; i < n; ++i) { VectorXd xi(2); xi << ori_x_.at(i), ori_y_.at(i); sum += alpha_(i) * kernel_gaussian(xi, x, sigma); } return sum + b; }