Apakah ada fungsi R yang akan menghitung matriks ketidaksamaan cosinus? [Tutup]

20

Saya ingin membuat peta panas dengan pengelompokan baris berdasarkan jarak kosinus. Saya menggunakan R dan heatmap.2()untuk membuat gambar. Saya dapat melihat bahwa ada distparameter di heatmap.2tetapi saya tidak dapat menemukan fungsi untuk menghasilkan matriks ketidakseimbangan cosinus. Fungsi builtin disttidak mendukung jarak cosinus, saya juga menemukan paket yang dipanggil arulesdengan dissimilarity()fungsi tetapi hanya bekerja pada data biner.

Greg Slodkowicz
sumber
5
Mungkin lebih cepat untuk menulis fungsi ketidaksamaan cosinus Anda sendiri.
Diasumsikan normal
2
Cosine adalah persamaan, bukan perbedaan. Anda dapat, bagaimanapun, mengubah cosinus menjadi jarak euclidean data yang diskalakan: d = sqrt (2 * (1-cos)).
ttnphns
Pertanyaan yang sama berakhir pada SO: Temukan persamaan cosinus antara dua array
smci

Jawaban:

29

Seperti @Max ditunjukkan dalam komentar (+1) akan lebih mudah untuk "menulis sendiri" daripada menghabiskan waktu mencarinya di tempat lain. Seperti kita ketahui, persamaan cosinus antara dua vektor dengan panjang adalahnA,Bn

C=i=1nAiBii=1nAi2i=1nBi2

yang sangat mudah untuk menghasilkan di R. Membiarkan Xmenjadi matriks di mana baris adalah nilai yang ingin kita hitung kesamaannya. Kemudian kita dapat menghitung matriks kesamaan dengan Rkode berikut :

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)

Kemudian matriksnya Cadalah cosine similarity matrix dan Anda bisa meneruskannya ke fungsi heatmap apa pun yang Anda suka (satu-satunya yang saya kenal adalah image()).

Makro
sumber
Terima kasih, ini sangat membantu. Sebenarnya, saya tidak ingin merencanakan matriks itu sendiri tetapi memiliki fungsi jarak untuk pengelompokan peta panas lain yang saya miliki.
Greg Slodkowicz
@GregSlodkowicz, OKE well mungkin Anda bisa melewatkan matriks ini ke fungsi yang Anda gunakan. Juga, jika Anda telah menemukan jawaban ini bermanfaat, silakan pertimbangkan upvote (atau menerima jawaban jika Anda menganggapnya definitif) :)
Makro
Hebat, terima kasih atas balasan dan komentar ttnphns saya bisa melakukan apa yang saya inginkan. Sekarang saya ingin memiliki metrik yang berbeda ketika mengelompokkan baris daripada ketika mengelompokkan kolom tapi mungkin itu mendorongnya ...
Greg Slodkowicz
Ternyata saya tidak punya cukup poin untuk bisa berkomentar. Saya hanya ingin menawarkan versi jawaban makro yang sedikit dimodifikasi. Ini dia. Versi ChirazB tentang cos.sim () oleh Macro # di mana S = X% *% t (X) cos.sim.2 <- function (S, ix) {i <- ix [1] j <- ix [2 ] return (S [i, j] / sqrt (S [i, i] * S [j, j]))} #test X <- matrix (rnorm (20), nrow = 5, ncol = 4) S < - X% *% t (X) n <- nrow (X) idx.arr <- expand.grid (i = 1: n, j = 1: n) C <- matriks (berlaku (idx.arr, 1, cos.sim, X), n, n) C2 <- matrix (berlaku (idx.arr, 1, cos.sim.2, S), n, n) Saya tidak suka variabel global, itu sebabnya saya memasukkan S sebagai parameter.
Chiraz BenAbdelkader
4

Fungsi berikut mungkin berguna ketika bekerja dengan matriks, bukan vektor 1-d:

# 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)
}
Kimsche
sumber
4

Beberapa jawaban di atas tidak efisien secara komputasi, coba ini;


Untuk matriks cosine similarity

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

Konversikan ke matriks ketidaksamaan cosinus (matriks jarak).

D_sim <- as.dist(1 - sim)
Brad
sumber
0

Menjelajahi beberapa kode sebelumnya (dari @ Macro) tentang masalah ini, kita dapat membungkusnya dengan versi yang lebih bersih sebagai berikut:

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)

Semoga ini membantu!

bmc
sumber