diff --git a/.gitignore b/.gitignore index 3ffb1da..5fb4f2b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /vendor/ .php_cs.cache /build +/tests/Performance/Data/*.csv diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b2d5f9e..68dd849 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,7 +8,7 @@ code base clean, unified and future proof. You should only open pull requests against the `master` branch. -## Unit-Tests +## Unit Tests Please try to add a test for your pull-request. You can run the unit-tests by calling: @@ -16,6 +16,22 @@ Please try to add a test for your pull-request. You can run the unit-tests by ca vendor/bin/phpunit ``` +## Performance Tests + +Before first run bootstrap script will download all necessary datasets from public repository `php-ai/php-ml-datasets`. + +Time performance tests: + +```bash +vendor/bin/phpbench run --report=time +``` + +Memory performance tests: + +```bash +vendor/bin/phpbench run --report=memory +``` + ## Travis GitHub automatically run your pull request through Travis CI. @@ -23,21 +39,21 @@ If you break the tests, I cannot merge your code, so please make sure that your ## Merge -Please allow me time to review your pull requests. I will give my best to review everything as fast as possible, but cannot always live up to my own expectations. +Please give me time to review your pull requests. I will give my best to review everything as fast as possible, but cannot always live up to my own expectations. ## Coding Standards & Static Analysis When contributing code to PHP-ML, you must follow its coding standards. To do that, just run: ```bash -vendor/bin/ecs check src tests --fix +composer fix-cs ``` [More about EasyCodingStandard](https://github.com/Symplify/EasyCodingStandard) Code has to also pass static analysis by [PHPStan](https://github.com/phpstan/phpstan): ```bash -vendor/bin/phpstan.phar analyse src tests --level max --configuration phpstan.neon +composer phpstan ``` diff --git a/README.md b/README.md index ddca60a..192195e 100644 --- a/README.md +++ b/README.md @@ -9,11 +9,9 @@ [![Coverage Status](https://coveralls.io/repos/github/php-ai/php-ml/badge.svg?branch=master)](https://coveralls.io/github/php-ai/php-ml?branch=master) [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/php-ai/php-ml/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/php-ai/php-ml/?branch=master) - - - -![PHP-ML - Machine Learning library for PHP](docs/assets/php-ml-logo.png) +

+ +

Fresh approach to Machine Learning in PHP. Algorithms, Cross Validation, Neural Network, Preprocessing, Feature Extraction and much more in one library. @@ -35,6 +33,11 @@ echo $classifier->predict([3, 2]); // return 'b' ``` +## Awards + + + + ## Documentation To find out how to use PHP-ML follow [Documentation](http://php-ml.readthedocs.org/). @@ -51,6 +54,10 @@ composer require php-ai/php-ml Example scripts are available in a separate repository [php-ai/php-ml-examples](https://github.com/php-ai/php-ml-examples). +## Datasets + +Public datasets are available in a separate repository [php-ai/php-ml-datasets](https://github.com/php-ai/php-ml-datasets). + ## Features * Association rule learning @@ -120,6 +127,7 @@ Example scripts are available in a separate repository [php-ai/php-ml-examples]( ## Contribute +- [Guide: CONTRIBUTING.md](https://github.com/php-ai/php-ml/blob/master/CONTRIBUTING.md) - [Issue Tracker: github.com/php-ai/php-ml](https://github.com/php-ai/php-ml/issues) - [Source Code: github.com/php-ai/php-ml](https://github.com/php-ai/php-ml) diff --git a/composer.json b/composer.json index c8652d9..c809822 100644 --- a/composer.json +++ b/composer.json @@ -23,6 +23,7 @@ "php": "^7.1" }, "require-dev": { + "phpbench/phpbench": "^0.14.0", "phpstan/phpstan-phpunit": "^0.9.4", "phpstan/phpstan-shim": "^0.9", "phpstan/phpstan-strict-rules": "^0.9.0", diff --git a/composer.lock b/composer.lock index 0462e94..0eeb693 100644 --- a/composer.lock +++ b/composer.lock @@ -4,9 +4,64 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "9135b3dece8c6938922f757123274e95", + "content-hash": "fc88078118714e9fb6b13a02dba0bd00", "packages": [], "packages-dev": [ + { + "name": "beberlei/assert", + "version": "v2.9.2", + "source": { + "type": "git", + "url": "https://github.com/beberlei/assert.git", + "reference": "2d555f72f3f4ff9e72a7bc17cb8a53c86737c8a0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/beberlei/assert/zipball/2d555f72f3f4ff9e72a7bc17cb8a53c86737c8a0", + "reference": "2d555f72f3f4ff9e72a7bc17cb8a53c86737c8a0", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": ">=5.3" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.1.1", + "phpunit/phpunit": "^4.8.35|^5.7" + }, + "type": "library", + "autoload": { + "psr-4": { + "Assert\\": "lib/Assert" + }, + "files": [ + "lib/Assert/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "authors": [ + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de", + "role": "Lead Developer" + }, + { + "name": "Richard Quadling", + "email": "rquadling@gmail.com", + "role": "Collaborator" + } + ], + "description": "Thin assertion library for input validation in business models.", + "keywords": [ + "assert", + "assertion", + "validation" + ], + "time": "2018-01-25T13:33:16+00:00" + }, { "name": "composer/semver", "version": "1.4.2", @@ -375,6 +430,144 @@ ], "time": "2017-08-23T07:46:41+00:00" }, + { + "name": "lstrojny/functional-php", + "version": "1.7.0", + "source": { + "type": "git", + "url": "https://github.com/lstrojny/functional-php.git", + "reference": "7c2091ddea572e012aa980e5d19d242d3a06ad5b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/lstrojny/functional-php/zipball/7c2091ddea572e012aa980e5d19d242d3a06ad5b", + "reference": "7c2091ddea572e012aa980e5d19d242d3a06ad5b", + "shasum": "" + }, + "require": { + "php": "~7" + }, + "require-dev": { + "phpunit/phpunit": "~6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2-dev" + } + }, + "autoload": { + "psr-4": { + "Functional\\": "src/Functional" + }, + "files": [ + "src/Functional/Average.php", + "src/Functional/Capture.php", + "src/Functional/ConstFunction.php", + "src/Functional/CompareOn.php", + "src/Functional/CompareObjectHashOn.php", + "src/Functional/Compose.php", + "src/Functional/Concat.php", + "src/Functional/Contains.php", + "src/Functional/Curry.php", + "src/Functional/CurryN.php", + "src/Functional/Difference.php", + "src/Functional/DropFirst.php", + "src/Functional/DropLast.php", + "src/Functional/Each.php", + "src/Functional/Equal.php", + "src/Functional/ErrorToException.php", + "src/Functional/Every.php", + "src/Functional/False.php", + "src/Functional/Falsy.php", + "src/Functional/Filter.php", + "src/Functional/First.php", + "src/Functional/FirstIndexOf.php", + "src/Functional/FlatMap.php", + "src/Functional/Flatten.php", + "src/Functional/Flip.php", + "src/Functional/GreaterThan.php", + "src/Functional/GreaterThanOrEqual.php", + "src/Functional/Group.php", + "src/Functional/Head.php", + "src/Functional/Id.php", + "src/Functional/IfElse.php", + "src/Functional/Identical.php", + "src/Functional/IndexesOf.php", + "src/Functional/Intersperse.php", + "src/Functional/Invoke.php", + "src/Functional/InvokeFirst.php", + "src/Functional/InvokeIf.php", + "src/Functional/InvokeLast.php", + "src/Functional/Invoker.php", + "src/Functional/Last.php", + "src/Functional/LastIndexOf.php", + "src/Functional/LessThan.php", + "src/Functional/LessThanOrEqual.php", + "src/Functional/LexicographicCompare.php", + "src/Functional/Map.php", + "src/Functional/Match.php", + "src/Functional/Maximum.php", + "src/Functional/Memoize.php", + "src/Functional/Minimum.php", + "src/Functional/None.php", + "src/Functional/Not.php", + "src/Functional/PartialAny.php", + "src/Functional/PartialLeft.php", + "src/Functional/PartialMethod.php", + "src/Functional/PartialRight.php", + "src/Functional/Partition.php", + "src/Functional/Pick.php", + "src/Functional/Pluck.php", + "src/Functional/Poll.php", + "src/Functional/Product.php", + "src/Functional/Ratio.php", + "src/Functional/ReduceLeft.php", + "src/Functional/ReduceRight.php", + "src/Functional/Reindex.php", + "src/Functional/Reject.php", + "src/Functional/Retry.php", + "src/Functional/Select.php", + "src/Functional/SelectKeys.php", + "src/Functional/SequenceConstant.php", + "src/Functional/SequenceExponential.php", + "src/Functional/SequenceLinear.php", + "src/Functional/Some.php", + "src/Functional/Sort.php", + "src/Functional/Sum.php", + "src/Functional/SuppressError.php", + "src/Functional/Tap.php", + "src/Functional/Tail.php", + "src/Functional/TailRecursion.php", + "src/Functional/True.php", + "src/Functional/Truthy.php", + "src/Functional/Unique.php", + "src/Functional/With.php", + "src/Functional/Zip.php", + "src/Functional/ZipAll.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Lars Strojny", + "email": "lstrojny@php.net", + "homepage": "http://usrportage.de" + }, + { + "name": "Max Beutel", + "email": "nash12@gmail.com" + } + ], + "description": "Functional primitives for PHP", + "keywords": [ + "functional" + ], + "time": "2018-01-03T10:08:50+00:00" + }, { "name": "myclabs/deep-copy", "version": "1.7.0", @@ -1072,6 +1265,168 @@ ], "time": "2017-10-19T09:58:18+00:00" }, + { + "name": "phpbench/container", + "version": "1.2", + "source": { + "type": "git", + "url": "https://github.com/phpbench/container.git", + "reference": "c0e3cbf1cd8f867c70b029cb6d1b0b39fe6d409d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpbench/container/zipball/c0e3cbf1cd8f867c70b029cb6d1b0b39fe6d409d", + "reference": "c0e3cbf1cd8f867c70b029cb6d1b0b39fe6d409d", + "shasum": "" + }, + "require": { + "psr/container": "^1.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.36" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "PhpBench\\DependencyInjection\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Leech", + "email": "daniel@dantleech.com" + } + ], + "description": "Simple, configurable, service container.", + "time": "2018-02-12T08:08:59+00:00" + }, + { + "name": "phpbench/dom", + "version": "0.2.0", + "source": { + "type": "git", + "url": "https://github.com/phpbench/dom.git", + "reference": "b135378dd0004c05ba5446aeddaf0b83339c1c4c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpbench/dom/zipball/b135378dd0004c05ba5446aeddaf0b83339c1c4c", + "reference": "b135378dd0004c05ba5446aeddaf0b83339c1c4c", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "php": "^5.4|^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "PhpBench\\Dom\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Leech", + "email": "daniel@dantleech.com" + } + ], + "description": "DOM wrapper to simplify working with the PHP DOM implementation", + "time": "2016-02-27T12:15:56+00:00" + }, + { + "name": "phpbench/phpbench", + "version": "0.14.0", + "source": { + "type": "git", + "url": "https://github.com/phpbench/phpbench.git", + "reference": "ea2c7ca1cdbfa952b8d50c4f36fc233dbfabe3c9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpbench/phpbench/zipball/ea2c7ca1cdbfa952b8d50c4f36fc233dbfabe3c9", + "reference": "ea2c7ca1cdbfa952b8d50c4f36fc233dbfabe3c9", + "shasum": "" + }, + "require": { + "beberlei/assert": "^2.4", + "doctrine/annotations": "^1.2.7", + "ext-dom": "*", + "ext-json": "*", + "ext-pcre": "*", + "ext-reflection": "*", + "ext-spl": "*", + "lstrojny/functional-php": "1.0|^1.2.3", + "php": "^7.0", + "phpbench/container": "~1.0", + "phpbench/dom": "~0.2.0", + "seld/jsonlint": "^1.0", + "symfony/console": "^2.6|^3.0|^4.0", + "symfony/debug": "^2.4|^3.0|^4.0", + "symfony/filesystem": "^2.4|^3.0|^4.0", + "symfony/finder": "^2.4|^3.0|^4.0", + "symfony/options-resolver": "^2.6|^3.0|^4.0", + "symfony/process": "^2.1|^3.0|^4.0" + }, + "require-dev": { + "doctrine/dbal": "^2.4", + "liip/rmt": "^1.2", + "padraic/phar-updater": "^1.0", + "phpstan/phpstan": "^0.8.5", + "phpunit/phpunit": "^6.0" + }, + "suggest": { + "ext-xdebug": "For XDebug profiling extension." + }, + "bin": [ + "bin/phpbench" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "PhpBench\\": "lib/", + "PhpBench\\Extensions\\Dbal\\": "extensions/dbal/lib/", + "PhpBench\\Extensions\\XDebug\\": "extensions/xdebug/lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Leech", + "email": "daniel@dantleech.com" + } + ], + "description": "PHP Benchmarking Framework", + "time": "2017-12-05T15:55:57+00:00" + }, { "name": "phpdocumentor/reflection-common", "version": "1.0.1", @@ -2457,6 +2812,55 @@ "homepage": "https://github.com/sebastianbergmann/version", "time": "2016-10-03T07:35:21+00:00" }, + { + "name": "seld/jsonlint", + "version": "1.7.1", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/jsonlint.git", + "reference": "d15f59a67ff805a44c50ea0516d2341740f81a38" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/d15f59a67ff805a44c50ea0516d2341740f81a38", + "reference": "d15f59a67ff805a44c50ea0516d2341740f81a38", + "shasum": "" + }, + "require": { + "php": "^5.3 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" + }, + "bin": [ + "bin/jsonlint" + ], + "type": "library", + "autoload": { + "psr-4": { + "Seld\\JsonLint\\": "src/Seld/JsonLint/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "JSON Linter", + "keywords": [ + "json", + "linter", + "parser", + "validator" + ], + "time": "2018-01-24T12:46:19+00:00" + }, { "name": "slevomat/coding-standard", "version": "4.2.1", diff --git a/docs/index.md b/docs/index.md index 2e204e8..4ba9d56 100644 --- a/docs/index.md +++ b/docs/index.md @@ -9,11 +9,9 @@ [![Coverage Status](https://coveralls.io/repos/github/php-ai/php-ml/badge.svg?branch=master)](https://coveralls.io/github/php-ai/php-ml?branch=master) [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/php-ai/php-ml/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/php-ai/php-ml/?branch=master) - - - -![PHP-ML - Machine Learning library for PHP](assets/php-ml-logo.png) +

+ +

Fresh approach to Machine Learning in PHP. Algorithms, Cross Validation, Neural Network, Preprocessing, Feature Extraction and much more in one library. @@ -35,6 +33,11 @@ $classifier->predict([3, 2]); // return 'b' ``` +## Awards + + + + ## Documentation To find out how to use PHP-ML follow [Documentation](http://php-ml.readthedocs.org/). @@ -105,6 +108,7 @@ Example scripts are available in a separate repository [php-ai/php-ml-examples]( ## Contribute +- Guide: [CONTRIBUTING.md](https://github.com/php-ai/php-ml/blob/master/CONTRIBUTING.md) - Issue Tracker: [github.com/php-ai/php-ml/issues](https://github.com/php-ai/php-ml/issues) - Source Code: [github.com/php-ai/php-ml](https://github.com/php-ai/php-ml) diff --git a/phpbench.json b/phpbench.json new file mode 100644 index 0000000..ea802f7 --- /dev/null +++ b/phpbench.json @@ -0,0 +1,17 @@ +{ + "bootstrap": "tests/Performance/bootstrap.php", + "path": "tests/Performance", + "reports": { + "time": { + "extends": "aggregate", + "title": "The Consumation of Time", + "cols": [ "subject", "mode", "mean", "rstdev", "diff"] + }, + "memory": { + "extends": "aggregate", + "title": "The Memory Usage", + "cols": [ "subject", "mem_real", "mem_final", "mem_peak", "diff"], + "diff_col": "mem_peak" + } + } +} \ No newline at end of file diff --git a/tests/Performance/Data/.gitkeep b/tests/Performance/Data/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/tests/Performance/Regression/LeastSquaresBench.php b/tests/Performance/Regression/LeastSquaresBench.php new file mode 100644 index 0000000..d6dba2f --- /dev/null +++ b/tests/Performance/Regression/LeastSquaresBench.php @@ -0,0 +1,40 @@ +dataset = new CsvDataset(__DIR__.'/../Data/bike-sharing-hour.csv', 14); + } + + /** + * @Revs(1) + * @Iterations(5) + */ + public function benchLeastSquaresTrain(): void + { + $leastSqueares = new LeastSquares(); + $leastSqueares->train($this->dataset->getSamples(), $this->dataset->getTargets()); + } +} diff --git a/tests/Performance/bootstrap.php b/tests/Performance/bootstrap.php new file mode 100644 index 0000000..a358903 --- /dev/null +++ b/tests/Performance/bootstrap.php @@ -0,0 +1,20 @@ +