# ------------------------------------------------------------
# 3. 辅助函数
# ------------------------------------------------------------
def plot_scatter(ax, X, y, alpha=0.75, s=38, zorder=3):
'''绘制两类散点,深蓝/深黄配色。'''
for val, color, marker, label in [
(-1, C_BLUE, 'o', '类别 $-1$'),
( 1, C_YELLOW, 's', '类别 $+1$'),
]:
mask = y == val
ax.scatter(X[mask, 0], X[mask, 1],
c=color, marker=marker, s=s, alpha=alpha,
edgecolors='white', linewidths=0.4,
label=label, zorder=zorder)
def plot_decision_boundary(ax, clf, X, resolution=300,
draw_margin=True, cmap_bg=True):
'''
绘制 SVC 的决策边界和间隔带。
- 实线:决策边界 f(x)=0
- 虚线:间隔边界 f(x)=±1
- 背景色块:两类的预测区域
'''
x_min, x_max = X[:, 0].min() - 0.5, X[:, 0].max() + 0.5
y_min, y_max = X[:, 1].min() - 0.5, X[:, 1].max() + 0.5
xx, yy = np.meshgrid(
np.linspace(x_min, x_max, resolution),
np.linspace(y_min, y_max, resolution)
)
Z = clf.decision_function(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
if cmap_bg:
bg_cmap = ListedColormap(['#D6E4F7', '#FFF3CC'])
ax.contourf(xx, yy, Z, levels=[-999, 0, 999],
cmap=bg_cmap, alpha=0.35, zorder=0)
# 决策边界
ax.contour(xx, yy, Z, levels=[0],
colors='#333333', linewidths=2.0, zorder=2)
if draw_margin:
ax.contour(xx, yy, Z, levels=[-1, 1],
colors=C_MARGIN, linewidths=1.2,
linestyles='--', zorder=2)
def mark_support_vectors(ax, clf, s=120):
'''用红色空心圆圈标注支持向量。'''
sv = clf.support_vectors_
ax.scatter(sv[:, 0], sv[:, 1],
s=s, facecolors='none', edgecolors=C_SV,
linewidths=1.8, zorder=5, label='支持向量')
def save_fig(fig, basename):
'''统一保存 PNG 和 SVG。'''
fig.savefig(f'./figs/{basename}.png', dpi=300, bbox_inches='tight')
fig.savefig(f'./figs/{basename}.svg', bbox_inches='tight')
print('辅助函数定义完毕')