2011-11-16 46 views
6

Tôi có hai vectơ giá trị và một vectơ có trọng số, và tôi cần tính toán độ tương tự cosin. Vì những lý do phức tạp, tôi chỉ có thể tính cosin cho một cặp tại một thời điểm. Nhưng tôi phải làm điều đó hàng triệu lần.tính toán R cosin hiệu quả nhất

cosine_calc <- function(a,b,wts) { 
    #scale both vectors by the weights, then compute the cosine of the scaled vectors 
    a = a*wts 
    b = b*wts 
    (a %*% b)/(sqrt(a%*%a)*sqrt(b%*%b)) 
} 

hoạt động, nhưng tôi muốn cố gắng cải thiện hiệu suất tốt hơn.

Ví dụ dữ liệu:

a = c(-1.2092420, -0.7053822, 1.4364633, 1.3612304, -0.3029147, 1.0319704, 0.6707610, -2.2128987, -0.9839970, -0.4302205) 
b = c(-0.69042619, 0.05811749, -0.17836802, 0.15699691, 0.78575477, 0.27925779, -0.08552864, -1.31031219, -1.92756861, -1.36350112) 
w = c(0.26333839, 0.12803180, 0.62396023, 0.37393705, 0.13539926, 0.09199102, 0.37347546, 1.36790007, 0.64978409, 0.46256891) 
> cosine_calc(a,b,w)[,1] 
[1,] 0.8390671 

question này chỉ ra rằng có những chức năng được xác định trước cosin khác có sẵn trong R, nhưng không nói gì về tính hiệu quả tương đối của chúng.

+0

chỉ có khả năng để làm điều đó một cặp tại một thời điểm sẽ là một nút cổ chai lớn ... –

+0

Tôi ghét phải phá vỡ nó cho bạn, nhưng trong kinh nghiệm của tôi, R dường như không được xây dựng cho hiệu suất (tương đối nói). Nếu dữ liệu này là từ một cơ sở dữ liệu quan hệ, bạn có thể muốn xem xét tính toán các điểm tương đồng ở đó và sau đó xuất sang R. Hầu hết những gì tôi sử dụng R là phân tích quy mô nhỏ (ví dụ trên các bộ dữ liệu sau khi tôi đã thực hiện một số lượng đáng kể tổng hợp) và sản xuất đồ họa. –

+2

Tại sao bạn không tiếp tục và đánh giá các ví dụ được liệt kê trong http://stackoverflow.com/questions/2535234/find-cosine-similarity-in-r/2536149#2536149 (tức là câu hỏi bạn đã liên kết; @JoshUlrich hiển thị cho bạn làm thế nào trong câu trả lời của mình) và xem cho chính mình? –

Trả lời

7

Tất cả các chức năng bạn đang sử dụng là .Primitive (do đó đã gọi mã được biên dịch trực tiếp), vì vậy sẽ rất khó để tìm được tốc độ phù hợp ngoài việc xây dựng lại R với BLAS được tối ưu hóa. Với những gì đã nói, đây là một lựa chọn mà có thể nhanh hơn cho vectơ lớn:

cosine_calc2 <- function(a,b,wts) { 
    a = a*wts 
    b = b*wts 
    crossprod(a,b)/sqrt(crossprod(a)*crossprod(b)) 
} 

all.equal(cosine_calc1(a,b,w),cosine_calc2(a,b,w)) 
# [1] TRUE 

# Check some timings 
library(rbenchmark) 
# cosine_calc2 is slower on my machine in this case 
benchmark(
    cosine_calc1(a,b,w), 
    cosine_calc2(a,b,w), replications=1e5, columns=1:4) 
#     test replications user.self sys.self 
# 1 cosine_calc1(a, b, w)  100000  1.06  0.02 
# 2 cosine_calc2(a, b, w)  100000  1.21  0.00 

# but cosine_calc2 is faster for larger vectors 
set.seed(21) 
a <- rnorm(1000) 
b <- rnorm(1000) 
w <- runif(1000) 
benchmark(
    cosine_calc1(a,b,w), 
    cosine_calc2(a,b,w), replications=1e5, columns=1:4) 
#     test replications user.self sys.self 
# 1 cosine_calc1(a, b, w)  100000  3.83  0 
# 2 cosine_calc2(a, b, w)  100000  2.12  0 

UPDATE:

Profiling cho thấy khá nhiều thời gian cho việc nhân mỗi vector của vector trọng số.

> Rprof(); for(i in 1:100000) cosine_calc2(a,b,w); Rprof(NULL); summaryRprof() 
$by.self 
      self.time self.pct total.time total.pct 
*     0.80 45.98  0.80  45.98 
crossprod   0.56 32.18  0.56  32.18 
cosine_calc2  0.32 18.39  1.74 100.00 
sqrt    0.06  3.45  0.06  3.45 

$by.total 
      total.time total.pct self.time self.pct 
cosine_calc2  1.74 100.00  0.32 18.39 
*     0.80  45.98  0.80 45.98 
crossprod   0.56  32.18  0.56 32.18 
sqrt    0.06  3.45  0.06  3.45 

$sample.interval 
[1] 0.02 

$sampling.time 
[1] 1.74 

Nếu bạn có thể làm trọng số trước khi bạn phải gọi hàm hàng triệu lần, bạn có thể tiết kiệm được khá nhiều thời gian. cosine_calc3 nhanh hơn một chút so với chức năng ban đầu của bạn với vectơ nhỏ. Byte-biên dịch các chức năng sẽ cung cấp cho bạn một tốc độ biên.

cosine_calc3 <- function(a,b) { 
    crossprod(a,b)/sqrt(crossprod(a)*crossprod(b)) 
} 
A = a*w 
B = b*w 
# Run again on the 1000-element vectors 
benchmark(
    cosine_calc1(a,b,w), 
    cosine_calc2(a,b,w), 
    cosine_calc3(A,B), replications=1e5, columns=1:4) 
#     test replications user.self sys.self 
# 1 cosine_calc1(a, b, w)  100000  3.85  0.00 
# 2 cosine_calc2(a, b, w)  100000  2.13  0.02 
# 3 cosine_calc3(A, B)  100000  1.31  0.00 
+2

Tôi có đọc kết quả đúng không? 100.000 reps của 1.000 đầu vào mất 3 giây? Có vẻ khó tin rằng đây có thể là một nút cổ chai trong mã của ai đó! – hadley

Các vấn đề liên quan