我正在尝试创建一个在神经元之间具有自定义连接的小型神经网络。如图所示,连接应该存在于多个层上,而不是完全连接(稀疏)。我还想手动而不是完全随机地进行权重初始化。我的目标是确定连接是积极的还是消极的。是否可以在 tensorflow (python/js) 或 pytorch 中创建这样的神经网络?
1 回答
总结一下:
你能做到吗?——是的,绝对的。
会好看吗?——不,绝对不是。
在我的解释中,我将进一步关注 PyTorch,因为这是我更熟悉的库,如果您有可以轻松地以 Python 方式表达的自定义操作,它尤其有用。Tensorflow 也有急切的执行模式(如果我没记错的话,从第 2 版开始更认真的集成),但它传统上是使用计算图完成的,这使得整个事情比它需要的更丑陋。
正如您希望知道的那样,反向传播(任何 ANN 中的“学习”步骤)基本上是通过网络的反向传递,以计算梯度,或者至少足够接近我们手头问题的真相。重要的是,torch
函数存储了这个“反向”方向,这使得用户调用反向传播函数变得微不足道。
要为您的图像中描述的简单网络建模,我们只有一个主要缺点:
可用的操作通常在他们正在做的事情上表现出色,因为它们很简单并且可以进行大量优化。在您的情况下,您必须将不同的层表示为自定义操作,这通常很难扩展,除非您可以将泛函表示为某种形式的矩阵操作,我在您的示例中没有直接看到。我进一步假设您正在应用某种形式的非线性,否则它将是一个网络,会因任何非线性可分问题而失败。
import torch
import torch.nn as nn
class CustomNetwork(nn.module):
def __init__(self):
self.h_1_1 = nn.Sequential(nn.Linear(1,2), nn.ReLU) # top node in first layer
self.h_1_2 = nn.Sequential(nn.Linear(1,2), nn.ReLU) # bottom node in first layer
# Note that these nodes have no shared weights, which is why we
# have to initialize separately.
self.h_2_1 = nn.Sequential(nn.Linear(1,1), nn.ReLU) # top node in second layer
self.h_2_2 = nn.Sequential(nn.Linear(1,1), nn.ReLU) # bottom node in second layer
self.h_2_1 = nn.Sequential(nn.Linear(2,1), nn.ReLU) # top node in third layer
self.h_2_2 = nn.Sequential(nn.Linear(2,1), nn.ReLU) # bottom node in third layer
# out doesn't require activation function due to pairing with loss function
self.out = nn.Linear(2,1)
def forward(self, x):
# x.shape: (batch_size, 2)
# first layer. shape of (batch_size, 2), respectively
out_top = self.h_1_1(x[:,0])
out_bottom = self.h_1_2(x[:,1])
# second layer. shape of (batch_size, 1), respectively
out_top_2 = self.h_2_1(out_top[:,0])
out_bottom_2 = self.h_2_2(out_bottom[:,0])
# third layer. shape of (batch_size, 1), respectively
# additional concatenation of previous outputs required.
out_top_3 = self.h_3_1(torch.cat([out_top_2, -1 * out_top[:,1]], dim=1))
out_bottom_3 = self.h_3_2(torch.cat([out_bottom_2, -1 * out_bottom[:,1]], dim=1))
return self.out(torch.cat([out_top_3, out_bottom_3], dim=1))
如您所见,任何计算步骤都是(在这种情况下相当明确地)给出的,并且很有可能。同样,一旦你想扩展每一层的神经元数量,你将不得不在处理方式上更有创意,但 for 循环在 PyTorch 中也做了很多工作。请注意,无论如何,这将比普通线性层慢得多。如果您可以使用单独训练的权重,您也可以始终只定义较小尺寸的单独线性层,并以更方便的方式放置它们。