Translating a scikit 3D SVM plane to XY plane

2020-05-23 python matplotlib 3d rotation geometry

I have a bunch of points in 3D and a 3D SVM boundary plane separating these points. I am trying to align this plane on to XY plane and simultaneously move the points such that their orientation w.r.t to the hyperplane remains the same.

Here is what I have tried so far following this blogpost

def get_coordinates_plane(x, y, z):
    coordinates_plane = []
    for i in range(len(x)):
        for j in range(len(y)):
            coordinates_plane.append((x[i][j], y[i][j], z(x, y)[i][j]))
    print(coordinates_plane)
    return coordinates_plane

def get_svm_plane(X,labels):
    svc = SVC(kernel='linear')
    svc.fit(X,labels)
    z = lambda x,y: (-svc.intercept_[0]-svc.coef_[0][0]*x-svc.coef_[0][1]*y) / svc.coef_[0][2]
    tmp = np.linspace(0, 60, 2)
    x, y = np.meshgrid(tmp, tmp)
    return x,y,z,svc.coef_[0],-svc.intercept_[0]

def rotate(positions,a,b,c,d): # rotation about specified vector
    positions = np.array(positions) - [0,0,d/c]
    cos_theta = c/np.sqrt(a**2+b**2+c**2)
    sin_theta = np.sqrt(a**2 + b**2) / np.sqrt(a ** 2 + b ** 2 + c ** 2)
    u1 = b/np.sqrt(a**2+b**2+c**2)
    u2 = -a/np.sqrt(a**2+b**2+c**2)

    #Utilize known rotation matrix
    rot = np.array([[cos_theta + u1*u1*(1-cos_theta), u1*u2*(1-cos_theta), u2*sin_theta],
                    [u1*u2*(1-cos_theta), cos_theta + u2*u2*(1-cos_theta), -u1*sin_theta],
                    [-u2*sin_theta, u1*sin_theta, cos_theta]])
    return np.dot(positions, rot)

x, y, z, [a, b, c], d = get_svm_plane(X,labels)
coordinates_plane = get_coordinates_plane(x, y, z)
rotated_plane = rotate(coordinates_plane,a, b, c,d)

When I try plotting the plane and points before and after rotation using matplotlib 3D, here is what I get

Before

Before rotation

After

After rotation

Where am I going wrong? I want the SVM plane to be perfectly aligned with XY plane.

Answers

Related