How to plot a hyperplane in Scatter3D in plotly?

Viewed 459

I want to create a stylized graph to explain SVM classifier.

Code and Graph:

import plotly.graph_objs as go 
import numpy as np
import pandas as pd
from plotly.subplots import make_subplots

columns = ['x1','y1','z1','x1','y2','z2','xl1','yl1']
x1 = np.random.normal(1,0.2,50)
y1 = np.random.normal(1,0.2,50)
z1 = np.random.normal(2,0.2,50)
xl1 = 50*[2.5]
yl1 = 50*[2.5]

x2 = np.random.normal(2,0.2,50)
y2 = np.random.normal(2,0.2,50)
z2 = np.random.normal(2,0.2,50)

df = pd.DataFrame({'x1' : x1,'y1' : y1,'z1' : z1,
                   'x2' : x2,'y2' : y2,'z2' : z2,
                   'xl1' : xl1,'yl1' : yl1})

fig = make_subplots(rows=2, cols=2,
    specs=[[{"type": "scatter"}, {"type": "scatter3d"}],
           [{"type": "scatter3d"}, {"type": "scatter3d"}]])

fig.add_trace(go.Scatter(x=x1, y=y1, mode='markers'), row=1, col=1)
fig.add_trace(go.Scatter(x=x2, y=y2, mode='markers'), row=1, col=1)
fig.add_trace(go.Scatter(x=[3.5,0], y=[0,2.5], mode='lines'), row=1, col=1)  

fig.add_trace(go.Scatter3d(x=x1, y=y1,z=z1, mode='markers'), row=1, col=2)
fig.add_trace(go.Scatter3d(x=x2, y=y2,z=z2, mode='markers'), row=1, col=2)
fig.add_trace(go.Scatter3d(x=[3.5,0,2.1], y=[0,2.5,2.1], z=100*[1,1,1], mode='lines'), row=1, col=2)

fig.add_trace(go.Scatter3d(x=x1, y=y1,z=z1, mode='markers'), row=2, col=1)
fig.add_trace(go.Scatter3d(x=x2, y=y2,z=z2, mode='markers'), row=2, col=1)

fig.add_trace(go.Scatter3d(x=x1, y=y1,z=z1, mode='markers'), row=2, col=2)

fig.update_layout(height=700, showlegend=False)    
fig.show() 

enter image description here

I want to visualize a stylzed hyperplanes for the 4 graphs. In subplot 1 I simply created a line. How can I achieve a hyperlane in the other 3 graphs? (see picture)

enter image description here

I could not find a good example. Any1 knows some smart codes for my purpose?

1 Answers

So suppose you fitted an SVM classifier as follows, where X is an array with 3 columns (features) and y has the same length as X and represents the classes:

model = SVC(kernel="linear").fit(X, y)

The hyperplane is defined as ax+by+cz+d=0 where x,y,z are the three features, a,b,c the fitted coefficients of the model and d the fitted intercept. To express the hyperplane as a function of the z coordinate (the third feature) create a mesh grid over the x and y coordinates (the first two features):

w = model.coef_[0]
xx, yy = np.meshgrid(*np.array([X.min(axis=0), X.max(axis=0)])[:,:2].T)
zz = -(w[0]/w[2])*xx -(w[1]/w[2])*yy - model.intercept_[0]/w[2]

Then, using plotly for visualization:

go.Figure([go.Scatter3d(x=X[:,0], y=X[:,1], z=X[:,2], mode="markers", showlegend=False,
                        marker=dict(color=y, size=2.5, line=dict(color="black", width=1))),
           go.Surface(x=xx, y=yy, z=zz, opacity=.5, showscale=False,
                      surfacecolor=np.zeros(zz.shape), colorscale=[[0, 'grey']])])

Which will create a plot similar to the following (without marker colors and symbols and without the points on the x-y axis):

enter image description here

Related