Memprediksi respons dari kurva baru menggunakan paket fda di R

10

Pada dasarnya yang ingin saya lakukan adalah memprediksi respons skalar menggunakan beberapa kurva. Saya sudah sejauh melakukan regresi (menggunakan fRegress dari paket fda) tetapi tidak tahu bagaimana menerapkan hasil ke set kurva BARU (untuk prediksi).

Saya memiliki N = 536 kurva, dan 536 respons skalar. Inilah yang telah saya lakukan sejauh ini:

  • Saya telah membuat dasar untuk kurva.
  • Saya telah membuat objek fdPar untuk memperkenalkan penalti
  • Saya telah membuat objek fd menggunakan smooth.basis untuk memuluskan kurva dengan penalti yang dipilih pada dasar yang ditentukan.
  • Saya telah menjalankan regresi menggunakan fRegress (), mundur kurva pada respon skalar.

Sekarang, yang ingin saya lakukan adalah menggunakan regresi itu untuk menghasilkan prediksi untuk set data baru yang saya miliki. Sepertinya saya tidak dapat menemukan cara mudah untuk melakukan ini.

Bersulang

dcl
sumber
Bahkan deskripsi cara menghitung prediksi secara manual dari basis, objek yang dihaluskan (fd) dan estimasi regresi dari fRegress () akan sangat membantu.
dcl
Hanya memeriksa: apakah Anda mencoba menggunakan predict.fRegressmenggunakan newdataopsi (dari manual FDA disini )?
Ya, hanya saja saya tidak begitu yakin kelas apa atau format 'data baru' harus. Ia tidak akan menerima objek fd atau fdSmooth yang merupakan kurva lancaran yang ingin saya prediksi. Dan itu tidak akan membiarkan saya memasukkan argumen mentah dan nilai kovariat.
dcl
1
Saya ingat memiliki masalah yang sama sekitar setahun yang lalu ketika saya bermain-main dengan fdapaket itu. Saya menulis respons yang melibatkan prediksi secara manual, tetapi sebagian besar hilang karena tidak menyimpannya. Jika orang lain tidak mengalahkan saya untuk itu, saya harus punya solusi untuk Anda dalam beberapa hari.

Jawaban:

14

Saya tidak peduli dengan fdapenggunaan struktur objek Inception - like-list-dalam-daftar-dalam-daftar, tetapi tanggapan saya akan mematuhi sistem yang telah dibuat oleh penulis paket.

Saya pikir itu penting untuk pertama-tama berpikir tentang apa yang sedang kita lakukan sebenarnya. Berdasarkan uraian Anda tentang apa yang telah Anda lakukan sejauh ini, inilah yang saya yakin Anda lakukan (beri tahu saya jika saya salah mengartikan sesuatu). Saya akan terus menggunakan notasi dan, karena kurangnya data nyata, contoh dari Analisis Data Fungsional Ramsay dan Silverman dan Analisis Data Fungsional Ramsay, Hooker, dan Graves dengan R dan MATLAB (Beberapa persamaan dan kode berikut diangkat langsung dari buku-buku ini).

Kami memodelkan respons skalar melalui model linier fungsional, yaitu

yi=β0+0TXi(s)β(s)ds+ϵi

Kami memperluas dengan dasar tertentu. Kami menggunakan, katakanlah, fungsi berbasisBegitu,KβK

β(s)=k=1Kbkθk(s)

Dalam notasi matriks, ini adalah .β(s)=θ(s)b

Kami juga memperluas fungsi kovariat dalam beberapa basis, juga (misalkan fungsi basis ). Begitu,L

Xi(s)=k=1Lcikψk(s)

Sekali lagi, dalam notasi matriks, ini adalah .X(s)=Cψ(s)

Dan dengan demikian, jika kita membiarkan , model kita dapat dinyatakan sebagaiJ=ψ(s)θ(s)ds

y=β0+CJb .

Dan jika kita membiarkan dan , model kami adalahZ=[1CJ]ξ=[β0b]

y=Zξ

Dan ini terlihat jauh lebih akrab bagi kita.

Sekarang saya melihat Anda menambahkan semacam regularisasi. The fdapaket bekerja dengan hukuman kekasaran bentuk

P=λ[Lβ(s)]2ds

untuk beberapa operator linear diferensial . Sekarang dapat ditunjukkan (detail ditinggalkan di sini - benar-benar tidak sulit untuk menunjukkan ini) bahwa jika kita mendefinisikan matriks penalti sebagaiLR

R=λ(0000R1000RK)

di mana adalah dalam hal perluasan dasar , maka kami meminimalkan jumlah kotak yang terkena penalti:Riβi

(yZξ)(yZξ)+λξRξ ,

dan masalah kita hanyalah regresi ridge dengan solusi:

ξ^=(ZZ+λR)1Zy .

Saya berjalan di atas karena, (1) Saya pikir penting untuk memahami apa yang kami lakukan, dan (2) beberapa di atas diperlukan untuk memahami beberapa kode yang akan saya gunakan nanti. Aktif ke kode ...

Berikut ini contoh data dengan kode R. Saya menggunakan dataset cuaca Kanada yang disediakan dalam fdapaket. Kami akan memodelkan curah hujan tahunan log untuk sejumlah stasiun cuaca melalui model linier fungsional dan kami akan menggunakan profil suhu (suhu dicatat sekali sehari selama 365 hari) dari masing-masing stasiun sebagai kovariat fungsional. Kami akan melanjutkan dengan cara yang Anda uraikan dalam situasi Anda. Data direkam di 35 stasiun. Saya akan memecah dataset menjadi 34 stasiun, yang akan digunakan sebagai data saya, dan stasiun terakhir, yang akan menjadi dataset "baru" saya.

Saya melanjutkan melalui kode R dan komentar (saya berasumsi Anda cukup akrab dengan fdapaket sehingga tidak ada yang berikut ini yang mengejutkan - jika ini tidak terjadi, tolong beri tahu saya):

# pick out data and 'new data'
dailydat <- daily$precav[,2:35]
dailytemp <- daily$tempav[,2:35]
dailydatNew <- daily$precav[,1]
dailytempNew <- daily$tempav[,1]

# set up response variable
annualprec <- log10(apply(dailydat,2,sum))

# create basis objects for and smooth covariate functions
tempbasis <- create.fourier.basis(c(0,365),65)
tempSmooth <- smooth.basis(day.5,dailytemp,tempbasis)
tempfd <- tempSmooth$fd

# create design matrix object
templist <- vector("list",2)
templist[[1]] <- rep(1,34)
templist[[2]] <- tempfd

# create constant basis (for intercept) and
# fourier basis objects for remaining betas
conbasis <- create.constant.basis(c(0,365))
betabasis <- create.fourier.basis(c(0,365),35)
betalist <- vector("list",2)
betalist[[1]] <- conbasis
betalist[[2]] <- betabasis

# set roughness penalty for betas 
Lcoef <- c(0,(2*pi/365)^2,0)
harmaccelLfd <- vec2Lfd(Lcoef, c(0,365))
lambda <- 10^12.5
betafdPar <- fdPar(betabasis, harmaccelLfd, lambda)
betalist[[2]] <- betafdPar

# regress
annPrecTemp <- fRegress(annualprec, templist, betalist)

Sekarang ketika saya pertama kali diajarkan tentang data fungsional setahun yang lalu, saya bermain-main dengan paket ini. Saya juga tidak bisa predict.fRegressmemberikan apa yang saya inginkan. Melihat ke belakang sekarang, saya masih tidak tahu bagaimana membuatnya berperilaku. Jadi, kita hanya perlu mendapatkan prediksi semi-manual. Saya akan menggunakan potongan yang saya tarik langsung dari kode fRegress(). Sekali lagi, saya melanjutkan melalui kode dan komentar.

Pertama, pengaturannya:

# create basis objects for and smooth covariate functions for new data
tempSmoothNew <- smooth.basis(day.5,dailytempNew,tempbasis)
tempfdNew <- tempSmoothNew$fd

# create design matrix object for new data
templistNew <- vector("list",2)
templistNew[[1]] <- rep(1,1)
templistNew[[2]] <- tempfdNew

# convert the intercept into an fd object
onebasis <- create.constant.basis(c(0,365))
templistNew[[1]] <- fd(matrix(templistNew[[1]],1,1), onebasis)

Sekarang untuk mendapatkan prediksi

y^new=Znewξ^

Saya hanya mengambil kode yang fRegressdigunakan untuk menghitung yhatfdobjdan mengeditnya sedikit. fRegressmenghitung yhatfdobjdengan memperkirakan integral melalui aturan trapesium (dengan dan diperluas di basis masing-masing). 0TXi(s)β(s)Xiβ

Biasanya, fRegresshitung nilai-nilai yang dipasang dengan mengulang melalui kovariat yang disimpan annPrecTemp$xfdlist. Jadi untuk masalah kami, kami mengganti daftar kovariat ini dengan yang sesuai dalam daftar kovariat baru kami, yaitu templistNew,. Berikut kodenya (identik dengan kode yang ditemukan fRegressdengan dua pengeditan, beberapa penghapusan kode yang tidak dibutuhkan, dan beberapa komentar ditambahkan):

# set up yhat matrix (in our case it's 1x1)
yhatmat <- matrix(0,1,1)

# loop through covariates
p <- length(templistNew)
for(j in 1:p){
    xfdj       <- templistNew[[j]]
    xbasis     <- xfdj$basis
    xnbasis    <- xbasis$nbasis
    xrng       <- xbasis$rangeval
    nfine      <- max(501,10*xnbasis+1)
    tfine      <- seq(xrng[1], xrng[2], len=nfine)
    deltat     <- tfine[2]-tfine[1]
    xmat       <- eval.fd(tfine, xfdj)
    betafdParj <- annPrecTemp$betaestlist[[j]]
    betafdj    <- betafdParj$fd
    betamat    <- eval.fd(tfine, betafdj)
    # estimate int(x*beta) via trapezoid rule
    fitj       <- deltat*(crossprod(xmat,betamat) - 
                      0.5*(outer(xmat[1,],betamat[1,]) +
              outer(xmat[nfine,],betamat[nfine,])))
    yhatmat    <- yhatmat + fitj
}

(catatan: jika Anda melihat kode chunk dan sekitarnya ini fRegress, Anda akan melihat langkah-langkah yang saya uraikan di atas).

Saya menguji kode dengan menjalankan kembali contoh cuaca menggunakan semua 35 stasiun sebagai data kami dan membandingkan output dari loop di atas annPrecTemp$yhatfdobjdan semuanya cocok. Saya juga menjalankannya beberapa kali menggunakan stasiun yang berbeda sebagai data "baru" saya dan semuanya tampak masuk akal.

Beri tahu saya jika ada di atas yang tidak jelas atau ada yang tidak berfungsi dengan benar. Maaf atas tanggapan yang terlalu rinci. Saya tidak bisa menahan diri :) Dan jika Anda belum memilikinya, lihat dua buku yang saya gunakan untuk menulis tanggapan ini. Buku-buku itu sangat bagus.


sumber
Sepertinya ini yang saya butuhkan. Terima kasih. Saya berasumsi saya tidak perlu bermain-main dengan hal-hal nfine / tine / deltat kan? Haruskah saya menganggap integrasi sedang dilakukan cukup akurat?
dcl
Juga, saya perhatikan Anda tidak menghukum kovariat 'baru' atau kovariat 'lama' secara langsung. Itu semua dilakukan dengan menghukum beta (dan jumlah fungsi dasar kurasa). Penalti lambda diterapkan pada beta. Apakah Anda mencapai efek yang sama dengan menghukum smoothes sebelum regresi? (dengan nilai yang sama dari lambda)
dcl
1
Kisi-kisi yang digunakan untuk mendekati integral cukup baik, sehingga perkiraannya harus cukup bagus. Anda selalu dapat meningkatkan nfinedan melihat berapa banyak perubahan integral tetapi saya kira itu tidak akan banyak membantu. Sejauh hukuman, ya kami langsung menghukum bukan dalam kasus ini. Ramsay dan Silverman membahas metode penalti lain yang memperkirakan tanpa fungsi dasar di mana kami menerapkan penalti langsung ke . Kedua cara menginduksi kendala kelancaran pada fungsi , tapi saya tidak yakin apakah Anda akan mendapatkan 'efek yang sama.' ξββ^ββ
Saya sudah mencoba memanipulasi kode untuk menghasilkan prediksi untuk banyak kurva, tetapi saya tidak yakin saya telah melakukannya dengan benar. Sebagai permulaan, yhatmat tidak konstan untuk semua kurva setelah iterasi pertama dari loop ... Apakah ini dimaksudkan untuk setara dengan ? β0
dcl
1
@ dcl Dalam loop, ketika , ia menambahkan ke (dengan asumsi daftar pertama di Xlist Anda sesuai dengan istilah intersep). Bisakah Anda menambahkan potongan kode yang Anda gunakan ke pertanyaan Anda sehingga saya bisa melihatnya? j=1β0^y^