มีฟังก์ชั่น R ที่จะคำนวณเมทริกซ์ที่ไม่เหมือนกันของโคไซน์หรือไม่? [ปิด]


20

ฉันต้องการสร้างแผนที่ความร้อนที่มีการจัดกลุ่มแถวตามระยะทางโคไซน์ ฉันใช้ R และheatmap.2()ทำรูป ฉันเห็นได้ว่ามีdistพารามิเตอร์อยู่heatmap.2แต่ฉันไม่สามารถหาฟังก์ชั่นเพื่อสร้างเมทริกซ์ที่แตกต่างกันได้ distฟังก์ชั่นบิวอินไม่รองรับระยะทางโคไซน์ฉันยังพบแพ็คเกจที่เรียกว่าarulesพร้อมdissimilarity()ฟังก์ชัน แต่ใช้งานได้กับข้อมูลไบนารีเท่านั้น


5
มันอาจจะเร็วกว่าที่จะเขียนฟังก์ชั่นที่แตกต่างโคไซน์ของคุณเอง
สันนิษฐานว่าโดยปกติ

2
โคไซน์มีความคล้ายคลึงกันไม่ต่างกัน อย่างไรก็ตามคุณสามารถเปลี่ยนโคไซน์เป็นระยะทางแบบยูคลิดของข้อมูลที่ปรับสเกลได้: d = sqrt (2 * (1-cos))
ttnphns

คำตอบ:


29

ตามที่ @ Max ระบุไว้ในความคิดเห็น (+1) การเขียน "ของคุณเอง" จะง่ายกว่าการใช้เวลาเพื่อค้นหาที่อื่น อย่างที่เรารู้ความคล้ายคลึงกันของโคไซน์ระหว่างสองเวกเตอร์ของความยาวnคือA,Bn

=Σผม=1nAผมBผมΣผม=1nAผม2Σผม=1nBผม2

ซึ่งตรงไปตรงมาเพื่อสร้าง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ก็คือเมทริกซ์ความเหมือนโคไซน์และคุณสามารถส่งผ่านไปยังฟังก์ชัน Heatmap ใดก็ได้ที่คุณชอบ (อันเดียวที่ฉันคุ้นเคยคือimage())


ขอบคุณสิ่งนี้มีประโยชน์ ที่จริงฉันไม่ต้องการพล็อตเมทริกซ์เอง แต่มีฟังก์ชันระยะทางสำหรับการรวมกลุ่มของ heatmap อื่นที่ฉันมี
Greg Slodkowicz

@GregSlodkowicz โอเคบางทีคุณสามารถส่งเมทริกซ์นี้ไปยังฟังก์ชันที่คุณใช้อยู่ได้ นอกจากนี้หากคุณพบว่าคำตอบนี้มีประโยชน์โปรดพิจารณา upvote (หรือยอมรับคำตอบหากคุณถือว่าเป็นคำจำกัดความ) :)
Macro

เยี่ยมมากขอบคุณคำตอบของคุณและความคิดเห็นของ ttnphns ฉันสามารถทำสิ่งที่ฉันต้องการได้ ตอนนี้ฉันต้องการที่จะมีตัวชี้วัดที่แตกต่างกันเมื่อการจัดกลุ่มแถวกว่าเมื่อการจัดกลุ่มคอลัมน์ แต่บางทีนั่นอาจจะผลักดัน ...
Greg Slodkowicz

เห็นได้ชัดว่าฉันไม่มีคะแนนเพียงพอที่จะแสดงความคิดเห็นได้ ฉันแค่อยากจะเสนอคำตอบที่ดีของ Macro รุ่นที่ปรับเปลี่ยนเล็กน้อย นี่มันคือ # เวอร์ชั่นของ ChirazB ของ cos.sim () ตามมาโคร # โดยที่ S = X% *% t (X) cos.sim.2 <- ฟังก์ชัน (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 (ใช้ (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)

หวังว่านี่จะช่วยได้!

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.