Прогнозування реакції з нових кривих за допомогою пакета fda в R


10

В основному все, що я хочу зробити, це передбачити скалярну реакцію за допомогою деяких кривих. У мене є регрес (з використанням fRegress з пакета fda), але не маю уявлення, як застосувати результати до НОВОГО набору кривих (для прогнозування).

У мене N = 536 кривих і 536 скалярних відповідей. Ось що я зробив досі:

  • Я створив основу для кривих.
  • Я створив об’єкт fdPar, щоб запровадити штраф
  • Я створив об'єкт fd за допомогою smooth.basis, щоб згладити криві з обраним штрафом за вказаною ознакою.
  • Я провів регресію за допомогою fRegress (), регресуючи криві скалярної реакції.

Тепер, все, що я хотів би зробити, - це використовувати цю регресію для створення прогнозів для нового набору даних, які я маю. Я не можу знайти простий спосіб зробити це.

Ура


Навіть опис того, як обчислити прогнози вручну з основи, згладжених (fd) об'єктів та регресійних оцінок з fRegress () буде дуже корисним.
dcl

Просто перевіряю: ви пробували використовувати з predict.fRegressдопомогою newdataопції (з керівництва Укравтодору тут )?

У мене є, я просто не впевнений, яким класом чи форматом мають бути "нові дані". Він не прийме об'єкт fd або fdSmooth, які є згладженими кривими, від яких я хочу передбачити. І це не дозволить мені вводити необгрунтовані аргументи та значення коефіцієнта.
dcl

1
Я пам’ятаю, що мав подібну проблему близько року тому, коли я грав із fdaпакетом. Я писав відповідь, яка передбачала отримання прогнозів вручну, але великий шматок цього було втрачено через те, що не зберегти його. Якщо хтось інший не переможе мене, я повинен мати рішення для вас за пару днів.

Відповіді:


14

Мені все одно, що я буду fdaвикористовувати об'єктні структури, подібні до Inception , в списку в межах списку, але моя відповідь буде дотримуватися системи, створеної авторами пакетів.

Я думаю, що спочатку подумати над тим, що ми робимо саме. Виходячи з вашого опису того, що ви робили до цього часу, я вважаю, що ви робите це (дайте мені знати, чи я неправильно трактував). Я продовжую використовувати позначення, і через відсутність реальних даних, приклад з функціонального аналізу даних Рамзая та Сільвермена та функціонального аналізу даних Рамсей, Хукера та Грейвса за допомогою R та MATLAB (Деякі з наступних рівнянь та коду піднімаються безпосередньо з цих книжок).

Ми моделюємо скалярний відгук за допомогою функціональної лінійної моделі, тобто

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

Розширюємо в деякій основі. Ми використовуємо, скажімо, K базисні функції. Тому,βK

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

У матричних позначеннях це .β(s)=θ(s)b

Ми також розширюємо коваріатні функції і в деякій основі (скажімо, базисні функції). Тому,L

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

Знову ж таки, у матричній нотації це .X(s)=Cψ(s)

Таким чином, якщо дозволити , наша модель може бути виражена якJ=ψ(s)θ(s)ds

y=β0+CJb .

І якщо дозволити та , наша модель -ξ = [ β 0Z=[1CJ]ξ=[β0b]

y=Zξ

І це нам виглядає набагато звичніше.

Тепер я бачу, що ви додаєте якусь регуляризацію. fdaПакет працює з шорсткістю штрафами форми

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

для деякого лінійного диференціального оператора . Тепер можна показати (деталі, залишені тут - це справді не важко показати), що якщо ми визначимо матрицю штрафу якRLR

R=λ(0000R1000RK)

де з точки зору розширення бази , ми мінімізуємо суму квадратів:β iRiβi

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

і тому наша проблема - це просто регресія хребта з рішенням:

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

Я переглянув вищесказане, тому що: (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 β0TXi(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і все збігається. Я також кілька разів запускав його, використовуючи різні станції, як мої "нові" дані, і все здається розумним.

Повідомте мене, якщо щось із вищезазначеного є незрозумілим або якщо щось не працює належним чином. Вибачте за занадто детальну відповідь. Я не міг собі допомогти :) А якщо ви ще не володієте ними, перегляньте дві книги, якими я писав цю відповідь. Вони справді хороші книги.


Це виглядає так, що це саме те, що мені потрібно. Дякую. Я припускаю, що мені не доведеться грати з nfine / tine / deltat, так? Чи слід вважати, що інтеграція працює досить точно?
dcl

Також я зауважую, що ви не штрафували безпосередньо «нового» коріаріату або «старого» коріаріату. Це все зроблено з пеналізацією бета-версії (і я думаю, що кількість базових функцій). Штраф-лямбда застосовується до бета-версії. Чи досягаєте ви такого ж ефекту, штрафуючи згладжування перед регресією? (з однаковим значенням лямбда)
dcl

1
Сітка, яка використовується для наближення інтеграла, є досить чудовою, тому наближення має бути досить хорошим. Ви завжди можете збільшити nfineі побачити, наскільки цілісні зміни, але я здогадуюсь, що це не дасть багато чого. Що стосується штрафних санкцій, так, ми прямо в такому випадку караємо замість . Рамсей і Сільверман обговорюють ще один метод штрафу, який оцінює без базових функцій, де ми застосовуємо штраф безпосередньо до . Обидва способи викликають обмеження плавності функцій , але я не впевнений, чи отримаєте ви "той самий ефект". & beta ; & beta ; & beta ; & beta ;ξββ^ββ

Я намагався маніпулювати кодом для створення прогнозів для декількох кривих, але я не впевнений, що зробив це правильно. Для початку, yhatmat не є постійним для всіх кривих після першої ітерації циклу ... Це означає, що це еквівалентно ? β0
dcl

1
@dcl У циклі, коли , він додає до (якщо припустити, що перший список у вашому Xlist відповідає терміну перехоплення). Чи можете ви додати фрагмент коду, який ви використовуєте, до свого питання, щоб я міг його переглянути? ^ β 0 уj=1β0^y^
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.