Contact
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
| Download

a research paper about FDSLRM modeling with supplementary materials - software, notebooks

Project: fdslrm
Views: 1041
Kernel: SageMath (stable)

Authors: Jozef Hanč, Martina Hančová, Andrej Gajdoš
Faculty of Science, P. J. Šafárik University in Košice, Slovakia
emails: [email protected]


EBLUP-NE for electricity consumption 1

Python-based computational tools - SageMath

Table of Contents

To get back to the contents, use the Home key.

SageMath - precision and functions

SageMath is a free Python-based mathematics software, an open source alternative to the well-known commercial computer algebra systems Mathematica or Maple, which is built on top of SciPy ecosystem, Maxima, R, GAP, FLINT and many others open-source packages; http://www.sagemath.org/

# arbitrary precision in dps decimal places for numerical results dps = 20 # precision in bits, real (floating-point) numbers with given precision bits = round((dps+1)*ln(10)/ln(2)) RRk = RealField(bits) # simplifying any symbolic matrix, vector def simplify_matrix(A): return A.apply_map(lambda item: item.expand()) # converting symbolic matrix, vector to numerical in RRk def RRk_matrix(A): return A.apply_map(RRk) from itertools import product

Data and Toy model 1

In this FDSLRM application, we model the econometric time series data set, representing the hours observations of the consumption of the electric energy in some department store. The number of time series observations is n=24n=24. The data was adapted from Štulajter & Witkovský, 2004 and the FDSLRM model from Gajdoš et al 2017.

The consumption data can be fitted by the following Gaussian orthogonal FDSLRM:

X(t) ⁣= ⁣β1+β2cos(2πt24)+β3sin(2πt24)++Y1cos(2πt324)+Y2sin(2πt324)++Y3cos(2πt424)+Y4sin(2πt424)+w(t),tN, \begin{array}{rl} & X(t) & \! = \! & \beta_1+\beta_2\cos\left(\tfrac{2\pi t}{24}\right)+\beta_3\sin\left(\tfrac{2\pi t}{24}\right) +\\ & & & +Y_1\cos\left(\tfrac{2\pi t\cdot 3}{24}\right)+Y_2\sin\left(\tfrac{2\pi t\cdot 3}{24}\right)+\\ & & & +Y_3\cos\left(\tfrac{2\pi t\cdot 4}{24}\right)+Y_4\sin\left(\tfrac{2\pi t\cdot 4}{24}\right) +w(t), \, t\in \mathbb{N}, \end{array}

where β=(β1,β2,β3)R3,Y=(Y1,Y2,Y3,Y4)N4(0,D),w(t)iidN(0,σ02),ν=(σ02,σ12,σ22,σ32,σ42)R+5.\boldsymbol{\beta}=(\beta_1,\,\beta_2,\,\beta_3)' \in \mathbb{R}^3\,,\mathbf{Y} = (Y_1, Y_2, Y_3, Y_4)' \sim \mathcal{N}_4(\boldsymbol{0}, \mathrm{D})\,, w(t) \sim \mathcal{iid}\, \mathcal{N} (0, \sigma_0^2)\,, \boldsymbol{\nu}= (\sigma_0^2, \sigma_1^2, \sigma_2^2, \sigma_3^2, \sigma_4^2) \in \mathbb{R}_{+}^5.

# data - time series observation x data = [40.3,40.7,38.5,37.9,38.6,41.1,45.2,45.7,46.7,46.5, 45.2,45.1,45.8,46.3,47.5,48.5,49.1,51.7,50.6,48.0, 44.7,41.2,40.0,40.3] # observation x as a one-column matrix of rational numbers (infinite precision) x = matrix(QQ, data).T xc = x.T xc
[403/10 407/10 77/2 379/10 193/5 411/10 226/5 457/10 467/10 93/2 226/5 451/10 229/5 463/10 95/2 97/2 491/10 517/10 253/5 48 447/10 206/5 40 403/10]
# model parameters n, k, l = 24, 3, 4 # significant frequencies om1, om2, om3 = 2*pi/24, 2*pi/8, 2*pi/6 # model design matrices F', F, V',V Fc = matrix([[1 for t in range(1,n+1)], [cos(om1*t) for t in range(1,n+1)], [sin(om1*t) for t in range(1,n+1)]]) Vc = matrix([[cos(om2*t) for t in range(1,n+1)], [sin(om2*t) for t in range(1,n+1)], [cos(om3*t) for t in range(1,n+1)], [sin(om3*t) for t in range(1,n+1)]]) F, V = Fc.T, Vc.T # columns vj of V and their squared norm ||vj||^2 vv = lambda j: V[:,j-1] nv2 = lambda j: (vv(j).T*vv(j)).trace().expand()
# auxiliary matrices and vectors # Gram matrices GF, GV GF, GV = (Fc*F).expand(), (Vc*V).expand() InvGF, InvGV = (GF^(-1)).expand(), (GV^(-1)).expand() # projectors PF, MF, PV, MV In = identity_matrix(n) PF = (F*InvGF*Fc).canonicalize_radical().expand() PV = (V*InvGV*Vc).canonicalize_radical().expand() MF, MV = (In-PF).expand(), (In-PV).expand() # residuals e, e' e = MF*x ec = e.T
# orthogonality condition show((Fc*V).expand()) show(GV)

Natural estimators

ANALYTICALLY

using formula (4.1) from Hancova et al 2019

ParseError: KaTeX parse error: \renewcommand{\arraystretch} when command \arraystretch does not yet exist; use \newcommand

1st\boldsymbol{1^{st}} stage of EBLUP-NE

# NE according to formula (4.1) NE0 = [1/(n-k-l)*(ec*MV*e).trace()] NEj = [((ec*vv(j)).trace()/nv2(j))^2 for j in [1..l]] NE = vector(NE0+NEj)
# final NE NEsimp = NE.column().expand() show(NEsimp)
# numerical results with given precision in dps NEnum = RRk_matrix(NEsimp) NEnum
[ 3.5323140972047290984] [ 0.37193497450591316960] [ 1.8634794260764497182] [0.0044444444444444444444] [ 1.2675000000000000000]
NEnum.norm()
4.206508062641579

2nd\boldsymbol{2^{nd}} stage of EBLUP-NE

using formula (3.10) from Hancova et al 2019.

ν˚j=ρj2ν˘j;j=0,1,lρ0=1,ρj=ν^jvj2ν^0+ν^jvj2 \mathring{\nu}_j = \rho_j^2 \breve{\nu}_j; j = 0,1 \ldots, l\\ \rho_0 = 1, \rho_j = \dfrac{\hat{\nu}_j||\mathbf{v}_j||^2}{\hat{\nu}_0+\hat{\nu}_j||\mathbf{v}_j||^2}

where ν˘\boldsymbol{\breve{\nu}} are NE, ν^\boldsymbol{\hat{\nu}} are initial estimates for EBLUP-NE

# EBLUP-NE based on formula (3.9) rho2 = lambda est: vector( [1] + [ (est[j]*nv2(j)/(est[0]+est[j]*nv2(j)))^2 for j in [1..l] ]) EBLUPNE = lambda est: vector( rho2(est).pairwise_product(NE).list() )
# final EBLUPNE based on NE EBLUPNEsimp = EBLUPNE(NE).column().expand() show(EBLUPNEsimp)
# numerical results rho2(NEnum).column()
[ 1] [ 0.31160298070636086388] [ 0.74578072518084832926] [0.00022123930617640118797] [ 0.65858525704640917570]
EBLUPNEnum = RRk_matrix(EBLUPNEsimp) EBLUPNEnum
[ 3.5323140972047290984] [ 0.11589604668498688117] [ 1.3897470377388857171] [9.8328580522844972432e-7] [ 0.83475681330632363020]
EBLUPNEnum.norm()
3.88830175542161

NN-DOOLSE or MLE

1st\boldsymbol{1^{st}} stage of EBLUP-NE

KKT algorithm

using the the KKT algorithm (tab.3, Hancova et al 2019)

 ~

q=(ee(ev1)2(evl)2) \qquad \mathbf{q} = \left(\begin{array}{c} \mathbf{e}' \mathbf{e}\\ (\mathbf{e}' \mathbf{v}_{1})^2 \\ \vdots \\ (\mathbf{e}' \mathbf{v}_{l})^2 \end{array}\right)

G=(nv12v22vl2v12v1400v220v240vl200vl4)\qquad\mathrm{G} = \left(\begin{array}{ccccc} \small n^* & ||\mathbf{v}_{1}||^2 & ||\mathbf{v}_{2}||^2 & \ldots & ||\mathbf{v}_{l}||^2 \\ ||\mathbf{v}_{1}||^2 & ||\mathbf{v}_{1}||^4 & 0 & \ldots & 0 \\ ||\mathbf{v}_{2}||^2 & 0 & ||\mathbf{v}_{2}||^4 & \ldots & 0 \\ \vdots & \vdots & \vdots & \ldots & \vdots \\ ||\mathbf{v}_{l}||^2 & 0 & 0 & \ldots & ||\mathbf{v}_{l}||^4 \end{array}\right)

# Input: form G ns = n u, v, Q = ns, matrix([nv2(j) for j in [1..l]]), diagonal_matrix([nv2(j)^2 for j in [1..l]]) G = block_matrix([[u,v],[v.T,Q]])
# form q e2, Ve2 = ec*e, (Vc*e).elementwise_product(Vc*e) q = e2.stack(Ve2).expand()
# body of the algorithm for b in product([0,1], repeat=l+1): # set the KKT-conditions matrix K K = G*1 for j in range(l+1): if b[j] == 1: K[0,j], K[j,j] = 0,-1 # calculate the auxiliary vector g g = K^(-1)*q # test non-negativity g if RRk(min(g.list()))>=0: break
# Output: Form estimates nu nu = g*1 for j in range(l+1): if b[j] == 1: nu[j] = 0
# final DOOLSE DOOLSE = nu show(DOOLSE)
# numerical results DOOLSEnum = RRk_matrix(DOOLSE) print(DOOLSEnum, DOOLSE.norm(),b)
([ 2.8620320469435108574] [0.13343230392728726481] [ 1.6249767554978238134] [0.00000000000000000000] [ 1.0289973294213740952], 3.450857368441582, (0, 0, 0, 1, 0))

2nd\boldsymbol{2^{nd}} stage of EBLUP-NE

# final EBLUPNE based on DOOLSE EBLUPNEsimp = EBLUPNE(DOOLSE).column().expand() show(EBLUPNEsimp)
# numerical results rho2(DOOLSEnum).column()
[ 1] [0.12870278135360510016] [0.76040524092632442211] [ 0] [0.65907154135208143391]
EBLUPNEnum = RRk_matrix(EBLUPNEsimp) EBLUPNEnum
[ 3.5323140972047290984] [0.047869065701593229783] [ 1.4169995219469115088] [ 0.00000000000000000000] [ 0.83537317866376321748]
EBLUPNEnum.norm()
3.8968282386565334

NN-MDOOLSE or REMLE

using the KKT algorithm (tab.3, Hancova et al 2019)

1st\boldsymbol{1^{st}} stage of EBLUP-NE

# Input: form G ns = n-k u, v, Q = ns, matrix([nv2(j) for j in [1..l]]), diagonal_matrix([nv2(j)^2 for j in [1..l]]) G = block_matrix([[u,v],[v.T,Q]])
# form q e2, Ve2 = ec*e, (Vc*e).elementwise_product(Vc*e) q = e2.stack(Ve2).expand()
# body of the algorithm for b in product([0,1], repeat=l+1): # set the KKT-conditions matrix K K = G*1 for j in range(l+1): if b[j] == 1: K[0,j], K[j,j] = 0,-1 # calculate the auxiliary vector g g = K^(-1)*q # test non-negativity g if RRk(min(g.list()))>=0: break
# Output: Form estimates nu nu = g*1 for j in range(l+1): if b[j] == 1: nu[j] = 0
# final MDOOLSE MDOOLSE = nu show(MDOOLSE)
# numerical results MDOOLSEnum = RRk_matrix(nu) print(MDOOLSEnum, MDOOLSE.norm(),b)
([ 3.3390373881007626670] [0.093681858830849614018] [ 1.5852263104013861626] [ 0.00000000000000000000] [ 0.98924688432493644442], 3.827466371262347, (0, 0, 0, 1, 0))

2nd\boldsymbol{2^{nd}} stage of EBLUP-NE

# final EBLUPNE based on NE EBLUPNEsimp = EBLUPNE(MDOOLSE).column().expand() show(EBLUPNEsimp)
# numerical results rho2(MDOOLSEnum).column()
[ 1] [0.063442013996488589587] [ 0.72365795262659512283] [ 0] [ 0.60913484862207232793]
EBLUPNEnum = RRk_matrix(EBLUPNEsimp) EBLUPNEnum
[ 3.5323140972047290984] [0.023596303858387770044] [ 1.3485217062362661184] [ 0.00000000000000000000] [ 0.77207842062847667565]
EBLUPNEnum.norm()
3.859069259116448

References

This notebook belongs to suplementary materials of the paper submitted to Statistical Papers and available at https://arxiv.org/abs/1905.07771.

Abstract of the paper

We propose a two-stage estimation method of variance components in time series models known as FDSLRMs, whose observations can be described by a linear mixed model (LMM). We based estimating variances, fundamental quantities in a time series forecasting approach called kriging, on the empirical (plug-in) best linear unbiased predictions of unobservable random components in FDSLRM.

The method, providing invariant non-negative quadratic estimators, can be used for any absolutely continuous probability distribution of time series data. As a result of applying the convex optimization and the LMM methodology, we resolved two problems - theoretical existence and equivalence between least squares estimators, non-negative (M)DOOLSE, and maximum likelihood estimators, (RE)MLE, as possible starting points of our method and a practical lack of computational implementation for FDSLRM. As for computing (RE)MLE in the case of n n observed time series values, we also discovered a new algorithm of order O(n)\mathcal{O}(n), which at the default precision is 10710^7 times more accurate and n2n^2 times faster than the best current Python(or R)-based computational packages, namely CVXPY, CVXR, nlme, sommer and mixed.

We illustrate our results on three real data sets - electricity consumption, tourism and cyber security - which are easily available, reproducible, sharable and modifiable in the form of interactive Jupyter notebooks.