PHP项目推荐算法如何简单代码实现

wen PHP项目 26

本文目录导读:

PHP项目推荐算法如何简单代码实现

  1. 基于用户行为的协同过滤(最简单)
  2. 基于内容的推荐(基于标签)
  3. 简单的热门推荐
  4. 组合推荐(混合推荐)
  5. 使用Redis实现实时推荐
  6. 数据库存储示例(MySQL)

我来介绍几种PHP推荐算法的简单实现方案:

基于用户行为的协同过滤(最简单)

<?php
class SimpleRecommend {
    private $userActions = [];
    // 记录用户行为
    public function recordAction($userId, $itemId, $action = 'view') {
        $this->userActions[$userId][$itemId] = ($this->userActions[$userId][$itemId] ?? 0) + 1;
    }
    // 获取协同推荐
    public function getRecommendations($userId, $limit = 5) {
        $similarUsers = $this->findSimilarUsers($userId);
        $recommendations = [];
        foreach ($similarUsers as $similarUserId => $similarity) {
            foreach ($this->userActions[$similarUserId] ?? [] as $itemId => $count) {
                // 排除用户已交互过的项目
                if (!isset($this->userActions[$userId][$itemId])) {
                    $recommendations[$itemId] = ($recommendations[$itemId] ?? 0) + $count * $similarity;
                }
            }
        }
        arsort($recommendations);
        return array_slice(array_keys($recommendations), 0, $limit);
    }
    // 查找相似用户(基于共同行为)
    private function findSimilarUsers($userId) {
        $userItems = $this->userActions[$userId] ?? [];
        $similarities = [];
        foreach ($this->userActions as $otherUserId => $items) {
            if ($otherUserId === $userId) continue;
            $common = array_intersect_key($userItems, $items);
            $similarity = count($common) / max(count($userItems), count($items), 1);
            if ($similarity > 0) {
                $similarities[$otherUserId] = $similarity;
            }
        }
        arsort($similarities);
        return $similarities;
    }
}
// 使用示例
$recommender = new SimpleRecommend();
$recommender->recordAction(1, 'article_1', 'like');
$recommender->recordAction(1, 'article_2', 'view');
$recommender->recordAction(2, 'article_1', 'like');
$recommender->recordAction(2, 'article_3', 'view');
$recommendations = $recommender->getRecommendations(1);
print_r($recommendations);
?>

的推荐(基于标签)

<?php
class ContentBasedRecommend {
    private $items = [];
    private $userPreferences = [];
    // 添加项目与标签
    public function addItem($itemId, $tags) {
        $this->items[$itemId] = $tags;
    }
    // 记录用户偏好
    public function recordPreference($userId, $itemId, $rating = 1) {
        $itemTags = $this->items[$itemId] ?? [];
        foreach ($itemTags as $tag) {
            $this->userPreferences[$userId][$tag] = 
                ($this->userPreferences[$userId][$tag] ?? 0) + $rating;
        }
    }
    // 获取内容推荐
    public function getRecommendations($userId, $limit = 5) {
        $preferences = $this->userPreferences[$userId] ?? [];
        $scores = [];
        foreach ($this->items as $itemId => $tags) {
            $score = 0;
            foreach ($tags as $tag) {
                $score += $preferences[$tag] ?? 0;
            }
            if ($score > 0) {
                $scores[$itemId] = $score / count($tags); // 归一化
            }
        }
        arsort($scores);
        return array_slice(array_keys($scores), 0, $limit);
    }
}
// 使用示例
$recommender = new ContentBasedRecommend();
$recommender->addItem('news_1', ['technology', 'ai', 'programming']);
$recommender->addItem('news_2', ['sports', 'football']);
$recommender->addItem('news_3', ['technology', 'startup']);
$recommender->recordPreference(1, 'news_1', 5);
$recommender->recordPreference(1, 'news_3', 3);
$recommendations = $recommender->getRecommendations(1);
print_r($recommendations);
?>

简单的热门推荐

<?php
class PopularRecommend {
    private $itemScores = [];
    private $userHistory = [];
    // 记录交互
    public function recordInteraction($userId, $itemId, $weight = 1) {
        $this->itemScores[$itemId] = ($this->itemScores[$itemId] ?? 0) + $weight;
        $this->userHistory[$userId][$itemId] = true;
    }
    // 带时间衰减的热门推荐
    public function getHotRecommendations($userId, $limit = 10, $days = 7) {
        $recommendations = [];
        $now = time();
        foreach ($this->itemScores as $itemId => $score) {
            // 排除用户已看过的
            if (isset($this->userHistory[$userId][$itemId])) {
                continue;
            }
            // 时间衰减
            $timeDecay = exp(-($now - $this->getItemTime($itemId)) / (86400 * $days));
            $recommendations[$itemId] = $score * $timeDecay;
        }
        arsort($recommendations);
        return array_slice(array_keys($recommendations), 0, $limit);
    }
    private function getItemTime($itemId) {
        // 实际项目中从数据库获取
        return time();
    }
}
// 使用示例
$recommender = new PopularRecommend();
$recommender->recordInteraction(1, 'video_1', 10);
$recommender->recordInteraction(1, 'video_2', 5);
$recommender->recordInteraction(2, 'video_1', 8);
$recommendations = $recommender->getHotRecommendations(1);
print_r($recommendations);
?>

组合推荐(混合推荐)

<?php
class HybridRecommend {
    private $contentBased;
    private $collaborative;
    private $popular;
    public function __construct() {
        $this->contentBased = new ContentBasedRecommend();
        $this->collaborative = new SimpleRecommend();
        $this->popular = new PopularRecommend();
    }
    // 组合推荐结果
    public function getHybridRecommendations($userId, $limit = 10) {
        $weights = [
            'content_based' => 0.4,
            'collaborative' => 0.3,
            'popular' => 0.3
        ];
        $scores = [];
        // 内容推荐
        $contentRecs = $this->contentBased->getRecommendations($userId, $limit * 2);
        foreach ($contentRecs as $index => $itemId) {
            $scores[$itemId] = ($scores[$itemId] ?? 0) + $weights['content_based'] * ($limit - $index);
        }
        // 协同推荐
        $collabRecs = $this->collaborative->getRecommendations($userId, $limit * 2);
        foreach ($collabRecs as $index => $itemId) {
            $scores[$itemId] = ($scores[$itemId] ?? 0) + $weights['collaborative'] * ($limit - $index);
        }
        // 热门推荐
        $popularRecs = $this->popular->getHotRecommendations($userId, $limit * 2);
        foreach ($popularRecs as $index => $itemId) {
            $scores[$itemId] = ($scores[$itemId] ?? 0) + $weights['popular'] * ($limit - $index);
        }
        arsort($scores);
        return array_slice(array_keys($scores), 0, $limit);
    }
}
?>

使用Redis实现实时推荐

<?php
class RedisRecommend {
    private $redis;
    public function __construct() {
        $this->redis = new Redis();
        $this->redis->connect('127.0.0.1', 6379);
    }
    // 使用Redis的Sorted Set实现
    public function recordAction($userId, $itemId, $score = 1) {
        $this->redis->zIncrBy("user:{$userId}:actions", $score, $itemId);
        $this->redis->zIncrBy("global:popular", $score, $itemId);
    }
    // 获取推荐
    public function getRecommendations($userId, $limit = 5) {
        // 获取用户行为历史
        $userActions = $this->redis->zRevRange("user:{$userId}:actions", 0, -1, true);
        // 获取全局热门
        $popular = $this->redis->zRevRange("global:popular", 0, $limit * 2, true);
        $recommendations = [];
        foreach ($popular as $itemId => $score) {
            if (!isset($userActions[$itemId])) {
                $recommendations[$itemId] = $score;
            }
            if (count($recommendations) >= $limit) break;
        }
        return array_keys($recommendations);
    }
}
?>

数据库存储示例(MySQL)

-- 用户行为表
CREATE TABLE user_actions (
    id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT NOT NULL,
    item_id VARCHAR(50) NOT NULL,
    action_type VARCHAR(20) NOT NULL, -- view, like, purchase
    weight DECIMAL(5,2) DEFAULT 1.00,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_user_item (user_id, item_id)
);
-- 项目标签表
CREATE TABLE item_tags (
    id INT AUTO_INCREMENT PRIMARY KEY,
    item_id VARCHAR(50) NOT NULL,
    tag VARCHAR(50) NOT NULL,
    weight DECIMAL(3,2) DEFAULT 1.00,
    INDEX idx_item (item_id)
);
-- 计算用户相似度查询
SELECT 
    ua2.user_id as similar_user,
    COUNT(*) as common_items,
    SUM(ua1.weight * ua2.weight) as score
FROM user_actions ua1
JOIN user_actions ua2 ON ua1.item_id = ua2.item_id AND ua1.user_id != ua2.user_id
WHERE ua1.user_id = 1
GROUP BY ua2.user_id
ORDER BY score DESC
LIMIT 5;

这些简单的实现适合小型项目快速上手,对于生产环境,建议考虑使用专门的推荐系统框架或使用MySQL+Redis的混合存储方案。

抱歉,评论功能暂时关闭!