【100 PyTorch exercises】 PyTorchを学ぼう 入門編 61~65問目

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

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

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

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

github.com

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

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

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

venoda.hatenablog.com




61. Find the nearest value from a given value in an array (★★☆)

「配列の中から指定された値に最も近い値を取得してください」

PyTorch

Z = torch.distributions.uniform.Uniform(0, 1).sample([10])
z = 0.5

m = Z[torch.abs(Z - z).argmin()]
print(m)
# Output
tensor(0.6153)

Numpy

Z = np.random.uniform(0,1,10)
z = 0.5

m = Z.flat[np.abs(Z - z).argmin()]
print(m)
# Output
0.40291452741174405


62. Considering two arrays with shape (1,3) and (3,1), how to compute their sum using an iterator? (★★☆)

「形状が(1, 3)と(3, 1)の二つの配列について、イテレーターを使用して合計を計算してください」

PyTorch

イテレータ部分はNumpyのものを使用しています。

A = torch.arange(3).view(3, 1)
B = torch.arange(3).view(1, 3)
it = np.nditer([A, B, None])

for x, y, z in it: z[...] = x + y
print(it.operands[2])
# Output
[[0 1 2]
 [1 2 3]
 [2 3 4]]

Numpy

A = np.arange(3).reshape(3, 1)
B = np.arange(3).reshape(1, 3)
it = np.nditer([A, B, None])
  
for x, y, z in it: z[...] = x + y
print(it.operands[2])
# Output
[[0 1 2]
 [1 2 3]
 [2 3 4]]




63. Create an array class that has a name attribute (★★☆)

「name属性を持つArrayクラスを作成してください」

PyTorch

PyTorchでの方法を見つけることができませんでした。

Numpy

class NamedArray(np.ndarray):
    def __new__(cls, array, name="no name"):
        obj = np.asarray(array).view(cls)
        obj.name = name
        return obj

    def __array_finalize__(self, obj):
        if obj is None: return
        self.info = getattr(obj, 'name', "no name")

Z = NamedArray(np.arange(10), "range_10")
print (Z.name)
# Output
range_10


64. Consider a given vector, how to add 1 to each element indexed by a second vector (be careful with repeated indices)? (★★★)

「2番目のベクトルでインデックス付けされた各要素に1を追加してください」

PyTorch

Z = torch.ones(10)
I = torch.randint(0, len(Z), (20, ))
Z += torch.bincount(I, minlength=len(Z))
print(Z)
# Output
[4. 3. 4. 4. 3. 1. 2. 4. 1. 4.]

Numpy

Z = np.ones(10)
I = np.random.randint(0,len(Z),20)
Z += np.bincount(I, minlength=len(Z))
print(Z)
# Output
[4. 3. 4. 4. 3. 1. 2. 4. 1. 4.]




65. How to accumulate elements of a vector (X) to an array (F) based on an index list (I)? (★★★)

「インデックスのリスト(I)に基づいて、ベクトル(X)の要素を配列(F)に累積してください」

PyTorch

X = torch.tensor([1, 2, 3, 4, 5, 6])
I = torch.tensor([1, 3, 9, 3, 4, 1])
F = torch.bincount(I, X)
print(F)
# Output
tensor([0., 7., 0., 6., 5., 0., 0., 0., 0., 3.], dtype=torch.float64)

Numpy

X = [1, 2, 3, 4, 5, 6]
I = [1, 3, 9, 3, 4, 1]
F = np.bincount(I, X)
print(F)
# Output
[0. 7. 0. 6. 5. 0. 0. 0. 0. 3.]