马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
1 猜测-双注意LSTM自动编码器
复现github链接:https://github.com/JulesBelveze/time-series-autoencoder.git
论文:A Dual-Stage Attention-Based Recurrent Neural Network for Time Series Prediction:https://arxiv.org/abs/1704.02971
1.1 复现环境设置
python版本:python3.8.20
cuda版本:cuda111
包版本环境参考:
- Package Version Editable project location
- -------------------- ------------ ---------------------------
- build 1.2.2.post1
- CacheControl 0.14.2
- certifi 2025.1.31
- charset-normalizer 3.4.1
- cleo 2.1.0
- colorama 0.4.6
- contourpy 1.1.1
- crashtest 0.4.1
- cycler 0.10.0
- distlib 0.3.9
- dulwich 0.21.7
- fastjsonschema 2.21.1
- filelock 3.16.1
- fonttools 4.56.0
- future 0.18.2
- idna 3.10
- importlib_metadata 8.5.0
- importlib_resources 6.4.5
- installer 0.7.0
- jaraco.classes 3.4.0
- joblib 0.15.1
- keyring 24.3.1
- kiwisolver 1.2.0
- matplotlib 3.2.1
- more-itertools 10.5.0
- msgpack 1.1.0
- numpy 1.21.0
- packaging 24.2
- pandas 1.1.5
- pexpect 4.9.0
- pillow 10.4.0
- pip 24.3.1
- pkginfo 1.12.1.2
- platformdirs 4.3.6
- poetry 1.8.5
- poetry-core 1.9.1
- poetry-plugin-export 1.8.0
- protobuf 5.29.3
- ptyprocess 0.7.0
- pyparsing 2.4.7
- pyproject_hooks 1.2.0
- python-dateutil 2.8.1
- pytz 2025.1
- pywin32-ctypes 0.2.3
- rapidfuzz 3.9.7
- requests 2.32.3
- requests-toolbelt 1.0.0
- scikit-learn 0.23.1
- scipy 1.4.1
- setuptools 75.3.0
- shellingham 1.5.4
- six 1.15.0
- sklearn 0.0
- tensorboardX 2.6.2.2
- threadpoolctl 2.1.0
- tomli 2.2.1
- tomlkit 0.13.2
- torch 1.9.1+cu111
- torchaudio 0.9.1
- torchvision 0.10.1+cu111
- tqdm 4.46.1
- trove-classifiers 2025.2.18.16
- tsa 0.1.0 D:\temp\Pytorch双注意LSTM自动编码器
- typing_extensions 4.12.2
- urllib3 2.2.3
- virtualenv 20.29.2
- wheel 0.45.1
- zipp 3.20.2
复制代码 注:
vscode设置:
- {
- // Use IntelliSense to learn about possible attributes.
- // Hover to view descriptions of existing attributes.
- // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
- "version": "0.2.0",
- "configurations": [
- {
- "name": "Python Debugger: Current File with Arguments",
- "type": "debugpy",
- "request": "launch",
- "program": "${file}",
- "cwd":"${fileDirname}",
- "console": "integratedTerminal",
- // "args": [
- // "--ckpt", "output/checkpoint-5000.ckpt" // 添加 --ckpt 参数及其值
- // ]
- }
- ]
- }
复制代码 1.2 数据流记载
源代码所用数据字段:
- | 列名 | 含义 | 单位 |
- | ------------- | ------------------ | -------- |
- | Date_Time | 日期和时间 | - |
- | CO(GT) | 一氧化碳浓度 | mg/m³ |
- | PT08.S1(CO) | 一氧化碳传感器响应值 | 无量纲 |
- | NMHC(GT) | 非甲烷烃浓度 | µg/m³ |
- | C6H6(GT) | 苯浓度 | µg/m³ |
- | PT08.S2(NMHC) | 非甲烷烃传感器响应值 | 无量纲 |
- | NOx(GT) | 氮氧化物浓度 | µg/m³ |
- | PT08.S3(NOx) | 氮氧化物传感器响应值 | 无量纲 |
- | NO2(GT) | 二氧化氮浓度 | µg/m³ |
- | PT08.S4(NO2) | 二氧化氮传感器响应值 | 无量纲 |
- | PT08.S5(O3) | 臭氧传感器响应值 | 无量纲 |
- | T | 温度 | °C |
- | RH | 相对湿度 | % |
- | AH | 绝对湿度 | g/m³ |
复制代码 将时间序列数据转换为适合时间序列猜测的格式,详细来说,它通过滑动窗口的方式从输入数据 X 和标签 y 中提取特性和标签,并天生一个 TensorDataset。提取特性和标签,猜测的是后面的猜测窗口长度的标签。下面我将详细表明 X、y 和 target 的取数逻辑,并指出 y 取数可能存在的问题。
1.2.1 构建Dataset
(1) X 的取数
- X 是输入特性数据,形状为 (nb_obs, nb_features),其中 nb_obs 是样本数目,nb_features 是特性数目。
- 通过滑动窗口的方式,从 X 中提取长度为 seq_length 的序列:
- features.append(torch.FloatTensor(X[i:i + self.seq_length, :]).unsqueeze(0))
复制代码
- 比方,假如 seq_length = 10,则每次提取 X[i:i+10, :],即从第 i 个时间步开始的 10 个时间步的特性数据。
- unsqueeze(0) 是为了增加一个批次维度。
(2) y 的取数
- y 是目标值(标签),通常是与 X 对应的输出值。
- 代码中从 y 中提取的是滞后一期的汗青值(y[i-1:i+self.seq_length-1]):
- y_hist.append(torch.FloatTensor(y[i - 1:i + self.seq_length - 1]).unsqueeze(0))
复制代码
- 比方,假如 seq_length = 10,则提取的是 y[i-1:i+9],即从第 i-1 个时间步开始的 10 个时间步的标签值。
- 这里 y[i-1] 的使用可能有问题,因为 y[i-1] 是前一个时间步的值,而不是当前时间步的值。假如 y 是当前时间步的标签,那么这里应该直接使用 y[i:i+self.seq_length]。
(3) target 的取数
- target 是猜测的目标值,即将来 prediction_window 个时间步的标签值:
- target.append(torch.FloatTensor(y[i + self.seq_length:i + self.seq_length + self.prediction_window]))
复制代码
- 比方,假如 seq_length = 10 且 prediction_window = 5,则提取的是 y[i+10:i+15],即从第 i+10 个时间步开始的 5 个时间步的标签值。
1.2.2 举例说明
假设有以下数据:
- X 和 y 的长度为 20。
- seq_length = 3,prediction_window = 2。
(1)X 的取数
- 当 i = 1 时,提取 X[1:4, :]。
- 当 i = 2 时,提取 X[2:5, :]。
- 以此类推。
(2)y 的取数
- 当 i = 1 时,提取 y[0:3](即 y[i-1:i+seq_length-1])。
- 当 i = 2 时,提取 y[1:4]。
- 以此类推。
(3)target 的取数
- 当 i = 1 时,提取 y[4:6](即 y[i+seq_length:i+seq_length+prediction_window])。
- 当 i = 2 时,提取 y[5:7]。
- 以此类推。
1.2.3 y 取数的问题
在代码中,y 的取数逻辑是:
- y_hist.append(torch.FloatTensor(y[i - 1:i + self.seq_length - 1]).unsqueeze(0))
复制代码 这里使用了 y[i-1],即前一个时间步的值。假如 y 是当前时间步的标签,那么这里应该直接使用 y[i:i+self.seq_length],而不是 y[i-1:i+self.seq_length-1]。修正后的代码应该是:
- y_hist.append(torch.FloatTensor(y[i:i + self.seq_length]).unsqueeze(0))
复制代码 修正后的代码
- def frame_series(self, X, y=None): ''' Function used to prepare the data for time series prediction :param X: set of features :param y: targeted value to predict :return: TensorDataset ''' nb_obs, nb_features = X.shape features, target, y_hist = [], [], [] for i in range(1, nb_obs - self.seq_length - self.prediction_window): features.append(torch.FloatTensor(X[i:i + self.seq_length, :]).unsqueeze(0))
- # 修正后的 y 取数逻辑 y_hist.append(torch.FloatTensor(y[i:i + self.seq_length]).unsqueeze(0))
- features_var, y_hist_var = torch.cat(features), torch.cat(y_hist) if y is not None: for i in range(1, nb_obs - self.seq_length - self.prediction_window): target.append( torch.FloatTensor(y[i + self.seq_length:i + self.seq_length + self.prediction_window])) target_var = torch.cat(target) return TensorDataset(features_var, y_hist_var, target_var) return TensorDataset(features_var)
复制代码 1.2.4 总结
- X 的取数是滑动窗口提取特性序列。
- y 的取数逻辑存在问题,不应使用 y[i-1],而应直接使用 y[i:i+self.seq_length]。
- target 的取数是提取将来 prediction_window 个时间步的标签值。
这段代码的数据流可以分为以下几个步调:
- 数据预处置处罚:
- 调用 self.preprocess_data() 方法,天生训练集和测试集的特性和标签:X_train, X_test, y_train, y_test。
- 从 X_train 中获取特性的数目 nb_features。
- 数据集封装:
- 调用 self.frame_series(X_train, y_train) 方法,将训练集的特性和标签封装成一个 train_dataset 对象。
- 调用 self.frame_series(X_test, y_test) 方法,将测试集的特性和标签封装成一个 test_dataset 对象。
- DataLoader 创建:
- 使用 DataLoader 类创建 train_iter,用于加载训练数据集。参数包括 batch_size(批次巨细)、shuffle=False(不打乱数据)、drop_last=True(丢弃末了一个不完整的批次)。
- 使用 DataLoader 类创建 test_iter,用于加载测试数据集。参数与 train_iter 相同。
- 返回效果:
- 返回 train_iter(训练数据加载器)、test_iter(测试数据加载器)和 nb_features(特性数目)。
1.2.5 数据流总结:
- 输入:原始数据通过 self.preprocess_data() 进行预处置处罚,天生特性和标签。
- 处置处罚:特性和标签被封装成 Dataset 对象,然后通过 DataLoader 进行批次加载。
- 输出:返回训练和测试的 DataLoader 对象,以及特性数目。
1.2.6 数据流图示:
- 原始数据 → preprocess_data() → (X_train, X_test, y_train, y_test) → frame_series() → (train_dataset, test_dataset) → DataLoader() → (train_iter, test_iter)
复制代码 1.2.7 参考:
- DataLoader 是 PyTorch 中用于批量加载数据的工具,支持多线程加载、数据打乱等功能。
- Dataset 是 PyTorch 中用于封装数据集的基类,通常需要实现 __len__ 和 __getitem__ 方法。
为了更好地明确数据维度的变化情况,我们可以通过一个详细的例子来渐渐分析代码中的数据维度变化。假设我们有一个时间序列数据集,包罗以下列:
- date: 时间戳
- feature1: 数值特性
- feature2: 数值特性
- category: 种别特性
- target: 目标值
2 数据维度变化流程
- 原始数据 (data):
- 假设数据集有 1000 行,5 列(date, feature1, feature2, category, target)。
- 维度:(1000, 5)
- 预处置处罚 (preprocess_data):
- X = data.drop('target', axis=1):去掉目标列,剩下 4 列。
- y = data['target']:目标列。
- X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.8, shuffle=False):
- X_train 维度:(800, 4)
- X_test 维度:(200, 4)
- y_train 维度:(800,)
- y_test 维度:(200,)
- X_train = preprocessor.fit_transform(X_train):颠末 ColumnTransformer 处置处罚,假设 category 列被编码为 3 个新列。
- 维度:(800, 5)(feature1, feature2, category_encoded_1, category_encoded_2, category_encoded_3)
- X_test = preprocessor.transform(X_test):
- 时间序列帧化 (frame_series):
- 假设 seq_length = 10,prediction_window = 1。
- nb_obs, nb_features = X_train.shape:
- nb_obs = 800, nb_features = 5
- features 和 y_hist 的天生:
- 对于 i 从 1 到 800 - 10 - 1 = 789,每次取 10 个时间步的数据。
- features 维度:(789, 10, 5)
- y_hist 维度:(789, 10)
- target 的天生:
- 对于 i 从 1 到 789,每次取 1 个时间步的目标值。
- target 维度:(789, 1)
- TensorDataset 的天生:
- features_var 维度:(789, 10, 5)
- y_hist_var 维度:(789, 10)
- target_var 维度:(789, 1)
- DataLoader (get_loaders):
- train_iter = DataLoader(train_dataset, batch_size=32, shuffle=False, drop_last=True):
- 每个 batch 的维度:(32, 10, 5)(特性),(32, 10)(汗青目标),(32, 1)(目标)
- test_iter = DataLoader(test_dataset, batch_size=32, shuffle=False, drop_last=True):
- 每个 batch 的维度:(32, 10, 5)(特性),(32, 10)(汗青目标),(32, 1)(目标)
2.1 流程图
- 原始数据 (1000, 5)
- |
- v
- 预处理 (X_train: 800, 5, y_train: 800)
- |
- v
- 时间序列帧化 (features: 789, 10, 5, y_hist: 789, 10, target: 789, 1)
- |
- v
- DataLoader (batch_size=32, features: 32, 10, 5, y_hist: 32, 10, target: 32, 1)
复制代码 2.2 总结
通过上述步调,可以看到数据从原始形式渐渐转换为适合时间序列模型训练的格式。每个步调中的数据维度变化如下:
- 原始数据:(1000, 5)
- 预处置处罚后:(800, 5)(训练集特性),(800,)(训练集目标)
- 时间序列帧化后:(789, 10, 5)(特性),(789, 10)(汗青目标),(789, 1)(目标)
- DataLoader 中:(32, 10, 5)(特性),(32, 10)(汗青目标),(32, 1)(目标)
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |