如何在 tensorflow 或 pytorch 中创建具有自定义权重初始化的自定义神经网络
How to create custom neural network with custom weight initialization in tensorflow or pytorch
我正在尝试创建一个在神经元之间具有自定义连接的小型神经网络。连接应该存在于多个层上,而不是完全连接(稀疏),如图所示。我还想手动而不是完全随机地进行权重初始化。我的目标是确定连接是正面的还是负面的。是否可以在 tensorflow (python/js) 或 pytorch 中创建这样的神经网络?
总结一下:
你可以做到吗? -- 是,绝对。
会变漂亮吗? -- 没有,绝对没有。
在我的解释中,我将进一步关注 PyTorch,因为这是我更熟悉的库,如果您有可以轻松地以 pythonic 方式表达的自定义操作,它尤其有用。 Tensorflow 也有急切的执行模式(如果我没记错的话,从版本 2 开始更严格的集成),但它传统上是用计算图完成的,这使得整个事情比它需要的更丑陋。
正如您所希望知道的那样,反向传播(任何 ANN 中的 "learning" 步骤)基本上是通过网络的反向传递,以计算梯度,或者至少足够接近我们手头问题的真相。重要的是,torch
函数存储了这个 "reverse" 方向,这使得用户调用反向传播函数变得微不足道。
要对图片中描述的简单网络进行建模,我们只有一个主要缺点:
可用的操作通常在它们正在做的事情上表现出色,因为它们 简单 并且可以进行大量优化。在您的情况下,您必须将不同的层表示为自定义操作,这通常很难扩展,除非您可以将功能表示为某种形式的矩阵操作,我在您的示例中并没有直接看到。我进一步假设您正在应用某种形式的非线性,否则它将是一个 would fail for any non-linearly separable problem.
的网络
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 中也做很多工作。请注意,这在任何情况下都会比普通线性层慢得多,尽管如此。
如果您可以接受单独训练的权重,您也可以随时定义较小尺寸的单独线性层并将它们放在更方便的方式中。
我正在尝试创建一个在神经元之间具有自定义连接的小型神经网络。连接应该存在于多个层上,而不是完全连接(稀疏),如图所示。我还想手动而不是完全随机地进行权重初始化。我的目标是确定连接是正面的还是负面的。是否可以在 tensorflow (python/js) 或 pytorch 中创建这样的神经网络?
总结一下:
你可以做到吗? -- 是,绝对。
会变漂亮吗? -- 没有,绝对没有。
在我的解释中,我将进一步关注 PyTorch,因为这是我更熟悉的库,如果您有可以轻松地以 pythonic 方式表达的自定义操作,它尤其有用。 Tensorflow 也有急切的执行模式(如果我没记错的话,从版本 2 开始更严格的集成),但它传统上是用计算图完成的,这使得整个事情比它需要的更丑陋。
正如您所希望知道的那样,反向传播(任何 ANN 中的 "learning" 步骤)基本上是通过网络的反向传递,以计算梯度,或者至少足够接近我们手头问题的真相。重要的是,torch
函数存储了这个 "reverse" 方向,这使得用户调用反向传播函数变得微不足道。
要对图片中描述的简单网络进行建模,我们只有一个主要缺点:
可用的操作通常在它们正在做的事情上表现出色,因为它们 简单 并且可以进行大量优化。在您的情况下,您必须将不同的层表示为自定义操作,这通常很难扩展,除非您可以将功能表示为某种形式的矩阵操作,我在您的示例中并没有直接看到。我进一步假设您正在应用某种形式的非线性,否则它将是一个 would fail for any non-linearly separable problem.
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 中也做很多工作。请注意,这在任何情况下都会比普通线性层慢得多,尽管如此。 如果您可以接受单独训练的权重,您也可以随时定义较小尺寸的单独线性层并将它们放在更方便的方式中。