Skip to content

Commit

Permalink
add Reformer
Browse files Browse the repository at this point in the history
  • Loading branch information
wuhaixu2016 committed Apr 11, 2022
1 parent 93efcd0 commit 0610c4f
Show file tree
Hide file tree
Showing 11 changed files with 589 additions and 1 deletion.
3 changes: 2 additions & 1 deletion exp/exp_main.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from data_provider.data_factory import data_provider
from exp.exp_basic import Exp_Basic
from models import Informer, Autoformer, Transformer
from models import Informer, Autoformer, Transformer, Reformer
from utils.tools import EarlyStopping, adjust_learning_rate, visual
from utils.metrics import metric

Expand Down Expand Up @@ -28,6 +28,7 @@ def _build_model(self):
'Autoformer': Autoformer,
'Transformer': Transformer,
'Informer': Informer,
'Reformer': Reformer,
}
model = model_dict[self.args.model].Model(self.args).float()

Expand Down
31 changes: 31 additions & 0 deletions layers/SelfAttention_Family.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import math
from math import sqrt
from utils.masking import TriangularCausalMask, ProbMask
from reformer_pytorch import LSHSelfAttention
import os


Expand Down Expand Up @@ -164,3 +165,33 @@ def forward(self, queries, keys, values, attn_mask):
out = out.view(B, L, -1)

return self.out_projection(out), attn


class ReformerLayer(nn.Module):
def __init__(self, attention, d_model, n_heads, d_keys=None,
d_values=None, causal=False, bucket_size=4, n_hashes=4):
super().__init__()
self.bucket_size = bucket_size
self.attn = LSHSelfAttention(
dim=d_model,
heads=n_heads,
bucket_size=bucket_size,
n_hashes=n_hashes,
causal=causal
)

def fit_length(self, queries):
# inside reformer: assert N % (bucket_size * 2) == 0
B, N, C = queries.shape
if N % (self.bucket_size * 2) == 0:
return queries
else:
# fill the time series
fill_len = (self.bucket_size * 2) - (N % (self.bucket_size * 2))
return torch.cat([queries, torch.zeros([B, fill_len, C]).to(queries.device)], dim=1)

def forward(self, queries, keys, values, attn_mask):
# in Reformer: defalut queries=keys
B, N, C = queries.shape
queries = self.attn(self.fit_length(queries))[:, :N, :]
return queries, None
57 changes: 57 additions & 0 deletions models/Reformer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import torch
import torch.nn as nn
import torch.nn.functional as F
from layers.Transformer_EncDec import Decoder, DecoderLayer, Encoder, EncoderLayer, ConvLayer
from layers.SelfAttention_Family import ReformerLayer
from layers.Embed import DataEmbedding
import numpy as np


class Model(nn.Module):
"""
Reformer with O(LlogL) complexity
- It is notable that Reformer is not proposed for time series forecasting, in that it cannot accomplish the cross attention.
- Here is only one adaption in BERT-style, other possible implementations can also be acceptable
- The hyper-parameters, such as bucket_size and n_hashes, need to be further tuned.
The official repo of Reformer (https://github.com/lucidrains/reformer-pytorch) can be very helpful, if you have any question.
"""

def __init__(self, configs):
super(Model, self).__init__()
self.pred_len = configs.pred_len
self.pred_len = configs.pred_len
self.output_attention = configs.output_attention

# Embedding
self.enc_embedding = DataEmbedding(configs.enc_in, configs.d_model, configs.embed, configs.freq,
configs.dropout)
# Encoder
self.encoder = Encoder(
[
EncoderLayer(
ReformerLayer(None, configs.d_model, configs.n_heads, bucket_size=configs.bucket_size,
n_hashes=configs.n_hashes),
configs.d_model,
configs.d_ff,
dropout=configs.dropout,
activation=configs.activation
) for l in range(configs.e_layers)
],
norm_layer=torch.nn.LayerNorm(configs.d_model)
)
self.projection = nn.Linear(configs.d_model, configs.c_out, bias=True)

def forward(self, x_enc, x_mark_enc, x_dec, x_mark_dec,
enc_self_mask=None, dec_self_mask=None, dec_enc_mask=None):
# add placeholder
x_enc = torch.cat([x_enc, x_dec[:, -self.pred_len:, :]], dim=1)
x_mark_enc = torch.cat([x_mark_enc, x_mark_dec[:, -self.pred_len:, :]], dim=1)
# Reformer: encoder only
enc_out = self.enc_embedding(x_enc, x_mark_enc)
enc_out, attns = self.encoder(enc_out, attn_mask=enc_self_mask)
enc_out = self.projection(enc_out)

if self.output_attention:
return enc_out[:, -self.pred_len:, :], attns
else:
return enc_out[:, -self.pred_len:, :] # [B, L, D]
6 changes: 6 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
pandas
sklearn
torchvision
numpy
matplotlib
reformer_pytorch
2 changes: 2 additions & 0 deletions run.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
parser.add_argument('--pred_len', type=int, default=96, help='prediction sequence length')

# model define
parser.add_argument('--bucket_size', type=int, default=4, help='for Reformer')
parser.add_argument('--n_hashes', type=int, default=4, help='for Reformer')
parser.add_argument('--enc_in', type=int, default=7, help='encoder input size')
parser.add_argument('--dec_in', type=int, default=7, help='decoder input size')
parser.add_argument('--c_out', type=int, default=7, help='output size')
Expand Down
81 changes: 81 additions & 0 deletions scripts/ECL_script/Reformer.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
export CUDA_VISIBLE_DEVICES=2

python -u run.py \
--is_training 1 \
--root_path ./dataset/electricity/ \
--data_path electricity.csv \
--model_id ECL_96_96 \
--model Reformer \
--data custom \
--features S \
--seq_len 96 \
--label_len 48 \
--pred_len 96 \
--e_layers 2 \
--d_layers 1 \
--factor 3 \
--enc_in 1 \
--dec_in 1 \
--c_out 1 \
--des 'Exp' \
--itr 1

python -u run.py \
--is_training 1 \
--root_path ./dataset/electricity/ \
--data_path electricity.csv \
--model_id ECL_96_192 \
--model Reformer \
--data custom \
--features S \
--seq_len 96 \
--label_len 48 \
--pred_len 192 \
--e_layers 2 \
--d_layers 1 \
--factor 3 \
--enc_in 1 \
--dec_in 1 \
--c_out 1 \
--des 'Exp' \
--itr 1

python -u run.py \
--is_training 1 \
--root_path ./dataset/electricity/ \
--data_path electricity.csv \
--model_id ECL_96_336 \
--model Reformer \
--data custom \
--features S \
--seq_len 96 \
--label_len 48 \
--pred_len 336 \
--e_layers 2 \
--d_layers 1 \
--factor 3 \
--enc_in 1 \
--dec_in 1 \
--c_out 1 \
--des 'Exp' \
--itr 1

python -u run.py \
--is_training 1 \
--root_path ./dataset/electricity/ \
--data_path electricity.csv \
--model_id ECL_96_720 \
--model Reformer \
--data custom \
--features S \
--seq_len 96 \
--label_len 48 \
--pred_len 720 \
--e_layers 2 \
--d_layers 1 \
--factor 3 \
--enc_in 1 \
--dec_in 1 \
--c_out 1 \
--des 'Exp' \
--itr 1
78 changes: 78 additions & 0 deletions scripts/ETT_script/Reformer.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
export CUDA_VISIBLE_DEVICES=0

# multivariate setting of vanilla transformer
python -u run.py \
--is_training 1 \
--root_path ./dataset/ETT-small/ \
--data_path ETTm1.csv \
--model_id ETTm1_96_96 \
--model Reformer \
--data ETTm1 \
--features M \
--seq_len 96 \
--label_len 48 \
--pred_len 96 \
--e_layers 2 \
--d_layers 1 \
--enc_in 7 \
--dec_in 7 \
--c_out 7 \
--des 'Exp' \
--itr 1

python -u run.py \
--is_training 1 \
--root_path ./dataset/ETT-small/ \
--data_path ETTm1.csv \
--model_id ETTm1_96_192 \
--model Reformer \
--data ETTm1 \
--features M \
--seq_len 96 \
--label_len 48 \
--pred_len 192 \
--e_layers 2 \
--d_layers 1 \
--enc_in 7 \
--dec_in 7 \
--c_out 7 \
--des 'Exp' \
--itr 1

python -u run.py \
--is_training 1 \
--root_path ./dataset/ETT-small/ \
--data_path ETTm1.csv \
--model_id ETTm1_96_336 \
--model Reformer \
--data ETTm1 \
--features M \
--seq_len 96 \
--label_len 48 \
--pred_len 336 \
--e_layers 2 \
--d_layers 1 \
--enc_in 7 \
--dec_in 7 \
--c_out 7 \
--des 'Exp' \
--itr 1

python -u run.py \
--is_training 1 \
--root_path ./dataset/ETT-small/ \
--data_path ETTm1.csv \
--model_id ETTm1_96_720 \
--model Reformer \
--data ETTm1 \
--features M \
--seq_len 96 \
--label_len 48 \
--pred_len 720 \
--e_layers 2 \
--d_layers 1 \
--enc_in 7 \
--dec_in 7 \
--c_out 7 \
--des 'Exp' \
--itr 1
83 changes: 83 additions & 0 deletions scripts/Exchange_script/Reformer.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
export CUDA_VISIBLE_DEVICES=4


python -u run.py \
--is_training 1 \
--root_path ./dataset/exchange_rate/ \
--data_path exchange_rate.csv \
--model_id Exchange_96_96 \
--model Reformer \
--data custom \
--features M \
--seq_len 96 \
--label_len 48 \
--pred_len 96 \
--e_layers 2 \
--d_layers 1 \
--factor 3 \
--enc_in 8 \
--dec_in 8 \
--c_out 8 \
--des 'Exp' \
--itr 1

python -u run.py \
--is_training 1 \
--root_path ./dataset/exchange_rate/ \
--data_path exchange_rate.csv \
--model_id Exchange_96_192 \
--model Reformer \
--data custom \
--features M \
--seq_len 96 \
--label_len 48 \
--pred_len 192 \
--e_layers 2 \
--d_layers 1 \
--factor 3 \
--enc_in 8 \
--dec_in 8 \
--c_out 8 \
--des 'Exp' \
--itr 1

python -u run.py \
--is_training 1 \
--root_path ./dataset/exchange_rate/ \
--data_path exchange_rate.csv \
--model_id Exchange_96_336 \
--model Reformer \
--data custom \
--features M \
--seq_len 96 \
--label_len 48 \
--pred_len 336 \
--e_layers 2 \
--d_layers 1 \
--factor 3 \
--enc_in 8 \
--dec_in 8 \
--c_out 8 \
--des 'Exp' \
--itr 1 \
--train_epochs 1

python -u run.py \
--is_training 1 \
--root_path ./dataset/exchange_rate/ \
--data_path exchange_rate.csv \
--model_id Exchange_96_720 \
--model Reformer \
--data custom \
--features M \
--seq_len 96 \
--label_len 48 \
--pred_len 720 \
--e_layers 2 \
--d_layers 1 \
--factor 3 \
--enc_in 8 \
--dec_in 8 \
--c_out 8 \
--des 'Exp' \
--itr 1
Loading

0 comments on commit 0610c4f

Please sign in to comment.