8000 ENH replace Cython loss functions in SGD part 2 (#28029) · MarcBresson/scikit-learn@f8f16d4 · GitHub
[go: up one dir, main page]

Skip to content

Commit f8f16d4

Browse files
lorentzenchrOmarManzoor
authored andcommitted
ENH replace Cython loss functions in SGD part 2 (scikit-learn#28029)
Co-authored-by: Omar Salman <omar.salman@arbisoft.com>
1 parent 8287538 commit f8f16d4

File tree

10 files changed

+72
-270
lines changed

10 files changed

+72
-270
lines changed

sklearn/linear_model/__init__.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@
4444
from ._quantile import QuantileRegressor
4545
from ._ransac import RANSACRegressor
4646
from ._ridge import Ridge, RidgeClassifier, RidgeClassifierCV, RidgeCV, ridge_regression
47-
from ._sgd_fast import Hinge, Huber, Log, ModifiedHuber, SquaredLoss
4847
from ._stochastic_gradient import SGDClassifier, SGDOneClassSVM, SGDRegressor
4948
from ._theil_sen import TheilSenRegressor
5049

@@ -53,8 +52,6 @@
5352
"BayesianRidge",
5453
"ElasticNet",
5554
"ElasticNetCV",
56-
"Hinge",
57-
"Huber",
5855
"HuberRegressor",
5956
"Lars",
6057
"LarsCV",
@@ -64,10 +61,8 @@
6461
"LassoLarsCV",
6562
"LassoLarsIC",
6663
"LinearRegression",
67-
"Log",
6864
"LogisticRegression",
6965
"LogisticRegressionCV",
70-
"ModifiedHuber",
7166
"MultiTaskElasticNet",
7267
"MultiTaskElasticNetCV",
7368
"MultiTaskLasso",
@@ -85,7 +80,6 @@
8580
"SGDClassifier",
8681
"SGDRegressor",
8782
"SGDOneClassSVM",
88-
"SquaredLoss",
8983
"TheilSenRegressor",
9084
"enet_path",
9185
"lars_path",

sklearn/linear_model/_logistic.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -313,14 +313,14 @@ def _logistic_regression_path(
313313
w0 = np.zeros(n_features + int(fit_intercept), dtype=X.dtype)
314314
mask = y == pos_class
315315
y_bin = np.ones(y.shape, dtype=X.dtype)
316-
if solver in ["lbfgs", "newton-cg", "newton-cholesky"]:
316+
if solver == "liblinear":
317+
mask_classes = np.array([-1, 1])
318+
y_bin[~mask] = -1.0
319+
else:
317320
# HalfBinomialLoss, used for those solvers, represents y in [0, 1] instead
318321
# of in [-1, 1].
319322
mask_classes = np.array([0, 1])
320323
y_bin[~mask] = 0.0
321-
else:
322-
mask_classes = np.array([-1, 1])
323-
y_bin[~mask] = -1.0
324324

325325
# for compute_class_weight
326326
if class_weight == "balanced":

sklearn/linear_model/_sag.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ def sag_solver(
127127
128128
y : ndarray of shape (n_samples,)
129129
Target values. With loss='multinomial', y must be label encoded
130-
(see preprocessing.LabelEncoder).
130+
(see preprocessing.LabelEncoder). For loss='log' it must be in [0, 1].
131131
132132
sample_weight : array-like of shape (n_samples,), default=None
133133
Weights applied to individual samples (1. for unweighted).

sklearn/linear_model/_sag_fast.pyx.tp

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,11 @@ dtypes = [('64', 'double', 'np.float64'),
2929
import numpy as np
3030
from libc.math cimport exp, fabs, isfinite, log
3131
from libc.time cimport time, time_t
32+
from libc.stdio cimport printf
3233

33-
from ._sgd_fast cimport LossFunction
34-
from ._sgd_fast cimport Log, SquaredLoss
35-
34+
from .._loss._loss cimport CyLossFunction, CyHalfSquaredError, CyHalfBinomialLoss
3635
from ..utils._seq_dataset cimport SequentialDataset32, SequentialDataset64
3736

38-
from libc.stdio cimport printf
39-
4037

4138
{{for name_suffix, c_type, np_type in dtypes}}
4239

@@ -77,7 +74,7 @@ cdef {{c_type}} _logsumexp{{name_suffix}}({{c_type}}* arr, int n_classes) noexce
7774
{{for name_suffix, c_type, np_type in dtypes}}
7875

7976
cdef class MultinomialLogLoss{{nam 8000 e_suffix}}:
80-
cdef {{c_type}} _loss(self, {{c_type}} y, {{c_type}}* prediction, int n_classes,
77+
cdef {{c_type}} cy_loss(self, {{c_type}} y, {{c_type}}* prediction, int n_classes,
8178
{{c_type}} sample_weight) noexcept nogil:
8279
r"""Multinomial Logistic regression loss.
8380

@@ -121,7 +118,7 @@ cdef class MultinomialLogLoss{{name_suffix}}:
121118
loss = (logsumexp_prediction - prediction[int(y)]) * sample_weight
122119
return loss
123120

124-
cdef void dloss(self, {{c_type}} y, {{c_type}}* prediction, int n_classes,
121+
cdef void cy_gradient(self, {{c_type}} y, {{c_type}}* prediction, int n_classes,
125122
{{c_type}} sample_weight, {{c_type}}* gradient_ptr) noexcept nogil:
126123
r"""Multinomial Logistic regression gradient of the loss.
127124

@@ -331,7 +328,7 @@ def sag{{name_suffix}}(
331328
cdef bint prox = beta > 0 and saga
332329

333330
# Loss function to optimize
334-
cdef LossFunction loss
331+
cdef CyLossFunction loss
335332
# Whether the loss function is multinomial
336333
cdef bint multinomial = False
337334
# Multinomial loss function
@@ -341,9 +338,9 @@ def sag{{name_suffix}}(
341338
multinomial = True
342339
multiloss = MultinomialLogLoss{{name_suffix}}()
343340
elif loss_function == "log":
344-
loss = Log()
341+
loss = CyHalfBinomialLoss()
345342
elif loss_function == "squared":
346-
loss = SquaredLoss()
343+
loss = CyHalfSquaredError()
347344
else:
348345
raise ValueError("Invalid loss parameter: got %s instead of "
349346
"one of ('log', 'squared', 'multinomial')"
@@ -406,9 +403,9 @@ def sag{{name_suffix}}(
406403

407404
# compute the gradient for this sample, given the prediction
408405
if multinomial:
409-
multiloss.dloss(y, &prediction[0], n_classes, sample_weight, &gradient[0])
406+
multiloss.cy_gradient(y, &prediction[0], n_classes, sample_weight, &gradient[0])
410407
else:
411-
gradient[0] = loss.dloss(y, prediction[0]) * sample_weight
408+
gradient[0] = loss.cy_gradient(y, prediction[0]) * sample_weight
412409

413410
# L2 regularization by simply rescaling the weights
414411
wscale *= wscale_update
@@ -539,7 +536,7 @@ def sag{{name_suffix}}(
539536
(n_iter + 1, end_time - start_time))
540537
break
541538
elif verbose:
542-
printf('Epoch %d, change: %.8f\n', n_iter + 1,
539+
printf('Epoch %d, change: %.8g\n', n_iter + 1,
543540
max_change / max_weight)
544541
n_iter += 1
545542
# We do the error treatment here based on error code in status to avoid
@@ -827,10 +824,10 @@ def _multinomial_grad_loss_all_samples(
827824
)
828825

829826
# compute the gradient for this sample, given the prediction
830-
multiloss.dloss(y, &prediction[0], n_classes, sample_weight, &gradient[0])
827+
multiloss.cy_gradient(y, &prediction[0], n_classes, sample_weight, &gradient[0])
831828

832829
# compute the loss for this sample, given the prediction
833-
sum_loss += multiloss._loss(y, &prediction[0], n_classes, sample_weight)
830+
sum_loss += multiloss.cy_loss(y, &prediction[0], n_classes, sample_weight)
834831

835832
# update the sum of the gradient
836833
for j in range(xnnz):

sklearn/linear_model/_sgd_fast.pxd

Lines changed: 0 additions & 27 deletions
This file was deleted.

0 commit comments

Comments
 (0)
0