Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/307.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python PyTorch-连续()做什么?_Python_Memory_Pytorch_Contiguous - Fatal编程技术网

Python PyTorch-连续()做什么?

Python PyTorch-连续()做什么?,python,memory,pytorch,contiguous,Python,Memory,Pytorch,Contiguous,我在github上浏览了这个LSTM语言模型的示例。 我很清楚它的作用。但是我仍然在努力理解调用continuous()做了什么,这在代码中发生了好几次 例如,在代码输入的第74/75行中,创建了LSTM的目标序列。 数据(存储在ids中)是二维的,其中第一个维度是批次大小 范围内的i(0,ID.大小(1)-序号长度,序号长度): #获取批量输入和目标 输入=变量(ID[:,i:i+序列长度]) targets=变量(id[:,(i+1):(i+1)+序列长度].连续() 因此,作为一个简单的

我在github上浏览了这个LSTM语言模型的示例。 我很清楚它的作用。但是我仍然在努力理解调用
continuous()
做了什么,这在代码中发生了好几次

例如,在代码输入的第74/75行中,创建了LSTM的目标序列。 数据(存储在
ids
中)是二维的,其中第一个维度是批次大小

范围内的i(0,ID.大小(1)-序号长度,序号长度):
#获取批量输入和目标
输入=变量(ID[:,i:i+序列长度])
targets=变量(id[:,(i+1):(i+1)+序列长度].连续()
因此,作为一个简单的例子,当使用批量大小1和
seq_length
10
输入和
目标时,如下所示:

输入变量包含:
0     1     2     3     4     5     6     7     8     9
[尺寸为1x10的火炬式传感器]
目标变量包含:
1     2     3     4     5     6     7     8     9    10
[尺寸为1x10的火炬式传感器]
所以一般来说,我的问题是,
contracting()
做什么?为什么我需要它

此外,我不明白为什么对目标序列而不是输入序列调用该方法,因为这两个变量都由相同的数据组成

目标
如何是非连续的,而
输入
如何仍然是连续的


编辑:

我试图省去调用
continuous()
,但这会导致计算丢失时出现错误消息

RuntimeError:无效参数1:输入在…/src/torch/lib/TH/generic/THTensor处不连续。c:231
因此,显然在本例中调用
continuous()
是必要的。

来自:

连续()→ 张量
返回包含与self相同数据的连续张量
张量。如果自张量是连续的,则此函数返回自张量
张量


其中
continuous
在这里不仅指内存中的连续,还指内存中与索引顺序相同的顺序:例如,如果应用
continuous()的话,进行转置不会更改内存中的数据,它只会更改从索引到内存指针的映射
它将更改内存中的数据,使从索引到内存位置的映射成为规范映射。

与前面的答案一样,contigous()分配contigous内存块,当我们在<强> >张量到C或C++后端代码< /强>时,它会有帮助,其中张量是强>作为指针< /强>

< P> PyTorch上张量有一些操作,它不改变张量的内容,而是改变数据组织的方式。这些行动包括:

shown()
view()
expand()
transpose()

例如:当调用
transpose()
时,PyTorch不会生成具有新布局的新张量,它只是修改张量对象中的元信息,以便偏移和跨步描述所需的新形状。在本例中,转置张量和原始张量共享相同的内存:

x=torch.randn(3,2)
y=火炬转置(x,0,1)
x[0,0]=42
打印(y[0,0])
#印刷品42
这就是连续概念的由来。在上面的例子中,
x
是连续的,但
y
不是连续的,因为它的内存布局不同于从头开始制作的相同形状的张量。请注意,“连续”一词有点误导,因为它不是张量的内容分布在断开连接的内存块周围。这里字节仍然分配在一个内存块中,但元素的顺序不同

当您调用
continuous()
时,它实际上复制了张量,使其元素在内存中的顺序与使用相同数据从头开始创建的顺序相同

通常你不需要担心这个。通常,您可以安全地假设一切正常,并等待出现
运行时错误:输入不是连续的
,PyTorch希望一个连续的张量添加对
连续()
张量的调用。continuous()将创建张量的副本,副本中的元素将以连续方式存储在内存中。 当我们首先转置一个张量,然后对它进行整形(查看)时,通常需要使用continuous()函数。首先,让我们创建一个连续张量:

aaa = torch.Tensor( [[1,2,3],[4,5,6]] )
print(aaa.stride())
print(aaa.is_contiguous())
#(3,1)
#True
stride()返回(3,1)意味着:当沿着第一维度每一步(一行一行)移动时,我们需要在内存中移动3步。当沿着第二维度移动时(逐列),我们需要在内存中移动一步。这表明张量中的元素是连续存储的

现在我们尝试将come函数应用于张量:

bbb = aaa.transpose(0,1)
print(bbb.stride())
print(bbb.is_contiguous())

#(1, 3)
#False


ccc = aaa.narrow(1,1,2)   ## equivalent to matrix slicing aaa[:,1:3]
print(ccc.stride())
print(ccc.is_contiguous())

#(3, 1)
#False


ddd = aaa.repeat(2,1)   # The first dimension repeat once, the second dimension repeat twice
print(ddd.stride())
print(ddd.is_contiguous())

#(3, 1)
#True


## expand is different from repeat.
## if a tensor has a shape [d1,d2,1], it can only be expanded using "expand(d1,d2,d3)", which
## means the singleton dimension is repeated d3 times
eee = aaa.unsqueeze(2).expand(2,3,3)
print(eee.stride())
print(eee.is_contiguous())

#(3, 1, 0)
#False


fff = aaa.unsqueeze(2).repeat(1,1,8).view(2,-1,2)
print(fff.stride())
print(fff.is_contiguous())

#(24, 2, 1)
#True
好的,我们可以发现transpose()、shown()和tensor切片以及expand()将使生成的张量不连续。有趣的是,repeat()和view()并没有使其不连续。现在的问题是:如果我使用不连续张量会发生什么?

答案是view()函数不能应用于不连续张量。这可能是因为view()需要连续存储张量,以便它可以在内存中进行快速重塑。e、 g:

bbb.view(-1,3)
我们将得到错误信息:

---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-63-eec5319b0ac5> in <module>()
----> 1 bbb.view(-1,3)

RuntimeError: invalid argument 2: view size is not compatible with input tensor's size and stride (at least one dimension spans across two contiguous subspaces). Call .contiguous() before .view(). at /pytorch/aten/src/TH/generic/THTensor.cpp:203

从我的理解来看,这是一个更概括的答案:

连续是一个术语,用于表示张量的内存布局与其公布的元数据或形状信息不一致

在我看来,“连续”一词是一个容易混淆/误导的术语,因为在正常上下文中,它的意思是当内存没有分散在断开连接的块中时(即其“连续/连接/连续”)

对于某些操作,某些操作可能需要此连续属性
bbb.contiguous().view(-1,3)
#tensor([[1., 4., 2.],
        [5., 3., 6.]])
        # normal lstm([loss, grad_prep, train_err]) = lstm(xn)
        n_learner_params = xn_lstm.size(1)
        (lstmh, lstmc) = hs[0] # previous hx from first (standard) lstm i.e. lstm_hx = (lstmh, lstmc) = hs[0]
        if lstmh.size(1) != xn_lstm.size(1): # only true when prev lstm_hx is equal to decoder/controllers hx
            # make sure that h, c from decoder/controller has the right size to go into the meta-optimizer
            expand_size = torch.Size([1,n_learner_params,self.lstm.hidden_size])
            lstmh, lstmc = lstmh.squeeze(0).expand(expand_size).contiguous(), lstmc.squeeze(0).expand(expand_size).contiguous()
        lstm_out, (lstmh, lstmc) = self.lstm(input=xn_lstm, hx=(lstmh, lstmc))
RuntimeError: rnn: hx is not contiguous

x = torch.randn(3,2)
y = x.transpose(0, 1)
y.view(6) # RuntimeError: view size is not compatible with input tensor's size and stride (at least one dimension spans across two contiguous subspaces). Use .reshape(...) instead.
  
x = torch.randn(3,2)
y = x.transpose(0, 1)
y.reshape(6)

x = torch.randn(3,2)
y = x.transpose(0, 1)
y.contiguous().view(6)
import torch
x = torch.randn(3,2)
y = x.transpose(0, 1) # flips two axes
print("\ntranspose")
print(x)
print(y)
contiguous(y)
samestorage(x,y)

print("\nnarrow")
x = torch.randn(3,2)
y = x.narrow(0, 1, 2) #dim, start, len  
print(x)
print(y)
contiguous(y)
samestorage(x,y)

print("\npermute")
x = torch.randn(3,2)
y = x.permute(1, 0) # sets the axis order
print(x)
print(y)
contiguous(y)
samestorage(x,y)

print("\nview")
x = torch.randn(3,2)
y=x.view(2,3)
print(x)
print(y)
contiguous(y)
samestorage(x,y)

print("\nreshape")
x = torch.randn(3,2)
y = x.reshape(6,1)
print(x)
print(y)
contiguous(y)
samestorage(x,y)

print("\nflip")
x = torch.randn(3,2)
y = x.flip(0)
print(x)
print(y)
contiguous(y)
samestorage(x,y)

print("\nexpand")
x = torch.randn(3,2)
y = x.expand(2,-1,-1)
print(x)
print(y)
contiguous(y)
samestorage(x,y)