2

-1 と 1 の間で列方向に正規化したい大きな行列 (数千行と数百行) があります。これは私が書いたコードです:

normalize <- function(x) { 
    for(j in 1:length(x[1,])){
        print(j)
        min <- min(x[,j])
        max <- max(x[,j])
        for(i in 1:length(x[,j])){
            x[i,j] <- 2 * (x[i,j] - min)/( max - min) - 1
        }
    }
    return(x)
}

残念ながら、遅くするのはいやです。私はこれを見ました:

normalize <- function(x) { 
    x <- sweep(x, 2, apply(x, 2, min)) 
    sweep(x, 2, apply(x, 2, max), "/") 
}

高速ですが、0 と 1 の間で正規化されます。私の目的に合わせて変更してください。申し訳ありませんが、私はRの学習を始めたばかりです

4

4 に答える 4

4

x自分の関数の最後で行列を再スケーリングするのはどうですか?

normalize <- function(x) { 
    x <- sweep(x, 2, apply(x, 2, min)) 
    x <- sweep(x, 2, apply(x, 2, max), "/") 
    2*x - 1
}
于 2013-01-11T16:37:14.787 に答える
4

ベンチマーク:

normalize2 <- function(A) { 
  scale(A,center=TRUE,scale=apply(A,2,function(x) 0.5*(max(x)-min(x))))
}

normalize3 <- function(mat) { 
  apply(mat,2,function(x) {xmin <- min(x); 2*(x-xmin)/(max(x)-xmin)-1})
}

normalize4 <- function(x) { 
  aa <- colMeans(x)
  x <- sweep(x, 2, aa)           # retrive the mean from each column

  2* sweep(x, 2, apply(x, 2, function(y) max(y)-min(y)), "/") 
}


set.seed(42)
mat <- matrix(sample(1:10,1e5,TRUE),1e3)
erg2 <- normalize2(mat)
attributes(erg2) <- attributes(normalize3(mat))
all.equal(  
  erg2,  
  normalize3(mat),   
  normalize4(mat)
  )

[1] TRUE

library(microbenchmark)
microbenchmark(normalize4(mat),normalize3(mat),normalize2(mat))

Unit: milliseconds
             expr      min       lq   median       uq      max
1 normalize2(mat) 4.846551 5.486845 5.597799 5.861976 30.46634
2 normalize3(mat) 4.191677 4.862655 4.980571 5.153438 28.94257
3 normalize4(mat) 4.960790 5.648666 5.766207 5.972404 30.08334

set.seed(42)
mat <- matrix(sample(1:10,1e4,TRUE),10)
microbenchmark(normalize4(mat),normalize3(mat),normalize2(mat))

Unit: milliseconds
             expr      min       lq   median       uq       max
1 normalize2(mat) 4.319131 4.445384 4.556756 4.821512  9.116263
2 normalize3(mat) 5.743305 5.927829 6.098392 6.454875 13.439526
3 normalize4(mat) 3.955712 4.102306 4.175394 4.402710  5.773221

列のapply数が少ない場合、解はわずかに遅くなりますが、列の数が多い場合はわずかに速くなります。全体として、パフォーマンスは同じ大きさです。

于 2013-01-11T17:35:47.893 に答える
2

これにより、同じ方法を使用してマトリックスが再スケーリングされます

normalize <- function(x) { 
  x <- sweep(x, 2, apply(x, 2, mean))           # retrive the mean from each column
  2* sweep(x, 2, apply(x, 2, function(y) max(y)-min(y)), "/") 
}

}

編集

colMeansもちろん、コメントで提案されているように使用する方が高速です

normalize <- function(x) { 
  aa <- colMeans(x)
  x <- sweep(x, 2, aa)           # retrive the mean from each column

  2* sweep(x, 2, apply(x, 2, function(y) max(y)-min(y)), "/") 
}
A <- matrix(1:24, ncol=3)

> normalize(A)
           [,1]       [,2]       [,3]
[1,] -1.0000000 -1.0000000 -1.0000000
[2,] -0.7142857 -0.7142857 -0.7142857
[3,] -0.4285714 -0.4285714 -0.4285714
[4,] -0.1428571 -0.1428571 -0.1428571
[5,]  0.1428571  0.1428571  0.1428571
[6,]  0.4285714  0.4285714  0.4285714
[7,]  0.7142857  0.7142857  0.7142857
[8,]  1.0000000  1.0000000  1.0000000

scaleベースパッケージの機能でEDIT

scale(A,center=TRUE,scale=apply(A,2,function(x) 0.5*(max(x)-min(x))))
           [,1]       [,2]       [,3]
[1,] -1.0000000 -1.0000000 -1.0000000
[2,] -0.7142857 -0.7142857 -0.7142857
[3,] -0.4285714 -0.4285714 -0.4285714
[4,] -0.1428571 -0.1428571 -0.1428571
[5,]  0.1428571  0.1428571  0.1428571
[6,]  0.4285714  0.4285714  0.4285714
[7,]  0.7142857  0.7142857  0.7142857
[8,]  1.0000000  1.0000000  1.0000000
于 2013-01-11T16:39:43.320 に答える
1

ちょうどどうですか:

x[,1] <- (x[,1]-mean(x[,1]))/(max(x[,1])-min(x[,1]))

の基本的な関数のほとんどはベクトル化されているため、コードにループRを含める必要はありません。forこのスニペットは、列 1 のすべてをスケーリングします (関数を使用することもできますがscale()、最小値/最大値のオプションはありません)。

データセット全体を処理するには、次のようにします。

Scale <- function(y) y <- (y-mean(y))/(max(y)-min(y))
DataFrame.Scaled <- apply(DataFrame, 2, Scale)

編集:関数の後に値を付けたくないことも指摘する価値があります。これを行うmin <- min(x)と、次に R を要求したときに R が混乱することになりますmin

于 2013-01-11T16:30:40.677 に答える