الـ Embeddings والبحث الدلالي· الدرس 2 من 7
قياس التشابه بين الفيكتورات
في سطر واحد · عشان تعرف نصّين قد إيه قريبين في المعنى، بتقيس المسافة أو الزاوية بين الفيكتورين — والأشهر هو cosine similarity.
ده القلب اللي بيرتّب نتايج أي بحث دلالي: طريقة القياس بتحدّد مين يطلع فوق ومين ينزل تحت، فلو غلطت فيها البحث كله بيبوظ.
cosine بيبصّ للاتجاه مش الطول: نصّين ماشيين في نفس الاتجاه = متشابهين، حتى لو واحد أطول من التاني. النتيجة بين -1 (عكس) و1 (نفس المعنى).
زي بوصلتين: مايهمّكش إبرة أطول من التانية، اللي يهمّك الاتنين مأشّرين على نفس الاتجاه ولا لأ. cosine بيقيس الاتجاه بالظبط ومابيبصّش للطول.
استعلام «إزاي أعمل ريستارت للسيرفر» بيطلع cosine عالي مع مقال «إعادة تشغيل الخادم»، وواطي مع «وصفة كشري» — فبتعرض الأول وتتجاهل التاني.
cosine similarity بيتحسب كالتالي: حاصل الضرب النقطي (dot product) للفيكتورين مقسوم على حاصل ضرب طوليهما — يعني بتشيل تأثير الطول وبيفضل الاتجاه بس. فيه مقاييس تانية: dot product الخام (بيتأثر بالطول) والمسافة الإقليدية (بتقيس البعد المباشر). موديلات كتير بتطلّع فيكتورات normalized (طولها 1)، وساعتها cosine وdot product بيدّوا نفس الترتيب بالظبط. القاعدة العملية: استخدم المقياس اللي الموديل اتدرّب عليه — صفحة الموديل بتقولك.
// cosine similarity بين فيكتورين
function cosine(a: number[], b: number[]): number {
let dot = 0, na = 0, nb = 0;
for (let i = 0; i < a.length; i++) {
dot += a[i] * b[i];
na += a[i] * a[i];
nb += b[i] * b[i];
}
return dot / (Math.sqrt(na) * Math.sqrt(nb));
}
// قريب من 1 = نفس المعنى، قريب من 0 = مالهمش علاقة🧪 جرّب بنفسك: اكتب استعلام واحد و٥ جُمل (٢ قريبين منه، ٢ بعاد، وواحدة في النص). اعمل embedding للكل بنفس الموديل، احسب cosine بين الاستعلام وكل جملة بالدالة اللي فوق، ورتّبهم تنازلي. شوف الترتيب مطابق لإحساسك ولا فيه مفاجآت — والمفاجآت دي هي اللي بتعلّمك حدود الموديل.
أشهر غلطة: تعامل قيمة الـ cosine كنسبة مئوية مطلقة — «0.8 يعني 80% تشابه». القيم دي نسبية لكل موديل: في موديل معيّن 0.8 ممكن تكون تطابق قوي، وفي تاني تكون عادية جدًا؛ حدّد الـ threshold بالتجربة على بياناتك. غلطة تانية: تخلط بين المقاييس — تخزّن في قاعدة متظبطة على cosine وتستعلم بـ Euclidean. وتالتة: تقارن قيم تشابه جاية من موديلين مختلفين.
استخدم cosine كاختيار افتراضي لتشابه النصوص — هو الأنسب لما يهمّك المعنى مش «شدّة» النص، وأغلب موديلات الـ embedding متدرّبة عليه أو على dot product مع normalization.
لو الموديل بتاعك متدرّب على dot product من غير normalization (زي بعض موديلات الترشيحات)، الطول نفسه شايل معلومة — استخدم dot product زي ما الموديل متوقّع. ولو بتقارن حاجات مش embeddings أصلًا (إحداثيات، قياسات فيزيائية) المسافة الإقليدية غالبًا أنسب.