Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Regression in DecisionBoundaryDisplay.from_estimator with colors and plot_method='contour' after upgrading to v1.7.0 #31546

Open
@jshn9515

Description

@jshn9515

Describe the bug

Hello. Recently, after upgrading to scikit-learn v1.7.0, I encountered an issue when using DecisionBoundaryDisplay.from_estimator with the colors keyword argument. Specifically, the following error is raised:

  File "D:\Project\Python Project\venv\Lib\site-packages\sklearn\inspection\_plot\decision_boundary.py", line 276, in plot
    plot_func(self.xx0, self.xx1, response, cmap=cmap, **safe_kwargs)
    ~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\Project\Python Project\venv\Lib\site-packages\matplotlib\contour.py", line 689, in __init__
    raise ValueError('Either colors or cmap must be None')
ValueError: Either colors or cmap must be None

However, in v1.6.0, everything works fine.

After further investigation, it seems this issue was introduced by PR #29797, where both cmap and colors are passed to plot_func unconditionally, without explicit conflict handling:

plot_func(self.xx0, self.xx1, response, cmap=cmap, **safe_kwargs)

Additionally, when setting plot_method='contour' in multiclass classification scenarios, the decision boundary is no longer shown as it was in v1.6.0. It appears that this regression is due to the switch in v1.7.0 to always using a cmap to plot the entire decision surface in multiclass scenarios.

Here are the visual differences:

  • v1.6.0 with plot_method='contour':
    Image
  • v1.7.0 with the same code:
    Image

Suggestion

To preserve backward compatibility and expected behavior:

  • Check for mutual exclusivity of colors and cmap and raise a clear warning/error;
  • Retain the old behavior when plot_method='contour'.

I'd be happy to open a PR to help address this regression if the core team is supportive.

Steps/Code to Reproduce

import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.inspection import DecisionBoundaryDisplay
from sklearn.linear_model import LogisticRegression

iris = load_iris()
X = iris.data[:, :2]
classifier = LogisticRegression().fit(X, iris.target)
disp = DecisionBoundaryDisplay.from_estimator(
    classifier,
    X,
    # plot_method='contour',
    xlabel=iris.feature_names[0],
    ylabel=iris.feature_names[1],
    colors='black',
    alpha=0.5,
)
disp.ax_.scatter(X[:, 0], X[:, 1], c=iris.target, edgecolor='k')
plt.show()

Expected Results

No error is raised when using plot_method='contour' together with colors, and the decision boundary is displayed correctly as expected.

Actual Results

Traceback (most recent call last):
  File "d:\Project\Python Project\cc.py", line 9, in <module>
    disp = DecisionBoundaryDisplay.from_estimator(
        classifier,
    ...<4 lines>...
        alpha=0.5,
    )
  File "D:\Project\Python Project\venv\Lib\site-packages\sklearn\inspection\_plot\decision_boundary.py", line 558, in from_estimator
    return display.plot(ax=ax, plot_method=plot_method, **kwargs)
           ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\Project\Python Project\venv\Lib\site-packages\sklearn\inspection\_plot\decision_boundary.py", line 276, in plot
    plot_func(self.xx0, self.xx1, response, cmap=cmap, **safe_kwargs)
    ~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\Project\Python Project\venv\Lib\site-packages\matplotlib\__init__.py", line 1521, in inner
    return func(
        ax,
        *map(cbook.sanitize_sequence, args),
        **{k: cbook.sanitize_sequence(v) for k, v in kwargs.items()})
  File "D:\Project\Python Project\venv\Lib\site-packages\matplotlib\axes\_axes.py", line 6794, in contourf
    contours = mcontour.QuadContourSet(self, *args, **kwargs)
  File "D:\Project\Python Project\venv\Lib\site-packages\matplotlib\contour.py", line 689, in __init__
    raise ValueError('Either colors or cmap must be None')
ValueError: Either colors or cmap must be None

Versions

System:
    python: 3.13.4 (tags/v3.13.4:8a526ec, Jun  3 2025, 17:46:04) [MSC v.1943 64 bit (AMD64)]
executable: D:\Project\Python Project\venv\Scripts\python.exe
   machine: Windows-11-10.0.26100-SP0

Python dependencies:
      sklearn: 1.7.0
          pip: None
   setuptools: 80.9.0
        numpy: 2.3.0
        scipy: 1.15.3
       Cython: 3.1.2
       pandas: 2.3.0
   matplotlib: 3.10.3
       joblib: 1.5.1
threadpoolctl: 3.6.0

Built with OpenMP: True

threadpoolctl info:
       user_api: openmp
   internal_api: openmp
    num_threads: 16
         prefix: vcomp
       filepath: D:\Project\Python Project\venv\Lib\site-packages\sklearn\.libs\vcomp140.dll
        version: None

       user_api: blas
   internal_api: openblas
    num_threads: 16
         prefix: libscipy_openblas
       filepath: D:\Project\Python Project\venv\Lib\site-packages\numpy.libs\libscipy_openblas64_-13e2df515630b4a41f92893938845698.dll
        version: 0.3.29
threading_layer: pthreads
   architecture: Haswell

       user_api: blas
   internal_api: openblas
    num_threads: 16
         prefix: libscipy_openblas
       filepath: D:\Project\Python Project\venv\Lib\site-packages\scipy.libs\libscipy_openblas-f07f5a5d207a3a47104dca54d6d0c86a.dll
        version: 0.3.28
threading_layer: pthreads
   architecture: Haswell

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions