辅助正念/贝叶斯平均

贝叶斯平均是一种使用外部信息(尤其是预先存在的信念)来估计总体平均值的方法,这些信息将纳入计算。

1.0.0 2022-09-19 20:16 UTC

This package is auto-updated.

Last update: 2024-09-12 01:40:14 UTC


README

贝叶斯平均是一种使用外部信息(尤其是预先存在的信念)来估计总体平均值的方法,这些信息将纳入计算。要了解贝叶斯平均是否适合您,让我们看看两种排名星级的方法

  • 使用算术平均,将所有评分加在一起,然后除以评分总数。如果有100个一星级评分和10个五星级评分,计算方法是 ((100x1) + (10x5))/ (100+10) = 1.36。
  • 使用贝叶斯平均,通过调整产品平均评分与目录平均评分的差异来调整产品平均评分。这有利于评分数量更多的产品。如前所述,忽略评分数量并不能帮助区分10个评分和1000个评分的项目。您至少需要计算一个包含评分数量的平均值。

以下图像显示了按不同平均值排名的三件商品。左侧使用算术平均进行排名。右侧使用贝叶斯平均。

image

两侧都在星星的右侧括号中显示了算术平均。它们还分别在每个项目下显示了用于排名的平均值,分别标记为 avg_star_ratingbayes_avg

通过将项目A放在顶部,左侧的排名既具有误导性又令人不满意。右侧的排名,基于贝叶斯平均,反映了评分和评分数量的更好平衡。这个例子显示了贝叶斯平均如何将项目A的平均值降低到4.3,因为它将A的10个评分与B和C的更多评分进行比较。正如后面所描述的,贝叶斯平均使项目B和C保持不变,因为贝叶斯平均对评分数量较低的项目的影响比评分数量较多的项目更大。

总之,通过以这种方式相对化评分,贝叶斯平均在产品之间创建了一个更可靠的比较。它确保了评分数量较少的产品在排名中的权重较低。

理解贝叶斯平均

贝叶斯平均调整了评分数量低于阈值的产品的平均评分。假设阈值为100。这意味着具有少于100个评分的平均评分会进行调整,而具有多于100个评分的平均评分只会发生非常小的变化。这个100的阈值称为置信度数字,因为它给您提供了信心,即具有100个或更多评分的平均值比具有少于100个评分的平均值更可靠。

这个置信度数字来源于目录的评分数量分布和所有产品的平均评分。通过考虑整个目录的评分数量和平均值,贝叶斯平均对单个项目的平均评分有以下影响

  • 对于评分数量少于平均数量的项目,贝叶斯平均通过将其(稍微)降低到较低的目录平均值来降低其人为的高评分。
  • 对于评分很多的项目(即,超过阈值),贝叶斯平均不会对其评分平均产生显著变化。

安装

您可以使用Composer包管理器将贝叶斯平均方法安装到您的项目中。

composer require assisted-mindfulness/bayesian-average

用法

创建一个AssistedMindfulness\BayesianAverage\BayesianAverage类的实例。

// Item with a large number of ratings
$itemLargeRating = collect(range(0, 500))->transform(fn () => random_int(4, 5));
$itemLargeRatingAverage = $itemLargeRating->avg();
$itemLargeRatingCount = $itemLargeRating->count();

$c = 100; // Confidence number
$m = 3.5; // Catalog average

$bayes = new BayesianAverage();
$bayes
    ->setConfidenceNumber($c)
    ->setAverageRatingOfAllElements($m);

$bayes->getAverage($itemLargeRatingAverage, $itemLargeRatingCount); // ~4.3

可以通过以下方法之一设置置信度数值:

  • setConfidenceNumber(int|float $confidenceNumber):将传入的参数设置为置信度数值。
  • setConfidenceNumberForEvenOrOdd(int $count, callable $even, callable $odd):如果$count(元素数量)是偶数,将执行$even的结果设置为置信度数值;如果$count是奇数,置信度平均值将被设置为执行$odd的结果。

示例

以下以数组为例计算贝叶斯平均值。

$data = collect([
    [
        'name'          => "Item A",
        "ratings"       => [5, 4, 3, 4, 3, 2, 4, 3],
        'ratings_count' => 8,
    ],
    [
        'name'          => "Item B",
        "ratings"       => [4, 5, 5, 5, 5, 5, 5, 5, 4],
        'ratings_count' => 9,
    ],
    [
        'name'          => "Item C",
        "ratings"       => [5],
        'ratings_count' => 1,
    ],
]);

$allRatingsCount = $data->sum('ratings_count');
$sum = $data->sum(fn($item) => array_sum($item['ratings']));

$bayes = new BayesianAverage($allRatingsCount, $sum);

$bayes->setConfidenceNumber(1);

$average = array_sum($data[0]['ratings']) / count($data[0]['ratings']); // 3.5
$bayes_avg = $bayes->getAverage($average, count($data[0]['ratings'])); // 3.5802469135802 

请考虑使用setConfidenceNumberForEvenOrOdd方法。我们将设置下四分位数作为置信度数值。

$bayes = new BayesianAverage($allRatingsCount, $sum);

$bayes->setConfidenceNumberForEvenOrOdd($data->count(), function ($position) use ($data) {
    $item = $data->sortBy('ratings_count')->values()->get($position / 2);

    return $item['ratings_count'];
}, function ($position) use ($data) {
    $item1 = $data->sortBy('ratings_count')->values()->get(($position + 1) / 2);
    $item2 = $data->sortBy('ratings_count')->values()->get(($position - 1) / 2);

    return ($item1['ratings_count'] + $item2['ratings_count']) / 2;
});

$data->each(function ($item) use ($bayes, $sum, $allRatingsCount) {
    $average = array_sum($item['ratings']) / count($item['ratings']);
    $bayes_avg = $bayes->getAverage($average, count($item['ratings']));
    
    printf('Average = %s, Bayesian  average = %s', $average, $bayes_avg);
});

/*
 *Average = 3.5, Bayesian  average = 3.5802469135802 
 *Average = 4.7777777777778, Bayesian  average = 4.7222222222222 
 *Average = 5, Bayesian  average = 4.6111111111111 
 */

许可证

MIT许可证(MIT)。有关更多信息,请参阅许可证文件