Memory Leak in Logistic Regression.

### Describe the bug

Extreme RAM spike and OOM after upgrade (0.24.2 → 1.1.1) for ultra‑wide sparse L1 Logistic Regression (liblinear & saga) – baseline 680 GB → >1.4 TB (ref #28993)



Summary

After upgrading scikit‑learn and Python, fitting an L1 Logistic Regression on a very large, sparse, high‑dimensional dataset now triggers a massive memory spike (baseline ~680 GB → allocates >1.4 TB → OOM). Previously (with 0.24.2) peak memory stabilized around 750–770 GB for the same data shape. Switching solvers (liblinear → saga) and using SGDClassifier did not resolve the issue.



Workload Scale

Samples: ~7,500,000

Features: ~550,000

Binary classification, L1 regularization

Input matrix: sparse (CSR)



Environments

Stable (old):

Python 3.9

scikit-learn 0.24.2

numpy 1.23.5

scipy 1.7.1

Peak during fit: ~750–770 GB



Problematic (new):

Python 3.10

scikit-learn 1.1.1

scipy 1.14.1

numpy 1.23.5

Baseline resident memory before calling .fit: ~680 GB (holding data & process)

During .fit: climbs rapidly past ~1.4 TB → OOM



Models Tried

Original:

Python

LogisticRegression(

    solver='liblinear',

    C=1.0,

    penalty='l1',

    intercept_scaling=3.0,

    random_state=123,

)



Alternative:

Python

SGDClassifier(

    loss='log_loss',

    penalty='l1',

    alpha=1.0,

    random_state=123,

)



Attempt with saga (still spikes):

Python

LogisticRegression(

    solver='saga',

    C=1.0,

    penalty='l1',

    max_iter=1000,

    n_jobs=-1,

    random_state=123,

)



New Observation

Memory right before training (after data load / preprocessing) sits around 680 GB.

Training triggers a single large jump rather than gradual leakage across multiple fits.

This suggests a large dense working allocation or multiple parallel buffers rather than slow accumulation.



Questions

Are there known regressions or algorithmic changes between 0.24.2 and 1.1.1 that increase memory for sparse, high‑feature L1 logistic regression (liblinear or saga)?
Does liblinear (L1) or saga under certain conditions implicitly densify parts of X at this scale?
Could n_jobs=-1 for saga (or OpenMP threads) multiply large temporary buffers? Is single-thread execution recommended for memory control here?
Is intercept_scaling=3.0 relevant for any hidden copy or augmentation step that becomes costly at extreme dimensionality?
Are there scipy 1.14.1 sparse changes that alter memory layout or workspace usage compared to what 0.24.2 relied on?
Recommended solver / pipeline for this regime (7.5M × 550k, very sparse, L1): saga vs SGD vs feature hashing + SGD vs dimensionality reduction first?
Would upgrading to a newer scikit-learn (1.5.x / 1.6.dev) likely help (any memory PRs touching saga/liblinear)?


### Steps/Code to Reproduce

LogisticRegression(
    solver='liblinear',
    C=1.0,
    penalty='l1',
    intercept_scaling=3.0,
    random_state=123,
)

### Expected Results

The peak memory usage should be below 780Gb. 

### Actual Results

The memory is exceeding 1.5Tb

### Versions

```shell
old: 0.24.2
new: 1.1.1
```

COMMENT:
Thanks for the report. Unfortunately you're still using a very old scikit-learn. The latest release is 1.7.2 at this time.

In order for us to proceed, we'd need a few things:

- Please provide a minimal reproducer according to our guidelines: https://scikit-learn.org/stable/developers/minimal_reproducer.html
- Check against the nightly build to see if the issue still persists
- Try find the relevant pull request which causes this in scikit-learn (you can use `git bisect` and build from source, which might be very tricky for old versions, or almost impossible)
- Use the tricks explained in the issue you linked, there's a reason that issue is closed.

Labels: Bug, Needs Info, Needs Reproducible Code