0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Autoformer のイラスト (+ トイモデル実装)

0
Last updated at Posted at 2026-04-09

イラスト集: Transformer | Autoformer (この記事) | PatchTST | iTransformer

Transformer を時系列予測向けに改修した恰好をしている Autoformer (Haixu Wu et al., NeurIPS 2021) のイラストを描きました。処理に漏れや誤りがあったらご指摘ください。

2026-04-23 イラストに諸々の誤りがあったので修正しました。
2026-04-10 イラストにテキスト追加・レイアウト修正をしました。

SVG 版はこちらです。この SVG の掲載記事はこちらです (イラストの元のメモがあります)。

autoformer.png

 

参考文献

イラスト内のグレーのボックスと同じ内容です。

補足

  • Time Feature Extraction はタイムスタンプから「1年のうち何日目」「1ヶ月のうち何日目」…を抽出する操作であるが、実際には [-0.5, 0.5] に正規化する。「何分」の特徴量は時系列の時間間隔が 1 時間未満の場合のみ。
  • イラストは d_model=6, d_ff=12, n_head=2 として描かれているが、実際にはオリジナル Transformer と同じ d_model=512, d_ff=2048, n_head=8 が採用されている。但し、活性化関数は GELU が採用されている。また、エンコーダ層が2層のみ、デコーダ層が1層のみであることもオリジナル Transformer と異なる。
  • AutoCorrelation 層では rfft → irfft で全ラグの Q-K 相互相関を計算してから、各ステップについてモデル次元方向の mean をとり、値が大きい k ステップに絞る。 この k は floor(c log L) で、係数 c の規定値は 1 なので、イラストのケースでは実際にはエンコーダ側では floor(log 6)=1 ステップ、デコーダ側でも floor(log 7)=1 ステップに絞られるはずだが、常に 1 ステップに絞るものという誤解を招きそうなため、敢えて 2 ステップ残している。

トイモデル実装

以下にトイモデルの実装例を記します。論文リポジトリの 2026/04/09 現在の最新リビジョン (51c7d41) を取得してインポートしただけです。※ 構造確認用に小さいサイズでインスタンス化しているのでトイモデルといっていますが、ハイパーパラメータによって大きいサイズにもできます。

script.py
from models.Autoformer import Model
import types
import torch

def main():
    configs = {
        'seq_len': 8, 'label_len': 4, 'pred_len': 3,
        'embed': 'timeF', 'freq': 'h',
        'moving_avg': 25, 'd_model': 6, 'n_heads': 2,
        'factor': 1, 'd_ff': 12,
        'e_layers': 2, 'enc_in': 5,
        'd_layers': 1, 'dec_in': 5, 'c_out': 5,
        'activation': 'gelu', 'dropout': 0.05,
        'output_attention': False,
    }
    model = Model(types.SimpleNamespace(configs))
    print(model)

    x_enc = torch.randn(1, 8, 5)
    x_dec = torch.zeros(1, 7, 5)
    x_mark_enc = torch.rand(1, 8, 4) - 0.5
    x_mark_dec = torch.rand(1, 7, 4) - 0.5

    with torch.no_grad():
        output = model(
            x_enc,
            x_mark_enc,
            x_dec,
            x_mark_dec,
        )
        assert output.shape == (1, 3, 5)

if __name__ == '__main__':
    main()
出力
Model(
  (decomp): series_decomp(
    (moving_avg): moving_avg(
      (avg): AvgPool1d(kernel_size=(25,), stride=(1,), padding=(0,))
    )
  )
  (enc_embedding): DataEmbedding_wo_pos(
    (value_embedding): TokenEmbedding(
      (tokenConv): Conv1d(5, 6, kernel_size=(3,), stride=(1,), padding=(1,), bias=False, padding_mode=circular)
    )
    (position_embedding): PositionalEmbedding()
    (temporal_embedding): TimeFeatureEmbedding(
      (embed): Linear(in_features=4, out_features=6, bias=False)
    )
    (dropout): Dropout(p=0.05, inplace=False)
  )
  (dec_embedding): DataEmbedding_wo_pos(
    (value_embedding): TokenEmbedding(
      (tokenConv): Conv1d(5, 6, kernel_size=(3,), stride=(1,), padding=(1,), bias=False, padding_mode=circular)
    )
    (position_embedding): PositionalEmbedding()
    (temporal_embedding): TimeFeatureEmbedding(
      (embed): Linear(in_features=4, out_features=6, bias=False)
    )
    (dropout): Dropout(p=0.05, inplace=False)
  )
  (encoder): Encoder(
    (attn_layers): ModuleList(
      (0-1): 2 x EncoderLayer(
        (attention): AutoCorrelationLayer(
          (inner_correlation): AutoCorrelation(
            (dropout): Dropout(p=0.05, inplace=False)
          )
          (query_projection): Linear(in_features=6, out_features=6, bias=True)
          (key_projection): Linear(in_features=6, out_features=6, bias=True)
          (value_projection): Linear(in_features=6, out_features=6, bias=True)
          (out_projection): Linear(in_features=6, out_features=6, bias=True)
        )
        (conv1): Conv1d(6, 12, kernel_size=(1,), stride=(1,), bias=False)
        (conv2): Conv1d(12, 6, kernel_size=(1,), stride=(1,), bias=False)
        (decomp1): series_decomp(
          (moving_avg): moving_avg(
            (avg): AvgPool1d(kernel_size=(25,), stride=(1,), padding=(0,))
          )
        )
        (decomp2): series_decomp(
          (moving_avg): moving_avg(
            (avg): AvgPool1d(kernel_size=(25,), stride=(1,), padding=(0,))
          )
        )
        (dropout): Dropout(p=0.05, inplace=False)
      )
    )
    (norm): my_Layernorm(
      (layernorm): LayerNorm((6,), eps=1e-05, elementwise_affine=True)
    )
  )
  (decoder): Decoder(
    (layers): ModuleList(
      (0): DecoderLayer(
        (self_attention): AutoCorrelationLayer(
          (inner_correlation): AutoCorrelation(
            (dropout): Dropout(p=0.05, inplace=False)
          )
          (query_projection): Linear(in_features=6, out_features=6, bias=True)
          (key_projection): Linear(in_features=6, out_features=6, bias=True)
          (value_projection): Linear(in_features=6, out_features=6, bias=True)
          (out_projection): Linear(in_features=6, out_features=6, bias=True)
        )
        (cross_attention): AutoCorrelationLayer(
          (inner_correlation): AutoCorrelation(
            (dropout): Dropout(p=0.05, inplace=False)
          )
          (query_projection): Linear(in_features=6, out_features=6, bias=True)
          (key_projection): Linear(in_features=6, out_features=6, bias=True)
          (value_projection): Linear(in_features=6, out_features=6, bias=True)
          (out_projection): Linear(in_features=6, out_features=6, bias=True)
        )
        (conv1): Conv1d(6, 12, kernel_size=(1,), stride=(1,), bias=False)
        (conv2): Conv1d(12, 6, kernel_size=(1,), stride=(1,), bias=False)
        (decomp1): series_decomp(
          (moving_avg): moving_avg(
            (avg): AvgPool1d(kernel_size=(25,), stride=(1,), padding=(0,))
          )
        )
        (decomp2): series_decomp(
          (moving_avg): moving_avg(
            (avg): AvgPool1d(kernel_size=(25,), stride=(1,), padding=(0,))
          )
        )
        (decomp3): series_decomp(
          (moving_avg): moving_avg(
            (avg): AvgPool1d(kernel_size=(25,), stride=(1,), padding=(0,))
          )
        )
        (dropout): Dropout(p=0.05, inplace=False)
        (projection): Conv1d(6, 5, kernel_size=(3,), stride=(1,), padding=(1,), bias=False, padding_mode=circular)
      )
    )
    (norm): my_Layernorm(
      (layernorm): LayerNorm((6,), eps=1e-05, elementwise_affine=True)
    )
    (projection): Linear(in_features=6, out_features=5, bias=True)
  )
)
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?