Wszystkie używane funkcje to .Primitive
(dlatego już teraz wywoływany jest kod skompilowany bezpośrednio), więc trudno będzie uzyskać spójne zyski prędkości poza ponownym budowaniem R ze zoptymalizowanym BLAS. Z powiedział, że tu jest jedną z opcji, które mogą być szybsze dla większych wektorów:
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:
Profilowanie ujawnia, że sporo czasu spędza mnożenie każdego wektora przez wektor wagi.
> 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
Jeśli możesz dokonać ważenia, zanim będziesz musiał wywołać tę funkcję miliony razy, może to zaoszczędzić sporo czasu. cosine_calc3
jest marginalnie szybszy niż oryginalna funkcja z małymi wektorami. Kompilowanie funkcji Byte'a powinno dać ci jeszcze większe przyspieszenie.
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
tylko jest w stanie to zrobić jedną parę na raz będzie głównym wąskim gardłem ... –
nienawidzę złamać go do ciebie, ale z mojego doświadczenia wynika, R nie wydaje się być zbudowany wydajność (relatywnie rzecz biorąc). Jeśli dane pochodzą z relacyjnej bazy danych, warto rozważyć obliczenie podobieństw, a następnie wyeksportowanie do R. Większość tego, co używam R, to analiza na małą skalę (tj. Na zbiory danych po tym, jak zrobiłem znaczną ilość agregacja) i wytwarzanie grafiki. –
Dlaczego nie posuwać się naprzód i porównywać przykłady wymienione na stronie http://stackoverflow.com/questions/2535234/find-cosine-similarity-in-r/2536149#2536149 (tzn. Pytanie, które łączysz, @JoshUlrich pokazuje jak w jego odpowiedzi) i przekonaj się sam? –