2016-05-08 18:35:01 +00:00
|
|
|
<?php
|
|
|
|
|
2016-11-20 21:53:17 +00:00
|
|
|
declare(strict_types=1);
|
2016-05-08 18:35:01 +00:00
|
|
|
|
|
|
|
namespace Phpml\Preprocessing;
|
|
|
|
|
|
|
|
use Phpml\Exception\NormalizerException;
|
|
|
|
|
|
|
|
class Normalizer implements Preprocessor
|
|
|
|
{
|
|
|
|
const NORM_L1 = 1;
|
|
|
|
const NORM_L2 = 2;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var int
|
|
|
|
*/
|
|
|
|
private $norm;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param int $norm
|
|
|
|
*
|
|
|
|
* @throws NormalizerException
|
|
|
|
*/
|
|
|
|
public function __construct(int $norm = self::NORM_L2)
|
|
|
|
{
|
|
|
|
if (!in_array($norm, [self::NORM_L1, self::NORM_L2])) {
|
|
|
|
throw NormalizerException::unknownNorm();
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->norm = $norm;
|
|
|
|
}
|
|
|
|
|
2016-06-16 22:08:10 +00:00
|
|
|
/**
|
|
|
|
* @param array $samples
|
|
|
|
*/
|
|
|
|
public function fit(array $samples)
|
|
|
|
{
|
2016-06-16 22:16:49 +00:00
|
|
|
// intentionally not implemented
|
2016-06-16 22:08:10 +00:00
|
|
|
}
|
|
|
|
|
2016-05-08 18:35:01 +00:00
|
|
|
/**
|
|
|
|
* @param array $samples
|
|
|
|
*/
|
2016-06-16 08:03:57 +00:00
|
|
|
public function transform(array &$samples)
|
2016-05-08 18:35:01 +00:00
|
|
|
{
|
|
|
|
$method = sprintf('normalizeL%s', $this->norm);
|
|
|
|
foreach ($samples as &$sample) {
|
|
|
|
$this->$method($sample);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param array $sample
|
|
|
|
*/
|
|
|
|
private function normalizeL1(array &$sample)
|
|
|
|
{
|
|
|
|
$norm1 = 0;
|
|
|
|
foreach ($sample as $feature) {
|
|
|
|
$norm1 += abs($feature);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (0 == $norm1) {
|
|
|
|
$count = count($sample);
|
|
|
|
$sample = array_fill(0, $count, 1.0 / $count);
|
|
|
|
} else {
|
|
|
|
foreach ($sample as &$feature) {
|
|
|
|
$feature = $feature / $norm1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param array $sample
|
|
|
|
*/
|
|
|
|
private function normalizeL2(array &$sample)
|
|
|
|
{
|
|
|
|
$norm2 = 0;
|
|
|
|
foreach ($sample as $feature) {
|
|
|
|
$norm2 += $feature * $feature;
|
|
|
|
}
|
2016-07-07 20:47:36 +00:00
|
|
|
$norm2 = sqrt(floatval($norm2));
|
2016-05-08 18:35:01 +00:00
|
|
|
|
|
|
|
if (0 == $norm2) {
|
|
|
|
$sample = array_fill(0, count($sample), 1);
|
|
|
|
} else {
|
|
|
|
foreach ($sample as &$feature) {
|
|
|
|
$feature = $feature / $norm2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|