├── phpdocs ├── svn ├── entities.svmmodel.xml ├── entities.svm.xml ├── configure.xml ├── book.xml ├── svm │ ├── construct.xml │ ├── getoptions.xml │ ├── setoptions.xml │ ├── train.xml │ └── crossvalidate.xml ├── setup.xml ├── svmmodel.xml ├── versions.xml ├── svmmodel │ ├── save.xml │ ├── load.xml │ ├── construct.xml │ └── predict.xml ├── svmexception.xml ├── examples.xml └── svm.xml ├── CREDITS ├── tests ├── 008_cross_validate.phpt ├── 009_badfile.phpt ├── 011_inttodouble.phpt ├── 001_train.phpt ├── 006_train_array.phpt ├── 004_setoptions.phpt ├── 003_getparms.phpt ├── 002_predict.phpt ├── 010_weights.phpt ├── 005_regression.phpt ├── 007_kernels.phpt └── australian.scale ├── LICENSE ├── config.m4 ├── package.xml ├── php_svm.h ├── README └── svm.c /phpdocs/svn: -------------------------------------------------------------------------------- 1 | svn -------------------------------------------------------------------------------- /CREDITS: -------------------------------------------------------------------------------- 1 | svm 2 | Ian Barber, Mikko Koppanen -------------------------------------------------------------------------------- /phpdocs/entities.svmmodel.xml: -------------------------------------------------------------------------------- 1 | &reference.svm.svmmodel.construct; 2 | &reference.svm.svmmodel.load; 3 | &reference.svm.svmmodel.predict; 4 | &reference.svm.svmmodel.save; 5 | -------------------------------------------------------------------------------- /phpdocs/entities.svm.xml: -------------------------------------------------------------------------------- 1 | &reference.svm.svm.construct; 2 | &reference.svm.svm.crossvalidate; 3 | &reference.svm.svm.getoptions; 4 | &reference.svm.svm.setoptions; 5 | &reference.svm.svm.train; 6 | -------------------------------------------------------------------------------- /tests/008_cross_validate.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test 5 fold cross validation 3 | --SKIPIF-- 4 | 7 | --FILE-- 8 | crossvalidate(dirname(__FILE__) . '/australian.scale', 5); 11 | if($result > 0) { 12 | echo "ok"; 13 | } 14 | ?> 15 | --EXPECT-- 16 | ok 17 | -------------------------------------------------------------------------------- /tests/009_badfile.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test handling a bad filename 3 | --SKIPIF-- 4 | 7 | --FILE-- 8 | train('bad.file'); // shutup op to stop the warning which has current path in it 12 | } catch(SVMException $e) { 13 | echo "got exception"; 14 | } 15 | ?> 16 | --EXPECT-- 17 | got exception 18 | -------------------------------------------------------------------------------- /tests/011_inttodouble.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Train from an array, testing conversion of ints to doubles 3 | --SKIPIF-- 4 | 7 | --FILE-- 8 | train(array(array(1, 1 => 1), array(-1, 1 => -1))); 11 | echo $result->predict(array(0, 1 => -1)), PHP_EOL; 12 | echo $result->predict(array(0, 1 => 1)); 13 | 14 | 15 | ?> 16 | --EXPECTF-- 17 | -1 18 | 1 -------------------------------------------------------------------------------- /tests/001_train.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Load training data from a file. 3 | --SKIPIF-- 4 | 7 | --FILE-- 8 | train(dirname(__FILE__) . '/australian.scale'); 11 | 12 | try { 13 | $result->save(dirname(__FILE__) . '/australian.model'); 14 | echo "ok"; 15 | } catch (SvmException $e) { 16 | echo $e->getMessage(); 17 | } 18 | 19 | ?> 20 | --EXPECT-- 21 | ok 22 | -------------------------------------------------------------------------------- /tests/006_train_array.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Train from an array 3 | --SKIPIF-- 4 | 7 | --FILE-- 8 | train(array(array(1, -13 => 1.33))); 11 | var_dump($result); 12 | 13 | try { 14 | $svm->train(array(array(1))); 15 | 16 | } catch (SvmException $e) { 17 | echo "got exception"; 18 | } 19 | 20 | ?> 21 | --EXPECTF-- 22 | object(svmmodel)#%d (%d) { 23 | } 24 | got exception 25 | -------------------------------------------------------------------------------- /tests/004_setoptions.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test setOptions 3 | --SKIPIF-- 4 | 7 | --FILE-- 8 | SVM::NU_SVR, Svm::OPT_COEF_ZERO => 1.2); 12 | 13 | $svm->setOptions($options); 14 | 15 | var_dump($options[Svm::OPT_TYPE] == SVM::NU_SVR); 16 | 17 | echo "ok\n"; 18 | 19 | $options = array(Svm::OPT_TYPE => 31337); 20 | try { 21 | $svm->setOptions($options); 22 | } catch (SVMException $e) { 23 | echo "got exception"; 24 | } 25 | ?> 26 | --EXPECT-- 27 | bool(true) 28 | ok 29 | got exception -------------------------------------------------------------------------------- /tests/003_getparms.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test retrieving the SVM training parameters. 3 | --SKIPIF-- 4 | 7 | --FILE-- 8 | getOptions(); 11 | if(count($params) > 2) { 12 | echo "ok 1\n"; 13 | } else { 14 | echo "retrieving params failed"; 15 | } 16 | 17 | if(isset($params[SVM::OPT_CACHE_SIZE])) { 18 | echo "ok 2\n"; 19 | } else { 20 | echo "missing cache size"; 21 | } 22 | 23 | if($params[SVM::OPT_CACHE_SIZE] == 100) { 24 | echo "ok 3\n"; 25 | } else { 26 | echo "invalid cache size"; 27 | } 28 | ?> 29 | --EXPECT-- 30 | ok 1 31 | ok 2 32 | ok 3 33 | 34 | -------------------------------------------------------------------------------- /tests/002_predict.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Make a prediction based on the model 3 | --SKIPIF-- 4 | 7 | --FILE-- 8 | load(dirname(__FILE__) . '/australian.model'); 11 | 12 | if($result) { 13 | $data = array( 14 | "1" => 1, 15 | 2 => -0.731729, 16 | 3 => -0.886786, 17 | 4 => -1, 18 | 5 => 0.230769, 19 | "6" => -0.25, 20 | 7 => -0.783509, 21 | 8 => 1, 22 | 9 => 1, 23 | 10 => "-0.820896", 24 | 11 => -1, 25 | 13 => -0.92, 26 | "14" => "-1" 27 | ); 28 | $result = $svm->predict($data); 29 | if($result > 0) { 30 | echo "ok"; 31 | } else { 32 | echo "predict failed: $result"; 33 | } 34 | } else { 35 | echo "loading failed"; 36 | } 37 | ?> 38 | --EXPECT-- 39 | ok 40 | -------------------------------------------------------------------------------- /phpdocs/configure.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | &reftitle.install; 6 | 7 | 8 | &pecl.info; 9 | &url.pecl.package;svm 10 | 11 | 12 | 13 | The latest PECL/svm Win32 DLL is available here: 14 | php_svm.dll 15 | 16 | 17 |
18 | 19 | 20 | 40 | -------------------------------------------------------------------------------- /tests/010_weights.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test training with some unbalanced weighting 3 | --SKIPIF-- 4 | 7 | --FILE-- 8 | setOptions(array(SVM::OPT_TYPE => SVM::NU_SVC)); 11 | try { 12 | $model = $svm->train(dirname(__FILE__) . '/australian.scale', array(1 => 1, -1 => 0.5)); 13 | } catch(SVMException $e) { 14 | echo "got exception\n"; 15 | } 16 | 17 | $svm->setOptions(array(SVM::OPT_TYPE => SVM::C_SVC)); 18 | $model = $svm->train(dirname(__FILE__) . '/australian.scale', array(1 => 1, -1 => 0.5)); 19 | 20 | try { 21 | $data = array( 22 | "1" => 1, 23 | 2 => -0.731729, 24 | 3 => -0.886786, 25 | 4 => -1, 26 | 5 => 0.230769, 27 | "6" => -0.25, 28 | 7 => -0.783509, 29 | 8 => 1, 30 | 9 => 1, 31 | 10 => "-0.820896", 32 | 11 => -1, 33 | 13 => -0.92, 34 | "14" => "-1" 35 | ); 36 | $result = $model->predict($data); 37 | if($result > 0) { 38 | echo "ok"; 39 | } 40 | } catch (SvmException $e) { 41 | echo $e->getMessage(); 42 | } 43 | 44 | ?> 45 | --EXPECT-- 46 | got exception 47 | ok -------------------------------------------------------------------------------- /phpdocs/book.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SVM 6 | SVM 7 | 8 | 9 | &reftitle.intro; 10 | 11 | LibSVM is an efficient solver for SVM classification and regression problems. The svm extension wraps this in a PHP interface for easy use in PHP scripts. 12 | 13 | 14 | 15 | &reference.svm.setup; 16 | &reference.svm.examples; 17 | 18 | &reference.svm.svm; 19 | &reference.svm.svmmodel; 20 | 21 | 22 | 23 | 43 | -------------------------------------------------------------------------------- /tests/005_regression.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Load a larger amount of training data from a file and test regressions 3 | --SKIPIF-- 4 | 7 | --FILE-- 8 | array(1 => -1 ,2 => 0.418919 ,3 => 0.411765 ,4 => -0.637168 ,5 => -0.168408 ,6 => -0.294553 ,7 => -0.24424 ,8 => -0.389138 ), 11 | "10" => array(2 => 0.486486 ,3 => 0.445378 ,4 => -0.734513 ,5 => -0.226138 ,6 => -0.287155 ,7 => -0.314022 ,8 => -0.413054 ), 12 | "12" => array(1 => -1 ,2 => 0.716216 ,3 => 0.680672 ,4 => -0.654867 ,5 => 0.378785 ,6 => 0.270343 ,7 => -0.00987492 ,8 => -0.0164425), 13 | ); 14 | 15 | sleep(1); 16 | $svm = new svm(); 17 | 18 | $svm->setOptions(array( 19 | SVM::OPT_TYPE => SVM::C_SVC, 20 | SVM::OPT_KERNEL_TYPE => SVM::KERNEL_LINEAR, 21 | SVM::OPT_P => 0.1, // epsilon 0.1 22 | )); 23 | $model = $svm->train(dirname(__FILE__) . '/abalone.scale'); 24 | if($model) { 25 | echo "ok train\n"; 26 | foreach($data as $class => $d) { 27 | $result = $model->predict($d); 28 | if($result > 0) { 29 | echo "ok\n"; 30 | } else { 31 | echo "regression failed: " . $result . "\n"; 32 | } 33 | } 34 | } else { 35 | echo "training failed"; 36 | } 37 | ?> 38 | --EXPECT-- 39 | ok train 40 | ok 41 | ok 42 | ok 43 | -------------------------------------------------------------------------------- /phpdocs/svm/construct.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | SVM::__construct 7 | Construct a new SVM object 8 | 9 | 10 | 11 | &reftitle.description; 12 | 13 | SVM::__construct 14 | 15 | 16 | 17 | Constructs a new SVM object ready to accept training data. 18 | 19 | 20 | 21 | 22 | 23 | &reftitle.parameters; 24 | &no.function.parameters; 25 | 26 | 27 | 28 | &reftitle.returnvalues; 29 | 30 | Thows SVMException if the libsvm library could not be loaded 31 | 32 | 33 | 34 | 35 | 36 | 37 | 57 | -------------------------------------------------------------------------------- /tests/007_kernels.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test for various kernels 3 | --SKIPIF-- 4 | 7 | --FILE-- 8 | 1, 11 | 2 => -0.731729, 12 | 3 => -0.886786, 13 | 4 => -1, 14 | 5 => 0.230769, 15 | "6" => -0.25, 16 | 7 => -0.783509, 17 | 8 => 1, 18 | 9 => 1, 19 | 10 => "-0.820896", 20 | 11 => -1, 21 | 13 => -0.92, 22 | "14" => "-1" 23 | ); 24 | 25 | $kernels = array( 26 | array( 27 | SVM::OPT_TYPE => SVM::C_SVC, 28 | SVM::OPT_KERNEL_TYPE => SVM::KERNEL_POLY, 29 | ), 30 | array( 31 | SVM::OPT_TYPE => SVM::ONE_CLASS, 32 | SVM::OPT_KERNEL_TYPE => SVM::KERNEL_RBF, 33 | ), 34 | array( 35 | SVM::OPT_TYPE => SVM::EPSILON_SVR, 36 | SVM::OPT_KERNEL_TYPE => SVM::KERNEL_SIGMOID, 37 | ), 38 | array( 39 | SVM::OPT_TYPE => SVM::NU_SVR, 40 | SVM::OPT_KERNEL_TYPE => SVM::KERNEL_PRECOMPUTED, 41 | ), 42 | ); 43 | 44 | $svm = new svm(); 45 | 46 | foreach($kernels as $kernel) { 47 | $svm->setOptions($kernel); 48 | $model = $svm->train(dirname(__FILE__) . '/australian.scale'); 49 | 50 | if($model) { 51 | echo "ok train " . $kernel[SVM::OPT_TYPE] . "\n"; 52 | 53 | $result = $model->predict($data); 54 | if($result != false) { 55 | echo "ok " . $kernel[SVM::OPT_TYPE] . "\n"; 56 | } else { 57 | echo "failed: " . $result . "\n"; 58 | } 59 | } else { 60 | echo "training failed"; 61 | } 62 | } 63 | ?> 64 | --EXPECT-- 65 | ok train 0 66 | ok 0 67 | ok train 2 68 | ok 2 69 | ok train 3 70 | ok 3 71 | ok train 4 72 | ok 4 -------------------------------------------------------------------------------- /phpdocs/svm/getoptions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | SVM::getOptions 7 | Return the current training parameters 8 | 9 | 10 | 11 | &reftitle.description; 12 | 13 | public arraySVM::getOptions 14 | 15 | 16 | 17 | Retrieve an array containing the training parameters. The parameters will be keyed on the predefined SVM constants. 18 | 19 | 20 | 21 | 22 | 23 | &reftitle.parameters; 24 | &no.function.parameters; 25 | 26 | 27 | 28 | &reftitle.returnvalues; 29 | 30 | Returns an array of configuration settings. 31 | 32 | 33 | 34 | 35 | 36 | 37 | 57 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | LibSVM extension for PHP 2 | Copyright (c) 2011, Ian Barber 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of the copyright holder nor the 13 | names of its contributors may be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL IAN BARBER BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /phpdocs/svm/setoptions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | SVM::setOptions 7 | Set training parameters 8 | 9 | 10 | 11 | &reftitle.description; 12 | 13 | public booleanSVM::setOptions 14 | arrayparams 15 | 16 | 17 | Set one or more training parameters. 18 | 19 | 20 | 21 | 22 | 23 | &reftitle.parameters; 24 | 25 | 26 | 27 | params 28 | 29 | 30 | An array of training parameters, keyed on the SVM constants. 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | &reftitle.returnvalues; 40 | 41 | Return true on success, throws SVMException on error. 42 | 43 | 44 | 45 | 46 | 66 | -------------------------------------------------------------------------------- /phpdocs/setup.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | &reftitle.setup; 6 | 7 |
8 | &reftitle.required; 9 | 10 | Libsvm itself is required, and is available through some package management, or direct from the website. If installing from the website: http://www.csie.ntu.edu.tw/~cjlin/libsvm then some steps will need to be taken as the package does not install automatically: 11 | 12 | wget http://www.csie.ntu.edu.tw/~cjlin/cgi-bin/libsvm.cgi?+http://www.csie.ntu.edu.tw/~cjlin/libsvm+tar.gz 13 | tar xvzf libsvm-2.9.tar.gz 14 | cd libsvm-2.9 15 | make lib 16 | cp libsvm.so.1 /usr/lib 17 | ln -s libsvm.so.1 libsvm.so 18 | ldconfig 19 | ldconfig --print | grep libsvm 20 | 21 | This last step should show libsvm is installed. 22 | 23 |
24 | 25 |
26 | &reftitle.install; 27 | &no.install; 28 |
29 | 30 |
31 | &reftitle.runtime; 32 | &no.config; 33 |
34 | 35 |
36 | &reftitle.resources; 37 | &no.resource; 38 | 39 | 40 | 41 |
42 | 43 |
44 | 45 | 65 | -------------------------------------------------------------------------------- /config.m4: -------------------------------------------------------------------------------- 1 | PHP_ARG_WITH(svm, whether to enable svm support, 2 | [ --with-svm[=DIR] Enable svn support. DIR is the prefix to libsvm installation directory.], yes) 3 | 4 | if test "$PHP_SVM" != "no"; then 5 | 6 | 7 | dnl Get PHP version depending on shared/static build 8 | 9 | AC_MSG_CHECKING([PHP version is at least 5.2.0]) 10 | 11 | if test -z "${PHP_VERSION_ID}"; then 12 | if test -z "${PHP_CONFIG}"; then 13 | AC_MSG_ERROR([php-config not found]) 14 | fi 15 | PHP_SVM_FOUND_VERNUM=`${PHP_CONFIG} --vernum`; 16 | PHP_SVM_FOUND_VERSION=`${PHP_CONFIG} --version` 17 | else 18 | PHP_SVM_FOUND_VERNUM="${PHP_VERSION_ID}" 19 | PHP_SVM_FOUND_VERSION="${PHP_VERSION}" 20 | fi 21 | 22 | if test "$PHP_SVM_FOUND_VERNUM" -ge "50200"; then 23 | AC_MSG_RESULT(yes. found $PHP_SVM_FOUND_VERSION) 24 | else 25 | AC_MSG_ERROR(no. found $PHP_SVM_FOUND_VERSION) 26 | fi 27 | 28 | AC_MSG_CHECKING([for svm.h header]) 29 | for i in $PHP_SVM /usr/local /usr; 30 | do 31 | test -r $i/include/libsvm-2.0/libsvm/svm.h && SVM_PREFIX=$i && SVM_INC_DIR=$i/include/libsvm-2.0/ && SVM_OK=1 32 | done 33 | 34 | if test "$SVM_OK" != "1"; then 35 | for i in $PHP_SVM /usr/local /usr; 36 | do 37 | test -r $i/include/libsvm/svm.h && SVM_PREFIX=$i && SVM_INC_DIR=$i/include/ && SVM_OK=1 38 | done 39 | fi 40 | 41 | if test "$SVM_OK" != "1"; then 42 | AC_MSG_ERROR([Unable to find svm.h]) 43 | fi 44 | 45 | AC_MSG_RESULT([found in $SVM_INC_DIR]) 46 | 47 | AC_MSG_CHECKING([for libsvm shared libraries]) 48 | PHP_CHECK_LIBRARY(svm, svm_train, [ 49 | PHP_ADD_LIBRARY_WITH_PATH(svm, $SVM_PREFIX/lib, SVM_SHARED_LIBADD) 50 | PHP_ADD_INCLUDE($SVM_INC_DIR) 51 | ],[ 52 | AC_MSG_ERROR([not found. Make sure that libsvm is installed]) 53 | ],[ 54 | SVM_SHARED_LIBADD -lsvm 55 | ]) 56 | 57 | PHP_NEW_EXTENSION(svm, svm.c, $ext_shared) 58 | AC_DEFINE(HAVE_SVM,1,[ ]) 59 | 60 | PHP_SUBST(SVM_SHARED_LIBADD) 61 | fi 62 | 63 | -------------------------------------------------------------------------------- /phpdocs/svmmodel.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | The SVMModel class 7 | SVMModel 8 | 9 | 10 | 11 | 12 |
13 | &reftitle.intro; 14 | 15 | The SVMModel is the end result of the training process. It can be used to classify previously unseen data. 16 | 17 |
18 | 19 | 20 |
21 | &reftitle.classsynopsis; 22 | 23 | 24 | 25 | SVMModel 26 | 27 | 28 | 29 | 30 | SVMModel 31 | 32 | 33 | 34 | 35 | Methods 36 | 37 | 38 | 39 | 40 |
41 | 42 |
43 | 44 | &reference.svm.entities.svmmodel; 45 | 46 |
47 | 48 | 68 | -------------------------------------------------------------------------------- /phpdocs/versions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 49 | -------------------------------------------------------------------------------- /package.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | svm 7 | pecl.php.net 8 | Support Vector Machine Library 9 | LibSVM is an efficient solver for SVM classification and regression problems. The svm extension wraps this in a PHP interface for easy use in PHP scripts. 10 | 11 | 12 | Ian Barber 13 | ianb 14 | ian.barber@gmail.co, 15 | yes 16 | 17 | 2011-04-26 18 | 19 | 20 | 0.9.0 21 | 0.9.0 22 | 23 | 24 | beta 25 | beta 26 | 27 | PHP 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 5.2.0 54 | 55 | 56 | 1.4.0 57 | 58 | 59 | 60 | svm 61 | 62 | 63 | -------------------------------------------------------------------------------- /phpdocs/svmmodel/save.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | SVMModel::save 7 | Save a model to a file 8 | 9 | 10 | 11 | &reftitle.description; 12 | 13 | public booleanSVMModel::save 14 | stringfilename 15 | 16 | 17 | Save the model data to a file, for later use. 18 | 19 | 20 | 21 | 22 | 23 | &reftitle.parameters; 24 | 25 | 26 | 27 | filename 28 | 29 | 30 | The file to save the model to. 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | &reftitle.returnvalues; 40 | 41 | Throws SVMException on error. 42 | Returns true on success. 43 | 44 | 45 | 46 | 47 | &reftitle.seealso; 48 | 49 | 50 | SVMModel::load 51 | 52 | 53 | 54 | 55 | 56 | 57 | 77 | -------------------------------------------------------------------------------- /phpdocs/svmmodel/load.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | SVMModel::load 7 | Load a saved SVM Model 8 | 9 | 10 | 11 | &reftitle.description; 12 | 13 | public booleanSVMModel::load 14 | stringfilename 15 | 16 | 17 | Load a model file ready for classification or regression. 18 | 19 | 20 | 21 | 22 | 23 | &reftitle.parameters; 24 | 25 | 26 | 27 | filename 28 | 29 | 30 | The filename of the model. 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | &reftitle.returnvalues; 40 | 41 | Throws SVMException on error. 42 | Returns true on success. 43 | 44 | 45 | 46 | 47 | &reftitle.seealso; 48 | 49 | 50 | SVMModel::save 51 | 52 | 53 | 54 | 55 | 56 | 57 | 77 | -------------------------------------------------------------------------------- /phpdocs/svmmodel/construct.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | SVMModel::__construct 7 | Construct a new SVMModel 8 | 9 | 10 | 11 | &reftitle.description; 12 | 13 | SVMModel::__construct 14 | stringfilename 15 | 16 | 17 | Build a new SVMModel. Models will usually be created from the SVM::train function, but then saved models may be restored directly. 18 | 19 | 20 | 21 | 22 | 23 | &reftitle.parameters; 24 | 25 | 26 | 27 | filename 28 | 29 | 30 | The filename for the saved model file this model should load. 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | &reftitle.returnvalues; 40 | 41 | Throws SVMException on error 42 | 43 | 44 | 45 | 46 | &reftitle.seealso; 47 | 48 | 49 | SVMModel::load 50 | 51 | 52 | 53 | 54 | 55 | 56 | 76 | -------------------------------------------------------------------------------- /phpdocs/svmmodel/predict.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | SVMModel::predict 7 | Predict a value for previously unseen data 8 | 9 | 10 | 11 | &reftitle.description; 12 | 13 | public floatSVMModel::predict 14 | arraydata 15 | 16 | 17 | This function accepts an array of data and attempts to predict the class or regression value based on the model extracted from previously trained data. 18 | 19 | 20 | 21 | 22 | 23 | &reftitle.parameters; 24 | 25 | 26 | 27 | data 28 | 29 | 30 | The array to be classified. This should be a series of key => value pairs in increasing key order, but not necessarily continuous. 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | &reftitle.returnvalues; 40 | 41 | Float the predicted value. This will be a class label in the case of classification, a real value in the case of regression. 42 | Throws SVMException on error 43 | 44 | 45 | 46 | 47 | &reftitle.seealso; 48 | 49 | 50 | SVM::train 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 78 | -------------------------------------------------------------------------------- /php_svm.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | PHP Version 5 / svm | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 2010 Ian Barber | 6 | +----------------------------------------------------------------------+ 7 | | This source file is subject to version 3.0 of the PHP license, | 8 | | that is bundled with this package in the file LICENSE, and is | 9 | | available through the world-wide-web at the following url: | 10 | | http://www.php.net/license/3_0.txt. | 11 | | If you did not receive a copy of the PHP license and are unable to | 12 | | obtain it through the world-wide-web, please send a note to | 13 | | license@php.net so we can mail you a copy immediately. | 14 | +----------------------------------------------------------------------+ 15 | | Authors: Ian Barber | 16 | +----------------------------------------------------------------------+ 17 | */ 18 | #ifndef _PHP_SVM_H_ 19 | # define _PHP_SVM_H_ 20 | 21 | #define PHP_SVM_EXTNAME "svm" 22 | #define PHP_SVM_EXTVER "@PACKAGE_VERSION@" 23 | 24 | #ifdef HAVE_CONFIG_H 25 | # include "config.h" 26 | #endif 27 | 28 | #ifdef ZTS 29 | # include "TSRM.h" 30 | #endif 31 | 32 | #include "php.h" 33 | #include 34 | 35 | ZEND_BEGIN_MODULE_GLOBALS(svm) 36 | zend_bool test; 37 | ZEND_END_MODULE_GLOBALS(svm) 38 | 39 | ZEND_EXTERN_MODULE_GLOBALS(svm) 40 | 41 | #ifdef ZTS 42 | # define SVM_G(v) TSRMG(svm_globals_id, zend_svm_globals *, v) 43 | #else 44 | # define SVM_G(v) (svm_globals.v) 45 | #endif 46 | 47 | typedef struct _php_svm_object { 48 | zend_object zo; 49 | /* hold the SVM parameters */ 50 | struct svm_parameter param; 51 | 52 | /* Store the last error message here */ 53 | char last_error[512]; 54 | 55 | } php_svm_object; 56 | 57 | typedef struct _php_svm_model_object { 58 | zend_object zo; 59 | 60 | /* Hold the training data */ 61 | struct svm_node *x_space; 62 | 63 | /* hold the model generated by training, or to be used for classifying*/ 64 | struct svm_model *model; 65 | 66 | } php_svm_model_object; 67 | 68 | extern zend_module_entry svm_module_entry; 69 | #define phpext_svm_ptr &svm_module_entry 70 | 71 | #endif /* _PHP_SVM_H_ */ 72 | 73 | 74 | -------------------------------------------------------------------------------- /phpdocs/svm/train.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | SVM::train 7 | Create a SVMModel based on training data 8 | 9 | 10 | 11 | &reftitle.description; 12 | 13 | public SVMModelsvm::train 14 | arrayproblem 15 | arrayweights 16 | 17 | 18 | Train a support vector machine based on the supplied training data. 19 | 20 | 21 | 22 | 23 | 24 | &reftitle.parameters; 25 | 26 | 27 | 28 | problem 29 | 30 | 31 | The problem can be provided in three different ways. 32 | An array, where the data should start with the class label (usually 1 or -1) then followed by a sparse data set of dimension => data pairs. 33 | A URL to a file containing a SVM Light formatted problem, with the each line being a new training example, the start of each line containing the class (1, -1) then a series of tab separated data values shows as key:value. 34 | A opened stream pointing to a data source formatted as in the file above. 35 | 36 | 37 | 38 | 39 | weights 40 | 41 | 42 | Weights are an optional set of weighting parameters for the different classes, to help account for unbalanced training sets. For example, if the classes were 1 and -1, and -1 had significantly more example than one, the weight for -1 could be 0.5. Weights should be in the range 0-1. 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | &reftitle.returnvalues; 52 | 53 | Returns an SVMModel that can be used to classify previously unseen data. 54 | Throws SVMException on error 55 | 56 | 57 | 58 | 59 | 60 | 61 | 81 | -------------------------------------------------------------------------------- /phpdocs/svm/crossvalidate.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | SVM::crossvalidate 7 | Test training params on subsets of the training data. 8 | 9 | 10 | 11 | &reftitle.description; 12 | 13 | public floatsvm::crossvalidate 14 | arrayproblem 15 | intnumber_of_folds 16 | 17 | 18 | Crossvalidate can be used to test the effectiveness of the current parameter set on a subset of the training data. Given a problem set and a n "folds", it separates the problem set into n subsets, and the repeatedly trains on one subset and tests on another. While the accuracy will generally be lower than a SVM trained on the enter data set, the accuracy score returned should be relatively useful, so it can be used to test different training parameters. 19 | 20 | 21 | 22 | 23 | 24 | &reftitle.parameters; 25 | 26 | 27 | 28 | problem 29 | 30 | 31 | The problem data. This can either be in the form of an array, the URL of an SVMLight formatted file, or a stream to an opened SVMLight formatted datasource. 32 | 33 | 34 | 35 | 36 | number_of_folds 37 | 38 | 39 | The number of sets the data should be divided into and cross tested. A higher number means smaller training sets and less reliability. 5 is a good number to start with. 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | &reftitle.returnvalues; 49 | 50 | The correct percentage, expressed as a floating point number from 0-1. In the case of NU_SVC or EPSILON_SVR kernels the mean squared error will returned instead. 51 | 52 | 53 | 54 | 55 | &reftitle.seealso; 56 | 57 | 58 | SVM::train 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 87 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | INTRODUCTION 2 | 3 | LibSVM is an efficient solver for SVM classification and regression problems. The svm extension wraps this in a PHP interface for easy use in PHP scripts. The extension requires PHP 5.2 or above. 4 | 5 | Libsvm itself is required, and is available through some package management, or direct from the website. 6 | 7 | On ubuntu and other debian based systems, you may be able to installed the libsvm-dev package: 8 | 9 | apt-get install libsvm-dev 10 | 11 | If installing from the website: http://www.csie.ntu.edu.tw/~cjlin/libsvm then some steps will need to be taken as the package does not install automatically: 12 | 13 | wget http://www.csie.ntu.edu.tw/~cjlin/cgi-bin/libsvm.cgi?+http://www.csie.ntu.edu.tw/~cjlin/libsvm+tar.gz 14 | tar xvzf libsvm-3.1.tar.gz 15 | cd libsvm-3.1 16 | make lib 17 | cp libsvm.so.1 /usr/lib 18 | ln -s libsvm.so.1 libsvm.so 19 | ldconfig 20 | ldconfig --print | grep libsvm 21 | 22 | This last step should show libsvm is installed. 23 | 24 | Once libsvm is installed, the extension can be installed in the usual way. 25 | 26 | USAGE 27 | 28 | The basic process is to define parameters, supply training data to generate a model on, then make predictions based on the model. There are a default set of parameters that should get some results with most any input, so we'll start by looking at the data. 29 | 30 | Data is supplied in either a file, a stream, or as an an array. If supplied in a file or a stream, it must contain one line per training example, which must be formatted as an integer class (usually 1 and -1) followed by a series of feature/value pairs, in increasing feature order. The features are integers, the values floats, usually scaled 0-1. For example: 31 | 32 | -1 1:0.43 3:0.12 9284:0.2 33 | 34 | In a document classification problem, say a spam checker, each line would represent a document. There would be two classes, -1 for spam, 1 for ham. Each feature would represent some word, and the value would represent that importance of that word to the document (perhaps the frequency count, with the total scaled to unit length). Features that were 0 (e.g. the word did not appear in the document at all) would simply not be included. 35 | 36 | In array mode, the data must be passed as an array of arrays. Each sub-array must have the class as the first element, then key => value sets for the feature values pairs. E.g. 37 | 38 | array( 39 | array(-1, 1 => 0.43, 3 => 0.12, 9284 => 0.2), 40 | ); 41 | 42 | This data is passed to the SVM class's train function, which will return an SVM model is successful. 43 | 44 | $svm = new SVM(); 45 | $model = $svm->train($data); 46 | 47 | or, for example with a filename 48 | 49 | $svm = new SVM(); 50 | $model = $svm->train("traindata.txt"); 51 | 52 | Once a model has been generated, it can be used to make predictions about previously unseen data. This can be passed as an array to the model's predict function, in the same format as before, but without the label. The response will be the class. 53 | 54 | $data = array(1 => 0.43, 3 => 0.12, 9284 => 0.2); 55 | $result = $model->predict($data); 56 | 57 | In this case, $result would be -1. 58 | 59 | Models can be saved and restored as required, using the save and load functions, which both take a file location. 60 | 61 | $model->save('model.svm'); 62 | 63 | And to load: 64 | 65 | $model = new SVMModel(); 66 | $model->load('model.svm'); 67 | 68 | -------------------------------------------------------------------------------- /phpdocs/svmexception.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | The SVMException class 7 | SVMException 8 | 9 | 10 | 11 | 12 |
13 | &reftitle.intro; 14 | 15 | The exception object thrown on errors from the SVM and SVMModel classes. 16 | 17 |
18 | 19 | 20 |
21 | &reftitle.classsynopsis; 22 | 23 | 24 | 25 | SVMException 26 | 27 | 28 | 29 | 30 | SVMException 31 | 32 | 33 | 34 | extends 35 | Exception 36 | 37 | 38 | 39 | Properties 40 | 41 | 42 | Methods 43 | 44 | 45 | Inherited methods 46 | 47 | 48 | 49 | 50 | 51 |
52 | 53 | 54 | 55 |
56 | &reftitle.properties; 57 | 58 | 59 | message 60 | 61 | 62 | 63 | 64 | 65 | code 66 | 67 | 68 | 69 | 70 | 71 | file 72 | 73 | 74 | 75 | 76 | 77 | line 78 | 79 | 80 | 81 | 82 | 83 |
84 | 85 | 86 | 87 |
88 | 89 | &reference.svm.entities.svmexception; 90 | 91 |
92 | 93 | 113 | -------------------------------------------------------------------------------- /phpdocs/examples.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | &reftitle.examples; 6 | 7 | 8 | The basic process is to define parameters, supply training data to generate a model on, then make predictions based on the model. There are a default set of parameters that should get some results with most any input, so we'll start by looking at the data. 9 | 10 | Data is supplied in either a file, a stream, or as an an array. If supplied in a file or a stream, it must contain one line per training example, which must be formatted as an integer class (usually 1 and -1) followed by a series of feature/value pairs, in increasing feature order. The features are integers, the values floats, usually scaled 0-1. For example: 11 | 12 | -1 1:0.43 3:0.12 9284:0.2 13 | 14 | In a document classification problem, say a spam checker, each line would represent a document. There would be two classes, -1 for spam, 1 for ham. Each feature would represent some word, and the value would represent that importance of that word to the document (perhaps the frequency count, with the total scaled to unit length). Features that were 0 (e.g. the word did not appear in the document at all) would simply not be included. 15 | 16 | In array mode, the data must be passed as an array of arrays. Each sub-array must have the class as the first element, then key => value sets for the feature values pairs. 17 | 18 | This data is passed to the SVM class's train function, which will return an SVM model is successful. 19 | 20 | Once a model has been generated, it can be used to make predictions about previously unseen data. This can be passed as an array to the model's predict function, in the same format as before, but without the label. The response will be the class. 21 | 22 | Models can be saved and restored as required, using the save and load functions, which both take a file location. 23 | 24 | 25 | 26 | Train from array 27 | 28 | 0.43, 3 => 0.12, 9284 => 0.2), 32 | array(1, 1 => 0.22, 5 => 0.01, 94 => 0.11), 33 | ); 34 | 35 | $svm = new SVM(); 36 | $model = $svm->train($data); 37 | 38 | $data = array(1 => 0.43, 3 => 0.12, 9284 => 0.2); 39 | $result = $model->predict($data); 40 | var_dump($result); 41 | $model->save('model.svm'); 42 | ?> 43 | ]]> 44 | 45 | &example.outputs.similar; 46 | 47 | 51 | 52 | 53 | 54 | Train from a file 55 | 56 | train("traindata.txt"); 60 | ?> 61 | ]]> 62 | 63 | &example.outputs.similar; 64 | 65 | 68 | 69 | 70 | 71 | 72 | 92 | 93 | -------------------------------------------------------------------------------- /phpdocs/svm.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | The SVM class 7 | SVM 8 | 9 | 10 | 11 | 12 |
13 | &reftitle.intro; 14 | 15 | 16 | 17 |
18 | 19 | 20 |
21 | &reftitle.classsynopsis; 22 | 23 | 24 | 25 | SVM 26 | 27 | 28 | 29 | 30 | SVM 31 | 32 | 33 | 34 | Constants 35 | 36 | const 37 | integer 38 | SVM::C_SVC 39 | 0 40 | 41 | 42 | const 43 | integer 44 | SVM::NU_SVC 45 | 1 46 | 47 | 48 | const 49 | integer 50 | SVM::ONE_CLASS 51 | 2 52 | 53 | 54 | const 55 | integer 56 | SVM::EPSILON_SVR 57 | 3 58 | 59 | 60 | const 61 | integer 62 | SVM::NU_SVR 63 | 4 64 | 65 | 66 | const 67 | integer 68 | SVM::KERNEL_LINEAR 69 | 0 70 | 71 | 72 | const 73 | integer 74 | SVM::KERNEL_POLY 75 | 1 76 | 77 | 78 | const 79 | integer 80 | SVM::KERNEL_RBF 81 | 2 82 | 83 | 84 | const 85 | integer 86 | SVM::KERNEL_SIGMOID 87 | 3 88 | 89 | 90 | const 91 | integer 92 | SVM::KERNEL_PRECOMPUTED 93 | 4 94 | 95 | 96 | const 97 | integer 98 | SVM::OPT_TYPE 99 | 101 100 | 101 | 102 | const 103 | integer 104 | SVM::OPT_KERNEL_TYPE 105 | 102 106 | 107 | 108 | const 109 | integer 110 | SVM::OPT_DEGREE 111 | 103 112 | 113 | 114 | const 115 | integer 116 | SVM::OPT_SHRINKING 117 | 104 118 | 119 | 120 | const 121 | integer 122 | SVM::OPT_PROPABILITY 123 | 105 124 | 125 | 126 | const 127 | integer 128 | SVM::OPT_GAMMA 129 | 201 130 | 131 | 132 | const 133 | integer 134 | SVM::OPT_NU 135 | 202 136 | 137 | 138 | const 139 | integer 140 | SVM::OPT_EPS 141 | 203 142 | 143 | 144 | const 145 | integer 146 | SVM::OPT_P 147 | 204 148 | 149 | 150 | const 151 | integer 152 | SVM::OPT_COEF_ZERO 153 | 205 154 | 155 | 156 | const 157 | integer 158 | SVM::OPT_C 159 | 206 160 | 161 | 162 | const 163 | integer 164 | SVM::OPT_CACHE_SIZE 165 | 207 166 | 167 | 168 | const 169 | integer 170 | SVM::OPT_WEIGHT 171 | 208 172 | 173 | 174 | Methods 175 | 176 | 177 | 178 | 179 |
180 | 181 | 182 |
183 | &reftitle.constants; 184 |
185 | svm Node Types 186 | 187 | 188 | 189 | SVM::C_SVC 190 | 191 | The basic C_SVC SVM type. The default, and a good starting point. 192 | 193 | 194 | 195 | 196 | SVM::NU_SVC 197 | 198 | The NU_SVC type uses a different, more flexible, error weighting. 199 | 200 | 201 | 202 | 203 | SVM::ONE_CLASS 204 | 205 | Train just on a single class, using outliers as negative examples. 206 | 207 | 208 | 209 | 210 | SVM::EPSILON_SVR 211 | 212 | A SVM type for regression (predicting a value rather than just a class) 213 | 214 | 215 | 216 | 217 | SVM::NU_SVR 218 | 219 | A NU style SVM regression type 220 | 221 | 222 | 223 | 224 | SVM::KERNEL_LINEAR 225 | 226 | A very simple kernel, can work well on large document classification problems. 227 | 228 | 229 | 230 | 231 | SVM::KERNEL_POLY 232 | 233 | A polynomial kernel. 234 | 235 | 236 | 237 | 238 | SVM::KERNEL_RBF 239 | 240 | The common Gaussian RBD kernel. Handles non-linear problems well and is a good default for classification. 241 | 242 | 243 | 244 | 245 | SVM::KERNEL_SIGMOID 246 | 247 | A kernel bsaed on the sigmoid function. Using this makes the SVM very similar to a two layer sigmoid based neural network. 248 | 249 | 250 | 251 | 252 | SVM::KERNEL_PRECOMPUTED 253 | 254 | A precomputer kernel - currently unsupported. 255 | 256 | 257 | 258 | 259 | SVM::OPT_TYPE 260 | 261 | The options key for the SVM type 262 | 263 | 264 | 265 | 266 | SVM::OPT_KERNEL_TYPE 267 | 268 | The options key for the kernel type 269 | 270 | 271 | 272 | 273 | SVM::OPT_DEGREE 274 | 275 | 276 | 277 | 278 | 279 | 280 | SVM::OPT_SHRINKING 281 | 282 | 283 | 284 | 285 | 286 | 287 | SVM::OPT_PROBABILITY 288 | 289 | 290 | 291 | 292 | 293 | 294 | SVM::OPT_GAMMA 295 | 296 | 297 | 298 | 299 | 300 | 301 | SVM::OPT_NU 302 | 303 | The option key for the nu parameter, only used in the NU_ SVM types 304 | 305 | 306 | 307 | 308 | SVM::OPT_EPS 309 | 310 | The option key for the Epsilon parameter, used in epsilon regression. 311 | 312 | 313 | 314 | 315 | SVM::OPT_P 316 | 317 | 318 | 319 | 320 | 321 | 322 | SVM::OPT_COEF_ZERO 323 | 324 | 325 | 326 | 327 | 328 | 329 | SVM::OPT_C 330 | 331 | The option for the cost parameter that controls tradeoff between errors and generality. 332 | 333 | 334 | 335 | 336 | SVM::OPT_CACHE_SIZE 337 | 338 | 339 | 340 | 341 | 342 | 343 | SVM::OPT_WEIGHT 344 | 345 | 346 | 347 | 348 | 349 | 350 |
351 |
352 | 353 | 354 | 355 |
356 | 357 | &reference.svm.entities.svm; 358 | 359 |
360 | 361 | 381 | -------------------------------------------------------------------------------- /tests/australian.scale: -------------------------------------------------------------------------------- 1 | -1 1:1 2:-0.749474 3:-0.181429 5:-0.538462 6:-0.25 7:-0.888772 8:-1 9:-1 10:-1 11:1 13:-0.9 14:-0.97576 2 | -1 1:-1 2:-0.731729 3:-0.5 5:0.0769231 6:-0.25 7:-0.988421 8:-1 9:-1 10:-1 11:-1 13:-0.84 14:-1 3 | -1 1:-1 2:-0.52391 3:-0.875 4:-1 5:-0.538462 6:-0.25 7:-0.912281 8:-1 9:-1 10:-1 11:1 13:-0.72 14:-1 4 | +1 1:-1 2:-0.761805 3:-0.178571 4:-1 5:-0.384615 6:-0.5 7:-1 8:1 9:1 10:-0.671642 11:1 13:-1 14:-1 5 | +1 1:1 2:-0.806917 3:-0.416429 5:-0.230769 6:-0.25 7:-0.862456 8:1 9:1 10:-0.58209 11:-1 13:-0.94 14:-0.99684 6 | +1 1:-1 2:-0.937444 3:-0.958214 5:0.0769231 6:0.75 7:-0.894737 8:1 9:1 10:-0.940299 11:-1 13:-0.9 14:-1 7 | -1 1:1 2:-0.889624 3:-0.535714 5:-0.692308 6:-0.25 7:-0.991228 8:-1 9:-1 10:-1 11:-1 13:-0.94 14:-0.998 8 | +1 1:-1 2:0.350977 3:-0.681429 5:0.538462 6:0.75 7:-0.786667 8:1 9:1 10:-0.820896 11:-1 13:-0.957 14:-0.9888 9 | -1 1:1 2:-0.576541 3:-0.928571 4:-1 5:-0.846154 6:0.75 7:-0.789474 8:-1 9:-1 10:-1 11:-1 13:-0.824 14:-0.98926 10 | -1 1:-1 2:0.263158 3:-0.494286 5:-0.538462 6:0.75 7:-0.526316 8:1 9:1 10:-0.910448 11:1 13:-0.9 14:-0.999 11 | +1 1:1 2:-0.406015 3:-0.875 5:1 6:0.75 7:-0.684211 8:1 9:1 10:-0.880597 11:1 13:-0.747 14:-0.98286 12 | +1 1:1 2:-0.16782 3:-0.642857 5:0.538462 6:0.75 7:-0.649123 8:1 9:1 10:-0.820896 11:1 13:-0.53 14:-1 13 | -1 1:1 2:-0.79188 3:-0.910714 4:-1 5:0.0769231 6:0.75 7:-0.903509 8:1 9:1 10:-0.910448 11:1 13:-0.86 14:-0.9958 14 | +1 1:1 2:-0.363308 3:-0.642857 5:1 6:0.75 7:-0.473684 8:1 9:1 10:-0.820896 11:1 13:-1 14:-0.98 15 | -1 1:1 2:0.348271 3:-0.806429 5:0.0769231 6:-0.25 7:-0.830526 8:-1 9:-1 10:-1 11:1 13:-0.68 14:-1 16 | +1 1:1 2:0.0324813 3:-0.568571 5:-0.538462 6:-0.25 7:-0.997193 8:-1 9:-1 10:-1 11:-1 13:-1 14:-0.9462 17 | +1 1:1 2:-0.52391 3:-0.678571 5:0.230769 6:-0.25 7:-0.473684 8:1 9:1 10:-0.940299 11:1 13:-0.67 14:-1 18 | +1 1:-1 2:-0.844511 3:-0.357143 5:-0.230769 6:-0.25 7:-0.947368 8:1 9:1 10:-0.940299 11:-1 13:-0.912 14:-0.98818 19 | -1 1:1 2:-0.81203 3:-0.910714 4:-1 5:-0.538462 6:-0.25 7:-0.991228 8:-1 9:-1 10:-1 11:-1 13:-0.86 14:-0.99992 20 | +1 1:-1 2:-0.739248 3:-0.595357 5:0.538462 6:-0.25 7:-0.818596 8:1 9:1 10:-0.791045 11:-1 13:-0.871 14:-0.93486 21 | -1 1:-1 2:-0.566316 3:-0.958214 5:-0.230769 6:-0.25 7:-0.997193 8:-1 9:-1 10:-1 11:-1 13:-0.74 14:-0.97992 22 | -1 1:-1 2:-0.836992 3:-0.958214 4:-1 5:-0.230769 6:-0.25 7:-0.958947 8:1 9:-1 10:-1 11:1 13:-0.84 14:-1 23 | -1 1:1 2:-0.175338 3:-0.904643 5:-0.846154 6:-0.25 7:-0.988421 8:-1 9:-1 10:-1 11:-1 13:-0.832 14:-1 24 | -1 1:1 2:-0.163007 3:-0.875 5:-0.538462 6:-0.25 7:-0.985263 8:1 9:-1 10:-1 11:-1 13:-0.84 14:-1 25 | -1 1:1 2:-0.827068 3:-0.315357 5:-0.230769 6:-0.25 7:-0.944561 8:-1 9:-1 10:-1 11:-1 13:-0.92 14:-0.993 26 | +1 1:1 2:-0.428571 3:-0.892857 5:0.846154 6:0.75 7:-0.614035 8:1 9:1 10:-0.910448 11:1 13:-1 14:-1 27 | -1 1:1 2:-0.736842 3:-0.991071 4:-1 5:-0.538462 6:-0.25 7:-0.991228 8:-1 9:-1 10:-1 11:-1 13:-0.8 14:-0.9986 28 | +1 1:1 2:-0.41594 3:-0.782857 4:-1 5:0.0769231 6:0.75 7:-0.856842 8:1 9:1 10:-0.970149 11:1 13:-0.82 14:-0.63946 29 | +1 1:-1 2:-0.491128 3:-0.142857 5:0.0769231 6:-0.25 7:-0.859649 8:1 9:1 10:-0.970149 11:-1 13:-0.78 14:-0.99962 30 | +1 1:1 2:-0.719398 3:-0.821429 5:0.0769231 6:-0.25 7:-0.92386 8:1 9:1 10:-0.671642 11:1 13:-0.94 14:-0.95632 31 | +1 1:1 2:-0.601504 3:-0.946429 5:0.0769231 6:0.75 7:-0.701754 8:1 9:1 10:-0.910448 11:1 13:-0.688 14:-0.997 32 | -1 1:-1 2:-0.799398 3:-0.25 4:-1 5:1 6:0.75 7:-1 8:-1 9:-1 10:-1 11:1 13:-0.846 14:-0.99936 33 | -1 1:1 2:0.160301 3:-0.901786 4:-1 5:0.0769231 6:0.75 7:-0.33614 8:1 9:-1 10:-1 11:1 13:-0.8 14:-0.998 34 | +1 1:1 2:-0.719398 3:-0.178571 5:0.230769 6:0.75 7:-0.850877 8:1 9:1 10:-0.671642 11:1 13:-0.71 14:-0.99432 35 | -1 1:1 2:-0.125413 3:-0.910714 5:-0.0769231 6:-0.25 7:-0.0263158 8:-1 9:1 10:-0.970149 11:1 13:-0.648 14:-0.99776 36 | -1 1:1 2:0.836993 3:0.357143 4:-1 5:-1 6:-1 7:-0.997193 8:-1 9:1 10:-0.940299 11:-1 13:-1 14:-0.99298 37 | +1 1:1 2:-0.661654 3:-0.107143 5:-0.230769 6:-0.25 7:-0.789474 8:1 9:-1 10:-1 11:1 12:-1 13:-0.98 14:-1 38 | +1 1:1 2:-0.223158 3:-0.00607143 5:0.230769 6:-0.25 7:-0.394737 8:1 9:1 10:-0.820896 11:1 13:-0.93 14:-1 39 | +1 1:-1 2:0.0225564 3:-0.428571 5:0.0769231 6:-0.25 7:-0.447368 8:1 9:1 10:-0.820896 11:1 13:-1 14:-0.9748 40 | +1 1:-1 2:0.0126315 3:-0.785714 5:1 6:-0.25 7:-0.0263158 8:1 9:1 10:-0.940299 11:1 13:-0.481 14:-0.96592 41 | +1 1:1 2:-0.716692 3:-1 5:0.846154 6:-0.25 7:-0.994035 8:1 9:-1 10:-1 11:-1 13:-1 14:-1 42 | -1 1:1 2:-0.734436 3:-0.892857 4:-1 5:-0.230769 6:-0.25 7:-0.962105 8:-1 9:-1 10:-1 11:1 13:-0.88 14:-0.99866 43 | +1 1:1 2:-0.609023 3:-0.919643 5:1 6:0.75 7:-0.912281 8:1 9:-1 10:-1 11:-1 13:-1 14:-0.89404 44 | -1 1:1 2:0.491128 3:-0.961429 5:0.0769231 6:-0.25 7:-0.958947 8:1 9:1 10:-0.910448 11:1 13:-0.82 14:-1 45 | -1 1:1 2:-0.699248 3:-0.970357 4:-1 5:0.0769231 6:-0.25 7:-0.997193 8:-1 9:1 10:-0.940299 11:-1 13:-0.872 14:-0.99988 46 | +1 1:-1 2:-0.789474 3:-0.267857 5:0.538462 6:-0.25 7:-0.950175 8:1 9:1 10:-0.940299 11:1 13:-0.951 14:-1 47 | -1 1:-1 2:-0.676692 3:-0.875 4:-1 5:0.0769231 6:-0.25 7:-0.988421 8:-1 9:-1 10:-1 11:-1 13:-0.868 14:-1 48 | +1 1:1 2:-0.927218 3:-0.997143 5:0.0769231 6:-0.25 7:-0.997193 8:-1 9:-1 10:-1 11:-1 13:-1 14:-1 49 | -1 1:-1 2:-0.526316 3:-0.857143 4:-1 5:0.384615 6:0.75 7:-0.859649 8:-1 9:-1 10:-1 11:-1 13:-0.744 14:-0.99966 50 | +1 1:-1 2:0.175338 3:0.0714286 5:0.0769231 6:-0.25 7:-0.614035 8:1 9:1 10:-0.58209 11:-1 13:-1 14:-0.956 51 | -1 1:1 2:-0.441203 3:-0.75 5:-0.538462 6:-0.25 7:-0.964912 8:-1 9:-1 10:-1 11:1 13:-0.768 14:-1 52 | -1 1:1 2:-0.779549 3:-0.705357 4:-1 5:-0.692308 6:0.75 7:-0.997193 8:-1 9:-1 10:-1 11:-1 13:-0.86 14:-0.998 53 | -1 1:1 2:-0.566316 3:-0.991071 4:-1 5:-0.538462 6:-0.25 7:-0.994035 8:-1 9:-1 10:-1 11:-1 13:-0.784 14:-0.958 54 | -1 1:1 2:-0.842105 3:-0.875 4:-1 5:0.0769231 6:-0.25 7:-0.83614 8:-1 9:-1 10:-1 11:1 13:-0.888 14:-0.99988 55 | -1 1:1 2:-0.58406 3:-0.767857 4:-1 5:0.538462 6:0.75 7:-0.643158 8:-1 9:1 10:-0.940299 11:1 13:-0.631 14:-0.99998 56 | +1 1:1 2:-0.576541 3:-0.892857 5:0.230769 6:-0.25 7:-0.859649 8:1 9:1 10:-0.671642 11:1 13:-0.566 14:-0.9993 57 | +1 1:1 2:-0.210526 3:-0.535714 5:-0.230769 7:-0.754386 8:1 9:1 10:-0.970149 11:-1 13:-1 14:-0.99 58 | -1 1:-1 2:-0.290827 3:-0.821429 5:-0.692308 6:0.75 7:-0.985263 8:-1 9:-1 10:-1 11:-1 13:-0.74 14:-0.99508 59 | +1 1:1 2:-0.135338 3:-0.648929 4:-1 5:0.230769 6:-0.25 7:-0.777895 8:1 9:-1 10:-1 11:1 13:-0.948 14:-0.97116 60 | +1 1:1 2:0.293233 3:-0.125 5:-0.0769231 6:-0.25 7:-0.912281 8:1 9:1 10:-0.880597 11:1 13:-0.8 14:-1 61 | -1 1:1 2:-0.115188 3:-0.642857 5:-0.692308 7:-0.842105 8:-1 9:-1 10:-1 11:1 13:-0.859 14:-1 62 | -1 1:-1 2:-0.699248 3:-0.949286 5:0.230769 6:-0.25 7:-0.982456 8:-1 9:1 10:-0.970149 11:1 13:-0.76 14:-0.99992 63 | +1 1:1 2:-0.857143 3:-0.857143 5:-0.692308 6:-0.25 7:-0.894737 8:1 9:1 10:-0.940299 11:-1 13:-0.88 14:-0.994 64 | -1 1:-1 2:-0.185564 3:-0.75 5:-0.692308 7:-0.964912 8:-1 9:-1 10:-1 11:-1 12:-1 13:0.16 14:-1 65 | +1 1:-1 2:-0.676692 3:-0.964286 5:0.538462 6:0.75 7:-0.894737 8:1 9:-1 10:-1 11:-1 13:-0.72 14:-0.98352 66 | +1 1:1 2:-0.150376 3:-0.300714 5:1 6:0.75 7:-0.441404 8:1 9:1 10:-0.761194 11:-1 13:-1 14:-1 67 | -1 1:-1 2:-0.827068 3:-0.988214 5:0.538462 6:-0.25 7:-0.997193 8:-1 9:-1 10:-1 11:1 13:-0.62 14:-1 68 | -1 1:1 2:-0.766917 3:-0.178571 5:-0.692308 6:-0.25 7:-0.964912 8:1 9:-1 10:-1 11:1 13:-0.9 14:-0.99864 69 | -1 1:1 2:-0.473684 3:-0.7975 5:-1 6:-1 7:-1 8:-1 9:1 10:-0.850746 11:-1 13:-0.824 14:-0.99708 70 | +1 1:1 2:-0.593985 3:-0.886786 5:0.846154 6:0.75 7:-0.871228 8:1 9:1 10:-0.641791 11:1 13:-0.417 14:-0.98574 71 | -1 1:1 2:0.0526316 3:0.881071 4:-1 5:-1 6:-1 7:-1 8:1 9:-1 10:-1 11:1 13:-1 14:-1 72 | -1 1:-1 2:-0.498647 3:-0.901786 5:0.230769 6:0.75 7:-0.997193 8:-1 9:1 10:-0.910448 11:-1 13:-1 14:-0.99934 73 | -1 1:1 2:-0.528722 3:-0.910714 5:0.230769 6:-0.25 7:-0.877193 8:-1 9:-1 10:-1 11:-1 13:-0.8 14:-1 74 | +1 1:1 2:-0.56391 3:-0.64 4:-1 5:0.0769231 7:-0.894737 8:1 9:1 10:-0.761194 11:1 13:-0.856 14:-0.99986 75 | +1 1:1 2:-0.203008 3:0.535714 5:0.384615 6:1 7:0.403509 8:1 9:1 10:-0.671642 11:-1 13:-1 14:-0.976 76 | -1 1:1 2:-0.315789 3:-0.696429 5:0.538462 6:-0.25 7:-0.754386 8:-1 9:-1 10:-1 11:-1 13:-0.546 14:-0.999 77 | -1 1:1 2:-0.644211 3:-0.976071 5:-0.538462 6:0.75 7:-0.754386 8:-1 9:-1 10:-1 11:1 13:-0.66 14:-1 78 | -1 1:1 2:-0.516391 3:-0.75 5:0.0769231 6:-0.25 7:-0.988421 8:-1 9:-1 10:-1 11:-1 13:-0.784 14:-1 79 | -1 1:1 2:-0.719398 3:-1 5:-0.538462 6:-0.25 7:-0.929825 8:-1 9:1 10:-0.671642 11:-1 12:-1 13:-1 14:-1 80 | +1 1:-1 2:-0.446015 3:-0.895714 5:0.230769 6:-0.25 7:-0.92386 8:1 9:1 10:-0.522388 11:-1 13:-0.88 14:-0.95842 81 | +1 1:1 2:-0.656541 3:-0.75 5:0.846154 6:-0.25 7:-0.95614 8:1 9:1 10:-0.791045 11:-1 13:-1 14:-0.85882 82 | -1 1:-1 2:-0.35579 3:-0.732143 5:-1 6:-1 7:-1 8:-1 9:1 10:-0.820896 11:-1 13:-1 14:-0.996 83 | -1 1:-1 2:-0.854737 3:-0.285714 5:-0.846154 6:-0.25 7:-0.970877 8:-1 9:-1 10:-1 11:-1 13:-0.92 14:-0.99916 84 | -1 1:1 2:-0.212932 3:-0.642857 5:-0.692308 7:-0.985263 8:-1 9:-1 10:-1 11:-1 13:-0.45 14:-1 85 | -1 1:1 2:-0.709173 3:-0.928571 5:0.0769231 6:-0.25 7:-0.964912 8:-1 9:-1 10:-1 11:1 12:-1 13:-0.72 14:-1 86 | +1 1:1 2:-0.283308 3:-1 5:0.0769231 6:-0.25 7:-1 8:-1 9:-1 10:-1 11:-1 12:1 13:-0.816 14:-1 87 | -1 1:-1 2:-0.669173 3:-0.0239286 5:0.538462 6:0.75 7:-0.894737 8:-1 9:-1 10:-1 11:-1 13:-0.72 14:-0.99998 88 | +1 1:-1 3:-0.0714286 5:-0.692308 7:-0.637544 8:1 9:1 10:-0.731343 11:1 13:-1 14:-1 89 | +1 1:1 2:-0.385865 3:-0.625 5:0.230769 6:-0.25 7:-0.994035 8:-1 9:-1 10:-1 11:1 13:-0.71 14:-0.99988 90 | -1 1:1 2:-0.746767 3:-0.958214 4:-1 5:-1 6:-1 7:-1 8:-1 9:-1 10:-1 11:-1 13:-0.9 14:-1 91 | -1 1:1 2:-0.578947 3:-0.907857 5:-0.538462 6:0.75 7:-0.982456 8:-1 9:-1 10:-1 11:1 12:-1 13:-0.86 14:-1 92 | -1 1:1 2:-0.12782 3:-0.708214 5:-0.230769 6:-0.25 7:-0.997193 8:-1 9:-1 10:-1 11:-1 13:-0.892 14:-0.998 93 | -1 1:1 2:-0.551278 3:0.0357143 5:-0.846154 6:-0.25 7:-0.991228 8:-1 9:-1 10:-1 11:-1 13:-1 14:-0.99428 94 | +1 1:1 2:-0.323308 3:-0.642857 5:0.0769231 7:-0.824561 8:1 9:1 10:-0.820896 11:-1 13:-1 14:-0.99266 95 | -1 1:-1 2:-0.867068 3:-0.285714 4:-1 5:0.538462 6:0.75 7:-0.988421 8:-1 9:-1 10:-1 11:-1 13:-0.66 14:-1 96 | +1 1:1 2:-0.774436 3:-0.892857 5:0.230769 6:-0.25 7:-0.894737 8:-1 9:-1 10:-1 11:-1 13:-0.85 14:-0.99984 97 | -1 1:-1 2:-0.243008 3:-0.881071 5:-0.230769 6:-0.25 7:-0.982456 8:-1 9:-1 10:-1 11:-1 13:-1 14:-0.9922 98 | -1 1:1 2:-0.456241 3:-0.997143 4:-1 5:-0.0769231 6:-0.25 7:-0.997193 8:-1 9:-1 10:-1 11:-1 13:-1 14:-1 99 | -1 1:-1 2:-0.892331 3:-0.321429 5:-0.230769 6:-0.25 7:-0.877193 8:-1 9:1 10:-0.701493 11:1 13:-1 14:-0.9998 100 | +1 1:-1 2:-0.799398 3:-0.940357 5:0.538462 6:-0.25 7:-0.888772 8:1 9:1 10:-0.970149 11:-1 13:-1 14:-1 101 | -1 1:-1 2:-0.238195 3:-0.714286 5:0.0769231 6:-0.25 7:-0.789474 8:-1 9:-1 10:-1 11:-1 13:-0.52 14:-1 102 | +1 1:1 2:-0.250526 3:-0.985 5:-0.538462 6:-0.25 7:-0.994035 8:1 9:-1 10:-1 11:1 13:-0.72 14:-1 103 | +1 1:1 2:-0.581353 3:-0.0178571 5:0.230769 6:-0.25 7:-0.596491 8:1 9:-1 10:-1 11:1 13:-0.513 14:-0.99 104 | +1 1:1 2:-0.578947 3:-0.958214 4:-1 5:0.846154 6:-0.25 7:-0.982456 8:1 9:1 10:-0.940299 11:-1 13:-0.74 14:-0.99 105 | -1 1:1 2:-0.842105 3:-1 4:-1 5:-1 6:-1 7:-1 8:-1 9:1 10:-0.880597 11:-1 13:-0.955 14:-0.99998 106 | +1 1:-1 2:-0.661654 3:-0.9375 5:1 6:0.75 7:-0.927018 8:1 9:-1 10:-1 11:1 13:-0.84 14:-0.8828 107 | +1 1:1 2:-0.581353 3:-0.857143 5:1 6:0.75 7:-0.929825 8:1 9:1 10:-0.880597 11:-1 13:-0.86 14:-0.84912 108 | -1 1:1 2:-0.744361 3:-0.357143 5:-0.230769 6:-0.25 7:-0.994035 8:-1 9:-1 10:-1 11:-1 13:-1 14:-1 109 | +1 1:-1 2:0.0851128 3:-0.0296429 5:-0.538462 6:0.75 7:-0.403509 8:1 9:-1 10:-1 11:1 13:-1 14:-1 110 | -1 1:1 2:-0.441203 3:-0.821429 5:0.0769231 6:-0.25 7:-0.912281 8:-1 9:-1 10:-1 11:1 13:-0.72 14:-1 111 | -1 1:1 2:-0.263158 3:-0.276786 4:-1 5:-0.538462 6:-0.25 7:-0.991228 8:-1 9:-1 10:-1 11:-1 13:-0.84 14:-1 112 | -1 1:1 2:0.00992487 3:-0.535714 5:0.0769231 6:-0.25 7:-0.929825 8:-1 9:-1 10:-1 11:1 13:-1 14:-0.99544 113 | -1 1:1 2:-0.576541 3:-0.714286 4:-1 5:-0.692308 6:0.75 7:-0.596491 8:1 9:1 10:-0.940299 11:1 13:-0.925 14:-1 114 | +1 1:-1 2:-0.338346 3:-0.934643 5:-0.230769 6:-0.25 7:-0.947368 8:1 9:1 10:-0.880597 11:-1 13:-1 14:-0.96834 115 | -1 1:1 2:-0.403609 3:-0.982143 5:-0.692308 7:-0.719298 8:-1 9:-1 10:-1 11:1 12:-1 13:-0.58 14:-1 116 | +1 1:1 2:-0.388571 3:-0.994286 4:-1 5:-0.0769231 7:-0.997193 8:1 9:1 10:-0.970149 11:1 13:-0.72 14:-0.96 117 | +1 1:-1 2:-0.789474 3:-0.261786 5:0.846154 6:0.75 7:-0.976491 8:1 9:1 10:-0.970149 11:1 13:-0.92 14:-0.999 118 | +1 1:1 2:-0.41594 3:-0.928571 5:1 6:-0.25 7:-0.947368 8:1 9:1 10:-0.791045 11:1 13:-0.66 14:-0.91858 119 | +1 1:1 2:-0.729323 3:-0.214286 5:0.538462 6:-0.25 7:-0.824561 8:1 9:1 10:-0.791045 11:1 13:-0.9 14:-0.98382 120 | +1 1:1 2:0.0526316 3:-0.392857 5:0.0769231 6:0.75 7:-0.122807 8:1 9:1 10:-0.731343 11:-1 13:-0.819 14:-0.9669 121 | +1 1:1 2:-0.193083 3:-0.642857 5:0.0769231 6:-0.25 7:-0.649123 8:1 9:1 10:-0.791045 11:-1 13:-1 14:-0.9387 122 | -1 1:1 2:-0.79188 3:-0.940357 4:-1 5:0.0769231 6:-0.25 7:-0.859649 8:-1 9:-1 10:-1 11:1 12:-1 13:-0.76 14:-1 123 | -1 1:-1 2:-0.24812 3:-0.892857 5:-1 6:-1 7:-1 8:-1 9:-1 10:-1 11:-1 13:-0.924 14:-1 124 | +1 1:-1 2:0.303158 3:0.392857 5:0.0769231 6:-0.25 7:-0.614035 8:1 9:1 10:-0.791045 11:-1 13:-1 14:-0.94 125 | +1 1:-1 2:-0.473684 3:-0.732143 5:0.846154 6:0.75 7:-0.95614 8:1 9:1 10:-0.731343 11:1 13:-0.819 14:-1 126 | -1 1:1 2:-0.75188 3:-0.943571 5:0.230769 6:-0.25 7:-0.979649 8:-1 9:1 10:-0.970149 11:-1 13:-0.58 14:-0.99434 127 | +1 1:-1 2:0.340752 3:-0.285714 5:0.538462 6:-0.25 7:-0.719298 8:1 9:1 10:-0.58209 11:-1 13:-1 14:-0.96796 128 | -1 1:1 2:-0.543759 3:-0.973214 5:0.0769231 6:-0.25 7:-0.979649 8:-1 9:-1 10:-1 11:-1 13:-0.78 14:-0.9972 129 | +1 1:-1 2:-0.0300752 3:-0.714286 5:-0.384615 6:-0.5 7:-1 8:1 9:-1 10:-1 11:-1 13:-0.9 14:-0.9808 130 | +1 1:1 2:-0.781955 3:-0.785714 4:-1 5:-0.846154 6:-0.25 7:-0.92386 8:1 9:1 10:-0.761194 11:1 13:-0.84 14:-0.99998 131 | +1 1:-1 2:-0.669173 3:-0.107143 5:-0.230769 6:-0.25 7:-0.894737 8:1 9:1 10:-0.641791 11:1 13:-0.88 14:-0.98866 132 | -1 1:-1 2:-0.787068 3:-0.964286 4:-1 5:0.384615 6:-0.75 7:-0.929825 8:-1 9:-1 10:-1 11:-1 13:-0.74 14:-1 133 | -1 1:1 2:-0.674286 3:-0.0357143 4:-1 5:-1 6:-1 7:-1 8:-1 9:-1 10:-1 11:-1 13:-0.816 14:-1 134 | -1 1:-1 2:-0.616541 3:-0.806429 4:-1 5:0.0769231 6:-0.25 7:-0.994035 8:-1 9:-1 10:-1 11:-1 12:-1 13:-0.92 14:-1 135 | -1 1:1 2:-0.182857 3:-0.940357 5:-1 6:-1 7:-1 8:1 9:-1 10:-1 11:-1 13:-0.87 14:-0.99998 136 | -1 1:-1 2:-0.260752 3:-0.684643 5:0.0769231 6:-0.25 7:-0.991228 8:-1 9:-1 10:-1 11:-1 13:-0.84 14:-1 137 | -1 1:1 2:-0.824662 3:-0.958214 5:-1 6:-1 7:-1 8:-1 9:1 10:-0.910448 11:-1 13:-0.65 14:-0.98462 138 | +1 1:1 2:-0.233083 3:-0.321429 5:-0.0769231 6:-0.25 7:-0.54386 8:1 9:1 10:-0.58209 11:-1 13:-0.76 14:-0.90786 139 | +1 1:1 2:-0.639098 3:-0.964286 5:0.0769231 6:-0.25 7:-0.897544 8:1 9:1 10:-0.850746 11:1 13:-0.688 14:-1 140 | +1 1:-1 2:-0.0276691 3:-0.785714 5:0.0769231 6:-0.25 7:-0.833333 8:1 9:1 10:-0.761194 11:1 13:-0.604 14:-0.91682 141 | -1 1:1 2:-0.821955 3:-0.285714 4:-1 5:-0.538462 6:0.75 7:-0.941404 8:1 9:-1 10:-1 11:1 13:-0.86 14:-1 142 | -1 1:-1 2:-0.744361 3:-0.910714 4:-1 5:-1 6:-1 7:-0.77193 8:-1 9:-1 10:-1 11:-1 13:-0.72 14:-1 143 | -1 1:1 2:-0.847218 3:-0.747143 4:-1 5:-1 6:-1 7:-1 8:-1 9:-1 10:-1 11:1 13:-0.82 14:-0.99998 144 | +1 1:1 2:0.513684 3:0.428571 5:1 6:0.75 7:0.22807 8:1 9:1 10:-0.731343 11:1 13:-1 14:-0.98 145 | -1 1:-1 2:-0.917293 3:-0.910714 5:0.538462 6:-0.25 7:-0.982456 8:-1 9:1 10:-0.970149 11:-1 13:-0.892 14:-0.99804 146 | +1 1:-1 2:0.651729 3:0.0714286 5:0.384615 6:1 7:-1 8:1 9:1 10:-0.58209 11:-1 13:-1 14:-0.93248 147 | +1 1:1 2:0.894737 3:0.592143 5:0.384615 6:1 7:-0.105263 8:1 9:1 10:-0.970149 11:1 13:-1 14:-0.99782 148 | -1 1:-1 2:-0.934737 3:-0.794643 5:0.538462 6:-0.25 7:-0.994035 8:-1 9:-1 10:-1 11:-1 13:-0.88 14:-1 149 | -1 1:1 2:-0.366015 3:-0.714286 5:-0.846154 7:-0.122807 8:1 9:-1 10:-1 11:1 13:-0.816 14:-1 150 | +1 1:-1 2:0.0126315 3:-0.428571 5:0.384615 7:-0.54386 8:1 9:1 10:-0.820896 11:-1 13:-0.625 14:0.022 151 | +1 1:1 2:-0.716692 3:-1 5:0.0769231 6:-0.25 7:-1 8:-1 9:-1 10:-1 11:-1 12:1 13:-0.816 14:-1 152 | -1 1:1 2:-0.0550377 3:-0.892857 5:0.0769231 6:-0.25 7:-0.824561 8:1 9:-1 10:-1 11:1 13:-0.86 14:-1 153 | -1 1:1 2:-0.957293 3:-0.5 5:0.384615 6:-0.25 7:-0.929825 8:-1 9:-1 10:-1 11:-1 13:-0.4 14:-1 154 | -1 1:1 2:-0.847218 3:-0.970357 4:-1 5:0.0769231 6:-0.25 7:-0.988421 8:-1 9:1 10:-0.970149 11:-1 13:-0.8 14:-0.99998 155 | +1 1:1 2:0.165414 3:-0.535714 5:-0.538462 6:-0.25 7:-0.558596 8:1 9:1 10:-0.552239 11:-1 13:-1 14:-0.77596 156 | +1 1:1 2:-0.836992 3:-1 4:-1 5:-0.0769231 7:-1 8:-1 9:-1 10:-1 11:1 12:-1 13:-0.5 14:-0.99998 157 | +1 1:1 2:-0.87218 3:-0.988214 5:0.538462 6:0.5 7:-0.985263 8:-1 9:-1 10:-1 11:-1 13:-0.8 14:-0.9992 158 | -1 1:1 2:-0.285714 3:-0.940357 5:0.384615 6:-0.25 7:-0.997193 8:-1 9:-1 10:-1 11:-1 13:-0.88 14:-0.9999 159 | +1 1:1 2:-0.731729 3:-0.886786 4:-1 5:0.230769 6:-0.25 7:-0.783509 8:1 9:1 10:-0.820896 11:-1 13:-0.92 14:-1 160 | -1 1:1 2:0.0249625 3:-0.7025 5:1 7:-0.994035 8:-1 9:-1 10:-1 11:1 13:-0.48 14:-1 161 | -1 1:1 2:-0.388571 3:-0.821429 5:0.0769231 6:-0.25 7:-0.929825 8:-1 9:-1 10:-1 11:-1 13:-0.54 14:-0.99968 162 | -1 1:-1 2:-0.418647 3:-0.883929 5:-0.846154 6:-0.25 7:-0.962105 8:-1 9:-1 10:-1 11:1 13:-1 14:-1 163 | +1 1:1 2:-0.117895 3:-0.973214 4:-1 5:0.0769231 6:-0.25 7:-0.973684 8:1 9:1 10:-0.761194 11:1 13:-0.7 14:-0.99676 164 | +1 1:1 2:-0.37594 3:-0.711429 4:-1 5:-0.692308 7:-0.403509 8:1 9:1 10:-0.791045 11:1 13:-0.805 14:-1 165 | -1 1:1 2:-0.12782 3:-0.785714 5:-0.692308 7:-0.929825 8:1 9:-1 10:-1 11:-1 13:-1 14:-0.996 166 | -1 1:1 2:-0.864662 3:-0.988214 5:-0.846154 6:-0.25 7:-0.982456 8:-1 9:-1 10:-1 11:1 12:-1 13:-0.72 14:-1 167 | -1 1:1 2:-0.719398 3:-0.821429 5:-1 6:-1 7:-0.994035 8:-1 9:-1 10:-1 11:1 13:-0.9 14:-0.91584 168 | +1 1:-1 2:-0.736842 3:-0.395714 4:-1 5:1 6:-0.25 7:-0.827368 8:-1 9:-1 10:-1 11:-1 13:-0.836 14:-1 169 | -1 1:1 2:-0.874586 3:-0.985357 5:-0.230769 6:-0.25 7:-0.997193 8:-1 9:-1 10:-1 11:-1 13:-0.72 14:-0.985 170 | -1 1:1 2:-0.859549 3:-0.256071 4:-1 5:-0.230769 6:-0.25 7:-0.991228 8:1 9:-1 10:-1 11:-1 13:-0.88 14:-0.9925 171 | -1 1:-1 2:-0.581353 3:-0.892857 5:-0.0769231 6:-0.25 7:-0.859649 8:1 9:-1 10:-1 11:-1 12:-1 13:-0.632 14:-1 172 | +1 1:-1 2:-0.844511 3:-0.339286 4:-1 5:0.0769231 6:-0.25 7:-0.929825 8:1 9:1 10:-0.880597 11:1 13:-0.92 14:-0.99 173 | -1 1:1 2:-0.731729 3:-0.946429 5:-0.692308 6:-0.25 7:-0.888772 8:-1 9:1 10:-0.970149 11:1 13:-0.6 14:-0.99982 174 | -1 1:1 2:0.466165 3:-0.0892857 4:-1 5:0.0769231 6:0.75 7:-0.649123 8:1 9:-1 10:-1 11:-1 13:-0.888 14:-1 175 | +1 1:-1 2:-0.706767 3:-0.357143 5:0.538462 6:-0.25 7:-0.403509 8:1 9:1 10:-0.850746 11:1 13:-0.88 14:-1 176 | -1 1:1 2:-0.353383 3:-0.773929 5:1 6:0.75 7:-0.736842 8:1 9:-1 10:-1 11:1 13:-0.32 14:-1 177 | -1 1:-1 2:0.295639 3:-0.696429 4:-1 5:-1 6:-1 7:-0.649123 8:-1 9:-1 10:-1 11:1 13:-1 14:-0.99992 178 | -1 1:-1 2:0.190376 3:-0.988214 5:-1 6:-1 7:-1 8:-1 9:-1 10:-1 11:1 12:-1 13:-0.938 14:-0.99946 179 | +1 1:1 2:-0.175338 3:-0.711429 5:0.846154 6:0.75 7:-0.508772 8:1 9:1 10:-0.761194 11:-1 13:-0.68 14:-1 180 | +1 1:1 2:-0.145263 3:-0.64 5:0.538462 6:0.75 7:-0.105263 8:1 9:-1 10:-1 11:1 13:-0.908 14:-1 181 | -1 1:1 2:-0.175338 3:-0.910714 4:-1 5:0.230769 6:-0.25 7:-0.982456 8:-1 9:-1 10:-1 11:-1 13:-1 14:-0.9961 182 | -1 1:-1 2:-0.398496 3:-0.946429 5:-0.538462 7:-0.929825 8:1 9:1 10:-0.910448 11:1 13:-0.788 14:-1 183 | +1 1:1 2:-0.641504 3:-0.107143 5:0.846154 6:-0.25 7:-0.915088 8:1 9:1 10:1 11:1 13:-0.86 14:-0.99484 184 | +1 1:1 2:-0.681805 3:-0.526786 4:-1 5:-0.846154 6:-0.25 7:-0.614035 8:1 9:-1 10:-1 11:1 12:-1 13:-0.9 14:-1 185 | +1 1:1 2:-0.71188 3:-0.169643 4:-1 5:0.230769 6:-0.25 7:-0.941404 8:1 9:-1 10:-1 11:1 13:-0.84 14:-0.994 186 | -1 1:1 2:-0.491128 3:-0.821429 5:0.846154 6:0.75 7:-0.842105 8:-1 9:-1 10:-1 11:1 12:-1 13:-0.66 14:-1 187 | -1 1:1 2:-0.295639 3:-0.714286 5:0.0769231 7:-0.649123 8:1 9:-1 10:-1 11:1 12:-1 13:-0.72 14:-1 -------------------------------------------------------------------------------- /svm.c: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | PHP Version 5 / svm | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 2010 Ian Barber | 6 | +----------------------------------------------------------------------+ 7 | | This source file is subject to version 3.0 of the PHP license, | 8 | | that is bundled with this package in the file LICENSE, and is | 9 | | available through the world-wide-web at the following url: | 10 | | http://www.php.net/license/3_0.txt. | 11 | | If you did not receive a copy of the PHP license and are unable to | 12 | | obtain it through the world-wide-web, please send a note to | 13 | | license@php.net so we can mail you a copy immediately. | 14 | +----------------------------------------------------------------------+ 15 | | Authors: Ian Barber | 16 | +----------------------------------------------------------------------+ 17 | */ 18 | 19 | #include "php_svm.h" 20 | #include "php_ini.h" /* needed for 5.2 */ 21 | #include "Zend/zend_exceptions.h" 22 | #include "ext/standard/info.h" 23 | 24 | zend_class_entry *php_svm_sc_entry; 25 | zend_class_entry *php_svm_model_sc_entry; 26 | zend_class_entry *php_svm_exception_sc_entry; 27 | 28 | static zend_object_handlers svm_object_handlers; 29 | static zend_object_handlers svm_model_object_handlers; 30 | 31 | #define SVM_MAX_LINE_SIZE 4096 32 | #define SVM_THROW(message, code) \ 33 | zend_throw_exception(php_svm_exception_sc_entry, message, (long)code TSRMLS_CC); \ 34 | return; 35 | 36 | #define SVM_THROW_LAST_ERROR(fallback, code) \ 37 | zend_throw_exception(php_svm_exception_sc_entry, (strlen(intern->last_error) ? intern->last_error : fallback), (long)code TSRMLS_CC); \ 38 | memset(intern->last_error, 0, 512); \ 39 | return; 40 | 41 | ZEND_DECLARE_MODULE_GLOBALS(svm); 42 | 43 | #define SVM_SET_ERROR_MSG(intern, ...) snprintf(intern->last_error, 512, __VA_ARGS__); 44 | 45 | typedef enum SvmLongAttribute { 46 | SvmLongAttributeMin = 100, 47 | phpsvm_svm_type, 48 | phpsvm_kernel_type, 49 | phpsvm_degree, 50 | phpsvm_shrinking, 51 | phpsvm_probability, 52 | SvmLongAttributeMax /* Always add before this */ 53 | } SvmLongAttribute; 54 | 55 | typedef enum SvmDoubleAttribute { 56 | SvmDoubleAttributeMin = 200, 57 | phpsvm_gamma, 58 | phpsvm_nu, 59 | phpsvm_eps, 60 | phpsvm_p, 61 | phpsvm_coef0, 62 | phpsvm_C, 63 | phpsvm_cache_size, 64 | phpsvm_weight, 65 | SvmDoubleAttributeMax /* Always add before this */ 66 | } SvmDoubleAttribute; 67 | 68 | /* ---- START HELPER FUNCS ---- */ 69 | 70 | void print_null(const char *s) {} 71 | 72 | static zend_bool php_svm_set_double_attribute(php_svm_object *intern, SvmDoubleAttribute name, double value) 73 | { 74 | if (name >= SvmDoubleAttributeMax) { 75 | return 0; 76 | } 77 | 78 | switch (name) { 79 | case phpsvm_gamma: 80 | intern->param.gamma = value; 81 | break; 82 | case phpsvm_nu: 83 | intern->param.nu = value; 84 | break; 85 | case phpsvm_eps: 86 | intern->param.eps = value; 87 | break; 88 | case phpsvm_cache_size: 89 | intern->param.cache_size = value; 90 | break; 91 | case phpsvm_p: 92 | intern->param.p = value; 93 | break; 94 | case phpsvm_coef0: 95 | intern->param.coef0 = value; 96 | break; 97 | case phpsvm_C: 98 | intern->param.C = value; 99 | break; 100 | case phpsvm_weight: 101 | /* Pointer */ 102 | intern->param.weight = &value; 103 | break; 104 | default: 105 | return 0; 106 | } 107 | 108 | return 1; 109 | } 110 | 111 | static zend_bool php_svm_set_long_attribute(php_svm_object *intern, SvmLongAttribute name, long value) 112 | { 113 | if (name >= SvmLongAttributeMax) { 114 | return 0; 115 | } 116 | 117 | switch (name) { 118 | case phpsvm_svm_type: 119 | if( value != C_SVC && 120 | value != NU_SVC && 121 | value != ONE_CLASS && 122 | value != EPSILON_SVR && 123 | value != NU_SVR ) { 124 | return 0; 125 | } 126 | intern->param.svm_type = (int)value; 127 | break; 128 | case phpsvm_kernel_type: 129 | if( value != LINEAR && 130 | value != POLY && 131 | value != RBF && 132 | value != SIGMOID && 133 | value != PRECOMPUTED ) { 134 | return 0; 135 | } 136 | intern->param.kernel_type = (int)value; 137 | break; 138 | case phpsvm_degree: 139 | intern->param.degree = (int)value; 140 | break; 141 | case phpsvm_shrinking: 142 | intern->param.shrinking = value; 143 | break; 144 | case phpsvm_probability: 145 | intern->param.probability = value; 146 | break; 147 | default: 148 | return 0; 149 | } 150 | 151 | return 1; 152 | } 153 | 154 | /** {{{ zend_bool php_svm_stream_to_array(php_svm_object *intern, php_stream *stream, zval *retval TSRMLS_DC) 155 | Take a stream containing lines of SVMLight format data and convert them into a PHP array for use by the training 156 | function. 157 | */ 158 | static zend_bool php_svm_stream_to_array(php_svm_object *intern, php_stream *stream, zval *retval TSRMLS_DC) 159 | { 160 | while (!php_stream_eof(stream)) { 161 | char buf[SVM_MAX_LINE_SIZE]; 162 | size_t retlen = 0; 163 | int line = 1; 164 | 165 | /* Read line by line */ 166 | if (php_stream_get_line(stream, buf, SVM_MAX_LINE_SIZE, &retlen)) { 167 | 168 | zval *line_array, *pz_label; 169 | char *label, *ptr, *l = NULL; 170 | 171 | ptr = buf; 172 | label = php_strtok_r(ptr, " \t", &l); 173 | 174 | if (!label) { 175 | SVM_SET_ERROR_MSG(intern, "Incorrect data format on line %d", line); 176 | return 0; 177 | } 178 | 179 | /* The line array */ 180 | MAKE_STD_ZVAL(line_array); 181 | array_init(line_array); 182 | 183 | /* The label */ 184 | MAKE_STD_ZVAL(pz_label); 185 | ZVAL_STRING(pz_label, label, 1); 186 | convert_to_double(pz_label); 187 | 188 | /* Label is the first item in the line array */ 189 | add_next_index_zval(line_array, pz_label); 190 | 191 | /* Read rest of the values on the line */ 192 | while (1) { 193 | char *idx, *value; 194 | zval *pz_idx, *pz_value; 195 | 196 | /* idx:value format */ 197 | idx = php_strtok_r(NULL, ":", &l); 198 | value = php_strtok_r(NULL, " \t", &l); 199 | 200 | if (!value) 201 | break; 202 | 203 | /* Make zvals and convert to correct types */ 204 | MAKE_STD_ZVAL(pz_idx); 205 | ZVAL_STRING(pz_idx, idx, 1); 206 | convert_to_long(pz_idx); 207 | 208 | MAKE_STD_ZVAL(pz_value); 209 | ZVAL_STRING(pz_value, value, 1); 210 | convert_to_double(pz_value); 211 | 212 | add_index_zval(line_array, Z_LVAL_P(pz_idx), pz_value); 213 | zval_dtor(pz_idx); 214 | FREE_ZVAL(pz_idx); 215 | } 216 | add_next_index_zval(retval, line_array); 217 | line++; 218 | } 219 | } 220 | return 1; 221 | } 222 | /* }}} */ 223 | 224 | 225 | /* {{{ int _php_count_values(zval *array); 226 | For a an array of arrays, count the number of items in all subarrays. 227 | */ 228 | static int _php_count_values(zval *array) 229 | { 230 | zval **ppzval; 231 | int values = 0; 232 | 233 | for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(array)); 234 | zend_hash_get_current_data(Z_ARRVAL_P(array), (void **) &ppzval) == SUCCESS; 235 | zend_hash_move_forward(Z_ARRVAL_P(array))) { 236 | 237 | if (Z_TYPE_PP(ppzval) == IS_ARRAY) 238 | values += zend_hash_num_elements(Z_ARRVAL_PP(ppzval)); 239 | } 240 | return values; 241 | } 242 | /* }}} */ 243 | 244 | /* {{{ static void php_svm_free_problem(struct svm_problem *problem) { 245 | Free the generated problem. 246 | */ 247 | static void php_svm_free_problem(struct svm_problem *problem) { 248 | if (problem->x) 249 | efree(problem->x); 250 | 251 | if (problem->y) 252 | efree(problem->y); 253 | 254 | if (problem) 255 | efree(problem); 256 | } 257 | /* }}} */ 258 | 259 | /* {{{ static zend_bool php_svm_read_array(php_svm_object *intern, php_svm_model_object *intern_model, zval *array TSRMLS_DC) 260 | Take a PHP array, and prepare libSVM problem data for training with. 261 | */ 262 | static struct svm_problem* php_svm_read_array(php_svm_object *intern, php_svm_model_object *intern_model, zval *array TSRMLS_DC) 263 | { 264 | zval **ppzval; 265 | 266 | char *err_msg = NULL; 267 | char *key; 268 | char *endptr; 269 | int i, j = 0, num_labels, elements, max_index = 0, inst_max_index = 0, key_len; 270 | long index; 271 | struct svm_problem *problem; 272 | HashPosition pointer; 273 | 274 | /* If reading multiple times make sure that we don't leak */ 275 | if (intern_model->x_space) { 276 | efree(intern_model->x_space); 277 | intern_model->x_space = NULL; 278 | } 279 | 280 | if (intern_model->model) { 281 | svm_destroy_model(intern_model->model); 282 | intern_model->model = NULL; 283 | } 284 | 285 | /* Allocate the problem */ 286 | problem = emalloc(sizeof(struct svm_problem)); 287 | 288 | /* x and y */ 289 | num_labels = zend_hash_num_elements(HASH_OF(array)); 290 | 291 | /* Allocate space for the labels */ 292 | problem->y = emalloc(num_labels * sizeof(double)); 293 | 294 | /* allocate space for x */ 295 | problem->x = emalloc(num_labels * sizeof(struct svm_node *)); 296 | 297 | /* total number of elements */ 298 | elements = _php_count_values(array); 299 | 300 | /* Allocate space: because the original array contains labels the alloc 301 | should match as we add additional -1 node in the loop */ 302 | intern_model->x_space = emalloc(elements * sizeof(struct svm_node)); 303 | 304 | /* How many labels */ 305 | problem->l = num_labels; 306 | 307 | /* Fill the problem */ 308 | for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(array)), i = 0; 309 | zend_hash_get_current_data(Z_ARRVAL_P(array), (void **) &ppzval) == SUCCESS; 310 | zend_hash_move_forward(Z_ARRVAL_P(array)), i++) { 311 | 312 | zval **ppz_label; 313 | 314 | if (Z_TYPE_PP(ppzval) != IS_ARRAY) { 315 | err_msg = "Data format error"; 316 | goto return_error; 317 | } 318 | 319 | if (zend_hash_num_elements(Z_ARRVAL_PP(ppzval)) < 2) { 320 | err_msg = "Wrong amount of nodes in the sub-array"; 321 | goto return_error; 322 | } 323 | 324 | problem->x[i] = &(intern_model->x_space[j]); 325 | 326 | zend_hash_internal_pointer_reset(Z_ARRVAL_PP(ppzval)); 327 | 328 | if ((zend_hash_get_current_data(Z_ARRVAL_PP(ppzval), (void **) &ppz_label) == SUCCESS)) { 329 | 330 | if (Z_TYPE_PP(ppz_label) != IS_DOUBLE) { 331 | convert_to_double(*ppz_label); 332 | } 333 | problem->y[i] = Z_DVAL_PP(ppz_label); 334 | } else { 335 | err_msg = "The sub-array contains only the label. Missing index-value pairs"; 336 | goto return_error; 337 | } 338 | 339 | while (1) { 340 | zval **ppz_value; 341 | 342 | if ((zend_hash_move_forward(Z_ARRVAL_PP(ppzval)) == SUCCESS) && 343 | (zend_hash_get_current_data(Z_ARRVAL_PP(ppzval), (void **) &ppz_value) == SUCCESS)) { 344 | 345 | if (zend_hash_get_current_key(Z_ARRVAL_PP(ppzval), &key, &index, 0) == HASH_KEY_IS_STRING) { 346 | intern_model->x_space[j].index = (int) strtol(key, &endptr, 10); 347 | } else { 348 | intern_model->x_space[j].index = (int) index; 349 | } 350 | 351 | if (Z_TYPE_PP(ppz_value) != IS_DOUBLE) { 352 | convert_to_double(*ppz_value); 353 | } 354 | intern_model->x_space[j].value = Z_DVAL_PP(ppz_value); 355 | 356 | inst_max_index = intern_model->x_space[j].index; 357 | j++; 358 | } else { 359 | break; 360 | } 361 | } 362 | 363 | intern_model->x_space[j++].index = -1; 364 | 365 | if (inst_max_index > max_index) { 366 | max_index = inst_max_index; 367 | } 368 | } 369 | 370 | if (intern->param.gamma == 0 && max_index > 0) { 371 | intern->param.gamma = 1.0/max_index; 372 | } 373 | 374 | return problem; 375 | 376 | return_error: 377 | php_svm_free_problem(problem); 378 | if (err_msg) { 379 | SVM_SET_ERROR_MSG(intern, err_msg); 380 | } 381 | 382 | return NULL; 383 | } 384 | /* }}} */ 385 | 386 | /* {{{ static zend_bool php_svm_train(php_svm_object *intern, php_svm_model_object *intern_model, struct svm_problem *problem) 387 | Train based on a libsvm problem structure 388 | */ 389 | static zend_bool php_svm_train(php_svm_object *intern, php_svm_model_object *intern_model, struct svm_problem *problem) 390 | { 391 | char *err_msg = NULL; 392 | err_msg = svm_check_parameter(problem, &(intern->param)); 393 | if (err_msg) { 394 | SVM_SET_ERROR_MSG(intern, err_msg); 395 | return 0; 396 | } 397 | 398 | intern_model->model = svm_train(problem, &(intern->param)); 399 | 400 | /* Failure ? */ 401 | if (!intern_model->model) { 402 | SVM_SET_ERROR_MSG(intern, "Failed to train using the data"); 403 | return 0; 404 | } 405 | 406 | return 1; 407 | } 408 | /* }}} */ 409 | 410 | /* {{{ static zval* php_svm_get_data_from_param(php_svm_object *intern, zval *zparam) 411 | Take an incoming parameter and convert it into a PHP array of svmlight style data. 412 | */ 413 | static zval* php_svm_get_data_from_param(php_svm_object *intern, zval *zparam TSRMLS_DC) 414 | { 415 | zval *data, *return_value; 416 | zend_bool our_stream = 0; 417 | zend_bool need_read = 1; 418 | php_stream *stream = NULL; 419 | 420 | switch (Z_TYPE_P(zparam)) { 421 | case IS_STRING: 422 | stream = php_stream_open_wrapper(Z_STRVAL_P(zparam), "r", ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL); 423 | our_stream = 1; 424 | break; 425 | 426 | case IS_RESOURCE: 427 | php_stream_from_zval(stream, &zparam); 428 | our_stream = 0; 429 | break; 430 | 431 | case IS_ARRAY: 432 | our_stream = 0; 433 | need_read = 0; 434 | break; 435 | 436 | default: 437 | SVM_SET_ERROR_MSG(intern, "Incorrect parameter type, expecting string, stream or an array"); 438 | return 0; 439 | break; 440 | } 441 | 442 | /* If we got stream then read it in */ 443 | if (need_read) { 444 | if (!stream) { 445 | SVM_SET_ERROR_MSG(intern, "Failed to open the data file"); 446 | return 0; 447 | } 448 | 449 | MAKE_STD_ZVAL(data); 450 | array_init(data); 451 | 452 | if (!php_svm_stream_to_array(intern, stream, data TSRMLS_CC)) { 453 | zval_dtor(data); 454 | FREE_ZVAL(data); 455 | if (our_stream) { 456 | php_stream_close(stream); 457 | } 458 | SVM_SET_ERROR_MSG(intern, "Failed to read the data"); 459 | return 0; 460 | } 461 | } else { 462 | data = zparam; 463 | } 464 | 465 | if (our_stream) { 466 | php_stream_close(stream); 467 | } 468 | 469 | return data; 470 | } 471 | /* }}} */ 472 | 473 | /* ---- END HELPER FUNCS ---- */ 474 | 475 | 476 | 477 | /* ---- START SVM ---- */ 478 | 479 | /* {{{ SVM SVM::__construct(); 480 | The constructor 481 | */ 482 | PHP_METHOD(svm, __construct) 483 | { 484 | php_svm_object *intern; 485 | 486 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { 487 | return; 488 | } 489 | 490 | intern = (php_svm_object *)zend_object_store_get_object(getThis() TSRMLS_CC); 491 | 492 | /* Setup the default parameters to match those in libsvm's svm_train */ 493 | php_svm_set_long_attribute(intern, phpsvm_svm_type, C_SVC); 494 | php_svm_set_long_attribute(intern, phpsvm_kernel_type, RBF); 495 | php_svm_set_long_attribute(intern, phpsvm_degree, 3); 496 | php_svm_set_double_attribute(intern, phpsvm_gamma, 0); 497 | php_svm_set_double_attribute(intern, phpsvm_coef0, 0); 498 | php_svm_set_double_attribute(intern, phpsvm_nu, 0.5); 499 | php_svm_set_double_attribute(intern, phpsvm_cache_size, 100.0); 500 | php_svm_set_double_attribute(intern, phpsvm_C, 1); 501 | php_svm_set_double_attribute(intern, phpsvm_eps, 1e-3); 502 | php_svm_set_double_attribute(intern, phpsvm_p, 0.1); 503 | php_svm_set_long_attribute(intern, phpsvm_shrinking, 1); 504 | php_svm_set_long_attribute(intern, phpsvm_probability, 0); 505 | 506 | return; 507 | } 508 | /* }}} */ 509 | 510 | /* {{{ array SVM::getOptions(); 511 | Get training parameters, in an array. 512 | */ 513 | PHP_METHOD(svm, getOptions) 514 | { 515 | php_svm_object *intern; 516 | intern = zend_object_store_get_object(getThis() TSRMLS_CC); 517 | 518 | array_init(return_value); 519 | 520 | add_index_long(return_value, phpsvm_svm_type, intern->param.svm_type); 521 | add_index_long(return_value, phpsvm_kernel_type, intern->param.kernel_type); 522 | add_index_long(return_value, phpsvm_degree, intern->param.degree); 523 | add_index_long(return_value, phpsvm_coef0, intern->param.shrinking); 524 | add_index_long(return_value, phpsvm_probability, intern->param.probability); 525 | 526 | add_index_long(return_value, phpsvm_gamma, intern->param.gamma); 527 | add_index_long(return_value, phpsvm_coef0, intern->param.coef0); 528 | add_index_long(return_value, phpsvm_nu, intern->param.nu); 529 | add_index_long(return_value, phpsvm_cache_size, intern->param.cache_size); 530 | add_index_long(return_value, phpsvm_C, intern->param.C); 531 | add_index_long(return_value, phpsvm_eps, intern->param.eps); 532 | add_index_long(return_value, phpsvm_p, intern->param.p); 533 | } 534 | /* }}} */ 535 | 536 | 537 | /* {{{ int SVM::setOptopms(array params); 538 | Takes an array of parameters and sets the training options to match them. 539 | Only used by the training functions, will not modify an existing model. 540 | */ 541 | PHP_METHOD(svm, setOptions) 542 | { 543 | HashTable *params_ht; 544 | php_svm_object *intern; 545 | zval *params, **ppzval; 546 | char *string_key = NULL; 547 | ulong num_key; 548 | 549 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", ¶ms) == FAILURE) { 550 | RETURN_FALSE; 551 | } 552 | 553 | params_ht = HASH_OF(params); 554 | 555 | if (zend_hash_num_elements(params_ht) == 0) { 556 | return; 557 | } 558 | 559 | intern = (php_svm_object *)zend_object_store_get_object(getThis() TSRMLS_CC); 560 | 561 | for (zend_hash_internal_pointer_reset(params_ht); 562 | zend_hash_get_current_data(params_ht, (void **) &ppzval) == SUCCESS; 563 | zend_hash_move_forward(params_ht)) { 564 | 565 | zval tmp_zval, *tmp_pzval; 566 | 567 | if (zend_hash_get_current_key(params_ht, &string_key, &num_key, 1) != HASH_KEY_IS_LONG) { 568 | continue; /* Ignore the arg (TODO: throw exception?) */ 569 | } 570 | 571 | /* Make sure we don't modify the original array */ 572 | tmp_zval = **ppzval; 573 | zval_copy_ctor(&tmp_zval); 574 | tmp_pzval = &tmp_zval; 575 | 576 | /* Long attribute */ 577 | if (num_key > SvmLongAttributeMin && num_key < SvmLongAttributeMax) { 578 | 579 | if (Z_TYPE_P(tmp_pzval) != IS_LONG) { 580 | convert_to_long(tmp_pzval); 581 | } 582 | 583 | if (!php_svm_set_long_attribute(intern, num_key, Z_LVAL_P(tmp_pzval))) { 584 | SVM_THROW("Failed to set the attribute", 999); 585 | } 586 | 587 | /* Double attribute */ 588 | } else if (num_key > SvmDoubleAttributeMin && num_key < SvmDoubleAttributeMax) { 589 | 590 | if (Z_TYPE_P(tmp_pzval) != IS_DOUBLE) { 591 | convert_to_double(tmp_pzval); 592 | } 593 | 594 | if (!php_svm_set_double_attribute(intern, num_key, Z_DVAL_P(tmp_pzval))) { 595 | SVM_THROW("Failed to set the attribute", 999); 596 | } 597 | 598 | } else { 599 | continue; /* Ignore the arg (TODO: throw exception?) */ 600 | } 601 | 602 | tmp_pzval = NULL; 603 | } 604 | 605 | RETURN_TRUE; 606 | } 607 | /* }}} */ 608 | 609 | /* {{{ double SVM::crossvalidate(mixed string|resource|array, long folds); 610 | Cross validate a the SVM parameters on the training data for tuning parameters. Will attempt to train then classify 611 | on different segments of the training data (the total number of segments is the folds parameter). The training data 612 | can be supplied as with the train function. For SVM classification, this will we return the correct percentage, 613 | for regression the mean squared error. 614 | @throws SVMException if the data format is incorrect 615 | */ 616 | PHP_METHOD(svm, crossvalidate) 617 | { 618 | int i; 619 | int total_correct = 0; 620 | long nrfolds; 621 | double total_error = 0; 622 | double sumv = 0, sumy = 0, sumvv = 0, sumyy = 0, sumvy = 0; 623 | struct svm_problem *problem; 624 | double returnval = 0.0; 625 | double *target; 626 | php_svm_object *intern; 627 | php_svm_model_object *intern_return; 628 | zval *zparam, *data, *zcount, *tempobj; 629 | 630 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zl", &zparam, &nrfolds) == FAILURE) { 631 | return; 632 | } 633 | 634 | intern = (php_svm_object *)zend_object_store_get_object(getThis() TSRMLS_CC); 635 | 636 | ALLOC_INIT_ZVAL(tempobj); 637 | object_init_ex(tempobj, php_svm_model_sc_entry); 638 | intern_return = (php_svm_model_object *)zend_object_store_get_object(tempobj TSRMLS_CC); 639 | 640 | data = php_svm_get_data_from_param(intern, zparam TSRMLS_CC); 641 | if(!data) { 642 | SVM_THROW_LAST_ERROR("Could not load data", 234); 643 | } 644 | problem = php_svm_read_array(intern, intern_return, data TSRMLS_CC); 645 | if(!problem) { 646 | SVM_THROW_LAST_ERROR("Cross validation failed", 1001); 647 | } 648 | 649 | target = emalloc(problem->l * sizeof(double)); 650 | svm_cross_validation(problem, &(intern->param), nrfolds, target); 651 | if(intern->param.svm_type == EPSILON_SVR || intern->param.svm_type == NU_SVR) { 652 | for(i=0;il;i++) { 653 | double y = problem->y[i]; 654 | double v = target[i]; 655 | total_error += (v-y)*(v-y); 656 | sumv += v; 657 | sumy += y; 658 | sumvv += v*v; 659 | sumyy += y*y; 660 | sumvy += v*y; 661 | } 662 | returnval = (total_error/problem->l); // return total_error divded by number of examples 663 | } else { 664 | for(i=0; il; i++) { 665 | if(target[i] == problem->y[i]) { 666 | ++total_correct; 667 | } 668 | } 669 | returnval = 1.0*total_correct/problem->l; 670 | } 671 | 672 | if (data != zparam) { 673 | zval_dtor(data); 674 | FREE_ZVAL(data); 675 | } 676 | zval_dtor(tempobj); 677 | FREE_ZVAL(tempobj); 678 | efree(target); 679 | php_svm_free_problem(problem); 680 | 681 | RETURN_DOUBLE(returnval); 682 | } 683 | /* }}} */ 684 | 685 | /* {{{ SVMModel SVM::train(mixed string|resource|array, [array classWeights]); 686 | Train a SVM based on the SVMLight format data either in a file, an array, or in a previously opened stream. 687 | @throws SVMException if the data format is incorrect. Can optionally accept a set of weights that will 688 | be used to multiply C. Only useful for C_SVC kernels. These should be in the form array(class (int) => weight (float)) 689 | */ 690 | PHP_METHOD(svm, train) 691 | { 692 | php_svm_object *intern; 693 | php_svm_model_object *intern_return; 694 | struct svm_problem *problem; 695 | zval *data, *zparam, *retval, *weights, **ppzval; 696 | HashTable *weights_ht; 697 | int i; 698 | char *key; 699 | long index; 700 | 701 | zend_bool status = 0; 702 | weights = 0; 703 | 704 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|a!", &zparam, &weights) == FAILURE) { 705 | return; 706 | } 707 | 708 | intern = (php_svm_object *)zend_object_store_get_object(getThis() TSRMLS_CC); 709 | if(weights && intern->param.svm_type != C_SVC) { 710 | SVM_THROW("Weights can only be supplied for C_SVC training", 424); 711 | } 712 | 713 | data = php_svm_get_data_from_param(intern, zparam TSRMLS_CC); 714 | if(!data) { 715 | SVM_THROW_LAST_ERROR("Could not load data", 234); 716 | } 717 | 718 | if(weights) { 719 | weights_ht = Z_ARRVAL_P(weights); 720 | if(zend_hash_num_elements(weights_ht) > 0) { 721 | intern->param.nr_weight = zend_hash_num_elements(weights_ht); 722 | intern->param.weight_label = emalloc(intern->param.nr_weight * sizeof(int)); 723 | intern->param.weight = emalloc(intern->param.nr_weight * sizeof(double)); 724 | 725 | for (zend_hash_internal_pointer_reset(weights_ht), i = 0; 726 | zend_hash_get_current_data(weights_ht, (void **) &ppzval) == SUCCESS; 727 | zend_hash_move_forward(weights_ht), i++) { 728 | 729 | zval tmp_zval, *tmp_pzval; 730 | 731 | if (zend_hash_get_current_key(weights_ht, &key, &index, 0) == HASH_KEY_IS_LONG) { 732 | intern->param.weight_label[i] = (int)index; 733 | 734 | /* Make sure we don't modify the original array */ 735 | tmp_zval = **ppzval; 736 | zval_copy_ctor(&tmp_zval); 737 | tmp_pzval = &tmp_zval; 738 | convert_to_double(tmp_pzval); 739 | intern->param.weight[i] = Z_DVAL_P(tmp_pzval); 740 | tmp_pzval = NULL; 741 | } 742 | } 743 | } 744 | } 745 | 746 | /* Return an object */ 747 | object_init_ex(return_value, php_svm_model_sc_entry); 748 | intern_return = (php_svm_model_object *)zend_object_store_get_object(return_value TSRMLS_CC); 749 | 750 | problem = php_svm_read_array(intern, intern_return, data TSRMLS_CC); 751 | if(problem != NULL) { 752 | if (php_svm_train(intern, intern_return, problem)) { 753 | status = 1; 754 | } 755 | php_svm_free_problem(problem); 756 | } 757 | 758 | if(weights) { 759 | efree(intern->param.weight_label); 760 | efree(intern->param.weight); 761 | } 762 | 763 | if (data != zparam) { 764 | zval_dtor(data); 765 | FREE_ZVAL(data); 766 | } 767 | 768 | if (!status) { 769 | SVM_THROW_LAST_ERROR("Training failed", 1000); 770 | } 771 | return; 772 | } 773 | /* }}} */ 774 | 775 | /* ---- END SVM ---- */ 776 | 777 | /* ---- START SVMMODEL ---- */ 778 | 779 | /** {{{ SvmModel::__construct([string filename]) 780 | Constructs an svm model 781 | */ 782 | PHP_METHOD(svmmodel, __construct) 783 | { 784 | php_svm_model_object *intern; 785 | char *filename = NULL; 786 | int filename_len; 787 | 788 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!", &filename, &filename_len) == FAILURE) { 789 | return; 790 | } 791 | 792 | if (!filename) 793 | return; 794 | 795 | intern = (php_svm_model_object *)zend_object_store_get_object(getThis() TSRMLS_CC); 796 | intern->model = svm_load_model(filename); 797 | 798 | if (!intern->model) { 799 | SVM_THROW("Failed to load the model", 1233); 800 | } 801 | 802 | return; 803 | } 804 | /* }}} */ 805 | 806 | /** {{{ SvmModel::load(string filename) 807 | Loads the svm model from a file 808 | */ 809 | PHP_METHOD(svmmodel, load) 810 | { 811 | php_svm_model_object *intern; 812 | char *filename = NULL; 813 | int filename_len; 814 | 815 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) { 816 | return; 817 | } 818 | 819 | intern = (php_svm_model_object *)zend_object_store_get_object(getThis() TSRMLS_CC); 820 | intern->model = svm_load_model(filename); 821 | 822 | if (!intern->model) { 823 | SVM_THROW("Failed to load the model", 1233); 824 | } 825 | 826 | RETURN_TRUE; 827 | } 828 | /* }}} */ 829 | 830 | /** {{{ SvmModel::save(string filename) 831 | Saves the svm model to a file 832 | */ 833 | PHP_METHOD(svmmodel, save) 834 | { 835 | php_svm_model_object *intern; 836 | char *filename; 837 | int filename_len; 838 | 839 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) { 840 | return; 841 | } 842 | 843 | intern = (php_svm_model_object *)zend_object_store_get_object(getThis() TSRMLS_CC); 844 | 845 | if (!intern->model) { 846 | SVM_THROW("The object does not contain a model", 2321); 847 | } 848 | 849 | if (svm_save_model(filename, intern->model) != 0) { 850 | SVM_THROW("Failed to save the model", 121); 851 | } 852 | 853 | RETURN_TRUE; 854 | } 855 | /* }}} */ 856 | 857 | /** {{{ SvmModel::predict(array data) 858 | Predicts based on the model 859 | */ 860 | PHP_METHOD(svmmodel, predict) 861 | { 862 | php_svm_model_object *intern; 863 | double predict_label; 864 | struct svm_node *x; 865 | int max_nr_attr = 64; 866 | zval *arr, **data; 867 | HashTable *arr_hash; 868 | HashPosition pointer; 869 | int array_count, i; 870 | char *endptr; 871 | 872 | /* we want an array of data to be passed in */ 873 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &arr) == FAILURE) { 874 | return; 875 | } 876 | 877 | arr_hash = Z_ARRVAL_P(arr); 878 | array_count = zend_hash_num_elements(arr_hash); 879 | intern = (php_svm_model_object *)zend_object_store_get_object(getThis() TSRMLS_CC); 880 | if(!intern->model) { 881 | SVM_THROW("No model available to classify with", 106); 882 | } 883 | 884 | /* need 1 extra to indicate the end */ 885 | x = emalloc((array_count + 1) *sizeof(struct svm_node)); 886 | 887 | i = 0; 888 | zval temp; 889 | char *key; 890 | uint key_len; 891 | ulong index; 892 | 893 | /* Loop over the array in the argument and convert into svm_nodes for the prediction */ 894 | for(zend_hash_internal_pointer_reset_ex(arr_hash, &pointer); 895 | zend_hash_get_current_data_ex(arr_hash, (void**) &data, &pointer) == SUCCESS; 896 | zend_hash_move_forward_ex(arr_hash, &pointer)) 897 | { 898 | if (zend_hash_get_current_key_ex(arr_hash, &key, &key_len, &index, 0, &pointer) == HASH_KEY_IS_STRING) { 899 | x[i].index = (int) strtol(key, &endptr, 10); 900 | } else { 901 | x[i].index = (int) index; 902 | } 903 | temp = **data; 904 | zval_copy_ctor(&temp); 905 | convert_to_double(&temp); 906 | x[i].value = Z_DVAL(temp); 907 | zval_dtor(&temp); 908 | i++; 909 | } 910 | /* needed so the predictor knows when to end */ 911 | x[i].index = -1; 912 | 913 | predict_label = svm_predict(intern->model, x); 914 | efree(x); 915 | 916 | RETURN_DOUBLE(predict_label); 917 | } 918 | /* }}} */ 919 | 920 | /* ---- END SVMMODEL ---- */ 921 | 922 | static void php_svm_init_globals(zend_svm_globals *svm_globals) 923 | { 924 | /* No globals */ 925 | } 926 | 927 | static void php_svm_object_free_storage(void *object TSRMLS_DC) 928 | { 929 | php_svm_object *intern = (php_svm_object *)object; 930 | 931 | if (!intern) { 932 | return; 933 | } 934 | 935 | zend_object_std_dtor(&intern->zo TSRMLS_CC); 936 | efree(intern); 937 | } 938 | 939 | static zend_object_value php_svm_object_new_ex(zend_class_entry *class_type, php_svm_object **ptr TSRMLS_DC) 940 | { 941 | zval *tmp; 942 | zend_object_value retval; 943 | php_svm_object *intern; 944 | 945 | /* Allocate memory for the internal structure */ 946 | intern = (php_svm_object *) emalloc(sizeof(php_svm_object)); 947 | memset(&intern->zo, 0, sizeof(zend_object)); 948 | 949 | if (ptr) { 950 | *ptr = intern; 951 | } 952 | 953 | /* Null model by default */ 954 | memset(intern->last_error, 0, 512); 955 | 956 | zend_object_std_init(&intern->zo, class_type TSRMLS_CC); 957 | zend_hash_copy(intern->zo.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref,(void *) &tmp, sizeof(zval *)); 958 | 959 | retval.handle = zend_objects_store_put(intern, NULL, (zend_objects_free_object_storage_t) php_svm_object_free_storage, NULL TSRMLS_CC); 960 | retval.handlers = (zend_object_handlers *) &svm_object_handlers; 961 | return retval; 962 | } 963 | 964 | static zend_object_value php_svm_object_new(zend_class_entry *class_type TSRMLS_DC) 965 | { 966 | return php_svm_object_new_ex(class_type, NULL TSRMLS_CC); 967 | } 968 | 969 | static void php_svm_model_object_free_storage(void *object TSRMLS_DC) 970 | { 971 | php_svm_model_object *intern = (php_svm_model_object *)object; 972 | 973 | if (!intern) { 974 | return; 975 | } 976 | 977 | if (intern->model) { 978 | svm_destroy_model(intern->model); 979 | intern->model = NULL; 980 | } 981 | 982 | if (intern->x_space) { 983 | efree(intern->x_space); 984 | intern->x_space = NULL; 985 | } 986 | 987 | zend_object_std_dtor(&intern->zo TSRMLS_CC); 988 | efree(intern); 989 | } 990 | 991 | static zend_object_value php_svm_model_object_new_ex(zend_class_entry *class_type, php_svm_model_object **ptr TSRMLS_DC) 992 | { 993 | zval *tmp; 994 | zend_object_value retval; 995 | php_svm_model_object *intern; 996 | 997 | /* Allocate memory for the internal structure */ 998 | intern = (php_svm_model_object *) emalloc(sizeof(php_svm_object)); 999 | memset(&intern->zo, 0, sizeof(zend_object)); 1000 | 1001 | if (ptr) { 1002 | *ptr = intern; 1003 | } 1004 | 1005 | /* Null model by default */ 1006 | intern->model = NULL; 1007 | intern->x_space = NULL; 1008 | 1009 | zend_object_std_init(&intern->zo, class_type TSRMLS_CC); 1010 | zend_hash_copy(intern->zo.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref,(void *) &tmp, sizeof(zval *)); 1011 | 1012 | retval.handle = zend_objects_store_put(intern, NULL, (zend_objects_free_object_storage_t) php_svm_model_object_free_storage, NULL TSRMLS_CC); 1013 | retval.handlers = (zend_object_handlers *) &svm_model_object_handlers; 1014 | return retval; 1015 | } 1016 | 1017 | static zend_object_value php_svm_model_object_new(zend_class_entry *class_type TSRMLS_DC) 1018 | { 1019 | return php_svm_model_object_new_ex(class_type, NULL TSRMLS_CC); 1020 | } 1021 | 1022 | ZEND_BEGIN_ARG_INFO_EX(svm_empty_args, 0, 0, 0) 1023 | ZEND_END_ARG_INFO() 1024 | 1025 | ZEND_BEGIN_ARG_INFO_EX(svm_train_args, 0, 0, 1) 1026 | ZEND_ARG_INFO(0, problem) 1027 | ZEND_ARG_INFO(0, weights) 1028 | ZEND_END_ARG_INFO() 1029 | 1030 | ZEND_BEGIN_ARG_INFO_EX(svm_crossvalidate_args, 0, 0, 2) 1031 | ZEND_ARG_INFO(0, problem) 1032 | ZEND_ARG_INFO(0, number_of_folds) 1033 | ZEND_END_ARG_INFO() 1034 | 1035 | ZEND_BEGIN_ARG_INFO_EX(svm_params_args, 0, 0, 1) 1036 | ZEND_ARG_INFO(0, params) 1037 | ZEND_END_ARG_INFO() 1038 | 1039 | static function_entry php_svm_class_methods[] = 1040 | { 1041 | PHP_ME(svm, __construct, svm_empty_args, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) 1042 | PHP_ME(svm, getOptions, svm_empty_args, ZEND_ACC_PUBLIC) 1043 | PHP_ME(svm, setOptions, svm_params_args, ZEND_ACC_PUBLIC) 1044 | PHP_ME(svm, train, svm_train_args, ZEND_ACC_PUBLIC) 1045 | PHP_ME(svm, crossvalidate, svm_crossvalidate_args, ZEND_ACC_PUBLIC) 1046 | { NULL, NULL, NULL } 1047 | }; 1048 | 1049 | ZEND_BEGIN_ARG_INFO_EX(svm_model_construct_args, 0, 0, 0) 1050 | ZEND_ARG_INFO(0, filename) 1051 | ZEND_END_ARG_INFO() 1052 | 1053 | ZEND_BEGIN_ARG_INFO_EX(svm_model_predict_args, 0, 0, 1) 1054 | ZEND_ARG_INFO(0, data) 1055 | ZEND_END_ARG_INFO() 1056 | 1057 | ZEND_BEGIN_ARG_INFO_EX(svm_model_file_args, 0, 0, 1) 1058 | ZEND_ARG_INFO(0, filename) 1059 | ZEND_END_ARG_INFO() 1060 | 1061 | static function_entry php_svm_model_class_methods[] = 1062 | { 1063 | PHP_ME(svmmodel, __construct, svm_model_construct_args, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) 1064 | PHP_ME(svmmodel, save, svm_model_file_args, ZEND_ACC_PUBLIC) 1065 | PHP_ME(svmmodel, load, svm_model_file_args, ZEND_ACC_PUBLIC) 1066 | PHP_ME(svmmodel, predict, svm_model_predict_args, ZEND_ACC_PUBLIC) 1067 | { NULL, NULL, NULL } 1068 | }; 1069 | 1070 | PHP_MINIT_FUNCTION(svm) 1071 | { 1072 | zend_class_entry ce; 1073 | ZEND_INIT_MODULE_GLOBALS(svm, php_svm_init_globals, NULL); 1074 | 1075 | memcpy(&svm_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); 1076 | memcpy(&svm_model_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); 1077 | 1078 | INIT_CLASS_ENTRY(ce, "svm", php_svm_class_methods); 1079 | ce.create_object = php_svm_object_new; 1080 | svm_object_handlers.clone_obj = NULL; 1081 | php_svm_sc_entry = zend_register_internal_class(&ce TSRMLS_CC); 1082 | 1083 | INIT_CLASS_ENTRY(ce, "svmmodel", php_svm_model_class_methods); 1084 | ce.create_object = php_svm_model_object_new; 1085 | svm_model_object_handlers.clone_obj = NULL; 1086 | php_svm_model_sc_entry = zend_register_internal_class(&ce TSRMLS_CC); 1087 | 1088 | INIT_CLASS_ENTRY(ce, "svmexception", NULL); 1089 | php_svm_exception_sc_entry = zend_register_internal_class_ex(&ce, zend_exception_get_default(TSRMLS_C), NULL TSRMLS_CC); 1090 | php_svm_exception_sc_entry->ce_flags |= ZEND_ACC_FINAL; 1091 | 1092 | /* Redirect the lib svm output */ 1093 | //extern void (*svm_print_string) (const char *); 1094 | //svm_print_string = &print_null; 1095 | svm_set_print_string_function(&print_null); 1096 | 1097 | #define SVM_REGISTER_CONST_LONG(const_name, value) \ 1098 | zend_declare_class_constant_long(php_svm_sc_entry, const_name, sizeof(const_name)-1, (long)value TSRMLS_CC); 1099 | 1100 | /* SVM types */ 1101 | SVM_REGISTER_CONST_LONG("C_SVC", C_SVC); 1102 | SVM_REGISTER_CONST_LONG("NU_SVC", NU_SVC); 1103 | SVM_REGISTER_CONST_LONG("ONE_CLASS", ONE_CLASS); 1104 | SVM_REGISTER_CONST_LONG("EPSILON_SVR", EPSILON_SVR); 1105 | SVM_REGISTER_CONST_LONG("NU_SVR", NU_SVR); 1106 | 1107 | /* Kernel types */ 1108 | SVM_REGISTER_CONST_LONG("KERNEL_LINEAR", LINEAR); 1109 | SVM_REGISTER_CONST_LONG("KERNEL_POLY", POLY); 1110 | SVM_REGISTER_CONST_LONG("KERNEL_RBF", RBF); 1111 | SVM_REGISTER_CONST_LONG("KERNEL_SIGMOID", SIGMOID); 1112 | SVM_REGISTER_CONST_LONG("KERNEL_PRECOMPUTED", PRECOMPUTED); 1113 | 1114 | /* Long options (for setOptions) */ 1115 | SVM_REGISTER_CONST_LONG("OPT_TYPE", phpsvm_svm_type); 1116 | SVM_REGISTER_CONST_LONG("OPT_KERNEL_TYPE", phpsvm_kernel_type); 1117 | SVM_REGISTER_CONST_LONG("OPT_DEGREE", phpsvm_degree); 1118 | SVM_REGISTER_CONST_LONG("OPT_SHRINKING", phpsvm_shrinking); 1119 | SVM_REGISTER_CONST_LONG("OPT_PROBABILITY", phpsvm_probability); 1120 | 1121 | /* Double options (for setOptions) */ 1122 | SVM_REGISTER_CONST_LONG("OPT_GAMMA", phpsvm_gamma); 1123 | SVM_REGISTER_CONST_LONG("OPT_NU", phpsvm_nu); 1124 | SVM_REGISTER_CONST_LONG("OPT_EPS", phpsvm_eps); 1125 | SVM_REGISTER_CONST_LONG("OPT_P", phpsvm_p); 1126 | SVM_REGISTER_CONST_LONG("OPT_COEF_ZERO", phpsvm_coef0); 1127 | SVM_REGISTER_CONST_LONG("OPT_C", phpsvm_C); 1128 | SVM_REGISTER_CONST_LONG("OPT_CACHE_SIZE", phpsvm_cache_size); 1129 | SVM_REGISTER_CONST_LONG("OPT_WEIGHT", phpsvm_weight); 1130 | 1131 | #undef SVM_REGISTER_CONST_LONG 1132 | 1133 | return SUCCESS; 1134 | } 1135 | 1136 | PHP_MSHUTDOWN_FUNCTION(svm) 1137 | { 1138 | UNREGISTER_INI_ENTRIES(); 1139 | return SUCCESS; 1140 | } 1141 | 1142 | PHP_MINFO_FUNCTION(svm) 1143 | { 1144 | php_info_print_table_start(); 1145 | php_info_print_table_header(2, "svm extension", "enabled"); 1146 | php_info_print_table_row(2, "svm extension version", PHP_SVM_EXTVER); 1147 | php_info_print_table_end(); 1148 | 1149 | DISPLAY_INI_ENTRIES(); 1150 | } 1151 | 1152 | /* No global functions */ 1153 | zend_function_entry svm_functions[] = { 1154 | {NULL, NULL, NULL} 1155 | }; 1156 | 1157 | zend_module_entry svm_module_entry = 1158 | { 1159 | STANDARD_MODULE_HEADER, 1160 | PHP_SVM_EXTNAME, 1161 | svm_functions, /* Functions */ 1162 | PHP_MINIT(svm), /* MINIT */ 1163 | PHP_MSHUTDOWN(svm), /* MSHUTDOWN */ 1164 | NULL, /* RINIT */ 1165 | NULL, /* RSHUTDOWN */ 1166 | PHP_MINFO(svm), /* MINFO */ 1167 | PHP_SVM_EXTVER, /* version */ 1168 | STANDARD_MODULE_PROPERTIES 1169 | }; 1170 | 1171 | 1172 | #ifdef COMPILE_DL_SVM 1173 | ZEND_GET_MODULE(svm) 1174 | #endif /* COMPILE_DL_SVM */ 1175 | --------------------------------------------------------------------------------