Pytorchで割とよく検索するけど、ひとつの記事にするほどでもない事をまとめてみる。使っていて便利そうだと思った情報はどんどん追加していくつもり。
- cuda.is_available(): GPU動作チェック
- GPUかCPUかを自動判断
- to(x.deice): model中での変数がGPUかCPUか
- numpy ndarray と pytorch tensorの相互変換
- 平均と標準偏差で正規化
- permute: 次元の入れ替え
- 画像左右反転
- like関数
- パラメータをもたないモジュール
- register_buffer(): 最適化しないパラメータ
- model.apply(): モジュールを再帰的に処理
- tensor.item(): スカラーの取り出し
- model.parameters()の中身のみかた
cuda.is_available(): GPU動作チェック
PytorchでGPUの動作をチェックするにはtorch.cuda.is_available()
の値をチェックするだけ。
TrueであればGPUは動作している。
import torch print(torch.cuda.is_available())
GPUかCPUかを自動判断
以下のおまじないdevice = ’cuda' ...
をプログラムのはじめに一行入れておく。そしてモデルと変数を定義したところでto(device)を書いておく。GPU搭載のPCでCPUで動かしたい場合は代わりにdevice = 'cpu'
と書けばよい。
import torch from torchvision import models device = 'cuda' if torch.cuda.is_available() else 'cpu' model = models.resnet50().to(device) x = x.to(device) y = y.to(device)
to(x.deice): model中での変数がGPUかCPUか
modelの中で新しく変数を定義した場合は、deviceがGPUなのかCPUなのかを指定する必要がある。基本的には自動でどちらでも動くようにすべきであるが、if文などで分ける必要はない。入力されたtensorのdeviceを参照するだけでよい。
def forward(self, x): a = torch.randn(x.shape).to(x.device) return x*a
numpy ndarray と pytorch tensorの相互変換
こちらの記事にまとめました。 tzmi.hatenablog.com
平均と標準偏差で正規化
Pytorchで使える学習済みモデルへ入力する際の画素値の変換。transform.normarizeを使うのもいいけど、以下のように書けば直接かける。
# x.shape = [n, 3, h, w], range: (0, 1) mean = torch.tensor([0.485, 0.456, 0.406]).reshape(1,3,1,1) std = torch.tensor([0.229, 0.224, 0.225]).reshape(1,3,1,1) eps = 1e-7 x = (x-mean)/(std+eps)
permute: 次元の入れ替え
numpyであれば、transpose
を使えば次元の位置をどんどん入れ替えられるが、pytorchでのtranspose()
関数は指定した2つの次元の位置を入れ替える関数なので、numpyのtransposeとは挙動が異なる。pytorchでnumpy.transpose
と同じことをしたいときはpermute()
関数を使う。channel lastからchannel firstへの変換などで使う。
x = torch.randn((4,3,8,8)) # x.shape = [4,3,8,8] a = x.permute(0,2,3,1) # a.shape= [4,8,8,3]
画像左右反転
pytorchではnumpyのx= x[:,:,::-1]
が使えないので、反転した整数配列を使って画像を反転させる。具体的には以下のようにする。
n,c,h,w = x.shape a = torch.arange(w-1,-1,-1) # start=w-1, end=-1, step=-1 x = x[:,:,:,a]
like関数
numpy のzeors_likeなどと似たことができる関数。torch tensorからshapeやtypeだけでなく、deviceも継承できる。
empty_like
, full_like
, ones_like
, rand_like
, randint_like
, randn_like
, zeros_like
パラメータをもたないモジュール
Swishのようにパラメータを持たないモジュールは以下のように__init__
関数を省略できる
class Swish(nn.Module): def forward(self, x): return x*torch.sigmoid(x)
register_buffer(): 最適化しないパラメータ
pytorchで定義するモジュールの中で、最適化されるパラメータ以外のパラメータを定義することができる。例えば、以下のように書くとパラメータ
a
は最適化され、パラメータb
は最適化されないというように分けることができる。
例えばbatchnorm2dのrunning mean
やrunning std
はこのような記法で書かれている。オリジナルのモジュールを作りたいときに重宝するかもしれない。model.parameters
では出てこない(最適化パラメータではない)のに、model.state_dict
では出てくる(保存が可能)という点で、非常に使い勝手がいい。
class A(nn.Module): def __init__(self): super().__init__() self.a = nn.Parameter(torch.randn(10)) self.register_buffer('b', torch.randn(10)) def forward(self, x): return self.a*x + b
model.apply(): モジュールを再帰的に処理
Pytorchのmodel. apply()関数はモデルの中にある全てのモジュールを再帰的に掘って関数を適用できる。例えば、pytorchのresnet50
は構造的にresnet50のモジュールの下に全てのconv2dがあるわけではないが、下記のようにすれば全てのconv2dを再帰的に初期化できる。
def weights_init(m): if isinstance(m, nn.Conv2d): nn.init.kaiming_normal_(m.weight) model = models.resnet50() model.apply(weights_init)
tensor.item(): スカラーの取り出し
tensor. item()関数は、tensorの中の変数が1つであることが必要であるが、deviceがGPUでもCPUでも関係なくpython scalarの数値を返してくれる
in [1]: import torch In [2]: x = torch.tensor([10.0]) In [3]: x Out[3]: tensor([10.]) In [4]: x.item() Out[4]: 10.0
model.parameters()の中身のみかた
model.parametersはpythonのgeneratorなので、直接の中を見るときにforループを書く必要がありそうだが、ipythonで以下のようにlist()でラップすれば中身を見れる。
params = list(model.parameters())