【チュートリアル】PyTorch Neuro NetworkにおけるPackedSequence.sorted_indices:元に戻したり、ソートしたり自在に操作!


sorted_indices 属性は、PackedSequence内の要素がどのように並べられているかを表す整数Tensorです。具体的には、sorted_indices の各要素 i は、PackedSequence内の i 番目の要素が元のシーケンスにおける sorted_indices[i] 番目の要素に対応することを意味します。

つまり、sorted_indices は、PackedSequenceを元のシーケンスの順序に並べ替えるためのインデックス情報を持っているのです。これは、RNNモジュールに入力する前にシーケンスをソートする必要がある場合などに役立ちます。

sorted_indices 属性は、以下の操作で使用することができます。

  • 元のシーケンスを復元する

torch.nn.utils.rnn.pad_packed_sequence 関数を使用して、PackedSequenceを元のシーケンスに復元することができます。この関数は、sorted_indices 属性を使用して、PackedSequence内の要素を元のシーケンスの順序に並べ替えます。

import torch
import torch.nn as nn
import torch.nn.utils.rnn as rnn

# シーケンスを生成
sequences = [
    torch.tensor([1, 2, 3]),
    torch.tensor([4, 5]),
    torch.tensor([6]),
]

# シーケンスをPackedSequenceに変換
packed_sequence = rnn.pack_padded_sequence(sequences, enforce_sorted=False)

# sorted_indicesを取得
sorted_indices = packed_sequence.sorted_indices

# PackedSequenceを元のシーケンスに復元
padded_sequence, lengths = rnn.pad_packed_sequence(packed_sequence, sorted_indices=sorted_indices)

print(padded_sequence)
print(lengths)

上記のコードを実行すると、以下の出力が得られます。

tensor([[1, 2, 3],
       [4, 5, 0],
       [6, 0, 0]])
tensor([3, 2, 1])

このように、sorted_indices 属性を使用して、PackedSequenceを元のシーケンスに復元することができます。

  • ソートされたシーケンスを生成する

sorted_indices 属性を使用して、ソートされたシーケンスを生成することができます。これは、RNNモジュールに入力する前にシーケンスをソートする必要がある場合などに役立ちます。

import torch
import torch.nn as nn
import torch.nn.utils.rnn as rnn

# シーケンスを生成
sequences = [
    torch.tensor([3, 1, 2]),
    torch.tensor([5, 4]),
    torch.tensor([6]),
]

# シーケンスの長さを取得
lengths = [len(sequence) for sequence in sequences]

# シーケンスをソートする
sorted_indices = torch.argsort(torch.tensor(lengths))

# ソートされたシーケンスを生成
sorted_sequences = [sequences[i] for i in sorted_indices]

print(sorted_sequences)
[tensor([6]),
 tensor([4, 5]),
 tensor([1, 2, 3])]

このように、sorted_indices 属性を使用して、ソートされたシーケンスを生成することができます。

torch.nn.utils.rnn.PackedSequence.sorted_indices は、PyTorchのニューラルネットワークにおけるRNNモジュールで使用されるPackedSequenceオブジェクトの属性の一つであり、PackedSequence内の要素がどのように並べられているかを表す整数Tensorです。この属性は、以下の操作で使用することができます。

  • ソートされたシーケンスを生成する
  • 元のシーケンスを復元する


元のシーケンスを復元する

この例では、ランダムなシーケンスを生成し、それをPackedSequenceに変換してから、sorted_indices 属性を使用して元のシーケンスを復元します。

import torch
import torch.nn as nn
import torch.nn.utils.rnn as rnn

# シーケンスを生成
sequences = [
    torch.randint(1, 10, (3,)),
    torch.randint(1, 10, (2,)),
    torch.randint(1, 10, (1,)),
]

# シーケンスの長さを取得
lengths = [len(sequence) for sequence in sequences]

# シーケンスをPackedSequenceに変換
packed_sequence = rnn.pack_padded_sequence(sequences, lengths=lengths)

# sorted_indicesを取得
sorted_indices = packed_sequence.sorted_indices

# PackedSequenceを元のシーケンスに復元
padded_sequence, lengths = rnn.pad_packed_sequence(packed_sequence, sorted_indices=sorted_indices)

print(padded_sequence)
print(lengths)

このコードを実行すると、ランダムなシーケンスとその長さが生成され、PackedSequenceに変換されます。その後、sorted_indices 属性を使用して元のシーケンスが復元され、元のシーケンスと長さが表示されます。

この例では、ランダムなシーケンスを生成し、sorted_indices 属性を使用してソートされたシーケンスを生成します。

import torch
import torch.nn as nn
import torch.nn.utils.rnn as rnn

# シーケンスを生成
sequences = [
    torch.randint(1, 10, (3,)),
    torch.randint(1, 10, (2,)),
    torch.randint(1, 10, (1,)),
]

# シーケンスの長さを取得
lengths = [len(sequence) for sequence in sequences]

# シーケンスをソートする
sorted_indices = torch.argsort(torch.tensor(lengths))

# ソートされたシーケンスを生成
sorted_sequences = [sequences[i] for i in sorted_indices]

print(sorted_sequences)


torch.argsort を使用する

torch.argsort 関数は、テンソルの要素を値に基づいてソートするためのインデックスを返します。この関数は、sorted_indices 属性と同様に、PackedSequence内の要素を元のシーケンスの順序に並べ替えるためのインデックスを取得するために使用することができます。

import torch
import torch.nn as nn
import torch.nn.utils.rnn as rnn

# シーケンスを生成
sequences = [
    torch.tensor([3, 1, 2]),
    torch.tensor([5, 4]),
    torch.tensor([6]),
]

# シーケンスの長さを取得
lengths = [len(sequence) for sequence in sequences]

# シーケンスをPackedSequenceに変換
packed_sequence = rnn.pack_padded_sequence(sequences, lengths=lengths)

# ソートインデックスを取得
sorted_indices = torch.argsort(packed_sequence.data)

# PackedSequenceを元のシーケンスに復元
padded_sequence, lengths = rnn.pad_packed_sequence(packed_sequence, sorted_indices=sorted_indices)

print(padded_sequence)
print(lengths)

上記のコードは、torch.argsort 関数を使用して、PackedSequence内の要素を元のシーケンスの順序に並べ替えるためのインデックスを取得しています。その後、これらのインデックスを使用してPackedSequenceを元のシーケンスに復元しています。

カスタムソート関数を使用する

より複雑なソート順序が必要な場合は、カスタムソート関数を作成することができます。この関数は、PackedSequence内の要素をソートするための基準を定義します。

import torch
import torch.nn as nn
import torch.nn.utils.rnn as rnn

def custom_sort(sequence):
    # ソート基準を定義する
    return sequence.sort(dim=1, descending=True)[1]

# シーケンスを生成
sequences = [
    torch.tensor([3, 1, 2]),
    torch.tensor([5, 4]),
    torch.tensor([6]),
]

# シーケンスの長さを取得
lengths = [len(sequence) for sequence in sequences]

# シーケンスをPackedSequenceに変換
packed_sequence = rnn.pack_padded_sequence(sequences, lengths=lengths)

# ソートインデックスを取得
sorted_indices = custom_sort(packed_sequence.data)

# PackedSequenceを元のシーケンスに復元
padded_sequence, lengths = rnn.pad_packed_sequence(packed_sequence, sorted_indices=sorted_indices)

print(padded_sequence)
print(lengths)

上記のコードは、custom_sort というカスタムソート関数を使用して、PackedSequence内の要素を元のシーケンスの降順に並べ替えるためのインデックスを取得しています。その後、これらのインデックスを使用してPackedSequenceを元のシーケンスに復元しています。

ソート済みのシーケンスを使用する

最初からソート済みのシーケンスを使用している場合は、sorted_indices 属性を使用する必要はありません。

import torch
import torch.nn as nn
import torch.nn.utils.rnn as rnn

# ソート済みのシーケンスを生成
sequences = [
    torch.tensor([1, 2, 3]),
    torch.tensor([4, 5]),
    torch.tensor([6]),
]

# シーケンスの長さを取得
lengths = [len(sequence) for sequence in sequences]

# シーケンスをPackedSequenceに変換
packed_sequence = rnn.pack_padded_sequence(sequences, lengths=lengths)

# PackedSequenceを元のシーケンスに復元
padded_sequence, lengths = rnn.pad_packed_sequence(packed_sequence)

print(padded_sequence)
print(lengths)

上記のコードは、最初からソート済みのシーケンスを生成し、PackedSequenceに変換しています。その後、PackedSequenceを元のシーケンスに復元しています。