基于余玄相似度的产品相似度推荐算法-PHP版

<?php

declare(strict_types=1);

namespace App\Common\Algorithm;

use Exception;

/**
*@author guicheng
*@visit www.mxreality.cn
*/
class AlgorithmSimilarity
{
    /**
     * 计算两个值之间的分数 1 / (abs($v2 - $v1) / $divide)
     *
     * @param $v1
     * @param $v2
     * @param boolean $equal 强相关参数,为true时只有0/1两种返回结果
     * @param integer $divide $v1和$v2差距敏感度,大于0的整数, 得分与该数值成正比
     * @return float 分数$score[0-1]
     */
    function calcScore($v1, $v2, bool $equal = false, int $divide = 1): float
    {
        if ($divide <= 0) {
            throw new Exception('敏感度参数不能小于0');
        }
        if ($v1 == $v2) {
            return 1;
        }
        $sub = abs($v2 - $v1);
        if ($sub < $divide) {
            return 1;
        }
        $score = 1 / ($sub / $divide);
        if ($equal && $score) {
            return 0;
        }
        return $score;
    }

    /**
     * 余玄相似度
     *
     * 设A、B为多维矩阵
     *
     *          ∑(Ai•Bi)            ∑(Ai•Bi)            ∑(USER1_i•USER2_i)
     * cos∂ = --------------- = -----------------  =  -------------------------
     *          |Ai|•|Bi|          √∑ Ai² • √∑ Bi²     √∑ USER1_i² • √∑ USER2_i²
     *
     * @param array $item1 项目1评分数组,eg:['1','3','4','5','1']
     * @param array $item2 项目2评分数组,eg:['2','2','4','5','1']
     * 
     * @return string 两个项目相似度
     */
    function calcSimilarity(array $item1, array $item2): float
    {
        $sumAiBi = '0';
        $sumAi   = '0';
        $sumBi   = '0';
        $len     = count($item1);

        if (count($item1) != count($item2)) {
            throw new Exception('相似计算两组评分结构不一致');
        }

        for ($i = 0; $i < $len; $i++) {
            //∑(Ai•Bi)
            $sumAiBi += $item1[$i] * $item2[$i];

            //∑USER1_i
            $sumAi += pow($item1[$i], 2);

            //∑USER2_i
            $sumBi += pow($item2[$i], 2);
        }
        return $sumAiBi / (sqrt($sumAi) * sqrt($sumBi));
    }
}

使用方法

<?php

/**
*
* @params $goods 被计算评分的数据列表
* @params $target 计算评分的商品 
*
*/
function test($goods,$target){
    foreach ($goods as $item) {
        $scores = [
            $algorithm->calcScore($item->getType(), $target->getType(), true), //类目评分,强相关,一致则评分最高1,不一致评分最低0
            $algorithm->calcScore($item->getCity(), $target->getCity(), true), //区域评分,强相关,区域id一致则评分最高1,不一致评分为0
            $algorithm->calcScore($item->getPrice(), $target->getPrice(), false, 10), //价格评分,10元为基准点,差距越大评分越低
            $algorithm->calcScore($item->getCreateAt(), time(), false, 2 * 24 * 60 * 60), //创建时间相关评分,以2天为基准点,越晚评分越低
            $algorithm->calcScore($item->badRate(),$target->badRate(),false,0.6) // 产品合格率评分
         ];
         // 最高基准评分
         $expectations = [1, 1, 1, 1, 1];
         // 得到该商品对于我的评分
         $score = $algorithm->calcSimilarity($scores, $expectations);
         // 保存产品ID,用户ID和对应的评分,避免实时计算
         $recommendModel->updateOrCreate($userId, $item->getId(), $score);
    }
}

欢迎大家批评指正!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_________MAN

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值