2010-06-25 28 views
10

I'm trying to use 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 

वेक्टर टुकड़ा करने की क्रिया है ताकि लेन (यू) == लेन (वी) सही दृष्टिकोण? मुझे लगता है कि कोसाइन समानता विभिन्न लंबाई के वैक्टरों के साथ काम करेगी।

मैं this function उपयोग कर रहा हूँ:

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 मानों का क्रम है? क्या उन्हें हल किया जाना चाहिए - या यह इस गणना के लिए कोई महत्व नहीं है?

उत्तर

5

क्या आप शब्द वैक्टर की कोसाइन समानता की गणना कर रहे हैं? टर्म वैक्टर एक ही लंबाई होना चाहिए। यदि दस्तावेज़ किसी दस्तावेज़ में मौजूद नहीं हैं तो उस शब्द के लिए 0 का मान होना चाहिए।

मुझे बिल्कुल यकीन नहीं है कि आप किस वैक्टर को कोसाइन समानता लागू कर रहे हैं लेकिन कोसाइन समानता करते समय आपके वैक्टर हमेशा एक ही लंबाई और क्रम होना चाहिए, इससे कोई फर्क नहीं पड़ता।

उदाहरण:

Term | Doc1 | Doc2 
Foo  .3  .7 
Bar | 0 | 8 
Baz | 1 | 1 

यहाँ आप दो वैक्टर है (.3,0,1) और (.7,8,1) और उन दोनों के बीच कोज्या समानता की गणना कर सकते हैं। यदि आपने तुलना की है (.3,1) और (.7,8) आप बार के डॉक 2 स्कोर के खिलाफ बाज़ के डॉक 1 स्कोर की तुलना करेंगे जो समझ में नहीं आता है।

+0

वैक्टर कि मैं cosine_distance कार्य करने के लिए गुजर रहा हूँ tf_idf मूल्यों का अजगर सूची नहीं है। v [: 5] == [.0060830126968545294, .00048241996565891193, .0020712248617478965, .0110036199241575, .0110036199241575] आपको मामलों कहते हैं - वेक्टर (smallest-> सबसे बड़ा, के आदेश की सामग्री सॉर्ट करने के लिए सही तरीका क्या है क्या दस्तावेज़ में शब्द?) – erikcw

+0

आपको शब्दों के लिए कुछ वैश्विक आदेश असाइन करना होगा। यदि बार 2 में foo से पहले बार प्रकट होता है तो बार के tf_idf मान को पहले आइटम होना चाहिए। – Pace

9

आप वेक्टर में शब्द इसी के लिए प्रविष्टियों गुणा की जरूरत है, इसलिए वहाँ शब्द के लिए एक वैश्विक आदेश होना चाहिए। इसका मतलब है कि सिद्धांत में आपके वैक्टर एक ही लंबाई होना चाहिए।

प्रैक्टिस में, यदि एक दस्तावेज़ दूसरे के सामने देखा गया था, तो दूसरे दस्तावेज़ में शब्दों को पहले दस्तावेज़ के बाद वैश्विक क्रम में जोड़ा जा सकता था, भले ही वैक्टरों का एक ही आदेश हो, पहला दस्तावेज़ हो सकता है कम हो, क्योंकि इसमें उन शब्दों के लिए प्रविष्टियां नहीं हैं जो उस वेक्टर में नहीं थीं।

दस्तावेज़ 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 वेक्टर पैड की जरूरत है। अभ्यास में, डॉट उत्पाद की गणना करते समय, आपको केवल वेक्टर 1 के अंत तक तत्वों को गुणा करने की आवश्यकता होती है (क्योंकि वेक्टर 2 के अतिरिक्त तत्वों को छोड़कर और शून्य से गुणा करके समान रूप से वही होते हैं, लेकिन अतिरिक्त तत्वों का दौरा धीमा होता है)।

तो फिर तुम अलग से प्रत्येक वेक्टर के परिमाण की गणना, और के लिए है कि वैक्टर एक ही लंबाई के होने की जरूरत नहीं है सकते हैं।

+0

कोसाइन-समानता की गणना करते समय, गद्दीदार शून्य एक अंतर डालते हैं। जो काम मैं कोसाइन समानता के लिए उपयोग कर रहा हूं वह है: कोसाइन-समानता = डॉट-उत्पाद (यू, वी)/एसकर्ट (डॉट-उत्पाद (यू, यू)) * एसकर्ट (डॉट-उत्पाद (वी, वी)) कोसाइन-समानता ([1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,], [1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1]) == 0.3333333333333333 कोसाइन-समानता ([1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 0, 0, 0, 0, 0, 0, 0 ]) == 0.4714045207910316 ऐसा लगता है कि समस्या यह है कि कोसाइन-समानता का विभाजक स्वयं का एक डॉट-उत्पाद करता है। तो पैडिंग का असर पड़ता है। क्या आप इसके बारे में किसी भी तरह से जानते हैं? – erikcw

+0

@erikcw: जब आप 'Doc1 * Doc1' के लिए डॉट-उत्पादों की गणना करते हैं तो आपको' Doc1' की पूर्ण लंबाई पर जाना होगा, लेकिन आगे नहीं। 'Doc2 * Doc2' के लिए आपको 'Doc2' की पूर्ण लंबाई पर जाना होगा, लेकिन आगे नहीं। डॉट उत्पाद के उस हिस्से के लिए, लंबे वेक्टर को छोटा न करें, लेकिन छोटे वेक्टर पैड के लिए अनावश्यक है। हालांकि, 'Doc1 * Doc2' की गणना करते समय, आप लंबे वेक्टर को सुरक्षित रूप से छोटा कर सकते हैं। इसलिए आपके कोड को 'डॉट-प्रोडक्ट' फ़ंक्शन को 'कोसाइन-समानता' फ़ंक्शन उन निर्णयों को करने के बजाय, पैडिंग/छंटनी के बारे में निर्णय लेने के लिए डिज़ाइन किया जाना चाहिए। –

+0

@ लार्समैन: दूसरे आंकड़े में वैक्टरों की बेमेल लंबाई जानबूझकर है। –

2

उन्हें cosine_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))