انتقل إلى المحتوى الرئيسي

الوحدة 2 — التصفية التعاونيّة القائمة على المستخدم وعلى العنصر

الوحدة السابقة أثبتت أنّ المسألة ترتيب لقائمة على مصفوفة نادرة. الآن نُنتج أوّل توصية عمليّة بمبدأ بسيط: مَن يشبهك يُحبّ ما ستحبّ. هذا هو جوهر التصفية التعاونيّة القائمة على الذاكرة، وهي طريقة تسبق كلّ نموذج، ولا تزال تُستعمَل خطًّا مرجعيًّا لكلّ نظام إنتاج جادّ.

فرضيّة الجوار: المستخدم أم العنصر؟

يوجد شكلان متكافئان في المبدأ ومختلفان في السلوك.

الجوار على المستخدم يقول: لأوصي المتعلّم أحمد بدورة، أبحث عن المتعلّمين الأكثر شبهًا به في تقييماتهم السابقة، ثمّ أرجّح تقييماتهم على الدورات الجديدة. يقوم على الحدس أنّ لكلّ شخص «توأمًا في الذوق».

الجوار على العنصر يقلب الاتّجاه: لأوصي بدورة، أبحث عن الدورات الشبيهة بما أعجب أحمد سابقًا. الفرق ليس شكليًّا؛ في منصّتنا، لدينا خمسمئة دورة و50000 متعلّم، فحساب تشابه المتعلّمين يعالج 50000×50000 زوجًا، بينما تشابه الدورات يعالج 500×500 = 250000 زوجًا فقط. ولأنّ ذوق الدورات أكثر استقرارًا من مزاج المتعلّم الفرديّ، فإنّ Amazon أعلنت في عام 2003 أنّها انتقلت إلى جوار العنصر لهذَين السببَين بالذات، وأصبح هذا التصميم المعياريّ.

قاعدة عمليّة: إذا كان عدد العناصر أقلّ من عدد المستخدمين بكثير، فاعتماد جوار العنصر أفضل من ناحية الحساب والاستقرار.

قياس التشابه

يوجد ثلاثة مقاييس شائعة، ولكلّ منها فخّ.

تشابه الكوسينوس بين متجهَي تقييم uu وvv:

cos(u,v)=iru,irv,iiru,i2irv,i2\text{cos}(u,v) = \frac{\sum_i r_{u,i} r_{v,i}}{\sqrt{\sum_i r_{u,i}^2}\,\sqrt{\sum_i r_{v,i}^2}}

يعمل جيّدًا حين تكون الإشارة ثنائيّة (سُجّل / لم يُسجّل). لكنّه على النقاط 1–5 يقع في فخّ: مستخدم يُقيّم كلّ شيء بأربع نجوم يبدو شبيهًا بمستخدم يُقيّم كلّ شيء بنجمتَين. الاثنان في نفس الاتّجاه من نقطة الأصل.

معامل بيرسون يُصلح هذا بطرح متوسّط تقييم كلّ مستخدم:

pearson(u,v)=i(ru,irˉu)(rv,irˉv)i(ru,irˉu)2i(rv,irˉv)2\text{pearson}(u,v) = \frac{\sum_i (r_{u,i}-\bar{r}_u)(r_{v,i}-\bar{r}_v)}{\sqrt{\sum_i (r_{u,i}-\bar{r}_u)^2}\,\sqrt{\sum_i (r_{v,i}-\bar{r}_v)^2}}

المقارنة تتمّ الآن على الانحرافات عن المتوسّط، لا على القيم المطلقة. مستخدم متحمّس دائمًا يصير مقارنًا بمستخدم متشائم دائمًا على أساس النمط، لا على أساس المستوى.

الفخّ الثالث: التشابه المحسوب على عنصر واحد أو عنصرَين مشترَكَين يُصبح صدفة. لذا يُشترَط عادةً حدّ أدنى (خمسة عناصر مشترَكة على الأقلّ) قبل الاعتماد على القيمة. أدناه هذا الحدّ، نُرجع صفرًا.

صيغة التنبّؤ الموزون

بعد اختيار k جارًا، نحسب تقدير تقييم المستخدم uu للعنصر ii:

r^u,i=rˉu+vNk(u)sim(u,v)(rv,irˉv)vNk(u)sim(u,v)\hat{r}_{u,i} = \bar{r}_u + \frac{\sum_{v \in N_k(u)} \text{sim}(u,v)\,(r_{v,i}-\bar{r}_v)}{\sum_{v \in N_k(u)} |\text{sim}(u,v)|}

المصطلحات تستحقّ التوقّف. متوسّط تقييم المستخدم rˉu\bar{r}_u يُصفّي مستواه الشخصيّ (المتفائل يعطي 4 حيث يعطي غيره 3). الانحرافات rv,irˉvr_{v,i}-\bar{r}_v تُقاس هي الأخرى بالنسبة للمتوسّط لكلّ جار. الوزن هو التشابه، والمقام يعيد الحساب إلى المقياس نفسه بغضّ النظر عن عدد الجيران وتشابهاتهم.

هذه الصيغة ليست ابتكارًا: هي متوسّط مرجّح تصحّح فيه كلّ نقطة بمتوسّط صاحبها.

اختيار k وحدود الجوار

قيمة k الصغيرة (5–10) تُعطي توصيات دقيقة لكنّها ضعيفة التغطية: كثير من العناصر لا يجد لها الجيران أيّ تقييم. قيمة k الكبيرة (100–200) تزيد التغطية لكنّها تُذيب التمييز: كلّ توصية تُصبح متوسّطًا للجميع، فتتقارب من مجرّد ترتيب بالشعبيّة.

قاعدة عمليّة على منصّتنا: k بين 20 و50 نقطة توازن جيّدة. الأدقّ: ضبط k بالتحقّق المتقاطع على مقياس ترتيب لا على RMSE (نعود لهذه النقطة في الوحدة الثامنة).

التنفيذ: جوار العنصر بمنصّة surprise

مكتبة surprise تُوفّر تنفيذًا متينًا للطرق القائمة على الذاكرة. المثال هنا على منصّة الدورات:

import pandas as pd
from surprise import Dataset, Reader, KNNWithMeans
from surprise.model_selection import cross_validate

# ratings.csv : userId, courseId, rating (1..5)
df = pd.read_csv("ratings.csv")

reader = Reader(rating_scale=(1, 5))
data = Dataset.load_from_df(df[["userId", "courseId", "rating"]], reader)

algo = KNNWithMeans(
k=30, # عدد الجيران
sim_options={
"name": "pearson_baseline", # يُعالج فخّ الكوسينوس
"user_based": False, # جوار العنصر
"min_support": 5, # حدّ العناصر المشترَكة
},
)

resultats = cross_validate(algo, data, measures=["RMSE", "MAE"], cv=5, verbose=True)

الخيار user_based=False يُبدّل الجوار من المستخدم إلى العنصر. min_support=5 يُلغي التشابهات المحسوبة على أقلّ من خمسة تقييمات مشترَكة، وهو ما يقتل الضجيج في المصفوفات النادرة. القيمة الافتراضيّة min_support=1 مُغرية لكنّها خطر.

قيود صادقة

الطرق القائمة على الذاكرة تعمل جيّدًا حتّى بضعة ملايين تفاعل، لكن لها ثلاث ضعف يجب معرفتها.

الأولى: الكلفة الحسابيّة. حساب كلّ التشابهات ينمو بمربّع عدد العناصر (أو المستخدمين). فوق مليون عنصر، الحساب المباشر لا يُطاق، ونحتاج إلى تقنيّات بحث الجيران التقريبيّ (سنعود إليها في الوحدة السادسة).

الثانية: الندرة الحرجة. حين تصبح المصفوفة أنحف من 0.5%، يقلّ عدد التقييمات المشترَكة كثيرًا، وتصبح كلّ التشابهات صغيرة، وتقلّ ثقة كلّ توصية. هنا يبدأ تفكيك المصفوفات في التفوّق (الوحدة 3).

الثالثة: البداية الباردة. عنصر جديد لا يملك أيّ تقييم، فلا يجد له الجيران أيّ عنصر مقارَن. مستخدم جديد كذلك. هذه المشكلة لا تحلّها التصفية التعاونيّة وحدها؛ نحتاج إلى المحتوى (الوحدات 4 و7).

الخيار العمليّ

ابدأ دومًا بجوار العنصر مع Pearson المُصحَّح وk حوالي 30 كخطّ مرجعيّ. أيّ نموذج لاحق لا يتغلّب عليه بوضوح لا يستحقّ الإنتاج.

الخلاصة

  • جوار العنصر يفوق جوار المستخدم حين يكون عدد العناصر أقلّ من عدد المستخدمين بكثير، وهو التصميم القياسيّ منذ Amazon 2003.
  • الكوسينوس يخدع على النقاط لأنّه لا يُلغي مستوى المستخدم؛ Pearson يُصلحه بطرح المتوسّط.
  • صيغة التنبّؤ الموزون تجمع انحرافات الجيران عن متوسّطاتهم، مرجّحةً بالتشابه، مع تصحيح بمتوسّط المستخدم المستهدَف.
  • الحدود: كلفة O(n2)O(n^2)، ضعف على الندرة الحادّة، عجز عن البداية الباردة. هذه الثلاثة تدفعنا إلى الوحدات التالية.

الوحدة التالية: تفكيك المصفوفات وSVD، الذي يستخرج عوامل كامنة من المصفوفة النادرة بدل حساب التشابهات مباشرةً.