|
"""Determination of parameter bounds""" |
|
|
|
|
|
|
|
|
|
from numbers import Real |
|
|
|
import numpy as np |
|
|
|
from ..preprocessing import LabelBinarizer |
|
from ..utils._param_validation import Interval, StrOptions, validate_params |
|
from ..utils.extmath import safe_sparse_dot |
|
from ..utils.validation import check_array, check_consistent_length |
|
|
|
|
|
@validate_params( |
|
{ |
|
"X": ["array-like", "sparse matrix"], |
|
"y": ["array-like"], |
|
"loss": [StrOptions({"squared_hinge", "log"})], |
|
"fit_intercept": ["boolean"], |
|
"intercept_scaling": [Interval(Real, 0, None, closed="neither")], |
|
}, |
|
prefer_skip_nested_validation=True, |
|
) |
|
def l1_min_c(X, y, *, loss="squared_hinge", fit_intercept=True, intercept_scaling=1.0): |
|
"""Return the lowest bound for C. |
|
|
|
The lower bound for C is computed such that for C in (l1_min_C, infinity) |
|
the model is guaranteed not to be empty. This applies to l1 penalized |
|
classifiers, such as LinearSVC with penalty='l1' and |
|
linear_model.LogisticRegression with penalty='l1'. |
|
|
|
This value is valid if class_weight parameter in fit() is not set. |
|
|
|
Parameters |
|
---------- |
|
X : {array-like, sparse matrix} of shape (n_samples, n_features) |
|
Training vector, where `n_samples` is the number of samples and |
|
`n_features` is the number of features. |
|
|
|
y : array-like of shape (n_samples,) |
|
Target vector relative to X. |
|
|
|
loss : {'squared_hinge', 'log'}, default='squared_hinge' |
|
Specifies the loss function. |
|
With 'squared_hinge' it is the squared hinge loss (a.k.a. L2 loss). |
|
With 'log' it is the loss of logistic regression models. |
|
|
|
fit_intercept : bool, default=True |
|
Specifies if the intercept should be fitted by the model. |
|
It must match the fit() method parameter. |
|
|
|
intercept_scaling : float, default=1.0 |
|
When fit_intercept is True, instance vector x becomes |
|
[x, intercept_scaling], |
|
i.e. a "synthetic" feature with constant value equals to |
|
intercept_scaling is appended to the instance vector. |
|
It must match the fit() method parameter. |
|
|
|
Returns |
|
------- |
|
l1_min_c : float |
|
Minimum value for C. |
|
|
|
Examples |
|
-------- |
|
>>> from sklearn.svm import l1_min_c |
|
>>> from sklearn.datasets import make_classification |
|
>>> X, y = make_classification(n_samples=100, n_features=20, random_state=42) |
|
>>> print(f"{l1_min_c(X, y, loss='squared_hinge', fit_intercept=True):.4f}") |
|
0.0044 |
|
""" |
|
|
|
X = check_array(X, accept_sparse="csc") |
|
check_consistent_length(X, y) |
|
|
|
Y = LabelBinarizer(neg_label=-1).fit_transform(y).T |
|
|
|
den = np.max(np.abs(safe_sparse_dot(Y, X))) |
|
if fit_intercept: |
|
bias = np.full( |
|
(np.size(y), 1), intercept_scaling, dtype=np.array(intercept_scaling).dtype |
|
) |
|
den = max(den, abs(np.dot(Y, bias)).max()) |
|
|
|
if den == 0.0: |
|
raise ValueError( |
|
"Ill-posed l1_min_c calculation: l1 will always " |
|
"select zero coefficients for this data" |
|
) |
|
if loss == "squared_hinge": |
|
return 0.5 / den |
|
else: |
|
return 2.0 / den |
|
|