Python
GPU
DeepLearning
PyTorch

PyTorch公式チュートリアル Deep Learning with PyTorch #1

PyTorchの公式チュートリアルであるDeep Learning withPyTorch: A 60 Minute Bitzの日本語訳といくつか補足したものです。
自分はこれまでTensorflowをメインに研究などのコードを作成したのでChainerについてはあまり知識がありません。

PyTorchとは何か

Pythonの科学計算パッケージ。ターゲットとなっているのは以下の二つの層。
1. GPUを使用するためにNumPyからの以降。
2. 柔軟かつ素早い実装が可能な深層学習研究プラットフォーム。

Getting Started

まずはPyTorchで用いられている基本的な概念について。

Tensor

TensorはNumpyのndarrayと似ているものの、GPUで利用されることができ、計算を加速することができる。
例えば、5x3の行列を作成したい場合はtorch.Tensorを使って以下のように初期化できる。ちなみにtorch.tensorは実際にはtorch.FloatTensorのエイリアスになっており、32-bit signed integerなどを初期化したい場合にはtorch.IntTensorなどを用いる。

import torch
x = torch.Tensor(5,3) # 5X3初期化されていないの行列が生成される。

またtorch.rand()でランダムに初期化された行列を生成することもできる。

x = torch.rand(5,3)
print(x)

Tensorのサイズを確認したい時はsize()というクラスメソッドでTensorのサイズを表すtorch.Sizeが返される。

print(x.size()) # torch.Size([5,3])が出力される

ちなみにこのtorch.Sizeはtupleとなっているため、Pythonの通常のtupleと同様の操作が可能。例えば x.size()[0]とすればTensorの一次元目の大きさを取得できる。

Operations

PyTorchには様々演算記法があり、以下でそれらを紹介する。

和(addition)

まず基本的な+を用いた和の演算とtorch.add(a,b)を用いた以下の方法がある。

x = torch.rand(5,3)
y = torch.rand(5,3)
print(x+y)
print(torch.add(x,y)) #どちらでも同様の演算結果を得ることができる

また、torch.add(a,b)を用いる場合、オプショナルな引数outを用いて結果を別のtensorに格納することも可能。

result = torch.Tensor(5,3)
torch.add(x,y, out=result)
print(result) # 先ほどのx+yと同様の結果がresultに格納される。

またPyTorchにおいて、Tensorをin-placeに変更する(つまり元のTensorの中身を書き換えてしまう)ような演算には関数名の後に接尾辞(postfix)として_がつく。
例えば、あるTensorをin-plceに転置するTensor.t_()メソッドなど。

>>> x = torch.rand(3,5)
>>> x.t_()
 0.9643  0.6642  0.7152
 0.8060  0.8571  0.8347
 0.5978  0.3552  0.2373
 0.3823  0.3224  0.9044
 0.7525  0.7579  0.0206
[torch.FloatTensor of size 5x3]
>>> x
 0.3229  0.8450  0.7299
 0.7590  0.0953  0.8313
 0.4026  0.4635  0.1336
 0.0777  0.3386  0.9635
 0.0899  0.3295  0.1540
[torch.FloatTensor of size 5x3]
# 3x5のTensorだったxが5x3に転置されているのが確認できる。

>>> x = torch.rand(3,5)
>>> x.t()
 0.3229  0.8450  0.7299
 0.7590  0.0953  0.8313
 0.4026  0.4635  0.1336
 0.0777  0.3386  0.9635
 0.0899  0.3295  0.1540
[torch.FloatTensor of size 5x3]
>>> x
 0.3229  0.7590  0.4026  0.0777  0.0899
 0.8450  0.0953  0.4635  0.3386  0.3295
 0.7299  0.8313  0.1336  0.9635  0.1540
[torch.FloatTensor of size 3x5]
# x自体は3x5のまま。

add()演算についても、in-placeで以下のように書きあらわすことができる。

x = torch.rand(5,3)
y = torch.rand(5,3)
y.add_(x)
print(y)

Tensorの大きさを変更する

Tensorの大きさを変える際にはtensor.viewを用いる。(tensorflowと比べるとちょっと名前がわかりにくいですね)
torch.view()はin-placeな演算ではないので、元のtensorは変更されない。

x = torch.randn(4,4)
y = x.view(16) # 4x4の行列が16x1のに変形される
z = x.view(-1,8) # -1が含まれる場合、他の次元に合わせて整形される。ここでは一方の次元が8なので16/8=2となる。

Numpy Bridge

NumpyのarrayをTorchのtensorに変換したり、その逆を行うことも可能。

TensorをNumpyのarrayに変換する

>>> a = torch.ones(5) # 要素が全てfloatの1の5x1のベクトルが出力される
 1
 1
 1
 1
 1
[torch.FloatTensor of size 5]
>>> b = a.numpy() # TensorをNumpy化する
>>> print(b)
[1. 1. 1. 1. 1.]

NumpyのarrayをTorch Tensorに変換する

import numpy as np
a = np.ones(5) # 5x1の要素が全て1のNumpy配列を作成
b = torch.from_numpy(a) # bはサイズが5のdoubleのTTensorになる
np.add(a, 1, out=a)
print(a)
print(b)