Kosinüs benzerlik matrisini hesaplayacak bir R fonksiyonu var mı? [kapalı]


20

Kosinüs mesafelerine dayalı sıra kümelemeli bir ısı haritası yapmak istiyorum. R'yi kullanıyorum ve heatmap.2()figür yapmak için. İçinde bir distparametre heatmap.2olduğunu görebiliyorum ama kosinüs farklılığı matrisini üretmek için bir fonksiyon bulamıyorum. Yerleşik distişlev kosinüs mesafelerini desteklemez, ayrıca arulesbir dissimilarity()işlevle adlandırılan bir paket buldum, ancak sadece ikili veriler üzerinde çalışıyor.


5
Kendi kosinüs farklılığı fonksiyonunuzu yazmak daha hızlı olabilir.
varsayılan

2
Kosinüs benzerliktir, benzerlik değildir. Bununla birlikte, kosinüsü ölçekli verilerin öklid mesafesine dönüştürebilirsiniz: d = sqrt (2 * (1-cos)).
ttnphns

Yanıtlar:


29

@Max'ın yorumlarda belirttiği gibi (+1) "kendiniz yazmak", başka bir yerde aramak için zaman harcamaktan daha kolay olacaktır. Bildiğimiz gibi, uzunluğundaki iki A , B vektörü arasındaki kosinüs benzerliği ,bir,Bn

C=Σben=1nbirbenBbenΣben=1nbirben2Σben=1nBben2

bu da üretilmesi kolaydır R. Izin vermek Xki satırlar arasındaki benzerliği hesaplamak istediğimiz değerler matrisi. Sonra benzerlik matrisini aşağıdaki Rkodla hesaplayabiliriz :

cos.sim <- function(ix) 
{
    A = X[ix[1],]
    B = X[ix[2],]
    return( sum(A*B)/sqrt(sum(A^2)*sum(B^2)) )
}   
n <- nrow(X) 
cmb <- expand.grid(i=1:n, j=1:n) 
C <- matrix(apply(cmb,1,cos.sim),n,n)

O zaman matris Ckosinüs benzerlik matrisidir ve istediğiniz ısı haritası işlevine aktarabilirsiniz (bildiğim tek şey image()).


Teşekkürler, bu yardımcı olur. Aslında, matrisin kendisini çizmek istemiyorum, daha ziyade sahip olduğum başka bir ısı haritasının kümelenmesi için bir mesafe fonksiyonuna sahibim.
Greg Slodkowicz

@GregSlodkowicz, tamam belki de bu matrisi kullandığınız işleve geçirebilirsiniz. Ayrıca, bu yanıtı yararlı bulduysanız lütfen bir yukarı oy (veya kesin olduğunu düşünüyorsanız cevabı kabul edin) düşünün :)
Macro

Harika, cevabınız ve ttnphns'ın yorumu sayesinde istediğimi yapabildim. Şimdi satırları kümelendirirken sütunları kümelemekten farklı bir metrik istiyorum ama belki de itiyor ...
Greg Slodkowicz

Görünüşe göre yorum yapabilmek için yeterli puanım yok. Macro'nun güzel cevabının biraz değiştirilmiş bir versiyonunu sunmak istedim. İşte burada. # ChirazB'nin makro # ile cos.sim () sürümü, burada S = X% *% t (X) cos.sim.2 <- fonksiyon (S, ix) {i <- ix [1] j <- ix [2 ] dönüş (S [i, j] / sqrt (S [i, i] * S [j, j]))} #test X <- matris (rnorm (20), nrow = 5, ncol = 4) S < - X% *% t (X) n <- boş (X) idx.arr <- genişletme.grid (i = 1: n, j = 1: n) C <- matris (uygula (idx.arr, 1, cos.sim, X), n, n) C2 <- matris (uygula (idx.arr, 1, cos.sim.2, S), n, n) Global değişkeni sevmiyorum, bu yüzden S'yi dahil ettim parametre olarak.
Chiraz BenAbdelkader


4

Aşağıdaki fonksiyon, 1-b vektörler yerine matrislerle çalışırken yararlı olabilir:

# input: row matrices 'ma' and 'mb' (with compatible dimensions)
# output: cosine similarity matrix

cos.sim=function(ma, mb){
  mat=tcrossprod(ma, mb)
  t1=sqrt(apply(ma, 1, crossprod))
  t2=sqrt(apply(mb, 1, crossprod))
  mat / outer(t1,t2)
}

4

Yukarıdaki bazı cevaplar hesaplama açısından yetersizdir, bunu deneyin;


Kosinüs benzerlik matrisi için

Matrix <- as.matrix(DF)
sim <- Matrix / sqrt(rowSums(Matrix * Matrix))
sim <- sim %*% t(sim)

Kosinüs benzerlik matrisine (mesafe matrisi) dönüştürün.

D_sim <- as.dist(1 - sim)

0

Bu konuda önceki kodlardan bazılarını (@Macro'dan) hızlandırarak, bunu daha temiz bir sürüme aşağıdaki gibi sarabiliriz:

df <- data.frame(t(data.frame(c1=rnorm(100),
                              c2=rnorm(100),
                              c3=rnorm(100),
                              c4=rnorm(100),
                              c5=rnorm(100),
                              c6=rnorm(100))))

#df[df > 0] <- 1
#df[df <= 0] <- 0



apply_cosine_similarity <- function(df){
  cos.sim <- function(df, ix) 
  {
    A = df[ix[1],]
    B = df[ix[2],]
    return( sum(A*B)/sqrt(sum(A^2)*sum(B^2)) )
  }   
  n <- nrow(df) 
  cmb <- expand.grid(i=1:n, j=1:n) 
  C <- matrix(apply(cmb,1,function(cmb){ cos.sim(df, cmb) }),n,n)
  C
}
apply_cosine_similarity(df)

Bu yardımcı olur umarım!

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.