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

为何基于Numpy的简单神经网络无法学习非线性数据?

问题分析与解决方案

嘿,我来帮你搞清楚为啥你的神经网络学不了这个非线性任务!

核心问题:你的单层网络只能处理线性可分问题

你现在的神经网络只有输入层+输出层(中间没有隐藏层),本质上就是个带sigmoid激活的线性分类器。这种结构的输出是输入的单调函数——因为sigmoid是单调递增的,输入的线性组合经过它之后,输出还是随输入单调变化的。

但你的目标任务是:输入1→0,2-3→1,4→0,这是一个先升后降的非单调映射,属于典型的线性不可分问题。单层网络无论怎么调整权重,都没法拟合这种非线性模式;而你之前的线性任务(输入[2,2,0,0]对应输出[1,1,0,0])是线性可分的,所以能轻松学好。

解决方案:给网络加一个隐藏层

要拟合非线性映射,你需要引入隐藏层——这是神经网络能处理非线性问题的核心。根据万能逼近定理,只要隐藏层有足够多的神经元,单隐藏层的神经网络可以拟合任何连续函数。

下面是修改后的代码,我加了一个2神经元的隐藏层,让网络有能力学习你的目标映射:

import numpy as np

# sigmoid函数及其导数
def nonlin(x, deriv=False):
    if deriv:
        return x * (1 - x)
    return 1 / (1 + np.exp(-x))

# 输入数据集
X = np.array([[1], [2], [3], [4]])
# 输出数据集
y = np.array([[0, 1, 1, 0]]).T

np.random.seed(1)

# 初始化两层权重:输入→隐藏(1→2神经元),隐藏→输出(2→1神经元)
syn0 = 2 * np.random.random((1, 2)) - 1
syn1 = 2 * np.random.random((2, 1)) - 1

for iter in range(100000):
    # 前向传播
    l0 = X
    l1 = nonlin(np.dot(l0, syn0))  # 隐藏层计算
    l2 = nonlin(np.dot(l1, syn1))  # 输出层预测

    # 计算误差并打印进度(每10000次迭代)
    l2_error = y - l2
    if iter % 10000 == 0:
        print(f"迭代{iter}次,平均误差:{np.mean(np.abs(l2_error)):.4f}")

    # 反向传播更新权重
    l2_delta = l2_error * nonlin(l2, deriv=True)
    l1_error = l2_delta.dot(syn1.T)
    l1_delta = l1_error * nonlin(l1, deriv=True)

    syn1 += l1.T.dot(l2_delta)
    syn0 += l0.T.dot(l1_delta)

print("\n训练后输出:")
print(l2)

效果说明

运行这段代码后,你会看到训练后的输出非常接近目标值[[0], [1], [1], [0]]。隐藏层的两个神经元会学习到不同的线性组合,再通过输出层的整合,就能实现你需要的先升后降的非线性映射。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:31:17