# ------------------------------------------------------------
# 图 08:核技巧直觉(低维不可分 → 高维可分)
# ml_SVM_fig08_kernel_idea
# ------------------------------------------------------------
fig = plt.figure(figsize=(13, 5.2))
# --- 左子图:二维空间,线性不可分 ---
ax1 = fig.add_subplot(1, 3, 1)
# 用简化版:一维问题映射到二维
x_1d = np.linspace(-2.5, 2.5, 300)
# 内圈(蓝)半径 < 1.5
theta_demo = np.linspace(0, 2*np.pi, 80)
r_inner_d = np.r_[0.5, 0.7, 0.9, 1.1, 1.3]
for r in r_inner_d:
ax1.scatter(r*np.cos(theta_demo[::4]), r*np.sin(theta_demo[::4]),
c=C_BLUE, s=18, alpha=0.7, edgecolors='none')
r_outer_d = np.r_[2.0, 2.3, 2.6]
for r in r_outer_d:
ax1.scatter(r*np.cos(theta_demo[::3]), r*np.sin(theta_demo[::3]),
c=C_YELLOW, s=18, alpha=0.7, edgecolors='none')
ax1.set_xlim(-3.2, 3.2); ax1.set_ylim(-3.2, 3.2)
ax1.set_aspect('equal')
ax1.set_title('原始空间 $(x_1, x_2)$\n线性不可分', fontsize=10)
ax1.set_xlabel('$x_1$'); ax1.set_ylabel('$x_2$')
patches = [mpatches.Patch(color=C_BLUE, label='类别 $-1$'),
mpatches.Patch(color=C_YELLOW, label='类别 $+1$')]
ax1.legend(handles=patches, fontsize=9, loc='upper right')
# --- 中间:变换箭头 ---
ax2 = fig.add_subplot(1, 3, 2)
ax2.axis('off')
ax2.set_xlim(0, 1); ax2.set_ylim(0, 1)
ax2.annotate('', xy=(0.85, 0.5), xytext=(0.15, 0.5),
arrowprops=dict(arrowstyle='->', color='#333333', lw=2.5))
ax2.text(0.5, 0.62, '特征映射 $\\phi(\\mathbf{x})$',
ha='center', fontsize=11, color='#333333')
ax2.text(0.5, 0.38, r'$\phi: (x_1,x_2) \mapsto (x_1,x_2,x_1^2+x_2^2)$',
ha='center', fontsize=9.5, color='#555555')
# --- 右子图:三维空间,线性可分 ---
ax3 = fig.add_subplot(1, 3, 3, projection='3d')
# 内圈点:z = r^2 小(在下方)
for r in r_inner_d:
pts_x = r*np.cos(theta_demo[::4])
pts_y = r*np.sin(theta_demo[::4])
pts_z = pts_x**2 + pts_y**2
ax3.scatter(pts_x, pts_y, pts_z, c=C_BLUE, s=12, alpha=0.7)
for r in r_outer_d:
pts_x = r*np.cos(theta_demo[::3])
pts_y = r*np.sin(theta_demo[::3])
pts_z = pts_x**2 + pts_y**2
ax3.scatter(pts_x, pts_y, pts_z, c=C_YELLOW, s=12, alpha=0.7)
# 分割平面:z = 3.5(阈值)
xx3, yy3 = np.meshgrid(np.linspace(-3, 3, 20), np.linspace(-3, 3, 20))
ax3.plot_surface(xx3, yy3, np.full_like(xx3, 3.5),
alpha=0.18, color='gray')
ax3.set_title('映射后的空间 $(x_1,x_2,x_1^2{+}x_2^2)$\n线性可分', fontsize=9.5)
ax3.set_xlabel('$x_1$'); ax3.set_ylabel('$x_2$'); ax3.set_zlabel('$x_1^2+x_2^2$')
ax3.view_init(elev=22, azim=-50)
fig.suptitle('图 8 核技巧的直觉:低维线性不可分 → 高维线性可分',
fontsize=11, y=1.01)
fig.tight_layout()
save_fig(fig, 'ml_SVM_fig08_kernel_idea')
plt.show()