2011-11-16 14 views
6

मेरे पास मूल्यों के दो वैक्टर और वजन के एक वेक्टर हैं, और मुझे कोसाइन समानता की गणना करने की आवश्यकता है। जटिल कारणों से, मैं एक समय में केवल एक जोड़ी के लिए कोसाइन की गणना कर सकता हूं। लेकिन मुझे इसे कई लाख बार करना है।सबसे कुशल आर कोसाइन गणना

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

काम करता है, लेकिन मैं इससे बेहतर प्रदर्शन करने की कोशिश करना चाहता हूं।

उदाहरण डेटा:

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 बताते अन्य पूर्वनिर्धारित कोज्या आर में उपलब्ध कार्यों देखते हैं कि, लेकिन उनके सापेक्ष दक्षता के बारे में कुछ भी नहीं कहना है।

+0

केवल यह एक समय में एक जोड़ी करने के लिए सक्षम किया जा रहा है एक प्रमुख अड़चन होने जा रहा है ... –

+0

मैं तुम्हें करने के लिए इसे तोड़ने के लिए नफरत है, लेकिन मेरे अनुभव में, अनुसंधान के लिए निर्मित किया जाना प्रतीत नहीं होता प्रदर्शन (अपेक्षाकृत बोलना)। यदि यह डेटा एक रिलेशनल डेटाबेस से है, तो आप वहां समानताएं कंप्यूटिंग पर विचार करना चाहेंगे और फिर आर को निर्यात कर सकते हैं। मैं जो कुछ भी आर का उपयोग करता हूं वह छोटे पैमाने पर विश्लेषण है (यानी डेटा सेट पर मैंने महत्वपूर्ण मात्रा में काम किया है एकत्रीकरण) और ग्राफिक्स का उत्पादन। –

+2

आप आगे क्यों नहीं जाते हैं और http://stackoverflow.com/questions/2535234/find-cosine-similarity-in-r/2536149#2536149 (यानी आपके द्वारा लिंक किया गया प्रश्न; @ जोशउलिच आपको दिखाता है) में सूचीबद्ध उदाहरणों का बेंचमार्क क्यों नहीं करते हैं उसके जवाब में कैसे) और खुद के लिए देखें? –

उत्तर

7

आपके द्वारा उपयोग किए जा रहे सभी कार्यों .Primitive (इसलिए पहले से ही संकलित कोड सीधे कॉल करें), इसलिए एक अनुकूलित BLAS के साथ पुन: निर्माण आर के बाहर लगातार गति लाभ प्राप्त करना मुश्किल होगा। इसके साथ ही कहा, यहां एक ही विकल्प है कि बड़े वैक्टर के लिए तेजी से हो सकता है:

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 

अद्यतन:

रूपरेखा पता चलता है कि काफी समय का एक सा वजन वेक्टर द्वारा प्रत्येक वेक्टर गुणा खर्च किया जाता है।

> 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 

इससे पहले कि आप समय की समारोह लाखों लोगों की कॉल करनी होगी आप भार कर सकते हैं, तो यह आपको काफी समय का एक सा बचा सकता है। cosine_calc3 छोटे वैक्टर के साथ आपके मूल कार्य से थोड़ा तेज़ है। बाइट-फ़ंक्शन को संकलित करने से आपको एक और मामूली गति मिलनी चाहिए।

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

क्या मैं उन परिणामों को सही पढ़ रहा हूं? 1,000 इनपुट के 100,000 प्रतिनिधि 3 सेकंड लेते हैं? यह मानना ​​मुश्किल लगता है कि यह किसी के कोड में एक बाधा हो सकती है! – hadley