FEA array API support for LogisticRegressionCV - #33906
Conversation
|
Benchmarks with mps are not that good: n_samples, n_features, n_classes = 10000, 1000, 300 Average fit time numpy: 10.513 Average predict time numpy: 0.016 Detailsfrom time import time
import numpy as np
import torch as xp
from tqdm import tqdm
from sklearn import config_context
from sklearn.linear_model import LogisticRegressionCV
n_samples, n_features, n_classes = 10000, 1000, 300
device = "mps"
n_iter = 10
X_np = np.random.rand(n_samples, n_features).astype(np.float32)
y_np = np.random.randint(0, n_classes, n_samples)
numpy_fit_times = []
numpy_predict_times = []
for _ in tqdm(range(n_iter), desc="Numpy"):
lr = LogisticRegressionCV(
Cs=[0.01, 0.1, 0.8],
solver="lbfgs",
max_iter=200,
tol=1e-4,
cv=5,
use_legacy_attributes=False,
l1_ratios=[0.0],
scoring="neg_log_loss",
)
start = time()
lr.fit(X_np, y_np)
numpy_fit_times.append(round(time() - start, 3))
start = time()
pred = lr.predict_proba(X_np)
numpy_predict_times.append(round(time() - start, 3))
avg_numpy_fit = round(sum(numpy_fit_times) / n_iter, 3)
avg_numpy_predict = round(sum(numpy_predict_times) / n_iter, 3)
torch_fit_times = []
torch_predict_times = []
X_xp = xp.rand((n_samples, n_features), dtype=xp.float32, device=device)
y_xp = xp.randint(0, n_classes, (n_samples,), device=device)
for _ in tqdm(range(n_iter), desc=f"Torch {device}"):
with config_context(array_api_dispatch=True):
lr = LogisticRegressionCV(
Cs=[0.01, 0.1, 0.8],
solver="lbfgs",
max_iter=200,
tol=1e-4,
cv=5,
use_legacy_attributes=False,
l1_ratios=[0.0],
scoring="neg_log_loss",
)
start = time()
lr.fit(X_xp, y_xp)
torch_fit_times.append(round(time() - start, 3))
start = time()
pred = lr.predict_proba(X_xp)
first = float(pred[0, 0])
torch_predict_times.append(round(time() - start, 3))
avg_torch_fit = round(sum(torch_fit_times) / n_iter, 3)
avg_torch_predict = round(sum(torch_predict_times) / n_iter, 3)
print(f"Average fit time numpy: {avg_numpy_fit}")
print(f"Average fit time torch {device}: {avg_torch_fit}")
print(f"Torch {device} fit speedup: {round(avg_numpy_fit / avg_torch_fit, 2)}X")
print(f"Average predict time numpy: {avg_numpy_predict}")
print(f"Average predict time torch {device}: {avg_torch_predict}")
print(
f"Torch {device} predict speedup: {round(avg_numpy_predict / avg_torch_predict, 2)}"
"X"
)With Colab they are better but then again Colab does not provide good systems that have much multi processing when running via Numpy on CPU: n_samples, n_features, n_classes = 10000, 300, 100 Average fit time numpy: 53.339 Average predict time numpy: 0.042 Details |
|
@ogrisel Could you kindly help with resolving these numerical discrepancy and tolerance issues? All tests (leaving aside CUDA) pass on my local mps system. |
|
Maybe it could help if we would run assert allclose checks on |
|
The problem is in some cases there are numerical discrepancies whereas if you try to fix those by increasing or decreasing tol then in other cases we get convergence issues in float32 cases. |
|
EDIT: alternatively to the above, we could start by trying the suggestions below: |
lorentzenchr
left a comment
There was a problem hiding this comment.
LGTM. Some minor comments, mostly for cleaner code.
|
@virchan Could you review this PR? |
virchan
left a comment
There was a problem hiding this comment.
LGTM! Thanks, everyone!
Let's merge this.
|
@lorentzenchr and @virchan, thank you for reviewing. |
Reference Issues/PRs
Fixes #33346
What does this implement/fix? Explain your changes.
AI usage disclosure
I used AI assistance for:
Any other comments?
CC: @ogrisel