Estimate probabilities for each possible outcome.

@param \Rubix\ML\Datasets\Dataset $dataset
@throws \InvalidArgumentException
@throws \RuntimeException
@return array
500545
public function proba(Dataset $dataset) : array
    {
        if (!$this->network or !$this->classes) {
            throw new RuntimeException('The learner has not'
                . ' been trained.');
        }

        DatasetIsCompatibleWithEstimator::check($dataset, $this);

        $xT = Matrix::quick($dataset->samples())->transpose();

        $yT = $this->network->infer($xT)->transpose();

        $probabilities = [];

        foreach ($yT as $activations) {
            $probabilities[] = array_combine($this->classes, $activations);
        }

        return $probabilities;
    }
194102
public function append(Dataset $dataset) : Dataset
    {
        return self::quick(array_merge($this->samples, $dataset->samples()));
    }
487786
public function train(Dataset $dataset) : void
    {
        if (!$dataset instanceof Labeled) {
            throw new InvalidArgumentException('This estimator requires a'
                . ' labeled training set.');
        }

        $this->strategy->fit($dataset->labels());

        $this->trained = true;
    }
1047502
public function proba(Dataset $dataset) : array
    {
        if (empty($this->forest)) {
            throw new RuntimeException('The learner has not'
                . ' been trained.');
        }

        $probabilities = array_fill(
            0,
            $dataset->numRows(),
            array_fill_keys($this->classes, 0.)
        );

        foreach ($this->forest as $tree) {
            foreach ($tree->proba($dataset) as $i => $joint) {
                foreach ($joint as $class => $probability) {
                    $probabilities[$i][$class] += $probability;
                }
            }
        }

        foreach ($probabilities as &$joint) {
            foreach ($joint as &$probability) {
                $probability /= $this->estimators;
            }
        }

        return $probabilities;
    }
1239152
public function train(Dataset $dataset) : void
    {
        if (!$dataset instanceof Labeled) {
            throw new InvalidArgumentException('This estimator requires a'
                . ' labeled training set.');
        }

        DatasetIsCompatibleWithEstimator::check($dataset, $this);

        $samples = $dataset->samples();
        $labels = $dataset->labels();

        $biases = Matrix::ones($dataset->numRows(), 1);

        $x = Matrix::build($samples)->augmentLeft($biases);
        $y = Vector::build($labels);

        $alphas = array_fill(0, $x->n() - 1, $this->alpha);

        $penalty = Matrix::diagonal(array_merge([0.], $alphas));

        $xT = $x->transpose();

        $coefficients = $xT->matmul($x)
            ->add($penalty)
            ->inverse()
            ->dot($xT->dot($y))
            ->asArray();

        $this->bias = (float) array_shift($coefficients);
        $this->weights = Vector::quick($coefficients);
    }
885811
protected function get(array $dataset)
    {
        foreach ($dataset as $key => $firstItem) {
            $remaining = $dataset;

            \array_splice($remaining, $key, 1);

            if (0 === \count($remaining)) {
                yield [$firstItem];

                continue;
            }

            foreach ($this->get($remaining) as $permutation) {
                \array_unshift($permutation, $firstItem);
                yield $permutation;
            }
        }
    }
1191811
public function execute(DataSetInterface $dataSet)
    {
        $localizedNotes = [];
        foreach ($dataSet[ProductDiscontinuedDataSetInterface::KEY_LOCALES] as $localeName => $idLocale) {
            $key = ProductDiscontinuedDataSetInterface::KEY_NOTE . '.' . $localeName;
            if (!isset($dataSet[$key])) {
                throw new InvalidDataException(
                    sprintf('Could not find note for locale "%s" and sku "%s"', $localeName, $dataSet[ProductDiscontinuedDataSetInterface::KEY_CONCRETE_SKU])
                );
            }
            if (empty($dataSet[$key])) {
                continue;
            }
            $localizedNotes[$idLocale] = [
                ProductDiscontinuedDataSetInterface::KEY_NOTE => $dataSet[$key],
            ];
        }

        $dataSet[ProductDiscontinuedDataSetInterface::KEY_LOCALIZED_NOTES] = $localizedNotes;
    }
736016
public function predict(Dataset $dataset) : array
    {
        if (empty($this->ensemble)) {
            throw new RuntimeException('Estimator has not been trained.');
        }

        DatasetIsCompatibleWithEstimator::check($dataset, $this);

        $predictions = $this->base->predict($dataset);

        foreach ($this->ensemble as $estimator) {
            foreach ($estimator->predict($dataset) as $j => $prediction) {
                $predictions[$j] += $this->rate * $prediction;
            }
        }

        return $predictions;
    }
485616
public function partial(Dataset $dataset) : void
    {
        if (empty($this->centroids) or empty($this->sizes)) {
            $this->train($dataset);

            return;
        }

        DatasetIsCompatibleWithEstimator::check($dataset, $this);

        if ($this->logger) {
            $this->logger->info('Learner init ' . Params::stringify([
                'k' => $this->k,
                'batch_size' => $this->batchSize,
                'kernel' => $this->kernel,
                'epochs' => $this->epochs,
                'min_change' => $this->minChange,
                'seeder' => $this->seeder,
            ]));
        }

        $n = $dataset->numRows();

        $samples = $dataset->samples();
        $labels = array_fill(0, $n, 0);

        $order = range(0, $n - 1);

        $randomize = $n > $this->batchSize ? true : false;

        $previous = INF;

        for ($epoch = 1; $epoch <= $this->epochs; $epoch++) {
            if ($randomize) {
                shuffle($order);

                array_multisort($order, $samples, $labels);
            }

            $sBatches = array_chunk($samples, $this->batchSize, true);
            $lBatches = array_chunk($labels, $this->batchSize, true);

            foreach ($sBatches as $i => $batch) {
                $assignments = array_map([self::class, 'assign'], $batch);

                $lHat = $lBatches[$i];

                foreach ($assignments as $j => $cluster) {
                    $expected = $lHat[$j];

                    if ($cluster !== $expected) {
                        $labels[$j] = $cluster;

                        $this->sizes[$expected]--;
                        $this->sizes[$cluster]++;
                    }
                }

                $strata = Labeled::quick($batch, $lHat)->stratify();

                foreach ($strata as $cluster => $stratum) {
                    $centroid = $this->centroids[$cluster];
                    $size = $this->sizes[$cluster];

                    $step = Matrix::quick($stratum->samples())
                        ->transpose()
                        ->mean()
                        ->asArray();

                    $weight = 1. / ($size ?: EPSILON);

                    foreach ($centroid as $i => &$mean) {
                        $mean = (1. - $weight) * $mean + $weight * $step[$i];
                    }

                    $this->centroids[$cluster] = $centroid;
                }
            }

            $inertia = $this->inertia($samples);

            $this->steps[] = $inertia;

            if ($this->logger) {
                $this->logger->info("Epoch $epoch complete, inertia=$inertia");
            }

            if (is_nan($inertia)) {
                break 1;
            }

            if (abs($previous - $inertia) < $this->minChange) {
                break 1;
            }

            $previous = $inertia;
        }

        if ($this->logger) {
            $this->logger->info('Training complete');
        }
    }
1164287
public function proba(Dataset $dataset) : array
    {
        if (empty($this->priors)) {
            throw new RuntimeException('Estimator has not been trained.');
        }

        DatasetIsCompatibleWithEstimator::check($dataset, $this);

        $probabilities = [];

        foreach ($dataset as $sample) {
            $jll = $this->jointLogLikelihood($sample);

            $total = logsumexp($jll);

            $dist = [];

            foreach ($jll as $cluster => $likelihood) {
                $dist[$cluster] = exp($likelihood - $total);
            }

            $probabilities[] = $dist;
        }

        return $probabilities;
    }
170842
public function predict(Dataset $dataset) : array
    {
        if (!$this->medians or !$this->mads) {
            throw new RuntimeException('The learner has not'
                . ' been trained.');
        }

        DatasetIsCompatibleWithEstimator::check($dataset, $this);

        $p = $dataset->numColumns();

        $predictions = [];

        foreach ($dataset as $sample) {
            $score = 0.;

            foreach ($sample as $column => $feature) {
                $median = $this->medians[$column];
                $mad = $this->mads[$column];

                $z = abs((self::LAMBDA * ($feature - $median)) / $mad);

                if ($z > $this->threshold) {
                    $predictions[] = 1;

                    continue 2;
                }

                $score += $z;
            }

            $predictions[] = ($score / $p) > $this->tolerance ? 1 : 0;
        }

        return $predictions;
    }
755694
public function train(Dataset $dataset) : void
    {
        $this->samples = $this->kdistances = $this->lrds = [];

        $this->partial($dataset);
    }
17145
public function partial(Dataset $dataset) : void
    {
        if (!$dataset instanceof Labeled) {
            throw new InvalidArgumentException('This Estimator requires a'
                . ' Labeled training set.');
        }

        if (!$dataset->homogeneous() or $dataset->columnType(0) !== DataType::CATEGORICAL) {
            throw new InvalidArgumentException('This estimator only works'
                . ' with categorical features.');
        }

        if (empty($this->weights) or empty($this->counts) or empty($this->probs)) {
            $this->train($dataset);
            return;
        }

        foreach ($dataset->stratify() as $class => $stratum) {
            $classCounts = $this->counts[$class];
            $classProbs = $this->probs[$class];

            foreach ($stratum->columns() as $column => $values) {
                $columnCounts = $classCounts[$column];

                $counts = array_count_values($values);

                foreach ($counts as $category => $count) {
                    if (isset($columnCounts[$category])) {
                        $columnCounts[$category] += $count;
                    } else {
                        $columnCounts[$category] = $count;
                    }
                }

                $total = (array_sum($columnCounts)
                    + (count($columnCounts) * $this->alpha))
                    ?: EPSILON;

                $probs = [];

                foreach ($columnCounts as $category => $count) {
                    $probs[$category] = log(($count + $this->alpha) / $total);
                }

                $classCounts[$column] = $columnCounts;
                $classProbs[$column] = $probs;
            }

            $this->counts[$class] = $classCounts;
            $this->probs[$class] = $classProbs;

            $this->weights[$class] += $stratum->numRows();
        }

        if ($this->fitPriors) {
            $total = (array_sum($this->weights)
                + (count($this->weights) * $this->alpha))
                ?: EPSILON;

            foreach ($this->weights as $class => $weight) {
                $this->priors[$class] = log(($weight + $this->alpha) / $total);
            }
        }
    }
338376
public function predict(Dataset $dataset) : array
    {
        if (empty($this->samples) or empty($this->labels)) {
            throw new RuntimeException('Estimator has not been trained.');
        }

        DatasetIsCompatibleWithEstimator::check($dataset, $this);

        $predictions = [];

        foreach ($dataset as $sample) {
            [$labels, $distances] = $this->nearest($sample);

            if ($this->weighted) {
                $weights = [];

                foreach ($distances as $i => $distance) {
                    $weights[] = 1. / (1. + $distance);
                }

                $outcome = Stats::weightedMean($labels, $weights);
            } else {
                $outcome = Stats::mean($labels);
            }

            $predictions[] = $outcome;
        }

        return $predictions;
    }
583652
public function partial(Dataset $dataset) : void
    {
        if (!$dataset instanceof Labeled) {
            throw new InvalidArgumentException('This estimator requires a'
                . ' labeled training set.');
        }

        DatasetIsCompatibleWithEstimator::check($dataset, $this);

        $this->classes = array_unique(array_merge($this->classes, $dataset->possibleOutcomes()));
        $this->samples = array_merge($this->samples, $dataset->samples());
        $this->labels = array_merge($this->labels, $dataset->labels());
    }
249199
public function predict(Dataset $dataset) : array
    {
        if (empty($this->samples) or empty($this->labels)) {
            throw new RuntimeException('The learner has not'
                . ' been trained.');
        }

        DatasetIsCompatibleWithEstimator::check($dataset, $this);

        $predictions = [];

        foreach ($dataset as $sample) {
            [$labels, $distances] = $this->nearest($sample);

            if ($this->weighted) {
                $weights = array_fill_keys($labels, 0.);

                foreach ($labels as $i => $label) {
                    $weights[$label] += 1. / (1. + $distances[$i]);
                }
            } else {
                $weights = array_count_values($labels);
            }

            $predictions[] = argmax($weights);
        }

        return $predictions;
    }
471127
public function train(Dataset $dataset) : void
    {
        $this->fit($dataset);

        if ($this->estimator instanceof Learner) {
            $this->estimator->train($dataset);
        }

        $this->fitted = true;
    }