sklearn FeatureUnion & HalvingGridSearchCV & PCA ValueError: n_components=20 must be between 0 and min(n_samples, n_features)=15 with svd_solver='full

Viewed 217

I am trying to put a FeatureUnion of a PCA, IncrementalPCA and FastICA into a pipeline with a RandomForestClassifier and searching the optimal parameters of the forest with a HalvingGridSearchCV.

Excerpts from the code look like this:

for n_components in range(20,80,10): 

    # all decomposers use the same parameters
    decomposer_pars = {
        'n_components':n_components,
        'whiten':True,
                   }

    # define the list of decomposers
    pipe_preprocessing = [
        ('pca',PCA(**decomposer_pars)),
        ('fastica',FastICA(**decomposer_pars)),
        ('incpca',IncrementalPCA(**decomposer_pars))
    ]

    # define clf
    clf = RandomForestClassifier(n_estimators=50,...)

    # model 
    pipe_model = Pipeline(steps=[
                            ('rf', clf)
                          ])

    # join to parallel feature union 
    pipe_preprocessing = FeatureUnion(pipe_preprocessing)

    # full pipeline preprocessing + model
    pipe = Pipeline(steps=[('preprocessing',pipe_preprocessing),*pipe_model.steps])
    
    # halving gridsearch with crossvalidation
    sh = HalvingGridSearchCV(estimator = pipe, 
         param_grid = {
                       'rf__min_weight_fraction_leaf' : [0,0.001,0.01,0.1],
                       'rf__min_samples_split'        : [0.001,0.01,0.1],
                       'rf__max_features'             : [3,5],
                       'rf__min_impurity_decrease'    : [0,0.001,0.01],
                      }, 
         cv = cv, # NOTE: see description below
         factor = 2, 
         scoring = make_scorer(accuracy_score),
         resource = 'n_samples',
         min_resources = 375,
         max_resources = 3000,
         aggressive_elimination = False, 
         refit = False,
         return_train_score = False,
         n_jobs = n_jobs, 
         verbose = 0,
         error_score='raise')

    res = sh.fit(X_train.values,y_train.reindex(X_train.index).values)

Notes:

  • The generator cv is custom written an generates training / validation folds of size 2794 / 279, respectively. The generator should result in n_splits=24 folds.
  • The overall training matrix X_train has a shape (69844, 80).
  • The classifier clf is simply an instance of RandomForestClassifier with n_estimators=50.

Execution of this code throws this error:

ValueError: n_components=20 must be between 0 and min(n_samples, n_features)=15 with svd_solver='full'

It's clear that the PCA components need not be larger than either the number of features or the number of samples. What I don't understand is why I get this error. The training fold that I feed in are of shape (2794,80), thus the error above should only occur for n_components>=min(n_samples, n_features)=80. I do not understand why the data is interpreted as having min(n_samples, n_features)=15. When I set n_components<15, the code works.

I don't understand what I am doing wrong here. In my understanding, FeatureUnion applies the three decomposers independently to the input training data, and should (internally) return a part of the feature matrix with shape=(n_components,2794). Thus, the transformed feature matrix would be (3*n_components,2794) and subsequent fitting of the clf should work fine.

  • I tried increasing the size of the validation folds (although this does not make sense in theory). Did not change anything.
  • Also, I increased the size of the train folds to 9978. Still the same error.

HOWEVER, increasing min_resources in HalvingGridSearchCV to 1000 does resolve the issue and the code runs up to n_components=40. Then, again, the same error.

Obviously, min_resources is limiting n_samples. But, the smallest value possible in my code above is 375, which would still result in folds of shape (375,80), such that the error should not occur for any value of n_components that I scan over.

Thus, min_resources seems to work differently than in my understanding. How does min_resources excatly affect the size of the internal training folds?

Thank you!

EDIT

I manually performed the transformation with the FeatureUnion with all values of n_components, and it works fine. This speaks for the fact that the problem must be caused by min_resources in HalvingGridSearchCV. Still did not find a solution for that.

0 Answers
Related