Skip to content

Commit 31abefb

Browse files
author
Christian Jorgensen
committed
Making linter happy
1 parent 9276860 commit 31abefb

File tree

5 files changed

+61
-46
lines changed

5 files changed

+61
-46
lines changed

examples/pcovc/PCovC_multioutput.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@
6969
labels_list = [["Even", "Odd"], [">= 5", "< 5"]]
7070

7171
for i, c, cmap in zip(range(3), [is_even, is_less_than_five, y], [cmap1, cmap2, cmap3]):
72-
7372
scat_pca = axs[0, i].scatter(T_pca[:, 0], T_pca[:, 1], c=c, cmap=cmap)
7473
axs[1, i].scatter(T_pcovc[:, 0], T_pcovc[:, 1], c=c, cmap=cmap)
7574

@@ -114,7 +113,6 @@
114113
labels_list = [["Even", "Odd"], ["0", "1", "2"]]
115114

116115
for i, c, cmap in zip(range(3), [is_even, num_holes, y], [cmap1, cmap2, cmap3]):
117-
118116
scat_pca = axs[0, i].scatter(T_pca[:, 0], T_pca[:, 1], c=c, cmap=cmap)
119117
axs[1, i].scatter(T_pcovc[:, 0], T_pcovc[:, 1], c=c, cmap=cmap)
120118

src/skmatter/decomposition/_kernel_pcovc.py

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,17 @@ class KernelPCovC(LinearClassifierMixin, _BaseKPCov):
8787
- ``sklearn.linear_model.RidgeClassifierCV()``
8888
- ``sklearn.linear_model.Perceptron()``
8989
90-
If a pre-fitted classifier is provided, it is used to compute :math:`{\mathbf{Z}}`.
91-
If None and ``n_outputs_ < 2``, ``sklearn.linear_model.LogisticRegression()`` is used.
92-
If None and ``n_outputs_ == 2``, ``sklearn.multioutput.MultiOutputClassifier()`` is used.
90+
If a pre-fitted classifier
91+
is provided, it is used to compute :math:`{\mathbf{Z}}`.
92+
Note that any pre-fitting of the classifier will be lost if `KernelPCovC` is
93+
within a composite estimator that enforces cloning, e.g.,
94+
`sklearn.pipeline.Pipeline` with model caching.
95+
In such cases, the classifier will be re-fitted on the same
96+
training data as the composite estimator.
97+
If None and ``n_outputs < 2``, ``sklearn.linear_model.LogisticRegression()`` is used.
98+
If None and ``n_outputs >= 2``, a ``sklearn.multioutput.MultiOutputClassifier()`` is
99+
constructed, with ``sklearn.linear_model.LogisticRegression()`` models used for each
100+
label.
93101
94102
kernel : {"linear", "poly", "rbf", "sigmoid", "precomputed"} or callable, default="linear"
95103
Kernel.
@@ -455,8 +463,8 @@ def decision_function(self, X=None, T=None):
455463
Z : numpy.ndarray, shape (n_samples,) or (n_samples, n_classes), or a list of \
456464
n_outputs_ such arrays if n_outputs_ > 1
457465
Confidence scores. For binary classification, has shape `(n_samples,)`,
458-
for multiclass classification, has shape `(n_samples, n_classes)`.
459-
If n_outputs_ > 1, the list can contain arrays with differing shapes
466+
for multiclass classification, has shape `(n_samples, n_classes)`.
467+
If n_outputs_ > 1, the list can contain arrays with differing shapes
460468
depending on the number of classes in each output of Y.
461469
"""
462470
check_is_fitted(self, attributes=["pkz_", "ptz_"])
@@ -489,15 +497,14 @@ def decision_function(self, X=None, T=None):
489497
est_.decision_function(T) for est_ in self.classifier_.estimators_
490498
]
491499

492-
def score(self, X, y):
493-
500+
def score(self, X, y, sample_weight=None):
494501
# accuracy_score will handle everything but multiclass-multilabel
495502
if self.n_outputs_ > 1 and len(self.classes_) > 2:
496503
y_pred = self.predict(X)
497504
return np.mean(np.all(y == y_pred, axis=1))
498505

499506
else:
500-
return super().score(X, y)
507+
return super().score(X, y, sample_weight)
501508

502509
# Inherit the docstring from scikit-learn
503510
score.__doc__ = LinearClassifierMixin.score.__doc__

src/skmatter/decomposition/_pcovc.py

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,6 @@
2121
from skmatter.utils import check_cl_fit
2222

2323

24-
# No inheritance from MultiOutputMixin because decision_function would fail
25-
# test_check_estimator.py 'check_classifier_multioutput' (line 2479 of estimator_checks.py).
26-
# This is the only test for multioutput classifiers, so is it OK to exclude this tag?
27-
28-
# did a search of all classifiers that inherit from MultiOutputMixin - none of them implement
29-
# decision function
30-
31-
3224
class PCovC(LinearClassifierMixin, _BasePCov):
3325
r"""Principal Covariates Classification (PCovC).
3426
@@ -133,7 +125,9 @@ class PCovC(LinearClassifierMixin, _BasePCov):
133125
In such cases, the classifier will be re-fitted on the same
134126
training data as the composite estimator.
135127
If None and ``n_outputs < 2``, ``sklearn.linear_model.LogisticRegression()`` is used.
136-
If None and ``n_outputs == 2``, ``sklearn.multioutput.MultiOutputClassifier()`` is used.
128+
If None and ``n_outputs >= 2``, a ``sklearn.multioutput.MultiOutputClassifier()`` is
129+
constructed, with ``sklearn.linear_model.LogisticRegression()`` models used for each
130+
label.
137131
138132
iterated_power : int or 'auto', default='auto'
139133
Number of iterations for the power method computed by
@@ -453,12 +447,13 @@ def decision_function(self, X=None, T=None):
453447
454448
Returns
455449
-------
456-
Z : numpy.ndarray, shape (n_samples,) or (n_samples, n_classes), or a list of \
457-
n_outputs such arrays if n_outputs > 1
458-
Confidence scores. For binary classification, has shape `(n_samples,)`,
459-
for multiclass classification, has shape `(n_samples, n_classes)`.
460-
If n_outputs > 1, the list can contain arrays with differing shapes
461-
depending on the number of classes in each output of Y.
450+
Z : numpy.ndarray, shape (n_samples,) or (n_samples, n_classes), or
451+
a list of n_outputs such arrays if n_outputs > 1.
452+
Confidence scores. For binary classification, has shape
453+
`(n_samples,)`, for multiclass classification, has shape
454+
`(n_samples, n_classes)`. If n_outputs > 1, the list can
455+
contain arrays with differing shapes depending on the number
456+
of classes in each output of Y.
462457
"""
463458
check_is_fitted(self, attributes=["pxz_", "ptz_"])
464459

@@ -514,15 +509,14 @@ def transform(self, X=None):
514509
"""
515510
return super().transform(X)
516511

517-
def score(self, X, y):
518-
512+
def score(self, X, y, sample_weight=None):
519513
# accuracy_score will handle everything but multiclass-multilabel
520514
if self.n_outputs_ > 1 and len(self.classes_) > 2:
521515
y_pred = self.predict(X)
522516
return np.mean(np.all(y == y_pred, axis=1))
523517

524518
else:
525-
return super().score(X, y)
519+
return super().score(X, y, sample_weight)
526520

527521
# Inherit the docstring from scikit-learn
528522
score.__doc__ = LinearClassifierMixin.score.__doc__

tests/test_kernel_pcovc.py

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import numpy as np
44
from sklearn import exceptions
5-
from sklearn.calibration import LinearSVC
5+
from sklearn.svm import LinearSVC
66
from sklearn.datasets import load_breast_cancer as get_dataset
77
from sklearn.multioutput import MultiOutputClassifier
88
from sklearn.naive_bayes import GaussianNB
@@ -31,12 +31,17 @@ def __init__(self, *args, **kwargs):
3131
scaler = StandardScaler()
3232
self.X = scaler.fit_transform(self.X)
3333

34-
self.model = lambda mixing=0.5, classifier=LogisticRegression(), n_components=4, **kwargs: KernelPCovC(
35-
mixing=mixing,
36-
classifier=classifier,
37-
n_components=n_components,
38-
svd_solver=kwargs.pop("svd_solver", "full"),
39-
**kwargs,
34+
self.model = (
35+
lambda mixing=0.5,
36+
classifier=LogisticRegression(),
37+
n_components=4,
38+
**kwargs: KernelPCovC(
39+
mixing=mixing,
40+
classifier=classifier,
41+
n_components=n_components,
42+
svd_solver=kwargs.pop("svd_solver", "full"),
43+
**kwargs,
44+
)
4045
)
4146

4247
def setUp(self):
@@ -484,9 +489,10 @@ def test_bad_n_components(self):
484489

485490

486491
class KernelPCovCMultiOutputTest(KernelPCovCBaseTest):
487-
488492
def test_prefit_multioutput(self):
489-
"""Check that KPCovC works if a prefit classifier is passed when `n_outputs > 1`."""
493+
"""Check that KPCovC works if a prefit classifier
494+
is passed when `n_outputs > 1`.
495+
"""
490496
kernel_params = {"kernel": "sigmoid", "gamma": 1, "degree": 3, "coef0": 0}
491497
K = pairwise_kernels(
492498
self.X, metric="sigmoid", filter_params=True, **kernel_params
@@ -545,7 +551,9 @@ def test_precomputed_multioutput(self):
545551
self.assertTrue(np.linalg.norm(t3 - t1) < self.error_tol)
546552

547553
def test_Z_shape_multioutput(self):
548-
"""Check that KPCovC returns the evidence Z in the desired form when `n_outputs > 1`."""
554+
"""Check that KPCovC returns the evidence Z in
555+
the desired form when `n_outputs > 1`.
556+
"""
549557
kpcovc = KernelPCovC(classifier=MultiOutputClassifier(estimator=Perceptron()))
550558

551559
Y_double = np.column_stack((self.Y, self.Y))
@@ -563,7 +571,9 @@ def test_Z_shape_multioutput(self):
563571
self.assertEqual(z_slice.ndim, 1)
564572

565573
def test_decision_function_multioutput(self):
566-
"""Check that KPCovC's decision_function works in edge cases when `n_outputs > 1`."""
574+
"""Check that KPCovC's decision_function works
575+
in edge cases when `n_outputs > 1`.
576+
"""
567577
kpcovc = self.model(
568578
classifier=MultiOutputClassifier(estimator=LinearSVC()), center=True
569579
)
@@ -580,7 +590,7 @@ def test_decision_function_multioutput(self):
580590
T = kpcovc.transform(self.X)
581591
_ = kpcovc.decision_function(T=T)
582592

583-
#TODO: Add tests for addition of score function to pcovc.py
593+
# TODO: Add tests for addition of score function to pcovc.py
584594

585595

586596
if __name__ == "__main__":

tests/test_pcovc.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
import numpy as np
55
from sklearn import exceptions
6-
from sklearn.calibration import LinearSVC
76
from sklearn.datasets import load_iris as get_dataset
87
from sklearn.decomposition import PCA
98
from sklearn.linear_model import LogisticRegression, RidgeClassifier
@@ -580,9 +579,10 @@ def test_incompatible_coef_shape(self):
580579

581580

582581
class PCovCMultiOutputTest(PCovCBaseTest):
583-
584582
def test_prefit_multioutput(self):
585-
"""Check that PCovC works if a prefit classifier is passed when `n_outputs > 1`."""
583+
"""Check that PCovC works if a prefit classifier
584+
is passed when `n_outputs > 1`.
585+
"""
586586
classifier = MultiOutputClassifier(estimator=LogisticRegression())
587587
Y_double = np.column_stack((self.Y, self.Y))
588588

@@ -625,7 +625,9 @@ def test_precomputed_multioutput(self):
625625
self.assertTrue(np.linalg.norm(t3 - t1) < self.error_tol)
626626

627627
def test_Z_shape_multioutput(self):
628-
"""Check that PCovC returns the evidence Z in the desired form when `n_outputs > 1`."""
628+
"""Check that PCovC returns the evidence Z in the
629+
desired form when `n_outputs > 1`.
630+
"""
629631
pcovc = PCovC()
630632

631633
Y_double = np.column_stack((self.Y, self.Y))
@@ -643,7 +645,9 @@ def test_Z_shape_multioutput(self):
643645
self.assertEqual(est.coef_.shape[0], z_slice.shape[1])
644646

645647
def test_decision_function_multioutput(self):
646-
"""Check that PCovC's decision_function works in edge cases when `n_outputs > 1`."""
648+
"""Check that PCovC's decision_function works in edge
649+
cases when `n_outputs_ > 1`.
650+
"""
647651
pcovc = self.model(classifier=MultiOutputClassifier(estimator=LinearSVC()))
648652
pcovc.fit(self.X, np.column_stack((self.Y, self.Y)))
649653
with self.assertRaises(ValueError) as cm:
@@ -656,6 +660,8 @@ def test_decision_function_multioutput(self):
656660
T = pcovc.transform(self.X)
657661
_ = pcovc.decision_function(T=T)
658662

659-
#TODO: Add tests for addition of score function to pcovc.py
663+
# TODO: Add tests for addition of score function to pcovc.py
664+
665+
660666
if __name__ == "__main__":
661667
unittest.main(verbosity=2)

0 commit comments

Comments
 (0)