توقع الإعجابات: داخل خوارزميات محرك التوصية البسيطة
نشرت: 2022-03-11محرك التوصية (يشار إليه أحيانًا بنظام التوصية) هو أداة تسمح لمطوري الخوارزميات بالتنبؤ بما قد يحبه المستخدم أو لا يحبه من بين قائمة العناصر المحددة. تعد محركات التوصية بديلاً مثيرًا للاهتمام لحقول البحث ، حيث تساعد محركات التوصية المستخدمين على اكتشاف المنتجات أو المحتوى الذي قد لا يصادفهم بطريقة أخرى. هذا يجعل محركات التوصية جزءًا كبيرًا من مواقع الويب والخدمات مثل Facebook و YouTube و Amazon والمزيد.
تعمل محركات التوصية بشكل مثالي بإحدى طريقتين. يمكن أن يعتمد على خصائص العناصر التي يحبها المستخدم ، والتي يتم تحليلها لتحديد ما قد يعجب المستخدم ؛ أو يمكن أن تعتمد على إبداءات الإعجاب وعدم الإعجاب للمستخدمين الآخرين ، والتي يستخدمها محرك التوصية بعد ذلك لحساب فهرس التشابه بين المستخدمين والتوصية بالعناصر لهم وفقًا لذلك. من الممكن أيضًا الجمع بين هاتين الطريقتين لبناء محرك توصية أكثر قوة. ومع ذلك ، مثل جميع المشكلات الأخرى المتعلقة بالمعلومات ، من الضروري اختيار خوارزمية مناسبة للمشكلة التي تتم معالجتها.
في هذا البرنامج التعليمي ، سنوجهك خلال عملية إنشاء محرك توصية تعاوني وقائم على الذاكرة. سيوصي محرك التوصيات هذا بالأفلام للمستخدمين بناءً على ما يعجبهم وما يكرهون ، وسيعمل مثل المثال الثاني الذي تم ذكره من قبل. بالنسبة لهذا المشروع ، سنستخدم عمليات المجموعة الأساسية ، والقليل من الرياضيات ، و Node.js / CoffeeScript. يمكن العثور على جميع التعليمات البرمجية المصدر ذات الصلة بهذا البرنامج التعليمي هنا.
المجموعات والمعادلات
قبل تنفيذ محرك توصية تعاوني قائم على الذاكرة ، يجب علينا أولاً فهم الفكرة الأساسية وراء مثل هذا النظام. بالنسبة لهذا المحرك ، كل عنصر وكل مستخدم ليس سوى معرفات. لذلك ، لن نأخذ في الاعتبار أي سمة أخرى للفيلم (على سبيل المثال ، طاقم العمل ، والمخرج ، والنوع ، وما إلى ذلك) أثناء إنشاء التوصيات. يتم تمثيل التشابه بين مستخدمين باستخدام رقم عشري بين -1.0 و 1.0. سوف نسمي هذا الرقم مؤشر التشابه. أخيرًا ، سيتم تمثيل إمكانية إعجاب المستخدم بفيلم باستخدام رقم عشري آخر بين -1.0 و 1.0. الآن وقد صممنا العالم حول هذا النظام باستخدام مصطلحات بسيطة ، يمكننا إطلاق مجموعة من المعادلات الرياضية الأنيقة لتحديد العلاقة بين هذه المعرفات والأرقام.
في خوارزمية التوصية الخاصة بنا ، سنحتفظ بعدد من المجموعات. سيكون لكل مستخدم مجموعتين: مجموعة من الأفلام التي يحبها المستخدم ، ومجموعة من الأفلام التي لا يحبها المستخدم. سيكون لكل فيلم أيضًا مجموعتان مرتبطتان به: مجموعة من المستخدمين الذين أحبوا الفيلم ، ومجموعة من المستخدمين الذين لم يعجبهم الفيلم. خلال المراحل التي يتم فيها إنشاء التوصيات ، سيتم إنتاج عدد من المجموعات - معظمها نقابات أو تقاطعات المجموعات الأخرى. سنقوم أيضًا بترتيب قوائم الاقتراحات والمستخدمين المماثلين لكل مستخدم.
لحساب مؤشر التشابه ، سنستخدم صيغة مختلفة من صيغة مؤشر Jaccard. تُعرف الصيغة في الأصل باسم "معامل de communaute" (صاغه Paul Jaccard) ، وتقارن الصيغة مجموعتين وتنتج إحصائية عشرية بسيطة بين 0 و 1.0:
تتضمن الصيغة قسمة عدد العناصر المشتركة في كلتا المجموعتين على عدد كل العناصر (تُحسب مرة واحدة فقط) في كلتا المجموعتين. سيكون فهرس Jaccard لمجموعتين متطابقتين دائمًا هو 1 ، في حين أن مؤشر Jaccard لمجموعتين بدون عناصر مشتركة سينتج عنه دائمًا 0. الآن بعد أن عرفنا كيفية مقارنة مجموعتين ، دعنا نفكر في إستراتيجية يمكننا استخدامها لمقارنة مجموعتين المستخدمين. كما تمت مناقشته سابقًا ، فإن المستخدمين ، من وجهة نظر النظام ، هم ثلاثة أشياء: معرّف ، ومجموعة من الأفلام المحببة ، ومجموعة من الأفلام غير المحببة. إذا أردنا تحديد مؤشر تشابه مستخدمينا بناءً على مجموعة أفلامهم المفضلة فقط ، فيمكننا استخدام صيغة مؤشر Jaccard مباشرة:
هنا ، U1 و U2 هما المستخدمان اللذان نقارنهما ، و L1 و L2 هما مجموعتي الأفلام التي أحبها U1 و U2 ، على التوالي. الآن ، إذا فكرت في الأمر ، هناك مستخدمان يعجبان بنفس الأفلام متشابهان ، ثم يجب أن يكون هناك مستخدمان لا يعجبان نفس الأفلام. هذا هو المكان الذي نقوم فيه بتعديل المعادلة قليلاً:
بدلاً من مجرد التفكير في إبداءات الإعجاب الشائعة في بسط الصيغة ، نضيف الآن عدد حالات عدم الإعجاب الشائعة أيضًا. في المقام ، نأخذ عدد جميع العناصر التي نالت إعجاب المستخدم أو عدم إعجابه. الآن بعد أن نظرنا في كل من إبداءات الإعجاب وعدم الإعجاب بطريقة مستقلة ، يجب أن نفكر أيضًا في الحالة التي يكون فيها مستخدمان متضادان في تفضيلاتهما. يجب ألا يكون فهرس التشابه لاثنين من المستخدمين حيث يحب أحدهما فيلمًا ويكره الآخر 0:
هذه صيغة واحدة طويلة! لكن الأمر بسيط ، أعدك. إنها تشبه الصيغة السابقة مع وجود اختلاف بسيط في البسط. نحن الآن بصدد طرح عدد المعجبين وغير المعجبين المتضاربين بين المستخدمين من عدد مرات إبداء الإعجاب وعدم الإعجاب. يؤدي هذا إلى أن يكون لصيغة مؤشر التشابه نطاق من القيم بين -1.0 و 1.0. سيكون لدى مستخدمين لهما أذواق متطابقة مؤشر تشابه يبلغ 1.0 بينما سيكون لدى مستخدمين لهما أذواق متضاربة تمامًا في الأفلام مؤشر تشابه يبلغ -1.0.
الآن بعد أن عرفنا كيفية مقارنة مستخدمين بناءً على ذوقهما في الأفلام ، يتعين علينا استكشاف صيغة أخرى قبل أن نبدأ في تنفيذ خوارزمية محرك التوصية المصنوع منزليًا:
دعنا نكسر هذه المعادلة قليلاً. ما نعنيه بـ P(U,M)
هو إمكانية إعجاب المستخدم U
بالفيلم M
ZL
و ZD
هما مجموع مؤشرات التشابه للمستخدم U
مع جميع المستخدمين الذين أحبوا أو كرهوا الفيلم M
، على التوالي. |ML|+|MD|
يمثل إجمالي عدد المستخدمين الذين أبدوا إعجابهم أو عدم إعجابهم بالفيلم M
ينتج عن النتيجة P(U,M)
رقمًا بين -1.0 و 1.0.
هذا عن ذلك. في القسم التالي ، يمكننا استخدام هذه الصيغ لبدء تنفيذ محرك التوصيات التعاوني المستند إلى الذاكرة.
بناء محرك التوصيات
سنقوم ببناء محرك التوصية هذا كتطبيق Node.js بسيط للغاية. سيكون هناك أيضًا القليل من العمل على الواجهة الأمامية ، معظمها بعض صفحات HTML والنماذج (سنستخدم Bootstrap لجعل الصفحات تبدو نظيفة). من جانب الخادم ، سوف نستخدم CoffeeScript. سيحتوي التطبيق على عدد قليل من مسارات GET و POST. على الرغم من أنه سيكون لدينا فكرة المستخدمين في التطبيق ، فلن يكون لدينا أي آلية تسجيل / تسجيل دخول مفصلة. من أجل المثابرة ، سنستخدم حزمة Bourne المتاحة عبر NPM والتي تمكن التطبيق من تخزين البيانات في ملفات JSON عادية ، وتنفيذ استعلامات قاعدة البيانات الأساسية عليها. سنستخدم Express.js لتسهيل عملية إدارة المسارات والمعالجات.
في هذه المرحلة ، إذا كنت جديدًا في تطوير Node.js ، فقد ترغب في استنساخ مستودع GitHub بحيث يسهل اتباع هذا البرنامج التعليمي. كما هو الحال مع أي مشروع Node.js آخر ، سنبدأ بإنشاء ملف package.json وتثبيت مجموعة من حزم التبعية المطلوبة لهذا المشروع. إذا كنت تستخدم المستودع المستنسخ ، فيجب أن يكون ملف package.json موجودًا بالفعل ، حيث يتطلب تثبيت التبعيات تنفيذ "تثبيت $ npm". سيؤدي ذلك إلى تثبيت جميع الحزم المدرجة داخل ملف package.json.
حزم Node.js التي نحتاجها لهذا المشروع هي:
- غير متزامن
- بورن
- نص القهوة
- يعبر
- يشم
- شرطة سفلية
سنقوم ببناء محرك التوصية من خلال تقسيم جميع الطرق ذات الصلة إلى أربع فئات منفصلة من CoffeeScript ، سيتم تخزين كل منها ضمن "lib / engine": Engine و Rater و Similars و Suggestions. سيكون Class Engine مسؤولاً عن توفير واجهة برمجة تطبيقات بسيطة لمحرك التوصية ، وسيربط الفئات الثلاث الأخرى معًا. سيكون Rater مسؤولاً عن تتبع إبداءات الإعجاب وعدم الإعجاب (كحالتين منفصلتين من فئة Rater). ستكون المتشابهة والاقتراحات مسؤولة عن تحديد وتتبع المستخدمين المتشابهين والعناصر الموصى بها للمستخدمين ، على التوالي.
تتبع المعجبين وغير المعجبين
دعونا نبدأ أولاً بفصل التقييم لدينا. هذا هو واحد بسيط:
class Rater constructor: (@engine, @kind) -> add: (user, item, done) -> remove: (user, item, done) -> itemsByUser: (user, done) -> usersByItem: (item, done) ->
كما هو موضح سابقًا في هذا البرنامج التعليمي ، سيكون لدينا مثيل واحد من Rater لإبداءات الإعجاب ومثيل آخر لم يعجبه. لتسجيل إعجاب المستخدم بأحد العناصر ، سنقوم بتمريرها إلى "Rater # add ()". وبالمثل ، لإزالة التصنيف ، سنمرره إلى "Rater # remove ()".
نظرًا لأننا نستخدم Bourne كحل قاعدة بيانات بدون خادم ، فسنخزن هذه التقييمات في ملف يسمى "./db-#{@kind}.json" ، حيث يكون النوع إما "الإعجابات" أو "غير المعجبين". سنفتح قاعدة البيانات داخل المنشئ لمثيل Rater:
constructor: (@engine, @kind) -> @db = new Bourne "./db-#{@kind}.json"
سيؤدي ذلك إلى جعل إضافة سجلات التصنيف أمرًا بسيطًا مثل استدعاء طريقة قاعدة بيانات Bourne داخل طريقة "Rater # add ()":
@db.insert user: user, item: item, (err) =>
وهو مشابه لإزالتها (“db.delete” بدلاً من “db.insert”). ومع ذلك ، قبل أن نضيف شيئًا ما أو نزيله ، يجب أن نتأكد من أنه غير موجود بالفعل في قاعدة البيانات. من الناحية المثالية ، باستخدام قاعدة بيانات حقيقية ، كان بإمكاننا القيام بذلك كعملية واحدة. مع Bourne ، علينا إجراء فحص يدوي أولاً ؛ وبمجرد الانتهاء من الإدراج أو الحذف ، نحتاج إلى التأكد من إعادة حساب مؤشرات التشابه لهذا المستخدم ، ثم إنشاء مجموعة من الاقتراحات الجديدة. ستبدو الطرق "Rater # add ()" و "Rater # remove ()" على النحو التالي:
add: (user, item, done) -> @db.find user: user, item: item, (err, res) => if res.length > 0 return done() @db.insert user: user, item: item, (err) => async.series [ (done) => @engine.similars.update user, done (done) => @engine.suggestions.update user, done ], done remove: (user, item, done) -> @db.delete user: user, item: item, (err) => async.series [ (done) => @engine.similars.update user, done (done) => @engine.suggestions.update user, done ], done
للإيجاز ، سنتخطى الأجزاء التي نتحقق فيها من وجود أخطاء. قد يكون هذا أمرًا معقولاً يجب القيام به في مقال ، ولكنه ليس عذراً لتجاهل الأخطاء في التعليمات البرمجية الحقيقية.
ستشمل الطريقتان الأخريان ، "Rater # itemsByUser ()" و "Rater # usersByItem ()" من هذه الفئة القيام بما تدل عليه أسمائهم - البحث عن العناصر التي تم تصنيفها بواسطة المستخدم والمستخدمين الذين قاموا بتقييم عنصر ، على التوالي. على سبيل المثال ، عند إنشاء مثيل لـ Rater بـ kind = “likes”
، سيجد “Rater # itemsByUser ()” جميع العناصر التي قام المستخدم بتصنيفها.
البحث عن مستخدمين مشابهين
ننتقل إلى فصلنا التالي: المتشابهة. سيساعدنا هذا الفصل في حساب مؤشرات التشابه بين المستخدمين وتتبعها. كما تمت مناقشته من قبل ، فإن حساب التشابه بين مستخدمين يتضمن تحليل مجموعات العناصر التي تعجبهم وتكرههم. للقيام بذلك ، سوف نعتمد على مثيلات Rater لجلب مجموعات العناصر ذات الصلة ، ثم تحديد مؤشر التشابه لأزواج معينة من المستخدمين باستخدام صيغة مؤشر التشابه.
تمامًا مثل الفصل السابق ، Rater ، سنضع كل شيء في قاعدة بيانات Bourne المسماة “./db-similars.json” ، والتي سنفتحها في منشئ Rater. سيكون للفصل الدراسي طريقة "Similars # byUser ()" ، والتي ستتيح لنا البحث عن مستخدمين مشابهين لمستخدم معين من خلال بحث بسيط في قاعدة البيانات:
@db.findOne user: user, (err, {others}) =>
ومع ذلك ، فإن الطريقة الأكثر أهمية في هذه الفئة هي "Similars # update ()" والتي تعمل عن طريق أخذ المستخدم وحساب قائمة المستخدمين الآخرين المتشابهين ، وتخزين القائمة في قاعدة البيانات ، جنبًا إلى جنب مع مؤشرات التشابه الخاصة بهم. يبدأ من خلال البحث عن إبداءات الإعجاب وعدم الإعجاب للمستخدم:
async.auto userLikes: (done) => @engine.likes.itemsByUser user, done userDislikes: (done) => @engine.dislikes.itemsByUser user, done , (err, {userLikes, userDislikes}) => items = _.flatten([userLikes, userDislikes])
نجد أيضًا جميع المستخدمين الذين صنفوا هذه العناصر:

async.map items, (item, done) => async.map [ @engine.likes @engine.dislikes ], (rater, done) => rater.usersByItem item, done , done , (err, others) =>
بعد ذلك ، لكل من هؤلاء المستخدمين الآخرين ، نحسب فهرس التشابه ونخزنه جميعًا في قاعدة البيانات:
async.map others, (other, done) => async.auto otherLikes: (done) => @engine.likes.itemsByUser other, done otherDislikes: (done) => @engine.dislikes.itemsByUser other, done , (err, {otherLikes, otherDislikes}) => done null, user: other similarity: (_.intersection(userLikes, otherLikes).length+_.intersection(userDislikes, otherDislikes).length-_.intersection(userLikes, otherDislikes).length-_.intersection(userDislikes, otherLikes).length) / _.union(userLikes, otherLikes, userDislikes, otherDislikes).length , (err, others) => @db.insert user: user others: others , done
داخل المقتطف أعلاه ، ستلاحظ أن لدينا تعبيرًا مطابقًا بطبيعته لصيغة فهرس التشابه ، وهي صيغة مختلفة لصيغة فهرس Jaccard.
توليد التوصيات
صفنا التالي ، الاقتراحات ، هو المكان الذي تحدث فيه جميع التوقعات. مثل فئة Similars ، نعتمد على قاعدة بيانات Bourne أخرى تسمى “./db-suggestions.json” ، مفتوحة داخل المُنشئ.
سيكون للفصل الدراسي طريقة "Suggestions # forUser ()" للبحث عن الاقتراحات المحسوبة للمستخدم المحدد:
forUser: (user, done) -> @db.findOne user: user, (err, {suggestions}={suggestion: []}) -> done null, suggestions
الطريقة التي ستحسب هذه النتائج هي "Suggestions # update ()". هذه الطريقة ، مثل "Similars # update ()" ، سوف تأخذ المستخدم كوسيطة. تبدأ الطريقة بإدراج جميع المستخدمين المشابهين لمستخدم معين ، وجميع العناصر التي لم يصنفها المستخدم المحدد:
@engine.similars.byUser user, (err, others) => async.auto likes: (done) => @engine.likes.itemsByUser user, done dislikes: (done) => @engine.dislikes.itemsByUser user, done items: (done) => async.map others, (other, done) => async.map [ @engine.likes @engine.dislikes ], (rater, done) => rater.itemsByUser other.user, done , done , done , (err, {likes, dislikes, items}) => items = _.difference _.unique(_.flatten items), likes, dislikes
بمجرد أن يكون لدينا جميع المستخدمين الآخرين والعناصر غير المصنفة المدرجة ، يمكننا البدء في حساب مجموعة جديدة من التوصيات عن طريق إزالة أي مجموعة سابقة من التوصيات ، والتكرار فوق كل عنصر ، وحساب إمكانية إعجاب المستخدم به بناءً على المعلومات المتاحة:
@db.delete user: user, (err) => async.map items, (item, done) => async.auto likers: (done) => @engine.likes.usersByItem item, done dislikers: (done) => @engine.dislikes.usersByItem item, done , (err, {likers, dislikers}) => numerator = 0 for other in _.without _.flatten([likers, dislikers]), user other = _.findWhere(others, user: other) if other? numerator += other.similarity done null, item: item weight: numerator / _.union(likers, dislikers).length , (err, suggestions) =>
بمجرد الانتهاء من ذلك ، نحفظه مرة أخرى في قاعدة البيانات:
@db.insert user: user suggestions: suggestions , done
كشف مكتبة API
داخل فئة المحرك ، نربط كل شيء بهيكل أنيق شبيه بواجهة برمجة التطبيقات لسهولة الوصول إليه من العالم الخارجي:
class Engine constructor: -> @likes = new Rater @, 'likes' @dislikes = new Rater @, 'dislikes' @similars = new Similars @ @suggestions = new Suggestions @
بمجرد إنشاء كائن محرك:
e = new Engine
يمكننا بسهولة إضافة أو إزالة إبداءات الإعجاب وعدم الإعجاب:
e.likes.add user, item, (err) -> e.dislikes.add user, item, (err) ->
يمكننا أيضًا البدء في تحديث مؤشرات تشابه المستخدم والاقتراحات:
e.similars.update user, (err) -> e.suggestions.update user, (err) ->
أخيرًا ، من المهم تصدير فئة المحرك هذه (وجميع الفئات الأخرى) من ملفات ".coffee" الخاصة بها:
module.exports = Engine
بعد ذلك ، قم بتصدير المحرك من الحزمة عن طريق إنشاء ملف "index.coffee" بسطر واحد:
module.exports = require './engine'
إنشاء واجهة المستخدم
لتتمكن من استخدام خوارزمية محرك التوصية في هذا البرنامج التعليمي ، نريد توفير واجهة مستخدم بسيطة عبر الويب. للقيام بذلك ، ننتج تطبيق Express داخل ملف "web.iced" الخاص بنا ونتعامل مع بعض المسارات:
movies = require './data/movies.json' Engine = require './lib/engine' e = new Eengine app = express() app.set 'views', "#{__dirname}/views" app.set 'view engine', 'jade' app.route('/refresh') .post(({query}, res, next) -> async.series [ (done) => e.similars.update query.user, done (done) => e.suggestions.update query.user, done ], (err) => res.redirect "/?user=#{query.user}" ) app.route('/like') .post(({query}, res, next) -> if query.unset is 'yes' e.likes.remove query.user, query.movie, (err) => res.redirect "/?user=#{query.user}" else e.dislikes.remove query.user, query.movie, (err) => e.likes.add query.user, query.movie, (err) => if err? return next err res.redirect "/?user=#{query.user}" ) app.route('/dislike') .post(({query}, res, next) -> if query.unset is 'yes' e.dislikes.remove query.user, query.movie, (err) => res.redirect "/?user=#{query.user}" else e.likes.remove query.user, query.movie, (err) => e.dislikes.add query.user, query.movie, (err) => res.redirect "/?user=#{query.user}" ) app.route('/') .get(({query}, res, next) -> async.auto likes: (done) => e.likes.itemsByUser query.user, done dislikes: (done) => e.dislikes.itemsByUser query.user, done suggestions: (done) => e.suggestions.forUser query.user, (err, suggestions) => done null, _.map _.sortBy(suggestions, (suggestion) -> -suggestion.weight), (suggestion) => _.findWhere movies, id: suggestion.item , (err, {likes, dislikes, suggestions}) => res.render 'index', movies: movies user: query.user likes: likes dislikes: dislikes suggestions: suggestions[...4] )
داخل التطبيق ، نتعامل مع أربعة مسارات. مسار الفهرس "/" هو المكان الذي نخدم فيه HTML للواجهة الأمامية عن طريق عرض قالب Jade. يتطلب إنشاء النموذج قائمة بالأفلام واسم المستخدم الحالي للمستخدم وإبداءات الإعجاب وعدم الإعجاب وأهم أربعة اقتراحات للمستخدم. تم ترك الكود المصدري لقالب Jade خارج المقالة ، ولكنه متاح في مستودع GitHub.
المساران "/ like" و "/ dislike" هما المكان الذي نقبل فيه طلبات POST لتسجيل إبداءات الإعجاب وعدم الإعجاب للمستخدم. يضيف كلا المسارين تصنيفًا عن طريق إزالة أي تصنيف متضارب أولاً ، إذا لزم الأمر. على سبيل المثال ، إذا أعجب المستخدم بشيء لم يعجبه سابقًا ، فسوف يتسبب المعالج في إزالة تصنيف "عدم الإعجاب" أولاً. تتيح هذه المسارات أيضًا للمستخدم "عدم الإعجاب" أو "عدم الإعجاب" بأحد العناصر ، إذا رغب في ذلك.
أخيرًا ، يسمح مسار "/ Refresh" للمستخدم بإعادة إنشاء مجموعة التوصيات عند الطلب. على الرغم من أن هذا الإجراء يتم تنفيذه تلقائيًا عندما يقوم المستخدم بأي تصنيف لعنصر ما.
اختبار القيادة
إذا كنت قد حاولت تنفيذ هذا التطبيق من البداية باتباع هذه المقالة ، فستحتاج إلى تنفيذ خطوة أخيرة قبل أن تتمكن من اختباره. ستحتاج إلى إنشاء ملف ".json" في "data / movies.json" ، وملئه ببعض بيانات الأفلام مثل:
[ { "id": "1", "name": "Transformers: Age of Extinction", "thumb": { "url": "//upload.wikimedia.org/wikipedia/en/7/7f/Inception_ver3.jpg" } }, // … ]
قد ترغب في نسخ الملف المتاح في مستودع GitHub ، والذي يتم ملؤه مسبقًا بعدد قليل من أسماء الأفلام وعناوين URL المصغرة.
بمجرد أن تصبح جميع التعليمات البرمجية المصدر جاهزة ومتصلة ببعضها البعض ، يتطلب بدء عملية الخادم استدعاء الأمر التالي:
$ npm start
بافتراض أن كل شيء سار بسلاسة ، يجب أن ترى النص التالي يظهر على الجهاز:
Listening on 5000
نظرًا لأننا لم ننفذ أي نظام مصادقة مستخدم حقيقي ، فإن تطبيق النموذج الأولي يعتمد فقط على اسم مستخدم تم اختياره بعد زيارة "http: // localhost: 5000". بمجرد إدخال اسم المستخدم ، وتقديم النموذج ، يجب أن يتم نقلك إلى صفحة أخرى من قسمين: "الأفلام الموصى بها" و "جميع الأفلام". نظرًا لأننا نفتقر إلى العنصر الأكثر أهمية في محرك التوصية التعاوني المستند إلى الذاكرة (البيانات) ، فلن نتمكن من التوصية بأي أفلام لهذا المستخدم الجديد.
في هذه المرحلة ، يجب عليك فتح نافذة متصفح أخرى لـ "http: // localhost: 5000" وتسجيل الدخول كمستخدم مختلف هناك. أحب وأكره بعض الأفلام مثل هذا المستخدم الثاني. ارجع إلى نافذة المتصفح للمستخدم الأول وقم بتقييم بعض الأفلام أيضًا. تأكد من تقييم اثنين على الأقل من الأفلام الشائعة لكلا المستخدمين. يجب أن تبدأ في رؤية التوصيات على الفور.
تحسينات
في هذا البرنامج التعليمي للخوارزمية ، ما قمنا ببنائه هو محرك توصية نموذج أولي. هناك بالتأكيد طرق لتحسين هذا المحرك. سيتناول هذا القسم بإيجاز بعض المجالات التي تكون فيها التحسينات ضرورية لاستخدامها على نطاق واسع. ومع ذلك ، في الحالات التي تتطلب قابلية التوسع والاستقرار وغيرها من الخصائص المماثلة ، يجب عليك دائمًا اللجوء إلى استخدام حل جيد تم اختباره بمرور الوقت. مثل بقية المقال ، فإن الفكرة هنا هي تقديم نظرة ثاقبة حول كيفية عمل محرك التوصيات. بدلاً من مناقشة العيوب الواضحة للطريقة الحالية (مثل حالة السباق في بعض الأساليب التي طبقناها) ، ستتم مناقشة التحسينات على مستوى أعلى.
أحد التحسينات الواضحة هنا هو استخدام قاعدة بيانات حقيقية ، بدلاً من الحل القائم على الملفات. قد يعمل الحل المستند إلى الملفات بشكل جيد في نموذج أولي على نطاق صغير ، لكنه ليس خيارًا معقولًا على الإطلاق للاستخدام الحقيقي. خيار واحد من بين العديد هو Redis. Redis سريع وله قدرات خاصة مفيدة عند التعامل مع هياكل البيانات الشبيهة بالمجموعة.
هناك مشكلة أخرى يمكننا حلها وهي حقيقة أننا نحسب توصيات جديدة في كل مرة يقوم فيها المستخدم بإجراء أو تغيير تقييماته للأفلام. بدلاً من إجراء عمليات إعادة الحساب أثناء التنقل في الوقت الفعلي ، يجب علينا ترتيب طلبات تحديث التوصيات هذه للمستخدمين وتنفيذها خلف الكواليس - ربما تعيين فاصل زمني محدد للتحديث.
إلى جانب هذه الخيارات "الفنية" ، هناك أيضًا بعض الخيارات الإستراتيجية التي يمكن إجراؤها لتحسين التوصيات. مع نمو عدد العناصر والمستخدمين ، سيصبح إنشاء التوصيات مكلفًا بشكل متزايد (من حيث الوقت وموارد النظام). من الممكن جعل هذا أسرع عن طريق اختيار مجموعة فرعية فقط من المستخدمين لإنشاء توصيات منهم ، بدلاً من معالجة قاعدة البيانات بأكملها في كل مرة. على سبيل المثال ، إذا كان هذا محرك توصيات للمطاعم ، فيمكنك تقييد مجموعة المستخدمين المماثلة بحيث تحتوي فقط على المستخدمين الذين يعيشون في نفس المدينة أو الولاية.
قد تتضمن التحسينات الأخرى اتباع نهج مختلط ، حيث يتم إنشاء التوصيات بناءً على كل من التصفية التعاونية والتصفية القائمة على المحتوى. سيكون هذا جيدًا بشكل خاص مع محتوى مثل الأفلام ، حيث يتم تحديد خصائص المحتوى جيدًا. Netflix ، على سبيل المثال ، تأخذ هذا الطريق ، وتوصي بالأفلام بناءً على كل من أنشطة المستخدمين الآخرين وسمات الأفلام.
خاتمة
يمكن أن تكون خوارزميات محرك التوصية التعاوني القائم على الذاكرة شيئًا قويًا جدًا. قد يكون الشيء الذي جربناه في هذه المقالة بدائيًا ، ولكنه أيضًا بسيط: سهل الفهم وبسيط البناء. قد يكون بعيدًا عن الكمال ، لكن عمليات التنفيذ القوية لمحركات التوصية ، مثل التوصية ، مبنية على أفكار أساسية مماثلة.
مثل معظم مشاكل علوم الكمبيوتر الأخرى التي تتضمن الكثير من البيانات ، فإن الحصول على توصيات صحيحة يتعلق كثيرًا باختيار الخوارزمية الصحيحة والسمات المناسبة للمحتوى للعمل عليها. آمل أن يكون هذا المقال قد أعطاك لمحة عن ما يحدث داخل محرك توصية تعاوني قائم على الذاكرة عند استخدامه.