wikillm

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

  1. A mixture of L+1 causal 1-D convolutions. Expert i has kernel size 2^i and maps d channels to d_T. The paper sets L = floor(log2(h/2)) §3.1.
  2. 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]
  3. Time-domain loss: MoCo-style InfoNCE. A random time step t is chosen, a one-layer MLP projection gives the query, and the key comes from a momentum encoder. Negatives come from a queue, with temperature tau §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

  1. A discrete Fourier transform over time maps the features to F = floor(h/2) + 1 complex frequency bins §3.2 app. B.
  2. A learnable Fourier layer applies a separate complex affine map to each frequency, with weights A in C^{F x d x d_S} and bias B in C^{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]
  3. The inverse DFT returns the seasonal representation to the time domain §3.2.
  4. 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-1 samples 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 phase phi(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.

Pseudocode
# 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.

Pseudocode
# 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

NameValueWhereNotes
Representation size d320, split 160 trend + 160 seasonal§3 §4.1 train.py encoder.pyd_T = d_S = d/2 in code
BackboneLinear to 64, 10 dilated blocks, kernel 3, dilation 2^i, GELU, output 320app. E encoder.pysame backbone for all TCN-based runs
Trend expertsL+1 causal convs, kernel 2^i, L = floor(log2(h/2))§3.1code default kernels 1 to 128 (8 experts) train.py; see Paper vs code
Seasonal bins Ffloor(h/2) + 1 (101 for h = 201)§3.2 app. Bfixed by length in the Fourier layer encoder.py
alpha5e-4§4.3scripts pass 5e-4 train.py
Time-domain temperature tau0.07§4.1cost.py
MoCo queue K256§4.1cost.py; batch size must divide K cost.py
MoCo momentum m0.999§4.1cost.py
Frequency-loss temperaturenone (raw dot product)§3.2cost.py
Augmentation probability0.5 for each of scale, shift, jitterapp. Ccost.py
Augmentation noiseGaussian, scale 0.5app. Cpaper writes N(0, 0.5); code uses std 0.5 cost.py
OptimiserSGD, momentum 0.9, weight decay 1e-4§4.1cost.py
Learning rate1e-3, cosine annealing over iterations§4.1cost.py
Batch size256§4.1scripts pass 128 ETT_CoST.sh; class default 16 cost.py
Iterations200 if under 100,000 samples, else 600§4.1code tests the element count train_data.size cost.py
Crop length201ETT_CoST.shtrain.py default 3000 train.py
Seeds0 to 4ETT_CoST.shpaper does not say whether tables average seeds
Ridge penalties0.1, 0.2, 0.5, 1, 2, 5, 10, 20, 50, 100, 200, 500, 1000§4.1 _eval_protocols.py
Ridge selectionvalidation RMSE + MAE_eval_protocols.pypaper says only "validation set" §4.1
Ridge subsample100,000 rows max_eval_protocols.pypaper silent
Split60/20/20 by time steps; ETT fixed at 12/4/4 months§4.1 datautils.py
NormalisationStandardScaler fit on the training split§4.1 datautils.pypaper says "zero-mean normalized"
Calendar covariates7 features: minute, hour, day of week, day, day of year, month, week of year; standardiseddatautils.pynot in paper; appended as input channels datautils.py
Forecast horizons24, 48, 168, 336, 720 (ETTh1, ETTh2, Electricity, Weather); 24, 48, 96, 288, 672 (ETTm1); 28 (M5)datautils.pymatches tab. 1
Univariate targetsOT (ETT), MT_001 (Electricity), WetBulbCelsius (Weather)§4.1 datautils.pyM5 uses 28-day horizon tab. 12
Hardwareone NVIDIA A100app. Fruntime 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

DatasetHCoSTTS2VecTNCMoCoInformerLogTransTCN
ETTh1240.386 / 0.4290.590 / 0.5310.708 / 0.5920.623 / 0.5550.577 / 0.5490.686 / 0.6040.583 / 0.547
ETTh1480.437 / 0.4640.624 / 0.5550.749 / 0.6190.669 / 0.5860.685 / 0.6250.766 / 0.7570.670 / 0.606
ETTh11680.643 / 0.5820.762 / 0.6390.884 / 0.6990.820 / 0.6740.931 / 0.7521.002 / 0.8460.811 / 0.680
ETTh13360.812 / 0.6790.931 / 0.7281.020 / 0.7680.981 / 0.7551.128 / 0.8731.362 / 0.9521.132 / 0.815
ETTh17200.970 / 0.7711.063 / 0.7991.157 / 0.8301.138 / 0.8311.215 / 0.8961.397 / 1.2911.165 / 0.813
ETTh2240.447 / 0.5020.423 / 0.4890.612 / 0.5950.444 / 0.4950.720 / 0.6650.828 / 0.7500.935 / 0.754
ETTh2480.699 / 0.6370.619 / 0.6050.840 / 0.7160.613 / 0.5951.457 / 1.0011.806 / 1.0341.300 / 0.911
ETTh21681.549 / 0.9821.845 / 1.0742.359 / 1.2131.791 / 1.0343.489 / 1.5154.070 / 1.6814.017 / 1.579
ETTh23361.749 / 1.0422.194 / 1.1972.782 / 1.3492.241 / 1.1862.723 / 1.3403.875 / 1.7633.460 / 1.456
ETTh27201.971 / 1.0922.636 / 1.3702.753 / 1.3942.425 / 1.2923.467 / 1.4733.913 / 1.5523.106 / 1.381
ETTm1240.246 / 0.3290.453 / 0.4440.522 / 0.4720.458 / 0.4440.323 / 0.3690.419 / 0.4120.363 / 0.397
ETTm1480.331 / 0.3860.592 / 0.5210.695 / 0.5670.594 / 0.5280.494 / 0.5030.507 / 0.5830.542 / 0.508
ETTm1960.378 / 0.4190.635 / 0.5540.731 / 0.5950.621 / 0.5530.678 / 0.6140.768 / 0.7920.666 / 0.578
ETTm12880.472 / 0.4860.693 / 0.5970.818 / 0.6490.700 / 0.6061.056 / 0.7861.462 / 1.3200.991 / 0.735
ETTm16720.620 / 0.5740.782 / 0.6530.932 / 0.7120.821 / 0.6741.192 / 0.9261.669 / 1.4611.032 / 0.756
Electricity240.136 / 0.2420.287 / 0.3750.354 / 0.4230.288 / 0.3740.312 / 0.3870.297 / 0.3740.235 / 0.346
Electricity480.153 / 0.2580.309 / 0.3910.376 / 0.4380.310 / 0.3900.392 / 0.4310.316 / 0.3890.253 / 0.359
Electricity1680.175 / 0.2750.335 / 0.4100.402 / 0.4560.337 / 0.4100.515 / 0.5090.426 / 0.4660.278 / 0.372
Electricity3360.196 / 0.2960.351 / 0.4220.417 / 0.4660.353 / 0.4220.759 / 0.6250.365 / 0.4170.287 / 0.382
Electricity7200.232 / 0.3270.378 / 0.4400.442 / 0.4830.380 / 0.4410.969 / 0.7880.344 / 0.4030.287 / 0.381
Weather240.298 / 0.3600.307 / 0.3630.320 / 0.3730.311 / 0.3650.335 / 0.3810.435 / 0.4770.321 / 0.367
Weather480.359 / 0.4110.374 / 0.4180.380 / 0.4210.372 / 0.4160.395 / 0.4590.426 / 0.4950.386 / 0.423
Weather1680.464 / 0.4910.491 / 0.5060.479 / 0.4950.482 / 0.4990.608 / 0.5670.727 / 0.6710.491 / 0.501
Weather3360.497 / 0.5170.525 / 0.5300.505 / 0.5140.516 / 0.5230.702 / 0.6200.754 / 0.6700.502 / 0.507
Weather7200.533 / 0.5420.556 / 0.5520.519 / 0.5250.540 / 0.5400.831 / 0.7310.885 / 0.7730.498 / 0.508
Average0.590 / 0.5240.750 / 0.6070.870 / 0.6550.753 / 0.6081.038 / 0.7351.180 / 0.8370.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

DatasetHCoSTTS2VecTNCMoCoInformerLogTransTCNTSFresh
ETTh1240.040 / 0.1520.039 / 0.1510.057 / 0.1840.040 / 0.1510.098 / 0.2470.103 / 0.2590.104 / 0.2540.080 / 0.224
ETTh1480.060 / 0.1860.062 / 0.1890.094 / 0.2390.063 / 0.1910.158 / 0.3190.167 / 0.3280.206 / 0.3660.092 / 0.242
ETTh11680.097 / 0.2360.142 / 0.2910.171 / 0.3290.122 / 0.2680.183 / 0.3460.207 / 0.3750.462 / 0.5860.097 / 0.253
ETTh13360.112 / 0.2580.160 / 0.3160.192 / 0.3570.144 / 0.2970.222 / 0.3870.230 / 0.3980.422 / 0.5640.109 / 0.263
ETTh17200.148 / 0.3060.179 / 0.3450.235 / 0.4080.183 / 0.3470.269 / 0.4350.273 / 0.4630.438 / 0.5780.142 / 0.302
ETTh2240.079 / 0.2070.091 / 0.2300.097 / 0.2380.095 / 0.2340.093 / 0.2400.102 / 0.2550.109 / 0.2510.176 / 0.331
ETTh2480.118 / 0.2590.124 / 0.2740.131 / 0.2810.130 / 0.2790.155 / 0.3140.169 / 0.3480.147 / 0.3020.202 / 0.357
ETTh21680.189 / 0.3390.198 / 0.3550.197 / 0.3540.204 / 0.3600.232 / 0.3890.246 / 0.4220.209 / 0.3660.273 / 0.420
ETTh23360.206 / 0.3600.205 / 0.3640.207 / 0.3660.206 / 0.3640.263 / 0.4170.267 / 0.4370.237 / 0.3910.284 / 0.423
ETTh27200.214 / 0.3710.208 / 0.3710.207 / 0.3700.206 / 0.3690.277 / 0.4310.303 / 0.4930.200 / 0.3670.339 / 0.466
ETTm1240.015 / 0.0880.016 / 0.0930.019 / 0.1030.015 / 0.0910.030 / 0.1370.065 / 0.2020.027 / 0.1270.027 / 0.128
ETTm1480.025 / 0.1170.028 / 0.1260.036 / 0.1420.027 / 0.1220.069 / 0.2030.078 / 0.2200.040 / 0.1540.043 / 0.159
ETTm1960.038 / 0.1470.045 / 0.1620.054 / 0.1780.041 / 0.1530.194 / 0.3720.199 / 0.3860.097 / 0.2460.054 / 0.178
ETTm12880.077 / 0.2090.095 / 0.2350.098 / 0.2440.083 / 0.2190.401 / 0.5540.411 / 0.5720.305 / 0.4550.098 / 0.245
ETTm16720.113 / 0.2570.142 / 0.2900.136 / 0.2900.122 / 0.2680.512 / 0.6440.598 / 0.7020.445 / 0.5760.121 / 0.274
Electricity240.243 / 0.2640.260 / 0.2880.252 / 0.2780.254 / 0.2800.251 / 0.2750.528 / 0.4470.243 / 0.367-
Electricity480.292 / 0.3000.313 / 0.3210.300 / 0.3080.304 / 0.3140.346 / 0.3390.409 / 0.4140.283 / 0.397-
Electricity1680.405 / 0.3750.429 / 0.3920.412 / 0.3840.416 / 0.3910.544 / 0.4240.959 / 0.6120.357 / 0.449-
Electricity3360.560 / 0.4730.565 / 0.4780.548 / 0.4660.556 / 0.4820.713 / 0.5121.079 / 0.6390.355 / 0.446-
Electricity7200.889 / 0.6450.863 / 0.6510.859 / 0.6510.858 / 0.6531.182 / 0.8061.001 / 0.7140.387 / 0.477-
Weather240.096 / 0.2130.096 / 0.2150.102 / 0.2210.097 / 0.2160.117 / 0.2510.136 / 0.2790.109 / 0.2170.192 / 0.330
Weather480.138 / 0.2620.140 / 0.2640.139 / 0.2640.140 / 0.2640.178 / 0.3180.206 / 0.3560.143 / 0.2690.231 / 0.361
Weather1680.207 / 0.3340.207 / 0.3350.198 / 0.3280.198 / 0.3260.266 / 0.3980.309 / 0.4390.188 / 0.3190.298 / 0.415
Weather3360.230 / 0.3560.231 / 0.3600.215 / 0.3470.220 / 0.3500.297 / 0.4160.359 / 0.4840.192 / 0.3200.314 / 0.429
Weather7200.242 / 0.3700.233 / 0.3650.219 / 0.3530.224 / 0.3570.359 / 0.4660.388 / 0.4990.198 / 0.3290.423 / 0.499
Average0.193 / 0.2830.203 / 0.2980.207 / 0.3070.198 / 0.2940.296 / 0.3860.352 / 0.4300.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

alpha1E-015E-021E-025E-031E-035E-041E-045E-051E-05
Multivariate MSE0.8100.8050.7810.7810.7820.7810.7800.7800.780
Univariate MSE0.1200.1130.1060.1040.1020.1020.1030.1030.103
ETTh2 H=168, multivariate MSE1.5091.6041.5551.5501.5501.5491.5441.5451.546
ETTh2 H=336, multivariate MSE1.5241.6461.7221.7311.7441.7491.7591.7621.765

Bold 5E-04 is the value used for all other experiments §4.3.

Table 3: component ablation, ETT averages tab. 3 §4.4

VariantMultivariate MSE / MAEUnivariate MSE / MAE
Trend: TFD without MARE (one expert, kernel floor(h/2))0.882 / 0.6740.115 / 0.243
Trend: TFD + MARE (mixture of AR experts)0.789 / 0.6300.105 / 0.235
Seasonal: SFD + FDCL0.905 / 0.6750.105 / 0.237
Seasonal: SFD + LFL0.895 / 0.7210.103 / 0.239
Seasonal: SFD + LFL + FDCL0.862 / 0.6680.129 / 0.255
CoST, end-to-end supervised (dagger)1.376 / 0.8340.228 / 0.366
CoST, end-to-end plus contrastive (double dagger)1.477 / 0.9090.965 / 0.883
MoCo0.996 / 0.7210.112 / 0.248
SimCLR1.021 / 0.7300.113 / 0.248
CoST (all components)0.781 / 0.6250.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

BackboneTS2Vec multi MSE / MAECoST multi MSE / MAETS2Vec uni MSE / MAECoST uni MSE / MAE
TCN0.990 / 0.7170.781 / 0.6250.116 / 0.2530.102 / 0.233
LSTM1.415 / 0.9030.928 / 0.7060.544 / 0.5960.148 / 0.301
Transformer1.092 / 0.7660.863 / 0.6740.172 / 0.3280.159 / 0.320

Table 5: downstream regressors, ETT averages tab. 5 §4.4

RegressorTS2Vec multi MSE / MAECoST multi MSE / MAETS2Vec uni MSE / MAECoST uni MSE / MAE
Ridge0.990 / 0.7170.781 / 0.6250.116 / 0.2530.102 / 0.233
Linear1.821 / 0.9441.472 / 0.7810.304 / 0.4140.182 / 0.310
Kernel ridge (RBF)1.045 / 0.7380.868 / 0.6860.132 / 0.2730.109 / 0.243

Table 12: M5, multivariate, MSE / MAE tab. 12 app. J

LevelCoSTTS2VecTNCMoCoInformerTCN
L10.063 / 0.2110.299 / 0.4460.671 / 0.6270.279 / 0.4150.836 / 0.7241.395 / 1.020
L20.154 / 0.3110.383 / 0.4980.521 / 0.5640.360 / 0.4821.436 / 0.9911.310 / 0.932
L30.191 / 0.3400.591 / 0.5490.621 / 0.5820.438 / 0.4961.747 / 1.0331.847 / 1.048
L40.149 / 0.2930.291 / 0.4030.393 / 0.4820.304 / 0.4081.023 / 0.8291.388 / 0.992
L50.260 / 0.3900.419 / 0.4840.506 / 0.5450.462 / 0.5081.514 / 0.8992.039 / 1.172
L60.255 / 0.3860.500 / 0.5280.586 / 0.5890.478 / 0.5101.099 / 0.8221.309 / 0.925
L70.394 / 0.4820.630 / 0.6000.648 / 0.6180.641 / 0.6051.565 / 0.9311.475 / 0.953
L80.328 / 0.4420.589 / 0.5590.614 / 0.5840.610 / 0.5751.969 / 1.0631.691 / 0.990
L90.702 / 0.5822.150 / 0.7481.445 / 0.7261.293 / 0.7014.923 / 1.3134.634 / 1.332
L101.471 / 0.7831.677 / 0.8121.679 / 0.8301.604 / 0.8152.474 / 0.9772.476 / 1.025
Average0.397 / 0.4220.753 / 0.5630.769 / 0.6150.647 / 0.5511.859 / 0.9581.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.

PhaseHCoSTTS2VecTNCMoCoInformerTCN
Training24262.78 + 7.1991.9 + 5.451801.58 + 4.7831.3 + 6.57331.32108.36
Training48262.78 + 8.4191.9 + 6.441801.58 + 5.7931.3 + 8.03167.18109.30
Training96262.78 + 10.091.9 + 8.131801.58 + 7.2331.3 + 9.40325.51110.02
Training288262.78 + 19.991.9 + 16.471801.58 + 14.5131.3 + 17.83449.86112.08
Training672262.78 + 38.391.9 + 32.221801.58 + 28.2131.3 + 36.63587.25112.87
Inference2423.60 + 0.043.73 + 0.053.38 + 0.053.67 + 0.0710.323.20
Inference4823.60 + 0.073.73 + 0.063.38 + 0.093.67 + 0.085.783.67
Inference9623.60 + 0.113.73 + 0.083.38 + 0.093.67 + 0.1011.324.78
Inference28823.60 + 0.243.73 + 0.183.38 + 0.213.67 + 0.2217.197.19
Inference67223.60 + 0.343.73 + 0.303.38 + 0.333.67 + 0.3325.6211.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. For h = 201 that 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 the h used 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 * epsilon and shift as x + epsilon, each with a single random scalar app. C. The code draws one value per channel for both, and scales by 1 + epsilon cost.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-1 original samples as negatives §3.2. The code uses all other 2B-1 items, 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-6 to the real part before atan2, 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 alpha is small, and the paper says a small alpha does not mean seasonality matters less §4.3.
  • Larger alpha helps some ETTh2 horizons. At ETTh2 horizons 168 and 336, the largest value tested (0.1) gives the lowest multivariate MSE. The paper uses 5E-04 for all other experiments tab. 2 §4.3.
  • MoCo batch size must divide the queue. The code asserts K % batch_size == 0 with K = 256 cost.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.py uses np.float datautils.py, which NumPy 1.24 and later reject. Replace it with float before 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.