1
votes

Accélération du calcul de la somme de la différence ponctuelle de R

Supposons que j'ai deux ensembles de données. Le premier est:

sumPD<-function(vector1,vector2){
  sumPD1<-sum((vector1-vector2)^2)
  return(sumPD1)
}
loc<-matrix(NA,nrow=dim(xtrain)[1],ncol=dim(xtest)[1])
for(j in 1:dim(xtest)[1]){    
  for(i in 1:dim(xtrain)[1]){
     loc[i,j]<-sumPD(xtrain[i,],xtest[j,])
   }
 }

Le second est:

sum((7-1)^2+(3-5)^2+(9-8)^2+.....(9-5)^2)
sum((5-1)^2+(1-5)^2+(1-8)^2+.....(4-5)^2)
...
sum((14-13)^2+(18-14)^2+(15-18)^2+.....(17-14)^2) 

Ce que j'ai aimé faire, c'est calculer la somme de la distance entre chaque ligne de xtest et chaque ligne de xtrain . Par exemple:

t6<-sample(1:10,10,replace = T)
t7<-sample(11:20,10,replace = T)
xtest<-rbind(t6,t7)
xtest
   [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
t6    1    5    8    2   10    2    3    4    8     5
t7   14   18   15   12   17   20   17   13   16    17

Ce que j'ai actuellement, c'est d'utiliser deux boucles for (voir ci-dessous), qui, je pense, ne peuvent pas gérer de grands ensembles de données:

t1<-sample(1:10,10,replace = T)
t2<-sample(1:10,10,replace = T)
t3<-sample(1:10,10,replace = T)
t4<-sample(11:20,10,replace = T)
t5<-sample(11:20,10,replace = T)
xtrain<-rbind(t1,t2,t3,t4,t5)
xtrain
   [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
t1    7    3    9   10    4    9    2    1    6     9
t2    5    1    1    6    5    3   10    2    6     3
t3    8    6    9    7    9    2    3    5    1     8
t4   16   18   14   17   19   20   15   15   20    19
t5   13   14   18   13   11   19   13   17   16    14

Je voudrais demander des suggestions sur la façon de modifier le code pour le rendre efficace. Merci d'avance! J'espère avoir une bonne discussion!


0 commentaires

4 Réponses :


2
votes

Une option serait outer

f1 <- Vectorize(function(i, j) sumPD(xtrain[i,], xtest[j,]))
loc2 <- outer(seq_len(nrow(xtrain)), seq_len(nrow(xtest)), f1)
identical(loc, loc2)
#[1] TRUE


0 commentaires

3
votes

Le package rdist a des fonctions pour calculer rapidement ces types de distances par paires:

     [,1] [,2]
[1,]   65 1029
[2,]   94 1324
[3,]  165 1103
[4,] 1189  213
[5,] 1271  191

Sortie:

rdist::cdist(xtrain, xtest)^2


0 commentaires

0
votes

Voici deux méthodes simples.

En utilisant dist - calculera plus de distances que nécessaire:

euclid <- function(X,y) colSums((X-y)^2)
dists  <- mapply(euclid, list(t(xtrain)), split(xtest, row(xtest)))
dists
   [,1] [,2]
t1  140 1179
t2  134  693
t3  119  974
t4 1028   91
t5 1085   44

En utilisant des fonctions personnalisées simples qui fonctionne sur la matrice X et le vecteur y:

dists <- as.matrix(dist(rbind(xtrain, xtest))^2)
dists <- dists[rownames(xtrain), rownames(xtest)]
dists
     t6   t7
t1  140 1179
t2  134  693
t3  119  974
t4 1028   91
t5 1085   44


0 commentaires

1
votes

Vous pouvez transposer votre matrice, utiliser la différence vectorielle et une seule boucle:

ftrain <- t(xtrain)
ftest <- t(xtest)


sapply(1:(dim(ftest)[2]),function(i){
  colSums((ftrain - ftest[,i])^2)
})


   [,1] [,2]
t1  103 1182
t2  125 1262
t3  130 1121
t4 1478  159
t5 1329  142

colSums est assez efficace, mais regardez si vous voulez plus de vitesse


1 commentaires

Je pense que vous pouvez éviter la boucle avec ntrain = nrow (xtrain); ntest = nrow (xtest); matrix (rowSums ((xtrain [rep (1: ntrain, ntest),] - xtest [rep (1: ntest, each = ntrain),]) ^ 2), nc = ntest) bien que l'intention est plus clair