Le spline vengono utilizzate nella modellazione di regressione per modellare forme funzionali eventualmente non lineari complesse. Una tendenza levigata della spline consiste di polinomi continui a tratti il cui coefficiente principale cambia ad ogni punto di rottura o nodo. La spline può essere specificata in termini di grado polinomiale della tendenza e di punti di interruzione. Una rappresentazione spline di una covariata estende un singolo vettore di valori osservati in una matrice la cui dimensione è il grado polinomiale più il numero di nodi.
Una versione periodica di spline è semplicemente una versione periodica di qualsiasi regressione: i dati vengono tagliati in repliche della lunghezza del periodo. Quindi, ad esempio, modellare una tendenza diurna in un esperimento di più giorni sui ratti richiederebbe il tempo di ricodifica dell'esperimento in incrementi di 24 ore, quindi la 154a ora sarebbe il valore del modulo 24 di 10 (154 = 6 * 24 + 10). Se si adatta una regressione lineare sui dati di taglio, si stima una forma d'onda a dente di sega per la tendenza. Se si inserisce una funzione di passaggio da qualche parte nel periodo, sarebbe una forma d'onda quadrata che si adatta alla serie. La spline è in grado di esprimere un wavelet molto più sofisticato. Per quello che vale, nel splines
pacchetto c'è una funzione periodicSpline
che fa esattamente questo.
Non trovo che l'implementazione "bs" della spline predefinita di R sia utile per l'interpretazione. Quindi ho scritto la mia sceneggiatura qui sotto. Per una spline di grado con nodi , questa rappresentazione fornisce alle prime colonne la rappresentazione polinomiale standard, le colonne ( ) vengono semplicemente valutate come dove è il vettore effettivo dei nodi.p p p + i i ≤ n k S p + i = ( X - k i ) p I ( X < k i ) knkpp+ii≤nkSp+i=(X−ki)pI(X<ki)k
myspline <- function(x, degree, knots) {
knots <- sort(knots)
val <- cbind(x, outer(x, knots, `-`))
val[val < 0] <- 0
val <- val^degree
if(degree > 1)
val <- cbind(outer(x, 1:{degree-1}, `^`), val)
colnames(val) <- c(
paste0('spline', 1:{degree-1}, '.1'),
paste0('spline', degree, '.', seq(length(knots)+1))
)
val
}
Per un piccolo caso di studio, interpolare una tendenza sinusoidale nel dominio da 0 a (o ) in questo modo:τ2πτ
x <- seq(0, 2*pi, by=pi/2^8)
y <- sin(x)
plot(x,y, type='l')
s <- myspline(x, 2, pi)
fit <- lm(y ~ s)
yhat <- predict(fit)
lines(x,yhat)
Vedrai che sono abbastanza concordanti. Inoltre, la convenzione di denominazione consente l'interpretazione. Nell'output di regressione viene visualizzato:
> summary(fit)
Call:
lm(formula = y ~ s)
Residuals:
Min 1Q Median 3Q Max
-0.04564 -0.02050 0.00000 0.02050 0.04564
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -0.033116 0.003978 -8.326 7.78e-16 ***
sspline1.1 1.268812 0.004456 284.721 < 2e-16 ***
sspline2.1 -0.400520 0.001031 -388.463 < 2e-16 ***
sspline2.2 0.801040 0.001931 414.878 < 2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.02422 on 509 degrees of freedom
Multiple R-squared: 0.9988, Adjusted R-squared: 0.9988
F-statistic: 1.453e+05 on 3 and 509 DF, p-value: < 2.2e-16
La prima serie di covariate per il mio spline 1.1 gradi è la tendenza polinomiale per il primo dominio dietro il primo punto di interruzione. Il termine lineare è la pendenza della tangente all'origine, X = 0. Questo è quasi 1 che sarebbe indicato dalla derivata della curva sinusoidale (cos (0) = 1), ma dobbiamo tenere presente che si tratta di approssimazioni e che l'errore di estrapolare la tendenza quadratica fuori è incline errore. Il termine quadratico indica una forma concava negativa. Il termine spline2.2 indica una differenza dalla prima pendenza quadratica, portando a un coefficiente iniziale positivo di 0,4 che indica una forma convessa verso l'alto. Quindi ora abbiamo un'interpretazione disponibile per l'output della spline e possiamo giudicare l'inferenza e le stime di conseguenza.π/2
Presumo che tu conosca la periodicità dei dati a portata di mano. Se i dati mancano di una componente di crescita o media mobile, è possibile trasformare una serie temporale lunga in repliche di una serie breve della durata di 1 periodo. Ora hai repliche e puoi utilizzare l'analisi dei dati per stimare la tendenza ricorrente.
Supponiamo che io generi le seguenti serie piuttosto rumorose, molto lunghe:
x <- seq(1, 100, by=0.01)
y <- sin(x) + rnorm(length(x), 0, 10)
xp <- x %% (2*pi)
s <- myspline(xp, degree=2, knots=pi)
lm(y ~ s)
L'output risultante mostra prestazioni ragionevoli.
> summary(fit)
Call:
lm(formula = y ~ s)
Residuals:
Min 1Q Median 3Q Max
-39.585 -6.736 0.013 6.750 37.389
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -0.48266 0.38155 -1.265 0.205894
sspline1.1 1.52798 0.42237 3.618 0.000299 ***
sspline2.1 -0.44380 0.09725 -4.564 5.09e-06 ***
sspline2.2 0.76553 0.18198 4.207 2.61e-05 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 9.949 on 9897 degrees of freedom
Multiple R-squared: 0.006406, Adjusted R-squared: 0.006105
F-statistic: 21.27 on 3 and 9897 DF, p-value: 9.959e-14