如何更改 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_channels
和 out_channels
之间的连接以及卷积到哪个,根据他们的文档:https://pytorch.org/docs/stable/generated/torch.nn.Conv2d.html.
您或许可以在您的模型中对其进行优化,或者以其他方式对其进行试验。
在任何情况下,简单地使用 Conv2D 的现有实现对您来说应该没问题。 Conv3D 通常用于 3 个空间维度,或有时 2 个空间维度和 1 个时间维度的情况。虽然您的情况有点像 3 个空间维度的有限版本,但就每个“像素”如何具有一些空间 relevance/correlation 而言,它不一定与流体流动的 3D 矢量场相同它的相邻“像素”。您的“空间像素”具有与此略有不同的相关性或相关性映射。
我正在尝试训练代理人玩 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_channels
和 out_channels
之间的连接以及卷积到哪个,根据他们的文档:https://pytorch.org/docs/stable/generated/torch.nn.Conv2d.html.
您或许可以在您的模型中对其进行优化,或者以其他方式对其进行试验。
在任何情况下,简单地使用 Conv2D 的现有实现对您来说应该没问题。 Conv3D 通常用于 3 个空间维度,或有时 2 个空间维度和 1 个时间维度的情况。虽然您的情况有点像 3 个空间维度的有限版本,但就每个“像素”如何具有一些空间 relevance/correlation 而言,它不一定与流体流动的 3D 矢量场相同它的相邻“像素”。您的“空间像素”具有与此略有不同的相关性或相关性映射。