Мені все одно, що я буду fda
використовувати об'єктні структури, подібні до Inception , в списку в межах списку, але моя відповідь буде дотримуватися системи, створеної авторами пакетів.
Я думаю, що спочатку подумати над тим, що ми робимо саме. Виходячи з вашого опису того, що ви робили до цього часу, я вважаю, що ви робите це (дайте мені знати, чи я неправильно трактував). Я продовжую використовувати позначення, і через відсутність реальних даних, приклад з функціонального аналізу даних Рамзая та Сільвермена та функціонального аналізу даних Рамсей, Хукера та Грейвса за допомогою R та MATLAB (Деякі з наступних рівнянь та коду піднімаються безпосередньо з цих книжок).
Ми моделюємо скалярний відгук за допомогою функціональної лінійної моделі, тобто
уi= β0+ ∫Т0Хi( s ) β( s ) ds + ϵi
Розширюємо в деякій основі. Ми використовуємо, скажімо, K базисні функції. Тому,βК
β( s ) = ∑k = 1Кбкθк( и )
У матричних позначеннях це .β( s ) = θ'( s ) b
Ми також розширюємо коваріатні функції і в деякій основі (скажімо, базисні функції). Тому,L
Хi( s ) = ∑k = 1Lcя кψк( и )
Знову ж таки, у матричній нотації це .Х( s ) = C ψ ( s )
Таким чином, якщо дозволити , наша модель може бути виражена якJ =∫ψ ( s ) θ'( s ) dс
у= β0+ C J b .
І якщо дозволити та , наша модель -ξ = [ β 0Z = [ 1C J ]ξ = [ β0б']'
y = Z ξ
І це нам виглядає набагато звичніше.
Тепер я бачу, що ви додаєте якусь регуляризацію. fda
Пакет працює з шорсткістю штрафами форми
П= λ ∫[ L β( и ) ]2гс
для деякого лінійного диференціального оператора . Тепер можна показати (деталі, залишені тут - це справді не важко показати), що якщо ми визначимо матрицю штрафу якRLR
R =λ ⎛⎝⎜⎜⎜⎜⎜00⋮00R1⋮0⋯⋯⋱⋯00⋮RК⎞⎠⎟⎟⎟⎟⎟
де з точки зору розширення бази , ми мінімізуємо суму квадратів:β iRiβi
( y - Z ξ )'( y - Z ξ ) + λ ξ'R ξ ,
і тому наша проблема - це просто регресія хребта з рішенням:
ξ^= ( Z'Z +λ R )- 1Z'у .
Я переглянув вищесказане, тому що: (1) Я думаю, що важливо, щоб ми розуміли, що ми робимо, і (2) деякі з перерахованих вище необхідні для розуміння коду, який я буду використовувати згодом. Про код ...
Ось приклад даних з кодом R. Я використовую канадський набір даних про погоду, наданий у fda
пакеті. Ми будемо моделювати річну кількість опадів для декількох метеостанцій за допомогою функціональної лінійної моделі та використовуватимемо температурні профілі (температури фіксувались один раз на день протягом 365 днів) від кожної станції як функціональні коваріати. Ми будемо діяти аналогічно тому, як ви описуєте у своїй ситуації. Дані були записані на 35 станціях. Я розбиваю набір даних на 34 станції, які будуть використовуватися як мої дані, і останню станцію, яка буде моїм "новим" набором даних.
Я продовжую користуватися кодом R та коментарями (я припускаю, що ви досить добре знайомі з fda
пакетом, щоб нічого з наступного не надто дивно - якщо це не так, будь ласка, повідомте мене):
# 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)
Тепер, коли мене вперше вчили про функціональні дані рік або близько того, я пограв з цим пакетом. Я також не міг змусити predict.fRegress
дати мені те, що хотів. Озираючись на це зараз, я все ще не знаю, як змусити його вести себе. Отже, нам доведеться просто отримати прогнози напівавтоматично. Я буду використовувати шматки, які я витягнув прямо з коду fRegress()
. Знову продовжую за допомогою коду та коментарів.
По-перше, налаштування:
# 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)
Тепер, щоб отримати прогнози
y^new=Znewξ^
Я просто беру код, який fRegress
використовує, щоб обчислити yhatfdobj
і трохи відредагувати його. fRegress
обчислює yhatfdobj
, оцінюючи інтеграл за допомогою правила трапеції (з та розширеними у відповідних базах). X i β∫T0Xi(s)β(s)Xiβ
Зазвичай, fRegress
обчислює встановлені значення, перебираючи коваріати, що зберігаються в annPrecTemp$xfdlist
. Отже, для нашої проблеми, ми замінюємо цей список коваріатів на відповідний у нашому новому списку коваріатів, тобто templistNew
. Ось код (ідентичний коду, знайденому fRegress
з двома правками, деякими видаленнями непотрібного коду та кількома коментарями додано):
# 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
}
(зауважте: якщо ви подивитеся на цей фрагмент та оточуючий код fRegress
, ви побачите кроки, які я окреслив вище).
Я перевірив код, повторно застосувавши приклад погоди, використовуючи всі наші 35 станцій як наші дані, і порівняв висновок з вищевказаного циклу annPrecTemp$yhatfdobj
і все збігається. Я також кілька разів запускав його, використовуючи різні станції, як мої "нові" дані, і все здається розумним.
Повідомте мене, якщо щось із вищезазначеного є незрозумілим або якщо щось не працює належним чином. Вибачте за занадто детальну відповідь. Я не міг собі допомогти :) А якщо ви ще не володієте ними, перегляньте дві книги, якими я писав цю відповідь. Вони справді хороші книги.