【100 PyTorch exercises】 PyTorchを学ぼう 入門編 56~60問目

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

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

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

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

github.com

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

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

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

venoda.hatenablog.com




56. Generate a generic 2D Gaussian-like array (★★☆)

「2Dのガウス配列を作成してください」

PyTorch

X, Y = torch.meshgrid(torch.linspace(-1, 1, 10), torch.linspace(-1, 1, 10))
D = torch.sqrt(X * X + Y * Y)
sigma, mu = 1.0, 0.0
G = torch.exp(-((D - mu) ** 2 / (2.0 * sigma **2)))
print(G)
# Output
tensor([[0.3679, 0.4482, 0.5198, 0.5738, 0.6028, 0.6028, 0.5738, 0.5198, 0.4482,
         0.3679],
        [0.4482, 0.5461, 0.6333, 0.6991, 0.7344, 0.7344, 0.6991, 0.6333, 0.5461,
         0.4482],
        [0.5198, 0.6333, 0.7344, 0.8107, 0.8517, 0.8517, 0.8107, 0.7344, 0.6333,
         0.5198],
        [0.5738, 0.6991, 0.8107, 0.8948, 0.9401, 0.9401, 0.8948, 0.8107, 0.6991,
         0.5738],
        [0.6028, 0.7344, 0.8517, 0.9401, 0.9877, 0.9877, 0.9401, 0.8517, 0.7344,
         0.6028],
        [0.6028, 0.7344, 0.8517, 0.9401, 0.9877, 0.9877, 0.9401, 0.8517, 0.7344,
         0.6028],
        [0.5738, 0.6991, 0.8107, 0.8948, 0.9401, 0.9401, 0.8948, 0.8107, 0.6991,
         0.5738],
        [0.5198, 0.6333, 0.7344, 0.8107, 0.8517, 0.8517, 0.8107, 0.7344, 0.6333,
         0.5198],
        [0.4482, 0.5461, 0.6333, 0.6991, 0.7344, 0.7344, 0.6991, 0.6333, 0.5461,
         0.4482],
        [0.3679, 0.4482, 0.5198, 0.5738, 0.6028, 0.6028, 0.5738, 0.5198, 0.4482,
         0.3679]])

Numpy

X, Y = np.meshgrid(np.linspace(-1,1,10), np.linspace(-1,1,10))
D = np.sqrt(X * X + Y * Y)
sigma, mu = 1.0, 0.0
G = np.exp(-((D - mu) ** 2 / (2.0 * sigma ** 2)))
print(G)
# Output
[[0.36787944 0.44822088 0.51979489 0.57375342 0.60279818 0.60279818
  0.57375342 0.51979489 0.44822088 0.36787944]
 [0.44822088 0.54610814 0.63331324 0.69905581 0.73444367 0.73444367
  0.69905581 0.63331324 0.54610814 0.44822088]
 [0.51979489 0.63331324 0.73444367 0.81068432 0.85172308 0.85172308
  0.81068432 0.73444367 0.63331324 0.51979489]
 [0.57375342 0.69905581 0.81068432 0.89483932 0.9401382  0.9401382
  0.89483932 0.81068432 0.69905581 0.57375342]
 [0.60279818 0.73444367 0.85172308 0.9401382  0.98773022 0.98773022
  0.9401382  0.85172308 0.73444367 0.60279818]
 [0.60279818 0.73444367 0.85172308 0.9401382  0.98773022 0.98773022
  0.9401382  0.85172308 0.73444367 0.60279818]
 [0.57375342 0.69905581 0.81068432 0.89483932 0.9401382  0.9401382
  0.89483932 0.81068432 0.69905581 0.57375342]
 [0.51979489 0.63331324 0.73444367 0.81068432 0.85172308 0.85172308
  0.81068432 0.73444367 0.63331324 0.51979489]
 [0.44822088 0.54610814 0.63331324 0.69905581 0.73444367 0.73444367
  0.69905581 0.63331324 0.54610814 0.44822088]
 [0.36787944 0.44822088 0.51979489 0.57375342 0.60279818 0.60279818
  0.57375342 0.51979489 0.44822088 0.36787944]]


57. How to randomly place p elements in a 2D array? (★★☆)

「p個の要素を2D配列にランダムに配置してください」

PyTorch

n = 10
p = 3
Z = torch.zeros((n, n))
Z.put_(torch.arange(
    0, n * n, dtype=torch.float64).multinomial(
    num_samples=p, replacement=False), torch.ones(p))
print(Z)
# Output
tensor([[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0., 0., 1., 0., 0., 0.],
        [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0., 1., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0., 0., 0., 0., 1., 0.],
        [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]])

Numpy

n = 10
p = 3
Z = np.zeros((n,n))
np.put(Z, np.random.choice(range(n*n), p, replace=False),1)
print(Z)
# Output
[[0. 0. 0. 0. 0. 0. 0. 0. 0. 1.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 1. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 1. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]]




58. Subtract the mean of each row of a matrix (★★☆)

「行列の各行の平均を減算してください」

PyTorch

X = torch.rand(5, 10)

Y = X - X.mean(dim=1, keepdims=True)
print(Y)

Y = X - X.mean(dim=1).view(-1, 1)
print(Y)
# Output
tensor([[ 0.2316, -0.2835, -0.1259,  0.2670,  0.2207,  0.0650, -0.1786, -0.0603,
         -0.3382,  0.2020],
        [-0.2283,  0.1400, -0.2683,  0.4233,  0.2576, -0.1185,  0.1167, -0.2064,
          0.3771, -0.4931],
        [-0.3614,  0.0750, -0.1156,  0.0150, -0.0695, -0.2335,  0.1359,  0.4216,
         -0.0577,  0.1903],
        [ 0.0015,  0.1657,  0.0481, -0.3934,  0.1169,  0.4440,  0.1496, -0.3833,
         -0.0599, -0.0891],
        [ 0.2079, -0.1061, -0.3909, -0.3309,  0.2117,  0.1951,  0.2687,  0.1644,
         -0.3071,  0.0873]])
tensor([[ 0.2316, -0.2835, -0.1259,  0.2670,  0.2207,  0.0650, -0.1786, -0.0603,
         -0.3382,  0.2020],
        [-0.2283,  0.1400, -0.2683,  0.4233,  0.2576, -0.1185,  0.1167, -0.2064,
          0.3771, -0.4931],
        [-0.3614,  0.0750, -0.1156,  0.0150, -0.0695, -0.2335,  0.1359,  0.4216,
         -0.0577,  0.1903],
        [ 0.0015,  0.1657,  0.0481, -0.3934,  0.1169,  0.4440,  0.1496, -0.3833,
         -0.0599, -0.0891],
        [ 0.2079, -0.1061, -0.3909, -0.3309,  0.2117,  0.1951,  0.2687,  0.1644,
         -0.3071,  0.0873]])

Numpy

X = np.random.rand(5, 10)

Y = X - X.mean(axis=1, keepdims=True)
print(Y)

Y = X - X.mean(axis=1).reshape(-1, 1)
print(Y)
# Output
[[ 0.40138171  0.27134797 -0.22548753  0.13729467 -0.07188423  0.34927514
  -0.37407702 -0.40508348  0.25552823 -0.33829546]
 [-0.26628778  0.2816949   0.05339935 -0.1707782  -0.09055441  0.17540123
   0.30862995  0.18213499 -0.27997828 -0.19366175]
 [ 0.36550913 -0.32756242 -0.11061519  0.47884103 -0.13503928 -0.35983063
   0.23440237  0.09513192 -0.30989413  0.06905721]
 [-0.19333044  0.29755002 -0.20463918 -0.20366138 -0.33199031  0.17288298
  -0.02676781  0.29480694 -0.21654379  0.41169296]
 [-0.20619787 -0.47221495  0.3096065   0.27687813 -0.53841866 -0.2289544
  -0.14863357  0.29301604  0.33446286  0.3804559 ]]
[[ 0.40138171  0.27134797 -0.22548753  0.13729467 -0.07188423  0.34927514
  -0.37407702 -0.40508348  0.25552823 -0.33829546]
 [-0.26628778  0.2816949   0.05339935 -0.1707782  -0.09055441  0.17540123
   0.30862995  0.18213499 -0.27997828 -0.19366175]
 [ 0.36550913 -0.32756242 -0.11061519  0.47884103 -0.13503928 -0.35983063
   0.23440237  0.09513192 -0.30989413  0.06905721]
 [-0.19333044  0.29755002 -0.20463918 -0.20366138 -0.33199031  0.17288298
  -0.02676781  0.29480694 -0.21654379  0.41169296]
 [-0.20619787 -0.47221495  0.3096065   0.27687813 -0.53841866 -0.2289544
  -0.14863357  0.29301604  0.33446286  0.3804559 ]]


59. How to sort an array by the nth column? (★★☆)

「n番目の列で配列を並べ替えてください」

PyTorch

Z = torch.randint(0, 10, (3, 3))
print(Z)
print(Z[Z[:, 1].argsort()])
# Output
tensor([[7, 7, 5],
        [5, 9, 1],
        [8, 8, 2]])
tensor([[7, 7, 5],
        [8, 8, 2],
        [5, 9, 1]])

Numpy

Z = np.random.randint(0, 10, (3, 3))
print(Z)
print(Z[Z[:,1].argsort()])
# Output
[[5 7 9]
 [0 1 1]
 [3 4 9]]
[[0 1 1]
 [3 4 9]
 [5 7 9]]




60. How to tell if a given 2D array has null columns? (★★☆)

「2D配列にNULL値があるかどうかを確認してください」

PyTorch

Z = torch.randint(0, 3, (3, 10))
print((~Z.any(dim=0)).any())
# Output
tensor(False)

Numpy

Z = np.random.randint(0,3,(3,10))
print((~Z.any(axis=0)).any())
# Output
False