From 3fea69aba7a34d55dd8777bb6232400a8b2c1b77 Mon Sep 17 00:00:00 2001 From: bachwani Date: Mon, 11 Nov 2019 13:34:13 +0530 Subject: [PATCH 1/4] Effect.py --- yellowbrick/regressor/effect.py | 120 ++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 yellowbrick/regressor/effect.py diff --git a/yellowbrick/regressor/effect.py b/yellowbrick/regressor/effect.py new file mode 100644 index 000000000..cbafbc0c2 --- /dev/null +++ b/yellowbrick/regressor/effect.py @@ -0,0 +1,120 @@ +import numpy as np +import pandas as pd +from .base import RegressionScoreVisualizer +from yellowbrick.style.colors import resolve_colors +from yellowbrick.features.base import DataVisualizer +from yellowbrick.utils.target import TargetType + + +import matplotlib.pyplot as plt + + +class EffectPlot(RegressionScoreVisualizer): + """ + Parameters + ---------- + + model : a Scikit-Learn regressor + Should be an instance of a regressor, otherwise will raise a + YellowbrickTypeError exception on instantiation. + If the estimator is not fitted, it is fit when the visualizer is fitted, + unless otherwise specified by ``is_fitted``. + + ax : matplotlib Axes, default: None + The axes to plot the figure on. If None is passed in the current axes. + will be used (or generated if required). + + colors : list or tuple, default: None + A single color to plot all instances as or a list of colors to color each + instance according to its class in the discrete case or as an ordered + colormap in the sequential case. If not enough colors per class are + specified then the colors are treated as a cycle. + + colormap : string or cmap, default: None + The colormap used to create the individual colors. In the discrete case + it is used to compute the number of colors needed for each class and + in the continuous case it is used to create a sequential color map based + on the range of the target. + + marker : string, default:'D' + Shape of the outliers in the boxplot. 'D' for diamond, '.' for + circles + + kwargs : dict + Keyword arguments that are passed to the base class and may influence + the visualization as defined in other Visualizers. + """ + + def __init__(self,model,ax=None, colors=None, colormap=None, marker='D', **kwargs): + super(EffectPlot, self).__init__(model=model, ax=ax, **kwargs) + self.colors = colors + self.colormap = colormap + self.marker=marker + self.target_type = 'auto' + + def fit(self, X, y, **kwargs): + categorical = self._get_categorical_columns(X) + + #Encoding + dummy_df = pd.get_dummies(X, columns=categorical, drop_first=True) + + self.estimator.fit(dummy_df, y) + coeffs = self.estimator.coef_ + dummy_df = dummy_df*coeffs + + # Recollect the columns + for cols in categorical: + col_names = [a for a in dummy_df.columns.values if cols in a] + dummy_df[cols] = (dummy_df[col_names]).sum(axis=1) + dummy_df.drop(columns = col_names, inplace=True) + + self.draw(dummy_df) + self.columns = dummy_df.columns + + def _get_categorical_columns(self, X): + categorical=[] + cols = X.columns + for col in cols: + DataVisualizer._determine_target_color_type(self, X[col]) + if(self._target_color_type==TargetType.DISCRETE): + categorical.append(col) + return categorical + + + def draw(self, X, **kwargs): + colors = resolve_colors( + n_colors=len(X.columns.values), + colormap=self.colormap, + colors=self.colors + ) + self.ax.vlines(x=0,ymin=0,ymax=X.shape[1]+1,linestyles='dashed', alpha=0.5) + X = np.array(X) + bp = self.ax.boxplot(X, sym='black', patch_artist=True,vert=False) + for (box,color) in zip(bp['boxes'],colors): + box.set( facecolor=color, linewidth=2) + for median in bp['medians']: + median.set(color='black', linewidth=3) + for whisker in bp['whiskers']: + whisker.set(color='black', linewidth=2) + for cap in bp['caps']: + cap.set(color='black', linewidth=2) + for flier in bp['fliers']: + # TODO: Set color of flier here + flier.set(marker=self.marker) + + + def finalize(self): + self.ax.set_xlabel('Feature effect') + self.ax.set_yticklabels(self.columns) + self.ax.set_title('Effect Plot') + plt.tight_layout() + + +def effectplot(model, X, y, **kwargs): + visualizer = EffectPlot(model=model, **kwargs) + visualizer.fit(X, y, **kwargs) + visualizer.finalize() + return visualizer.ax + +#Alias for Effectplot +EffectViz = EffectPlot \ No newline at end of file From eeab5a0e06a881442314e1607749cb01d097aa86 Mon Sep 17 00:00:00 2001 From: bachwani Date: Thu, 14 Nov 2019 23:40:54 +0530 Subject: [PATCH 2/4] Minor changes --- tests/test_regressor/test_effect.py | 280 ++++++++++++++++++++++++++++ yellowbrick/regressor/effect.py | 17 +- 2 files changed, 292 insertions(+), 5 deletions(-) create mode 100644 tests/test_regressor/test_effect.py diff --git a/tests/test_regressor/test_effect.py b/tests/test_regressor/test_effect.py new file mode 100644 index 000000000..73d9e56e0 --- /dev/null +++ b/tests/test_regressor/test_effect.py @@ -0,0 +1,280 @@ +""" +Test the base ProjectionVisualizer drawing functionality +""" + +########################################################################## +## Imports +########################################################################## + + +#import pytest +#import numpy.testing as npt +#import matplotlib.pyplot as plt + +from yellowbrick.regressor.effect import * +from yellowbrick.datasets import load_occupancy +#from yellowbrick.exceptions import YellowbrickValueError + +from tests.base import VisualTestCase +#from ..fixtures import Dataset +#from unittest import mock + +from sklearn.linear_model import LinearRegression +#from sklearn.pipeline import Pipeline +#from sklearn.preprocessing import StandardScaler +#from sklearn.datasets import make_classification, make_regression + + +########################################################################### +### Fixtures +########################################################################### +# +# +#@pytest.fixture(scope="class") +#def discrete(request): +# """ +# Creare a random classification fixture. +# """ +# X, y = make_classification( +# n_samples=400, +# n_features=12, +# n_informative=10, +# n_redundant=0, +# n_classes=5, +# random_state=2019, +# ) +# +# # Set a class attribute for discrete data +# request.cls.discrete = Dataset(X, y) +# +# +#@pytest.fixture(scope="class") +#def continuous(request): +# """ +# Creates a random regressor fixture. +# """ +# X, y = make_regression( +# n_samples=500, n_features=22, n_informative=8, random_state=2019 +# ) +# +# # Set a class attribute for continuous data +# request.cls.continuous = Dataset(X, y) +# +# +########################################################################### +### MockVisualizer +########################################################################### +# +# +#class MockVisualizer(ProjectionVisualizer): +# """ +# The MockVisualizer implements the ProjectionVisualizer interface using +# PCA as an internal transformer. This visualizer is used to directly test +# how subclasses interact with the ProjectionVisualizer base class. +# """ +# +# def __init__( +# self, +# ax=None, +# features=None, +# classes=None, +# colors=None, +# colormap=None, +# target_type="auto", +# projection=2, +# alpha=0.75, +# colorbar=True, +# **kwargs +# ): +# +# super(MockVisualizer, self).__init__( +# ax=ax, +# features=features, +# classes=classes, +# colors=colors, +# colormap=colormap, +# target_type=target_type, +# projection=projection, +# alpha=alpha, +# colorbar=colorbar, +# **kwargs +# ) +# +# self.pca_transformer = Pipeline( +# [ +# ("scale", StandardScaler()), +# ("pca", PCA(self.projection, random_state=2019)), +# ] +# ) +# +# def fit(self, X, y=None): +# super(MockVisualizer, self).fit(X, y) +# self.pca_transformer.fit(X) +# return self +# +# def transform(self, X, y=None): +# try: +# Xp = self.pca_transformer.transform(X) +# except AttributeError as e: +# raise AttributeError(str(e) + " try using fit_transform instead.") +# self.draw(Xp, y) +# return Xp +# + +########################################################################## +## ProjectionVisualizer Tests +########################################################################## + + +#@pytest.mark.usefixtures("discrete", "continuous") +class TestEffectPlot(VisualTestCase): + """ + Test the ProjectionVisualizer base class + """ + + def test_quick_method(self): + """ + Test quick method + """ + X, y = load_occupancy() + visualizer = effectplot(LinearRegression(), X, y, show=False) + self.assert_images_similar(visualizer) + + +# def test_discrete_plot(self): +# """ +# Test the visualizer with discrete target. +# """ +# X, y = self.discrete +# classes = ["a", "b", "c", "d", "e"] +# visualizer = MockVisualizer(projection=2, colormap="plasma", classes=classes) +# X_prime = visualizer.fit_transform(X, y) +# npt.assert_array_equal(visualizer.classes_, classes) +# visualizer.finalize() +# self.assert_images_similar(visualizer) +# assert X_prime.shape == (self.discrete.X.shape[0], 2) +# +# def test_continuous_plot(self): +# """ +# Test the visualizer with continuous target. +# """ +# X, y = self.continuous +# visualizer = MockVisualizer(projection="2d") +# visualizer.fit_transform(X, y) +# visualizer.finalize() +# visualizer.cax.set_yticklabels([]) +# self.assert_images_similar(visualizer) +# +# def test_continuous_when_target_discrete(self): +# """ +# Ensure user can override discrete target_type by specifying continuous +# """ +# _, ax = plt.subplots() +# X, y = self.discrete +# visualizer = MockVisualizer( +# ax=ax, projection="2D", target_type="continuous", colormap="cool" +# ) +# visualizer.fit(X, y) +# visualizer.transform(X, y) +# visualizer.finalize() +# visualizer.cax.set_yticklabels([]) +# self.assert_images_similar(visualizer) +# +# def test_single_plot(self): +# """ +# Assert single color plot when y is not specified +# """ +# X, y = self.discrete +# visualizer = MockVisualizer(projection=2, colormap="plasma") +# visualizer.fit_transform(X) +# visualizer.finalize() +# self.assert_images_similar(visualizer) +# +# def test_discrete_3d(self): +# """ +# Test visualizer for 3 dimensional discrete plots +# """ +# X, y = self.discrete +# +# classes = ["a", "b", "c", "d", "e"] +# colors = ["r", "b", "g", "m", "c"] +# visualizer = MockVisualizer(projection=3, colors=colors, classes=classes) +# visualizer.fit_transform(X, y) +# npt.assert_array_equal(visualizer.classes_, classes) +# visualizer.finalize() +# self.assert_images_similar(visualizer) +# +# def test_3d_continuous_plot(self): +# """ +# Tests visualizer for 3 dimensional continuous plots +# """ +# X, y = self.continuous +# visualizer = MockVisualizer(projection="3D") +# visualizer.fit_transform(X, y) +# visualizer.finalize() +# visualizer.cbar.set_ticks([]) +# self.assert_images_similar(visualizer) +# +# def test_alpha_param(self): +# """ +# Ensure that the alpha parameter modifies opacity +# """ +# # Instantiate a prediction error plot, provide custom alpha +# X, y = self.discrete +# params = {"alpha": 0.3, "projection": 2} +# visualizer = MockVisualizer(**params) +# visualizer.ax = mock.MagicMock() +# visualizer.fit(X, y) +# visualizer.transform(X, y) +# +# assert visualizer.alpha == 0.3 +# +# # Test that alpha was passed to internal matplotlib scatterplot +# _, scatter_kwargs = visualizer.ax.scatter.call_args +# assert "alpha" in scatter_kwargs +# assert scatter_kwargs["alpha"] == 0.3 +# +# # Check Errors +# @pytest.mark.parametrize("projection", ["4D", 1, "100d", 0]) +# def test_wrong_projection_dimensions(self, projection): +# """ +# Validate projection hyperparameter +# """ +# msg = "Projection dimensions must be either 2 or 3" +# with pytest.raises(YellowbrickValueError, match=msg): +# MockVisualizer(projection=projection) +# +# def test_target_not_label_encoded(self): +# """ +# Assert label encoding mismatch with y raises exception +# """ +# X, y = self.discrete +# # Multiply every element by 10 to make non-label encoded +# y = y * 10 +# visualizer = MockVisualizer() +# msg = "Target needs to be label encoded." +# with pytest.raises(YellowbrickValueError, match=msg): +# visualizer.fit_transform(X, y) +# +# @pytest.mark.parametrize("dataset", ("discrete", "continuous")) +# def test_y_required_for_discrete_and_continuous(self, dataset): +# """ +# Assert error is raised when y is not passed to transform +# """ +# X, y = getattr(self, dataset) +# visualizer = MockVisualizer() +# visualizer.fit(X, y) +# +# msg = "y is required for {} target".format(dataset) +# with pytest.raises(YellowbrickValueError, match=msg): +# visualizer.transform(X) +# +# def test_colorbar_false(self): +# """ +# Test that colorbar equals false works correctly +# """ +# visualizer = MockVisualizer(colorbar=False, colormap="YlOrRd") +# visualizer.fit_transform(*self.continuous) +# visualizer.finalize() +# +# self.assert_images_similar(visualizer) diff --git a/yellowbrick/regressor/effect.py b/yellowbrick/regressor/effect.py index cbafbc0c2..f4bc3936a 100644 --- a/yellowbrick/regressor/effect.py +++ b/yellowbrick/regressor/effect.py @@ -110,11 +110,18 @@ def finalize(self): plt.tight_layout() -def effectplot(model, X, y, **kwargs): - visualizer = EffectPlot(model=model, **kwargs) - visualizer.fit(X, y, **kwargs) - visualizer.finalize() - return visualizer.ax +def effectplot(model, X, y, ax=None, colors=None, colormap=None, marker='D', + show=True, **kwargs): + visualizer = EffectPlot(model=model, ax=ax, colors=colors, colormap=colormap, + marker=marker, **kwargs) + visualizer.fit(X, y) + + if show: + visualizer.show() + else: + visualizer.finalize() + + return visualizer #Alias for Effectplot EffectViz = EffectPlot \ No newline at end of file From 3f7fca3b9c6b77b9f10edabfe6f857156f54a98f Mon Sep 17 00:00:00 2001 From: Naresh Date: Tue, 24 Dec 2019 17:19:36 +0530 Subject: [PATCH 3/4] Test for effect plot --- .../test_effect/test_marker.png | Bin 0 -> 11991 bytes .../test_effect/test_quick_method.png | Bin 0 -> 11742 bytes tests/test_regressor/test_effect.py | 278 ++---------------- 3 files changed, 26 insertions(+), 252 deletions(-) create mode 100644 tests/baseline_images/test_regressor/test_effect/test_marker.png create mode 100644 tests/baseline_images/test_regressor/test_effect/test_quick_method.png diff --git a/tests/baseline_images/test_regressor/test_effect/test_marker.png b/tests/baseline_images/test_regressor/test_effect/test_marker.png new file mode 100644 index 0000000000000000000000000000000000000000..f1f072456aa394098894a90b03667ab403c015ce GIT binary patch literal 11991 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 SlExAE_pA0Pt@Oj^fB$cg0-^B$ literal 0 HcmV?d00001 diff --git a/tests/baseline_images/test_regressor/test_effect/test_quick_method.png b/tests/baseline_images/test_regressor/test_effect/test_quick_method.png new file mode 100644 index 0000000000000000000000000000000000000000..7c397ddc02b461f204ffce8e2231de9f195e4574 GIT binary patch literal 11742 zcmeHtcT`i^+V=s*VH5>X1VkW=j1>eCrMFRvV*wSVH>pyjhF+4fj0h5#89^Po$RHvh zAVq1SKtM!_(uD}21Sz3~l0fo3C)nn_^WHn_uJ!%#t@W{%Msvc+K6~%y_x#Gfeo9|& z!#a_52!d?*>8SP@1mTiE5YC<7eGBhoSxr{K%QrrUe>(de{DgdG9}fRt>v`1F2SNDG zqklN=Yi2mZn@U(66Re?!Bi8@Cw*zwVJl50A1MB8&E8*wh?c?m>E-xb|b3j_+0v7A3 zA}jmlx{QanlkASj)ME%Df&8TX3bCQcAci#*~Kjr@ZhX=uDwYEG^+LZO;jIvpx z&u+^0&ik5LE?WxLmQE6If%sy$BD4sE0`_r;r5>-BFg!Y?J!St(z zI}5Km!qhx8EBBhlIdC9IjFxo^yx?a}X~Ez20vlndTi1MpAV+mM;QilD|3CM(qelye zUqLQzW$af6)47EOA+a?G;$86csYvXx9ZA8HPsC&!1Y^YN@}={od)iBiNnyd}c3p|D z0+sJ9%*c%l*}ZPayfItR+f=?SZ;d^7dr?RkHI&-ZS~4^=bm5?g*N3;6_uE_owbL4I z&w3xAqMs)w+%nucva*e|s7s7<;Q0=w^#&&=g8Yz%huu@ZTLM9}4y^mX^|tcu#Kb7l zN-rr&lS$SjJbCiuE*a74_@@hs&KDANy3i~Nv-mS6e1)-~S7^3Rg%`nYSo4hpw}CqC zY{=pZ3_&-IUs6(1hsc4?IWHvr^){)iYHdAp;^fI1&6PKrHQDCH5d<#8@(2eJr{WK6zHw&f$l+ml=ywfNGwVv|SNw5}Rsyx??JTLj@7#PUaU zd@$I7F>6-PtEML6L{IU*-r{eT@tMqiW#z3eUc8V~QxpCD_utVex#%Neg}h|rglhn73yiSZfmfrg730jc)pMUxkEP;7N~@*>mekz2)8$~5V8zoIqv)AWhD?k++c2V$O%M+9sZrFsVgfY@Y-Ug2Hcxr6UZNh|Kl!yZh>pI|8;OBJa*}IjMn%m1Tj{s-t>U%sY#rXM)JxF2CCA%Wh z)6;#6dq4DI4m8ZC7L4as!bd0j%D3_J`&0Y&tuQ$F&S)ViFBDW}O|=6xuo@qHR;DevPBgZn5OpMm6 zRy96MRWQ!ADo^%MGzsRr1)nctHokFeApQaCY)IserO|S;JNU%agcl}zd*;1^hE{e* z9$;EEBIk+UHssrv)7t&hfdohoGao^=7zsrRSo)<3c z*45LCBos)NssGiFoa~KJ>xp<$d*bv9J+iF1r+p1TR#~DvER8jw3oQ z^i$jT;^RXt%jtAuV`D1oorg|t1!ihDfGf87?c29@R4R=x-XJKnoJlV>I~=sKf{z0D zZ9X5}z3EIGUwm{>qC?YzWqO(x z@x{YV<%^3c4_=64uHd=%NFd54mX=W?$v6#yxVi|2wMdL4yfNIlbEmDFn>4&c5N5PZ z<9b=SH(oN)(MdMsGdjN6%V2Q0CamF+*rhplL{mU7T0Dv`Z0fR(-sm1OnJlNFVTE0f z6x9oUX}q-nVQWmv!c@_^#2H3kEXMR%FF(gErcuUvx@bCrxgL{$Y(biTTKAn6N4}pR zPlx-(;N=ZN9C*uP92`gQTjhGVS^­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

F8_c9Jaaie*j6*1m^$% literal 0 HcmV?d00001 diff --git a/tests/test_regressor/test_effect.py b/tests/test_regressor/test_effect.py index 73d9e56e0..d26e09389 100644 --- a/tests/test_regressor/test_effect.py +++ b/tests/test_regressor/test_effect.py @@ -1,280 +1,54 @@ """ -Test the base ProjectionVisualizer drawing functionality +Test the EffectPlot functionality """ ########################################################################## ## Imports ########################################################################## - -#import pytest -#import numpy.testing as npt -#import matplotlib.pyplot as plt +import pytest from yellowbrick.regressor.effect import * -from yellowbrick.datasets import load_occupancy -#from yellowbrick.exceptions import YellowbrickValueError +from yellowbrick.datasets import load_concrete from tests.base import VisualTestCase -#from ..fixtures import Dataset -#from unittest import mock - -from sklearn.linear_model import LinearRegression -#from sklearn.pipeline import Pipeline -#from sklearn.preprocessing import StandardScaler -#from sklearn.datasets import make_classification, make_regression - -########################################################################### -### Fixtures -########################################################################### -# -# -#@pytest.fixture(scope="class") -#def discrete(request): -# """ -# Creare a random classification fixture. -# """ -# X, y = make_classification( -# n_samples=400, -# n_features=12, -# n_informative=10, -# n_redundant=0, -# n_classes=5, -# random_state=2019, -# ) -# -# # Set a class attribute for discrete data -# request.cls.discrete = Dataset(X, y) -# -# -#@pytest.fixture(scope="class") -#def continuous(request): -# """ -# Creates a random regressor fixture. -# """ -# X, y = make_regression( -# n_samples=500, n_features=22, n_informative=8, random_state=2019 -# ) -# -# # Set a class attribute for continuous data -# request.cls.continuous = Dataset(X, y) -# -# -########################################################################### -### MockVisualizer -########################################################################### -# -# -#class MockVisualizer(ProjectionVisualizer): -# """ -# The MockVisualizer implements the ProjectionVisualizer interface using -# PCA as an internal transformer. This visualizer is used to directly test -# how subclasses interact with the ProjectionVisualizer base class. -# """ -# -# def __init__( -# self, -# ax=None, -# features=None, -# classes=None, -# colors=None, -# colormap=None, -# target_type="auto", -# projection=2, -# alpha=0.75, -# colorbar=True, -# **kwargs -# ): -# -# super(MockVisualizer, self).__init__( -# ax=ax, -# features=features, -# classes=classes, -# colors=colors, -# colormap=colormap, -# target_type=target_type, -# projection=projection, -# alpha=alpha, -# colorbar=colorbar, -# **kwargs -# ) -# -# self.pca_transformer = Pipeline( -# [ -# ("scale", StandardScaler()), -# ("pca", PCA(self.projection, random_state=2019)), -# ] -# ) -# -# def fit(self, X, y=None): -# super(MockVisualizer, self).fit(X, y) -# self.pca_transformer.fit(X) -# return self -# -# def transform(self, X, y=None): -# try: -# Xp = self.pca_transformer.transform(X) -# except AttributeError as e: -# raise AttributeError(str(e) + " try using fit_transform instead.") -# self.draw(Xp, y) -# return Xp -# +from sklearn.linear_model import LinearRegression, Lasso, Ridge ########################################################################## -## ProjectionVisualizer Tests +## EffectPlot Tests ########################################################################## - -#@pytest.mark.usefixtures("discrete", "continuous") class TestEffectPlot(VisualTestCase): """ - Test the ProjectionVisualizer base class + Test the EffectPlot base class """ def test_quick_method(self): """ Test quick method """ - X, y = load_occupancy() + X, y = load_concrete() visualizer = effectplot(LinearRegression(), X, y, show=False) self.assert_images_similar(visualizer) + def test_marker(self): + """ + Test circular marker. + """ + X, y = load_concrete() + visualizer = EffectPlot(LinearRegression(), marker='.', colormap='cool') + visualizer.fit(X, y) + visualizer.finalize() + self.assert_images_similar(visualizer) -# def test_discrete_plot(self): -# """ -# Test the visualizer with discrete target. -# """ -# X, y = self.discrete -# classes = ["a", "b", "c", "d", "e"] -# visualizer = MockVisualizer(projection=2, colormap="plasma", classes=classes) -# X_prime = visualizer.fit_transform(X, y) -# npt.assert_array_equal(visualizer.classes_, classes) -# visualizer.finalize() -# self.assert_images_similar(visualizer) -# assert X_prime.shape == (self.discrete.X.shape[0], 2) -# -# def test_continuous_plot(self): -# """ -# Test the visualizer with continuous target. -# """ -# X, y = self.continuous -# visualizer = MockVisualizer(projection="2d") -# visualizer.fit_transform(X, y) -# visualizer.finalize() -# visualizer.cax.set_yticklabels([]) -# self.assert_images_similar(visualizer) -# -# def test_continuous_when_target_discrete(self): -# """ -# Ensure user can override discrete target_type by specifying continuous -# """ -# _, ax = plt.subplots() -# X, y = self.discrete -# visualizer = MockVisualizer( -# ax=ax, projection="2D", target_type="continuous", colormap="cool" -# ) -# visualizer.fit(X, y) -# visualizer.transform(X, y) -# visualizer.finalize() -# visualizer.cax.set_yticklabels([]) -# self.assert_images_similar(visualizer) -# -# def test_single_plot(self): -# """ -# Assert single color plot when y is not specified -# """ -# X, y = self.discrete -# visualizer = MockVisualizer(projection=2, colormap="plasma") -# visualizer.fit_transform(X) -# visualizer.finalize() -# self.assert_images_similar(visualizer) -# -# def test_discrete_3d(self): -# """ -# Test visualizer for 3 dimensional discrete plots -# """ -# X, y = self.discrete -# -# classes = ["a", "b", "c", "d", "e"] -# colors = ["r", "b", "g", "m", "c"] -# visualizer = MockVisualizer(projection=3, colors=colors, classes=classes) -# visualizer.fit_transform(X, y) -# npt.assert_array_equal(visualizer.classes_, classes) -# visualizer.finalize() -# self.assert_images_similar(visualizer) -# -# def test_3d_continuous_plot(self): -# """ -# Tests visualizer for 3 dimensional continuous plots -# """ -# X, y = self.continuous -# visualizer = MockVisualizer(projection="3D") -# visualizer.fit_transform(X, y) -# visualizer.finalize() -# visualizer.cbar.set_ticks([]) -# self.assert_images_similar(visualizer) -# -# def test_alpha_param(self): -# """ -# Ensure that the alpha parameter modifies opacity -# """ -# # Instantiate a prediction error plot, provide custom alpha -# X, y = self.discrete -# params = {"alpha": 0.3, "projection": 2} -# visualizer = MockVisualizer(**params) -# visualizer.ax = mock.MagicMock() -# visualizer.fit(X, y) -# visualizer.transform(X, y) -# -# assert visualizer.alpha == 0.3 -# -# # Test that alpha was passed to internal matplotlib scatterplot -# _, scatter_kwargs = visualizer.ax.scatter.call_args -# assert "alpha" in scatter_kwargs -# assert scatter_kwargs["alpha"] == 0.3 -# -# # Check Errors -# @pytest.mark.parametrize("projection", ["4D", 1, "100d", 0]) -# def test_wrong_projection_dimensions(self, projection): -# """ -# Validate projection hyperparameter -# """ -# msg = "Projection dimensions must be either 2 or 3" -# with pytest.raises(YellowbrickValueError, match=msg): -# MockVisualizer(projection=projection) -# -# def test_target_not_label_encoded(self): -# """ -# Assert label encoding mismatch with y raises exception -# """ -# X, y = self.discrete -# # Multiply every element by 10 to make non-label encoded -# y = y * 10 -# visualizer = MockVisualizer() -# msg = "Target needs to be label encoded." -# with pytest.raises(YellowbrickValueError, match=msg): -# visualizer.fit_transform(X, y) -# -# @pytest.mark.parametrize("dataset", ("discrete", "continuous")) -# def test_y_required_for_discrete_and_continuous(self, dataset): -# """ -# Assert error is raised when y is not passed to transform -# """ -# X, y = getattr(self, dataset) -# visualizer = MockVisualizer() -# visualizer.fit(X, y) -# -# msg = "y is required for {} target".format(dataset) -# with pytest.raises(YellowbrickValueError, match=msg): -# visualizer.transform(X) -# -# def test_colorbar_false(self): -# """ -# Test that colorbar equals false works correctly -# """ -# visualizer = MockVisualizer(colorbar=False, colormap="YlOrRd") -# visualizer.fit_transform(*self.continuous) -# visualizer.finalize() -# -# self.assert_images_similar(visualizer) + @pytest.mark.parametrize("model", [LinearRegression(), Lasso(alpha=100), Ridge()]) + def test_other_linear_models(self, model): + """ + Test other linear_models + """ + message = "case failed for {}".format(model) + viz = EffectPlot(model=model, marker='.', colormap='cool') + assert viz.estimator == model, message + + \ No newline at end of file From 549293e27bbe7525b1fbca633a342c97820286ff Mon Sep 17 00:00:00 2001 From: Naresh Date: Fri, 27 Dec 2019 16:27:47 +0530 Subject: [PATCH 4/4] Added few docstrig --- yellowbrick/regressor/effect.py | 47 +++++++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/yellowbrick/regressor/effect.py b/yellowbrick/regressor/effect.py index f4bc3936a..b9a2316cc 100644 --- a/yellowbrick/regressor/effect.py +++ b/yellowbrick/regressor/effect.py @@ -8,6 +8,9 @@ import matplotlib.pyplot as plt +########################################################################## +## Effect Plots +########################################################################## class EffectPlot(RegressionScoreVisualizer): """ @@ -53,6 +56,24 @@ def __init__(self,model,ax=None, colors=None, colormap=None, marker='D', **kwarg self.target_type = 'auto' def fit(self, X, y, **kwargs): + """ + Fits the estimator to dataset and then multiply weights of a feature + with each feature values to generate new dataset. + Parameters + ---------- + X : ndarray or DataFrame of shape n x m + A matrix of n instances with m features + + y : ndarray or Series of length n + An array or series of target values + + kwargs: keyword arguments passed to Scikit-Learn API. + + Returns + ------- + self : EffectPlot + The visualizer instance + """ categorical = self._get_categorical_columns(X) #Encoding @@ -70,8 +91,13 @@ def fit(self, X, y, **kwargs): self.draw(dummy_df) self.columns = dummy_df.columns + return self def _get_categorical_columns(self, X): + """ + Finds the categorical features among the given features. Uses + _determine_targer_color_type from `DataVisualizer` for this purpose. + """ categorical=[] cols = X.columns for col in cols: @@ -82,6 +108,9 @@ def _get_categorical_columns(self, X): def draw(self, X, **kwargs): + """ + Draws a box plot. Provide control over almost anything in the plot. + """ colors = resolve_colors( n_colors=len(X.columns.values), colormap=self.colormap, @@ -101,6 +130,7 @@ def draw(self, X, **kwargs): for flier in bp['fliers']: # TODO: Set color of flier here flier.set(marker=self.marker) + return self.ax def finalize(self): @@ -110,18 +140,25 @@ def finalize(self): plt.tight_layout() +########################################################################## +## Quick Method +########################################################################## + def effectplot(model, X, y, ax=None, colors=None, colormap=None, marker='D', show=True, **kwargs): - visualizer = EffectPlot(model=model, ax=ax, colors=colors, colormap=colormap, + """ + Quick Method. + """ + viz = EffectPlot(model=model, ax=ax, colors=colors, colormap=colormap, marker=marker, **kwargs) - visualizer.fit(X, y) + viz.fit(X, y) if show: - visualizer.show() + viz.show() else: - visualizer.finalize() + viz.finalize() - return visualizer + return viz #Alias for Effectplot EffectViz = EffectPlot \ No newline at end of file