في نافذة الطباعة اختر «حفظ كملف PDF» كوجهة.
تعلم الآلة، الأسبوع 9
التوصيات المعتمدة على المحتوى
صف كل فيلم بكلماته، وقس مدى التشابه بين فيلمين بتشابه جيب التمام، وأوص بالأفلام الأقرب.
الأهداف
- ▸شرح كيف يختار نظام التوصية المعتمد على المحتوى (content-based) الأفلام: المحتوى المشابه يوصى به أولا
- ▸تحويل النص إلى متجهات أعداد (count vectors) باستخدام
CountVectorizer، وبيان وظيفةstop_wordsوmin_df - ▸حساب تشابه جيب التمام (cosine similarity) يدويا: الضرب النقطي (dot product)، والطولان، والقسمة
- ▸بناء مصفوفة التشابه (similarity matrix) باستخدام
cosine_similarityوقراءة صف واحد منها - ▸تتبع
get_recommendationsسطرا بسطر وشرح مواضع خطئها - ▸إعداد عرض مشروع فريقك لمناقشة هذا الأسبوع
الأسبوع 9 من الخطة
موقع الدرس من المقرر
- ▸الدفتر (notebook): Movie Recommendations، قاعدة بيانات من 4,803 أفلام بأنواعها وكلماتها المفتاحية وطاقم تمثيلها ومخرجيها
- ▸سيناريو من الواقع: توصيات الأفلام، نموذج يأخذ عنوان فيلم ويعيد أفلاما مشابهة
- ▸مرحلة المشروع: عروض فرق المشاريع ومناقشاتها (Project Teams Presentations and Discussions)
خطة الساعتين
| الجزء | ما نفعله | الزمن |
|---|---|---|
| 1 | الفكرة، ومثال محلول يدويا | 35 دقيقة |
| 2 | الدفتر: المتجهات ومصفوفة التشابه | 25 دقيقة |
| 3 | get_recommendations ومواضع خطئها | 20 دقيقة |
| 4 | عروض المشاريع والمناقشة | 10 دقائق |
| 5 | تمارين مع الإجابات، ثم الخلاصة | 30 دقيقة |
الجزء 1
الفكرة
محتوى متشابه، ذوق متشابه
ما نظام التوصية المعتمد على المحتوى؟
- التوصية المعتمدة على المحتوى
- التوصية بمنتجات، مثل الكتب والأفلام، اعتمادا على منتجات أخرى تحبها، بقياس مدى تشابه المنتجات نفسها.
الوصفة في أربع خطوات
- 1الوصف: صف كل فيلم بنص واحد يضم عنوانه، وأنواعه، وكلماته المفتاحية، وطاقم تمثيله، ومخرجه
- 2التحويل إلى متجهات: عد كم مرة تظهر كل كلمة من المفردات (vocabulary) في ذلك النص
- 3المقارنة: احسب تشابه جيب التمام لكل زوج من الأفلام
- 4التوصية: لفيلم أعجب المشاهد، أعد الأفلام صاحبة أعلى تشابه
من النص إلى الأعداد: CountVectorizer
texts = ['Action Adventure Fantasy Science Fiction',
'Adventure Fantasy Action']
cv = CountVectorizer(stop_words='english')
m = cv.fit_transform(texts)
print(cv.get_feature_names_out())
print(m.toarray())['action' 'adventure' 'fantasy' 'fiction' 'science']
[[1 1 1 1 1]
[1 1 1 0 0]]- ▸تبني
fitالمفردات: كل كلمة مختلفة، بحروف صغيرة، ومرتبة - ▸تعطي
transformكل نص صفا من الأعداد، بعمود لكل كلمة - ▸يحذف
stop_words='english'كلمات التوقف (stop words)، أي الكلمات الشائعة جدا مثلtheوof - ▸يضيع ترتيب الكلمات: لا يبقى إلا الأعداد
تشابه جيب التمام
- ▸
AوBمتجها الأعداد لفيلمين، وnعدد كلمات المفردات - ▸
a_iوb_iعدد مرات ظهور الكلمةiفي كل فيلم - ▸
A · Bهو الضرب النقطي، و‖A‖هو طولA
قراءة قيمة جيب التمام
- ▸1: يشير المتجهان إلى الاتجاه نفسه، أي المزيج نفسه من الكلمات
- ▸0: لا يشترك الفيلمان في أي كلمة إطلاقا
- ▸الأعداد لا تكون سالبة أبدا، لذا تقع قيمة جيب التمام عندنا دائما بين 0 و1
- ▸الاتجاه وحده هو المهم: مضاعفة كل أعداد فيلم لا تغير قيمة جيب التمام
يدويا
مثال محلول: خمسة أفلام
أول خمسة صفوف من movies.csv، باستخدام العمود genres وحده. أعجب Avatar أحد المشاهدين: أي فيلم نوصي به؟
| الفيلم | genres |
|---|---|
| Avatar | Action Adventure Fantasy Science Fiction |
| Pirates of the Caribbean: At World's End | Adventure Fantasy Action |
| Spectre | Action Adventure Crime |
| The Dark Knight Rises | Action Crime Drama Thriller |
| John Carter | Action Adventure Science Fiction |
الخطوة 1: المفردات
['action' 'adventure' 'crime' 'drama' 'fantasy' 'fiction' 'science' 'thriller']الأعمدة بترتيب المفردات
الخطوة 1: متجهات الأعداد
action, adventure, crime, drama, fantasy, fiction, science, thriller
| الفيلم | متجه الأعداد | الكلمات |
|---|---|---|
| Avatar | [1 1 0 0 1 1 1 0] | 5 |
| Pirates of the Caribbean | [1 1 0 0 1 0 0 0] | 3 |
| Spectre | [1 1 1 0 0 0 0 0] | 3 |
| The Dark Knight Rises | [1 0 1 1 0 0 0 1] | 4 |
| John Carter | [1 1 0 0 0 1 1 0] | 4 |
الخطوة 2: الأطوال
| الفيلم | مجموع المربعات | الطول ‖v‖ |
|---|---|---|
| Avatar | 5 | √5 = 2.2361 |
| Pirates of the Caribbean | 3 | √3 = 1.7321 |
| Spectre | 3 | √3 = 1.7321 |
| The Dark Knight Rises | 4 | √4 = 2.0000 |
| John Carter | 4 | √4 = 2.0000 |
الخطوة 3: الضرب النقطي مع Avatar
| الفيلم | الكلمات المشتركة | A · B |
|---|---|---|
| Pirates of the Caribbean | action, adventure, fantasy | 3 |
| Spectre | action, adventure | 2 |
| The Dark Knight Rises | action | 1 |
| John Carter | action, adventure, fiction, science | 4 |
A = Avatar، وB = Pirates of the Caribbean
الخطوة 4: قيمة واحدة لجيب التمام
A = Avatar في كل الصفوف
الخطوة 4: الأفلام الثلاثة الأخرى
| الفيلم B | الحساب | cos(A, B) |
|---|---|---|
| Spectre | 2 / (2.2361 × 1.7321) = 2 / 3.8730 | 0.5164 |
| The Dark Knight Rises | 1 / (2.2361 × 2) = 1 / 4.4721 | 0.2236 |
| John Carter | 4 / (2.2361 × 2) = 4 / 4.4721 | 0.8944 |
الخطوة 5: الترتيب والتوصية
| الترتيب | الفيلم | cos(A, B) |
|---|---|---|
| 1 | John Carter | 0.8944 |
| 2 | Pirates of the Caribbean | 0.7746 |
| 3 | Spectre | 0.5164 |
| 4 | The Dark Knight Rises | 0.2236 |
التحقق باستخدام scikit-learn
from sklearn.metrics.pairwise import cosine_similarity
cv = CountVectorizer(stop_words='english')
m = cv.fit_transform(df['genres'].head(5))
sim = cosine_similarity(m)
sim[0]array([1. , 0.77459667, 0.51639778,
0.2236068 , 0.89442719])
جربها: جيب التمام خطوة بخطوة
الجزء 2
الدفتر على 4,803 أفلام
المتجهات ومصفوفة التشابه
افتح الدفتر في Colab
https://colab.research.google.com/github/
jeffprosise/Machine-Learning/blob/master/
Movie%20Recommendations.ipynbتحميل البيانات
import pandas as pd
url = ('https://raw.githubusercontent.com/'
'jeffprosise/Machine-Learning/'
'master/Data/movies.csv')
df = pd.read_csv(url)
df.shape- ▸
(4803, 24): 4,803 أفلام، و24 عمودا - ▸من بينها:
titleوgenresوkeywordsوcastوdirector - ▸وأيضا الميزانية والإيرادات ومدة العرض والأصوات: لا يستخدمها هذا النموذج
- ▸حجم الملف نحو 23 MB، لذا تستغرق الخلية بضع ثوان
احتفظ بخمسة أعمدة، واملأ الفجوات
df = df[['title', 'genres', 'keywords', 'cast', 'director']]
df = df.fillna('') # Fill missing values with empty stringsنص واحد لكل فيلم: العمود features
df['features'] = (df['title'] + ' ' + df['genres'] + ' ' +
df['keywords'] + ' ' + df['cast'] + ' ' +
df['director'])- ▸تلصق الأعمدة الخمسة في سلسلة نصية واحدة، بينها مسافات
- ▸تصبح الأسماء كلمات عادية: الاسم الأول للمخرج واسم عائلته كلمتان
- ▸مثال: يعطي العنوان
The Dark Knight Risesالكلماتdarkوknightوrises(وtheمن كلمات التوقف)
تحويل الأفلام الـ4,803 كلها إلى متجهات
vectorizer = CountVectorizer(stop_words='english', min_df=20)
word_matrix = vectorizer.fit_transform(df['features'])
word_matrix.shapeعمود features نفسه، مع stop_words='english'
كيف يشكل min_df المفردات
| min_df | الكلمات المحتفظ بها |
|---|---|
| 1 | 17,286 |
| 5 | 3,852 |
| 20 (الدفتر) | 918 |
| 50 | 271 |
مصفوفة التشابه
from sklearn.metrics.pairwise import cosine_similarity
sim = cosine_similarity(word_matrix)
sim.shape- ▸
(4803, 4803):sim[i, j]هو قيمة جيب التمام بين الفيلمينiوj - ▸متماثلة (symmetric):
sim[i, j]يساويsim[j, i] - ▸القطر يساوي 1.0 في 4,794 فيلما، أما الأفلام الـ9 الأخرى فلم تبق فيها أي كلمة، لذا كل قيم صفها 0
متجهات حقيقية من word_matrix
مثال محلول: Skyfall وSpectre
كل الأعداد تساوي 1 في المتجهين
| الكلمات من | Skyfall | Spectre | المشتركة |
|---|---|---|---|
| الأنواع | 3 | 3 | 2: action, adventure |
| الكلمات المفتاحية | 5 | 6 | 3: spy, secret, agent |
| أسماء طاقم التمثيل والإخراج | 7 | 6 | 6 |
| المجموع | 15 | 15 | 11 |
A = Skyfall، وB = Spectre
Skyfall وSpectre: قيمة جيب التمام
الجزء 3
توليد التوصيات
get_recommendations سطرا بسطر
العثور على صف الفيلم
def get_recommendations(title, df, sim, count=10):
# Get the row index of the specified title in the DataFrame
index = df.index[df['title'].str.lower() == title.lower()]
# Return an empty list if there is no entry for the specified title
if (len(index) == 0):
return []
# Get the corresponding row in the similarity matrix
similarities = list(enumerate(sim[index[0]]))- ▸مطابقة العنوان لا تفرق بين الحروف الكبيرة والصغيرة:
'skyfall'تعمل أيضا - ▸العنوان غير المعروف يعيد
[]بدلا من خطأ - ▸تقرن
enumerateكل قيمة (score) برقم فيلمها، وفي Skyfall:(0, 0.1732), (1, 0.1333), (2, 0.7333), ...
الترتيب، ثم التخطي، ثم إعادة العناوين
recommendations = sorted(similarities, key=lambda x: x[1], reverse=True)
top_recs = recommendations[1:count + 1]
titles = []
for i in range(len(top_recs)):
title = df.iloc[top_recs[i][0]]['title']
titles.append(title)
return titlesget_recommendations('Skyfall', df, sim)
Skyfall: التوصيات العشر

A = Mulan (10 كلمات)، وB = Shrek (15 كلمة)
لماذا يحصل Mulan على Shrek؟
استكشف: أي فيلم، وأي توصية
مواضع الخطأ
- ▸المتجهات الفارغة: تفقد 9 أفلام كل كلماتها بعد
min_df=20، لذا كل قيمة في صفها 0 - ▸العناوين المكررة: فيلمان اسمهما
Batman، والدالة تستخدم دائما الأول - ▸التعادل مع الفيلم نفسه: في 14 صفا لا يكون الفيلم هو العنصر 0، لذا قد يتخطى
[1:]الفيلم الخطأ - ▸المحتوى وحده: لا يرى النموذج التقييمات أبدا، لذا لا يستطيع التمييز بين فيلم جيد وفيلم سيئ
أحد المتجهات الفارغة الـ9
مثال محلول: Sharkskin
["Pirates of the Caribbean: At World's End", 'Spectre', 'The Dark Knight Rises']الجزء 4
عروض فرق المشاريع ومناقشاتها
مرحلة المشروع هذا الأسبوع
مشروع فريقك
عرض فريقك
- 1الفكرة، أو الورقة البحثية، وسبب أهميتها
- 2البيانات: المصدر، والاستكشاف، والتنظيف
- 3الخصائص (features) والمتغير الهدف (target variable) التي اخترتها
- 4النموذج الذي نفذته وطريقة تقييمك له
- 5ما ستحسنه بعد ذلك
قبل التمارين
الأخطاء الشائعة
- ▸قراءة
Data/movies.csvفي Colab، حيث لا يوجد المجلد - ▸نسيان
fillna('')، فيعطل النص المفقودCountVectorizer - ▸إعادة العنصر 0: الفيلم المفضل يوصي بنفسه
- ▸جمع الكلمات المشتركة ونسيان القسمة على الطولين
- ▸الثقة بقائمة دون قيمها (المتجهات الفارغة، والتعادلات، والعناوين المكررة)
- ▸توقع أن تحسب كلمة نادرة من العنوان بعد أن حذفها
min_df
الجزء 5
التمارين: دورك
نحو 30 دقيقة، والإجابات تلي كل مهمة
نحو 10 دقائق
التمرين 1: فيلم سادس
- ▸الصف 11 من الملف، Quantum of Solace، أنواعه
Adventure Action Thriller Crime - ▸اكتب متجه أعداده على الكلمات الـ8 نفسها، واحسب طوله
- ▸احسب قيمة جيب التمام بينه وبين كل من الأفلام الخمسة في المثال المحلول
- ▸أي فيلمين توصي بهما لمشاهد أعجبه؟
الإجابات
التمرين 1: الإجابة
- ▸A = Quantum of Solace =
[1 1 1 0 0 0 0 1]، و‖A‖ = √4 = 2
| الفيلم B | A · B | cos(A, B) |
|---|---|---|
| Spectre | 3 | 3 / (2 × 1.7321) = 0.8660 |
| The Dark Knight Rises | 3 | 3 / (2 × 2) = 0.7500 |
| Pirates of the Caribbean | 2 | 2 / (2 × 1.7321) = 0.5774 |
| John Carter | 2 | 2 / (2 × 2) = 0.5000 |
| Avatar | 2 | 2 / (2 × 2.2361) = 0.4472 |
نحو 5 دقائق
التمرين 2: الأعداد والطول
- ▸ثلاثة نصوص قصيرة: X =
space war space alien، وY =space alien robot، وZ هو X مكتوبا مرتين - ▸استخدم المفردات
alien, robot, space, warواكتب X وY وZ متجهات أعداد - ▸احسب cos(X, Y) وcos(Z, Y) وcos(X, Z)
- ▸ماذا يفعل تكرار النص بقيمة جيب التمام الخاصة به؟
الإجابات
التمرين 2: الإجابة
- ▸X =
[1, 0, 2, 1]، وY =[1, 1, 1, 0]، وZ =[2, 0, 4, 2]
نحو 10 دقائق
التمرين 3: القيم في Colab
- 1شغل الدفتر حتى
sim = cosine_similarity(word_matrix) - 2انسخ
get_recommendationsواجعلها تعيد أزواجا(title, score)، مع تقريب القيمة إلى 4 منازل عشرية - 3اطبع أعلى 5 نتائج للعنوان
'The Dark Knight Rises' - 4تحقق من القيمة الأولى يدويا من
word_matrix: الضرب النقطي ومجموعا المربعات
الإجابات
التمرين 3: الإجابة
| الترتيب | الفيلم | القيمة |
|---|---|---|
| 1 | The Dark Knight | 0.7924 |
| 2 | Batman Begins | 0.7348 |
| 3 | Harsh Times | 0.4667 |
| 4 | The Killer Inside Me | 0.4648 |
| 5 | Amidst the Devil's Wings | 0.4619 |
نحو 5 دقائق
التمرين 4: غير min_df
- ▸الشكل
(4803, 3852): تبقى كلمات أكثر بكثير - ▸يبقى Spectre أولا، لكن قيمته تنخفض من 0.7333 إلى 0.5500: في كل متجه الآن 20 كلمة، والمشتركة ما زالت 11
- ▸من الوافدين الجدد: Casino Royale (0.3500) وGoldfinger (0.2635)
الخلاصة
- 1يقترح نظام التوصية المعتمد على المحتوى العناصر التي يكون محتواها الأقرب إلى عنصر أعجبك
- 2يحول
CountVectorizerالنص إلى متجهات أعداد، ويحددstop_wordsوmin_dfالكلمات التي تحسب - 3تشابه جيب التمام هو الضرب النقطي مقسوما على الطولين: بين 0 و1 للأعداد
- 4تعطي
cosine_similarityالمصفوفة كاملة، وصف مرتب واحد منها هو قائمة توصيات - 5انظر دائما إلى القيم: فالمتجهات الفارغة والتعادلات والعناوين المكررة تعطي قوائم مضللة
افتح هذا الدرس
Mahmoud Abas|التوصيات المعتمدة على المحتوى