Created
February 3, 2016 02:42
-
-
Save diegopso/d41cea26f64667138b0f to your computer and use it in GitHub Desktop.
Content-Based Recommendation PHP (based on http://www.codediesel.com/php/item-based-collaborative-filtering-php/)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* PHP item based filtering | |
* | |
* This library is distributed in the hope that it will be useful, | |
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
* Lesser General Public License for more details. | |
* | |
* @package PHP item based filtering | |
*/ | |
class ContentBasedRecommend extends Recommend | |
{ | |
const USER_ID = '__USER__'; | |
protected $data; | |
function __construct($user, $objects) | |
{ | |
$this->data[self::USER_ID] = $this->processUser($user); | |
$this->data = array_merge($this->data, $this->processObjects($objects)); | |
} | |
public function getRecommendation() | |
{ | |
$result = []; | |
foreach ($this->data as $k => $v) { | |
if($k !== self::USER_ID) { | |
$result[$k] = $this->similarityDistance($this->data, self::USER_ID, $k); | |
} | |
} | |
arsort($result); | |
return $result; | |
} | |
protected function processUser($user) | |
{ | |
$result = []; | |
foreach ($user as $tag) { | |
$result[$tag] = 1.0; | |
} | |
return $result; | |
} | |
protected function processObjects($objects) | |
{ | |
$result = []; | |
foreach ($objects as $object => $tags) { | |
foreach ($tags as $tag) { | |
$result[$object][$tag] = 1.0 ; | |
} | |
} | |
return $result; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* PHP item based filtering | |
* | |
* This library is distributed in the hope that it will be useful, | |
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
* Lesser General Public License for more details. | |
* | |
* @package PHP item based filtering | |
*/ | |
require_once 'recommend.php'; | |
require_once 'content_based.php'; | |
$objects = [ | |
'The Matrix' => ['Action', 'Sci-Fi'], | |
'Lord of The Rings' => ['Adventure', 'Drama', 'Fantasy'], | |
'Batman' => ['Action', 'Drama', 'Crime'], | |
'Fight Club' => ['Drama'], | |
'Pulp Fiction' => ['Drama', 'Crime'], | |
'Django' => ['Drama', 'Western'], | |
]; | |
$user = ['Drama', 'Crime']; | |
$engine = new ContentBasedRecommend($user, $objects); | |
var_dump($engine->getRecommendation()); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* PHP item based filtering | |
* | |
* This library is distributed in the hope that it will be useful, | |
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
* Lesser General Public License for more details. | |
* | |
* @package PHP item based filtering | |
*/ | |
class Recommend { | |
public function similarityDistance($preferences, $person1, $person2) | |
{ | |
$similar = array(); | |
$sum = 0; | |
$alpha = 0; | |
$beta = 0; | |
foreach($preferences[$person2] as $key=>$value) | |
{ | |
$alpha += $preferences[$person2][$key] * $preferences[$person2][$key]; | |
} | |
foreach($preferences[$person1] as $key=>$value) | |
{ | |
$beta += $preferences[$person1][$key] * $preferences[$person1][$key]; | |
if(array_key_exists($key, $preferences[$person2])) { | |
$sum += $preferences[$person2][$key] * $preferences[$person1][$key]; | |
} | |
} | |
if($alpha === 0 || $beta === 0) | |
return 0; | |
return $sum / sqrt($alpha) / sqrt($beta); | |
} | |
public function matchItems($preferences, $person) | |
{ | |
$score = array(); | |
foreach($preferences as $otherPerson=>$values) | |
{ | |
if($otherPerson !== $person) | |
{ | |
$sim = $this->similarityDistance($preferences, $person, $otherPerson); | |
if($sim > 0) | |
$score[$otherPerson] = $sim; | |
} | |
} | |
array_multisort($score, SORT_DESC); | |
return $score; | |
} | |
public function transformPreferences($preferences) | |
{ | |
$result = array(); | |
foreach($preferences as $otherPerson => $values) | |
{ | |
foreach($values as $key => $value) | |
{ | |
$result[$key][$otherPerson] = $value; | |
} | |
} | |
return $result; | |
} | |
public function getRecommendations($preferences, $person) | |
{ | |
$total = array(); | |
$simSums = array(); | |
$ranks = array(); | |
$sim = 0; | |
foreach($preferences as $otherPerson=>$values) | |
{ | |
if($otherPerson != $person) | |
{ | |
$sim = $this->similarityDistance($preferences, $person, $otherPerson); | |
} | |
if($sim > 0) | |
{ | |
foreach($preferences[$otherPerson] as $key=>$value) | |
{ | |
if(!array_key_exists($key, $preferences[$person])) | |
{ | |
if(!array_key_exists($key, $total)) { | |
$total[$key] = 0; | |
} | |
$total[$key] += $preferences[$otherPerson][$key] * $sim; | |
if(!array_key_exists($key, $simSums)) { | |
$simSums[$key] = 0; | |
} | |
$simSums[$key] += $sim; | |
} | |
} | |
} | |
} | |
foreach($total as $key=>$value) | |
{ | |
$ranks[$key] = $value / $simSums[$key]; | |
} | |
array_multisort($ranks, SORT_DESC); | |
return $ranks; | |
} | |
} |
what method you use to find similarityDistance?
What calculation was used to calculate the similarity distance in this code?
Never received a notification about this '^^
For anyone in the future, I used Cosine.
Hi, can I know what does it mean by
$result[$object][$tag] = 1.0
1.0 for what?
Thank You.
@nrlsyhmina If I still remember, the idea is that to represent an object X with the tags a, b, and d, in a universe with the tags a, b, c, d, and e, I put one for the tags that my object has and zero for the rest. So X = (1,1,0,1,0). Somewhere else I check if the key exists and, if not, I put a zero.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
hei, what metode did u use for find similarity, i think that not eucledian in return