Bagaimana cara memplot set level 3 dimensi Python?
Saya mengalami kesulitan merencanakan gambar yang ada di kepala saya. Saya ingin memvisualisasikan Kernel-trick dengan Support Vector Machines. Jadi saya membuat beberapa data dua dimensi yang terdiri dari dua lingkaran (lingkaran dalam dan luar) yang harus dipisahkan oleh bidang hiper. Jelas ini tidak mungkin dalam dua dimensi - jadi saya mengubahnya menjadi 3D. Misalkan n adalah banyaknya sampel. Sekarang saya memiliki (n, 3) -array (3 kolom, n baris) X titik data dan (n, 1) -array y dengan label. Menggunakan sklearn saya mendapatkan pengklasifikasi linier melalui
clf = svm.SVC(kernel='linear', C=1000)
clf.fit(X, y)
Saya sudah memplot titik data sebagai plot pencar melalui
plt.scatter(X[:, 0], X[:, 1], c=y, s=30, cmap=plt.cm.Paired)
Sekarang saya ingin memplot hyperplane pemisah sebagai plot permukaan. Masalah saya di sini adalah representasi eksplisit yang hilang dari hyperplane karena fungsi keputusan hanya menghasilkan hyperplane implisit melalui decision_function = 0. Oleh karena itu saya perlu memplot set level (level 0) dari objek 4 dimensi.
Karena saya bukan ahli python, saya akan sangat menghargai jika seseorang dapat membantu saya! Dan saya tahu bahwa ini sebenarnya bukan "gaya" menggunakan SVM, tetapi saya membutuhkan gambar ini sebagai ilustrasi untuk tesis saya.
Edit: "kode" saya saat ini
import numpy as np
import matplotlib.pyplot as plt
from sklearn import svm
from sklearn.datasets import make_blobs, make_circles
from tikzplotlib import save as tikz_save
plt.close('all')
# we create 50 separable points
#X, y = make_blobs(n_samples=40, centers=2, random_state=6)
X, y = make_circles(n_samples=50, factor=0.5, random_state=4, noise=.05)
X2, y2 = make_circles(n_samples=50, factor=0.2, random_state=5, noise=.08)
X = np.append(X,X2, axis=0)
y = np.append(y,y2, axis=0)
# shifte X to [0,2]x[0,2]
X = np.array([[item[0] + 1, item[1] + 1] for item in X])
X[X<0] = 0.01
clf = svm.SVC(kernel='rbf', C=1000)
clf.fit(X, y)
plt.scatter(X[:, 0], X[:, 1], c=y, s=30, cmap=plt.cm.Paired)
# plot the decision function
ax = plt.gca()
xlim = ax.get_xlim()
ylim = ax.get_ylim()
# create grid to evaluate model
xx = np.linspace(xlim[0], xlim[1], 30)
yy = np.linspace(ylim[0], ylim[1], 30)
YY, XX = np.meshgrid(yy, xx)
xy = np.vstack([XX.ravel(), YY.ravel()]).T
Z = clf.decision_function(xy).reshape(XX.shape)
# plot decision boundary and margins
ax.contour(XX, YY, Z, colors='k', levels=[-1, 0, 1], alpha=0.5, linestyles=['--','-','--'])
# plot support vectors
ax.scatter(clf.support_vectors_[:, 0], clf.support_vectors_[:, 1], s=100,
linewidth=1, facecolors='none', edgecolors='k')
################## KERNEL TRICK - 3D ##################
trans_X = np.array([[item[0]**2, item[1]**2, np.sqrt(2*item[0]*item[1])] for item in X])
fig = plt.figure()
ax = plt.axes(projection ="3d")
# creating scatter plot
ax.scatter3D(trans_X[:,0],trans_X[:,1],trans_X[:,2], c = y, cmap=plt.cm.Paired)
clf2 = svm.SVC(kernel='linear', C=1000)
clf2.fit(trans_X, y)
ax = plt.gca(projection='3d')
xlim = ax.get_xlim()
ylim = ax.get_ylim()
zlim = ax.get_zlim()
### from here i don't know what to do ###
xx = np.linspace(xlim[0], xlim[1], 3)
yy = np.linspace(ylim[0], ylim[1], 3)
zz = np.linspace(zlim[0], zlim[1], 3)
ZZ, YY, XX = np.meshgrid(zz, yy, xx)
xyz = np.vstack([XX.ravel(), YY.ravel(), ZZ.ravel()]).T
Z = clf2.decision_function(xyz).reshape(XX.shape)
#ax.contour(XX, YY, ZZ, Z, colors='k', levels=[-1, 0, 1], alpha=0.5, linestyles=['--','-','--'])
Output yang Diinginkan
Saya ingin mendapatkan sesuatu seperti itu . Secara umum saya ingin merekonstruksi apa yang mereka lakukan dalam artikel ini , terutama "Transformasi non-linier".
Jawaban
Sebagian dari pertanyaan Anda dibahas dalam pertanyaan ini tentang linear-kernel SVM . Ini adalah jawaban parsial, karena hanya kernel linier yang dapat direpresentasikan dengan cara ini, yaitu berkat koordinat hyperplane yang dapat diakses melalui estimator saat menggunakan kernel linier.
Solusi lain adalah dengan menemukan isosurface marching_cubes
Solusi ini melibatkan penginstalan scikit-imagetoolkit (https://scikit-image.org) yang memungkinkan untuk menemukan isosurface dari nilai yang diberikan (di sini, saya menganggap 0 karena ini mewakili jarak ke hyperplane) dari grid mesh dari koordinat 3D.
Dalam kode di bawah ini (disalin dari milik Anda), saya mengimplementasikan ide untuk kernel apa pun (dalam contoh, saya menggunakan kernel RBF), dan hasilnya ditampilkan di bawah kode. Harap pertimbangkan catatan kaki saya tentang plot 3D dengan matplotlib, yang mungkin menjadi masalah lain dalam kasus Anda.
import numpy as np
import matplotlib.pyplot as plt
from sklearn import svm
from skimage import measure
from sklearn.datasets import make_blobs, make_circles
from tikzplotlib import save as tikz_save
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
plt.close('all')
# we create 50 separable points
#X, y = make_blobs(n_samples=40, centers=2, random_state=6)
X, y = make_circles(n_samples=50, factor=0.5, random_state=4, noise=.05)
X2, y2 = make_circles(n_samples=50, factor=0.2, random_state=5, noise=.08)
X = np.append(X,X2, axis=0)
y = np.append(y,y2, axis=0)
# shifte X to [0,2]x[0,2]
X = np.array([[item[0] + 1, item[1] + 1] for item in X])
X[X<0] = 0.01
clf = svm.SVC(kernel='rbf', C=1000)
clf.fit(X, y)
plt.scatter(X[:, 0], X[:, 1], c=y, s=30, cmap=plt.cm.Paired)
# plot the decision function
ax = plt.gca()
xlim = ax.get_xlim()
ylim = ax.get_ylim()
# create grid to evaluate model
xx = np.linspace(xlim[0], xlim[1], 30)
yy = np.linspace(ylim[0], ylim[1], 30)
YY, XX = np.meshgrid(yy, xx)
xy = np.vstack([XX.ravel(), YY.ravel()]).T
Z = clf.decision_function(xy).reshape(XX.shape)
# plot decision boundary and margins
ax.contour(XX, YY, Z, colors='k', levels=[-1, 0, 1], alpha=0.5, linestyles=['--','-','--'])
# plot support vectors
ax.scatter(clf.support_vectors_[:, 0], clf.support_vectors_[:, 1], s=100,
linewidth=1, facecolors='none', edgecolors='k')
################## KERNEL TRICK - 3D ##################
trans_X = np.array([[item[0]**2, item[1]**2, np.sqrt(2*item[0]*item[1])] for item in X])
fig = plt.figure()
ax = plt.axes(projection ="3d")
# creating scatter plot
ax.scatter3D(trans_X[:,0],trans_X[:,1],trans_X[:,2], c = y, cmap=plt.cm.Paired)
clf2 = svm.SVC(kernel='rbf', C=1000)
clf2.fit(trans_X, y)
z = lambda x,y: (-clf2.intercept_[0]-clf2.coef_[0][0]*x-clf2.coef_[0][1]*y) / clf2.coef_[0][2]
ax = plt.gca(projection='3d')
xlim = ax.get_xlim()
ylim = ax.get_ylim()
zlim = ax.get_zlim()
### from here i don't know what to do ###
xx = np.linspace(xlim[0], xlim[1], 50)
yy = np.linspace(ylim[0], ylim[1], 50)
zz = np.linspace(zlim[0], zlim[1], 50)
XX ,YY, ZZ = np.meshgrid(xx, yy, zz)
xyz = np.vstack([XX.ravel(), YY.ravel(), ZZ.ravel()]).T
Z = clf2.decision_function(xyz).reshape(XX.shape)
# find isosurface with marching cubes
dx = xx[1] - xx[0]
dy = yy[1] - yy[0]
dz = zz[1] - zz[0]
verts, faces, _, _ = measure.marching_cubes_lewiner(Z, 0, spacing=(1, 1, 1), step_size=2)
verts *= np.array([dx, dy, dz])
verts -= np.array([xlim[0], ylim[0], zlim[0]])
# add as Poly3DCollection
mesh = Poly3DCollection(verts[faces])
mesh.set_facecolor('g')
mesh.set_edgecolor('none')
mesh.set_alpha(0.3)
ax.add_collection3d(mesh)
ax.view_init(20, -45)
plt.savefig('kerneltrick')
Menjalankan kode menghasilkan gambar berikut dengan Matplotlib, di mana permukaan semi-transparan hijau mewakili batas keputusan non-linier.
Catatan kaki: Plotting 3D dengan matplotlib
Perhatikan bahwa Matplotlib 3D tidak dapat mengelola "kedalaman" objek dalam beberapa kasus, karena dapat bertentangan dengan zorderobjek ini. Inilah alasan mengapa kadang-kadang hyperplane terlihat diplot "di atas" poin, bahkan harus "di belakang". Masalah ini adalah bug yang diketahui yang dibahas dalam dokumentasi matplotlib 3d dan dalam jawaban ini .
Jika Anda ingin mendapatkan hasil rendering yang lebih baik, Anda mungkin ingin menggunakan Mayavi , seperti yang direkomendasikan oleh pengembang Matplotlib, atau pustaka plotting 3D Python lainnya.