【发布时间】:2021-12-20 03:37:30
【问题描述】:
很遗憾,我想不出一个更好的标题;我承认,我无法更好地解释这一事实可能会妨碍我寻找已经确定的答案。
所以,我有一个包含 N1 行和 D 列的时间序列数据集。
循环神经网络需要 N2xTxD 格式的数据,因此如果序列长度 T 为 2,则新 N2xTxD 数据集ds2[0] 的第一个元素将是原始数据集的前两行ds[0:2, :]。第二个元素ds2[1] 将是ds[1:3, :] 以此类推,直到ds2[N2] = ds[N-2:N, :]
我现在的做法是使用这些函数:
import numpy as np
#Shift Array arr's elements by num positions
def NpShift(arr, num, fill_value = np.nan):
result = np.empty_like(arr)
result[:num] = fill_value
result[num:] = arr[:-num]
return result
def TemporalTransformation(ds, T):
tmp = ds
ds = ds.reshape(-1, 1, ds.shape[1]) #By definition ds is NxD, so Nx1xD is -1x1xshape[1]
for t in range(T):
ds = np.concatenate((NpShift(tmp, t+1)[:, np.newaxis, :], ds), axis = 1) #Adding the shifted matrices one by one
ds = ds[T-1:, 1:, :] #The 1st T-1 elements contain the shifted values so they have to be discarded; same goes for the 1st element on axis=1
return ds
您可以使用以下方法对其进行测试以查看结果是否正确:
t = 2
xall = np.array([[1,1,1], [2,2,2], [3,3,3], [4,4,4], [5,5,5]], dtype = float)
print(f"ds shape:\n{xall.shape}")
print(f"ds:\n{xall}\n")
ds2 = TemporalTransformation(xall, t)
print("ds2 shape:\n", ds2.shape)
print(f"ds2:\n{ds2}")
哪个输出:
ds shape:
(5, 3)
ds:
[[1. 1. 1.]
[2. 2. 2.]
[3. 3. 3.]
[4. 4. 4.]
[5. 5. 5.]]
ds2 shape:
(4, 2, 3)
ds2:
[[[1. 1. 1.]
[2. 2. 2.]]
[[2. 2. 2.]
[3. 3. 3.]]
[[3. 3. 3.]
[4. 4. 4.]]
[[4. 4. 4.]
[5. 5. 5.]]]
现在,它完美地工作并完成了我想要的,但是,对于大型数据集(数十万行)上的大量 T(例如 700),完成转换需要大量时间(30分钟左右)。
我可以观察到这段(当前)单线程代码在创建最终 (N-T-1)xTxD 张量(3 维数组)时如何缓慢而稳定地分配越来越多的 RAM。
有没有办法在不分配如此大量内存的情况下更快地完成它? 我的意思是,在其核心中,ds2 的值与 ds1 相同,所以我认为应该存在一种使用指针的方法(我只是想不出如何)。
任何可能的解决方案最好在 windows 和 linux 上都可以使用 最后一个值得注意的事情是,最终,这个 N2xTxD numpy 数组将被分批调用(因此一次迭代将调用前 b 行,然后是下 b 行),这批将成为 PyTorch 张量。
现在,我熟悉了 torch.utils.data.Dataset,并且我尝试通过继承它来扩展它以制作我自己的迭代器:
import numpy as np
from torch.utils.data import Dataset
class TemporalTransformation_Dataset(Dataset):
def __init__(self, data, T):
self.data = data
self.T = T
def __getitem__(self, index):
Xi = self.data[index : index + self.T]
return Xi
def __len__(self):
return self.data.shape[0] - self.T + 1
t = 2
ds = torch.from_numpy(np.array([[1,1,1], [2,2,2], [3,3,3], [4,4,4], [5,5,5]]))
print(f"ds shape:\n{ds.shape}")
print(f"ds:\n{ds}\n")
ds2 = TemporalTransformation_Dataset(ds, t)
ds2_loader = torch.utils.data.DataLoader(dataset = ds2, batch_size = len(ds2), shuffle = False)
print("W/o Y:\n", next(iter(ds2_loader)))
但是,与我的 numpy 实现相比,它的训练速度要慢得多。我们正在谈论两倍左右的时间,因此这并不有趣。 话虽如此,与我的 numpy 的解决方案相当快的 pytorch 解决方案也是我可以使用的 - 我只是不知道如何使它更快.. 似乎这是一个 pytorch 问题。
【问题讨论】:
标签: python arrays numpy machine-learning