24
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

updated at

Chainer ⇒ PyTorch移行を試してみた

今週、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分足らずで完了します。

20191207_01.png

$ 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の皆様、ありがとうございました!

参考

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
24
Help us understand the problem. What are the problem?