phpでLIBSVM(追記あり)

1 月 6th, 2008 in C, PECL, PHP, SVM, Sakura users

前回のエントリーでPHPでもSWIGが使えることが分ったので,実際にC言語で書かれたライブラリをPHPエクステンションにコンバートしてみた.
今回PHPエクステンション化に挑戦したライブラリはLIBSVM.有名なサポートベクターマシーンのライブラリ.つかったことけど(え

選んだ理由は

  • 最近SVM勉強中
  • Python用のインターフェイスファイルが付属

とくに学術系に顕著だが,Perl,Python,Ruby用のインターフェイスは用意されているのにPHPでは用意されていないことが多い.それもSWIGで作っただけのインターフェイスなのに.
他のLL言語に比べてPHPはなめられている気がしなくもない.インタラクティブなシェル(php -a)がイマイチだから?WEB専用だから?
とりあえず結論からいうとLIBSVMもPHPで使えるんです!仲間にいれてください!

個人的な思いは置いといて,以下,LIBSVMをPHPで使うまでの流れメモ

LIBSVMインストール

wget "http://www.csie.ntu.edu.tw/~cjlin/cgi-bin/libsvm.cgi?+http://www.csie.ntu.edu.tw/~cjlin/libsvm+tar.gz"
tar xzvf libsvm-2.85.tar.gz
cd libsvm-2.85
make

SWIGでPHPエクステンション作成

SWIGで面倒なのはインターフェイスファイルを書くことな気がするが,LIBSVMには幸いPython用のインターフェイスファイル(svmc.i)がついています.これを使わない手はない.

swig -php5 svmc.i

であっさりsvmc_wrap.c, php_svmc.hが出来上がります.↑で作ったsvm.oをリンクすれば前回エントリと同じ用にsvmc.soが出来上がります.
ちなみにsvmc.iはこんな感じ

%module svmc
%{
#include "svm.h"
%}
 
enum { C_SVC, NU_SVC, ONE_CLASS, EPSILON_SVR, NU_SVR };	/* svm_type */
enum { LINEAR, POLY, RBF, SIGMOID, PRECOMPUTED };	/* kernel_type */
 
struct svm_parameter
{
	int svm_type;
	int kernel_type;
	int degree;	// for poly
	double gamma;	// for poly/rbf/sigmoid
	double coef0;	// for poly/sigmoid
 
	// these are for training only
	double cache_size; // in MB
	double eps;	// stopping criteria
	double C;	// for C_SVC, EPSILON_SVR and NU_SVR
	int nr_weight;		// for C_SVC
	int *weight_label;	// for C_SVC
	double* weight;		// for C_SVC
	double nu;	// for NU_SVC, ONE_CLASS, and NU_SVR
	double p;	// for EPSILON_SVR
	int shrinking;	// use the shrinking heuristics
	int probability;
};
 
struct svm_problem
{
	int l;
	double *y;
	struct svm_node **x;
};
 
struct svm_model *svm_train(const struct svm_problem *prob, const struct svm_parameter *param);
 
void svm_cross_validation(const struct svm_problem *prob, const struct svm_parameter *param, int nr_fold, double *target);
 
int svm_save_model(const char *model_file_name, const struct svm_model *model);
struct svm_model *svm_load_model(const char *model_file_name);
 
int svm_get_svm_type(const struct svm_model *model);
int svm_get_nr_class(const struct svm_model *model);
void svm_get_labels(const struct svm_model *model, int *label);
double svm_get_svr_probability(const struct svm_model *model);
 
void svm_predict_values(const struct svm_model *model, const struct svm_node *x, double* decvalue);
double svm_predict(const struct svm_model *model, const struct svm_node *x);
double svm_predict_probability(const struct svm_model *model, const struct svm_node *x, double* prob_estimates);
 
void svm_destroy_model(struct svm_model *model);
/* Not necessary: the weight vector is (de)allocated at python-part
   void svm_destroy_param(struct svm_parameter *param); */
 
const char *svm_check_parameter(const struct svm_problem *prob, const struct svm_parameter *param);
int svm_check_probability_model(const struct svm_model *model);
 
%include carrays.i
%array_functions(int,int)
%array_functions(double,double)
 
%inline %{
struct svm_node *svm_node_array(int size)
{
	return (struct svm_node *)malloc(sizeof(struct svm_node)*size);
}
 
void svm_node_array_set(struct svm_node *array, int i, int index, double value)
{
	array[i].index = index;
	array[i].value = value;
}
 
void svm_node_array_destroy(struct svm_node *array)
{
	free(array);
}
 
struct svm_node **svm_node_matrix(int size)
{
	return (struct svm_node **)malloc(sizeof(struct svm_node *)*size);
}
 
void svm_node_matrix_set(struct svm_node **matrix, int i, struct svm_node* array)
{
	matrix[i] = array;
}
 
void svm_node_matrix_destroy(struct svm_node **matrix)
{
	free(matrix);
}
 
%}

これだけ用意されていればでPHPエクステンションの作成は一瞬です!

ラッパークラス作成

SWIGで外部インターフェイスを作ると汎用的なものができあがるので直接使うのはちょっと大変です.なのでPHPでラッパークラスを作るのが良いと思います.
今回はPythonのラッパークラスをまるパクリで作成しました(svm.php).割愛しますがサンプルもまるパクリでつくり(svm_test.php, test_cross_validation.php),
Pythonのものと同じ結果が得られることを確認しました.

delete_svm_parameterとか delete_svm_problemは登録されていなかったけど,デストラクタが勝手に働くかたいいのかな.

ソースダウンロード

以上のファイルをまとめたのでここからダウンロードできます.
libsvm-2.85フォルダで展開して

cd php
make
make install
php test_svm.php
php test_cross_validation.php

でサンプルを実行できます!
何か間違いとかつっこみがありましたら是非是非お願いします!!

PHPでもそれなりできるんじゃないでしょうか?
今度はSVMを使ったアプリも作ってみよう.

** 追記(08/09/13) **
デモ作った

Leave a Reply

Recent Posts

Search

ドミノ・ピザ 5%OFF!

デル株式会社

 iTunes Store(Japan)

Sony Style(ソニースタイル)

Recommend

Effective Java 第2版 (The Java Series)
Effective Java 第2版 (The Java
Series)

¥ 3,780(新品)
Javaをある程度やった人はこの本読んで
昔のコードを恥じましょう.

view all

Categories

Tags