Maison  >  Article  >  développement back-end  >  Implémentation de l'algorithme de filtrage collaboratif php+mysql

Implémentation de l'algorithme de filtrage collaboratif php+mysql

巴扎黑
巴扎黑original
2017-08-15 09:29:122476parcourir

Pour mettre en œuvre l'algorithme de recommandation de filtrage collaboratif, vous devez d'abord comprendre l'idée centrale et le processus de l'algorithme. L'idée centrale de cet algorithme peut être résumée comme suit : si a et b aiment la même série d'éléments (appelons b un voisin pour l'instant), alors a est susceptible d'aimer d'autres éléments que b aime. Le processus de mise en œuvre de l'algorithme peut être simplement résumé comme suit : 1. Déterminer les voisins d'un 2. Utiliser les voisins pour prédire le type d'articles qu'un pourrait aimer. 3. Recommander les éléments qu'un pourrait aimer à un.

La formule de base de l'algorithme est la suivante :

1. Similitude cosinus (trouver des voisins) :

Implémentation de lalgorithme de filtrage collaboratif php+mysql

2. . Formule de prédiction (Prédire le type d'articles qu'un objet pourrait aimer) :

Implémentation de lalgorithme de filtrage collaboratif php+mysql

À partir de ces deux formules seules, nous pouvons voir que le simple calcul selon ces deux formules nécessite un calcul. beaucoup de boucles et de jugement, et cela implique également des problèmes de tri, ce qui implique la sélection et l'utilisation d'algorithmes de tri. Ici, je choisis le tri rapide, je copie une section de tri rapide à partir d'Internet et je l'utilise directement. Bref, c'est très compliqué à mettre en œuvre, sans parler de l'efficacité dans le cas du big data.

Créez d'abord un tableau :

DROP TABLE IF EXISTS `tb_xttj`;
CREATE TABLE `tb_xttj` (
  `name` varchar(255) NOT NULL,
  `a` int(255) default NULL,
  `b` int(255) default NULL,
  `c` int(255) default NULL,
  `d` int(255) default NULL,
  `e` int(255) default NULL,
  `f` int(255) default NULL,
  `g` int(255) default NULL,
  `h` int(255) default NULL,
  PRIMARY KEY  (`name`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

INSERT INTO `tb_xttj` VALUES ('John', '4', '4', '5', '4', '3', '2', '1', null);
INSERT INTO `tb_xttj` VALUES ('Mary', '3', '4', '4', '2', '5', '4', '3', null);
INSERT INTO `tb_xttj` VALUES ('Lucy', '2', '3', null, '3', null, '3', '4', '5');
INSERT INTO `tb_xttj` VALUES ('Tom', '3', '4', '5', null, '1', '3', '5', '4');
INSERT INTO `tb_xttj` VALUES ('Bill', '3', '2', '1', '5', '3', '2', '1', '1');
INSERT INTO `tb_xttj` VALUES ('Leo', '3', '4', '5', '2', '4', null, null, null);

Je recommanderai uniquement Léo dans la dernière rangée pour voir lequel de f, g et h peut lui être recommandé.

En utilisant php+mysql, l'organigramme est le suivant :


Le code pour se connecter à la base de données et le stocker sous un tableau bidimensionnel est le suivant :

header("Content-Type:text/html;charset=utf-8");

mysql_connect("localhost","root","admin");
mysql_select_db("geodatabase");
mysql_query("set names 'utf8'");	

$sql = "SELECT * FROM tb_xttj";
$result = mysql_query($sql);

$array = array();
while($row=mysql_fetch_array($result))
{
	$array[]=$row;//$array[][]是一个二维数组
}

Question 1 : Cette étape peut être considérée comme une requête de table entière. Ce type de requête est tabou. un petit système de démonstration, mais pour un grand système de données est inefficace Quant à la manière de l'améliorer, nous devons encore en apprendre davantage.

Le code pour trouver la valeur Cos du Lion et des autres est le suivant :

/*
 * 以下示例只求Leo的推荐,如此给变量命名我也是醉了;初次理解算法,先不考虑效率和逻辑的问题,主要把过程做出来
 */

$cos = array();
$cos[0] = 0;
$fm1 = 0;
//开始计算cos
//计算分母1,分母1是第一个公式里面 “*”号左边的内容,分母二是右边的内容
for($i=1;$i<9;$i++){
	if($array[5][$i] != null){//$array[5]代表Leo
		$fm1 += $array[5][$i] * $array[5][$i];
	}
}

$fm1 = sqrt($fm1);

for($i=0;$i<5;$i++){
	$fz = 0;
	$fm2 = 0;
	echo "Cos(".$array[5][0].",".$array[$i][0].")=";
	
	for($j=1;$j<9;$j++){
	    //计算分子
		if($array[5][$j] != null && $array[$i][$j] != null){
			$fz += $array[5][$j] * $array[$i][$j];
		}
		//计算分母2
		if($array[$i][$j] != null){
			$fm2 += $array[$i][$j] * $array[$i][$j];
		}			
	}
	$fm2 = sqrt($fm2);
	$cos[$i] = $fz/$fm1/$fm2;
	echo $cos[$i]."<br/>";
}
Le résultat de cette étape est Jiang Zi :

Triez les valeurs Cos obtenues et utilisez le code de tri rapide comme suit (copié depuis Baidu) :

//对计算结果进行排序,凑合用快排吧先
function quicksort($str){
	if(count($str)<=1) return $str;//如果个数不大于一,直接返回
	$key=$str[0];//取一个值,稍后用来比较;
	$left_arr=array();
	$right_arr=array();
	
	for($i=1;$i<count($str);$i++){//比$key大的放在右边,小的放在左边;
		if($str[$i]>=$key)
		$left_arr[]=$str[$i];
		else
		$right_arr[]=$str[$i];
	}
	$left_arr=quicksort($left_arr);//进行递归;
	$right_arr=quicksort($right_arr);
	return array_merge($left_arr,array($key),$right_arr);//将左中右的值合并成一个数组;
}

$neighbour = array();//$neighbour只是对cos值进行排序并存储
$neighbour = quicksort($cos);

Le Le tableau $neighbour ici stocke uniquement les valeurs Cos triées de grand à petit ne sont pas liées aux personnes. Ce problème doit encore être résolu.

Sélectionnez les 3 personnes avec les valeurs CoS les plus élevées comme voisins de Leo :

//$neighbour_set 存储最近邻的人和cos值
$neighbour_set = array();
for($i=0;$i<3;$i++){
	for($j=0;$j<5;$j++){
		if($neighbour[$i] == $cos[$j]){
			$neighbour_set[$i][0] = $j;
			$neighbour_set[$i][1] = $cos[$j];
			$neighbour_set[$i][2] = $array[$j][6];//邻居对f的评分
			$neighbour_set[$i][3] = $array[$j][7];//邻居对g的评分
			$neighbour_set[$i][4] = $array[$j][8];//邻居对h的评分
		}
	}
}
print_r($neighbour_set);
echo "<p><br/>";

Le résultat de cette étape est Jiang Zi :


Il s'agit d'un tableau bidimensionnel. Les indices du premier niveau du tableau sont 0, 1 et 2, représentant 3 personnes. L'indice de deuxième niveau 0 représente l'ordre des voisins dans la table de données, par exemple, Jhon est la 0ème personne dans la table ; l'indice 1 représente la valeur Cos de Leo et l'indice 2, 3 et 4 ; représentent respectivement la paire voisine f et g , h rating.

Démarrer la prédiction. Le code de calcul pour Predict est le suivant :

Je calcule les valeurs prédites de Leo pour f, g, h respectivement. Il y a ici un problème, c'est-à-dire comment le résoudre si certains voisins ont des scores vides pour f, g, h. Par exemple, les évaluations de Jhon et Mary pour h sont vides. Instinctivement, j'ai pensé à utiliser if pour juger, et s'il est vide, ignorer cet ensemble de calculs, mais reste à déterminer si cela est raisonnable. Le code suivant n'écrit pas ceci en cas de jugement.

//计算Leo对f的评分
$p_arr = array();
$pfz_f = 0;
$pfm_f = 0;
for($i=0;$i<3;$i++){
	$pfz_f += $neighbour_set[$i][1] * $neighbour_set[$i][2];
	$pfm_f += $neighbour_set[$i][1];
}
$p_arr[0][0] = 6;
$p_arr[0][1] = $pfz_f/sqrt($pfm_f);
if($p_arr[0][1]>3){
	echo "推荐f";
}

//计算Leo对g的评分
$pfz_g = 0;
$pfm_g = 0;
for($i=0;$i<3;$i++){
	$pfz_g += $neighbour_set[$i][1] * $neighbour_set[$i][3];
	$pfm_g += $neighbour_set[$i][1];
	$p_arr[1][0] = 7;
	$p_arr[1][1] = $pfz_g/sqrt($pfm_g);
}
if($p_arr[0][1]>3){
	echo "推荐g";
}

//计算Leo对h的评分
$pfz_h = 0;
$pfm_h = 0;
for($i=0;$i<3;$i++){
	$pfz_h += $neighbour_set[$i][1] * $neighbour_set[$i][4];
	$pfm_h += $neighbour_set[$i][1];
	$p_arr[2][0] = 8;
	$p_arr[2][1] = $pfz_h/sqrt($pfm_h);
}
print_r($p_arr);
if($p_arr[0][1]>3){
	echo "推荐h";
}

$p_arr est le tableau recommandé pour Leo, son contenu est similaire à ce qui suit ;

Array ( [0] => Array ( [0] => ; 6 [ 1] => 4.2314002228795 ) [1] => Tableau ( [0] => 8 [1 ] => ; 0.45287424581774 ) )

f est la 6ème colonne, la valeur de prédiction est 4,23, g est la septième colonne, la valeur de prédiction est 2,65...

Après avoir calculé les valeurs Predict de f, g, h, il existe deux méthodes de traitement : l'une consiste à recommander au Lion les éléments avec des valeurs Predict supérieures à 3, l'autre consiste à trier les valeurs Predict du grand au petit, et Les 2 premiers éléments avec la valeur la plus élevée sont recommandés au Lion. Ce code n'a pas été écrit.

Comme le montre l'exemple ci-dessus, la mise en œuvre de l'algorithme de recommandation est très gênante, nécessitant du bouclage, du jugement, une fusion de tableaux, etc. S’il n’est pas géré correctement, cela deviendra un fardeau pour le système. Il existe toujours les problèmes suivants dans le traitement réel :

1 Dans l'exemple ci-dessus, nous recommandons uniquement Leo, et nous savons déjà que Leo n'a pas évalué les éléments f, g, h. Dans un système réel, pour chaque utilisateur qui doit faire une recommandation, il est nécessaire de découvrir quels éléments il n'a pas évalués, ce qui représente une autre partie des frais généraux.

2. L'intégralité de la requête de table ne doit pas être effectuée dans le système actuel, certaines valeurs standard peuvent être définies. Par exemple : On retrouve la valeur Cos entre Lion et les autres personnes dans le tableau. Si la valeur est supérieure à 0,80, cela signifie qu'ils peuvent être voisins. De cette façon, lorsque je trouve 10 voisins, j'arrête de calculer la valeur Cos pour éviter d'interroger la table entière. Cette méthode peut également être utilisée de manière appropriée pour les éléments recommandés. Par exemple, je recommande uniquement 10 éléments et j'arrête de calculer la valeur de prévision après les avoir recommandés.

3. Au fur et à mesure que le système est utilisé, les éléments changeront également. Aujourd'hui, c'est fgh, et demain, ce sera peut-être xyz. Lorsque les éléments changent, la table de données doit être modifiée dynamiquement.

4. Des recommandations basées sur le contenu peuvent être introduites de manière appropriée pour améliorer l'algorithme de recommandation.

5. Problèmes de précision recommandés. La définition de différentes valeurs standard affectera la précision.

Résumé : Je pense que le problème essentiel est que l'efficacité de l'algorithme n'est pas élevée. Continuez à étudier et voyez s'il existe un meilleur algorithme de recommandation de filtrage collaboratif.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn