Shogun

概要 Abstract
Shogun は C++ で実装された機械学習ライブラリで,C++, Python, Octave, Matlab などに対するインターフェイスを提供している.分類,回帰,クラスタリングなどにおける多数の機械学習アルゴリズムを収録する.
Shogun is machine learning library implemented by C++, and is providing interface for C++, Python, Octave, Matlab. It Includes a large number of machine learning algorithm such as Sequence, recursion, clustering.
目次 Table of contents

機械学習 (Machine Learning) Machine Learning

機械学習とは,人間が持つような学習機能をコンピュータにも持たせることを目的とした学問分野である.Shogun には以下のような種類の学習アルゴリズムが実装されている.

Machine learning is discipline for the purpose of letting computer have learning function which human being has. Learning algorithm of the following kinds is implemented in Shogun.

教師あり学習 (Supervised Learning) Supervised Learning
入力と出力が対になっているデータが与えられた場合に,入力から出力を予想するモデルを作る.回帰 (Regression) または分類 (Classification) に分けられる.例:顔認識.
When pairing data of output/input are given, prepare model expecting output from input. It is classified by Regression or Classification. Example: Face recognition.
クラスタリング (Clustering) Clustering
教師なし学習 (Unsupervised Learning) の一種.入力のみのデータが与えられた場合に,そのデータの構造などを推定する.クラスタリングは教師なし学習の一種.
Kind of Unsupervised Learning. When data only for input are given, estimate structures of the data. Clustering is kind of learning without teacher.
その他の統計モデル Other statistical models
隠れマルコフモデル (Hidden Markov Model; HMM) など.
Hidden Markov Model(HMM); etc.

Shogun に実装されているアルゴリズム一覧は以下から見られる.

Algorithmic list implemented in Shogun is as following.

教師あり学習 (Supervised Learning) Supervised Learning

教師あり学習は,「入力と出力の対が多数与えられたとき,これらのデータをもとにして,任意の入力特徴量から出力特徴量を予想するモデルを作る」学習である.ここで「入力」や「出力」は任意の空間のベクトルで,実数でも整数でも,何次元あってもよい.Shogun では入力のことを「特徴量(Feature)」,出力のことを「ラベル(Label)」と呼ぶ.ラベルがクラスを表すインデックス(整数)の場合を特に「分類(Classification)」といい,ラベルが連続量のベクトルの場合を特に「回帰(Regression)」という.

Supervised learning is a learning that, "When a lot of pairs of input and output were given, from these data, create model expecting output characteristic quantity from any input characteristic quantity.". Here, "Input" and "output" are any spatial vectors, and are OK if these are real number, short number, several dimensions. In Shogun, Input is called "Quantity of characteristic (Feature)", and output is called "Label". If label is Index (short number) which expresses class, say in particular "sequence (Classification)", and if label is vector of continuous variate, say in particular "regression (Regression)".

回帰 (Regression) Regression

回帰とは,ようするに関数近似器である.入力(一般に多次元ベクトル)と出力(一般に多次元ベクトル)の対がたくさん与えられたときに,入力から出力を推定するモデル(関数近似器)を学習する.学習されたモデルは,学習データにない任意のモデルに対しても,出力を推定 (estimate) できるようになる.

Regression is, in brief, function approximation device. You Learn model (function approximation device) to estimate output from input, when a lot of pairs of input (generally multidimensional vector) and output (generally multidimensional vector) were given. Learned model comes to estimate output for any model that learning data do not have.

下図の左は学習データ(青の点群),中央は学習された回帰モデル(赤線)を表す. この例では,入力は1次元ベクトル,出力も1次元ベクトルである. なお,図の右のような補間 (interpolation) 手法も一種の回帰だが,補間の場合はすべての学習データ点を通るようにモデルを作るので,ノイズを含むデータで用いると精度よく出力が予測できなくなる.一方,ガウス過程回帰モデル (Gaussian process regression) などの回帰モデルではノイズを考慮した学習を行うので,ノイズを含むデータで学習した場合でもある程度推定精度が期待できる.

The center expresses learned regression model (red line). In this example, Input is one dimension vector, and output is one dimension vector, too. In addition, interpolation technique such as the right of figure is a kind of regression, too, but in the case of interpolation, as creating model to pass all learning data points, cannot predict accurate output when using with data including noise. On the other hand, learning in consideration of noise is performed in Regression models such as Gaussian process regression model, so we can expect estimated accuracy to some extent when learning it by data including noise.

ml-reg1.png
回帰モデルの学習データ.
Learning data of regression model.
ml-reg2.png
学習された回帰モデル(赤の曲線).
Regression model (red curve) that was learned.
ml-intrpl.png
補間によって生成した曲線.
Curve which was formed by interpolation.

回帰問題の例として,ロボットの運動学の学習などが該当する(入力:ロボットの関節角ベクトル,出力:手先位置).

As example of the issue of regression, Kinematical learning of robot falls on it. (Input: Joint angle vector of robot, output: Fingers position).

分類 (Classification) Classification

分類器 (Classifier) の学習は,入力(一般に多次元ベクトル)とラベル(整数)の対がたくさん与えられたときに,入力から出力を推定するモデル(関数近似器)を学習する.学習されたモデルは,学習データにない任意のモデルに対しても,出力を推定 (estimate) できるようになる. ラベルを1次元の連続値ベクトルだと思えば,この問題は回帰問題でも解けるので,分類と回帰は同じ性質の問題だということがわかる.

For Learning of Classifier, learn model (function approximation device) to estimate output from input when a lot of pairs of input (generally multidimensional vector) and label (short number) were given. Learned model comes to estimate output for any model that learning data do not have. If assuming that label is one-dimensional consecutive value vector, because this problem is solved if it is issue of regression, it is found that sequence and regression is a problem of the same nature.

下図の左は学習データ(青の点群),右は学習された分類器(赤線)を表す. この例では,入力は2次元ベクトル,出力は2値(+1か-1)のラベルである.

The right expresses learned classifier (red line), and the left of the chart below expresses learning data (blue point group). In this example, Input is two dimensions vector, and the output is label of binary (+1 or -1).

ml-cls1.png
分類器の学習データ.
Learning data of classifier.
ml-cls2.png
学習された分類器(赤の境界線).
Classifier (red boarder line) which was learned.

分類の例として,顔認識を考える.入力は顔画像で,ラベルは人を表すインデックスとする(実際には顔画像を直接用いると次元が大きすぎるので低次元化処理を行うが,ここでは特に考慮しない).この場合,学習に使うデータは,Aさんの顔画像1,Aさんの顔画像2,...,Bさんの顔画像1,... というふうな,特徴量とラベルの対を多数用意したものである.このデータを使って「分類器」を学習する.すると,学習した分類器は,任意の特徴量(顔画像)を与えたときに,そのラベル(人を表すインデックス)を推定できるようになる.

As example of classification, think about face recognition. Assume that Input is face image, and label is index that expresses person (In fact, because dimension is too big when using face image directly, we performs low dimension processes, but do not consider it in particular here.). In this case, data to use for learning is the one which prepares a lot of pairs of characteristic quantity and label, such as face image 1 of A, face image 2 of A, ..., face image 1 of B,.... Learn "classifier" using these data. Then, classifier which you learned, becomes able to estimate the label (index expressing person) when giving quantity of any characteristic (face image).

クラスタリング (Clustering) Clustering

クラスタリングは教師なし学習 (Unsupervised Learning) の一例である.教師なし学習では,入力の特徴量に対応する出力(教師データ)が与えられない.クラスタリングでは,与えられたデータからクラス構造を自動的に発見し,クラスのラベルをつける. 下図はクラスタリングの例である.左は学習データ(青の点群),右は得られたクラス構造(赤線)を表す.学習されたモデルを使うと,任意の入力に対してクラスを推定することができる.

Clustering is an example of learning without teacher (Unsupervised Learning). For Unsupervised Learning, output (teacher data) corresponding to quantity of characteristic of input is not given. For clustering, discover class structure automatically from given data, then attach class label. The chart below is example of clustering. The left is learning data (blue point group), and the right expresses obtained class structure (red line). Using learned model, class can be estimated for any input.

ml-clu1.png
クラスタリングの学習データ.
Learning data of clustering.
ml-clu2.png
クラスタリングで得られた結果.
Obtained result by clustering.

機械学習のプログラミング Programming of machine learning

一般に,バッチ処理型(データを一度に学習する)の機械学習では,以下の流れでプログラムを作成する.

Generally, for machine learning of batch processing type (learn data at a time), program by the following flow.

  • データの生成: 学習に用いるデータを生成する. Data generation: Generate data to use for learning.
  • 学習: 生成したデータを用いて学習を行う. Learning: Learn using created data.
  • 使用: 学習結果を使用する.「テスト」とも言う. Usage: It use learning result. It is also said as "test".
    データの量が大規模になると,データの生成,学習に時間が掛かるため,これら3つの処理は個別のプログラムとして作成した方が便利なことが多い.ウェブなどで公開されているデータを用いて学習する場合は,「データの生成」プログラムは不要となる.
    When data quantity becomes large, it takes long time for data generation, learning, so these three processes is usually convenient when it is created as individual program. When learning it using data shown in Web, "Data generation" program is needless.

なお,当然だが,Shogun はデータを生成するプログラムは提供しない.

In addition, it is natural that Shogun does not provide program to generate data.

インストール方法 Installation method

For Debian squeeze

 sudo apt-get -f install libshogun-dev libshogun8 liblzo2-dev
  1. パッケージ libshogun-dev libshogun8 liblzo2-dev をインストール. Install package libshogun-dev libshogun8 liblzo2-dev.
    (完了)
    (completion)

For Ubuntu 10.04

  1. パッケージ libshogun-dev libshogun6 liblzo2-dev をインストール. Install package libshogun-dev libshogun6 liblzo2-dev.
     sudo apt-get -f install libshogun-dev libshogun6 liblzo2-dev
  2. パッケージ libatlas-headers をインストール. Install package libatlas-headers.
     sudo apt-get -f install libatlas-headers
    (完了)
    (completion)

For Ubuntu 14.04

 sudo apt-get -f install libshogun-dev libshogun15 liblzo2-dev
  1. パッケージ libshogun-dev libshogun15 liblzo2-dev をインストール. Install package libshogun-dev libshogun15 liblzo2-dev.
    (完了)
    (completion)
Note
libatlas-headers がない場合, libatlas-dev でもよいようだ.
Note
If there is not libatlas-headers, even libatlas-dev may be OK.

確認作業 Confirmation work

下記プログラムを保存 (filetest-s-1.1.cpp):

Store the following program (filetest-s-1.1.cpp):

length() used on @lines (did you mean "scalar(@lines)"?) at /usr/bin/code2html line 1360.
length() used on @lines (did you mean "scalar(@lines)"?) at /usr/bin/code2html line 1370.
#include <iostream>

#include <shogun/kernel/GaussianKernel.h>
#include <shogun/features/SimpleFeatures.h>
#include <shogun/regression/svr/LibSVR.h>
#include <shogun/lib/common.h>
#include <shogun/base/init.h>
using namespace shogun;
using namespace std;
int main()
{
  init_shogun();

  const int NUM(10),DIMS(1);
  SGVector<float64_t> lab(NUM);
  SGMatrix<float64_t> feat(DIMS,NUM);
  for (int x(0);x<NUM;++x)
  {
    lab[x]= (double)x/20.0;
    feat[x*DIMS]= (double)x/10.0;
  }

  CLabels* labels=new CLabels();
  labels->set_labels(lab);
  SG_REF(labels);

  CSimpleFeatures<float64_t>* features = new CSimpleFeatures<float64_t>(0);
  SG_REF(features);
  features->set_feature_matrix(feat);

  CGaussianKernel* kernel = new CGaussianKernel(0, /*rbf_width*/2.0);
  SG_REF(kernel);
  kernel->init(features, features);

  CLibSVR* svm = new CLibSVR(/*C*/1.2, /*eps*/0.001, kernel, labels);
  SG_REF(svm);
  svm->set_tube_epsilon(0.01);
  svm->train();

  cout<<"num of support vectors: "<<svm->get_num_support_vectors()<<endl;

  SG_UNREF(labels);
  SG_UNREF(kernel);
  SG_UNREF(features);
  SG_UNREF(svm);

  exit_shogun();
  return 0;
}

バージョンが0.9の場合は filetest-s.cpp を用いる.

Use filetest-s.cpp if version is 0.9.

下記プログラムを保存 (filetest-s-1.2.cpp):(for shogun15)

Store the following program (filetest-s-1.2.cpp):

length() used on @lines (did you mean "scalar(@lines)"?) at /usr/bin/code2html line 1360.
length() used on @lines (did you mean "scalar(@lines)"?) at /usr/bin/code2html line 1370.
#include <iostream>
#include <shogun/kernel/GaussianKernel.h>
#include <shogun/features/DenseFeatures.h>
#include <shogun/labels/RegressionLabels.h>
#include <shogun/regression/svr/LibSVR.h>
#include <shogun/lib/common.h>
#include <shogun/base/init.h>
using namespace shogun;
using namespace std;

int main(int argc, char **argv)
{
	init_shogun();

	const int NUM(10),DIMS(1);
	SGVector<float64_t> lab(NUM);
	SGMatrix<float64_t> feat(DIMS,NUM);
	for (int x(0);x<NUM;++x)
	{
		lab[x]= (double)x/20.0;
		feat[x*DIMS]= (double)x/10.0;
	}

	CRegressionLabels* labels=new CRegressionLabels();
	SG_REF(labels);
	labels->set_labels(lab);

	CDenseFeatures<float64_t>* features = new CDenseFeatures<float64_t>(0);
	SG_REF(features);
	features->set_feature_matrix(feat);

	CGaussianKernel* kernel = new CGaussianKernel(0, /*rbf_width*/2.0);
	SG_REF(kernel);
	kernel->init(features, features);

	CLibSVR* svm = new CLibSVR(/*C*/1.2, /*eps*/0.001, kernel, labels);
	SG_REF(svm);
	svm->set_tube_epsilon(0.01);
	svm->train();

	cout<<"num of support vectors: "<<svm->get_num_support_vectors()<<endl;

	SG_UNREF(labels);
	SG_UNREF(kernel);
	SG_UNREF(features);
	SG_UNREF(svm);

	exit_shogun();

	return 0;
}

以下でコンパイル:

Compile it with the following:

g++ test-s-1.1.cpp -lshogun
g++ -std=c++11 test-s-1.2.cpp -lshogun (for shogun15)

実行結果:

Execution result:

length() used on @lines (did you mean "scalar(@lines)"?) at /usr/bin/code2html line 1360.
length() used on @lines (did you mean "scalar(@lines)"?) at /usr/bin/code2html line 1370.
num of support vectors: 2

バージョンの出力 Output of version

以下のプログラムをコンパイルし,実行すると,バージョン情報を出力できる.

After compile the following programs and execute it, then output version information.

length() used on @lines (did you mean "scalar(@lines)"?) at /usr/bin/code2html line 1360.
length() used on @lines (did you mean "scalar(@lines)"?) at /usr/bin/code2html line 1370.
#include <shogun/lib/common.h>
#include <shogun/base/init.h>
#include <shogun/base/Version.h>
#include <iostream>
using namespace shogun;
using namespace std;
void print_message(FILE* target, const char* str)
{
  fputs(str,target);
}
int main()
{
  init_shogun(print_message);
  get_global_version()->print_version();
  exit_shogun();
  return 0;
}

Shogun を用いたプログラミング Programming using Shogun

回帰 Regression

Shogun には様々な回帰モデルが用意されている.ここでは,サポートベクタマシンによる回帰 (Support Vector Regression, SVR) を使用する例をもとに,Shogun の回帰プログラミングを解説する.

Various regression models are prepared for Shogun. Here, based on example to use regression (Support Vector Regression, SVR) by support vector machine, explain regression programming of Shogun.

サンプルプログラム Sample program

ソースコード Source code (fileregression1-1.1.cpp):

length() used on @lines (did you mean "scalar(@lines)"?) at /usr/bin/code2html line 1360.
length() used on @lines (did you mean "scalar(@lines)"?) at /usr/bin/code2html line 1370.
#include <cmath>
#include <iostream>
#include <fstream>

#include <shogun/kernel/GaussianKernel.h>
#include <shogun/features/SimpleFeatures.h>
#include <shogun/regression/svr/LibSVR.h>
#include <shogun/lib/common.h>
#include <shogun/base/init.h>

using namespace std;
using namespace shogun;

#define print(var) std::cerr<<#var"= "<<(var)<<std::endl

int main(int,char**)
{
  const int32_t feature_cache=0;
  const int32_t kernel_cache=0;
  const float64_t rbf_width=0.5;
  const float64_t svm_C=1.0;
  const float64_t svm_eps=0.0001;
  const float64_t svm_tube_eps=0.01;

  cerr<<"Learning ..."<<endl;
  init_shogun();

  // generate training data
  ofstream ofs_in("in.dat");
  const int num(100),dim(1);  // number of samples, sample dimension
  SGVector<float64_t> lab(num);
  SGMatrix<float64_t> feat(dim,num);
  for(int i(0);i<num;++i)
  {
    feat[dim*i]= ((double)i/(double)num-0.5)*6.0;
    lab[i]= sin(2.0*feat[dim*i]);
    ofs_in<<feat[dim*i]<<" "<<lab[i]<<endl;
  }

  // create training features
  CSimpleFeatures<float64_t> *features;
  features= new CSimpleFeatures<float64_t>(feature_cache);
  features->set_feature_matrix(feat);
  SG_REF(features);

  // create gaussian kernel
  CGaussianKernel *kernel;
  kernel= new CGaussianKernel(kernel_cache, rbf_width);
  kernel->init(features, features);
  SG_REF(kernel);

  // create training labels
  CLabels *labels;
  labels= new CLabels();
  labels->set_labels(lab);
  SG_REF(labels);

  // create svm via libsvm and train
  CLibSVR *svm;
  svm= new CLibSVR(svm_C, svm_eps, kernel, labels);
  SG_REF(svm);
  svm->set_tube_epsilon(svm_tube_eps);
  svm->train();

  print(svm->get_num_support_vectors());
  print(svm->get_bias());
  cerr<<"Done: Learning"<<endl;


  cerr<<"Testing ..."<<endl;
  // generating testing features
  const int mesh_size(200), test_num(mesh_size);
  const double xmin(-4),xmax(4);
  SGMatrix<float64_t> test_feat(dim,test_num);
  for(int x(0);x<mesh_size;++x)
    test_feat[dim*x]= xmin+(xmax-xmin)*(double)x/(double)(mesh_size-1);

  // create testing features
  CSimpleFeatures<float64_t> *test_features= new CSimpleFeatures<float64_t>(feature_cache);
  SG_REF(test_features);
  test_features->set_feature_matrix(test_feat);

  // estimating labels
  CLabels* out_labels;
  out_labels= svm->apply(test_features);

  // saving data into file
  ofstream ofs_out("out.dat");
  for(int x(0);x<mesh_size;++x)
    ofs_out<<test_feat[dim*x]<<" "<<out_labels->get_label(x)<<endl;
  cerr<<"Done: Testing"<<endl;


  SG_UNREF(test_features);
  SG_UNREF(out_labels);

  SG_UNREF(kernel);
  SG_UNREF(features);
  SG_UNREF(labels);
  SG_UNREF(svm);

  return 0;
}

バージョンが0.9の場合は fileregression1.cpp を参照.

Refer to fileregression1.cpp if version is 0.9.

ソースコード Source code (fileregression1-1.2.cpp):(for shogun15)

length() used on @lines (did you mean "scalar(@lines)"?) at /usr/bin/code2html line 1360.
length() used on @lines (did you mean "scalar(@lines)"?) at /usr/bin/code2html line 1370.
#include <iostream>
#include <fstream>
#include <cmath>
#include <shogun/kernel/GaussianKernel.h>
#include <shogun/features/DenseFeatures.h>
#include <shogun/labels/RegressionLabels.h>
#include <shogun/regression/svr/LibSVR.h>
#include <shogun/lib/common.h>
#include <shogun/base/init.h>
using namespace std;
using namespace shogun;
#define print(var) std::cerr<<#var"= "<<(var)<<std::endl

int main(int argc, char **argv)
{
	init_shogun();

	const int32_t feature_cache = 0;
	const int32_t kernel_cache = 0;
	const float64_t rbf_width = 0.5;
	const float64_t svm_C = 1.0;
	const float64_t svm_eps = 0.0001;
	const float64_t svm_tube_eps = 0.01;

	cerr<<"Learning ..."<<endl;

	// generate training data
	ofstream ofs_in("in.dat");
	const int num(100),dim(1);  // number of samples, sample dimension
	SGVector<float64_t> lab(num);
	SGMatrix<float64_t> feat(dim,num);
	for(int i(0);i<num;++i)
	{
		feat[dim*i]= ((double)i/(double)num-0.5)*6.0;
		lab[i]= sin(2.0*feat[dim*i]);
		ofs_in<<feat[dim*i]<<" "<<lab[i]<<endl;
	}

	// create training features
	CDenseFeatures<float64_t> *features;
	features= new CDenseFeatures<float64_t>(feature_cache);
	SG_REF(features);
	features->set_feature_matrix(feat);

	// create gaussian kernel
	CGaussianKernel *kernel;
	kernel= new CGaussianKernel(kernel_cache, rbf_width);
	SG_REF(kernel);
	kernel->init(features, features);

	// create training labels
	CRegressionLabels *labels;
	labels= new CRegressionLabels();
	SG_REF(labels);
	labels->set_labels(lab);

	// create svm via libsvm and train
	CLibSVR *svm;
	svm= new CLibSVR(svm_C, svm_eps, kernel, labels);
	SG_REF(svm);
	svm->set_tube_epsilon(svm_tube_eps);
	svm->train();

	print(svm->get_num_support_vectors());
	print(svm->get_bias());
	cerr<<"Done: Learning"<<endl;

	cerr<<"Testing ..."<<endl;
	// generating testing features
	const int mesh_size(200), test_num(mesh_size);
	const double xmin(-4),xmax(4);
	SGMatrix<float64_t> test_feat(dim,test_num);
	for(int x(0);x<mesh_size;++x)
		test_feat[dim*x]= xmin+(xmax-xmin)*(double)x/(double)(mesh_size-1);

	// create testing features
	CDenseFeatures<float64_t> *test_features= new CDenseFeatures<float64_t>(feature_cache);
	SG_REF(test_features);
	test_features->set_feature_matrix(test_feat);

	// estimating labels
	CRegressionLabels* out_labels;
	out_labels= CLabelsFactory::to_regression(svm->apply(test_features));

	// saving data into file
	ofstream ofs_out("out.dat");
	for(int x(0);x<mesh_size;++x)
		ofs_out<<test_feat[dim*x]<<" "<<out_labels->get_label(x)<<endl;
	cerr<<"Done: Testing"<<endl;

	SG_UNREF(test_features);
	SG_UNREF(out_labels);
	SG_UNREF(kernel);
	SG_UNREF(features);
	SG_UNREF(labels);
	SG_UNREF(svm);

	exit_shogun();

	return 0;
}

コンパイル:

Compile:

g++ -g -Wall -O3 regression1-1.1.cpp -lshogun
g++ -g -Wall -O3 -std=c++11 regression1-1.2.cpp -lshogun (for shogun15)

実行:

Execution:

./a.out

プログラムを実行すると,カレントディレクトリに in.dat と out.dat というファイルが生成される.

When execute program, files called in.dat and out.dat are created to current directory.

  • in.dat: 学習に用いたデータ(1行目:入力,2行目:出力). in.dat: data used for learning (The first line: Input, the second line: Output ).
  • out.dat: 学習されたSVRを用いて推定したデータ(1行目:入力,2行目:推定した出力). out.dat: Data estimated using learned SVR (The first line: Input, the second line: Estimated output).

学習が正常に行われたか,gnuplot でプロットして確認しよう:

Plot with gnuplot and confirm if learning was carried out normally.

set key right top
set xlabel "input"
set ylabel "output"
set size ratio 0.5
plot  "in.dat" pt 5 , "out.dat" w l
out-reg1.png
学習データ(点群)と学習結果(曲線).
Learning data (point group) and learning result (curve).

解説 Explanation

プログラムは以下のような流れになっている:

Program is following flow:

  1. Shogun の初期化. Initialization of Shogun.
  2. 学習データの生成,ファイルに保存. Generation of learning data, Saving to file.
    • 上の例では,入力,出力ともに1次元の実数. In the above example, both Input and output are one-dimensional real number.
    • 出力はsin関数によって生成されている. Output is created by sin function.
  3. 学習データのうち,入力をもとに特徴量オブジェクトを生成し,さらにカーネルオブジェクトを生成. Among learning data, generate quantity of characteristic object based on input, furthermore, generate kernel object.
    • カーネル: ガウシアンカーネルを使用. Kernel: Use Gaussian kernel.
  4. 学習データのうち,出力をもとにラベルオブジェクトを生成. Among learning data, generate label object based on output.
    • ラベルと言っているが,実数値. We call it a label, but actual number.
  5. カーネルとラベルをもとに SVR オブジェクトを生成し,パラメータを設定後,学習. Generate SVR object based on kernel and label, then set parameter and learn it.
  6. テストデータの生成(入力のみ). Generation of test data (Only input).
  7. テストデータをもとに特徴量オブジェクトを生成し,さらにカーネルオブジェクトを生成. Generate quantity of characteristic object based on test data, then furthermore, generate kernel object.
  8. SVR オブジェクトを使って,出力を推定. Using SVR object, estimate output.
  9. テストデータの入力と推定された出力を保存. Save test data input and estimated output.
  10. 確保したオブジェクトの解放. Release of assigned object.

理解しておくべきポイントは以下の点:

The points that you should understand are as follows:

  • プログラムは学習とテストの2つに分けられる: Program is classified by two of learning and test:
    • 学習: (学習データの生成(入力・出力))→SVRを学習. Learning: (Generation of learning data (input, output)) →Learn SVR.
    • テスト: (テストデータの生成(入力のみ))→SVR→出力を推定. Test: (Generation of test data (Only input)) →SVR→Estimate output.
  • 入力は,学習の場合もテストの場合も,特徴量オブジェクトに変換し,カーネルオブジェクトを生成後,カーネルオブジェクトを SVR に渡す. If learning or if test, then convert input into quantity of characteristic object, then after Kernel object generation, hand kernel object to SVR.

発展 Advance

入力の次元を変更するには To change input dimension
上のプログラムの dim を変更し,学習・テストデータを生成すればよい.この場合,例えば入力データが \{ (x_{1,1},x_{2,1}), (x_{1,2},x_{2,2}), (x_{1,3},x_{2,3}), ... \} だとすると,feat には \{ x_{1,1}, x_{2,1}, x_{1,2},x_{2,2}, x_{1,3}, x_{2,3}, ... \} のようにシリアライズして(1次元ベクトルとして)格納する.
Change dim of upper program, then generate learning, test data. In this case, for example, if input data is \{ (x_{1,1},x_{2,1}), (x_{1,2},x_{2,2}), (x_{1,3},x_{2,3}), ... \},As for feat, serialize as \{ x_{1,1}, x_{2,1}, x_{1,2},x_{2,2}, x_{1,3}, x_{2,3}, ... \} (As one dimension vector) and store it.
出力の次元を変更するには To change output dimension
出力の次元数だけ SVR を用意し(配列として用意すればよい),出力の次元ごとに独立に学習・推定する. このとき,入力の特徴量オブジェクトおよびカーネルオブジェクトは共通のものを使ってよい.
Prepare SVR for the number of dimensions of output (should prepare as array), then learn and estimate by every output dimension independently. At this time, you may use common thing for quantity of characteristic object of input and kernel object.

分類 Classification

Shogun には様々な分類器が用意されている.ここでは,サポートベクタマシン (Support Vector Machine) を用いた分類の例をもとに,Shogun の分類プログラミングを解説する.

Various classifier is prepared for Shogun. Here, based on classification example using support vector machine (Support Vector Machine), we explain classification programming of Shogun.

サンプルプログラム Sample program

ソースコード Source code (fileclassification1-1.1.cpp):

length() used on @lines (did you mean "scalar(@lines)"?) at /usr/bin/code2html line 1360.
length() used on @lines (did you mean "scalar(@lines)"?) at /usr/bin/code2html line 1370.
#include <cmath>
#include <iostream>
#include <fstream>

#include <shogun/kernel/GaussianKernel.h>
#include <shogun/features/SimpleFeatures.h>
#include <shogun/classifier/svm/LibSVM.h>
#include <shogun/lib/common.h>
#include <shogun/base/init.h>

using namespace std;
using namespace shogun;

#define print(var) std::cerr<<#var"= "<<(var)<<std::endl

int main(int,char**)
{
  const int32_t feature_cache=0;
  const int32_t kernel_cache=0;
  const float64_t rbf_width=0.5;
  const float64_t svm_C=1.0;
  const float64_t svm_eps=0.0001;

  cerr<<"Learning ..."<<endl;
  init_shogun();

  // generate training data
  ofstream ofs_in("in.dat");
  int num(100),dim(1);  // number of samples, sample dimension
  SGVector<float64_t> lab(num);
  SGMatrix<float64_t> feat(dim,num);
  for(int i(0);i<num;++i)
  {
    feat[dim*i]= ((double)i/(double)num-0.5)*6.0;
    lab[i]= (sin(2.0*feat[dim*i])>0 ? +1 : -1);
    ofs_in<<feat[dim*i]<<" "<<lab[i]<<endl;
  }

  // create training features
  CSimpleFeatures<float64_t> *features;
  features= new CSimpleFeatures<float64_t>(feature_cache);
  features->set_feature_matrix(feat);
  SG_REF(features);

  // create gaussian kernel
  CGaussianKernel *kernel;
  kernel= new CGaussianKernel(kernel_cache, rbf_width);
  kernel->init(features, features);
  SG_REF(kernel);

  // create training labels
  CLabels *labels;
  labels= new CLabels();
  labels->set_labels(lab);
  SG_REF(labels);

  // create svm via libsvm and train
  CLibSVM *svm;
  svm= new CLibSVM(svm_C, kernel, labels);
  SG_REF(svm);
  svm->set_epsilon(svm_eps);
  svm->train();

  print(svm->get_num_support_vectors());
  print(svm->get_bias());
  cerr<<"Done: Learning"<<endl;


  cerr<<"Testing ..."<<endl;
  // generating testing features
  const int mesh_size(200), test_num(mesh_size);
  const double xmin(-4),xmax(4);
  SGMatrix<float64_t> test_feat(dim,test_num);
  for(int x(0);x<mesh_size;++x)
    test_feat[dim*x]= xmin+(xmax-xmin)*(double)x/(double)(mesh_size-1);

  // create testing features
  CSimpleFeatures<float64_t> *test_features= new CSimpleFeatures<float64_t>(feature_cache);
  SG_REF(test_features);
  test_features->set_feature_matrix(test_feat);

  // estimating labels
  CLabels* out_labels;
  out_labels= svm->apply(test_features);

  // saving data into file
  ofstream ofs_out("out.dat");
  for(int x(0);x<mesh_size;++x)
  {
    double label= out_labels->get_label(x);
    ofs_out<<test_feat[dim*x]<<"   "<<(label>0 ? +1 : -1)<<" "<<label<<endl;
  }
  cerr<<"Done: Testing"<<endl;


  SG_UNREF(test_features);
  SG_UNREF(out_labels);

  SG_UNREF(kernel);
  SG_UNREF(features);
  SG_UNREF(labels);
  SG_UNREF(svm);

  return 0;
}

バージョンが0.9の場合は fileclassification1.cpp を参照.

Refer to fileclassification1.cpp if version is 0.9.

ソースコード Source code (fileclassification1-1.2.cpp):(for shogun15)

length() used on @lines (did you mean "scalar(@lines)"?) at /usr/bin/code2html line 1360.
length() used on @lines (did you mean "scalar(@lines)"?) at /usr/bin/code2html line 1370.
#include <iostream>
#include <fstream>
#include <cmath>
#include <shogun/kernel/GaussianKernel.h>
#include <shogun/features/DenseFeatures.h>
#include <shogun/labels/BinaryLabels.h>
#include <shogun/classifier/svm/LibSVM.h>
#include <shogun/lib/common.h>
#include <shogun/base/init.h>
using namespace std;
using namespace shogun;
#define print(var) std::cerr<<#var"= "<<(var)<<std::endl

int main(int argc, char **argv)
{
	init_shogun();

	const int32_t feature_cache = 0;
	const int32_t kernel_cache = 0;
	const float64_t rbf_width = 0.5;
	const float64_t svm_C = 1.0;
	const float64_t svm_eps = 0.0001;

	cerr<<"Learning ..."<<endl;

	// generate training data
	ofstream ofs_in("in.dat");
	int num(100),dim(1);  // number of samples, sample dimension
	SGVector<float64_t> lab(num);
	SGMatrix<float64_t> feat(dim,num);
	for(int i(0);i<num;++i)
	{
		feat[dim*i]= ((double)i/(double)num-0.5)*6.0;
		lab[i]= (sin(2.0*feat[dim*i])>0 ? +1 : -1);
		ofs_in<<feat[dim*i]<<" "<<lab[i]<<endl;
	}

	// create training features
	CDenseFeatures<float64_t> *features;
	features= new CDenseFeatures<float64_t>(feature_cache);
	SG_REF(features);
	features->set_feature_matrix(feat);

	// create gaussian kernel
	CGaussianKernel *kernel;
	kernel= new CGaussianKernel(kernel_cache, rbf_width);
	SG_REF(kernel);
	kernel->init(features, features);

	// create training labels
	CBinaryLabels *labels;
	labels= new CBinaryLabels();
	SG_REF(labels);
	labels->set_labels(lab);

	// create svm via libsvm and train
	CLibSVM *svm;
	svm= new CLibSVM(svm_C, kernel, labels);
	SG_REF(svm);
	svm->set_epsilon(svm_eps);
	svm->train();

	print(svm->get_num_support_vectors());
	print(svm->get_bias());
	cerr<<"Done: Learning"<<endl;

	cerr<<"Testing ..."<<endl;
	// generating testing features
	const int mesh_size(200), test_num(mesh_size);
	const double xmin(-4),xmax(4);
	SGMatrix<float64_t> test_feat(dim,test_num);
	for(int x(0);x<mesh_size;++x)
		test_feat[dim*x]= xmin+(xmax-xmin)*(double)x/(double)(mesh_size-1);

	// create testing features
	CDenseFeatures<float64_t> *test_features= new CDenseFeatures<float64_t>(feature_cache);
	SG_REF(test_features);
	test_features->set_feature_matrix(test_feat);

	// estimating labels
	CBinaryLabels* out_labels;
	out_labels= CLabelsFactory::to_binary(svm->apply(test_features));

	// saving data into file
	ofstream ofs_out("out.dat");
	for(int x(0);x<mesh_size;++x)
	{
		double label= out_labels->get_label(x);
		ofs_out<<test_feat[dim*x]<<"   "<<(label>0 ? +1 : -1)<<" "<<label<<endl;
	}
	cerr<<"Done: Testing"<<endl;

	SG_UNREF(test_features);
	SG_UNREF(out_labels);
	SG_UNREF(kernel);
	SG_UNREF(features);
	SG_UNREF(labels);
	SG_UNREF(svm);

	exit_shogun();

	return 0;
}

コンパイル:

Compile:

g++ -g -Wall -O3 classification1-1.1.cpp -lshogun

実行:

Execution:

./a.out

プログラムを実行すると,カレントディレクトリに in.dat と out.dat というファイルが生成される.

When executing program, files called in.dat and out.dat are created to current directory.

  • in.dat: 学習に用いたデータ(1行目:入力,2行目:出力). in.dat: Data used for learning (The first line: Input, the second line:Output).
  • out.dat: 学習されたSVRを用いて推定したデータ(1行目:入力,2行目:推定した出力). out.dat: Estimated data using learned SVR (The first line: Input, the second line: Estimated output).

学習が正常に行われたか,gnuplot でプロットして確認しよう:

Plot with gnuplot and confirm If learning is performed normally:

plot  "in.dat" pt 5 , "out.dat" w l
out-cls1.png
学習データ(点群)と学習結果(曲線).
Learning data (point group) and learning result (curve).

解説 Explanation

ほとんど回帰の場合と同じ.異なる点は以下のとおり.

Almost same as the case of regression. Different points are as follows.

  • 学習データのうち,出力がラベル(-1, +1)となっている. Among learning data, Output is label (-1, +1).
  • CLibSVR の代わりに CLibSVM を用いている. Using CLibSVM instead of CLibSVR.
  • パラメータがやや異なる. Parameters are slightly different.
  • 推定される出力値は連続値なので,0以上なら+1,0以下なら-1としてラベルに変換している. Because estimated output value is consecutive value, then if more than 0 and less than +1,0, then convert into label as -1.

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2018-08-30 (木) 07:17:04 (23d)