برنامه نویسی

سیستم توصیه‌کننده با آپاچی AGE

از تماشای نحوه کار سیستم‌های توصیه‌کننده (Netflix/Amazon) توسط هنر مسئله در یوتیوب، از آن الهام گرفتم و می خواستم یک پست وبلاگی در مورد این موضوع ایجاد کنم. بنابراین، در اینجا ما روی چگونگی ایجاد یک سیستم توصیه با پایگاه داده گراف کار خواهیم کرد. برای این کار، ما از Apache AGE استفاده خواهیم کرد، که یک پسوند منبع باز برای PostgreSQL است که به ما امکان می دهد گره ها و لبه ها را ایجاد کنیم.

ایجاد نمودار

با توجه به مشاهدات فعالیت های گذشته کاربران، باید پیش بینی کنیم که کاربر چه چیزهای دیگری را نیز دوست دارد. ما می توانیم ترجیحات کاربر را به صورت گرافیکی به عنوان ارتباط بین نمایش دهیم People و مواردی که نسبت به آنها امتیاز یا نظر دارند، مانند Movies. رویکردی که قرار است از آن استفاده کنیم نامیده می شود فیلتر کردن محتوا، که از اطلاعاتی که درباره افراد و چیزها می دانیم به عنوان بافت همبند برای توصیه ها استفاده می کند.

-- Creating the graph.
SELECT create_graph('RecommenderSystem');


-- Adding user.
SELECT * FROM cypher('RecommenderSystem', $$
    CREATE (:Person {name: 'Abigail'})
$$) AS (a agtype);


-- Adding movies.
SELECT * FROM cypher('RecommenderSystem', $$
    CREATE (:Movie {title: 'The Matrix'}),
           (:Movie {title: 'Shrek'}),
           (:Movie {title: 'The Blair Witch Project'}),
           (:Movie {title: 'Jurassic Park'}),
           (:Movie {title: 'Thor: Love and Thunder'})
$$) AS (a agtype);


-- Adding categories.
SELECT * FROM cypher('RecommenderSystem', $$
    CREATE (:Category {name: 'Action'}),
           (:Category {name: 'Comedy'}),
           (:Category {name: 'Horror'})
$$) AS (a agtype);
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

می توانیم قدرت اتصالات را با خاصیتی به نام نشان دهیم rating در لبه های بین کاربران و دسته ها و فیلم ها و دسته بندی ها. این رتبه بندی بین 0 تا 4 متغیر خواهد بود، که 0 به این معنی است که کاربر از فیلم متنفر است و 4 به این معنی است که کاربر فیلم را دوست داشته است. این همچنین برای دسته‌ها و فیلم‌ها کار می‌کند، جایی که 0 کمتر احتمال دارد و 4 بیشترین احتمال را دارد.

بیایید بگوییم که ابیگیل دارای رتبه بندی است 3 برای Comedy، 1 برای Action، و 0 برای Horror.

-- User preferences.
SELECT * FROM cypher('RecommenderSystem', $$
    MATCH (a:Person {name: 'Abigail'}), (A:Category), (C:Category), (H:Category)
    WHERE A.name = 'Action' AND C.name = 'Comedy' AND H.name = 'Horror' 
    CREATE (a)-[:RATING {rating: 3}]->(C),
           (a)-[:RATING {rating: 1}]->(A),
           (a)-[:RATING {rating: 0}]->(H)
$$) AS (a agtype);
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

هر فیلم نیز به همان روش به هر دسته نگاشت می شود. به عنوان مثال، ماتریکس فاقد کمدی، اکشن و ترسناک است.

-- The Matrix and it's relationship with Categories.
SELECT * FROM cypher('RecommenderSystem', $$
    MATCH (matrix:Movie {title: 'The Matrix'}), (A:Category), (C:Category), (H:Category)
    WHERE A.name = 'Action' AND C.name = 'Comedy' AND H.name = 'Horror' 
    CREATE (matrix)-[:RATING {rating: 0}]->(C),
           (matrix)-[:RATING {rating: 4}]->(A),
           (matrix)-[:RATING {rating: 0}]->(H)
$$) AS (a agtype);

-- Shrek and it's relationship with Categories.
SELECT * FROM cypher('RecommenderSystem', $$
    MATCH (shrek:Movie {title: 'Shrek'}), (A:Category), (C:Category), (H:Category)
    WHERE A.name = 'Action' AND C.name = 'Comedy' AND H.name = 'Horror' 
    CREATE (shrek)-[:RATING {rating: 4}]->(C),
           (shrek)-[:RATING {rating: 2}]->(A),
           (shrek)-[:RATING {rating: 0}]->(H)
$$) AS (a agtype);

-- The Blair Witch Project and it's relationship with Categories.
SELECT * FROM cypher('RecommenderSystem', $$
    MATCH (witch:Movie {title: 'The Blair Witch Project'}), (A:Category), (C:Category), (H:Category)
    WHERE A.name = 'Action' AND C.name = 'Comedy' AND H.name = 'Horror' 
    CREATE (witch)-[:RATING {rating: 0}]->(C),
           (witch)-[:RATING {rating: 0}]->(A),
           (witch)-[:RATING {rating: 4}]->(H)
$$) AS (a agtype);

-- Jurassic Park and it's relationship with Categories.
SELECT * FROM cypher('RecommenderSystem', $$
    MATCH (jurassic:Movie {title: 'Jurassic Park'}), (A:Category), (C:Category), (H:Category)
    WHERE A.name = 'Action' AND C.name = 'Comedy' AND H.name = 'Horror' 
    CREATE (jurassic)-[:RATING {rating: 1}]->(C),
           (jurassic)-[:RATING {rating: 3}]->(A),
           (jurassic)-[:RATING {rating: 0}]->(H)
$$) AS (a agtype);

-- Thor: Love and Thunder and it's relationship with Categories.
SELECT * FROM cypher('RecommenderSystem', $$
    MATCH (thor:Movie {title: 'Thor: Love and Thunder'}), (A:Category), (C:Category), (H:Category)
    WHERE A.name = 'Action' AND C.name = 'Comedy' AND H.name = 'Horror' 
    CREATE (thor)-[:RATING {rating: 4}]->(C),
           (thor)-[:RATING {rating: 2}]->(A),
           (thor)-[:RATING {rating: 0}]->(H)
$$) AS (a agtype);
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

نمودار با نمایشگر سن

روش فیلتر محتوا

برای تعیین اینکه آیا کسی فیلمی را دوست دارد یا خیر، باید فاکتورها را با هم ضرب کنیم و آن را در تعداد دسته ها در 4 قرار دهیم.

-- The Matrix estimated rating for the user.
SELECT e1/(ct*4) AS factor FROM cypher('RecommenderSystem', $$
MATCH (u:Person)-[e1:RATING]->(v:Category)<-[e2:RATING]-(w:Movie{title: 'The Matrix'}), (c:Category) WITH e1, e2, COUNT(*) AS ct
RETURN SUM(e1.rating * e2.rating)::float, ct
$$) AS (e1 float, ct agtype);

      factor       
-------------------
 0.333333333333333
(1 row)

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

ما می توانیم قدرت ارتباط بین ابیگیل و ماتریکس را به صورت زیر نشان دهیم: [(3 x 0) + (1 x 4) + (0 x 0)] / 12 = 0.3. تخمین ما این است که او چندان از فیلم خوشش نخواهد آمد. اکنون باید داده‌های هر فیلم دیگری را جمع‌آوری کنیم تا بتوانیم آنهایی را که به بهترین وجه با علایق او مطابقت دارند را نشان دهیم.

-- Shrek's estimated rating for the user.
SELECT e1/(ct*4) AS factor FROM cypher('RecommenderSystem', $$
MATCH (u:Person)-[e1:RATING]->(v:Category)<-[e2:RATING]-(w:Movie{title: 'Shrek'}), (c:Category) WITH e1, e2, COUNT(*) AS ct
RETURN SUM(e1.rating * e2.rating)::float, ct
$$) AS (e1 float, ct agtype);

      factor      
------------------
 1.16666666666667
(1 row)


-- The Blair Witch Project estimated rating for the user.
SELECT e1/(ct*4) AS factor FROM cypher('RecommenderSystem', $$
MATCH (u:Person)-[e1:RATING]->(v:Category)<-[e2:RATING]-(w:Movie{title: 'The Blair Witch Project'}), (c:Category) WITH e1, e2, COUNT(*) AS ct
RETURN SUM(e1.rating * e2.rating)::float, ct
$$) AS (e1 float, ct agtype);

 factor 
--------
 0.0
(1 row)


-- Jurassic Park estimated rating for the user.
SELECT e1/(ct*4) AS factor FROM cypher('RecommenderSystem', $$
MATCH (u:Person)-[e1:RATING]->(v:Category)<-[e2:RATING]-(w:Movie{title: 'Jurassic Park'}), (c:Category) WITH e1, e2, COUNT(*) AS ct
RETURN SUM(e1.rating * e2.rating)::float, ct
$$) AS (e1 float, ct agtype);
 factor 
--------
 0.5
(1 row)


-- Thor: Love and Thunder estimated rating for the user.
SELECT e1/(ct*4) AS factor FROM cypher('RecommenderSystem', $$
MATCH (u:Person)-[e1:RATING]->(v:Category)<-[e2:RATING]-(w:Movie{title: 'Thor: Love and Thunder'}), (c:Category) WITH e1, e2, COUNT(*) AS ct
RETURN SUM(e1.rating * e2.rating)::float, ct
$$) AS (e1 float, ct agtype);
      factor      
------------------
 1.16666666666667
(1 row)
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اگرچه شرک و ثور زیاد فنجان چای او را نمی خورد، فیلم هایی از فهرست ما خواهند بود که ابیگیل با توجه به تجزیه و تحلیل نمودار ما تماشای آنها را ترجیح می دهد.

نتیجه

ما نشان داده‌ایم که چگونه می‌توان با استفاده از Apache AGE یک سیستم توصیه با پایگاه داده گراف ایجاد کرد. این رویکرد را می توان برای سازگاری با سناریوهای پیچیده تر، مانند ترکیب جمعیت شناسی کاربر، تاریخچه جستجو، یا اتصالات شبکه های اجتماعی گسترش داد. پایگاه های داده گراف به خوبی برای سیستم های توصیه مناسب هستند زیرا می توانند به راحتی روابط بین کاربران و آیتم ها و همچنین ویژگی های آن موجودیت ها را نشان دهند. علاوه بر این، استفاده از SQL و زبان پرس و جو Cypher کار با مجموعه داده های بزرگ و انجام پرس و جوهای پیچیده را آسان تر می کند. به طور کلی، امیدواریم این پست نقطه شروعی برای کسانی باشد که علاقه مند به ساختن یک سیستم توصیه با پایگاه داده گراف هستند.

اگر می خواهید درباره Apache AGE اطلاعات بیشتری کسب کنید، پیوندهای زیر را بررسی کنید:

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا