Update dev dependencies (#187)

* composer: update dev dependencies

* phpstan fixes

* phpstan fixes

* phpstan fixes

* phpstan fixes

* drop probably forgotten humbug configs

* apply cs

* fix cs bug

* compsoer: add coding standard and phsptan dev friendly scripts

* ecs: add skipped errors

* cs: fix PHP 7.1

* fix cs

* ecs: exclude strict fixer that break code

* ecs: cleanup commented sets

* travis: use composer scripts for testing to prevent duplicated setup
This commit is contained in:
Tomáš Votruba 2018-01-06 21:25:47 +01:00 committed by Arkadiusz Kondas
parent a348111e97
commit 6660645ecd
25 changed files with 457 additions and 454 deletions

1
.gitignore vendored
View File

@ -1,4 +1,3 @@
/vendor/
humbuglog.*
.php_cs.cache
/build

View File

@ -30,8 +30,8 @@ install:
script:
- vendor/bin/phpunit $PHPUNIT_FLAGS
- if [[ $STATIC_ANALYSIS != "" ]]; then vendor/bin/ecs check src tests; fi
- if [[ $STATIC_ANALYSIS != "" ]]; then vendor/bin/phpstan.phar analyse src tests --level max --configuration phpstan.neon; fi
- if [[ $STATIC_ANALYSIS != "" ]]; then composer check-cs; fi
- if [[ $STATIC_ANALYSIS != "" ]]; then composer phpstan; fi
after_success:
- |

View File

@ -15,11 +15,10 @@
"php": "^7.1"
},
"require-dev": {
"phpunit/phpunit": "^6.4",
"symplify/easy-coding-standard": "v3.0.0-RC3",
"symplify/coding-standard": "v3.0.0-RC3",
"symplify/package-builder": "v3.0.0-RC3",
"phpstan/phpstan-shim": "^0.8"
"phpunit/phpunit": "^6.5",
"symplify/easy-coding-standard": "^3.1",
"symplify/coding-standard": "^3.1",
"phpstan/phpstan-shim": "^0.9"
},
"autoload": {
"psr-4": {
@ -30,5 +29,10 @@
"psr-4": {
"Phpml\\Tests\\": "tests/Phpml"
}
},
"scripts": {
"check-cs": "vendor/bin/ecs check src tests bin",
"fix-cs": "vendor/bin/ecs check src tests bin --fix",
"phpstan": "vendor/bin/phpstan.phar analyse src tests bin --level max --configuration phpstan.neon"
}
}

744
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,14 +1,8 @@
includes:
- vendor/symplify/easy-coding-standard/config/psr2.neon
- vendor/symplify/easy-coding-standard/config/php70.neon
- vendor/symplify/easy-coding-standard/config/php71.neon
- vendor/symplify/easy-coding-standard/config/clean-code.neon
- vendor/symplify/easy-coding-standard/config/common/array.neon
- vendor/symplify/easy-coding-standard/config/common/docblock.neon
- vendor/symplify/easy-coding-standard/config/common/namespaces.neon
- vendor/symplify/easy-coding-standard/config/common/control-structures.neon
# many errors, need help
#- vendor/symplify/easy-coding-standard/config/common/strict.neon
- vendor/symplify/easy-coding-standard/config/common.neon
checkers:
# spacing
@ -33,13 +27,16 @@ checkers:
- Symplify\CodingStandard\Fixer\Import\ImportNamespacedNameFixer
- Symplify\CodingStandard\Fixer\Php\ClassStringToClassConstantFixer
- Symplify\CodingStandard\Fixer\Property\ArrayPropertyDefaultValueFixer
- Symplify\CodingStandard\Fixer\ClassNotation\PropertyAndConstantSeparationFixer
- Symplify\CodingStandard\Fixer\ArrayNotation\StandaloneLineInMultilineArrayFixer
parameters:
exclude_checkers:
# from strict.neon
- PhpCsFixer\Fixer\PhpUnit\PhpUnitStrictFixer
- PhpCsFixer\Fixer\Strict\StrictComparisonFixer
# personal prefference
- PhpCsFixer\Fixer\Operator\NotOperatorWithSuccessorSpaceFixer
skip:
PhpCsFixer\Fixer\Alias\RandomApiMigrationFixer:
# random_int() breaks code
@ -47,6 +44,15 @@ parameters:
SlevomatCodingStandard\Sniffs\Classes\UnusedPrivateElementsSniff:
# magic calls
- src/Phpml/Preprocessing/Normalizer.php
PhpCsFixer\Fixer\StringNotation\ExplicitStringVariableFixer:
# bugged
- src/Phpml/Classification/DecisionTree/DecisionTreeLeaf.php
Symplify\CodingStandard\Fixer\Commenting\RemoveUselessDocBlockFixer:
# bug in fixer
- src/Phpml/Math/LinearAlgebra/LUDecomposition.php
PhpCsFixer\Fixer\FunctionNotation\VoidReturnFixer:
# covariant return types
- src/Phpml/Classification/Linear/Perceptron.php
skip_codes:
# missing typehints
@ -56,3 +62,4 @@ parameters:
- SlevomatCodingStandard\Sniffs\TypeHints\TypeHintDeclarationSniff.MissingTraversableReturnTypeHintSpecification
- SlevomatCodingStandard\Sniffs\TypeHints\TypeHintDeclarationSniff.MissingPropertyTypeHint
- SlevomatCodingStandard\Sniffs\TypeHints\TypeHintDeclarationSniff.MissingTraversablePropertyTypeHintSpecification
- PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis\AssignmentInConditionSniff.Found

View File

@ -1,11 +0,0 @@
{
"source": {
"directories": [
"src"
]
},
"timeout": 10,
"logs": {
"text": "humbuglog.txt"
}
}

View File

@ -1,19 +1,15 @@
parameters:
ignoreErrors:
- '#Phpml\\Dataset\\FilesDataset::__construct\(\) does not call parent constructor from Phpml\\Dataset\\ArrayDataset#'
- '#Parameter \#2 \$predictedLabels of static method Phpml\\Metric\\Accuracy::score\(\) expects mixed\[\], mixed\[\]\|string given#'
# should be always defined
- '#Undefined variable: \$j#'
# mocks
- '#PHPUnit_Framework_MockObject_MockObject#'
# bugged
- '#expects [a-z\\\|\[\]]*, [a-z\\\|\(\)\[\]]*\[\] given#'
# mock
- '#Parameter \#1 \$node of class Phpml\\NeuralNetwork\\Node\\Neuron\\Synapse constructor expects Phpml\\NeuralNetwork\\Node, Phpml\\NeuralNetwork\\Node\\Neuron\|PHPUnit_Framework_MockObject_MockObject given#'
- '#Parameter \#1 \$(activationFunction|synapse) of class Phpml\\NeuralNetwork\\Node\\Neuron constructor expects Phpml\\NeuralNetwork\\ActivationFunction|null, Phpml\\NeuralNetwork\\ActivationFunction\\BinaryStep|PHPUnit_Framework_MockObject_MockObject given#'
# wide range cases
- '#Call to function count\(\) with argument type array<int>\|Phpml\\Clustering\\KMeans\\Point will always result in number 1#'
- '#Parameter \#1 \$coordinates of class Phpml\\Clustering\\KMeans\\Point constructor expects array, array<int>\|Phpml\\Clustering\\KMeans\\Point given#'
# probably known value
- '#Variable \$j might not be defined#'
- '#Method Phpml\\Classification\\DecisionTree::getBestSplit\(\) should return Phpml\\Classification\\DecisionTree\\DecisionTreeLeaf but returns Phpml\\Classification\\DecisionTree\\DecisionTreeLeaf\|null#'
- '#Method Phpml\\Classification\\Linear\\DecisionStump::getBestNumericalSplit\(\) should return mixed\[\] but returns \(float\|int\|mixed\|string\)\[\]\|null#'
- '#Method Phpml\\Classification\\Linear\\DecisionStump::getBestNominalSplit\(\) should return mixed\[\] but returns mixed\[\]\|null#'
- '#Call to an undefined method Phpml\\Helper\\Optimizer\\Optimizer::getCostValues\(\)#'

View File

@ -64,9 +64,9 @@ class DecisionTree implements Classifier
private $featureImportances;
/**
* @var array|null
* @var array
*/
private $columnNames;
private $columnNames = [];
public function __construct(int $maxDepth = 10)
{
@ -89,7 +89,7 @@ class DecisionTree implements Classifier
// If column names are given or computed before, then there is no
// need to init it and accidentally remove the previous given names
if ($this->columnNames === null) {
if ($this->columnNames === []) {
$this->columnNames = range(0, $this->featureCount - 1);
} elseif (count($this->columnNames) > $this->featureCount) {
$this->columnNames = array_slice($this->columnNames, 0, $this->featureCount);
@ -380,9 +380,9 @@ class DecisionTree implements Classifier
$median = Mean::median($values);
foreach ($values as &$value) {
if ($value <= $median) {
$value = "<= $median";
$value = "<= ${median}";
} else {
$value = "> $median";
$value = "> ${median}";
}
}
}

View File

@ -122,7 +122,7 @@ class DecisionTreeLeaf
public function getHTML($columnNames = null): string
{
if ($this->isTerminal) {
$value = "<b>$this->classValue</b>";
$value = "<b>${this}->classValue</b>";
} else {
$value = $this->value;
if ($columnNames !== null) {
@ -132,13 +132,13 @@ class DecisionTreeLeaf
}
if (!preg_match('/^[<>=]{1,2}/', (string) $value)) {
$value = "=$value";
$value = "=${value}";
}
$value = "<b>$col $value</b><br>Gini: ".number_format($this->giniIndex, 2);
$value = "<b>${col} ${value}</b><br>Gini: ".number_format($this->giniIndex, 2);
}
$str = "<table ><tr><td colspan=3 align=center style='border:1px solid;'>$value</td></tr>";
$str = "<table ><tr><td colspan=3 align=center style='border:1px solid;'>${value}</td></tr>";
if ($this->leftLeaf || $this->rightLeaf) {
$str .= '<tr>';

View File

@ -148,7 +148,7 @@ class RandomForest extends Bagging
}
return $classifier
->setColumnNames($this->columnNames)
->setNumFeatures($featureCount);
->setColumnNames($this->columnNames)
->setNumFeatures($featureCount);
}
}

View File

@ -86,7 +86,7 @@ class DecisionStump extends WeightedClassifier
public function __toString(): string
{
return "IF $this->column $this->operator $this->value ".
return "IF ${this}->column ${this}->operator ${this}->value ".
'THEN '.$this->binaryLabels[0].' '.
'ELSE '.$this->binaryLabels[1];
}
@ -176,14 +176,14 @@ class DecisionStump extends WeightedClassifier
$maxValue = max($values);
$stepSize = ($maxValue - $minValue) / $this->numSplitCount;
$split = null;
$split = [];
foreach (['<=', '>'] as $operator) {
// Before trying all possible split points, let's first try
// the average value for the cut point
$threshold = array_sum($values) / (float) count($values);
[$errorRate, $prob] = $this->calculateErrorRate($targets, $threshold, $operator, $values);
if ($split == null || $errorRate < $split['trainingErrorRate']) {
if ($split === [] || $errorRate < $split['trainingErrorRate']) {
$split = [
'value' => $threshold,
'operator' => $operator,
@ -218,13 +218,13 @@ class DecisionStump extends WeightedClassifier
$valueCounts = array_count_values($values);
$distinctVals = array_keys($valueCounts);
$split = null;
$split = [];
foreach (['=', '!='] as $operator) {
foreach ($distinctVals as $val) {
[$errorRate, $prob] = $this->calculateErrorRate($targets, $val, $operator, $values);
if ($split === null || $split['trainingErrorRate'] < $errorRate) {
if ($split === [] || $split['trainingErrorRate'] < $errorRate) {
$split = [
'value' => $val,
'operator' => $operator,

View File

@ -34,7 +34,7 @@ class Perceptron implements Classifier, IncrementalEstimator
protected $featureCount = 0;
/**
* @var array|null
* @var array
*/
protected $weights = [];
@ -146,7 +146,7 @@ class Perceptron implements Classifier, IncrementalEstimator
$this->labels = [];
$this->optimizer = null;
$this->featureCount = 0;
$this->weights = null;
$this->weights = [];
$this->costValues = [];
}
@ -174,7 +174,7 @@ class Perceptron implements Classifier, IncrementalEstimator
* Executes a Gradient Descent algorithm for
* the given cost function
*/
protected function runGradientDescent(array $samples, array $targets, Closure $gradientFunc, bool $isBatch = false): void
protected function runGradientDescent(array $samples, array $targets, Closure $gradientFunc, bool $isBatch = false)
{
$class = $isBatch ? GD::class : StochasticGD::class;

View File

@ -147,7 +147,7 @@ class NaiveBayes implements Classifier
return $this->discreteProb[$label][$feature][$value];
}
$std = $this->std[$label][$feature] ;
$std = $this->std[$label][$feature];
$mean = $this->mean[$label][$feature];
// Calculate the probability density by use of normal/Gaussian distribution
// Ref: https://en.wikipedia.org/wiki/Normal_distribution

View File

@ -78,7 +78,7 @@ class FuzzyCMeans implements Clusterer
}
/**
* @param array|Point[] $samples
* @param Point[]|int[][] $samples
*/
public function cluster(array $samples): array
{

View File

@ -156,9 +156,9 @@ class KernelPCA extends PCA
$N_K_N = $N->multiply($K_N);
return $K->subtract($N_K)
->subtract($K_N)
->add($N_K_N)
->toArray();
->subtract($K_N)
->add($N_K_N)
->toArray();
}
/**

View File

@ -25,7 +25,7 @@ class StopWords
public static function factory(string $language = 'English'): self
{
$className = __NAMESPACE__."\\StopWords\\$language";
$className = __NAMESPACE__."\\StopWords\\${language}";
if (!class_exists($className)) {
throw InvalidArgumentException::invalidStopWordsLanguage($language);

View File

@ -164,7 +164,7 @@ trait OneVsRest
*/
private function binarizeTargets(array $targets, $label): array
{
$notLabel = "not_$label";
$notLabel = "not_${label}";
foreach ($targets as $key => $target) {
$targets[$key] = $target == $label ? $label : $notLabel;
}

View File

@ -171,7 +171,7 @@ class ConjugateGradient extends GD
$dNew = array_sum($this->gradient($newTheta));
$dOld = array_sum($this->gradient($this->theta)) + 1e-100;
return $dNew ** 2 / $dOld ** 2;
return $dNew ** 2 / $dOld ** 2;
}
/**

View File

@ -47,7 +47,7 @@ abstract class Optimizer
public function setInitialTheta(array $theta)
{
if (count($theta) != $this->dimensions) {
throw new Exception("Number of values in the weights array should be $this->dimensions");
throw new Exception("Number of values in the weights array should be ${this}->dimensions");
}
$this->theta = $theta;

View File

@ -10,7 +10,7 @@ use IteratorAggregate;
class Set implements IteratorAggregate
{
/**
* @var string[]|int[]|float[]
* @var string[]|int[]|float[]|bool[]
*/
private $elements = [];
@ -135,7 +135,7 @@ class Set implements IteratorAggregate
}
/**
* @return string[]|int[]|float[]
* @return string[]|int[]|float[]|bool[]
*/
public function toArray(): array
{
@ -160,9 +160,9 @@ class Set implements IteratorAggregate
/**
* Removes duplicates and rewrites index.
*
* @param string[]|int[]|float[] $elements
* @param string[]|int[]|float[]|bool[] $elements
*
* @return string[]|int[]|float[]
* @return string[]|int[]|float[]|bool[]
*/
private static function sanitize(array $elements): array
{

View File

@ -15,14 +15,14 @@ class Backpropagation
private $learningRate;
/**
* @var array|null
* @var array
*/
private $sigmas;
private $sigmas = [];
/**
* @var array|null
* @var array
*/
private $prevSigmas;
private $prevSigmas = [];
public function __construct(float $learningRate)
{
@ -57,8 +57,8 @@ class Backpropagation
}
// Clean some memory (also it helps make MLP persistency & children more maintainable).
$this->sigmas = null;
$this->prevSigmas = null;
$this->sigmas = [];
$this->prevSigmas = [];
}
private function getSigma(Neuron $neuron, int $targetClass, int $key, bool $lastLayer): float

View File

@ -10,6 +10,7 @@ use Phpml\Math\Matrix;
class LeastSquares implements Regression
{
use Predictable;
/**
* @var array
*/

View File

@ -2,7 +2,7 @@
declare(strict_types=1);
namespace tests\Phpml\Classification\Linear;
namespace Phpml\Tests\Classification\Linear;
use Phpml\Classification\Linear\LogisticRegression;
use PHPUnit\Framework\TestCase;
@ -55,12 +55,12 @@ class LogisticRegressionTest extends TestCase
$zero = $method->invoke($predictor, [0.1, 0.1], 0);
$one = $method->invoke($predictor, [0.1, 0.1], 1);
$this->assertEquals(1, $zero + $one, null, 1e-6);
$this->assertEquals(1, $zero + $one, '', 1e-6);
$this->assertTrue($zero > $one);
$zero = $method->invoke($predictor, [0.9, 0.9], 0);
$one = $method->invoke($predictor, [0.9, 0.9], 1);
$this->assertEquals(1, $zero + $one, null, 1e-6);
$this->assertEquals(1, $zero + $one, '', 1e-6);
$this->assertTrue($zero < $one);
}
@ -97,9 +97,9 @@ class LogisticRegressionTest extends TestCase
$two = $method->invoke($predictor, [3.0, 9.5], 2);
$not_two = $method->invoke($predictor, [3.0, 9.5], 'not_2');
$this->assertEquals(1, $zero + $not_zero, null, 1e-6);
$this->assertEquals(1, $one + $not_one, null, 1e-6);
$this->assertEquals(1, $two + $not_two, null, 1e-6);
$this->assertEquals(1, $zero + $not_zero, '', 1e-6);
$this->assertEquals(1, $one + $not_one, '', 1e-6);
$this->assertEquals(1, $two + $not_two, '', 1e-6);
$this->assertTrue($zero < $two);
$this->assertTrue($one < $two);
}

View File

@ -45,7 +45,7 @@ class AccuracyTest extends TestCase
$classifier = new SVC(Kernel::RBF);
$classifier->train($dataset->getTrainSamples(), $dataset->getTrainLabels());
$predicted = $classifier->predict($dataset->getTestSamples());
$predicted = (array) $classifier->predict($dataset->getTestSamples());
$accuracy = Accuracy::score($dataset->getTestLabels(), $predicted);

View File

@ -2,7 +2,7 @@
declare(strict_types=1);
namespace tests\Phpml\NeuralNetwork\Network;
namespace Phpml\Tests\NeuralNetwork\Network;
use Phpml\NeuralNetwork\Network\MultilayerPerceptron;
use PHPUnit\Framework\TestCase;
@ -11,6 +11,7 @@ class MultilayerPerceptronTest extends TestCase
{
public function testLearningRateSetter(): void
{
/** @var MultilayerPerceptron $mlp */
$mlp = $this->getMockForAbstractClass(
MultilayerPerceptron::class,
[5, [3], [0, 1], 1000, null, 0.42]