半亩花草 发表于 2025-3-8 12:18:47

【猜测】-双注意LSTM自动编码器记载

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_resources6.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).unsqueeze(0))


[*]比方,假如 seq_length = 10,则每次提取 X,即从第 i 个时间步开始的 10 个时间步的特性数据。
[*]unsqueeze(0) 是为了增加一个批次维度。

(2) y 的取数



[*]y 是目标值(标签),通常是与 X 对应的输出值。
[*]代码中从 y 中提取的是滞后一期的汗青值(y):y_hist.append(torch.FloatTensor(y).unsqueeze(0))



[*]比方,假如 seq_length = 10,则提取的是 y,即从第 i-1 个时间步开始的 10 个时间步的标签值。
[*]这里 y 的使用可能有问题,因为 y 是前一个时间步的值,而不是当前时间步的值。假如 y 是当前时间步的标签,那么这里应该直接使用 y。

(3) target 的取数



[*]target 是猜测的目标值,即将来 prediction_window 个时间步的标签值:target.append(torch.FloatTensor(y))


[*]比方,假如 seq_length = 10 且 prediction_window = 5,则提取的是 y,即从第 i+10 个时间步开始的 5 个时间步的标签值。

1.2.2 举例说明

假设有以下数据:


[*]X 和 y 的长度为 20。
[*]seq_length = 3,prediction_window = 2。
(1)X 的取数



[*]当 i = 1 时,提取 X。
[*]当 i = 2 时,提取 X。
[*]以此类推。
(2)y 的取数



[*]当 i = 1 时,提取 y(即 y)。
[*]当 i = 2 时,提取 y。
[*]以此类推。
(3)target 的取数



[*]当 i = 1 时,提取 y(即 y)。
[*]当 i = 2 时,提取 y。
[*]以此类推。
1.2.3 y 取数的问题

在代码中,y 的取数逻辑是:
y_hist.append(torch.FloatTensor(y).unsqueeze(0))

这里使用了 y,即前一个时间步的值。假如 y 是当前时间步的标签,那么这里应该直接使用 y,而不是 y。修正后的代码应该是:
y_hist.append(torch.FloatTensor(y).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).unsqueeze(0))
      # 修正后的 y 取数逻辑      y_hist.append(torch.FloatTensor(y).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))      target_var = torch.cat(target)      return TensorDataset(features_var, y_hist_var, target_var)    return TensorDataset(features_var) 1.2.4 总结



[*]X 的取数是滑动窗口提取特性序列。
[*]y 的取数逻辑存在问题,不应使用 y,而应直接使用 y。
[*]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 列。

[*]维度:(1000, 4)

[*]y = data['target']:目标列。

[*]维度:(1000,)

[*]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):

[*]维度:(200, 5)


[*] 时间序列帧化 (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企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 【猜测】-双注意LSTM自动编码器记载