Чи є функція R, яка обчислить матрицю невідмінності косинусів? [зачинено]


20

Я хотів би зробити теплову карту з кластеризацією рядків на основі косинусних відстаней. Я використовую R і heatmap.2()для виготовлення фігури. Я бачу, що в ньому є distпараметр, heatmap.2але я не можу знайти функцію для створення матриці косинусної несхожості. Вбудована distфункція не підтримує косинус відстані, я також знайшов пакет , званий arulesз dissimilarity()функцією , але він працює тільки на двійкових даних.


5
Можливо, буде швидше написати власну функцію невідмінності косинусів.
припускаєтьсянормальне

2
Косин - це подібність, а не несхожість. Однак ви можете перетворити косинус на евклідову відстань від масштабованих даних: d = sqrt (2 * (1-cos)).
ttnphns

Відповіді:


29

Як @Max вказав у коментарях (+1), було б простіше "написати своє", ніж витратити час на пошуки десь в іншому місці. Як відомо, косинусна схожість між двома векторами довжиною дорівнюєА,Бн

С=i=1нАiБii=1нАi2i=1нБi2

що легко створити в R. Нехай Xбуде матриця, у якій рядки - це значення, для яких ми хочемо обчислити схожість. Тоді ми можемо обчислити матрицю подібності за допомогою наступного Rкоду:

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)

Тоді матриця C- це матриця подібності косинусу, і ви можете передати її будь-якій функції теплової карти, яка вам подобається (єдина, з якою я знайома image()).


Дякую, це корисно. Насправді, я не хочу будувати саму матрицю, а скоріше маю дистанційну функцію для кластеризації іншої теплової карти, яку я маю.
Грег Слодковіч

@GregSlodkowicz, добре, можливо, ви можете передати цю матрицю функції, яку ви використовуєте. Крім того, якщо ви вважаєте, що ця відповідь є корисною, будь ласка, розгляньте нагороду (або прийнявши відповідь, якщо вважаєте її остаточною) :)
Макрос

Чудово, завдяки вашій відповіді та коментарю ttnphns я зміг зробити те, що хочу. Тепер я хотів би мати іншу метрику при кластеризації рядків, ніж при кластеризації стовпців, але, можливо, це підштовхує ...
Грег Слодковіч

Мабуть, у мене недостатньо балів, щоб я міг коментувати. Я просто хотів запропонувати трохи модифіковану версію приємної відповіді Макроса. Ось. # ChirazB версія cos.sim () від Macro # де S = X% *% t (X) cos.sim.2 <- функція (S, ix) {i <- ix [1] j <- ix [2 ] повернення (S [i, j] / sqrt (S [i, i] * S [j, j]))} #test X <- матриця (rnorm (20), nrow = 5, ncol = 4) S < - X% *% t (X) n <- nrow (X) idx.arr <- розширити.grid (i = 1: n, j = 1: n) C <- матриця (застосувати (idx.arr, 1, cos.sim, X), n, n) C2 <- матриця (застосувати (idx.arr, 1, cos.sim.2, S), n, n) Я не люблю глобальну змінну, тому я включив S як параметр.
Chiraz BenAbdelkader


4

Наступна функція може бути корисною для роботи з матрицями замість 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)
}

4

Деякі відповіді, наведені вище, обчислювально неефективні, спробуйте це;


Для матриці подібності косинусу

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

Перетворити в матрицю несхожості косинусів (матриця відстані).

D_sim <- as.dist(1 - sim)

0

Розгортаючи частину попереднього коду (від @Macro) з цього питання, ми можемо перетворити його на більш чисту версію в наступному:

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)

Сподіваюся, це допомагає!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.