SMOTE
Sequential Data
Data Augmentation
Machine Learning
Time Series

How to use SMOTE for sequential data

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

Introduction

Using vanilla SMOTE on sequential data is usually risky because SMOTE assumes feature vectors are independent points in space, while sequences have order and temporal structure. The safe answer is not "apply SMOTE directly to the raw sequence", but to decide whether each sequence window is truly an independent sample or whether you need sequence-aware balancing strategies instead.

Why Raw SMOTE Is a Problem for Sequences

SMOTE creates synthetic minority examples by interpolating between nearby samples. That can make sense for ordinary tabular vectors, but it can distort sequential data in several ways:

  • temporal order may be blurred
  • unrealistic transitions may be created
  • future information can leak through bad window construction
  • sequence semantics may no longer match the label

For example, interpolating two sensor sequences point-by-point may produce a shape that no real system would ever generate.

When SMOTE Can Still Be Acceptable

SMOTE can be reasonable if you have already transformed each sequence into an independent fixed-length example and the downstream model treats each window as one labeled sample.

For example, suppose you classify short windows of a signal after converting each window into summary features:

python
1import numpy as np
2from imblearn.over_sampling import SMOTE
3
4X = np.array([
5    [0.2, 1.1, 0.3],
6    [0.1, 1.0, 0.4],
7    [2.0, 3.1, 0.8],
8    [2.2, 3.0, 0.9],
9])
10y = np.array([0, 0, 1, 1])
11
12smote = SMOTE(random_state=42)
13X_resampled, y_resampled = smote.fit_resample(X, y)
14
15print(X_resampled.shape, y_resampled.shape)

Here, SMOTE operates on feature vectors that already summarize the sequence. That is much safer than interpolating the raw time steps directly.

A Better First Option: Class Weights

If you are training an LSTM, GRU, or transformer on raw sequences, class weighting is often a better first choice than synthetic oversampling.

python
1import tensorflow as tf
2
3class_weight = {
4    0: 1.0,
5    1: 4.0,
6}
7
8model.fit(
9    x_train,
10    y_train,
11    epochs=5,
12    class_weight=class_weight
13)

This keeps the original sequential structure intact while still telling the loss function to care more about the minority class.

Windowing Must Respect Time Order

If you create sliding windows from a time series, do that before any balancing logic and be careful not to mix windows from future data into earlier training folds.

Good order:

  1. split data by time or sequence identity
  2. build windows
  3. balance only the training set
  4. leave validation and test sets untouched

If you oversample before the split, you can leak information between train and validation sets and get unrealistic scores.

Sequence-Aware Alternatives

Depending on the domain, safer alternatives include:

  • class weighting
  • focal loss
  • undersampling the majority class
  • domain-specific sequence augmentation
  • generating synthetic sequences with a model built for sequence data

For example, in NLP you might use token-level augmentation rules. In sensor data you might use time warping, magnitude scaling, or jitter that respects the problem domain better than linear interpolation between full sequences.

If You Must Use SMOTE, Flatten Carefully

Some practitioners flatten fixed-length windows and run SMOTE on the flattened vectors:

python
1windows = np.random.rand(100, 20, 3)
2labels = np.random.randint(0, 2, size=100)
3
4flat = windows.reshape(len(windows), -1)
5smote = SMOTE(random_state=42)
6flat_resampled, labels_resampled = smote.fit_resample(flat, labels)
7windows_resampled = flat_resampled.reshape(-1, 20, 3)

This can work mechanically, but it is only defensible if each fixed window is already treated as an independent example and the synthetic interpolation still makes sense in the domain. That is a much narrower use case than many tutorials suggest.

Common Pitfalls

The biggest mistake is applying vanilla SMOTE directly to raw sequential observations and assuming the synthetic outputs are still realistic time-series samples.

Another common issue is balancing before the train-validation split, which leaks information and inflates performance metrics.

People also forget that class imbalance can often be handled more safely with class weights, focal loss, or careful sampling rather than synthetic interpolation.

Finally, do not evaluate balancing methods only by class counts. The synthetic data has to preserve the temporal meaning of the task, not just produce equal label frequencies.

Summary

  • Vanilla SMOTE is usually not the first choice for raw sequential data.
  • It can be acceptable on sequence-derived feature vectors when each sample is already independent.
  • For raw sequence models, class weighting and sequence-aware augmentation are usually safer.
  • Build windows and split data before applying any balancing step.
  • Only use flattened-window SMOTE if the domain supports that interpretation and validation confirms it helps.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

All Rights Reserved.