Skip to content

Instantly share code, notes, and snippets.

@emsifa
Last active November 27, 2022 07:21
Show Gist options
  • Save emsifa/ce2a6d2375a86d414c63ff8123c2db38 to your computer and use it in GitHub Desktop.
Save emsifa/ce2a6d2375a86d414c63ff8123c2db38 to your computer and use it in GitHub Desktop.
PHP Cosine Similarity untuk Sistem Rekomendasi

PHP Cosine Similarity untuk Sistem Rekomendasi

Catatan class PHP sederhana untuk menghitung cosine similarity yang diperuntukan untuk sistem rekomendasi guna mencari tahu seberapa besar kemiripan user A, dan user B berdasarkan rating pada produk yang mereka berikan.

Implementasi class disini dibuat berdasarkan video youtube: https://www.youtube.com/watch?v=BDJmJnrlaO8

Pada video youtube tersebut, data yang digunakan adalah seperti dibawah ini:

M1 M2 M3 M4 M5 M6
User A 3 5
User B 2 3 3 4
User C 5 4 4 5
User D 5 5 2 5 4

Jika diterapkan kedalam array $ratings, maka akan jadi seperti ini:

$ratings = [
    'User A' => [3, null, 5, null, null, null],
    'User B' => [2, 3, null, 3, 4, null],
    'User C' => [5, 4, 4, null, 5, null],
    'User D' => [5, 5, 2, null, 5, 4],
];

null berarti user belum melakukan rating terhadap film tersebut

Dengan data $ratings diatas, jika kita ingin mencari tahu berapa besar tingkat kesamaan User A dan User B, serta User A dan User C. Kita dapat menggunakan kode seperti dibawah ini:

$sim_ab = CosineSimilarity::calc($ratings['User A'], $ratings['User B']); // 0.1669244652224
$sim_ac = CosineSimilarity::calc($ratings['User A'], $ratings['User C']); // 0.66285976669375
<?php
class CosineSimilarity
{
protected $data_a;
protected $data_b;
public function __construct(array $data_a, array $data_b)
{
$this->data_a = $data_a;
$this->data_b = $data_b;
}
/**
* Mengambil nilai similaritas (kesamaan)
* Rentang hasil: 0 - 1
* Rumus: sum(ai * bi) / (root(sum(ai^2)) * root(sum(bi^2)))
*
* @return float
*/
public function calculate(): float
{
$top = $this->getTop();
$div = $this->getDivider();
return $top / $div;
}
/**
* Kalkulasi nilai atas (angka yang mau dibagi)
* Rumus: sum(ai * bi)
*
* @return float
*/
private function getTop(): float
{
$data_a = $this->data_a;
$data_b = $this->data_b;
$sum = 0;
foreach ($data_a as $i => $a) {
$b = isset($data_b[$i]) ? $data_b[$i] : null;
// Jika salah satu dari a atau b nilainya null ...
if (is_null($a) || is_null($b)) {
continue; // ... skip
}
$sum += $a * $b;
}
return $sum;
}
/**
* Kalkulasi nilai pembagi
* Rumus: root(sum(ai^2)) * root(sum(bi^2))
*
* @return float
*/
private function getDivider(): float
{
$data_a = $this->data_a;
$data_b = $this->data_b;
$root_sum_square_a = $this->rootSumSquares($data_a);
$root_sum_square_b = $this->rootSumSquares($data_b);
return $root_sum_square_a * $root_sum_square_b;
}
private function rootSumSquares(array $data): float
{
// Kalkulasi nilai kuadrat masing-masing item dari data
// [1, null, 2] -> [1, 0, 4] (null diubah jadi 0)
$squares = array_map(function($x) {
return is_null($x) ? 0 : $x * $x;
}, $data);
// Summary hasil kuadrat
// [1, 0, 4] -> 5
$sum_squares = array_sum($squares);
// Kembalikan akar dari summary
return sqrt($sum_squares);
}
/**
* Static function untuk menyederhanakan
* pemanggilan fungsi calculate tanpa harus
* inisiasi class terlebih dehulu
*
* @return float
*/
public static function calc(array $data_a, array $data_b): float
{
return (new static($data_a, $data_b))->calculate();
}
}
@imammufiid
Copy link

imammufiid commented Apr 16, 2021

Message: Too few arguments to function CosineSimilarity::__construct(), 0 passed

saya punya issue ketika saya pakai saya harus passing params di dalam constructor. case saya Cosine Similarity ini saya jadikan lib di Codeigniter. Mungkin ada solusi?

@emsifa
Copy link
Author

emsifa commented Apr 18, 2021

Message: Too few arguments to function CosineSimilarity::__construct(), 0 passed

saya punya issue ketika saya pakai saya harus passing params di dalam constructor. case saya Cosine Similarity ini saya jadikan lib di Codeigniter. Mungkin ada solusi?

Method __construct-nya diganti dengan nama lain, misal setData.
Di CI-nya setelah load library panggil method setData($data_a, $data_b), baru setelahnya panggil method calculate.

@sulkifli27
Copy link

sulkifli27 commented Oct 13, 2021

bagaimana jika ingin menambahkan string di dalam array tersebut dan melakukan perbandingan
? Terimakasih

@wahyu72122
Copy link

untuk mendapatkan nilai nya untuk penjumlahan bagaimana kak ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment