24
26

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

PyTorch Tutorials 1/5, 2/5

Last updated at Posted at 2018-01-19

注意!

PyTorch 0.4 以降、Variableは非推奨となり、Tensorに統合されました。

Welcome to the migration guide for PyTorch 0.4.0. In this release we introduced many exciting new features and critical bug fixes, with the goal of providing users a better and cleaner interface. In this guide, we will cover the most important changes in migrating existing code from previous versions:
・ Tensors and Variables have merged

よって、本記事の内容は一部サポートされていませんので、0.4向けに改変された元のTutorialを見てください!

Pytorch Tutorial

References:

公式ドキュメント:PyTorch Tutorials
このノートのソース:[Github]
(https://github.com/kenmikanmi/PyTorch_Tutorials_in_hand/blob/master/Pytorch_Tutorials_.ipynb)

本記事について

基本的に,PyTorch初心者向けの公式ドキュメントに記載してあるコードを動かしたものです。公式ドキュメントには,以下の5つのチュートリアルがあり,一応60分で全体をさらうことができるみたいです。

Screenshot from 2018-01-19 19-50-44.png

このノートは,公式ドキュメントに公開されているチュートリアルのうち,最初の2つ:

  • What is PyTorch?
  • Autograd: automatic differentiation

の日本語訳と,適宜説明を追加しています。

余談ですが,PyTorchがなんたるかを知るにはこちらの記事が良いと思います:
https://qiita.com/miyamotok0105/items/1fd1d5c3532b174720cd

いきさつ(読まなくても良い)

研究でこれまで色々論文を読んできたけれど,学習済みモデルをベースに,自分のタスクに対応した学習を行う必要がでてきました。論文著者の公開している学習済みモデルがTorch7の形式(.t7)で保存されていたのですが,Torch7ライブラリを使うにはプログラミング言語luaを新しく学ばなくてはならない…

そんななか,Torch7のモデルを簡単に利用できる別のPythonベースのライブラリPyTorchがあることを知り,軽く使ってみた所PyTorchいけそう・・・と思ったので,一から勉強することにしました。

PyTorchの公式ドキュメントのチュートリアルがわかりやすいという情報を得たので,jupyter notebookでちまちま動かしてみたものを,後で参照しやすいようにまとめました。このノートのソースの方が見やすいと思います。ツッコミ歓迎ですm(._.)m

PyTorchとは

  • 深層学習研究のプラットフォーム
  • numpyよりも優れた,GPU上での計算の仕組みを提供する

なるほど。

はじめに

Tensors

PyTorchの基本はtorch.Tensorに含まれるTensor型です。
Tensornumpy.ndarrayに似ているが,TensorはGPU上での計算において優れた型です。

これからTensorの使い方を軽く見てみましょう:

from __future__ import print_function
import torch

初期化されていない(5, 3)行列をTensor型で宣言すると:

x = torch.Tensor(5, 3)
x
-1.9742e-22  4.5800e-41  4.0313e+05
 3.0777e-41  1.6255e-43  1.5554e-43
 1.5975e-43  1.3873e-43  1.4574e-43
 6.4460e-44  1.5975e-43  1.3593e-43
 1.5414e-43  1.4013e-43  1.5414e-43
[torch.FloatTensor of size 5x3]

乱数で初期化した(5, 3)行列をTensor型で宣言すると

x = torch.rand(5, 3)
x
 0.3983  0.2964  0.2377
 0.9519  0.3093  0.3955
 0.4799  0.2055  0.6707
 0.8251  0.8141  0.7262
 0.9655  0.8692  0.6213
[torch.FloatTensor of size 5x3]

サイズの確認は:

x.size()
torch.Size([5, 3])

Operations:演算

Tensorは様々な方法で四則演算できる。

例えば,加算1つとっても4つくらいの方法がある。

加算方法1:

y = torch.rand(5, 3)
x + y
 0.6591  0.3766  1.1684
 1.8462  0.7029  0.9779
 1.4392  0.5668  0.9335
 1.1356  1.1658  0.9240
 1.8273  1.0639  1.0738
[torch.FloatTensor of size 5x3]

加算方法2:

print(x + y)
 0.6591  0.3766  1.1684
 1.8462  0.7029  0.9779
 1.4392  0.5668  0.9335
 1.1356  1.1658  0.9240
 1.8273  1.0639  1.0738
[torch.FloatTensor of size 5x3]

加算方法3:

result = torch.Tensor(5, 3)      # make empty (5, 3) Tensor
torch.add(x, y, out = result)    # input x + y to Tensor
result
 0.6591  0.3766  1.1684
 1.8462  0.7029  0.9779
 1.4392  0.5668  0.9335
 1.1356  1.1658  0.9240
 1.8273  1.0639  1.0738
[torch.FloatTensor of size 5x3]

加算方法4:

y.add_(x)     # "add_(x)" -> y = y + x 
y
 0.6591  0.3766  1.1684
 1.8462  0.7029  0.9779
 1.4392  0.5668  0.9335
 1.1356  1.1658  0.9240
 1.8273  1.0639  1.0738
[torch.FloatTensor of size 5x3]

Note

基本的に,演算の関数の後に _ がついているものは代入の操作を表す。
上記の例でy.add_(x)は,y = y+xを行うことと同じ。


numpyと同じように,次のようにインデックスを指定できる。

x[:, 1]
 0.2964
 0.3093
 0.2055
 0.8141
 0.8692
[torch.FloatTensor of size 5]

あとで読みたい

Tensorの演算は他にも,インデックス,スライス,線形代数の演算などが100以上ある。詳細はこちら


Torch.Tensornumpyを行ったり来たり

Torch.Tensornumpyの要素は,同じメモリの場所に格納されており,相互の変換は簡単にできる。

numpyへの変換

a = torch.ones(5)
a
 1
 1
 1
 1
 1
[torch.FloatTensor of size 5]
b = a.numpy()
b
array([ 1.,  1.,  1.,  1.,  1.], dtype=float32)

ここで,面白いことに…

a.add_(1)
print(a)
print(b)
 2
 2
 2
 2
 2
[torch.FloatTensor of size 5]

[ 2.  2.  2.  2.  2.]

torch.Tensorに変換

import numpy as np

a = np.ones(5)
b = torch.from_numpy(a)
np.add(a, 1, out=a)
print(a)
print(b)
[ 2.  2.  2.  2.  2.]

 2
 2
 2
 2
 2
[torch.DoubleTensor of size 5]

CPU上のTensorは,全てnumpyに変換できるらしい(GPU上のTensorは変換できないということだろうか?)。

autogradVariable

Autogradは”automatic differentiation”のことで,そのパッケージであるautogradはPyTorchの中核を担っている。これから,autogradに少し触れてみて,それをもとにニューラルネットワークを学習させてみよう。

autogradパッケージは,Tensorの全ての演算に対して自動微分を行うためのもの。これは,PyTorchの特徴である"define-by-run"を実現している。つまり,順伝播のコードを書くだけで逆伝播が定義できる。

Variable

  • autograd.Variableが,autogradの中心的なパッケージである。VariableTensorのラッパーであり,Tensorのほぼ全ての演算が含まれている。
  • ネットワークを定義してしまえば,.backward()を呼び出すだけで勾配計算を自動的に行うことができる。

Tensorの生データには.dataでアクセスできる。そして,Variableに関する勾配は.gradに蓄積されている。Variableの概念図を以下に示す。

概念図

Function

autogradに関して,もうひとつ重要なクラスがあります。それはFunctionと呼ばれるパッケージです。
VariableFunctionは内部でつながっていて,この2つによってニューラルネットワークのグラフが構築されます。そしてこのグラフに,ニューラルネットの計算の全ての履歴が残ります。

生成されたvariableのそれぞれに.grad_fnという属性があり,この属性によってどのFunctionによってvariableが生成されたのかを参照できる。ただし,ユーザによって作られたvariableの場合grad_fnNoneとなる。

variableの導関数を計算したいのであれば,variableがもっている.backward()を呼び出すと良い。もしvariableが単一の要素だけのとき,backward()には特に引数を指定する必要はないが,複数の要素をもつときは引数grad_outputを指定してやる必要がある(←どういうこと?)。

と言っても分かりづらいので,具体例を交えながら見ていきましょう。


import torch
from torch.autograd import Variable

variableを作ってみます:

x = Variable(torch.ones(2, 2), requires_grad = True)
x
Variable containing:
 1  1
 1  1
[torch.FloatTensor of size 2x2]

次に,variableの加算をしてみましょう:

y = x + 2
y
Variable containing:
 3  3
 3  3
[torch.FloatTensor of size 2x2]

さっき言ったように,何らかの演算の後に生成されたvariableには属性grad_fnが付与されます。ygrad_fnを参照してみると:

y.grad_fn
<AddBackward0 at 0x7fac69a8d320>

yにもっと色んな演算をしていきます:

z = y * y * 3
out = z.mean()
print(z, out)
Variable containing:
 27  27
 27  27
[torch.FloatTensor of size 2x2]
 Variable containing:
 27
[torch.FloatTensor of size 1]

勾配計算

いよいよ逆伝播の計算です。
次に行うout.backward()は,out.backward(torch.tensor([1.0]))と等価です。

out.backward()

勾配を出力してみましょう。勾配とはすなわち $\frac{d({\rm out})}{dx}$ のことです。

x.grad
Variable containing:
 4.5000  4.5000
 4.5000  4.5000
[torch.FloatTensor of size 2x2]

4.5の要素をもつ行列(テンソル)が得られました。これはどういうことなのでしょうか。

out Variable を"$o$"とします。$o$は,out = z.mean()で定義したので,次式で得られます。

$o = \frac{1}{4}\sum_i z_i$

ここで,$z_i = 3(x_i + 2)^2$ですから,

$\frac{\partial o}{\partial x_i}=\frac{3}{2}(x_i + 2)$

$x_i$の各要素は$1$なので,

$\frac{\partial o}{\partial x_i}|_{x_i = 1} = 4.5$

確かに,Variableには過去の計算の履歴が残っていましたね!


autogradを使えば,もっとクレイジーなことができる!

import torch
x = torch.randn(3)
x = Variable(x, requires_grad=True)

y = x * 2
while y.data.norm() < 1000:
    y = y * 2

print(y)
Variable containing:
-1453.1710
  229.0913
  -37.1547
[torch.FloatTensor of size 3]
gradients = torch.FloatTensor([0.1, 1.0, 0.0001])
y.backward(gradients)

print(x.grad)
Variable containing:
  51.2000
 512.0000
   0.0512
[torch.FloatTensor of size 3]

この上記の操作は何を意味しているのでしょうか…?(疑問)


Python歴1年半で,プログラミング言語やライブラリのリテラシーがあまりない僕にもなんとなくわかったような気がします。

次のチュートリアルへ

24
26
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
26

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?