جيب التمام تشابه ناقلات من أطوال مختلفة؟
-
30-09-2019 - |
سؤال
أحاول استخدام TF-IDF لفرز المستندات إلى فئات. لقد قمت بحساب TF_IDF لبعض المستندات ، لكن الآن عندما أحاول حساب تشابه جيب التمام بين اثنين من هذه المستندات ، أحصل على تتبع قائل:
#len(u)==201, len(v)==246
cosine_distance(u, v)
ValueError: objects are not aligned
#this works though:
cosine_distance(u[:200], v[:200])
>> 0.52230249969265641
هل تقطيع المتجه بحيث len (u) == len (v) النهج الصحيح؟ أعتقد أن تشابه جيب التمام سيعمل مع متجهات بأطوال مختلفة.
أنا استخدم هذه الوظيفة:
def cosine_distance(u, v):
"""
Returns the cosine of the angle between vectors v and u. This is equal to
u.v / |u||v|.
"""
return numpy.dot(u, v) / (math.sqrt(numpy.dot(u, u)) * math.sqrt(numpy.dot(v, v)))
أيضًا - هل ترتيب قيم TF_IDF في المتجهات مهم؟ هل يجب فرزها - أم أنها ليست ذات أهمية لهذا الحساب؟
المحلول
هل تقوم بحساب تشابه جيب التمام من ناقلات المصطلح؟ يجب أن تكون المتجهات المدى بنفس الطول. إذا لم تكن الكلمات موجودة في مستند ، فيجب أن يكون لها قيمة 0 لهذا المصطلح.
لست متأكدًا تمامًا من المتجهات التي تقوم بتطبيق تشابه جيب التمام إليها ، ولكن عند القيام بتشابه جيب التمام ، يجب أن تكون المتجهات الخاصة بك دائمًا بنفس الطول وأن ترتيب يهم كثيرًا.
مثال:
Term | Doc1 | Doc2
Foo .3 .7
Bar | 0 | 8
Baz | 1 | 1
هنا لديك اثنين من المتجهات (.3،0،1) و (.7،8،1) ويمكن أن تحسب تشابه جيب التمام بينهما. إذا قارنت (.3،1) و (.7،8) ، فستقارن درجة DOC1 من BAZ مقابل درجة DOC2 التي لن يكون لها معنى.
نصائح أخرى
تحتاج إلى ضرب الإدخالات للكلمات المقابلة في المتجه ، لذلك يجب أن يكون هناك ترتيب عالمي للكلمات. هذا يعني أنه من الناحية النظرية يجب أن تكون ناقلاتك بنفس الطول.
في الممارسة العملية ، إذا شوهد أحد المستندات من قبل الآخر ، فقد تمت إضافة الكلمات الواردة في المستند الثاني إلى الطلب العالمي بعد رؤية المستند الأول ، لذلك على الرغم من أن المتجهات لها نفس الترتيب ، فقد يكون المستند الأول أقصر ، منذ ذلك الحين ، منذ ذلك الحين ليس لديها إدخالات للكلمات التي لم تكن في هذا المتجه.
الوثيقة 1: قفز الثعلب البني السريع فوق الكلب الكسول.
Global order: The quick brown fox jumped over the lazy dog
Vector for Doc 1: 1 1 1 1 1 1 1 1 1
الوثيقة 2: كان العداء سريعًا.
Global order: The quick brown fox jumped over the lazy dog runner was
Vector for Doc 1: 1 1 1 1 1 1 1 1 1
Vector for Doc 2: 1 1 0 0 0 0 0 0 0 1 1
في هذه الحالة ، من الناحية النظرية ، تحتاج إلى وضع متجه المستند 1 مع الأصفار في النهاية. في الممارسة العملية ، عند حساب منتج DOT ، تحتاج فقط إلى مضاعفة العناصر حتى نهاية المتجه 1 (لأن حذف العناصر الإضافية من المتجه 2 وضربها على الصفر هي نفسها تمامًا ، لكن زيارة العناصر الإضافية أبطأ).
ثم يمكنك حساب حجم كل متجه بشكل منفصل ، ولهذا لا تحتاج المتجهات إلى أن تكون بنفس الطول.
حاول بناء المتجهات قبل إطعامها إلى وظيفة comtin_distance:
import math
from collections import Counter
from nltk import cluster
def buildVector(iterable1, iterable2):
counter1 = Counter(iterable1)
counter2= Counter(iterable2)
all_items = set(counter1.keys()).union( set(counter2.keys()) )
vector1 = [counter1[k] for k in all_items]
vector2 = [counter2[k] for k in all_items]
return vector1, vector2
l1 = "Julie loves me more than Linda loves me".split()
l2 = "Jane likes me more than Julie loves me or".split()
v1,v2= buildVector(l1, l2)
print(cluster.util.cosine_distance(v1,v2))