推荐系统算法之基于邻域的算法

本文介绍了推荐系统中的基于邻域算法,包括基于用户的协同过滤和基于物品的协同过滤。这两种算法广泛应用于实际推荐系统,如亚马逊。协同过滤通过计算用户或物品之间的相似度来生成推荐。文中提供了PHP代码示例来解释算法的实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

     基于领域的算法是推荐系统中最基本的算法,该算法在实际应用中得到了广泛的应用,亚马逊的推荐算法就是采用基于领域的算法。基于领域的算法分为两大类,一类是基于用户的协同过滤算法,这种算法给用户推荐和他兴趣相似的其他用户喜欢的物品;另一类是基于物品的协同过滤算法,这种算法给用户推荐和他之前喜欢的物品相似的物品。

    实验所采用的数据集可以用GroupLens提供的MovieLens数据集。为了测试方便,这里暂时使用一个有10条记录的二维数组:

	$train=array(
							array(1,11),		//array(userid,itemid)
						 	array(1,12),
							array(1,14),
							array(2,11),
							array(2,13),
							array(3,12),
							array(3,15),
							array(4,13),
							array(4,14),
							array(4,15),
				);
      一、基于用户的协同过滤算法

该算法的主要步骤:

1、找到与该用户兴趣相似的用户集;

2、找到这个集合中的用户喜欢的但是没有听说过的物品推荐给目标用户。

用户的相似度可以用如下公式计算:


其中u,v表示两个用户,N(u)表示用户u曾经有过正反馈的物品集合;N(v)表示用户v曾经有过正反馈的物品集合。因为大多数用户的兴趣相似度可能位0,即|N(u)∩N(v)| = 0,所以我们可以建立一个物品到用户的倒排表:


实现该步骤的PHP代码:

	//计算相似度
	function userSimilarity($train){
		//建立物品列表
		$item_user=array();	//存放物品列表
		for($i=0;$i<count($train);$i++){
			$item=$train[$i][1];
			$user=$train[$i][0];
			$item_user[$item][]=$user;
		}	
		
		$N=array();	//$N[u]表示用户u使用过的物品总数
		$C=array();	//C[u][v]=|N(u)∩N(u)|
		foreach($item_user as $user){
			for($i=0;$i<count($user);$i++){
				$N[$user[$i]]+=1;
				for($j=0;$j<count($user);$j++){
					if($user[$i]!=$user[$j]){
						$C[$user[$i]][$user[$j]]+=1;
					}
				}
			}
		}
		
		$W=array();	//$W[u][v]表示用户u和用户v的相似度
		foreach($C as $key=>$value){
			$u=$key;	//用户u
			foreach($value as $v=>$cuv){
				$W[$u][$v]=$cuv/sqrt($N[$u]*$N[$v]);
			}
		}
		
		return $W;
	}
最后我们就可以给用户推荐和他兴趣相似的其他用户喜欢的物品:


其中,P(u,i)是用户u对物品i的感兴趣程度,S(u,k)包含和用户兴趣最接近的K个用户,N(i)是对物品i有过行为的用户集合Wuv是用户u和v的兴趣相似度,Rvi代表用户v对物品i的兴趣,因为使用的是单一的隐反馈数据,所以所有的Rvi=1.

实现上面UserCF算法的PHP代码如下:

	//推荐算法
	function recommend($user,$train,$W){
		$rank=array();	//用户对物品的感兴趣程度
		
		for($i=0;$i<count($train);$i++){
			if($train[$i][0]==$user){
				//用户使用过的物品集合
				$interacted_items[]=$train[$i][1];
			}
		}
		
		$group=$W[$user];	//和用户兴趣相似的其他用户
		arsort($group);
		$count=0;	//计算器
		$K=3;	//和用户最接近的K个用户
		foreach($group as $v=>$wuv){
			$count++;
			for($i=0;$i<count($train);$i++){
				if($train[$i][0]==$v&&!in_array($train[$i][1], $interacted_items)){
					$rank[$train[$i][1]]+=$wuv;
				}
			}	
			
			if($count==$K) break;
		}
		
		return $rank;
	}
最后使用如下代码测试(即给id为1的用户推荐物品):

    $W=userSimilarity($train);
	print_r(recommend(1,$train,$W));
	/*
	 * 显示
	Array
	(
	    [13] => 0.7415816237972
	    [15] => 0.7415816237972
	)
	 */
推荐系统会给用户推荐物品id为13、15号的物品,用户1对它们的感兴趣程度都是0.7416.

 二、基于物品的协同过滤算法

基于物品的协同过滤(item-based collaborative filtering)算法是目前使用最多的算法。亚马逊、Netflix、Hulu、Youtube的推荐算法基础都是该算法。基于物品的协同过滤算法主要分为两步:

1、计算物品间的相似度;

2、根据物品的相似度和用户的历史行为给用户生成推荐列表。

和基于用户的协同过滤算法相似,我们也需要建立一个用户倒物品的倒排表,物品i和物品j的相似度可以用同时喜欢物品i和j的用户数,即|N(i)∩N(j)|,除以√|N(i)||N(j)|.并且计算用户u对一个物品i的感兴趣程度也和基于用户的协同过滤算法类似,所有的代码如下:

<?php 
	//ItemCF
	error_reporting(E_ALL&&~E_NOTICE);
	$train=array(
			array(1,11),		//array(userid,itemid)
			array(1,12),
			array(1,14),
			array(2,12),
			array(2,13),
			array(2,15),
			array(3,13),
			array(3,14),
			array(4,12),
			array(4,13),
			array(4,14),
			array(5,11),
			array(5,14),
	);
	
	//计算相似度
	function itemSimilarity($train){
		//建立用户到物品倒排表
		$user_item=array();	
		for($i=0;$i<count($train);$i++){
			$item=$train[$i][1];
			$user=$train[$i][0];
			$user_item[$user][]=$item;
		}
		
		$N=array();	//$N[i]表示喜欢物品i的用户数
		$C=array();	//C[i][j]=|N(i)∩N(j)|
		foreach($user_item as $item){
			for($i=0;$i<count($item);$i++){
				$N[$item[$i]]+=1;
				for($j=0;$j<count($item);$j++){
					if($item[$i]!=$item[$j]){
						$C[$item[$i]][$item[$j]]+=1;
					}
				}
			}
		}
		
		$W=array();	//$W[i][j]表示物品i和物品j的相似度
		foreach($C as $key=>$value){
			$i=$key;	//物品i
			foreach($value as $j=>$cij){
				$W[$i][$j]=$cij/sqrt($N[$i]*$N[$j]);
			}
		}
		return $W;
	}
	
	//推荐算法
	function recommend($train,$user_id,$W,$K){
		$rank=array();	//用户对物品的感兴趣程度
		//用户到物品倒排表,和itemSimilarity的重复,以后可以考虑合并或更换训练集的数据结构
		$user_item=array();
		for($i=0;$i<count($train);$i++){
			$item=$train[$i][1];
			$user=$train[$i][0];
			$user_item[$user][]=$item;
		}
		$ru=$user_item[$user_id];	//用户喜欢的物品集合
		foreach($ru as $i){
			//$W[$i]表示和物品i相似的其他物品集合
			arsort($W[$i]);
			$count=0;	//计数器
			foreach($W[$i] as $j=>$wij){
				$count++;
				if(!in_array($j, $ru)){
					$rank[$j]+=$wij;
				}
				
				if($count==$K) break;
			}
		}

		return $rank;
	}
	
	$W=itemSimilarity($train);
	print_r(recommend($train,1,$W,3));
?>



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值