Birisi kosinüs benzerliğine çok basit, grafik bir şekilde örnek verebilir mi?


201

Wikipedia'da Kosinüs Benzerlik makalesi

Vektörleri burada (bir listede veya bir şeyde) gösterebilir ve daha sonra matematiği yapabilir ve nasıl çalıştığını görelim mi?

Acemiyim.


1
Widdows ( press.uchicago.edu/presssite/… ) tarafından Geometri ve Anlam'ın bir kopyasını almayı deneyin , bir süre önce okudum ve birkaç yıl önce büyük tanıtım metni olmasını diledim.
Nathan Howell

Yanıtlar:


464

Karşılaştırılacak iki kısa metin:

  1. Julie loves me more than Linda loves me

  2. Jane likes me more than Julie loves me

Bu metinlerin ne kadar benzer olduğunu bilmek istiyoruz, sadece kelime sayıları açısından (ve kelime sırasını göz ardı ederek). Her iki metinden de kelimelerin bir listesini yaparak başlıyoruz:

me Julie loves Linda than more likes Jane

Şimdi, bu kelimelerin her birinin her metinde kaç kez göründüğünü sayıyoruz:

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

Yine de kelimelerin kendileri ile ilgilenmiyoruz. Sadece bu iki dikey sayım vektörü ile ilgileniyoruz. Örneğin, her metinde iki "ben" örneği vardır. Bu iki vektörün bir fonksiyonunu yani aralarındaki açının kosinüsünü hesaplayarak bu iki metnin birbirine ne kadar yakın olduğuna karar vereceğiz.

İki vektör yine:

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

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

Aralarındaki açının kosinüsü yaklaşık 0.822'dir.

Bu vektörler 8 boyutludur. Kosinüs benzerliğini kullanmanın bir erdemi, açıkça insanın görselleştirme yeteneğinin ötesinde bir soruyu olabilecek bir soruna dönüştürmesidir. Bu durumda, bunu sıfırdan veya mükemmel anlaşmadan bir miktar 'mesafe' olan yaklaşık 35 derecelik açı olarak düşünebilirsiniz.


12
Tam da aradığım şey buydu. Kesinlikle. Bu, "vektör uzay modeli" nin en basit şekli olarak mı kabul edilir?
TIMEX

2
Bunun sizin için yararlı olduğuna sevindim, Alex. Cevap gecikmesi için üzgünüz. Bir süredir StackOverflow'u ziyaret etmedim. Aslında bu bir "iç ürün alanı" örneğidir. Wikipedia hakkında temel bir tartışma var.
Bill Bell

1
Belge uzunluğunu normalleştirmenin bir yolu var mı?
sinθ

1
Uzunluk normalizasyonu kullanmalısınız ve bundan önce tüm terim vektörlerinde log frekansı ağırlıklandırmayı kullanmaya çalışın. Zaten normalize edilmiş vektörlerle uğraşıyorsanız, AB'nin nokta ürünüdür
Ali Gajani

4
Uzunluk normalizasyonu ve TF-IDF kullanımı ile daha ayrıntılı örnek: site.uottawa.ca/~diana/csi4107/cosine_tf_idf_example.pdf
Mike B.

121

Sana "içine bazı bilgiler almak daha fazla ilgilenen tahmin ediyorum neden ziyade, (o benzerlik iyi bir gösterge sağlar neden)" kosinüs benzerliği işler " nasıl " hesaplanır (hesaplamada kullanılan özel operasyonlar). Eğer ilgi sonuncusu ise, bu yazı Daniel tarafından belirtilen referans yanı sıra ilgili bir SO Soru bakın .

Hem nasıl hem de daha fazla nedenini açıklamak için, öncelikle sorunu basitleştirmek ve sadece iki boyutta çalışmak faydalıdır. Bunu 2D olarak aldıktan sonra, üç boyutlu olarak düşünmek daha kolay ve elbette daha fazla boyutta hayal etmek daha zor, ancak o zamana kadar sayısal hesaplamaları yapmak ve aynı zamanda terimler içinde düşünmemize yardımcı olmak için doğrusal cebiri kullanabiliriz. bunları çizemesek bile, n boyutlarında çizgiler / vektörler / "düzlemler" / "küreler".

Yani, iki boyutta : metin benzerliği ile ilgili olarak bu, iki farklı terime odaklanacağımız anlamına gelir, "Londra" ve "Paris" kelimelerini söyleyin ve bu kelimelerin her birinde kaç kez bulunduğunu sayarız iki belgeyi karşılaştırmak istiyoruz. Bu bize her belge için xy düzleminde bir nokta verir. Örneğin, Doc1 bir kez Paris'e ve dört kez Londra'ya sahip olsaydı, (1,4) 'te bir nokta bu belgeyi sunacaktır (belgelerin bu küçük değerlendirmesiyle ilgili olarak). Veya, vektörler açısından konuşursak, bu Doc1 belgesi başlangıç ​​noktasından noktaya (1,4) giden bir ok olacaktır. Bu görüntü göz önünde bulundurularak, iki belgenin benzer olmasının ne anlama geldiğini ve bunun vektörlerle nasıl ilişkili olduğunu düşünelim.

ÇOK benzer dokümanlar (yine bu sınırlı boyutlar dizisi ile ilgili olarak) Paris'e çok sayıda referansa sahiptir ve Londra'ya çok sayıda referansa sahiptir ya da belki de bu referansların oranına sahip olabilirler. Paris'e 2, Londra'ya 8 referanslı bir Belge, Doc2 de çok benzer olacaktır, sadece belki daha uzun bir metinle ya da şehir adlarının bir şekilde daha tekrarlayan, ancak aynı oranda. Belki her iki belge de Londra hakkında rehberler, sadece Paris'e geçen referanslar (ve bu şehrin ne kadar soğuk olduğunu ;-) Şaka yapıyorum !!!).

Şimdi, daha az benzer belgeler her iki şehre de referanslar içerebilir, ancak farklı oranlarda. Belki Doc2 Paris'e sadece bir kez ve Londra'ya yedi kez atıfta bulunurdu.

Xy uçağımıza geri dönersek , bu varsayımsal belgeleri çizersek, ÇOK benzer olduklarında, vektörlerinin örtüştüğünü (bazı vektörler daha uzun olsa da) ve daha az ortak noktaya sahip olduklarında, bu vektörlerin ayrılmaya başladığını görürüz, aralarında daha geniş bir açıya sahip olmak.

Vektörler arasındaki açıyı ölçerek benzerlikleri hakkında iyi bir fikir edinebilir ve işleri daha da kolaylaştırabiliriz, bu açının kosinüsünü alarak, 0 ila 1 veya -1 ila 1 değerine sahip güzel bir değere sahibiz. neyi ve nasıl açıkladığımıza bağlı olarak bu benzerlik. Açı ne kadar küçük olursa, kosinüs değeri de o kadar büyük (1'e yakın) ve benzerlik de o kadar yüksek olur.

Aşırıda, eğer Doc1 sadece Paris'i ve Doc2 sadece Londra'dan bahsediyorsa, belgelerin hiçbir ortak yanı yoktur. Doc1'in vektörü x ekseninde, Doc2 y ekseninde, açı 90 derece, Kosinüs 0 olur. Bu durumda bu belgelerin birbirine dik olduğunu söyleyebiliriz.

Boyutlar ekleme :
Küçük bir açı (veya büyük kosinüs) olarak ifade edilen bu sezgisel benzerlik hissi ile, şimdi "Amsterdam" kelimesini karışıma getirerek 3 boyutta bir şeyler hayal edebiliyoruz ve iki kişilik bir belgenin her birine referanslar belirli bir yönde giden bir vektöre sahip olacak ve bu yönün Paris ve Londra'yı her biri üç kez aktaran, ancak Amsterdam vb. 10 veya 100 şehir için yer. Çizmek zor ama kavramsallaştırması kolay.

Formülün kendisi hakkında birkaç kelime söyleyerek tamamlayacağım . Söylediğim gibi, diğer referanslar hesaplamalar hakkında iyi bilgi sağlar.

İlk olarak iki boyutta. İki vektör arasındaki açının Kosinüs formülü, trigonometrik farktan (a açısı ve b açısı arasında) türetilir:

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

Bu formül, nokta ürün formülüne çok benzer:

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

burada cos(a)karşılık gelir xdeğeri ve değeri, ilk vektör için, vb tek sorun, yani , vb tam değildir ve bu değerler birim çember üzerinde okunması gereken için, değerler. Formülün paydası burada devreye girer: bu vektörlerin uzunluğunun ürününe bölünerek ve koordinatları normalleşir.sin(a)yxycossinxy


25

İşte benim uygulama 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));
        }
    }
}

bu harika teşekkür ederim nasıl açıkladı sevdi Magnitude =)
liminal18

Bu harika bir şey ama dosyalar veya dizelerle çalışıyorsak.
Talha

22

Basitlik için a ve b vektörünü düşürüyorum:

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

Sonra kosinüs benzerliği (Teta):

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

daha sonra cos 0.5'in tersi 60 derecedir.


18

Bu Python kodu algoritmayı uygulamak için benim hızlı ve kirli girişimdir:

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 ()). Union (set (counter2.keys ()))") satırında neden set kullandığınızı açıklayabilir misiniz?
Ghos3t

@ Ghos3t, yani her iki belgeden de ayrı kelimelerin listesini almak
Jobs

7

@Bill Bell örneğini kullanarak, bunu [R] 'de yapmanın iki yolu

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)))

veya crossprod () yönteminin performansından yararlanma ...

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

5

Bu, Pythonkosinüs benzerliğini uygulayan basit bir koddur.

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

Kosinüs benzerliğini hesaplamak için basit JAVA kodu

/**
   * 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
Bu "basit, grafiksel bir yol" değil, sadece kod. Diğerleri de aynı hatayı yapmış olmasına rağmen: /
Skrylar

-1

İki vektör A ve B, bir 2D uzayda veya 3D uzayda bulunur, bu vektörler arasındaki açı cos benzerliğidir.

Açı daha fazla ise (maksimum 180 dereceye ulaşabilir) ki bu Cos 180 = -1'dir ve minimum açı 0 derecedir. cos 0 = 1, vektörlerin birbirine hizalandığını ve dolayısıyla vektörlerin benzer olduğunu gösterir.

cos 90 = 0 (A ve B vektörlerinin hiç benzer olmadığı ve mesafe negatif olamadığı için kosinüs değerleri 0'dan 1'e çıkacağı sonucuna varmak için yeterlidir. Dolayısıyla, daha fazla açı benzerliği azaltmayı ima eder (ayrıca görselleştirme) mantıklı)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.