Torch:如何按行对张量进行洗牌?

Posted

技术标签:

【中文标题】Torch:如何按行对张量进行洗牌?【英文标题】:Torch: How to shuffle a tensor by its rows? 【发布时间】:2017-11-28 00:40:00 【问题描述】:

我目前正在使用 torch 对一些输入数据实施随机洗牌(在行上,在这种情况下为第一个维度)。我是torch新手,所以在弄清楚排列如何工作时遇到了一些麻烦..

以下内容应该对数据进行洗牌:

if argshuffle then 
    local perm = torch.randperm(sids:size(1)):long()
    print("\n\n\nSize of X and y before")
    print(X:view(-1, 1000, 128):size())
    print(y:size())
    print(sids:size())
    print("\nPerm size is: ")
    print(perm:size())
    X = X:view(-1, 1000, 128)[perm,,]
    y = y[perm,]
    print(sids[1, ])
    sids = sids[perm,]
    print(sids[1, ])
    print(X:size())
    print(y:size())
    print(sids:size())
    os.exit(69)
end

打印出来

Size of X and y before 
99 
1000
128
[torch.LongStorage of size 3]

99 
1
[torch.LongStorage of size 2]

99 
1
[torch.LongStorage of size 2]

Perm size is: 
99 
[torch.LongStorage of size 1]
5
[torch.LongStorage of size 1x1]
5
[torch.LongStorage of size 1x1]


99 
1000
128
[torch.LongStorage of size 3]

99 
1
[torch.LongStorage of size 2]

99 
1
[torch.LongStorage of size 2]

超出值,我可以暗示该函数没有对数据进行洗牌。我怎样才能让它正确洗牌,lua/torch中的常见解决方案是什么?

【问题讨论】:

好吧,我编辑了我的答案,如果它回答了你的问题,请告诉我:) 【参考方案1】:

我也遇到了类似的问题。在文档中,张量没有随机播放功能(有dataset loaders)。我使用torch.randperm 找到了解决该问题的方法。

>>> a=torch.rand(3,5)
>>> print(a)
tensor([[0.4896, 0.3708, 0.2183, 0.8157, 0.7861],
        [0.0845, 0.7596, 0.5231, 0.4861, 0.9237],
        [0.4496, 0.5980, 0.7473, 0.2005, 0.8990]])
>>> # Row shuffling
... 
>>> a=a[torch.randperm(a.size()[0])]
>>> print(a)
tensor([[0.4496, 0.5980, 0.7473, 0.2005, 0.8990],
        [0.0845, 0.7596, 0.5231, 0.4861, 0.9237],
        [0.4896, 0.3708, 0.2183, 0.8157, 0.7861]])
>>> # column shuffling
... 
>>> a=a[:,torch.randperm(a.size()[1])]
>>> print(a)
tensor([[0.2005, 0.7473, 0.5980, 0.8990, 0.4496],
        [0.4861, 0.5231, 0.7596, 0.9237, 0.0845],
        [0.8157, 0.2183, 0.3708, 0.7861, 0.4896]])

我希望它能回答这个问题!

【讨论】:

【参考方案2】:

一个直接的解决方案是使用置换矩阵(那些在线性代数中常见的矩阵)。由于您似乎对 3d 案例感兴趣,我们必须先展平您的 3d 张量。所以,这是我想出的示例代码(即用型)

data=torch.floor(torch.rand(5,3,2)*100):float()
reordered_data=data:view(5,-1)

perm=torch.randperm(5);
perm_rep=torch.repeatTensor(perm,5,1):transpose(1,2)

indexes=torch.range(1,5);
indexes_rep=torch.repeatTensor(indexes,5,1)

permutation_matrix=indexes_rep:eq(perm_rep):float()
permuted=permutation_matrix*reordered_data

print("perm")
print(perm)
print("before permutation")
print(data)
print("after permutation")
print(permuted:view(5,3,2))

正如您将在一次执行中看到的那样,它根据perm 中给出的行索引对张量data 重新排序。

【讨论】:

你能否在你的代码中给出一些关于每个语句在做什么的cmets。我正在尝试在 numpy 中实现相同的功能,而我在 pytorch 中没有背景。【参考方案3】:
dim = 0
idx = torch.randperm(t.shape[dim])

t_shuffled = t[idx]

如果您的张量是例如形状为 CxNxF(按行按特征的通道),然后您可以像这样沿第二维随机播放:

dim=1
idx = torch.randperm(t.shape[dim])

t_shuffled = t[:,idx]

【讨论】:

【参考方案4】:

根据您的语法,我假设您正在使用 lua 而不是 PyTorch 来进行火炬传递。 torch.Tensor.index 是你的函数,它的工作原理如下:

x = torch.rand(4, 4)
p = torch.randperm(4)
print(x)
print(p)
print(x:index(1,p:long())

【讨论】:

以上是关于Torch:如何按行对张量进行洗牌?的主要内容,如果未能解决你的问题,请参考以下文章

如何按行对数据进行排序? [MYSQL]

如何在 C# 中使用 Random 类对数组进行洗牌 [重复]

如何对数据进行物理分区以避免 Spark SQL 连接中的洗牌

SQL - 按行对排序

如何洗牌 List<T; 中的元素?

在 n log n 时间内洗牌链表的算法