@@ -220,7 +220,6 @@ def __init__(
220
220
self .kernel_params = kernel_params
221
221
222
222
self .n_jobs = n_jobs
223
- self .n_samples_ = None
224
223
225
224
self .fit_inverse_transform = fit_inverse_transform
226
225
@@ -308,17 +307,19 @@ def fit(self, X, Y, W=None):
308
307
309
308
if self .n_components is None :
310
309
if self .svd_solver != "arpack" :
311
- self .n_components = X .shape [0 ]
310
+ self .n_components_ = X .shape [0 ]
312
311
else :
313
- self .n_components = X .shape [0 ] - 1
312
+ self .n_components_ = X .shape [0 ] - 1
313
+ else :
314
+ self .n_components_ = self .n_components
314
315
315
316
K = self ._get_kernel (X )
316
317
317
318
if self .center :
318
319
self .centerer_ = KernelNormalizer ()
319
320
K = self .centerer_ .fit_transform (K )
320
321
321
- self .n_samples_ = X .shape [ 0 ]
322
+ self .n_samples_in_ , self . n_features_in_ = X .shape
322
323
323
324
if self .regressor != "precomputed" :
324
325
if self .regressor is None :
@@ -362,7 +363,7 @@ def fit(self, X, Y, W=None):
362
363
# to avoid needing to compute the kernel a second time
363
364
self .regressor_ = check_krr_fit (regressor , K , X , Y )
364
365
365
- W = self .regressor_ .dual_coef_ .reshape (X . shape [ 0 ] , - 1 )
366
+ W = self .regressor_ .dual_coef_ .reshape (self . n_samples_in_ , - 1 )
366
367
367
368
# Use this instead of `self.regressor_.predict(K)`
368
369
# so that we can handle the case of the pre-fitted regressor
@@ -387,12 +388,17 @@ def fit(self, X, Y, W=None):
387
388
# Handle svd_solver
388
389
self ._fit_svd_solver = self .svd_solver
389
390
if self ._fit_svd_solver == "auto" :
390
- # Small problem or self.n_components == 'mle', just call full PCA
391
- if max (X .shape ) <= 500 or self .n_components == "mle" :
391
+ # Small problem or self.n_components_ == 'mle', just call full PCA
392
+ if (
393
+ max (self .n_samples_in_ , self .n_features_in_ ) <= 500
394
+ or self .n_components_ == "mle"
395
+ ):
392
396
self ._fit_svd_solver = "full"
393
- elif self .n_components >= 1 and self .n_components < 0.8 * min (X .shape ):
397
+ elif self .n_components_ >= 1 and self .n_components_ < 0.8 * max (
398
+ self .n_samples_in_ , self .n_features_in_
399
+ ):
394
400
self ._fit_svd_solver = "randomized"
395
- # This is also the case of self.n_components in (0,1)
401
+ # This is also the case of self.n_components_ in (0,1)
396
402
else :
397
403
self ._fit_svd_solver = "full"
398
404
@@ -536,31 +542,31 @@ def score(self, X, Y):
536
542
return - sum ([Lkpca , Lkrr ])
537
543
538
544
def _decompose_truncated (self , mat ):
539
- if not 1 <= self .n_components <= self .n_samples_ :
545
+ if not 1 <= self .n_components_ <= self .n_samples_in_ :
540
546
raise ValueError (
541
547
"n_components=%r must be between 1 and "
542
548
"n_samples=%r with "
543
549
"svd_solver='%s'"
544
550
% (
545
- self .n_components ,
546
- self .n_samples_ ,
551
+ self .n_components_ ,
552
+ self .n_samples_in_ ,
547
553
self .svd_solver ,
548
554
)
549
555
)
550
- elif not isinstance (self .n_components , numbers .Integral ):
556
+ elif not isinstance (self .n_components_ , numbers .Integral ):
551
557
raise ValueError (
552
558
"n_components=%r must be of type int "
553
559
"when greater than or equal to 1, was of type=%r"
554
- % (self .n_components , type (self .n_components ))
560
+ % (self .n_components_ , type (self .n_components_ ))
555
561
)
556
- elif self .svd_solver == "arpack" and self .n_components == self .n_samples_ :
562
+ elif self .svd_solver == "arpack" and self .n_components_ == self .n_samples_in_ :
557
563
raise ValueError (
558
564
"n_components=%r must be strictly less than "
559
565
"n_samples=%r with "
560
566
"svd_solver='%s'"
561
567
% (
562
- self .n_components ,
563
- self .n_samples_ ,
568
+ self .n_components_ ,
569
+ self .n_samples_in_ ,
564
570
self .svd_solver ,
565
571
)
566
572
)
@@ -569,7 +575,7 @@ def _decompose_truncated(self, mat):
569
575
570
576
if self ._fit_svd_solver == "arpack" :
571
577
v0 = _init_arpack_v0 (min (mat .shape ), random_state )
572
- U , S , Vt = svds (mat , k = self .n_components , tol = self .tol , v0 = v0 )
578
+ U , S , Vt = svds (mat , k = self .n_components_ , tol = self .tol , v0 = v0 )
573
579
# svds doesn't abide by scipy.linalg.svd/randomized_svd
574
580
# conventions, so reverse its outputs.
575
581
S = S [::- 1 ]
@@ -581,7 +587,7 @@ def _decompose_truncated(self, mat):
581
587
# sign flipping is done inside
582
588
U , S , Vt = randomized_svd (
583
589
mat ,
584
- n_components = self .n_components ,
590
+ n_components = self .n_components_ ,
585
591
n_iter = self .iterated_power ,
586
592
flip_sign = True ,
587
593
random_state = random_state ,
@@ -594,24 +600,25 @@ def _decompose_truncated(self, mat):
594
600
return U , S , Vt
595
601
596
602
def _decompose_full (self , mat ):
597
- if self .n_components != "mle" :
598
- if not (0 <= self .n_components <= self .n_samples_ ):
603
+ if self .n_components_ != "mle" :
604
+ if not (0 <= self .n_components_ <= self .n_samples_in_ ):
599
605
raise ValueError (
600
606
"n_components=%r must be between 1 and "
601
607
"n_samples=%r with "
602
608
"svd_solver='%s'"
603
609
% (
604
- self .n_components ,
605
- self .n_samples_ ,
610
+ self .n_components_ ,
611
+ self .n_samples_in_ ,
606
612
self .svd_solver ,
607
613
)
608
614
)
609
- elif self .n_components >= 1 :
610
- if not isinstance (self .n_components , numbers .Integral ):
615
+ elif self .n_components_ >= 1 :
616
+ if not isinstance (self .n_components_ , numbers .Integral ):
611
617
raise ValueError (
612
618
"n_components=%r must be of type int "
613
619
"when greater than or equal to 1, "
614
- "was of type=%r" % (self .n_components , type (self .n_components ))
620
+ "was of type=%r"
621
+ % (self .n_components_ , type (self .n_components_ ))
615
622
)
616
623
617
624
U , S , Vt = linalg .svd (mat , full_matrices = False )
@@ -623,26 +630,28 @@ def _decompose_full(self, mat):
623
630
U , Vt = svd_flip (U , Vt )
624
631
625
632
# Get variance explained by singular values
626
- explained_variance_ = (S ** 2 ) / (self .n_samples_ - 1 )
633
+ explained_variance_ = (S ** 2 ) / (self .n_samples_in_ - 1 )
627
634
total_var = explained_variance_ .sum ()
628
635
explained_variance_ratio_ = explained_variance_ / total_var
629
636
630
637
# Postprocess the number of components required
631
- if self .n_components == "mle" :
632
- self .n_components = _infer_dimension (explained_variance_ , self .n_samples_ )
633
- elif 0 < self .n_components < 1.0 :
638
+ if self .n_components_ == "mle" :
639
+ self .n_components_ = _infer_dimension (
640
+ explained_variance_ , self .n_samples_in_
641
+ )
642
+ elif 0 < self .n_components_ < 1.0 :
634
643
# number of components for which the cumulated explained
635
644
# variance percentage is superior to the desired threshold
636
645
# side='right' ensures that number of features selected
637
- # their variance is always greater than self.n_components float
646
+ # their variance is always greater than self.n_components_ float
638
647
# passed. More discussion in issue: #15669
639
648
ratio_cumsum = stable_cumsum (explained_variance_ratio_ )
640
- self .n_components = (
641
- np .searchsorted (ratio_cumsum , self .n_components , side = "right" ) + 1
649
+ self .n_components_ = (
650
+ np .searchsorted (ratio_cumsum , self .n_components_ , side = "right" ) + 1
642
651
)
643
- self . n_components = self . n_components
652
+
644
653
return (
645
- U [:, : self .n_components ],
646
- S [: self .n_components ],
647
- Vt [: self .n_components ],
654
+ U [:, : self .n_components_ ],
655
+ S [: self .n_components_ ],
656
+ Vt [: self .n_components_ ],
648
657
)
0 commit comments