4、数据集可视化:绘制数据分布散点图,观察类别边界

好,咱们进入第四步。这一步其实挺有意思的——把数据画出来看看。

我个人习惯,拿到任何分类任务,第一件事不是调模型,而是先画图。你想想看,数据长什么样你都不知道,就开始调参,那不是盲人摸象吗?

说白了,散点图能让你直观看到:两类样本能不能分开?边界是直线还是曲线?有没有重叠区域?这些信息,比你跑一百行代码都管用。

4.1 为什么一定要可视化?

我记得有一次做项目,队友直接拿数据训练MLP,折腾了两天,准确率死活上不去。我过去一看,让他把数据画出来——好家伙,两类样本完全混在一起,根本就不是线性可分的。他用的还是单层感知机,那能分得开才怪。

所以,可视化能帮你回答三个关键问题:

  • 数据是否线性可分?——决定你用单层还是多层网络
  • 边界形状什么样?——决定中间层需要多少神经元
  • 有没有噪声点?——决定要不要做数据清洗

核心观点:可视化不是花架子,它是你调试模型的「第一双眼睛」。

4.2 生成实验数据

咱们这次用两种经典分布:

  • 线性可分数据——两个簇,中间有明显间隔
  • 非线性可分数据——比如同心圆、月牙形

代码很简单,我用 sklearn.datasets 直接生成:

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_classification, make_moons

# 生成线性可分数据
X_linear, y_linear = make_classification(
    n_samples=300, 
    n_features=2, 
    n_redundant=0, 
    n_clusters_per_class=1,
    class_sep=1.5,  # 间隔越大越容易分
    random_state=42
)

# 生成月牙形数据(非线性)
X_moons, y_moons = make_moons(
    n_samples=300, 
    noise=0.15, 
    random_state=42
)

这里有个小细节:class_sep 参数控制类别间隔。我刚开始调的时候,设成0.5,画出来两个簇都快叠一起了。后来改成1.5,边界才清晰起来。嗯,这个参数你得多试试。

4.3 绘制散点图

画图代码也不复杂,但有几个点要注意:

def plot_data_distribution(X, y, title):
    plt.figure(figsize=(8, 6))
    
    # 分别画出两类样本
    plt.scatter(X[y==0, 0], X[y==0, 1], 
                c='skyblue', label='类别0', 
                edgecolors='white', alpha=0.7)
    plt.scatter(X[y==1, 0], X[y==1, 1], 
                c='salmon', label='类别1', 
                edgecolors='white', alpha=0.7)
    
    plt.title(title, fontsize=14)
    plt.xlabel('特征1')
    plt.ylabel('特征2')
    plt.legend()
    plt.grid(True, linestyle='--', alpha=0.3)
    plt.tight_layout()
    plt.show()

# 画线性可分数据
plot_data_distribution(X_linear, y_linear, 
                       '线性可分数据分布')

# 画月牙形数据
plot_data_distribution(X_moons, y_moons, 
                       '非线性可分数据(月牙形)')

小技巧:我习惯把 alpha 设成0.7,这样重叠的点能看出密度。如果设成1.0,重叠区域就全黑了,啥也看不出来。

4.4 观察类别边界

画完图,咱们来聊聊怎么看。

线性可分数据:

  • 两类样本分布在左右两侧
  • 中间有一条明显的「空白带」
  • 用一条直线就能分开——单层感知机就够了

月牙形数据:

  • 两类样本像两个弯弯的月亮,交错在一起
  • 没有直线能分开——必须用多层网络
  • 边界是弯曲的,需要中间层来拟合

我曾经犯过一个错:看到月牙形数据,觉得两层MLP肯定够。结果训练出来,边界画得歪歪扭扭的。后来加了中间层宽度,从4个神经元加到16个,边界才变得平滑。

注意:不要只看散点图就下结论。有时候数据在高维空间是线性可分的,但在二维投影里看着像非线性。所以,可视化只是辅助,不是最终判断。

4.5 可视化对实验的意义

回到咱们这个实验——MLP中间层宽度与泛化能力。

你想想看:

  • 如果数据是线性可分的,中间层宽度影响不大,甚至不需要中间层
  • 如果数据是月牙形的,中间层太窄(比如2个神经元),边界拟合不好
  • 中间层太宽(比如100个神经元),又容易过拟合,边界变得「张牙舞爪」

所以,先画图,心里有个底。后面调参的时候,你才知道自己在干什么。

我个人习惯,把散点图和训练后的决策边界放在一起对比。这样能直观看到:模型学到的边界,跟数据的真实分布,到底像不像?

好,这一步就到这儿。下一步咱们开始搭建MLP,看看不同宽度的中间层,到底能画出什么样的决策边界。