我的神经网络可以在分类时学习条件规则吗?

数据挖掘 神经网络 分类
2022-03-14 12:02:55

我担心我正在用我的神经网络尝试不可能的事情。这是场景:

我有一个 2D 方形世界。在其中,我创建了五个随机大小和位置的圆圈。然后,我根据以下规则将其中一个分类为正确答案:

  • 如果任何圆的半径> THRESHOLD,我选择最大的圆
  • 否则,我选择原点最靠近中心的圆

我将输入作为串行坐标发送,如下所示:[X0, Y0, RADIUS0, X1, Y1, RADIUS1, ...]。

输出是 one-hot 数组,例如 [0, 0, 1, 0, 0]。

我在 TensorFlow 中对此进行了建模,但没有成功。我最好的得分结果似乎总是选择最大的圆圈,而忽略了任意规则的 else 子句。

我是否从根本上误解了神经网络的能力?我已经尝试了许多(许多)不同的配置(层数、节点数、激活函数......你说的)。到目前为止,我所有的网络都是前馈的。

提前感谢您的任何见解!


以下是我的网络和数据的一些详细信息:

  • 我已经尝试了多达 50 万个案例。我在训练后将 10% 用于泛化检查,并以 50/50 的验证拆分对剩余的 90% 进行训练。
  • 我已经尝试使用对规则 A、50/50 和 75% 对规则 B 加权 75% 的测试数据。
  • 我尝试了 0-10 个隐藏层,神经元数量从 2 到 256(每个隐藏层的神经元数量相同)。
  • 我会在时间允许的情况下更改时期数,但通常为 10-100。我最长的运行时间是几个小时(有大量的案例数量,并且为了防止过度拟合而辍学)。
  • 我使用了 1-50 的批量大小。
  • 我尝试了 0.0001 - 0.1 的学习率。
  • 我目前正在使用 ReLU 激活,将偏差初始化为 const(0.1) 和带有 heNormal 的内核。我已经为这三种方法尝试了其他几种方法。
  • 我将输入标准化为以零为中心,方差为一。
  • 损失函数是分类交叉熵。
  • 优化器是亚当。
4个回答

将数据集中在零上并缩放到一的方差有助于解决许多分类问题,但在这种情况下,它会删除我理解的解决问题所需的信息。

另一个可能的问题是损失函数,您在问题中根本没有提到。当你的神经网络只学习两个规则之一时,我会建议一些保持相当高的东西。

好的,我写了一些代码来模拟你的问题。我发现了同样的问题,因此简化了问题。当我修改标签函数以始终选择最大半径而不考虑任意规则时,我发现它仍然无法计算出来,而是会收敛到预测 5 个圆中的每一个的 0.2。看来,如果您不在输入处对圆圈进行排序,则网络无法区分它们。如果您考虑通过密集连接的网络的流量,这是有道理的。如果我们在输入之前尝试对圆圈进行排序,可能会取得一些成功。

import numpy as np
from tqdm import tqdm

N_CIRCLES = 5
CENTRE_RANGE = 1
RMIN, RMAX = 0.1, 0.5
THRESHOLD = 0.45

def label(x):
    # If above threshold, then choose largest circle
    if np.any(x[:5] > THRESHOLD):
        return np.argmax(x[:5])
    
    # Else, choose the circle nearest to (0, 0)
    return np.argmax([np.linalg.norm(x[i:i+2]) for i in range(N_CIRCLES, 3*N_CIRCLES, 2)])

def generate_sample():
    # {r0, r1, r2, r3, r4, x0, y0, x1, y1, x2, y2, x3, y3, x4, y4}
    x = np.concatenate((np.random.uniform(RMIN, RMAX, N_CIRCLES), 
                        np.random.uniform(-CENTRE_RANGE, CENTRE_RANGE, 2*N_CIRCLES)))
    
    return x, label(x)

def generate_samples(n):
    x = np.zeros((n, N_CIRCLES*3))
    y = np.zeros(n)
    
    for i in range(n):
        x[i], y[i] = generate_sample()
    
    return x, y

import torch
import torch.nn as nn
import torch.nn.functional as F

class Net(nn.Module):
    def __init__(self):
        super().__init__()
        # Kernel size 5
        self.fc1 = nn.Linear(3*N_CIRCLES, 32)
        self.fc2 = nn.Linear(32, 64)
        self.fc3 = nn.Linear(64, N_CIRCLES)
        
    def forward(self, x):
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = F.relu(self.fc3(x))
        return F.softmax(x, dim=1)
    
net = Net()

import torch.optim as optim

optimizer = optim.Adam(net.parameters(), lr=0.001)
loss_function = nn.MSELoss()

BATCH_SIZE = 100
EPOCHS = 1_000

losses = []
for epoch in tqdm(range(EPOCHS)):
    X, y = generate_samples(BATCH_SIZE)
    y = np.array(y, dtype=int)

    ohe = np.zeros((y.size, y.max()+1))
    ohe[np.arange(y.size), y] = 1
    
    X = torch.Tensor(X).view(-1, 3*N_CIRCLES)
    y = torch.Tensor(ohe)

    net.zero_grad()
    yhat = net(X)
    loss = loss_function(yhat, y)
    loss.backward()
    optimizer.step()
    
    losses.append(float(loss.detach().numpy()))    
    
import matplotlib.pyplot as plt
%matplotlib inline
import seaborn as sns 

fig, ax = plt.subplots(figsize=(20, 10))
ax.plot(losses)
plt.show()
```

是的,他们绝对可以“学习”条件规则。

事实证明我在激活函数中有一个错误,我(最终)让这个网络来学习这个问题。它学得非常好,而且很快。令人惊奇的事情,这些神经网络 :) 非常感谢那些回答和评论的人!

是的,通用逼近定理指出,神经网络可以学习中具有一个隐藏层和有限数量的具有非线性激活函数的神经元的任何函数。训练网络可能会出现很多问题,例如,您是否尝试过绘制其性能随时间变化的图表并查看它是否正在收敛?Rn