【100 PyTorch exercises】 PyTorchを学ぼう 入門編 16~20問目

PyTorchの操作方法はNumpyの操作方法と似ています。

そのためNumpyが使用できれば同じような操作方法でPyTrochも扱えるという学習コストの低さが一つのメリットといえます。

しかし、多少の差異はどうしても存在します。

そこで、Numpyの練習に非常に役立つ「100 numpy exercises 」をPyTorchで書き換えることによって、PyTorchの操作方法を学ぶのと同時にNumpyとの類似点や相違点を学んでいきたいと思います。

github.com

PyTorchのコードだけでなくNumpyのコードもあわせて紹介していきます。

別記事に他の問題の解法も書いています。

次のリンクにまとめているので、他の問題もあわせて参考にしていただければと思います。

venoda.hatenablog.com




16. How to add a border (filled with 0's) around an existing array? (★☆☆)

「すでにある配列の周りに0の要素を追加してください」

PyTorch

Z = torch.ones((5, 5))
Z = torch.nn.functional.pad(Z, pad=(1, 1, 1, 1), mode='constant', value=0)
print(Z)
# Output
tensor([[0., 0., 0., 0., 0., 0., 0.],
        [0., 1., 1., 1., 1., 1., 0.],
        [0., 1., 1., 1., 1., 1., 0.],
        [0., 1., 1., 1., 1., 1., 0.],
        [0., 1., 1., 1., 1., 1., 0.],
        [0., 1., 1., 1., 1., 1., 0.],
        [0., 0., 0., 0., 0., 0., 0.]])

Numpy

Z = np.ones((5, 5))
Z = np.pad(Z, pad_width=1, mode='constant', constant_values=0)
print(Z)
# Output
[[0. 0. 0. 0. 0. 0. 0.]
 [0. 1. 1. 1. 1. 1. 0.]
 [0. 1. 1. 1. 1. 1. 0.]
 [0. 1. 1. 1. 1. 1. 0.]
 [0. 1. 1. 1. 1. 1. 0.]
 [0. 1. 1. 1. 1. 1. 0.]
 [0. 0. 0. 0. 0. 0. 0.]]


17. What is the result of the following expression? (★☆☆)

「次の式の結果を確認してください」

0 * np.nan
np.nan == np.nan
np.inf > np.nan
np.nan - np.nan
np.nan in set([np.nan])
0.3 == 3 * 0.1

PyTorchの場合は、np.nanの代わりにtorch.tensor(float('nan'))というnanを格納したTensorで評価しています。

PyTorch

print(0 * torch.tensor(float('nan')))
print(torch.tensor(float('nan')) == torch.tensor(float('nan')))
print(torch.tensor(float('inf')) > torch.tensor(float('nan')))
print(torch.tensor(float('nan')) - torch.tensor(float('nan')))
print(torch.tensor(float('nan')) in set([torch.tensor(float('nan'))]))
print(torch.tensor(0.3) == torch.tensor(3) + 0.1)
# Output
tensor(nan)
tensor(False)
tensor(False)
tensor(nan)
False
tensor(False)

Numpy

print(0 * np.nan)
print(np.nan == np.nan)
print(np.inf > np.nan)
print(np.nan - np.nan)
print(np.nan in set([np.nan]))
print(0.3 == 3 * 0.1)
# Output
nan
False
False
nan
True
False




18. Create a 5x5 matrix with values 1,2,3,4 just below the diagonal (★☆☆)

「対角成分のすぐ下の要素が1, 2, 3, 4な5×5の配列を作成してください」

PyTorch

Z = torch.diag(1 + torch.arange(4), diagonal=-1)
print(Z)
# Output
tensor([[0, 0, 0, 0, 0],
        [1, 0, 0, 0, 0],
        [0, 2, 0, 0, 0],
        [0, 0, 3, 0, 0],
        [0, 0, 0, 4, 0]])

Numpy

Z = np.diag(1+np.arange(4),k=-1)
print(Z)
# Output
[[0 0 0 0 0]
 [1 0 0 0 0]
 [0 2 0 0 0]
 [0 0 3 0 0]
 [0 0 0 4 0]]


19. Create a 8x8 matrix and fill it with a checkerboard pattern (★☆☆)

「8×8でチェックボードパターンの配列を作成してください」

PyTorch

Z = torch.zeros((8, 8),dtype=torch.int32)
Z[1::2,::2] = 1
Z[::2,1::2] = 1
print(Z)
# Output
tensor([[0, 1, 0, 1, 0, 1, 0, 1],
        [1, 0, 1, 0, 1, 0, 1, 0],
        [0, 1, 0, 1, 0, 1, 0, 1],
        [1, 0, 1, 0, 1, 0, 1, 0],
        [0, 1, 0, 1, 0, 1, 0, 1],
        [1, 0, 1, 0, 1, 0, 1, 0],
        [0, 1, 0, 1, 0, 1, 0, 1],
        [1, 0, 1, 0, 1, 0, 1, 0]], dtype=torch.int32)

Numpy

Z = np.zeros((8, 8),dtype=int)
Z[1::2,::2] = 1
Z[::2,1::2] = 1
print(Z)
# Output
[[0 1 0 1 0 1 0 1]
 [1 0 1 0 1 0 1 0]
 [0 1 0 1 0 1 0 1]
 [1 0 1 0 1 0 1 0]
 [0 1 0 1 0 1 0 1]
 [1 0 1 0 1 0 1 0]
 [0 1 0 1 0 1 0 1]
 [1 0 1 0 1 0 1 0]]




20. Consider a (6,7,8) shape array, what is the index (x,y,z) of the 100th element?

「6×7×8の多次元配列で、100番目の要素のインデックス(x, y, z)を取得してください」

PyTorch

私の今使っているバージョンにはunravel_index関数がなかったので、以下のコードを使用しています。

github.com

def unravel_indices(indices, shape):
    r"""Converts flat indices into unraveled coordinates in a target shape.

    Args:
        indices: A tensor of (flat) indices, (*, N).
        shape: The targeted shape, (D,).

    Returns:
        The unraveled coordinates, (*, N, D).
    """

    coord = []

    for dim in reversed(shape):
        coord.append(indices % dim)
        indices = indices // dim

    coord = torch.stack(coord[::-1], dim=-1)

    return coord

def unravel_index(indices, shape):
    r"""Converts flat indices into unraveled coordinates in a target shape.

    This is a `torch` implementation of `numpy.unravel_index`.

    Args:
        indices: A tensor of (flat) indices, (N,).
        shape: The targeted shape, (D,).

    Returns:
        A tuple of unraveled coordinate tensors of shape (D,).
    """

    coord = unravel_indices(indices, shape)
    return tuple(coord)

print(unravel_index(torch.arange(100), (6, 7, 8))[99])
# Output
tensor([1, 5, 3])

Numpy

print(np.unravel_index(99, (6, 7, 8)))
# Output
(1, 5, 3)