为什么 MLP 不能逼近一个封闭的形状函数?

人工智能 机器学习 喀拉斯 多层感知器 线性代数
2021-10-25 10:57:46

[TL;博士]

我在 2D 空间上生成了两个类 Red 和 Blue。红色是单位圆上的点,蓝色是具有半径限制 (3,4) 的圆环上的点。我尝试用不同数量的隐藏层训练多层感知器,所有隐藏层都有 2 个神经元。MLP 从未达到 100% 的准确度。我试图想象 MLP 如何用黑白对 2D 空间的点进行分类。这是我得到的最终图像:

在此处输入图像描述

起初,我期待 MLP 可以在 2D 空间上对 2 个类别进行分类,每个隐藏层有 2 个神经元,我期待看到一个白色圆圈包裹着红点,其余的是黑色空间。是否有(数学)原因,为什么 MLP 无法创建紧密的形状,而是它似乎在 2d 空间上从无穷大变为无穷大?(注意:如果我在每个隐藏层使用 3 个神经元,MLP 会很快成功)。

[笔记本风格]

我在 2D 空间上生成了两个类 Red 和 Blue。
红色是单位圆上的点

size_ = 200
classA_r = np.random.uniform(low = 0, high = 1, size = size_)
classA_theta = np.random.uniform(low = 0, high = 2*np.pi, size = size_)
classA_x = classA_r * np.cos(classA_theta)
classA_y = classA_r * np.sin(classA_theta)

和蓝色是具有半径限制 (3,4) 的圆环上的点。

classB_r = np.random.uniform(low = 2, high = 3, size = size_)
classB_theta = np.random.uniform(low = 0, high = 2*np.pi, size = size_)
classB_x = classB_r * np.cos(classB_theta)
classB_y = classB_r * np.sin(classB_theta)

我尝试用不同数量的隐藏层训练多层感知器,所有隐藏层都有 2 个神经元。

hidden_layers = 15
inputs = Input(shape=(2,))
dnn = inputs
for l_no in range(hidden_layers):
    dnn = Dense(2, activation='tanh', name = "layer_{}".format(l_no))(dnn)
outputs = Dense(2, activation='softmax', name = "layer_out")(dnn)

model = Model(inputs=inputs, outputs=outputs)

model.compile(optimizer='adam', loss='categorical_crossentropy', metrics='accuracy'])

MLP 从未达到 100% 的准确度。我试图想象 MLP 如何用黑白对 2D 空间的点进行分类。

limit = 4
step = 0.2
grid = []
x = -limit
while x <= limit:
    y = -limit
    while y <= limit:
        grid.append([x, y])
        y += step
    x += step
grid = np.array(grid)
prediction = model.predict(grid)

这是我得到的最终图像:

xs = []
ys = []
cs = []
for point in grid:
    xs.append(point[0])
    ys.append(point[1])
for pred in prediction:
    cs.append(pred[0])

plt.scatter(xs, ys, c = cs, s=70, cmap = 'gray')
plt.scatter(classA_x, classA_y, c = 'r', s= 50)
plt.scatter(classB_x, classB_y, c = 'b', s= 50)
plt.show()

在此处输入图像描述

起初,我期待 MLP 可以在 2D 空间上对 2 个类别进行分类,每个隐藏层有 2 个神经元,我期待看到一个白色圆圈包裹着红点,其余的是黑色空间。是否有(数学)原因,为什么 MLP 无法创建紧密的形状,而是它似乎在 2d 空间上从无穷大变为无穷大?(注意:如果我在每个隐藏层使用 3 个神经元,MLP 会很快成功)。

我所说的封闭形状是什么意思,看看第二张图像,它是通过在每一层使用 3 个神经元生成的:

for l_no in range(hidden_layers):
    dnn = Dense(3, activation='tanh', name = "layer_{}".format(l_no))(dnn)

在此处输入图像描述

[根据标记答案]

from keras import backend as K
def x_squared(x):
    x = K.abs(x) * K.abs(x)
    return x
hidden_layers = 3
inputs = Input(shape=(2,))
dnn = inputs
for l_no in range(hidden_layers):
    dnn = Dense(2, activation=x_squared, name = "layer_{}".format(l_no))(dnn)
outputs = Dense(2, activation='softsign', name = "layer_out")(dnn)
model.compile(optimizer='adam',
              loss='mean_squared_error',
              metrics=['accuracy'])

我得到:

在此处输入图像描述

1个回答

在神经网络中,函数族和它们可以为决策表面制作的形状取决于您使用的激活函数(在您的情况下,tanh或双曲正切)。

假设至少有一个隐藏层,则通用逼近定理适用。对任何给定函数的逼近程度受神经元数量的限制,而不是受激活函数选择的影响。然而,激活函数的选择仍然与近似值的好坏有关。当隐藏层中的神经元数量较少时,近似值与激活函数的性质密切相关。

在隐藏层中有一个神经元,您只能近似激活函数的一些仿射变换。其他较小的数字,例如 2、3 等,对于某些形状系列仍会显示出强烈的趋势。这在概念上与在傅里叶变换中使用有限数量的频率非常相似 - 如果您将自己限制为仅a1sin(x)+a2sin(2x)要逼近一个函数,那么您肯定会注意到任何输出中的正弦构造块。

我怀疑如果您将第一个隐藏层中的激活函数更改为f(x)=x2那么你可以得到一个很好的结果,每层有两个神经元。如果您随后使用该网络并尝试在简单的线性分割上对其进行训练,它将失败,总是会产生一些弯曲的封闭表面,尽可能地覆盖训练示例 - 与您在圆形中看到的相反的问题与 NN 相匹配的模式在整个过程中都有 tanh 激活。

关于使用的一件有趣的事情f(x)=x2是这是一个深思熟虑的选择(鉴于您如何构建示例的知识)将您的输入空间映射到可以线性分离示例的新空间。事实上,这似乎是多层 NN 中的层所学习的内容——每一层都将其输入空间逐步地映射到一个新空间,在该空间中,示例可以以线性方式更好地分离。