如何更改 Pytorch 模型以使用 3d 输入而不是 2d 输入?

How to change Pytorch model to work with 3d input instead 2d input?

我正在尝试训练代理人玩 Connect4 游戏。我找到了一个如何训练它的例子。板的表示是 1x6x7 数组:

[[[0 0 0 0 0 0 0]
  [0 0 0 0 0 0 0]
  [0 0 0 0 0 0 0]
  [0 0 0 0 0 0 0]
  [0 0 0 0 0 0 2]
  [0 0 0 0 0 0 1]]]

使用了这个神经网络架构:

class Net(BaseFeaturesExtractor):
    def __init__(self, observation_space: gym.spaces.Box, features_dim: int = 256):
        super(Net, self).__init__(observation_space, features_dim)
        # We assume CxHxW images (channels first)
        # Re-ordering will be done by pre-preprocessing or wrapper
        n_input_channels = observation_space.shape[0]
        self.cnn = nn.Sequential(
            nn.Conv2d(n_input_channels, 32, kernel_size=3, stride=1, padding=1),
            nn.ReLU(),
            nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1),
            nn.ReLU(),
            nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=0),
            nn.ReLU(),
            nn.Flatten(),
        )

        # Compute shape by doing one forward pass
        with th.no_grad():
            n_flatten = self.cnn(th.as_tensor(observation_space.sample()[None]).float()).shape[1]

        self.linear = nn.Sequential(nn.Linear(n_flatten, features_dim), nn.ReLU())

    def forward(self, observations: th.Tensor) -> th.Tensor:
        return self.linear(self.cnn(observations))

它在随机移动的智能体 2 的游戏中得分还不错:

Agent 1 Win Percentage: 0.59 
Agent 2 Win Percentage: 0.38 
Number of Invalid Plays by Agent 1: 3 
Number of Invalid Plays by Agent 2: 0
Number of Draws (in 100 game rounds): 0

Here 建议将 3 层表示作为改进代理的方法之一:

我已经尝试实现它,这是板的新 3 层表示的示例:

[[[0 0 0 0 0 0 0]
  [0 0 0 0 0 0 0]
  [0 0 0 0 0 0 0]
  [0 0 0 0 0 0 0]
  [0 0 0 0 0 0 0]
  [0 0 0 0 0 0 1]]

 [[0 0 0 0 0 0 0]
  [0 0 0 0 0 0 0]
  [0 0 0 0 0 0 0]
  [0 0 0 0 0 0 0]
  [0 0 0 0 0 0 1]
  [0 0 0 0 0 0 0]]

 [[0 0 0 0 0 0 0]
  [0 0 0 0 0 0 0]
  [0 0 0 0 0 0 0]
  [0 0 0 0 0 0 1]
  [0 0 0 0 0 0 0]
  [1 1 1 1 1 1 0]]]

当我 运行 使用当前的神经网络架构时,代理无法正确训练:

Agent 1 Win Percentage: 0.0
Agent 2 Win Percentage: 0.0
Number of Invalid Plays by Agent 1: 100
Number of Invalid Plays by Agent 2: 0
Number of Draws (in 100 game rounds): 0

Here你可以看到我的代码。

正如你现在看到的,我有 3 层而不是一层。这就是我尝试使用 Conv3d 的原因:

class Net(BaseFeaturesExtractor):
    def __init__(self, observation_space: gym.spaces.Box, features_dim: int = 256):
        super(Net, self).__init__(observation_space, features_dim)
        # We assume CxHxW images (channels first)
        # Re-ordering will be done by pre-preprocessing or wrapper
        n_input_channels = observation_space.shape[0]
        self.cnn = nn.Sequential(
            nn.Conv3d(n_input_channels, 32, kernel_size=3, stride=1, padding=1),
            nn.ReLU(),
            nn.Conv3d(32, 64, kernel_size=3, stride=1, padding=1),
            nn.ReLU(),
            nn.Conv3d(64, 128, kernel_size=3, stride=1, padding=0),
            nn.ReLU(),
            nn.Flatten(),
        )

        # Compute shape by doing one forward pass
        with th.no_grad():
            n_flatten = self.cnn(th.as_tensor(observation_space.sample()[None]).float()).shape[1]

        self.linear = nn.Sequential(nn.Linear(n_flatten, features_dim), nn.ReLU())

当我尝试 运行 这段代码时,它显示了这个错误:

RuntimeError: Expected 5-dimensional input for 5-dimensional weight [32, 1, 3, 3, 3], but got 4-dimensional input of size [1, 3, 6, 7] instead

我的问题:如何使用具有 3x6x7 形状输入的 Conv3D 层?

Shai 的评论是正确的。您不需要在这里使用 Conv3D 层。通过将至少 1 个维度减少到小于 1,您的 Conv3D 过滤器的形状将违反应用卷积过滤器后的大小计算,这就是您收到错误的原因(您不能使用不存在的值进行倍增) .

只需使用原始模型实现即可。

与具有 3 个色带的图像类似,这些图像通常不使用 Conv3d 进行处理(高光谱图像的情况可能不同,但这与此处无关)。有一些关于如何处理每个色带的讨论,您可以通过多种方式影响它。

例如,在实例化时调整 Conv2D 层的 groups 参数将改变层的 in_channelsout_channels 之间的连接以及卷积到哪个,根据他们的文档:https://pytorch.org/docs/stable/generated/torch.nn.Conv2d.html.

您或许可以在您的模型中对其进行优化,或者以其他方式对其进行试验。

在任何情况下,简单地使用 Conv2D 的现有实现对您来说应该没问题。 Conv3D 通常用于 3 个空间维度,或有时 2 个空间维度和 1 个时间维度的情况。虽然您的情况有点像 3 个空间维度的有限版本,但就每个“像素”如何具有一些空间 relevance/correlation 而言,它不一定与流体流动的 3D 矢量场相同它的相邻“像素”。您的“空间像素”具有与此略有不同的相关性或相关性映射。