تحتوي مدونة ivi للأفلام عبر الإنترنت على مقالات كثيرة عن بنية نظام توصية Hydra. ومع ذلك ، لا تعد التوصيات واجهة برمجة تطبيقات خارجية فحسب ، ولكنها أيضًا خوارزميات تعيش "تحت الغطاء" وتطبق منطقًا تجاريًا معقدًا للغاية.
في هذه المقالة ، سأتحدث عن مشكلة "البداية الباردة" للمحتوى. إذا كنت مهتمًا بمعرفة كيف نوصي بالمحتوى الذي تمت إضافته مؤخرًا إلى الفهرس ولم تتمكن من الحصول على تعليقات من المستخدمين ، فمرحباً بك في cat.
سوف تحتوي المقالة على عينة مستنسخة من شفرة بايثون باستخدام Keras.
بداية المحتوى البارد: بيان المشكلة
كيف تعمل التوصيات؟ تقريبا على النحو التالي:
نستخدم خط الأنابيب التالي للتوصيات:
- تحميل إحصائيات عرض المحتوى في شكل مصفوفة محتوى المستخدم
- تطبيق الآلة تعلم المربع السحري
- عند الخروج من الصندوق لكل وحدة من ميزات الكتالوج تظهر
- نستخدم ميزات المحتوى للتوصيات
يمكن العثور على جميع مراحل خط أنابيب نموذج التدريب على البدء البارد في هذا المستودع
github.com/ivi-ru/hydraنحصل على ميزات المحتوى باستخدام المكتبة الضمنية على النحو التالي
train_model.pyimport implicit import numpy as np from scipy.sparse import load_npz
كيف يمكنك التوصية بالمحتوى الذي تم عرضه على الخدمة مؤخرًا؟ لن يكون لهذا المحتوى أي مشاهدات (أو لن يكون هناك سوى عدد قليل جدًا من المشاهدات) - وهذا يعني أنه لن تكون هناك ميزات لهذا المحتوى في عادم الصندوق السحري للتعلم الآلي ولن تظهر في توصيات المستخدم. الميزات التي نحصل عليها على أساس تفاعلات محتوى المستخدم ، بالمناسبة ، تسمى التعاونية.
وبالتالي ، فإننا نواجه مشكلة البداية الباردة: كيف يمكننا التوصية بالمحتوى الذي لا يحتوي على تعليقات المستخدمين؟ من الممكن ، على سبيل المثال ، مزج المحتوى الجديد في إخراج عشوائي والانتظار حتى يتم تجميع المشاهدات "العضوية".
خيار آخر هو بناء نموذج يمكنه التنبؤ بميزات المحتوى "البارد".
قررنا السير في الطريق الثاني وهذا هو المكان الذي أتينا إليه
بدء الباردة 1.0
لحل مشكلة البداية الباردة ، يتم دعمنا من خلال ميزات المحتوى المعروفة مسبقًا بالمحتوى الجديد ، على سبيل المثال
- الأشخاص: مخرج ، كاتب سيناريو ، ممثلون
- نوع المحتوى: الحركة ، الكوميديا ، إلخ.
- الفئة: فيلم روائي طويل ، رسوم متحركة ، وثائقي
- علامات المحرر
العلامات التحريرية هي وصف قصير للمحتوى في شكل مجموعة من الخصائص المحددة (عادة عدة مئات). يوجد أدناه مجموعة من علامات محتوى Beaver Zombie
في التقريب الأول ، قمنا بحل مشكلة البداية الباردة على النحو التالي:
- لكل محتوى "بارد" ، قم بمسحه قدر الإمكان بواسطة العلامات
- تأخذ ميزات تعاونية من محتوى مماثل
- الميزات التعاونية للمحتوى البارد هي متوسط ميزات جيرانها "الحار"
في الثعبان ، يبدو شيء من هذا القبيل for row in new_items_neighbors: neighbors_als_indices = row.neighbors_ids[:self.cold_start_neighbors_count] neighbors_average_factors = item_factors[neighbors_als_indices].mean(axis=0)
نجحت هذه الطريقة
بطريقة ما ، ولكن كان لها عيبان:
- القابلية للتوسعة الضعيفة: من الصعب إضافة ، على سبيل المثال ، تشابه الملصقات مع النموذج
- لا أحد يضمن تشابه ميزات ALS لمحتوى مماثل في العلامات ، وبدون ذلك ، فإن استخدام المتوسط يبدو غريبًا
لقد أدركنا أنه لم يعد بإمكانك العيش هكذا ، وتوصلنا إلى نموذج أكثر شفافية وقابلية للتوسيع.
إعادة بيع نموذج البداية الباردة
بدلاً من حساب ميزات محتوى ALS باستخدام الاستدلال (مثل المتوسط) ، يمكننا تدريب شبكة عصبية تتنبأ بميزات المحتوى التعاوني - على سبيل المثال ، بواسطة علامات المحرر. تم عرض نموذج مشابه بالفعل
على Habr's هنا ، وقبل Yandex
تحدثت خدمة Spotify الموسيقية عن طراز مماثل
يتوفر نموذج النموذج الأولي
في مستودع IVI ،
وتكون الشبكة العصبية لبداية باردة كما يلي:
cold_start_model.py def _get_model(self, dims: List[int]) -> Sequential: model = Sequential() model.add( Dense( units=dims[1], activation='linear', input_dim=dims[0], kernel_initializer=WeightInitializer.custom_normal, bias_initializer='zeros' ) ) model.compile( loss=lambda y_true, y_pred: K.sum(K.square(y_pred - y_true), axis=-1), optimizer=optimizers.Adam(lr=self.learning_rate, decay=self.decay) ) return model
ما الصعوبات التي واجهتك أثناء تنفيذ هذه التجربة؟
- لقد تبين أنه من الصعب جدًا تدريب الشبكة: يتم ترميز الميزات بسرعة واحدة ، ويتم تدريب الشبكة بشكل سيئ بسبب البعد الكبير لطبقة الإدخال. اضطررت لإجراء مجموعة مختارة بعناية من الميزات ، في النهاية نستخدم فقط الفئات والأنواع ، ومن علامات المحرر نختار الأكثر "أهمية" باستخدام tf-idf
- مشكلة تثبيت Keras باستخدام مدير حزمة pipenv: python ، البيئة لم تكن تعمل ، اضطررت إلى إنهاء حزمة maxvolpy التابعة لجهة خارجية والتي لم يصنعها Keras مع
نتائج التجربة
نتيجةً لذلك ، فقد استنفدنا الوظيفة الجديدة أقل قليلاً ، الأمر الذي قضى فيه المطور لمدة 100 ساعة لعدة ساعات - وهذه هي أول تجربة لاستخدام الشبكات العصبية في الإنتاج في مشروعنا. تم توزيع هذه المرة على النحو التالي:
- 60 ساعة لقراءة المقالات وتطوير النموذج الأولي
- 30 ساعة لدمج النموذج الأولي في قاعدة رمز المشروع
- 10 ساعات من نشر النموذج الجديد - سحب Keras في بيئة بيثون لم يكن بهذه البساطة بسبب تبعياتنا المحددة (مثل maxvolpy)
حصلنا على مساحة لمزيد من التجارب - استخدام الشبكات العصبية يسمح لك بالتعلم ليس فقط على علامات المحرر ، ولكن أيضًا في الميزات الأخرى: الصور ، البرامج النصية ، تعليقات المستخدمين ، لقطات ، إلخ.