आर

2010-06-12 8 views
8

में एक बिंदु और अंक के समूह के बीच सभी दूरी की गणना करना सबसे पहले, मैं आर (मैंने कल शुरू किया) में नया हूं।आर

मैं आकार n के पहले एक और आकार K की दूसरी दो अंक के समूहों, data और centers, (उदाहरण के लिए, n = 3823 और K = 10) है, और पहले सेट में प्रत्येक i के लिए, मैं j खोजने की जरूरत है न्यूनतम दूरी के साथ दूसरे में। मैं केवल which.min(dist) उपयोग करने के लिए मैं क्या देख रहा हूँ खोजने की जरूरत है, के लिए प्रत्येक i, dist[j]i और j के बीच की दूरी रहने दो:

मेरा विचार सरल है।

प्रत्येक बिंदु 64 युगल की एक सरणी, इसलिए

> dim(data) 
[1] 3823 64 
> dim(centers) 
[1] 10 64 

मैं (, यह 40 से अधिक लेता है !! n = 200 साथ)

for (i in 1:n) { 
    for (j in 1:K) { 
    d[j] <- sqrt(sum((centers[j,] - data[i,])^2)) 
    } 
    S[i] <- which.min(d) 
} 

जो बेहद धीमी गति से है के साथ की कोशिश की है है। सबसे तेजी से समाधान है कि मैंने लिखा

distance <- function(point, group) { 
    return(dist(t(array(c(point, t(group)), dim=c(ncol(group), 1+nrow(group)))))[1:nrow(group)]) 
} 

for (i in 1:n) { 
    d <- distance(data[i,], centers) 
    which.min(d) 
} 

यहां तक ​​कि अगर यह गणना है कि मैं (क्योंकि dist(m)m की सभी पंक्तियों के बीच की दूरी की गणना करता है) का उपयोग नहीं करते की एक बहुत कुछ करता है, जिस तरह से अधिक एक दूसरे की तुलना में तेजी है (क्या कोई बता सकता है क्यों?), लेकिन यह मेरी जरूरत के लिए पर्याप्त तेज़ नहीं है, क्योंकि इसका उपयोग केवल एक बार नहीं किया जाएगा। और, distance कोड बहुत बदसूरत है। मैंने इसे

distance <- function(point, group) { 
    return (dist(rbind(point,group))[1:nrow(group)]) 
} 

के साथ बदलने की कोशिश की लेकिन यह दो बार धीमा लगता है। मैंने प्रत्येक जोड़ी के लिए dist का उपयोग करने की भी कोशिश की, लेकिन यह भी धीमी है।

मुझे नहीं पता कि अब क्या करना है। ऐसा लगता है कि मैं कुछ गलत कर रहा हूँ। इस बारे में कोई विचार अधिक कुशलतापूर्वक कैसे करें?

ps: मुझे हाथ से के-साधन लागू करने की आवश्यकता है (और मुझे यह करने की ज़रूरत है, यह असाइनमेंट का हिस्सा है)। मेरा मानना ​​है कि मुझे केवल यूक्लिडियन दूरी की आवश्यकता होगी, लेकिन मुझे अभी तक यकीन नहीं है, इसलिए मैं कुछ कोड रखना पसंद करूंगा जहां दूरी गणना को आसानी से बदला जा सकता है। stats::kmeans एक सेकंड से भी कम समय में सभी गणना करें।

+1

लोग 'दौर यहां तरह-एक-इसे की तरह कर कार्य ... इसलिए एक विशिष्ट समस्या पर ध्यान केंद्रित करने की कोशिश करो। – aL3xa

उत्तर

13

डेटा पॉइंट्स में पुनरावृत्ति करने की बजाय, आप केवल मैट्रिक्स ऑपरेशन को सघन कर सकते हैं, जिसका अर्थ है कि आपको केवल K पर फिर से भरना होगा।

utilisateur  système  écoulé 
     0.100  0.008  0.108 
अपने लैपटॉप पर

: में

# Generate some fake data. 
n <- 3823 
K <- 10 
d <- 64 
x <- matrix(rnorm(n * d), ncol = n) 
centers <- matrix(rnorm(K * d), ncol = K) 

system.time(
    dists <- apply(centers, 2, function(center) { 
    colSums((x - center)^2) 
}) 
) 

चलाता है।

+0

+1 डिट्स मैट्रिक्स की गणना करने के लिए अपना रास्ता धड़कता है। ऑटो-प्रतिकृति वेक्टर के साथ मैट्रिक्स से जोड़ा या घटाया गया यह अच्छी चाल है। – Marek

+0

मैं आपके समाधान का उपयोग करने की कोशिश कर रहा हूं, लेकिन आपके मैट्रिक्स को स्थानांतरित किया गया है।क्या कॉलम के साथ की तरह लाइनों को घटाने का कोई तरीका है? – dbarbosa

+0

मैंने आवेदन का उपयोग करके लाइनों के साथ घटाव की कोशिश की लेकिन यह आपके समाधान के जितना तेज़ नहीं था। अब मैं मैट्रिक्स को ट्रांसपोज़ कर रहा हूं और अपने कोड का उपयोग कर रहा हूं और यह वास्तव में तेज़ है! बहुत धन्यवाद!!! और, एक छोटे से उदाहरण और system.time के उपयोग के साथ आपके पूर्ण उत्तर के लिए धन्यवाद। बहुत बहुत धन्यवाद :) – dbarbosa

1

आप apply फ़ंक्शंस में एक बार देखना चाहते हैं।

उदाहरण के लिए

, इस कोड

for (j in 1:K) 
    { 
    d[j] <- sqrt(sum((centers[j,] - data[i,])^2)) 
    } 

आसानी से की तरह

dt <- data[i,] 
d <- apply(centers, 1, function(x){ sqrt(sum(x-dt)^2)}) 

कुछ द्वारा प्रतिस्थापित किया जा सकता आप निश्चित रूप से इसे और अधिक अनुकूलन कर सकते हैं, लेकिन आप बात समझ मैं

+0

धन्यवाद ... यह पहली बार कोड है कि मैं ने लिखा है की तुलना में एक तेजी से लेकिन फिर भी अजीब एक distance' का उपयोग कर 'के पास नहीं है। – dbarbosa

+1

@ डबरबोसा: ठीक है, स्पष्ट रूप से 'आँकड़े :: kmeans' पैकेज संकलित कोड का उपयोग करता है जो स्पष्ट रूप से तेज़ है। बस 'kmeans' टाइप करें और आप इसके लिए स्रोत कोड देखेंगे। :) – nico

1

dist काम करता है तेजी से आशा क्योंकि वेक्टरकृत नहीं हैं और आंतरिक सी कार्यों को कॉल करते हैं।
आप लूप में कोड कई तरीकों से वेक्टरकृत किया जा सकता है।

उदाहरण data और के बीच की दूरी की गणना करने के लिए centers आप outer इस्तेमाल कर सकते हैं:

यह आपको दूरी की n x K मैट्रिक्स देता है। और लूप से तेज रास्ता होना चाहिए।

फिर आप प्रत्येक पंक्ति में अधिकतम खोजने के लिए max.col का उपयोग कर सकते हैं (सहायता देखें, कई सटीक होने पर कुछ बारीकियां हैं)। X नकारात्मक होना चाहिए क्योंकि हम न्यूनतम खोजते हैं।

CL <- max.col(-X) 

आर में कुशल होने के लिए आपको जितना संभव हो सदिश होना चाहिए। लूप्स कई मामलों में वेक्टरकृत विकल्प द्वारा प्रतिस्थापित किया जा सकता है। rowSums (जो rowMeans, colSums, rowSums), pmax, cumsum के लिए सहायता की जांच करें। आप SO खोज सकते हैं, उदा। https://stackoverflow.com/search?q=[r]+avoid+loop (कुछ उदाहरणों के लिए & इस लिंक को पेस्ट करें, मैं इसे क्लिक करने योग्य नहीं करता)।

+0

हाय, मैं आपके कोड का उपयोग करने की कोशिश कर रहा हूं लेकिन यह काम नहीं कर रहा है। मैं एक ही कोड है कि @Jonathan चांग ने लिखा है के साथ इसका इस्तेमाल करने की कोशिश की, जोड़ने: 'system.time (बाहरी (seq_len (एन), seq_len (के), समारोह (i, j) sqrt (rowSums ((एक्स [, मैं] -centers [, j])^2)))) ', लेकिन मैं इस त्रुटि हो रही है: ' मंद (robj करने में त्रुटि) <- सी (dX, उप): मंद [उत्पाद 38,230] लंबाई से मेल नहीं खाते वस्तु का [64] ' क्या आप देखते हैं कि क्या गलत है? – dbarbosa

+0

असल में मैं 'बाहरी' नहीं समझ रहा था (मैंने सोचा था कि यह प्रत्येक जोड़ी के लिए एक बार समारोह को बुला रहा था)। अब मैं इसे समझ रहा हूं, धन्यवाद, यह उपयोगी हो सकता है! और, 'max.col' के बारे में बताने के लिए भी धन्यवाद। – dbarbosa

0

मेरे समाधान:

# data is a matrix where each row is a point 
# point is a vector of values 
euc.dist <- function(data, point) { 
    apply(data, 1, function (row) sqrt(sum((point - row)^2))) 
} 

आप यह कोशिश कर सकते हैं जैसे:

x <- matrix(rnorm(25), ncol=5) 
euc.dist(x, x[1,]) 
3

rdist() {क्षेत्रों} पैकेज से एक आर समारोह जिनमें से दो सेट के बीच दूरी की गणना करने में सक्षम है मैट्रिक्स प्रारूप में अंक जल्दी से।

https://www.image.ucar.edu/~nychka/Fields/Help/rdist.html

उपयोग:

library(fields) 
#generating fake data 
n <- 5 
m <- 10 
d <- 3 

x <- matrix(rnorm(n * d), ncol = d) 
y <- matrix(rnorm(m * d), ncol = d) 

rdist(x, y) 
      [,1]  [,2]  [,3]  [,4]  [,5] 
[1,] 1.512383 3.053084 3.1420322 4.942360 3.345619 
[2,] 3.531150 4.593120 1.9895867 4.212358 2.868283 
[3,] 1.925701 2.217248 2.4232672 4.529040 2.243467 
[4,] 2.751179 2.260113 2.2469334 3.674180 1.701388 
[5,] 3.303224 3.888610 0.5091929 4.563767 1.661411 
[6,] 3.188290 3.304657 3.6668867 3.599771 3.453358 
[7,] 2.891969 2.823296 1.6926825 4.845681 1.544732 
[8,] 2.987394 1.553104 2.8849988 4.683407 2.000689 
[9,] 3.199353 2.822421 1.5221291 4.414465 1.078257 
[10,] 2.492993 2.994359 3.3573190 6.498129 3.337441