Forum Discussion
Scaling Machine Learning Workloads in Microsoft Fabric: How Do You Optimize Performance and Cost?
Hi binitafulpagare,
For very large and highly imbalanced datasets, I would normally start with class weighting rather than oversampling.
Class weighting keeps the original dataset size unchanged while giving the minority class more influence during training. That is usually much cheaper in Spark than generating synthetic observations across a very large dataset.
If the majority class is extremely large, I would next consider distributed undersampling of that class. The important part is to do it reproducibly and only on the training data, while leaving validation and test data in their original distribution.
I would be more cautious with SMOTE at this scale. It can work well for smaller datasets, but creating synthetic observations across millions or billions of records can add significant shuffle, memory and storage overhead. It can also make the training distribution increasingly different from what the model will actually see in production.
For Fabric Spark specifically, Microsoft's Spark performance guidance recommends watching partitioning, skew and executor memory closely. The Spark Advisor can also identify skew and caching problems directly from notebook execution.
I would therefore use a pattern such as:
original Delta training data
-> time or stratified train/validation split
-> class weighting or majority-class undersampling on the training partition only
-> distributed training
-> evaluation against the untouched validation/test distributionFor cost, I would also monitor whether the training job is CPU-bound, memory-bound or simply scanning too much data before increasing capacity. Fabric now supports autoscaling and on-demand Spark billing, so bursty ML training workloads can be isolated from the main Fabric capacity rather than permanently sizing the whole capacity for occasional model-training peaks. Microsoft's on-demand Spark billing guidance is useful for that scenario.
I would also avoid repeatedly rebuilding the same feature dataset for every experiment. Persist the curated feature set as Delta and reuse it across MLflow runs, then vary the model parameters and sampling strategy rather than rerunning the entire feature-engineering pipeline each time.
So for a very large imbalanced dataset, my order would usually be:
- class weighting first
- distributed undersampling if the majority class is still unnecessarily large
- SMOTE only when the dataset is small enough that the extra synthetic data is justified
- and always evaluate against the original production-like class distribution
That tends to give a better balance between model quality, training time and Fabric compute consumption.
AI-assisted drafting: AI was used to help structure and phrase this response. I reviewed and validated the technical content before posting.