2010-10-27 50 views
5

về cơ bản tôi muốn thực hiện trung bình đường chéo trong R. Dưới đây là một số mã được điều chỉnh từ gói simsalabim để làm trung bình đường chéo. Chỉ có điều này là chậm.Giúp tăng tốc vòng lặp trong R

Bất kỳ đề xuất nào để vector hóa điều này thay vì sử dụng một cách thủ công?

reconSSA <- function(S,v,group=1){ 
### S : matrix 
### v : vector 

    N <- length(v) 
    L <- nrow(S) 
    K <- N-L+1 
    XX <- matrix(0,nrow=L,ncol=K) 
    IND <- row(XX)+col(XX)-1 
    XX <- matrix(v[row(XX)+col(XX)-1],nrow=L,ncol=K) 
    XX <- S[,group] %*% t(t(XX) %*% S[,group]) 

    ##Diagonal Averaging 
    .intFun <- function(i,x,ind) mean(x[ind==i]) 

    RC <- sapply(1:N,.intFun,x=XX,ind=IND) 
    return(RC) 
} 

Đối với dữ liệu bạn có thể sử dụng sau đây

data(AirPassengers) 
v <- AirPassengers 
L <- 30 
T <- length(v) 
K <- T-L+1 

x.b <- matrix(nrow=L,ncol=K) 
x.b <- matrix(v[row(x.b)+col(x.b)-1],nrow=L,ncol=K) 
S <- eigen(x.b %*% t(x.b))[["vectors"]] 
out <- reconSSA(S, v, 1:10) 
+6

Ví dụ về dữ liệu ví dụ. –

+1

tôi đã thêm một số dữ liệu. cảm ơn vì lời nhắc. – pslice

+1

Tuyệt vời; bạn sẽ nhận được câu trả lời tốt hơn nhiều với một ví dụ tái sản xuất. –

Trả lời

3

Bạn có thể tăng tốc độ tính toán bằng gần 10 lần với sự giúp đỡ của một thủ thuật rất chuyên ngành với rowsum:

reconSSA_1 <- function(S,v,group=1){ 
### S : matrix 
### v : vector 
    N <- length(v) 
    L <- nrow(S) 
    K <- N-L+1 
    XX <- matrix(0,nrow=L,ncol=K) 
    IND <- row(XX)+col(XX)-1 
    XX <- matrix(v[row(XX)+col(XX)-1],nrow=L,ncol=K) 
    XX <- S[,group] %*% t(t(XX) %*% S[,group]) 
    ##Diagonal Averaging 
    SUMS <- rowsum.default(c(XX), c(IND)) 
    counts <- if(L <= K) c(1:L, rep(L, K-L-1), L:1) 
    else c(1:K, rep(K, L-K-1), K:1) 
    c(SUMS/counts) 
} 

all.equal(reconSSA(S, v, 1:10), reconSSA_1(S, v, 1:10)) 
[1] TRUE 

library(rbenchmark) 

benchmark(SSA = reconSSA(S, v, 1:10), 
      SSA_1 = reconSSA_1(S, v, 1:10), 
      columns = c("test", "elapsed", "relative"), 
      order = "relative") 


    test elapsed relative 
2 SSA_1 0.23 1.0000 
1 SSA 2.08 9.0435 

[Cập nhật: Như Joshua gợi ý nó có thể tăng tốc độ hơn nữa bằng cách sử dụng mấu chốt của mã rowsum:

reconSSA_2 <- function(S,v,group=1){ 
### S : matrix 
### v : vector 
    N <- length(v) 
    L <- nrow(S) 
    K <- N-L+1 
    XX <- matrix(0,nrow=L,ncol=K) 
    IND <- c(row(XX)+col(XX)-1L) 
    XX <- matrix(v[row(XX)+col(XX)-1],nrow=L,ncol=K) 
    XX <- c(S[,group] %*% t(t(XX) %*% S[,group])) 
    ##Diagonal Averaging 
    SUMS <- .Call("Rrowsum_matrix", XX, 1L, IND, 1:N, 
        TRUE, PACKAGE = "base") 
    counts <- if(L <= K) c(1:L, rep(L, K-L-1), L:1) 
    else c(1:K, rep(K, L-K-1), K:1) 
    c(SUMS/counts) 
} 

    test elapsed relative 
3 SSA_2 0.156 1.000000 
2 SSA_1 0.559 3.583333 
1 SSA 5.389 34.544872 

Một sự tăng tốc của x34.5 so với mã gốc !!

]

+0

Vectơ rất đẹp với 'rowsums'! –

+0

wow. thật tuyệt. tôi đã không nghĩ về nó theo cách đó. – pslice

+0

Bạn có thể làm cho nó nhanh hơn nữa bằng cách chỉ sử dụng các phần của 'rowsums' mà bạn cần: (tức là' sort (unique (...)) 'và' .Call ("Rrowsum_matrix", ...) '. –

0

tôi không thể có được ví dụ của bạn để tạo ra kết quả hợp lý. Tôi nghĩ rằng có một số lỗi trong chức năng của bạn.

  1. XX được sử dụng trong sapply, nhưng không được định nghĩa trong hàm
  2. sapply công trình trên 1:N, nơi N=144 trong ví dụ của bạn, nhưng x.b chỉ có 115 cột
  3. reconSSA chỉ đơn giản trả x

Bất kể, tôi nghĩ bạn muốn:

data(AirPassengers) 
x <- AirPassengers 
rowMeans(embed(x,30)) 

CẬP NHẬT: Tôi đã làm việc lại và lược tả chức năng. Phần lớn thời gian được sử dụng trong mean, vì vậy có thể khó có thể sử dụng mã R này nhanh hơn nhiều. Điều đó nói rằng, bạn có thể tăng tốc 20% bằng cách sử dụng sum thay thế.

reconSSA <- function(S,v,group=1){ 

    N <- length(v) 
    L <- nrow(S) 
    K <- N-L+1 
    XX <- matrix(0,nrow=L,ncol=K) 
    IND <- row(XX)+col(XX)-1 
    XX <- matrix(v[row(XX)+col(XX)-1],nrow=L,ncol=K) 
    XX <- S[,group] %*% t(t(XX) %*% S[,group]) 

    ##Diagonal Averaging 
    .intFun <- function(i,x,ind) { 
     I <- ind==i 
     sum(x[I])/sum(I) 
    } 

    RC <- sapply(1:N,.intFun,x=XX,ind=IND) 
    return(RC) 
} 
+0

Đó không phải là những gì tôi đang tìm kiếm. Ý tưởng là sử dụng cấu trúc xb (Hankel) và trung bình chống đường chéo, vì chúng ta sẽ tìm kiếm xấp xỉ xb, có khả năng sẽ không có cấu trúc đúng (Hankel), vì vậy sử dụng tính trung bình chéo làm giảm bớt vấn đề này ở một mức độ nào đó . Điều này thuộc chủ đề phân tích phổ số ít. Tôi cũng đã cố định tham chiếu mà bạn đã đề cập. – pslice

+0

Tôi sẽ chụp một bức ảnh khác nếu bạn có thể giải thích những gì bạn mong đợi cuộc gọi đến 'sapply' để làm. Mục đích của bạn không rõ ràng từ mã. –

+0

Những gì tôi mong đợi nó làm là ở dưới cùng của trang 3. Xem liên kết cho một PDF. http://bit.ly/ati1ll – pslice

Các vấn đề liên quan