You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:使用Keras在2D数据上演示过拟合无法复现问题

嘿,作为经常帮同行搞定教学演示的人,我太懂你这种想完美复现Ng那套过拟合演示的心情了——毕竟直观的可视化比讲十遍理论都管用。你没复现成功大概率是在数据集、模型梯度或者训练设置上没踩准点,给你梳理几个关键步骤,亲测有效:

1. 先把演示用的2D数据集调对

Andrew Ng课程里的演示之所以效果明显,核心是用了少量带噪声的非线性分布数据——比如月牙形、环形散点。如果你的数据集太规整、样本量太大,就算模型再复杂也难出明显过拟合:

  • 用sklearn生成标准演示数据就行,记得加噪声、控样本量:
    from sklearn.datasets import make_moons
    from sklearn.model_selection import train_test_split
    
    # 生成300个带噪声的月牙形数据
    X, y = make_moons(n_samples=300, noise=0.2, random_state=42)
    # 按7:3拆分训练/验证集(必须拆,过拟合的核心是训练/验证表现差异)
    X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.3, random_state=42)
    
2. 设计“复杂度梯度明确”的模型链

要给学生展示从欠拟合→拟合合适→过拟合的完整过程,模型的复杂度差异必须拉够:

  • 欠拟合模型:用最简单的单层逻辑回归,连激活函数都不用太复杂:
    from tensorflow.keras.models import Sequential
    from tensorflow.keras.layers import Dense
    
    def build_simple_model():
        model = Sequential([
            Dense(1, activation='sigmoid', input_shape=(2,))
        ])
        model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
        return model
    
  • 拟合合适模型:2-3层全连接,每层10-20个神经元,刚好能捕捉数据规律但不会记噪声:
    def build_medium_model():
        model = Sequential([
            Dense(16, activation='relu', input_shape=(2,)),
            Dense(8, activation='relu'),
            Dense(1, activation='sigmoid')
        ])
        model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
        return model
    
  • 过拟合模型:堆5层以上全连接,每层50+神经元,完全不加正则化(故意让它“死记硬背”训练集):
    def build_overfit_model():
        model = Sequential([
            Dense(100, activation='relu', input_shape=(2,)),
            Dense(100, activation='relu'),
            Dense(100, activation='relu'),
            Dense(100, activation='relu'),
            Dense(1, activation='sigmoid')
        ])
        model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
        return model
    
3. 训练时的关键细节
  • 训练轮数要够多:别只训10轮,至少训150-200轮,才能看到验证集准确率从上升到下降的完整曲线
  • 一定要记录训练历史:用history = model.fit(...)保存训练/验证的准确率、损失,然后画图对比——这是给学生看的核心可视化:
    import matplotlib.pyplot as plt
    
    def plot_overfit_comparison(hist_simple, hist_medium, hist_overfit):
        plt.figure(figsize=(15,5))
        
        # 子图1:简单模型
        plt.subplot(1,3,1)
        plt.plot(hist_simple.history['accuracy'], label='Train')
        plt.plot(hist_simple.history['val_accuracy'], label='Val')
        plt.title('Underfitting Model')
        plt.xlabel('Epochs')
        plt.ylabel('Accuracy')
        plt.legend()
        
        # 子图2:中等模型
        plt.subplot(1,3,2)
        plt.plot(hist_medium.history['accuracy'], label='Train')
        plt.plot(hist_medium.history['val_accuracy'], label='Val')
        plt.title('Well-Fitted Model')
        plt.xlabel('Epochs')
        plt.legend()
        
        # 子图3:过拟合模型
        plt.subplot(1,3,3)
        plt.plot(hist_overfit.history['accuracy'], label='Train')
        plt.plot(hist_overfit.history['val_accuracy'], label='Val')
        plt.title('Overfitting Model')
        plt.xlabel('Epochs')
        plt.legend()
        
        plt.show()
    
  • 暂时关掉所有正则化(Dropout、L2约束):这些是用来抑制过拟合的,演示阶段先不加,才能让过拟合效果更明显
4. 避坑提醒
  • 别用数据增强:如果给2D数据加了随机翻转、平移,模型泛化能力会变强,反而看不到过拟合
  • 优化器用默认adam就行:别随便调学习率,太高会导致模型震荡,看不到清晰的过拟合曲线
  • 确保训练/验证集分布一致:用train_test_split拆分时别打乱分布,否则验证集的表现会失真

把三个模型的训练曲线放在一起展示,学生一眼就能看懂:简单模型训练/验证准确率都低(欠拟合),中等模型两者都高且接近(拟合合适),复杂模型训练准确率直奔100%但验证准确率先升后降(过拟合)——完全贴合Ng课程里的演示效果。

内容的提问来源于stack exchange,提问作者Baptiste

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 08:23:43