mr4-lc / recommendation
Laravel 推荐包
0.0.1
2023-12-21 02:50 UTC
Requires
- php: >=7.0.0
- halaxa/json-machine: ^1.0
- mr4-lc/php-json-exporter: ^0.0
Requires (Dev)
- phpunit/phpunit: >=6.0
README
相似度汉明(Hamming)是衡量两个二进制字符串之间距离的一种方法,通过计算它们之间不同位的数量。例如,1011和1101之间的汉明相似度为2,因为它们在第二位和第三位上有两个不同的位。计算汉明相似度的算法非常简单,只需比较两个二进制字符串的每个位,如果不同则增加计数器。=> 用于计算特征的相似度。
欧几里得相似度(Euclidean similarity)是衡量多维空间中两点之间距离的一种方法,通过计算它们坐标差的平方和的平方根。例如,点A(1, 2)和B(4, 6)之间的欧几里得相似度为√[(4−1)²+(6−2)²]=√25=5。计算欧几里得相似度的算法非常简单,只需应用以下公式:d(A,B)=∑i=1n(Ai−Bi)²,其中d(A,B)是点A和B之间的欧几里得相似度,n是空间的维度,Ai和Bi是点A和B在第i维上的坐标。=> 用于计算价格的相似度。
Jaccard相似度(Jaccard similarity)是衡量两个集合之间相似度的一种方法,通过将共同元素的数量除以不同元素的总数。例如,集合A = {1, 2, 3}和B = {2, 3, 4}之间的Jaccard相似度为2/4 = 0.5,因为它们有两个共同元素2和3,以及四个不同元素1, 2, 3, 4。计算Jaccard相似度的算法非常简单,只需应用以下公式:J(A,B)=|A∪B|/|A∩B|,其中J(A,B)是集合A和B之间的Jaccard相似度,|A∩B|是A和B的共同元素数量,|A∪B|是A和B的不同元素数量。=> 用于计算类别的相似度。
安装
composer require mr4-lc/recommendation php artisan vendor:publish --tag=mr4-lc-recommendation --force
配置
return [ 'featureWeight' => 1, 'categoryWeight' => 1, 'priceWeight' => 1, 'priceHighRange' => 1000, 'chunkSize' => 1000, 'perPage' => 5, 'output' => storage_path('app/private/recommendation/data'), 'mapping' => [ 'tables' => [ // Sample config 'table_name' => [ 'data_version' => '0.0.1', 'output' => 'table_name.json', // SQL WHERE condition 'status' => [ 'status' => 1, ], // SQL ORDER BY 'order' => 'id', // Customize model response 'model' => \App\Models\SomeModel::class, // Load relatíonhip 'model_with' => ['tags'], // Customize similarity 'class' => \App\Similarities\PostSimilarity::class, 'map' => [ 'id' => 'id', 'price' => 'price', 'categories' => ['categories', 'group'], // Array or string column name, 'features' => ['color', 'type'], // Array or string column name, ], 'map_type' => [ 'categories' => 'merge', // String data 'features' => 'object', // Object data ], ], ], ], ];
namespace App\Similarities; use Mr4Lc\Recommendation\Similarity\Similarity; class PostSimilarity extends \Mr4Lc\Recommendation\Similarity\ItemSimilarity { protected function calculateSimilarityScore($productA, $productB) { $productAFeatures = implode('', get_object_vars($productA->features)); $productBFeatures = implode('', get_object_vars($productB->features)); return array_sum([ (Similarity::hamming($productAFeatures, $productBFeatures) * $this->featureWeight), (Similarity::jaccard($productA->categories, $productB->categories) * $this->categoryWeight) ]) / ($this->featureWeight + $this->categoryWeight); } public static function GetSimilarityPosts($product_id, $page = null, $perPage = null, $pagePrefix = 'page') { $products = static::GetSimilarityItems('posts', $product_id, $page, $perPage, $pagePrefix); return $products; } }
使用
创建矩阵
php artisan recommendation:export {tableName} {--chunkSize=}
创建相似度(运行时间较长,运行时请注意)
php artisan recommendation:create {tableName} {--id=}
<script> function buildView (response, container, ctrl, perPage, pagePrefix) { const items = document.createElement('div') items.className = 'items' response.data.forEach(element => { const div = document.createElement('div') div.className = 'item' if (element.name) { const name = document.createElement('div') name.className = 'name' name.innerHTML = element.name div.appendChild(name) } if (element.images) { const images = JSON.parse(element.images) if (images && images.length > 0) { const img = document.createElement('img') img.src = location.origin + '/public/' + images[0] img.className = 'thumbnail' div.appendChild(img) } } items.appendChild(div) }); container.appendChild(items) const pagination = document.createElement('div') pagination.className = 'pagination' response.links.forEach(element => { const button = document.createElement('button') button.innerHTML = element.label button.className = element.active ? '' : 'inactive' pagination.appendChild(button) const urlParams = new URLSearchParams(element.url) const selectPage = urlParams.get(pagePrefix) button.onclick = () => { LoadRecommendation(ctrl, selectPage, perPage, pagePrefix) } }) container.appendChild(pagination) } </script> <x-mr4-lc.recommendation itemName='wines' itemId='1' apiUrl='http://127.0.0.1:8000/api/recommendation' builder="buildView" />
<x-mr4-lc.recommendation itemName='wines' itemId='1' apiUrl='http://127.0.0.1:8000/api/recommendation' />
控制器
$fields = request()->validate([ 'item_name' => ['required'], 'item_id' => ['required'], ]); $result = ItemSimilarity::GetSimilarityItems($fields['item_name'], $fields['item_id']); return new JsonResponse($result, 200);