今週、PFNよりChainerの開発を停止するという発表があって驚きました。
Chainer/CuPy v7のリリースと今後の開発体制について
深層学習・機械学習・Pythonの素人でしたが、深層学習ブームの中、2015年の秋くらいから使い始めて、Chainer meetup(#3,#8)でも発表させて頂きました。
新しい機能もあまり使っていなかったので、しらばくこのままChainerを使い続けることもできますが、これを機にPyTorchを一度試してみました。
公式の移行ドキュメントを見ると、関数の対応など書いてあり、とても参考になります。
Chainer ⇒ PyTorchへの移行ドキュメント(公式)
以下は個人的な移行時のメモとして置いておきます。
PyTorch インストール
- OS: Windows 10, ubuntu 18.04
- GPU: RTX 2080
- python 3.7(anaconda)
- Cuda 10.1
- Chainer 7.0.0a1
- Cupy-cuda101 7.0.0a1
PyThorch公式からOSやPython,Cudaバージョンなどを選択すると以下のようなコマンドが表示されるので、それを実行するとPyTorchのインストールが5分足らずで完了します。
$ conda install pytorch torchvision cudatoolkit=10.1 -c pytorch
Windows・ubuntu両方、GPUでそのまま動いたので、Chainerで使っているCudaのバージョンが合えば、インストールはとても簡単なようです。
コードの移行
ChainerとPytorchはとても似ているので、だいたい対応するクラス・関数があります。
Trainerとかは使ってないので、そのあたりの変換については触れていません。
細かい関数の対応は公式の対応表が便利です。
以下のimportから学習までの簡単な全体コードはこちらに置きました
import 関係
# import chainer
# import chainer.links as L
# import chainer.functions as F
# from chainer import optimizers
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
データ型の変換
ChainerのValiableにあたるものは、Pytorchではtensorのようです。
- Numpy ⇒ Variable, tensor
# x = chainer.Variable(x_array)
x = torch.tensor(x_array)
- Variable, tensor ⇒ Numpy
# y_array = y.data
y_array = y.detach().numpy()
※グラフ形成後はy.detach()が必要なようです
- CPU(Variable, tensor) ⇒ GPU(Variable, tensor)
# x.to_gpu()
x = x.to("cuda")
- GPU(Variable, tensor) ⇒ CPU(Variable, tensor)
# y.to_cpu()
y = y.to("cpu")
ネットワーク
#class MLP(chainer.Chain):
# def __init__(self):
# super(MLP, self).__init__()
# with self.init_scope():
# self.l1 = L.Linear(None, 1000)
# self.l2 = L.Linear(None, 1000)
# self.l3 = L.Linear(None, 10)
#
# def forward(self, x):
# h1 = F.relu(self.l1(x))
# h2 = F.relu(self.l2(h1))
# return self.l3(h2)
class MLP(nn.Module):
def __init__(self):
super(MLP, self).__init__()
self.l1 = nn.Linear(784, 1000)
self.l2 = nn.Linear(1000, 1000)
self.l3 = nn.Linear(1000, 10)
def forward(self, x):
h1 = F.relu(self.l1(x))
h2 = F.relu(self.l2(h1))
return self.l3(h2)
関数名が同じ名前の場合もあれば、L.Convolution2D ⇒ nn.Conv2d のように違う場合もあります。あまり調べていませんが、Noneにあたるものはつかえない?のかもしれません。
モデル・Optimizerセットアップ
# model = MLP()
# model.to_gpu()
# optimizer = optimizers.SGD(lr=0.01)
# optimizer.setup(model)
model = MLP()
model = model.to("cuda")
optimizer = optim.SGD(model.parameters(), lr=0.01)
学習
# y = model(x)
# loss = F.mean_squared_error(y, t)
# model.cleargrads()
# loss.backward()
# optimizer.update()
y = model(x)
loss = F.mse_loss(y, t)
model.zero_grad()
loss.backward()
optimizer.step()
最後に
今回とりあえず、今研究で使っているChainerのコードをPyTorchに手で書き換えを試して動かしてみました。Pytorchは全然使ったことはなかったですが、公式の移行ドキュメントやWebで都度調べるくらいで、1日で動くまでできました。基本的に似ているので、関数の対応を確認して、複数あるところは置換使ってというのを地道に続ければOKでした。
だた、動かしてみるとwindowsで約2割、ubuntuで約1割程度遅くなったので、いつ完全移行するかはゆっくり考えてみようと思います。
Chainerを使って4年経ちますが、Chainerがなかったら深層学習の世界に入ることはなく、普通のサラリーマンを続けていたかもしれません。良かったかはまだわかりませんが、研究生活はそれなりに楽しく過ごせております。
Chainerの皆様、ありがとうございました!