mirror of
https://github.com/Llewellynvdm/php-ml.git
synced 2024-11-22 04:55:10 +00:00
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:
parent
a348111e97
commit
6660645ecd
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,4 +1,3 @@
|
||||
/vendor/
|
||||
humbuglog.*
|
||||
.php_cs.cache
|
||||
/build
|
||||
|
@ -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:
|
||||
- |
|
||||
|
@ -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
744
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"source": {
|
||||
"directories": [
|
||||
"src"
|
||||
]
|
||||
},
|
||||
"timeout": 10,
|
||||
"logs": {
|
||||
"text": "humbuglog.txt"
|
||||
}
|
||||
}
|
18
phpstan.neon
18
phpstan.neon
@ -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\(\)#'
|
||||
|
@ -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}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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>';
|
||||
|
@ -148,7 +148,7 @@ class RandomForest extends Bagging
|
||||
}
|
||||
|
||||
return $classifier
|
||||
->setColumnNames($this->columnNames)
|
||||
->setNumFeatures($featureCount);
|
||||
->setColumnNames($this->columnNames)
|
||||
->setNumFeatures($featureCount);
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -78,7 +78,7 @@ class FuzzyCMeans implements Clusterer
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array|Point[] $samples
|
||||
* @param Point[]|int[][] $samples
|
||||
*/
|
||||
public function cluster(array $samples): array
|
||||
{
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -10,6 +10,7 @@ use Phpml\Math\Matrix;
|
||||
class LeastSquares implements Regression
|
||||
{
|
||||
use Predictable;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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]
|
||||
|
Loading…
Reference in New Issue
Block a user