코사인 상이 행렬을 계산하는 R 함수가 있습니까? [닫은]


20

코사인 거리를 기반으로 행 클러스터링으로 히트 맵을 만들고 싶습니다. 나는 R을 사용 heatmap.2()하고 그림을 만들기 위해 사용하고 있습니다. 나는이 있다고 볼 수 dist있는 매개 변수가 heatmap.2있지만 코사인 유사성 행렬을 생성하는 기능을 찾을 수 없습니다. 내장 dist함수는 코사인 거리를 지원하지 않으며 함수 arules와 함께 호출 된 패키지를 찾았 dissimilarity()지만 이진 데이터에서만 작동합니다.


5
자신의 코사인 비 유사 함수를 작성하는 것이 더 빠를 수 있습니다.
정상적인

2
코사인은 유사성이 아니라 유사성입니다. 그러나 코사인을 스케일 된 데이터의 유클리드 거리 (d = sqrt (2 * (1-cos)))로 전환 할 수 있습니다.
ttnphns

SO에 대한 동일한 질문 : 두 배열 사이의 코사인 유사점 찾기
smci

답변:


29

댓글 (+1)에 @Max가 표시 한 것처럼 다른 곳을 찾는 데 시간을 보내는 것보다 "자신의 것을 작성하는"것이 더 간단합니다. 우리가 알고 있듯이, 길이 n 의 두 벡터 A , B 사이 의 코사인 유사성A,Bn

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

에서 간단하게 생성 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().


감사합니다. 도움이됩니다. 실제로, 나는 매트릭스 자체를 플롯하고 싶지 않고 내가 가지고있는 다른 히트 맵을 클러스터링하기위한 거리 함수를 가지고 있습니다.
Greg Slodkowicz

@GregSlodkowicz, 좋아, 아마도이 행렬을 사용중인 함수에 전달할 수 있습니다. 또한,이 답변이 도움이 되었으면 공감대를 고려해보십시오 (또는 결정적인 것으로 판단되면 답변을 수락하십시오) :)
Macro

답장과 ttnphns의 의견 덕분에 나는 내가 원하는 것을 할 수있었습니다. 이제 열을 군집화 할 때와 행을 군집화 할 때 다른 메트릭을 원하지만 아마도 그것을 추진하고있을 것입니다.
Greg Slodkowicz

분명히 의견을 말할 수있는 충분한 포인트가 없습니다. 매크로의 좋은 대답을 약간 수정 한 버전을 제공하고 싶었습니다. 여기있어. # Macro by ChirazB의 cos.sim () 버전 # 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 <-행렬 (rnorm (20), nrow = 5, ncol = 4) S < -X % * % t (X) n <-nrow (X) idx.arr <-expand.grid (i = 1 : n, j = 1 : n) C <-행렬 (적용 (idx.arr, 1, cos.sim, X), n, n) C2 <-matrix (apply (idx.arr, 1, cos.sim.2, S), n, n) 전역 변수가 마음에 들지 않기 때문에 S를 포함 시켰습니다. 매개 변수로.
Chiraz BenAbdelkader


4

다음 함수는 1 차원 벡터 대신 행렬로 작업 할 때 유용 할 수 있습니다.

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

도움이 되었기를 바랍니다!

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.