Paper · 2022-02-03 · cs.LG
CoST: Contrastive Learning of Disentangled Seasonal-Trend Representations for Time Series Forecasting
Pretrains a dilated-TCN encoder with two contrastive branches: a MoCo loss on a mixture-of-AR-experts trend branch, and amplitude and phase losses on a learnable Fourier seasonal branch. A ridge regressor forecasts from the frozen features. Author-reported: 21.3% lower average MSE than the best feature-based baseline (TS2Vec) on five multivariate benchmarks.
Time series forecastingContrastive learningSeries decompositionFrequency-domain learningtime-seriesforecastingrepresentation-learningcontrastive-learning
arXivPDFCodeMarkdown21 min read
AI-compiled by claude-haiku-5-5 on 2026-10-24, not yet reviewed by a human. Every claim cites its source; check it when a detail matters.
In plain words
Forecasting a time series, such as electricity load or a weather reading, is usually learned end to end: one network is trained to predict the next values directly. This paper argues for a different order. First learn a compact description of the series, then fit a simple regressor on top of it.
The description has two parts. One captures the slow trend and the other the repeating seasonal pattern. Each part is trained with a contrastive objective, which teaches the network to treat two altered copies of the same series as alike and other series as different. The seasonal part does this in the frequency domain, so the period of the pattern does not have to be known in advance.
Once the features are learned, a ridge regression predicts the future values. The authors report that this beats the best earlier representation method and the end-to-end forecasters they compare with, with the largest gains on the multivariate benchmarks.
TL;DR
- CoST learns a per-timestep representation with a trend branch and a seasonal branch, each trained with a contrastive loss, then fits a ridge regressor on the frozen features §3 §4.1.
- Author-reported: average multivariate MSE 0.590 against 0.750 for TS2Vec (21.3% lower) and 0.972 for the best end-to-end baseline, TCN (39.3% lower) §4.2 tab. 1.
- The code is official (salesforce/CoST, BSD-3-Clause). Several details differ from the paper: projection head, number of trend experts, batch size, augmentations and the inputs of the frequency loss. See Paper vs code.
Problem
End-to-end forecasters learn features and prediction jointly from noisy observations. The paper argues this can pick up spurious correlations, and that the learned features transfer poorly when one component of the data-generating process shifts §1. It models a series as a sum of trend, seasonal and error terms. It argues that trend and seasonal representations are invariant to interventions on the error term, so they should support forecasting better §1 §2.
Two practical costs are named. Choosing an autoregressive lookback window by grid search is too expensive, so the trend branch mixes several windows §3.1. Determining the seasonal period in advance is avoided by a frequency-domain loss §1.
Method
The backbone maps the input series X (length h, m channels) to features
V of shape h x d, with d = 320 §3 §4.1. The backbone is a temporal
convolution network as in TS2Vec: a linear input layer to 64 channels, ten
dilated residual blocks (kernel 3, dilation 2^i, GELU), and a final block to
320 channels app. E. Two feature disentanglers split the output into a trend
part V^(T) and a seasonal part V^(S), each with d/2 = 160 channels. The
two parts are concatenated at the end §3. The paper's equations are unnumbered
in the source, so they are cited by section.
\mathcal{L} = \mathcal{L}_{\mathrm{time}} + \frac{\alpha}{2} \left( \mathcal{L}_{\mathrm{amp}} + \mathcal{L}_{\mathrm{phase}} \right) \quad [§3]
Trend branch (Trend Feature Disentangler). §3.1 fig. 3b
- A mixture of
L+1causal 1-D convolutions. Expertihas kernel size2^iand mapsdchannels tod_T. The paper setsL = floor(log2(h/2))§3.1. - The trend representation is the average of the expert outputs §3.1: V^{(T)} = \frac{1}{L+1} \sum_{i=0}^{L} \mathrm{CausalConv}(\tilde V, 2^i) \quad [§3.1]
- Time-domain loss: MoCo-style InfoNCE. A random time step
tis chosen, a one-layer MLP projection gives the query, and the key comes from a momentum encoder. Negatives come from a queue, with temperaturetau§3.1 §4.1. \mathcal{L}_{\mathrm{time}} = \sum_{i=1}^{N} -\log \frac{\exp(q_i \cdot k_i / \tau)} {\exp(q_i \cdot k_i / \tau) + \sum_{j=1}^{K} \exp(q_i \cdot k_j / \tau)} \quad [§3.1]
Seasonal branch (Seasonal Feature Disentangler). §3.2 fig. 3c
- A discrete Fourier transform over time maps the features to
F = floor(h/2) + 1complex frequency bins §3.2 app. B. - A learnable Fourier layer applies a separate complex affine map to each
frequency, with weights
AinC^{F x d x d_S}and biasBinC^{F x d_S}. It is not translation invariant by design §3.2: V^{(S)}_{i,k} = \mathcal{F}^{-1}\!\left( \sum_{j=1}^{d} A_{i,j,k} \, \mathcal{F}(\tilde V)_{i,j} + B_{i,k} \right) \quad [§3.2] - The inverse DFT returns the seasonal representation to the time domain §3.2.
- Frequency-domain loss. Each complex bin is split into amplitude and phase.
For each bin, the augmented view of a sample is the positive, and the other
N-1samples in the batch are negatives. There is no temperature. Amplitude and phase losses are averaged over bins and samples §3.2: \mathcal{L}_{\mathrm{amp}} = \frac{1}{FN} \sum_{i=1}^{F} \sum_{j=1}^{N} -\log \frac{\exp(|F^{(j)}_{i}| \cdot |F'^{(j)}_{i}|)} {\exp(|F^{(j)}_{i}| \cdot |F'^{(j)}_{i}|) + \sum_{k \neq j}^{N} \exp(|F^{(j)}_{i}| \cdot |F^{(k)}_{i}|)} \quad [§3.2] \mathcal{L}_{\mathrm{phase}} has the same form with the phasephi(F)in place of|F|§3.2.
Augmentations. Scale, shift and jitter, each applied with probability 0.5 and with a Gaussian draw of scale 0.5. The paper treats them as interventions on the error term app. C §2.
Training. Self-supervised training uses the training split only. SGD, initial learning rate 1e-3, momentum 0.9, weight decay 1e-4, cosine annealing, batch size 256. The MoCo queue has 256 entries, momentum 0.999 and temperature 0.07. Training runs 200 iterations for datasets under 100,000 samples and 600 otherwise §4.1.
Evaluation. The encoder is frozen. A ridge regression maps the representation of the last time step to the whole forecast horizon. The ridge penalty is chosen on the validation split from 13 values. Inputs are zero-mean normalised, the split is 60/20/20, and MSE and MAE are reported on the test split §4.1.
The training step, following the paper and the code. Where the code departs from the paper, the code is used and the difference is listed under Paper vs code.
# One CoST training iteration [§3] [app. C] [code: cost.py#L141-L172]
# Input: series (B, T, m), crops of T = 201 in the scripts
# Output: scalar loss
def training_step(series, queue, encoder_q, encoder_k, alpha):
# Two views, each with random scale, shift and jitter [app. C]
view_q = augment(series)
view_k = augment(series)
# Trend and seasonal features, each (B, T, 160) [§3]
trend_q, season_q = encoder_q(view_q)
# Key trend features from the momentum encoder [§3.1] [code: cost.py#L150]
trend_k, _ = encoder_k(view_k)
# Time-domain loss at one random step t [§3.1] [code: cost.py#L143]
t = random_step(T)
query = normalize(head_q(trend_q[:, t]))
key = normalize(head_k(trend_k[:, t]))
loss_time = info_nce(query, key, queue, temperature=0.07)
queue = enqueue(queue, key)
# Seasonal key: second query-encoder pass [code: cost.py#L162]
_, season_k = encoder_q(view_k)
# Frequency view of each seasonal output, (B, F, 160) [§3.2]
freq_q = rfft(normalize(season_q), dim=time)
freq_k = rfft(normalize(season_k), dim=time)
# Contrast amplitudes and phases; other batch items are negatives [§3.2]
loss_amp = contrast(abs(freq_q), abs(freq_k))
loss_phase = contrast(phase(freq_q), phase(freq_k))
# Weighted sum; alpha = 5e-4 in the experiments [§3] [§4.3]
return loss_time + (alpha / 2) * (loss_amp + loss_phase)Inference. The encoder is run on every time step, with a causal window of 201
steps ending at that step, and the last step's trend and seasonal features are
concatenated. The ridge regression then predicts the next pred_len values.
# Frozen-feature forecasting [§4.1] [code: tasks/forecasting.py#L26-L33]
# Input: standardised series (N, T, m), causal window 201
# Output: forecasts (N, T, pred_len * m)
def forecast(series, encoder, ridge, pred_len):
# Left-pad with NaN to 201 steps [code: models/encoder.py#L115-L116]
for t in range(T):
window = pad_nan_left(series[:, max(0, t - 200) : t + 1], 201)
trend, season = encoder(window)
# Last-step features, 320 dims in total [§3] [code: cost.py#L334]
features[:, t] = concat(trend[:, -1], season[:, -1])
# Step t's feature predicts t+1 .. t+pred_len [code: tasks/forecasting.py#L9]
return ridge.predict(features)Hyperparameters
| Name | Value | Where | Notes |
|---|---|---|---|
Representation size d | 320, split 160 trend + 160 seasonal | §3 §4.1 train.py encoder.py | d_T = d_S = d/2 in code |
| Backbone | Linear to 64, 10 dilated blocks, kernel 3, dilation 2^i, GELU, output 320 | app. E encoder.py | same backbone for all TCN-based runs |
| Trend experts | L+1 causal convs, kernel 2^i, L = floor(log2(h/2)) | §3.1 | code default kernels 1 to 128 (8 experts) train.py; see Paper vs code |
Seasonal bins F | floor(h/2) + 1 (101 for h = 201) | §3.2 app. B | fixed by length in the Fourier layer encoder.py |
alpha | 5e-4 | §4.3 | scripts pass 5e-4 train.py |
Time-domain temperature tau | 0.07 | §4.1 | cost.py |
MoCo queue K | 256 | §4.1 | cost.py; batch size must divide K cost.py |
MoCo momentum m | 0.999 | §4.1 | cost.py |
| Frequency-loss temperature | none (raw dot product) | §3.2 | cost.py |
| Augmentation probability | 0.5 for each of scale, shift, jitter | app. C | cost.py |
| Augmentation noise | Gaussian, scale 0.5 | app. C | paper writes N(0, 0.5); code uses std 0.5 cost.py |
| Optimiser | SGD, momentum 0.9, weight decay 1e-4 | §4.1 | cost.py |
| Learning rate | 1e-3, cosine annealing over iterations | §4.1 | cost.py |
| Batch size | 256 | §4.1 | scripts pass 128 ETT_CoST.sh; class default 16 cost.py |
| Iterations | 200 if under 100,000 samples, else 600 | §4.1 | code tests the element count train_data.size cost.py |
| Crop length | 201 | ETT_CoST.sh | train.py default 3000 train.py |
| Seeds | 0 to 4 | ETT_CoST.sh | paper does not say whether tables average seeds |
| Ridge penalties | 0.1, 0.2, 0.5, 1, 2, 5, 10, 20, 50, 100, 200, 500, 1000 | §4.1 _eval_protocols.py | |
| Ridge selection | validation RMSE + MAE | _eval_protocols.py | paper says only "validation set" §4.1 |
| Ridge subsample | 100,000 rows max | _eval_protocols.py | paper silent |
| Split | 60/20/20 by time steps; ETT fixed at 12/4/4 months | §4.1 datautils.py | |
| Normalisation | StandardScaler fit on the training split | §4.1 datautils.py | paper says "zero-mean normalized" |
| Calendar covariates | 7 features: minute, hour, day of week, day, day of year, month, week of year; standardised | datautils.py | not in paper; appended as input channels datautils.py |
| Forecast horizons | 24, 48, 168, 336, 720 (ETTh1, ETTh2, Electricity, Weather); 24, 48, 96, 288, 672 (ETTm1); 28 (M5) | datautils.py | matches tab. 1 |
| Univariate targets | OT (ETT), MT_001 (Electricity), WetBulbCelsius (Weather) | §4.1 datautils.py | M5 uses 28-day horizon tab. 12 |
| Hardware | one NVIDIA A100 | app. F | runtime measurements only |
Results
Author-reported. Setup: five public benchmarks in the multivariate and univariate settings. Representation learners are scored with a ridge regression on top, and end-to-end forecasters are trained with a supervised loss §4.1 §4.2. The tables give MSE / MAE for each cell. Bold marks the best value in the source and is not reproduced. Table numbers follow the source order of the LaTeX.
Headline numbers §4.2 tab. 1
- Multivariate average MSE / MAE: CoST 0.590 / 0.524, TS2Vec 0.750 / 0.607, TCN 0.972 / 0.666.
- Univariate average MSE / MAE: CoST 0.193 / 0.283, TS2Vec 0.203 / 0.298, TCN 0.236 / 0.367 tab. 7.
Table 1: multivariate forecasting, MSE / MAE tab. 1
| Dataset | H | CoST | TS2Vec | TNC | MoCo | Informer | LogTrans | TCN |
|---|---|---|---|---|---|---|---|---|
| ETTh1 | 24 | 0.386 / 0.429 | 0.590 / 0.531 | 0.708 / 0.592 | 0.623 / 0.555 | 0.577 / 0.549 | 0.686 / 0.604 | 0.583 / 0.547 |
| ETTh1 | 48 | 0.437 / 0.464 | 0.624 / 0.555 | 0.749 / 0.619 | 0.669 / 0.586 | 0.685 / 0.625 | 0.766 / 0.757 | 0.670 / 0.606 |
| ETTh1 | 168 | 0.643 / 0.582 | 0.762 / 0.639 | 0.884 / 0.699 | 0.820 / 0.674 | 0.931 / 0.752 | 1.002 / 0.846 | 0.811 / 0.680 |
| ETTh1 | 336 | 0.812 / 0.679 | 0.931 / 0.728 | 1.020 / 0.768 | 0.981 / 0.755 | 1.128 / 0.873 | 1.362 / 0.952 | 1.132 / 0.815 |
| ETTh1 | 720 | 0.970 / 0.771 | 1.063 / 0.799 | 1.157 / 0.830 | 1.138 / 0.831 | 1.215 / 0.896 | 1.397 / 1.291 | 1.165 / 0.813 |
| ETTh2 | 24 | 0.447 / 0.502 | 0.423 / 0.489 | 0.612 / 0.595 | 0.444 / 0.495 | 0.720 / 0.665 | 0.828 / 0.750 | 0.935 / 0.754 |
| ETTh2 | 48 | 0.699 / 0.637 | 0.619 / 0.605 | 0.840 / 0.716 | 0.613 / 0.595 | 1.457 / 1.001 | 1.806 / 1.034 | 1.300 / 0.911 |
| ETTh2 | 168 | 1.549 / 0.982 | 1.845 / 1.074 | 2.359 / 1.213 | 1.791 / 1.034 | 3.489 / 1.515 | 4.070 / 1.681 | 4.017 / 1.579 |
| ETTh2 | 336 | 1.749 / 1.042 | 2.194 / 1.197 | 2.782 / 1.349 | 2.241 / 1.186 | 2.723 / 1.340 | 3.875 / 1.763 | 3.460 / 1.456 |
| ETTh2 | 720 | 1.971 / 1.092 | 2.636 / 1.370 | 2.753 / 1.394 | 2.425 / 1.292 | 3.467 / 1.473 | 3.913 / 1.552 | 3.106 / 1.381 |
| ETTm1 | 24 | 0.246 / 0.329 | 0.453 / 0.444 | 0.522 / 0.472 | 0.458 / 0.444 | 0.323 / 0.369 | 0.419 / 0.412 | 0.363 / 0.397 |
| ETTm1 | 48 | 0.331 / 0.386 | 0.592 / 0.521 | 0.695 / 0.567 | 0.594 / 0.528 | 0.494 / 0.503 | 0.507 / 0.583 | 0.542 / 0.508 |
| ETTm1 | 96 | 0.378 / 0.419 | 0.635 / 0.554 | 0.731 / 0.595 | 0.621 / 0.553 | 0.678 / 0.614 | 0.768 / 0.792 | 0.666 / 0.578 |
| ETTm1 | 288 | 0.472 / 0.486 | 0.693 / 0.597 | 0.818 / 0.649 | 0.700 / 0.606 | 1.056 / 0.786 | 1.462 / 1.320 | 0.991 / 0.735 |
| ETTm1 | 672 | 0.620 / 0.574 | 0.782 / 0.653 | 0.932 / 0.712 | 0.821 / 0.674 | 1.192 / 0.926 | 1.669 / 1.461 | 1.032 / 0.756 |
| Electricity | 24 | 0.136 / 0.242 | 0.287 / 0.375 | 0.354 / 0.423 | 0.288 / 0.374 | 0.312 / 0.387 | 0.297 / 0.374 | 0.235 / 0.346 |
| Electricity | 48 | 0.153 / 0.258 | 0.309 / 0.391 | 0.376 / 0.438 | 0.310 / 0.390 | 0.392 / 0.431 | 0.316 / 0.389 | 0.253 / 0.359 |
| Electricity | 168 | 0.175 / 0.275 | 0.335 / 0.410 | 0.402 / 0.456 | 0.337 / 0.410 | 0.515 / 0.509 | 0.426 / 0.466 | 0.278 / 0.372 |
| Electricity | 336 | 0.196 / 0.296 | 0.351 / 0.422 | 0.417 / 0.466 | 0.353 / 0.422 | 0.759 / 0.625 | 0.365 / 0.417 | 0.287 / 0.382 |
| Electricity | 720 | 0.232 / 0.327 | 0.378 / 0.440 | 0.442 / 0.483 | 0.380 / 0.441 | 0.969 / 0.788 | 0.344 / 0.403 | 0.287 / 0.381 |
| Weather | 24 | 0.298 / 0.360 | 0.307 / 0.363 | 0.320 / 0.373 | 0.311 / 0.365 | 0.335 / 0.381 | 0.435 / 0.477 | 0.321 / 0.367 |
| Weather | 48 | 0.359 / 0.411 | 0.374 / 0.418 | 0.380 / 0.421 | 0.372 / 0.416 | 0.395 / 0.459 | 0.426 / 0.495 | 0.386 / 0.423 |
| Weather | 168 | 0.464 / 0.491 | 0.491 / 0.506 | 0.479 / 0.495 | 0.482 / 0.499 | 0.608 / 0.567 | 0.727 / 0.671 | 0.491 / 0.501 |
| Weather | 336 | 0.497 / 0.517 | 0.525 / 0.530 | 0.505 / 0.514 | 0.516 / 0.523 | 0.702 / 0.620 | 0.754 / 0.670 | 0.502 / 0.507 |
| Weather | 720 | 0.533 / 0.542 | 0.556 / 0.552 | 0.519 / 0.525 | 0.540 / 0.540 | 0.831 / 0.731 | 0.885 / 0.773 | 0.498 / 0.508 |
| Average | 0.590 / 0.524 | 0.750 / 0.607 | 0.870 / 0.655 | 0.753 / 0.608 | 1.038 / 0.735 | 1.180 / 0.837 | 0.972 / 0.666 |
The Informer and LogTrans values are copied from other papers, as noted in app. E. See Pitfalls.
Table 7: univariate forecasting, MSE / MAE tab. 7, appendix G §4.2
| Dataset | H | CoST | TS2Vec | TNC | MoCo | Informer | LogTrans | TCN | TSFresh |
|---|---|---|---|---|---|---|---|---|---|
| ETTh1 | 24 | 0.040 / 0.152 | 0.039 / 0.151 | 0.057 / 0.184 | 0.040 / 0.151 | 0.098 / 0.247 | 0.103 / 0.259 | 0.104 / 0.254 | 0.080 / 0.224 |
| ETTh1 | 48 | 0.060 / 0.186 | 0.062 / 0.189 | 0.094 / 0.239 | 0.063 / 0.191 | 0.158 / 0.319 | 0.167 / 0.328 | 0.206 / 0.366 | 0.092 / 0.242 |
| ETTh1 | 168 | 0.097 / 0.236 | 0.142 / 0.291 | 0.171 / 0.329 | 0.122 / 0.268 | 0.183 / 0.346 | 0.207 / 0.375 | 0.462 / 0.586 | 0.097 / 0.253 |
| ETTh1 | 336 | 0.112 / 0.258 | 0.160 / 0.316 | 0.192 / 0.357 | 0.144 / 0.297 | 0.222 / 0.387 | 0.230 / 0.398 | 0.422 / 0.564 | 0.109 / 0.263 |
| ETTh1 | 720 | 0.148 / 0.306 | 0.179 / 0.345 | 0.235 / 0.408 | 0.183 / 0.347 | 0.269 / 0.435 | 0.273 / 0.463 | 0.438 / 0.578 | 0.142 / 0.302 |
| ETTh2 | 24 | 0.079 / 0.207 | 0.091 / 0.230 | 0.097 / 0.238 | 0.095 / 0.234 | 0.093 / 0.240 | 0.102 / 0.255 | 0.109 / 0.251 | 0.176 / 0.331 |
| ETTh2 | 48 | 0.118 / 0.259 | 0.124 / 0.274 | 0.131 / 0.281 | 0.130 / 0.279 | 0.155 / 0.314 | 0.169 / 0.348 | 0.147 / 0.302 | 0.202 / 0.357 |
| ETTh2 | 168 | 0.189 / 0.339 | 0.198 / 0.355 | 0.197 / 0.354 | 0.204 / 0.360 | 0.232 / 0.389 | 0.246 / 0.422 | 0.209 / 0.366 | 0.273 / 0.420 |
| ETTh2 | 336 | 0.206 / 0.360 | 0.205 / 0.364 | 0.207 / 0.366 | 0.206 / 0.364 | 0.263 / 0.417 | 0.267 / 0.437 | 0.237 / 0.391 | 0.284 / 0.423 |
| ETTh2 | 720 | 0.214 / 0.371 | 0.208 / 0.371 | 0.207 / 0.370 | 0.206 / 0.369 | 0.277 / 0.431 | 0.303 / 0.493 | 0.200 / 0.367 | 0.339 / 0.466 |
| ETTm1 | 24 | 0.015 / 0.088 | 0.016 / 0.093 | 0.019 / 0.103 | 0.015 / 0.091 | 0.030 / 0.137 | 0.065 / 0.202 | 0.027 / 0.127 | 0.027 / 0.128 |
| ETTm1 | 48 | 0.025 / 0.117 | 0.028 / 0.126 | 0.036 / 0.142 | 0.027 / 0.122 | 0.069 / 0.203 | 0.078 / 0.220 | 0.040 / 0.154 | 0.043 / 0.159 |
| ETTm1 | 96 | 0.038 / 0.147 | 0.045 / 0.162 | 0.054 / 0.178 | 0.041 / 0.153 | 0.194 / 0.372 | 0.199 / 0.386 | 0.097 / 0.246 | 0.054 / 0.178 |
| ETTm1 | 288 | 0.077 / 0.209 | 0.095 / 0.235 | 0.098 / 0.244 | 0.083 / 0.219 | 0.401 / 0.554 | 0.411 / 0.572 | 0.305 / 0.455 | 0.098 / 0.245 |
| ETTm1 | 672 | 0.113 / 0.257 | 0.142 / 0.290 | 0.136 / 0.290 | 0.122 / 0.268 | 0.512 / 0.644 | 0.598 / 0.702 | 0.445 / 0.576 | 0.121 / 0.274 |
| Electricity | 24 | 0.243 / 0.264 | 0.260 / 0.288 | 0.252 / 0.278 | 0.254 / 0.280 | 0.251 / 0.275 | 0.528 / 0.447 | 0.243 / 0.367 | - |
| Electricity | 48 | 0.292 / 0.300 | 0.313 / 0.321 | 0.300 / 0.308 | 0.304 / 0.314 | 0.346 / 0.339 | 0.409 / 0.414 | 0.283 / 0.397 | - |
| Electricity | 168 | 0.405 / 0.375 | 0.429 / 0.392 | 0.412 / 0.384 | 0.416 / 0.391 | 0.544 / 0.424 | 0.959 / 0.612 | 0.357 / 0.449 | - |
| Electricity | 336 | 0.560 / 0.473 | 0.565 / 0.478 | 0.548 / 0.466 | 0.556 / 0.482 | 0.713 / 0.512 | 1.079 / 0.639 | 0.355 / 0.446 | - |
| Electricity | 720 | 0.889 / 0.645 | 0.863 / 0.651 | 0.859 / 0.651 | 0.858 / 0.653 | 1.182 / 0.806 | 1.001 / 0.714 | 0.387 / 0.477 | - |
| Weather | 24 | 0.096 / 0.213 | 0.096 / 0.215 | 0.102 / 0.221 | 0.097 / 0.216 | 0.117 / 0.251 | 0.136 / 0.279 | 0.109 / 0.217 | 0.192 / 0.330 |
| Weather | 48 | 0.138 / 0.262 | 0.140 / 0.264 | 0.139 / 0.264 | 0.140 / 0.264 | 0.178 / 0.318 | 0.206 / 0.356 | 0.143 / 0.269 | 0.231 / 0.361 |
| Weather | 168 | 0.207 / 0.334 | 0.207 / 0.335 | 0.198 / 0.328 | 0.198 / 0.326 | 0.266 / 0.398 | 0.309 / 0.439 | 0.188 / 0.319 | 0.298 / 0.415 |
| Weather | 336 | 0.230 / 0.356 | 0.231 / 0.360 | 0.215 / 0.347 | 0.220 / 0.350 | 0.297 / 0.416 | 0.359 / 0.484 | 0.192 / 0.320 | 0.314 / 0.429 |
| Weather | 720 | 0.242 / 0.370 | 0.233 / 0.365 | 0.219 / 0.353 | 0.224 / 0.357 | 0.359 / 0.466 | 0.388 / 0.499 | 0.198 / 0.329 | 0.423 / 0.499 |
| Average | 0.193 / 0.283 | 0.203 / 0.298 | 0.207 / 0.307 | 0.198 / 0.294 | 0.296 / 0.386 | 0.352 / 0.430 | 0.236 / 0.367 | - |
Other multivariate baselines, average MSE / MAE tab. 8 app. H: Triplet 0.969 / 0.732, CPC 0.880 / 0.663, TST 0.893 / 0.671, TCC 1.021 / 0.701. TSFresh (hand-crafted features) has per-dataset numbers in tab. 8 but no average. The per-dataset numbers for all of them are in tab. 8.
Table 2: sensitivity to alpha, ETT tab. 2 §4.3
| alpha | 1E-01 | 5E-02 | 1E-02 | 5E-03 | 1E-03 | 5E-04 | 1E-04 | 5E-05 | 1E-05 |
|---|---|---|---|---|---|---|---|---|---|
| Multivariate MSE | 0.810 | 0.805 | 0.781 | 0.781 | 0.782 | 0.781 | 0.780 | 0.780 | 0.780 |
| Univariate MSE | 0.120 | 0.113 | 0.106 | 0.104 | 0.102 | 0.102 | 0.103 | 0.103 | 0.103 |
| ETTh2 H=168, multivariate MSE | 1.509 | 1.604 | 1.555 | 1.550 | 1.550 | 1.549 | 1.544 | 1.545 | 1.546 |
| ETTh2 H=336, multivariate MSE | 1.524 | 1.646 | 1.722 | 1.731 | 1.744 | 1.749 | 1.759 | 1.762 | 1.765 |
Bold 5E-04 is the value used for all other experiments §4.3.
Table 3: component ablation, ETT averages tab. 3 §4.4
| Variant | Multivariate MSE / MAE | Univariate MSE / MAE |
|---|---|---|
Trend: TFD without MARE (one expert, kernel floor(h/2)) | 0.882 / 0.674 | 0.115 / 0.243 |
| Trend: TFD + MARE (mixture of AR experts) | 0.789 / 0.630 | 0.105 / 0.235 |
| Seasonal: SFD + FDCL | 0.905 / 0.675 | 0.105 / 0.237 |
| Seasonal: SFD + LFL | 0.895 / 0.721 | 0.103 / 0.239 |
| Seasonal: SFD + LFL + FDCL | 0.862 / 0.668 | 0.129 / 0.255 |
| CoST, end-to-end supervised (dagger) | 1.376 / 0.834 | 0.228 / 0.366 |
| CoST, end-to-end plus contrastive (double dagger) | 1.477 / 0.909 | 0.965 / 0.883 |
| MoCo | 0.996 / 0.721 | 0.112 / 0.248 |
| SimCLR | 1.021 / 0.730 | 0.113 / 0.248 |
| CoST (all components) | 0.781 / 0.625 | 0.102 / 0.233 |
Abbreviations used in the table: TFD is the trend branch, MARE the mixture of autoregressive experts inside it, SFD the seasonal branch, LFL the learnable Fourier layer, and FDCL the frequency-domain loss.
Table 4: backbone encoders, ETT averages tab. 4 §4.4
| Backbone | TS2Vec multi MSE / MAE | CoST multi MSE / MAE | TS2Vec uni MSE / MAE | CoST uni MSE / MAE |
|---|---|---|---|---|
| TCN | 0.990 / 0.717 | 0.781 / 0.625 | 0.116 / 0.253 | 0.102 / 0.233 |
| LSTM | 1.415 / 0.903 | 0.928 / 0.706 | 0.544 / 0.596 | 0.148 / 0.301 |
| Transformer | 1.092 / 0.766 | 0.863 / 0.674 | 0.172 / 0.328 | 0.159 / 0.320 |
Table 5: downstream regressors, ETT averages tab. 5 §4.4
| Regressor | TS2Vec multi MSE / MAE | CoST multi MSE / MAE | TS2Vec uni MSE / MAE | CoST uni MSE / MAE |
|---|---|---|---|---|
| Ridge | 0.990 / 0.717 | 0.781 / 0.625 | 0.116 / 0.253 | 0.102 / 0.233 |
| Linear | 1.821 / 0.944 | 1.472 / 0.781 | 0.304 / 0.414 | 0.182 / 0.310 |
| Kernel ridge (RBF) | 1.045 / 0.738 | 0.868 / 0.686 | 0.132 / 0.273 | 0.109 / 0.243 |
Table 12: M5, multivariate, MSE / MAE tab. 12 app. J
| Level | CoST | TS2Vec | TNC | MoCo | Informer | TCN |
|---|---|---|---|---|---|---|
| L1 | 0.063 / 0.211 | 0.299 / 0.446 | 0.671 / 0.627 | 0.279 / 0.415 | 0.836 / 0.724 | 1.395 / 1.020 |
| L2 | 0.154 / 0.311 | 0.383 / 0.498 | 0.521 / 0.564 | 0.360 / 0.482 | 1.436 / 0.991 | 1.310 / 0.932 |
| L3 | 0.191 / 0.340 | 0.591 / 0.549 | 0.621 / 0.582 | 0.438 / 0.496 | 1.747 / 1.033 | 1.847 / 1.048 |
| L4 | 0.149 / 0.293 | 0.291 / 0.403 | 0.393 / 0.482 | 0.304 / 0.408 | 1.023 / 0.829 | 1.388 / 0.992 |
| L5 | 0.260 / 0.390 | 0.419 / 0.484 | 0.506 / 0.545 | 0.462 / 0.508 | 1.514 / 0.899 | 2.039 / 1.172 |
| L6 | 0.255 / 0.386 | 0.500 / 0.528 | 0.586 / 0.589 | 0.478 / 0.510 | 1.099 / 0.822 | 1.309 / 0.925 |
| L7 | 0.394 / 0.482 | 0.630 / 0.600 | 0.648 / 0.618 | 0.641 / 0.605 | 1.565 / 0.931 | 1.475 / 0.953 |
| L8 | 0.328 / 0.442 | 0.589 / 0.559 | 0.614 / 0.584 | 0.610 / 0.575 | 1.969 / 1.063 | 1.691 / 0.990 |
| L9 | 0.702 / 0.582 | 2.150 / 0.748 | 1.445 / 0.726 | 1.293 / 0.701 | 4.923 / 1.313 | 4.634 / 1.332 |
| L10 | 1.471 / 0.783 | 1.677 / 0.812 | 1.679 / 0.830 | 1.604 / 0.815 | 2.474 / 0.977 | 2.476 / 1.025 |
| Average | 0.397 / 0.422 | 0.753 / 0.563 | 0.769 / 0.615 | 0.647 / 0.551 | 1.859 / 0.958 | 1.957 / 1.039 |
Table 6: runtime in seconds, training and inference tab. 6 app. F. For
representation methods, A + B is encoder time plus ridge time. The source
repeats the CoST and TS2Vec training times for every horizon.
| Phase | H | CoST | TS2Vec | TNC | MoCo | Informer | TCN |
|---|---|---|---|---|---|---|---|
| Training | 24 | 262.78 + 7.19 | 91.9 + 5.45 | 1801.58 + 4.78 | 31.3 + 6.57 | 331.32 | 108.36 |
| Training | 48 | 262.78 + 8.41 | 91.9 + 6.44 | 1801.58 + 5.79 | 31.3 + 8.03 | 167.18 | 109.30 |
| Training | 96 | 262.78 + 10.0 | 91.9 + 8.13 | 1801.58 + 7.23 | 31.3 + 9.40 | 325.51 | 110.02 |
| Training | 288 | 262.78 + 19.9 | 91.9 + 16.47 | 1801.58 + 14.51 | 31.3 + 17.83 | 449.86 | 112.08 |
| Training | 672 | 262.78 + 38.3 | 91.9 + 32.22 | 1801.58 + 28.21 | 31.3 + 36.63 | 587.25 | 112.87 |
| Inference | 24 | 23.60 + 0.04 | 3.73 + 0.05 | 3.38 + 0.05 | 3.67 + 0.07 | 10.32 | 3.20 |
| Inference | 48 | 23.60 + 0.07 | 3.73 + 0.06 | 3.38 + 0.09 | 3.67 + 0.08 | 5.78 | 3.67 |
| Inference | 96 | 23.60 + 0.11 | 3.73 + 0.08 | 3.38 + 0.09 | 3.67 + 0.10 | 11.32 | 4.78 |
| Inference | 288 | 23.60 + 0.24 | 3.73 + 0.18 | 3.38 + 0.21 | 3.67 + 0.22 | 17.19 | 7.19 |
| Inference | 672 | 23.60 + 0.34 | 3.73 + 0.30 | 3.38 + 0.33 | 3.67 + 0.33 | 25.62 | 11.93 |
The paper attributes CoST's extra time over TS2Vec to running the trend experts one after another, and says parallel methods could speed this up app. F.
Paper vs code
The official repository is salesforce/CoST at commit
7bb5271c2b66cd5a1d634c27f5df308f190b50ec. The paper's Method and
Implementation sections and the code differ in the following places. Each
difference is listed with both citations.
- Projection head. The paper says the head is a one-layer MLP §3.1. The code builds two linear layers with a ReLU between them cost.py.
- Number of trend experts. The paper sets
L = floor(log2(h/2))§3.1. Forh = 201that gives kernels up to 64. The scripts use kernels 1 to 128, which is 8 experts ETT_CoST.sh train.py. The paper does not give thehused in its experiments. - Batch size. The paper says 256 §4.1. The scripts pass 128 ETT_CoST.sh. The class default is 16 cost.py.
- Iteration rule. The paper says "fewer than 100,000 samples" §4.1. The code tests
train_data.size, the total number of elements cost.py. - Scale and shift augmentation. The paper defines scale as
x * epsilonand shift asx + epsilon, each with a single random scalar app. C. The code draws one value per channel for both, and scales by1 + epsiloncost.py. - Frequency-loss input. The paper computes amplitude and phase on the pre-inverse-FFT complex output
F§3.2. The code takes the FFT of the time-domain seasonal output, after L2 normalisation over channels and training-time dropout cost.py encoder.py. - Frequency-loss negatives. The paper uses the other
N-1original samples as negatives §3.2. The code uses all other2B-1items, including the other augmented view cost.py. - Seasonal key. The paper does not say which encoder produces the seasonal key. The code runs the query encoder a second time on the second view, with gradients cost.py.
- Random time step. The paper picks a random time step §3.1. The code draws one index per iteration, shared by the whole batch cost.py.
- Phase and amplitude numerics. The code adds
1e-6to the real part beforeatan2, and to both parts in the amplitude cost.py. The paper's formulas have no epsilon. - Seasonal dropout. The code applies dropout with probability 0.1 to the seasonal output during training encoder.py encoder.py. The paper does not mention it.
- Encoder masking. The encoder can apply a binomial input mask in training encoder.py. CoST's calls use the default
mask='all_true', so the mask is not applied cost.py. - Ridge model selection. The paper says the validation set picks the penalty §4.1. The code chooses by RMSE plus MAE on validation _eval_protocols.py. It also caps the ridge training set at 100,000 rows _eval_protocols.py.
- Evaluation windows. The paper uses the representation of the final step §3. The code evaluates every step on a causal 201-step window with NaN left-padding forecasting.py cost.py.
- Calendar covariates. The code appends seven calendar features as input channels for CSV datasets, and drops them from the targets at evaluation datautils.py forecasting.py. The paper does not mention them.
- Normalisation. The paper says "zero-mean normalized" §4.1. The code uses a StandardScaler fit on the training split datautils.py.
- Reported metric scale. The paper does not say whether its tables use the normalised or the raw scale. The code computes both forecasting.py.
- Seeds. The paper does not say whether it averages seeds §4.1. The scripts run seeds 0 to 4 ETT_CoST.sh.
- Data preparation. The Electricity, Weather and M5 data are not in the repository. They must be downloaded and prepared with the scripts described in the README.
Pitfalls
- Effective lookback is 201 steps, not
h. At inference each step sees the 201 steps ending at it, with NaN padding on the left forecasting.py. The seasonal layer is built for 201 steps: its weights cover 101 frequency bins encoder.py. Longer inputs are only written into the first 101 bins, so the rest of the spectrum is zero encoder.py. Keep the window at 201 or re-derive the bin count. - Frequency loss scale. The paper says the frequency loss is about three
orders of magnitude larger than the time-domain loss. That is why
alphais small, and the paper says a smallalphadoes not mean seasonality matters less §4.3. - Larger
alphahelps some ETTh2 horizons. At ETTh2 horizons 168 and 336, the largest value tested (0.1) gives the lowest multivariate MSE. The paper uses5E-04for all other experiments tab. 2 §4.3. - MoCo batch size must divide the queue. The code asserts
K % batch_size == 0withK = 256cost.py. Batch sizes such as 100 fail. - Numbers are author-reported and partly copied. TS2Vec, TNC, MoCo, Triplet, CPC, TST and TCC are reproduced by the authors. Informer and LogTrans are copied from TS2Vec and Informer app. E. TS2Vec was run with its default settings app. E. The settings used for the other reproduced baselines are listed in app. E.
- Table averages do not fully recompute. The paper gives a 4.71% univariate gain over the best feature-based baseline §4.2. The rounded averages in tab. 7 give about 4.9% (0.193 against 0.203). Use the paper's text values when comparing with it.
- Source and metadata differ. The LaTeX source is the ICLR 2022 camera-ready. The arXiv metadata's abstract omits the phrase "long sequence". The numbers in this card come from the source.
- Old NumPy calls.
datautils.pyusesnp.floatdatautils.py, which NumPy 1.24 and later reject. Replace it withfloatbefore running. - Runtime is A100-specific. Runtime numbers come from one A100 app. F. The paper gives no other hardware.
Lineage
- Builds on: MoCo for the time-domain loss §3.1; the TS2Vec backbone and evaluation protocol §4.1 app. E; structural time-series models for the trend and seasonal decomposition §2.
- Compared against: TS2Vec, TNC, MoCo, Triplet, CPC, TST, TCC, TSFresh for representation learning; Informer, LogTrans, LSTNet and TCN for end-to-end forecasting §4.2 app. E.
- Superseded by: not stated in the content on this wiki.
Source and license
Adapted from “CoST: Contrastive Learning of Disentangled Seasonal-Trend Representations for Time Series Forecasting” by Gerald Woo, Chenghao Liu, Doyen Sahoo, Akshat Kumar, Steven Hoi (arXiv:2202.01575), used under CC BY 4.0. Changes: condensed and restructured for implementation, with tables, equations and algorithms taken from the paper and its code, each cited to its source. Not affiliated with or endorsed by the authors. Code citations refer to https://github.com/salesforce/CoST at commit 7bb5271c2b66 (BSD-3-Clause). Any quoted code is shown under that license.