Pytorch 预期步幅为单个整数值或1个值的列表,以匹配卷积维度,但获得步幅=[1,1]

Pytorch 预期步幅为单个整数值或1个值的列表,以匹配卷积维度,但获得步幅=[1,1],pytorch,Pytorch,我读了,但它似乎没有回答我的问题 所以基本上我正在尝试将游戏蛇矢量化,这样它可以跑得更快。 这是我到目前为止的代码: import torch import torch.nn.functional as F device = torch.device("cpu") class SnakeBoard: def __init__(self, board=None): if board != None: self.channels = board else:

我读了,但它似乎没有回答我的问题

所以基本上我正在尝试将游戏蛇矢量化,这样它可以跑得更快。 这是我到目前为止的代码:

import torch
import torch.nn.functional as F
device = torch.device("cpu")
class SnakeBoard:
  def __init__(self, board=None):
    if board != None:
      self.channels = board
    else:
      # 0 - Food, 1 - Head, 2 - Body
      self.channels = torch.zeros(1, 3, 15, 17,
                                  device=device)

      # Initialize game channels
      self.channels[:, 0, 7, 12] = 1
      self.channels[:, 1, 7, 5] = 1
      self.channels[:, 2, 7, 2:6] = torch.arange(1, 5)
    self.move()

  def move(self):
    self.channels[:, 2] -= 1
    F.relu(self.channels[:, 2], inplace=True)
    # Up movement test
    F.conv2d(self.channels[:, 1], torch.tensor([[[0,1,0],[0,0,0],[0,0,0]]]), padding=1)

SnakeBoard()
通道中的第一个维度表示批量大小,第二个维度表示蛇游戏的3个通道:食物、头部和身体,最后第三个和第四个维度表示棋盘的高度和宽度

不幸的是,在运行代码时,我得到了一个错误:期望步长为单个整数值或1个值的列表,以匹配卷积维度,但得到了步长=[1,1]


如何解决此问题?

卷积输入的尺寸对于二维卷积不正确。让我们看看您传递到的尺寸:

self.channels[:,1].size()
#=>火炬尺寸([1,15,17])
火炬张量([[0,1,0],[0,0,0],[0,0,0]])。大小()
#=>火炬尺寸([1,3,3])
正确的尺寸应该是

  • 输入:(批量大小、输入通道、高度、宽度)
  • 重量:(输出通道、输入通道、内核高度、内核宽度)
因为您的权重只有3个维度,所以它被认为是1D卷积,但由于您调用了
F.conv2d
,因此步幅和填充将是元组,因此它不起作用

对于为第二个维度编制索引的输入,该维度选择该维度上的特定元素并消除该维度。要保留该维度,可以仅使用一个元素的切片对其进行索引。 对于权重,您也缺少一个维度,可以直接添加。此外,您的权重类型为
torch.long
,因为您在张量创建中仅使用整数,但权重类型必须为
torch.float

F.conv2d(self.channels[:,1:2],torch.tensor([[[0,1,0],[0,0,0],[0,0,0]]],dtype=torch.float),padding=1)

另一方面,我不认为卷积适合这个用例,因为你没有使用卷积的一个关键属性,那就是捕捉周围环境。这些只是太多不必要的计算,无法实现你想要的,大多数都是0的乘法

例如,上移更容易通过移除第一行并在末尾添加一行新的零来实现,因此所有内容都上移(假设第一行是板的顶部,最后一行是板的底部)

head=self.channels[:,1:2]
批次尺寸、通道、高度、宽度=头部尺寸()
#除了头上的第一排,什么都拿
#通过在整个高度(尺寸2)上连接零,将一行零添加到端点
新的焊炬头=焊炬.cat([head[:,:,1:],焊炬.zero(批次尺寸,通道,1,宽度)],尺寸=2)
#或者如果你想把它包在黑板上,那就更简单了。
#将第一行移到末尾
缠绕头=火炬。猫([head[:,:,1:,head[:,:,0:1]],尺寸=2)

对于二维卷积,卷积输入的尺寸不正确。让我们看看您要传递到的尺寸:

self.channels[:,1].size()
#=>火炬尺寸([1,15,17])
火炬张量([[0,1,0],[0,0,0],[0,0,0]])。大小()
#=>火炬尺寸([1,3,3])
正确的尺寸应该是

  • 输入:(批量大小、输入通道、高度、宽度)
  • 重量:(输出通道、输入通道、内核高度、内核宽度)
因为您的权重只有3个维度,所以它被认为是1D卷积,但由于您调用了
F.conv2d
,因此步幅和填充将是元组,因此它不起作用

对于为第二个维度编制索引的输入,该维度选择该维度上的特定元素并消除该维度。要保留该维度,可以仅使用一个元素的切片对其进行索引。 对于权重,您也缺少一个维度,可以直接添加。此外,您的权重类型为
torch.long
,因为您在张量创建中仅使用整数,但权重类型必须为
torch.float

F.conv2d(self.channels[:,1:2],torch.tensor([[[0,1,0],[0,0,0],[0,0,0]]],dtype=torch.float),padding=1)

另一方面,我不认为卷积适合这个用例,因为你没有使用卷积的一个关键属性,那就是捕捉周围环境。这些只是太多不必要的计算,无法实现你想要的,大多数都是0的乘法

例如,上移更容易通过移除第一行并在末尾添加一行新的零来实现,因此所有内容都上移(假设第一行是板的顶部,最后一行是板的底部)

head=self.channels[:,1:2]
批次尺寸、通道、高度、宽度=头部尺寸()
#除了头上的第一排,什么都拿
#通过在整个高度(尺寸2)上连接零,将一行零添加到端点
新的焊炬头=焊炬.cat([head[:,:,1:],焊炬.zero(批次尺寸,通道,1,宽度)],尺寸=2)
#或者如果你想把它包在黑板上,那就更简单了。
#将第一行移到末尾
缠绕头=火炬。猫([head[:,:,1:,head[:,:,0:1]],尺寸=2)

谢谢,但是在效率方面,当使用GPU时,使用第二种删除和添加方法还是仅使用conv2d更快?第二种方法肯定更快,尤其是在环绕式情况下,所有数据都已在GPU上,只是视图发生了更改。但即使数据需要复制以在内存中保持连续,它仍然是l仅加载该数据,该数据也分配给卷积结果,但卷积需要使用3x3乘法(和和)计算每个元素