PyTorchはオープンソースの機械学習フレームワークです。少ないコードで様々な機械学習を実装できます。また、GPUを使って高速な計算をすることができ、また、豊富なライブラリを持つことから、最も広く用いられている機械学習にのライブラリの一つです。今回、PyTorchのチュートリアルをベースにPyTorchを基本から学んでいきたいと思います。
Python Tutorials(英語版サイト)
PyTorchチュートリアル(日本語翻訳版)
Tensorとは
TensorはPyTorchで使われるデータ構造で、Numpyのndarrayと似た形状です。ただし、GPUを使った並列処理ができたり、ディープラーニングなどで重要な自動微分を取ることができたり、便利な性質を持ちます。PyTorchのTensorとNumpyのndarrayは相互変換が可能で、同じデータメモリを共有することもできます。
PyTorchと類似のNumpyを使うときは、それぞれをインポートして使用します。
import torch
import numpy as np
Tensorの作成
Tensorの作成例を示します。
# リストやシーケンスからのTensorの生成
L = [[1,2],[8,9]]
a = torch.Tensor(L)
# Tensor.dtypeでデータ型確認
print(a.dtype)
print(a)
torch.float32 tensor([[1., 2.], [8., 9.]])
Tensor.dtypeでデータ型を確認できます。Tensorのデフォルトのデータ型はfloat32です。
# 指定のサイズのTensor(中身はランダム)を生成
t1 = torch.empty(2,3)
print(t1)
tensor([[0.0000e+00, 1.0000e+00, 2.7597e-06], [1.0740e-05, 2.6426e+20, 4.2247e-05]])
※値はメモリ上のランダムな値
# 指定したサイズのゼロで埋めたTensorを生成
t2 = torch.zeros(4)
print(t2)
# 指定したサイズの1で埋めたTensorを生成
t3 = torch.ones(3,2)
print(t3)
tensor([0., 0., 0., 0.]) tensor([[1., 1.], [1., 1.], [1., 1.]])
# 指定したサイズの0~1の一様ランダムなTensorを生成
t4 = torch.rand(2,2)
print(t4)
# 指定したサイズの-1~1の正規分布に従うTensorを生成
t5 = torch.randn(4)
print(t5)
tensor([[0.7073, 0.0986], [0.9827, 0.8421]]) tensor([-1.3731, -0.4215, 0.3472, 0.3218])
# startからstep刻みでend未満の数列のTensorを生成
t6 = torch.arange(0,10,2)
print(t6)
# startからendまでstep等分の数列でTensorを生成
t7 = torch.linspace(0,1,20)
print(t7)
import math
t8 = torch.linspace(0, 2*math.pi,8)
print(t8)
tensor([0, 2, 4, 6, 8]) tensor([0.0000, 0.0526, 0.1053, 0.1579, 0.2105, 0.2632, 0.3158, 0.3684, 0.4211, 0.4737, 0.5263, 0.5789, 0.6316, 0.6842, 0.7368, 0.7895, 0.8421, 0.8947, 0.9474, 1.0000]) tensor([0.0000, 0.8976, 1.7952, 2.6928, 3.5904, 4.4880, 5.3856, 6.2832])
Tensorの形元(形)やデータ型の変換
Tensorの次元(形)はreshapeでおこないます。
# 1×16のTensorの次元を変換
b1 = torch.arange(16)
print(b1)
b2 = torch.reshape(b1,(4,4))
print(b2)
# -1はデータ数から8を自動補完
b3 = torch.reshape(b1,(2,-1))
print(b3)
tensor([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) tensor([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11], [12, 13, 14, 15]]) tensor([[ 0, 1, 2, 3, 4, 5, 6, 7], [ 8, 9, 10, 11, 12, 13, 14, 15]])
# Tensorの次元を確認
print(b3.size())
print(b3.shape)
# 0次元目の大きさ
print(b3.size(0))
# 1次元目の大きさ
print(b3.size(1))
torch.Size([2, 8]) torch.Size([2, 8]) 2 8
# 次元数
print(b3.ndim)
2
データ型はdtypeで指定し、変更できる。
# 生成時に設定
c6 = torch.zeros(2,3, dtype=torch.int64)
print(c6.dtype)
# データ型の変換
c7 = torch.Tensor.type(c6,dtype=torch.float64)
print(c7.dtype)
# データ型とサイズの継承
c8 = torch.ones_like(c6)
print(c8)
print(c8.dtype)
torch.int64 torch.float64 tensor([[1, 1, 1], [1, 1, 1]]) torch.int64
Tensorの転置
Tensorはtransposeで転置したTensorを得ることができる。また、Tensor.Tでも転置したTensorを得ることができます。
# 転置
c1 = torch.Tensor([[1,2],[3,4]])
print(c1)
c2 = torch.transpose(c1,0,1)
print(c2)
print(c1.T)
tensor([[1., 2.], [3., 4.]]) tensor([[1., 3.], [2., 4.]]) tensor([[1., 3.], [2., 4.]])
transposeは任意の次元を入れ替えることができる。
c3 = torch.rand(2,3,4)
print(c3.shape)
# 0次元目と1次元目を入れ替え
c4 = torch.transpose(c1, 0, 1)
print(c4.shape)
# 1次元目と2次元目を入れ替え
c5 = torch.transpose(c1, 1, 2)
print(c5.shape)
torch.Size([2, 3, 4]) torch.Size([3, 2, 4]) torch.Size([2, 4, 3])
Tensorの演算
Tensorは各値の演算について示します。Tensorの演算は、
・+=*/などの演算子を用いる方法
・torch.add,torch.sub,torch.mul,torch.divなどの演算関数を用いる方法
・Tensor.add, Tensor.add_などのTensorのメソッドを用いる方法
などがあります。
# 演算子を用いた四則演算
x = torch.Tensor([[5,6],[8,10]])
y = torch.Tensor([[1,2],[3,4]])
z1 = x+y
z2 = x-y
z3 = x*y
z4 = x/y
print(z1)
print(z2)
print(z3)
print(z4)
tensor([[ 6., 8.], [11., 14.]]) tensor([[4., 4.], [5., 6.]]) tensor([[ 5., 12.], [24., 40.]]) tensor([[5.0000, 3.0000], [2.6667, 2.5000]])
# 演算関数を用いた四則演算
x = torch.Tensor([[5,6],[8,10]])
y = torch.Tensor([[1,2],[3,4]])
z1 = torch.add(x,y)
z2 = torch.sub(x,y)
z3 = torch.mul(x,y)
z4 = torch.div(x,y)
print(z1)
print(z2)
print(z3)
print(z4)
tensor([[ 6., 8.], [11., 14.]]) tensor([[4., 4.], [5., 6.]]) tensor([[ 5., 12.], [24., 40.]]) tensor([[5.0000, 3.0000], [2.6667, 2.5000]])
メソッドを使って演算する場合、元の値を保持する方法と値を書き換えるin-place操作をする方法があります。例えば、x.add(y)ではTensorのxにyを足した結果を返しますが、元のxは変わりません。一方で、x.add_(y)とアンダーバーを使ったメソッドでは、xの値は書き換わります。
# 演算メソッドを用いた四則演算
x = torch.Tensor([[5,6],[8,10]])
y = torch.Tensor([[1,2],[3,4]])
print(x.add(y))
print(x.sub(y))
print(x.mul(y))
print(x.div(y))
# xの値は変わらない
print(x)
tensor([[ 6., 8.], [11., 14.]]) tensor([[4., 4.], [5., 6.]]) tensor([[ 5., 12.], [24., 40.]]) tensor([[5.0000, 3.0000], [2.6667, 2.5000]]) tensor([[ 5., 6.], [ 8., 10.]])
# in-place処理をする演算メソッドを用いた四則演算
x = torch.Tensor([[5,6],[8,10]])
y = torch.Tensor([[1,2],[3,4]])
x.add_(y) # x+y
print(x)
x.mul_(y) # x*y
print(x)
x.sub_(y) # x-y
print(x)
x.div_(y) # x/y
print(x)
# yは不変
print(y)
tensor([[ 6., 8.], [11., 14.]]) tensor([[ 6., 16.], [33., 56.]]) tensor([[ 5., 14.], [30., 52.]]) tensor([[ 5., 7.], [10., 13.]]) tensor([[1., 2.], [3., 4.]])
Tensorの行列積
Tensorの行列式はtorch.matmul関数、またはtorch.mm関数で行うことができます。
x = torch.rand((2,3))
y = torch.rand((3,2))
print(x)
print(y)
tensor([[0.9107, 0.6812, 0.3674], [0.8000, 0.2388, 0.7749]]) tensor([[0.8742, 0.2070], [0.9954, 0.5732], [0.0333, 0.1516]])
# torch.matmul関数の場合
print(torch.matmul(x,y))
print(torch.matmul(y,x))
tensor([[1.4864, 0.6346], [0.9629, 0.4200]]) tensor([[0.9617, 0.6449, 0.4816], [1.3651, 0.8150, 0.8099], [0.1517, 0.0589, 0.1298]])
# torch.mm関数の場合
print(torch.mm(x,y))
print(torch.mm(y,x))
tensor([[1.4864, 0.6346], [0.9629, 0.4200]]) tensor([[0.9617, 0.6449, 0.4816], [1.3651, 0.8150, 0.8099], [0.1517, 0.0589, 0.1298]])
PyTorchのTensorとNumpyのndarrayの相互変換
Tensorからndarrayへの変換はTensorのnumpyメソッドを使います。一方、ndarrayからTensorへの変換はfrom_numpy関数を使います。
a = torch.Tensor([[1,2],[3,4]])
print(type(a))
# PyTorchのTensorからNumpyのndarrayへの変換
b = a.numpy()
print(type(b))
# NumpyのndarrayからPyTorchのTensorへの変換
c = torch.from_numpy(b)
print(type(c))
この場合、Tensorとndarrayは同じメモリを共有して使います。ですので、どちらかを変更した場合、もう一方も変更されます。それを避けるために、copyメソッドで新しいメモリのデータ構造を作る必要があります。
c[1][1] = 10
print(a)
print(b)
tensor([[ 1., 2.], [ 3., 10.]]) [[ 1. 2.] [ 3. 10.]]
a = torch.Tensor([[1,2],[3,4]])
b = a.numpy().copy()
a[1][1] = 10
# bはaの変更の影響を受けない
print(b)
[[1. 2.] [3. 4.]]
Tensorのデバイス
Tensorは、CPUの他、GPU上で計算を行うことができます。デバイスは、torch.deviceクラスで表されます。CPUを表すデバイスはtorch.device(“cpu”)、GPUを表すデバイスはtorch.device(“cuda”)やtorch.device(“cuda:0”)と書きます。(0はGPUの番号)
# GPUが使えるか確認
torch.cuda.is_available()
True
# デフォルトではCPU上でTensorを生成
d1 = torch.rand(3, 4)
print(d1.device)
cpu
# GPUを指定してTensorを生成
d2 = torch.rand(3, 4, device=torch.device("cuda"))
print(d2.device)
cuda:0
# GPUが使える環境の時はGPUでTensorを生成
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
d3 = torch.rand(3, 4, device = device)
print(d3.device)
cuda:0
コメント