كتابة: James Ng ترجمة: سعد العجلان مراجعة: أسيل المسعد
[المقال الأصلي بالانجليزي اضغط هنا]دليل لبناء نموذج توصيات أفلام قائم على أساس المحتوى بناءً على معالجة اللغات الطبيعية (NLP).
عندما نقّيم منتج أو خدمة على الأنترنت، يتم استخدام كل التفضيلات والبيانات التي نشاركها (بشكل صريح أم لا) لإنشاء توصيات باستخدام أنظمة متخصصة في إعطاء التوصيات. من أشهر هذه الأنظمة هي الأنظمة المستخدمة في Amazon و Google وNetflix.
هناك نوعان من الأنظمة المستخدمة لإعطاء التوصيات وهي:
- الأنظمة التعاونية: تكون قائمة على تقييم المستخدم واستهلاكه بحيث يتم تجميع المستخدمين المتشابهين معاً في مجموعة واحدة ثم يتم إعطاء التوصيات لهم.
- الأنظمة القائمة على المحتوى: إعطاء التوصيات بناءً على التشابه في سمات المنتجات والخدمات.
في هذا المقال قمت بدمج سمات الفيلم مثل النوع والحبكة والمخرج والممثلين الرئيسيين لحساب التشابه مع فيلم آخر باستخدام جيب تمام الزاوية (cosine similarity). مجموعة البيانات المستخدمة هي أفضل 50 فيلمًا إنجليزيًا حسب تصنيف موقع IMBD وتم تنزيلها من موقع data.world.
الخطوة الأولى: استدعاء المكتبات المطلوبة ومجموعة البيانات عن طريق python واستكشاف البيانات عن طريق تحليلها
تأكد من أن مكتبة the Rapid Automatic Keyword Extraction (RAKE) تم تثبيتها أو قم بعمل التالي (pip install rake_nltk)
from rake_nltk import Rake
import pandas as pdfrom rake_nltk import Rake
import pandas as pd
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
from sklearn.feature_extraction.text import CountVectorizerdf = pd.read_csv('IMDB_Top250Engmovies2_OMDB_Detailed.csv')
df.head()
بعد استكشاف مجموعة البيانات، وجدنا 250 فلم (كصفوف) و 38 سمة (كأعمدة). ومع ذلك، فإن 5 سمات من 38 سمة هي المفيدة، وهم عنوان الفلم والممثلين والمخرج وأحداث الفلم ونوع الفلم. في ما يلي قائمة بـ 10 من المخرجين المشهورين.
df['Director'].value_counts()[0:10].plot('barh', figsize=[8,5], fontsize=15, color='navy').invert_yaxis()
الخطوة الثانية: معالجة مسبقة للبيانات لحذف الكلمات الشائعة (الكلمات المستبعدة) وعلامات الترقيم والفراغات وتحويل جميع الأحرف إلى أحرف صغيرة
في البداية، يجب معالجة البيانات مسبقًا باستخدام معالجة اللغات الطبيعية (NLP) للحصول على عمود واحد يحتوي جميع السمات. بعد ذلك، هذه المعلومات سيتم تحويلها إلى أرقام بواسطة تمثيلها كمتجهات، حيث كل كلمة سوف تعطي قيم معينة. لاحقاً يتم حساب التشابه باستخدام جيب تمام الزاوية.
استخدمت دالة (RAKE) لاستخراج الكلمات الأكثر صلة من جميع الجمل المتواجدة في عمود “أحداث الفلم”. ومن أجل القيام بذلك، أنشأت عمود آخر بإسم مفتاح الكلمات ‘Key_words’.
df['Key_words'] = ''
r = Rake()for index, row in df.iterrows():
r.extract_keywords_from_text(row['Plot'])
key_words_dict_scores = r.get_word_degrees()
row['Key_words'] = list(key_words_dict_scores.keys())
أسماء المخرجين والممثلين تم تحويلهم إلى أسماء ذات قيمة مميزة بدمج الاسم الأول والاسم الأخير معاً، وأصبح الاسم عبارة عن كلمة واحدة. الآن اسم Chris Evans واسم Chris Hemsworth أصبحوا أسماء مختلفة (لو لم نعمل هذه الخطوة لكان التشابه بين الاسمين سوف يكون 50٪ لأن اسم Chris موجود في كلا الإسمين). أيضاً تحتاج كل الكلمات لتحويلها لأحرف صغيرة لتجنب التكرار في الأسماء.
df['Genre'] = df['Genre'].map(lambda x: x.split(','))
df['Actors'] = df['Actors'].map(lambda x: x.split(',')[:3])
df['Director'] = df['Director'].map(lambda x: x.split(','))for index, row in df.iterrows():
row['Genre'] = [x.lower().replace(' ','') for x in row['Genre']]
row['Actors'] = [x.lower().replace(' ','') for x in row['Actors']]
row['Director'] = [x.lower().replace(' ','') for x in row['Director']]
الخطوة الثالثة: تمثيل الكلمات بواسطة دمج السمات في عمود واحد تحت مسمى حقيبة الكلمات “bag of words”
بعد المعالجة المسبقة للبيانات، تم دمج أربع أعمدة في عمود واحد باسم حقيبة الكلمات. هذه الأعمدة هي نوع الفلم والممثلين والمخرجين وأخيراً مفتاح الكلمات. الـ DataFrame النهائية تحتوي على عمودين فقط.
df['Bag_of_words'] = ''
columns = ['Genre', 'Director', 'Actors', 'Key_words']for index, row in df.iterrows():
words = ''
for col in columns:
words += ' '.join(row[col]) + ' '
row['Bag_of_words'] = words
df = df[['Title','Bag_of_words']]
الخطوة الرابعة: تمثيل عمود “حقيبة الكلمات” كمتجهات وإنشاء مصفوفة التشابه
نموذج التوصيات يستطيع فقط قراءة ومقارنة متجه (مصفوفة) مع متجه آخر. لذلك نحتاج إلى تمثيل “حقيبة الكلمات” كمتجهات باستخدام “CountVectorizer” .”CountVectorizer” تقوم باحتساب تكرار كل كلمة من الكلمات الموجودة في عمود “حقيبة الكلمات”. عندما يتم حساب تكرار كل كلمة متواجدة في عمود “حقيبة الكلمات” أستطيع تطبيق دالة cosine_similarity لمقارنة أوجه التشابه بين الأفلام.
count = CountVectorizer()
count_matrix = count.fit_transform(df['Bag_of_words'])cosine_sim = cosine_similarity(count_matrix, count_matrix)
print(cosine_sim)
التالي هو إنشاء سلسلة من عناوين الأفلام باستخدام عمود “العنوان” بحيث كل عنوان فلم يرمز له برقم يتطابق مع أرقام الصفوف والأعمدة الموجودة في مصفوفة التشابه.
indices = pd.Series(df['Title'])
الخطوة الخامسة: تشغيل واختبار نموذج التوصيات
الخطوة الأخيرة هي إنشاء دالة تقبل عنوان الفلم كمدخل وتعطي أكثر 10أفلام مشابهة لهذا الفلم كنتيجة لهذه الدالة. هذه الدالة ستقوم بمطابقة عنوان الفيلم المدخل مع الرقم المقابل لرقم الفلم في مصفوفة التشابه واستخراج قيم الصفوف الأكثر تشابهاً بالترتيب التنازلي. أكثر 10 أفلام مشابهة للفلم المدخل تستطيع استخراجها باستدعاء أكثر 11 فلم مشابه للفلم المدخل حيث ان اول قيمة يتم اهمالها بسبب انها تعود للفلم المدخل نفسه.
def recommend(title, cosine_sim = cosine_sim):
recommended_movies = []
idx = indices[indices == title].index[0]
score_series = pd.Series(cosine_sim[idx]).sort_values(ascending = False)
top_10_indices = list(score_series.iloc[1:11].index)
for i in top_10_indices:
recommended_movies.append(list(df['Title'])[i])
return recommended_movies
الآن أنا جاهز لاختبار النموذج. سوف أقوم بإدخال فلمي المفضل “The Avengers” وأنتظر التوصيات من النظام:
recommend('The Avengers')
الخاتمة
قد أوصى النموذج بأفلام مشابهة جداً. من “معرفتي للمجال” أستطيع أن أرى بعض أوجه التشابه تستند إلى المخرجين وأحداث الفلم. لقد شاهدت بالفعل معظم هذه الأفلام الموصى بها، وأتطلع لمشاهدة تلك الأفلام التي لم أشاهدها.
تستطيع الرجوع لصفحتي في GitHub للحصول على الكود بلغة بايثون مع التعليقات المتضمنة.