2

データの新しい距離関数を作成しようとしています。ただし、statsパッケージのdist関数と比較すると、コードのパフォーマンスは非常に遅くなります。たとえば、ユークリッド距離の結果を参照してください。

mydist = function (x){

  euclidean = function (a, b){
    sqrt(sum((a-b)^2))
  }

  distances = matrix(0, nrow=nrow(x), ncol=nrow(x))
  for (i in 1:nrow(x))
    for (j in 1:(i-1)){  # <- corrected this
      if (j > 0){
         distances[i,j]=euclidean(x[i,], x[j,])
         distances[j,i]=distances[i,j]
      }
    }

  distances
}


m=matrix(1:800, ncol=2)
system.time(as.dist(mydist(m)))
  usuário   sistema decorrido 
    0.714     0.000     0.716      # <- updated values with corrected version

system.time(dist(m))
  usuário   sistema decorrido 
    0.004     0.000     0.002 

ユークリッド距離は使用しません。たとえば、プロキシパッケージの統計とは異なり、データに固有の統計を使用して、はるかに複雑な新しい統計を開発しています。データセットには数百の変数と数千の例(行)があります。距離を計算するためだけに数時間待つことはできません。

私はapplyでouterを使用して別のコードを試しました。2つのループよりも高速でしたが、それでも非常に低速でした。誰かが何か提案できますか?

4

2 に答える 2

2

重要なのは、個々の行ではなく、マトリックス全体から各行を減算することです。減算は列ごとに行われるため、単純に行列を転置します。

m=matrix(1:800, ncol=2)
system.time(a<-as.dist(mydist(m)))
# user  system elapsed
# 1.32    0.00    1.32 

t.m<-t(m)
system.time(x<-as.dist(apply(m,1,function(x) sqrt(colSums((x - t.m)^2)))))
# user  system elapsed
# 0.04    0.00    0.03 

any(x!=a) # FALSE

しかし、本当に速度が必要な場合は、C ライブラリを使用する必要があります。

于 2012-10-05T18:32:11.403 に答える
1

スピードアップのカギは

  • 距離関数は簡単にベクトル化できます。その場合は、? outer、および/または をご覧ください? rep
    このアプローチは非常に高速ですが、メモリを消費します。

  • applyは 2 つのループを本質的に 1 つに減らしますが、通常は実際のベクトル化の方がはるかに高速です。

  • または、インライン C コードなどを使用したい場合もあります。パッケージ inline を参照してください。

  • 誤って必要な距離の 2 倍を計算してしまいます (対称コピーを実行しますが、両方ijループして全体をループします1 : nrow (x))。

于 2012-10-05T18:05:12.000 に答える