mcordingley/regression

PHP 的回归包

2.2.0 2017-02-11 00:28 UTC

This package is auto-updated.

Last update: 2024-09-27 16:02:35 UTC


README

Build Status Code Climate Code Climate

这一切都是关于什么的?

这是一个用于数据回归分析的库。也就是说,它试图找到最佳拟合线来描述数据中的关系。它接受一系列训练观察结果,每个观察结果由特征和结果组成,并找出每个特征对结果的影响程度。

以一个具体的例子来说明,考虑房价。面积、浴室数量、房屋年龄以及房屋是否有完工的地下室都可能影响房屋的最终销售价格。出于某种精心设计的理由,你想开始对你所在地区的房屋进行定价。你会找到一些已经售出的房屋,并输入它们的面积等作为特征,以及它们的销售价格作为结果,然后运行带有这些数据的回归。你将在过程的另一端得到每平方英尺的价值、每个浴室的价值等。有了这些信息,你就可以开始预测市场上出现的新房屋的价格,这些房屋尚未售出。如果你的模型是可靠的,你会发现哪些房屋定价过高或过低!

这个库还处理逻辑回归,其中结果为布尔值。在这种情况下,回归将告诉你每个特征对结果概率的贡献程度,预测过程将为给定的新示例提供结果概率。

快速入门

一如既往,从 Composer 开始

composer require mcordingley/Regression

对于那些不能或不想在特定项目中使用 Composer 的人,你可以下载此库的副本,并运行 composer install,然后运行 php build-phar.php 来生成一个可以包含到你的项目中的 PHAR 归档。

运行回归的第一步是将你的数据加载到一个 Observations 对象中。这可以通过单个训练示例使用 $observations->add($exampleFeatures, $outcome); 或通过批量使用 Observations::fromArray($arrayOfExampleFeatures, $arrayOfOutcomes) 来完成。对于大多数用途,你将为每个训练示例在特征列表的开始处添加一个额外的特征。这将是一个数字 1.0,它代表 y 截距项。如果省略,回归线将强制通过原点。请注意,你也可以创建导出特征,如某些特征的平方或对数,如果其结果贡献是非线性的。

然后你可以创建一个 LeastSquares 实例,并在上面调用 regress,使用你的观察结果集合。根据数据集的大小,这可能需要一些时间来执行,但它将返回一个表示每个特征对结果相对影响的系数数组的数组。如果你为每个训练示例将 1.0 作为第一个特征,那么第一个系数将是 y 截距。将这些系数传递给一个 Predictor 对象,以立即开始预测新数据的结果,或将其存储以供以后使用。

警告:回归可能计算成本很高,尤其是如果你正在使用梯度下降。始终在离线运行回归,无论是作为夜间批量作业还是通过某些队列服务。预测很便宜,并且可以使用离线回归生成的系数在线进行。

整合一切

use MCordingley\Regression\Algorithm\LeastSquares;
use MCordingley\Regression\Observations;
use MCordingley\Regression\Predictor\Linear;

$observations = new Observations;

// Load the data
foreach ($data as $datum) {
    // Note addition of a constant for the first feature.
    $observations->add(array_merge([1.0], $datum->features), $datum->outcome);
}

$algorithm = new LeastSquares;
$coefficients = $algorithm->regress($observations);

$predictor = new Linear($coefficients);
$predictedOutcome = $predictor->predict(array_merge([1.0], $hypotheticalFeatures));

收集回归统计信息

对于线性回归,可以获取关于回归如何拟合数据的详细信息。这样做相对简单,最好在执行回归后立即进行。每个术语的含义以及如何解释它们的详细信息超出了本文档的范围,但Minitab博客上有一篇文章,提供了关于解释回归的良好起点。

use MCordingley\Regression\StatisticsGatherer\Linear;

$gatherer = new Linear($observations, $coefficients, $predictor);

$gatherer->getFStatistic(); // etc.

逻辑回归

逻辑回归是通过梯度下降实现的,具体细节如下。进行逻辑回归的关键是使用具有Logistic梯度的GradientDescent算法实例来执行回归。您的ScheduleStoppingCriteria应该选择以最好地匹配您的数据和所选的下降算法。

以下是一个示例,这是您的默认设置。此配置适用于大多数逻辑回归。请注意,在将特征输入之前,您需要对特征进行归一化。

use MCordingley\Regression\Algorithm\GradientDescent\Batch;
use MCordingley\Regression\Algorithm\GradientDescent\Schedule\Adam;
use MCordingley\Regression\Algorithm\GradientDescent\Gradient\Logistic as LogisticGradient;
use MCordingley\Regression\Algorithm\GradientDescent\StoppingCriteria\GradientNorm;
use MCordingley\Regression\Observations;
use MCordingley\Regression\Predictor\Logistic as LogisticPredictor;

$algorithm = new Batch(new LogisticGradient, new Adam, new GradientNorm);
$coefficients = $algorithm->regress(Observations::fromArray($features, $outcomes));

$predictor = new LogisticPredictor($coefficients);
$predictedOutcomeProbability = $predictor->predict($novelFeatures);

梯度下降

有时,最小二乘回归不是一个可行的选项。这可能会发生,如果数据集太大,无法在合理的时间内通过最小二乘法运行,或者在执行逻辑回归时,尽管可能有其他、更特殊的原因。在这些情况下,我们通过称为“梯度下降”的迭代数值过程找到一个近似解。组合一个有效的下降回归可能是一个复杂的过程,有许多不同的选项。以下详细说明了这些选项。

特征归一化

大多数情况下,您希望在将特征输入到Observations类之前对其进行归一化。这意味着改变您的数据,使每个特征的平均值为零,方差为1。直观地说,这“拉直”了下降过程的路径,导致对结果收敛得更快。有时,这可能是快速收敛和无法收敛的回归之间的区别。

虽然不需要将平均值和方差精确地调整为零和一,但将它们调整为这些值的数量级是有帮助的。例如,在梯度下降测试中,GRE分数被除以100,使其在零到十的范围内。布尔特征可以保持为0.01.0,因为这些值本身就非常接近。

可以通过此公式完全归一化特征:($value - $averageOfValue) / $standardDeviationOfValue,但如果计算标准差太麻烦,则可以使用($value - $averageOfValue) / ($maxOfValue - $minOfValue),效果相同。更多详情请参阅这篇博客文章

算法选择

目前,有三种主要的下降算法可供选择:BatchStochasticMiniBatchBatch将在每次迭代中遍历所有数据。这可能需要更长的时间,但会导致更稳定的下降过程,应该成为您的默认选择。Stochastic使用每个迭代中从训练数据中随机抽取的单个示例。对于非常大的数据集,这可能会比Batch过程更快地收敛,但缺点是每次迭代的噪声更大。MiniBatch是其他两种方法的结合,其中从训练数据集中随机抽取指定大小的随机批次。这导致每次迭代的稳定性略高于Stochastic,但仍然避免了每次迭代都要处理整个数据集。

《Adam》步长计划对所有梯度下降都是一个很好的默认设置。《GradientNorm》停止条件对于《Batch》下降效果良好。对于《Stochastic》和《MiniBatch》下降,收敛性要复杂得多。目前建议运行足够多的迭代次数,使下降接近收敛,然后使用《MaxIterations》停止。为了使下降在收敛时稳定,将您的下降计划包裹在《ExponentialDecay》中,为其比例提供与最大迭代次数相同的值。用于测试《Batch》的逻辑测试数据,在《Stochastic》下降和推荐计划下,在10,000,000次迭代后接近收敛。

当开始一个新的项目时,尝试不同的选项以找到最适合您数据的是很有帮助的。《DescentSpy》停止条件被提供以协助这个过程。它装饰另一个停止条件,并在委托给装饰的停止条件之前,在每次迭代时调用指定的回调。在GradientDescent测试文件夹中有一个此类使用的示例,其中使用了《DescentDebugger》特质来调整下降测试案例。

过拟合和正则化

回归可能选择系数,这些系数更准确地描述了训练数据,但以模型中相同过程的创新数据的准确性为代价。这被称为“过拟合”。有几种不同的方法可以对抗这种过拟合。一种方法是“交叉验证”,在这种方法中,将一部分训练数据保留在回归之外,并用于检查所得到的回归模型如何准确地描述创新数据。

另一种对抗过拟合的工具称为“正则化”,它涉及对每个系数构建一个与其偏离零的距离成比例的惩罚。《Regularized》类装饰另一个《Gradient》实例,并将此功能提供给梯度下降过程。将其构造函数中的1传递为L1正则化,或2为L2正则化。当找到一个既适用于L1又适用于L2正则化的优雅实现时,计划为LeastSquares实现正则化。

L2正则化将惩罚分散到系数上,对较大系数的惩罚比对较小系数的惩罚更重。这有助于减少整体过拟合,应作为默认选择。L1正则化对系数的大小一视同仁。这往往会使不必要的特征的系数降为零。

这些概念在MSDN上有更详细的讨论。向下滚动到“Understanding Regularization”。

扩展库

整个库是根据接口编写的,尽可能地将功能提取到协作对象中。这意味着您可以轻松地将自己的类替换提供的类。特别是,《Gradient》、《Schedule》和《StoppingCriteria》接口是扩展的预期点。如果您已经编写了一个您认为对他人有用的实现,请将其与伴随的测试一起以拉取请求的形式提交。

变更日志

2.2.0

  • 从《Observations》和《Observation》中提取接口。

2.1.0

  • 添加《InverseRootDecay》。
  • 添加《ExponentialDecay》。

2.0.0

  • 要求PHP 7.0或更高版本。
  • 要求LinearAlgebra版本2。
  • 大写命名空间。
  • 添加标量和返回类型提示。
  • 使《Observations》的设置器流畅。

1.1.0

  • 添加《Adam》更新计划。
  • 调整《RmpsProp》的默认值。
  • 添加《NthIteration》标准装饰器。
  • 添加《SteppedCriteria》标准装饰器。

1.0.0

  • 第一个稳定版本。