我有一个提高速度/可读性的问题。我在矩阵Y(dim = TxN)中具有N个长度为T的时间序列。我也有一个3D Matrix X,它是TxNxK。
数据具有一些随机的NaN值。
考虑到回归窗口(W),目标是使用截至X的数据创建Y的预测。考虑到对于任何单个Y时间序列,回归都应超过最后一个可用 W变量值。这意味着您需要所有X变量和相应的系列Y变量,但是您不需要关心其他Y变量。
我可以使用下面的代码来做到这一点,但是我觉得可能有一种删除循环的方法。我尝试使用地图和函数,但得到类似的timeit值,可读性较低。
import random
import numpy as np
from numpy.linalg import inv
# Parameters
N = 500 #Number of time series
T = 1000 #Length of each time series
W = 72 #Regression window
K = 3 #Numer of independent variables
Y = np.random.randn(T, N)
X = np.random.randn(T, N, K)
# Add the constants
X = np.concatenate((X, np.ones((T, N, 1))), axis=2)
def get_rand_arr(arr, frac_rand=0.0001):
ix = [(row, col) for row in range(arr.shape[0]) for col in range(arr.shape[1])]
for row, col in random.sample(ix, int(round(frac_rand*len(ix)))):
arr[row, col] = np.nan
return arr
# Insert some NaN values - like the real world - I dont care about this loop
Y = get_rand_arr(Y)
for i in range(X.shape[2]):
X[:, :, i] = get_rand_arr(X[:, :, i])
X_mask = np.apply_along_axis(np.any, 1, np.apply_along_axis(np.any, 2, np.isnan(X)))
Y_mask = np.concatenate([np.logical_or(np.isnan(Y)[:, i],X_mask).reshape(-1,1) for i in range(N)],axis=1)
Y_hat = np.NaN*np.zeros((T, N))
for j in range(N):
y = Y[~Y_mask[:, j], j]
x = X[~Y_mask[:, j], j, :]
y_hat = np.NaN*np.zeros(y.shape[0])
for i in range(y_hat.shape[0]-W):
y_hat[i+W] = x[i+W, :].dot(inv(x[i:i+W, :].T.dot(x[i:i+W, :])).dot(x[i:i+W, :].T.dot(y[i:i+W])))
Y_hat[~Y_mask[:, j], j] = y_hat
我得到以下时间结果
%%timeit
Y_hat = np.NaN*np.zeros((T, N))
for j in range(N):
y = Y[~Y_mask[:, j], j]
x = X[~Y_mask[:, j], j, :]
y_hat = np.NaN*np.zeros(y.shape[0])
for i in range(y_hat.shape[0]-W):
y_hat[i+W] = x[i+W, :].dot(inv(x[i:i+W, :].T.dot(x[i:i+W, :])).dot(x[i:i+W, :].T.dot(y[i:i+W])))
Y_hat[~Y_mask[:, j], j] = y_hat
9.5 s ± 373 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
时间序列足够长,回归窗口足够小,因此我实际上不必担心要确保我有足够的值来运行至少1个回归。