क्या कोई बहुत सरल, चित्रमय तरीके से, कॉस्मिक समानता का उदाहरण दे सकता है?


201

Cosine समानता लेख विकिपीडिया पर

क्या आप यहां वैक्टर दिखा सकते हैं (एक सूची में या कुछ और) और फिर गणित करते हैं, और हमें देखते हैं कि यह कैसे काम करता है?

मैं एक नौसिखिया हूं।


1
जिओमेट्री और मीनिंग ऑफ विडोज़ ( press.uchicago.edu/presssite/… ) द्वारा कॉपी लेने का प्रयास करें , मैंने इसे थोड़ी देर पहले पढ़ा और कामना की कि यह मेरे पास कई साल पहले, महान परिचयात्मक पाठ था।
नाथन हॉवेल

जवाबों:


463

इसकी तुलना करने के लिए दो बहुत ही संक्षिप्त पाठ हैं:

  1. Julie loves me more than Linda loves me

  2. Jane likes me more than Julie loves me

हम जानना चाहते हैं कि ये पाठ शब्द के समान हैं, विशुद्ध रूप से शब्द गणना (और शब्द क्रम की अनदेखी) के संदर्भ में। हम दोनों ग्रंथों से शब्दों की एक सूची बनाकर शुरू करते हैं:

me Julie loves Linda than more likes Jane

अब हम गिनते हैं कि प्रत्येक पाठ में इनमें से प्रत्येक शब्द कितनी बार दिखाई देता है:

   me   2   2
 Jane   0   1
Julie   1   1
Linda   1   0
likes   0   1
loves   2   1
 more   1   1
 than   1   1

हम हालांकि खुद शब्दों में दिलचस्पी नहीं रखते हैं। हम केवल उन दो ऊर्ध्वाधर वैक्टर में रुचि रखते हैं जो मायने रखते हैं। उदाहरण के लिए, प्रत्येक पाठ में 'मी' के दो उदाहरण हैं। हम यह तय करने जा रहे हैं कि उन दो वैक्टरों के एक फ़ंक्शन की गणना करके ये दोनों ग्रंथ एक दूसरे के कितने करीब हैं, अर्थात् उनके बीच के कोण का कोसाइन।

दो वैक्टर हैं, फिर से:

a: [2, 0, 1, 1, 0, 2, 1, 1]

b: [2, 1, 1, 0, 1, 1, 1, 1]

उनके बीच के कोण का कोसाइन लगभग 0.822 है।

ये वैक्टर 8-आयामी हैं। कोसाइन समानता का उपयोग करने का एक गुण स्पष्ट रूप से यह है कि यह एक ऐसे प्रश्न को परिवर्तित करता है जो किसी व्यक्ति की कल्पना करने की क्षमता से परे है। इस मामले में आप इसे 35 डिग्री के कोण के रूप में सोच सकते हैं जो शून्य या पूर्ण समझौते से कुछ 'दूरी' है।


12
यही वह है जिसकी तलाश में मैं हूं। बिल्कुल सही। क्या इसे "वेक्टर स्पेस मॉडल" का सबसे सरल रूप माना जाता है?
टिमेक्स

2
मुझे खुशी है कि यह आपके लिए उपयोगी था, एलेक्स। जवाब देने में देरी के लिए शर्मिंदा हूँ। मैंने थोड़ी देर में StackOverflow का दौरा नहीं किया है। वास्तव में यह "आंतरिक उत्पाद स्थान" का एक उदाहरण है। विकिपीडिया पर एक बुनियादी चर्चा है।
बिल बेल

1
क्या दस्तावेज़ की लंबाई को सामान्य करने का कोई तरीका है?
sin

1
आपको लंबाई सामान्यीकरण का उपयोग करना होगा और इससे पहले, सभी टर्म वैक्टर पर लॉग फ़्रीक्वेंसी वेटिंग का उपयोग करने का प्रयास करें। यदि आपका पहले से ही सामान्यीकृत वैक्टर के साथ काम कर रहा है, तो यह AB
अली गजनी

4
लंबाई सामान्यीकरण और TF-IDF के उपयोग के साथ अधिक विस्तृत उदाहरण: site.uottawa.ca/~diana/csi4107/cosine_tf_idf_example.pdf
माइक बी।

121

मैं अनुमान लगा रहा हूं कि आप " क्यों " कॉशन समानता का काम करने में अधिक रुचि रखते हैं (क्यों यह समानता का एक अच्छा संकेत प्रदान करता है), इसके बजाय " कैसे " इसकी गणना की जाती है (गणना के लिए उपयोग किए जाने वाले विशिष्ट संचालन)। यदि आपकी रुचि बाद में है, तो इस पोस्ट में डैनियल द्वारा इंगित संदर्भ देखें, साथ ही संबंधित एसओ प्रश्न भी

समस्या को सरल बनाने के लिए और केवल दो आयामों में काम करने के लिए, यह कैसे और कितना अधिक है, दोनों को समझाने के लिए, यह उपयोगी है। एक बार जब आप 2 डी में इसे प्राप्त करते हैं, तो इसे तीन आयामों में सोचना आसान होता है, और निश्चित रूप से कई और आयामों में कल्पना करना कठिन होता है, लेकिन तब तक हम संख्यात्मक गणना करने के लिए रैखिक बीजगणित का उपयोग कर सकते हैं और हमें शब्दों में सोचने में भी मदद कर सकते हैं। लाइनों / वैक्टर / "विमानों" / "क्षेत्रों" के n आयामों में, भले ही हम इन्हें आकर्षित नहीं कर सकते।

इसलिए, दो आयामों में : पाठ समानता के संबंध में इसका मतलब है कि हम दो अलग-अलग शब्दों पर ध्यान केंद्रित करेंगे, "लंदन" और "पेरिस" शब्द कहें, और हम यह गिनेंगे कि इनमें से प्रत्येक शब्द कितनी बार मिला है। दो दस्तावेजों की हम तुलना करना चाहते हैं। यह हमें, प्रत्येक दस्तावेज़ के लिए, एक्स प्लेन में एक बिंदु देता है। उदाहरण के लिए, यदि Doc1 में एक बार पेरिस, और लंदन में चार बार, (1,4) पर एक बिंदु इस दस्तावेज़ को प्रस्तुत करेगा (दस्तावेजों के इस कम मूल्यांकन के संबंध में)। या, वैक्टरों के संदर्भ में बोलते हुए, यह Doc1 दस्तावेज़ एक तीर होगा जो मूल से बिंदु (1,4) तक जाएगा। इस छवि को ध्यान में रखते हुए, आइए इस बारे में सोचें कि दो दस्तावेजों के समान होने का क्या अर्थ है और यह कैसे वैक्टर से संबंधित है।

बहुत समान दस्तावेजों (फिर से आयामों के इस सीमित सेट के संबंध में) में पेरिस के संदर्भों की संख्या बहुत अधिक होगी, और लंदन के संदर्भों की बहुत ही संख्या, या शायद, इन संदर्भों का समान अनुपात हो सकता है। एक दस्तावेज़, Doc2, 2 रेफरी के साथ पेरिस और 8 रेफरी के लिए लंदन, यह भी बहुत समान होगा, केवल शायद एक लंबे समय तक पाठ या किसी तरह शहरों के नामों के अधिक दोहराव के साथ, लेकिन उसी अनुपात में। हो सकता है कि दोनों दस्तावेज़ लंदन के बारे में मार्गदर्शक हों, केवल पेरिस के संदर्भ में (और यह कि शहर कितना कच्चा है ;-) बस मजाक कर रहे हैं।

अब, कम समान दस्तावेजों में दोनों शहरों के संदर्भ भी शामिल हो सकते हैं, लेकिन अलग-अलग अनुपात में। शायद Doc2 केवल एक बार पेरिस और सात बार लंदन का हवाला देगा।

अपने एक्स प्लेन में वापस, यदि हम इन काल्पनिक दस्तावेजों को खींचते हैं, तो हम देखते हैं कि जब वे बहुत समान होते हैं, तो उनके वैक्टर ओवरलैप होते हैं (हालांकि कुछ वैक्टर लंबे समय तक हो सकते हैं), और जैसा कि वे सामान्य रूप से कम होने लगते हैं, ये वैक्टर उलटना शुरू कर देते हैं, उनके बीच एक व्यापक कोण है।

वैक्टरों के बीच के कोण को मापने से, हम उनकी समानता का एक अच्छा विचार प्राप्त कर सकते हैं , और चीजों को और भी आसान बनाने के लिए, इस कोण के कोसाइन को ले कर , हमारे पास एक अच्छा 0 से 1 या -1 से 1 मान है जो इसका सूचक है यह समानता, इस बात पर निर्भर करती है कि हम क्या और कैसे खाते हैं। छोटा कोण, बड़ा (1 के करीब) कोसाइन मान, और उच्चतर समानता भी।

चरम पर, अगर Doc1 केवल पेरिस का हवाला देता है और Doc2 केवल लंदन का हवाला देता है, तो दस्तावेजों में आम कुछ भी नहीं है। Doc1 का एक्स-अक्ष पर इसका वेक्टर होगा, Y- अक्ष पर Doc2, कोण 90 डिग्री, कोसाइन 0. इस मामले में हम कहेंगे कि ये दस्तावेज़ एक-दूसरे के लिए ऑर्थोगोनल हैं।

आयाम जोड़ना :
एक छोटे कोण (या बड़े कोसाइन) के रूप में व्यक्त समानता के लिए इस सहज महसूस के साथ, हम अब 3 आयामों में चीजों की कल्पना कर सकते हैं, मिश्रण में "एम्स्टर्डम" शब्द लाकर कह सकते हैं, और अच्छी तरह से कल्पना करें कि दो के साथ एक दस्तावेज़ कैसे प्रत्येक के संदर्भ में एक वेक्टर एक विशेष दिशा में जा रहा होगा, और हम देख सकते हैं कि यह दिशा प्रत्येक और तीन बार पेरिस और लंदन का हवाला देते हुए दस्तावेज़ की तुलना कैसे करेगी, लेकिन एम्स्टर्डम आदि नहीं, जैसा कि हमने कहा, हम इस फैंसी की कोशिश और कल्पना कर सकते हैं। 10 या 100 शहरों के लिए जगह। यह आकर्षित करना कठिन है, लेकिन अवधारणा को आसान बनाता है।

मैं केवल सूत्र के बारे में कुछ शब्द कहकर लपेटता हूँ । जैसा कि मैंने कहा है, अन्य संदर्भ गणना के बारे में अच्छी जानकारी प्रदान करते हैं।

पहले दो आयामों में। दो वैक्टर के बीच के कोण के कोसाइन का सूत्र त्रिकोणमितीय अंतर (कोण a और कोण b के बीच) से लिया गया है:

cos(a - b) = (cos(a) * cos(b)) + (sin (a) * sin(b))

यह सूत्र डॉट उत्पाद सूत्र के समान दिखता है:

Vect1 . Vect2 =  (x1 * x2) + (y1 * y2)

जहां cos(a)से मेल खाती xमूल्य और मूल्य, प्रथम वेक्टर के लिए, आदि केवल समस्या यह है कि है , आदि नहीं वास्तव में कर रहे हैं और मूल्यों, इन मूल्यों के लिए इकाई वृत्त पर पढ़ा जा करने की जरूरत है। जहां सूत्र के हरक को इन वैक्टरों की लंबाई के गुणनफल के द्वारा विभाजित करके, और निर्देशांकों को सामान्यीकृत किया जाता है।sin(a)yxycossinxy


25

यहाँ C # में मेरा कार्यान्वयन है।

using System;

namespace CosineSimilarity
{
    class Program
    {
        static void Main()
        {
            int[] vecA = {1, 2, 3, 4, 5};
            int[] vecB = {6, 7, 7, 9, 10};

            var cosSimilarity = CalculateCosineSimilarity(vecA, vecB);

            Console.WriteLine(cosSimilarity);
            Console.Read();
        }

        private static double CalculateCosineSimilarity(int[] vecA, int[] vecB)
        {
            var dotProduct = DotProduct(vecA, vecB);
            var magnitudeOfA = Magnitude(vecA);
            var magnitudeOfB = Magnitude(vecB);

            return dotProduct/(magnitudeOfA*magnitudeOfB);
        }

        private static double DotProduct(int[] vecA, int[] vecB)
        {
            // I'm not validating inputs here for simplicity.            
            double dotProduct = 0;
            for (var i = 0; i < vecA.Length; i++)
            {
                dotProduct += (vecA[i] * vecB[i]);
            }

            return dotProduct;
        }

        // Magnitude of the vector is the square root of the dot product of the vector with itself.
        private static double Magnitude(int[] vector)
        {
            return Math.Sqrt(DotProduct(vector, vector));
        }
    }
}

यह बहुत बढ़िया है, धन्यवाद, मैंने आपसे प्यार किया कि आपने मैग्निट्यूड =) कैसे समझाया
liminal18

यह बहुत अच्छा है लेकिन क्या होगा अगर हम फाइलों या तार के साथ काम कर रहे हैं।
तल्हा

21

सादगी के लिए मैं वेक्टर को कम कर रहा हूं और बी:

Let :
    a : [1, 1, 0]
    b : [1, 0, 1]

फिर कोसाइन समानता (थीटा):

 (Theta) = (1*1 + 1*0 + 0*1)/sqrt((1^2 + 1^2))* sqrt((1^2 + 1^2)) = 1/2 = 0.5

फिर कॉस 0.5 का व्युत्क्रम 60 डिग्री है।


18

यह पायथन कोड एल्गोरिथ्म को लागू करने का मेरा त्वरित और गंदा प्रयास है:

import math
from collections import Counter

def build_vector(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

def cosim(v1, v2):
    dot_product = sum(n1 * n2 for n1, n2 in zip(v1, v2) )
    magnitude1 = math.sqrt(sum(n ** 2 for n in v1))
    magnitude2 = math.sqrt(sum(n ** 2 for n in v2))
    return dot_product / (magnitude1 * magnitude2)


l1 = "Julie loves me more than Linda loves me".split()
l2 = "Jane likes me more than Julie loves me or".split()


v1, v2 = build_vector(l1, l2)
print(cosim(v1, v2))

क्या आप बता सकते हैं कि आपने "all_items = set (counter1.keys ()) संघ (सेट (counter2.keys ()))" लाइन में सेट क्यों किया था।
घोस

@ Ghos3t, कि दोनों दस्तावेजों से अलग शब्दों की सूची प्राप्त करने के लिए है
नौकरियां

7

@ बेल उदाहरण का उपयोग करते हुए, [R] में ऐसा करने के दो तरीके

a = c(2,1,0,2,0,1,1,1)

b = c(2,1,1,1,1,0,1,1)

d = (a %*% b) / (sqrt(sum(a^2)) * sqrt(sum(b^2)))

या क्रॉसप्रोड () विधि के प्रदर्शन का लाभ उठा रहा है ...

e = crossprod(a, b) / (sqrt(crossprod(a, a)) * sqrt(crossprod(b, b)))

5

यह एक सरल Pythonकोड है जो कोसाइन समानता को लागू करता है।

from scipy import linalg, mat, dot
import numpy as np

In [12]: matrix = mat( [[2, 1, 0, 2, 0, 1, 1, 1],[2, 1, 1, 1, 1, 0, 1, 1]] )

In [13]: matrix
Out[13]: 
matrix([[2, 1, 0, 2, 0, 1, 1, 1],
        [2, 1, 1, 1, 1, 0, 1, 1]])
In [14]: dot(matrix[0],matrix[1].T)/np.linalg.norm(matrix[0])/np.linalg.norm(matrix[1])
Out[14]: matrix([[ 0.82158384]])

3
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * 
* @author Xiao Ma
* mail : 409791952@qq.com
*
*/
  public class SimilarityUtil {

public static double consineTextSimilarity(String[] left, String[] right) {
    Map<String, Integer> leftWordCountMap = new HashMap<String, Integer>();
    Map<String, Integer> rightWordCountMap = new HashMap<String, Integer>();
    Set<String> uniqueSet = new HashSet<String>();
    Integer temp = null;
    for (String leftWord : left) {
        temp = leftWordCountMap.get(leftWord);
        if (temp == null) {
            leftWordCountMap.put(leftWord, 1);
            uniqueSet.add(leftWord);
        } else {
            leftWordCountMap.put(leftWord, temp + 1);
        }
    }
    for (String rightWord : right) {
        temp = rightWordCountMap.get(rightWord);
        if (temp == null) {
            rightWordCountMap.put(rightWord, 1);
            uniqueSet.add(rightWord);
        } else {
            rightWordCountMap.put(rightWord, temp + 1);
        }
    }
    int[] leftVector = new int[uniqueSet.size()];
    int[] rightVector = new int[uniqueSet.size()];
    int index = 0;
    Integer tempCount = 0;
    for (String uniqueWord : uniqueSet) {
        tempCount = leftWordCountMap.get(uniqueWord);
        leftVector[index] = tempCount == null ? 0 : tempCount;
        tempCount = rightWordCountMap.get(uniqueWord);
        rightVector[index] = tempCount == null ? 0 : tempCount;
        index++;
    }
    return consineVectorSimilarity(leftVector, rightVector);
}

/**
 * The resulting similarity ranges from −1 meaning exactly opposite, to 1
 * meaning exactly the same, with 0 usually indicating independence, and
 * in-between values indicating intermediate similarity or dissimilarity.
 * 
 * For text matching, the attribute vectors A and B are usually the term
 * frequency vectors of the documents. The cosine similarity can be seen as
 * a method of normalizing document length during comparison.
 * 
 * In the case of information retrieval, the cosine similarity of two
 * documents will range from 0 to 1, since the term frequencies (tf-idf
 * weights) cannot be negative. The angle between two term frequency vectors
 * cannot be greater than 90°.
 * 
 * @param leftVector
 * @param rightVector
 * @return
 */
private static double consineVectorSimilarity(int[] leftVector,
        int[] rightVector) {
    if (leftVector.length != rightVector.length)
        return 1;
    double dotProduct = 0;
    double leftNorm = 0;
    double rightNorm = 0;
    for (int i = 0; i < leftVector.length; i++) {
        dotProduct += leftVector[i] * rightVector[i];
        leftNorm += leftVector[i] * leftVector[i];
        rightNorm += rightVector[i] * rightVector[i];
    }

    double result = dotProduct
            / (Math.sqrt(leftNorm) * Math.sqrt(rightNorm));
    return result;
}

public static void main(String[] args) {
    String left[] = { "Julie", "loves", "me", "more", "than", "Linda",
            "loves", "me" };
    String right[] = { "Jane", "likes", "me", "more", "than", "Julie",
            "loves", "me" };
    System.out.println(consineTextSimilarity(left,right));
}
}

3

कॉस्मिक समानता की गणना करने के लिए सरल जावा कोड

/**
   * Method to calculate cosine similarity of vectors
   * 1 - exactly similar (angle between them is 0)
   * 0 - orthogonal vectors (angle between them is 90)
   * @param vector1 - vector in the form [a1, a2, a3, ..... an]
   * @param vector2 - vector in the form [b1, b2, b3, ..... bn]
   * @return - the cosine similarity of vectors (ranges from 0 to 1)
   */
  private double cosineSimilarity(List<Double> vector1, List<Double> vector2) {

    double dotProduct = 0.0;
    double normA = 0.0;
    double normB = 0.0;
    for (int i = 0; i < vector1.size(); i++) {
      dotProduct += vector1.get(i) * vector2.get(i);
      normA += Math.pow(vector1.get(i), 2);
      normB += Math.pow(vector2.get(i), 2);
    }
    return dotProduct / (Math.sqrt(normA) * Math.sqrt(normB));
  }

1
यह एक "सरल, चित्रमय तरीका" नहीं है, लेकिन अभी तक सिर्फ कोड है। हालाँकि अन्य लोगों ने भी यही त्रुटि की है: /
Skrylar

-1

दो सेक्टर ए और बी एक 2 डी अंतरिक्ष या 3 डी अंतरिक्ष में मौजूद हैं, उन वैक्टर के बीच का कोण कॉस समानता है।

यदि कोण अधिक है (अधिकतम 180 डिग्री तक पहुंच सकता है) जो कि Cos 180 = -1 है और न्यूनतम कोण 0 डिग्री है। cos 0 = 1 का अर्थ है कि वैक्टर एक-दूसरे से जुड़े हुए हैं और इसलिए वैक्टर समान हैं।

cos 90 = 0 (जो यह निष्कर्ष निकालने के लिए पर्याप्त है कि वैक्टर A और B एक समान नहीं हैं और चूंकि दूरी कैंटीन नकारात्मक हो सकती है, cosine मान 0 से 1 तक झूठ होंगे। इसलिए, अधिक कोण का तात्पर्य समानता को कम करने से है (इसे भी देखें) समझ में आता है)

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.