110
110
from sklearn .inspection import DecisionBoundaryDisplay
111
111
112
112
113
- def plot_training_data_with_decision_boundary (kernel ):
113
+ def plot_training_data_with_decision_boundary (
114
+ kernel , ax = None , long_title = True , support_vectors = True
115
+ ):
114
116
# Train the SVC
115
117
clf = svm .SVC (kernel = kernel , gamma = 2 ).fit (X , y )
116
118
117
119
# Settings for plotting
118
- _ , ax = plt .subplots (figsize = (4 , 3 ))
120
+ if ax is None :
121
+ _ , ax = plt .subplots (figsize = (4 , 3 ))
119
122
x_min , x_max , y_min , y_max = - 3 , 3 , - 3 , 3
120
123
ax .set (xlim = (x_min , x_max ), ylim = (y_min , y_max ))
121
124
@@ -136,20 +139,26 @@ def plot_training_data_with_decision_boundary(kernel):
136
139
linestyles = ["--" , "-" , "--" ],
137
140
)
138
141
139
- # Plot bigger circles around samples that serve as support vectors
140
- ax .scatter (
141
- clf .support_vectors_ [:, 0 ],
142
- clf .support_vectors_ [:, 1 ],
143
- s = 250 ,
144
- facecolors = "none" ,
145
- edgecolors = "k" ,
146
- )
142
+ if support_vectors :
143
+ # Plot bigger circles around samples that serve as support vectors
144
+ ax .scatter (
145
+ clf .support_vectors_ [:, 0 ],
146
+ clf .support_vectors_ [:, 1 ],
147
+ s = 150 ,
148
+ facecolors = "none" ,
149
+ edgecolors = "k" ,
150
+ )
151
+
147
152
# Plot samples by color and add legend
148
- ax .scatter (X [:, 0 ], X [:, 1 ], c = y , s = 150 , edgecolors = "k" )
153
+ ax .scatter (X [:, 0 ], X [:, 1 ], c = y , s = 30 , edgecolors = "k" )
149
154
ax .legend (* scatter .legend_elements (), loc = "upper right" , title = "Classes" )
150
- ax .set_title (f" Decision boundaries of { kernel } kernel in SVC" )
155
+ if long_title :
156
+ ax .set_title (f" Decision boundaries of { kernel } kernel in SVC" )
157
+ else :
158
+ ax .set_title (kernel )
151
159
152
- _ = plt .show ()
160
+ if ax is None :
161
+ plt .show ()
153
162
154
163
155
164
# %%
@@ -237,7 +246,6 @@ def plot_training_data_with_decision_boundary(kernel):
237
246
# using the hyperbolic tangent function (:math:`\tanh`). The kernel function
238
247
# scales and possibly shifts the dot product of the two points
239
248
# (:math:`\mathbf{x}_1` and :math:`\mathbf{x}_2`).
240
-
241
249
plot_training_data_with_decision_boundary ("sigmoid" )
242
250
243
251
# %%
@@ -271,3 +279,26 @@ def plot_training_data_with_decision_boundary(kernel):
271
279
# parameters using techniques such as
272
280
# :class:`~sklearn.model_selection.GridSearchCV` is recommended to capture the
273
281
# underlying structures within the data.
282
+
283
+ # %%
284
+ # XOR dataset
285
+ # -----------
286
+ # A classical example of a dataset which is not linearly separable is the XOR
287
+ # pattern. HEre we demonstrate how different kernels work on such a dataset.
288
+
289
+ xx , yy = np .meshgrid (np .linspace (- 3 , 3 , 500 ), np .linspace (- 3 , 3 , 500 ))
290
+ np .random .seed (0 )
291
+ X = np .random .randn (300 , 2 )
292
+ y = np .logical_xor (X [:, 0 ] > 0 , X [:, 1 ] > 0 )
293
+
294
+ _ , ax = plt .subplots (2 , 2 , figsize = (8 , 8 ))
295
+ args = dict (long_title = False , support_vectors = False )
296
+ plot_training_data_with_decision_boundary ("linear" , ax [0 , 0 ], ** args )
297
+ plot_training_data_with_decision_boundary ("poly" , ax [0 , 1 ], ** args )
298
+ plot_training_data_with_decision_boundary ("rbf" , ax [1 , 0 ], ** args )
299
+ plot_training_data_with_decision_boundary ("sigmoid" , ax [1 , 1 ], ** args )
300
+ plt .show ()
301
+
302
+ # %%
303
+ # As you can see from the plots above, only the `rbf` kernel can find a
304
+ # reasonable decision boundary for the above dataset.
0 commit comments