web-dev-qa-db-ja.com

テンソルとして与えられたインデックスから1つのホットベクトルを作成する

サイズ4 x 6のテンソルがあります。4はバッチサイズ、6はシーケンスの長さです。シーケンスベクトルのすべての要素は、いくつかのインデックス(0〜n)です。 4 x 6 x nテンソルを作成します。3次元のベクトルは、インデックスの1つのホットエンコーディングになります。つまり、指定したインデックスに1を入れ、残りの値はゼロにします。

たとえば、次のテンソルがあります。

[[5, 3, 2, 11, 15, 15],
[1, 4, 6, 7, 3, 3],
[2, 4, 7, 8, 9, 10],
[11, 12, 15, 2, 5, 7]]

ここでは、すべての値が(0からn)の間(n = 15)にあります。したがって、テンソルを4 X 6 X 16テンソルに変換します。ここで、3番目の次元は1つのホットエンコーディングベクトルを表します。

PyTorch機能を使用してどうすればよいですか?現在、私はこれをループで行っていますが、ループを避けたいです!

13
Wasi Ahmad

NEW ANSWER PyTorch 1.1以降、one_hot関数torch.nn.functional。インデックスのテンソルindicesと最大インデックスnを指定すると、次のようにone_hotバージョンを作成できます。

n = 5
indices = torch.randint(0,n, size=(4,7))
one_hot = torch.nn.functional.one_hot(indices, n) # size=(4,7,n)

非常に古い回答

現時点では、スライスとインデックス作成は、私の経験からPyTorchで少し苦痛になる可能性があります。テンソルをnumpy配列に変換したくないと思います。現時点で私が考えることができる最もエレガントな方法は、疎なテンソルを使用してから密なテンソルに変換することです。それは次のように機能します:

from torch.sparse import FloatTensor as STensor

batch_size = 4
seq_length = 6
feat_dim = 16

batch_idx = torch.LongTensor([i for i in range(batch_size) for s in range(seq_length)])
seq_idx = torch.LongTensor(list(range(seq_length))*batch_size)
feat_idx = torch.LongTensor([[5, 3, 2, 11, 15, 15], [1, 4, 6, 7, 3, 3],                            
                             [2, 4, 7, 8, 9, 10], [11, 12, 15, 2, 5, 7]]).view(24,)

my_stack = torch.stack([batch_idx, seq_idx, feat_idx]) # indices must be nDim * nEntries
my_final_array = STensor(my_stack, torch.ones(batch_size * seq_length), 
                         torch.Size([batch_size, seq_length, feat_dim])).to_dense()    

print(my_final_array)

注:PyTorchは現在いくつかの作業を行っており、今後2〜3週間以内に派手なスタイルの放送やその他の機能が追加され、その他の機能も追加されます。したがって、それは可能です。近い将来、より良いソリューションが利用可能になるでしょう。

これが少し役立つことを願っています。

13
mexmex

私が見つけた最も簡単な方法。ここで、xは数値のリストで、class_countはクラスの数です。

def one_hot(x, class_count):
    return torch.eye(class_count)[x,:]

次のように使用します。

x = [0,2,5,4]
class_count = 8
one_hot(x,class_count)
tensor([[1., 0., 0., 0., 0., 0., 0., 0.],
        [0., 0., 1., 0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0., 1., 0., 0.],
        [0., 0., 0., 0., 1., 0., 0., 0.]])


8
ege ozsoy

これは、PyTorchオブジェクトのインプレースscatter_メソッドを使用してTensorで実行できます。

labels = torch.LongTensor([[[2,1,0]], [[0,1,0]]]).permute(0,2,1) # Let this be your current batch
batch_size, k, _ = labels.size()
labels_one_hot = torch.FloatTensor(batch_size, k, num_classes).zero_()
labels_one_hot.scatter_(2, labels, 1)

num_classes=3(インデックスは[0,3)とは異なる必要があります)の場合、これにより

(0 ,.,.) = 
  0  0  1
  0  1  0
  1  0  0
(1 ,.,.) = 
  1  0  0
  0  1  0
  1  0  0
[torch.FloatTensor of size 2x3x3]

labelstorch.LongTensorである必要があります。

PyTorchドキュメントリファレンス: torch.Tensor.scatter _

3
activatedgeek