I have a dataset with the following characteristics:
- moderate sample size (~300 samples)
- moderate class imbalance (~20% positives)
- high-dimensional (the number of independent variables, again ~300, is comparable to the number of samples)
I fitted a logistic regression model with Lasso regularization and two-level 3-fold cross-validation (the outer split is used exclusively for performance evaluation, while the inner CV is used for tuning the regularization hyperparameter). I am using scikit-learn's LogisticRegressionCV
with class_weigh='balanced'
to try and make up for at least some of the imbalance.
The performance as evaluated on the outer CV split is quite good: the model achieves a ROC AUC of around 0.97 ± 0.02 and a Matthews' correlation coefficient of 0.8 ± 0.05 when using a decision threshold of 0.5. This all sounds fun until I look at the model parameters. The regularized model contains around 60 non-zero coefficients, and the optimized regularization hyperparameter is tiny ($\frac{1}{C} = \frac{1}{50}$). Furthermore, when I check the predictions on the training set, I can see that the model achieves complete separation of the classes, which is a known problem with optimizing logistic regression using the standard cross-entropy loss (which is what scikit-learn does).
Now my problem with this is that the number of non-zero coefficients is comparable to the number of positive samples, i.e., the cardinality of the smaller class. I know of the common advice that in an imbalanced-class logistic regression modell, one should adjust the number of predictors based on the cardinality of the smaller class, and this seems reasonable enough (even obvious): if there's one predictor for each positive sample, then it would be trivial to overfit the model and basically have it memorize every single training data point.
So, my question is: do you think my model is overfit? The small regularization parameter and the relatively high remaining dimensionality of the final model would suggest so, but the cross-validated performance suggests that it really is as good as it sounds like. What do you think?
P.s.: I was careful enough to apply at least some basic measures for preventing information leakage. The dataset I am trying to model is from a biomedical study, and sometimes, multiple samples are present by certain patients. I am using the StratifiedGroupKFold
splitter to take this into account, by ensuring that the same patient never shows up in multiple splits during cross-validation.