forked from PyTorchKorea/tutorials-kr
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathautogradqs_tutorial.py
More file actions
214 lines (181 loc) Β· 11 KB
/
autogradqs_tutorial.py
File metadata and controls
214 lines (181 loc) Β· 11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
"""
`νμ΄ν μΉ(PyTorch) κΈ°λ³Έ μ΅νκΈ° <intro.html>`_ ||
`λΉ λ₯Έ μμ <quickstart_tutorial.html>`_ ||
`ν
μ(Tensor) <tensorqs_tutorial.html>`_ ||
`Datasetκ³Ό Dataloader <data_tutorial.html>`_ ||
`λ³ν(Transform) <transforms_tutorial.html>`_ ||
`μ κ²½λ§ λͺ¨λΈ ꡬμ±νκΈ° <buildmodel_tutorial.html>`_ ||
**Autograd** ||
`μ΅μ ν(Optimization) <optimization_tutorial.html>`_ ||
`λͺ¨λΈ μ μ₯νκ³ λΆλ¬μ€κΈ° <saveloadrun_tutorial.html>`_
``torch.autograd``\ λ₯Ό μ¬μ©ν μλ λ―ΈλΆ
==========================================================================
μ κ²½λ§μ νμ΅ν λ κ°μ₯ μμ£Ό μ¬μ©λλ μκ³ λ¦¬μ¦μ **μμ ν**\ μ
λλ€. μ΄ μκ³ λ¦¬μ¦μμ,
λ§€κ°λ³μ(λͺ¨λΈ κ°μ€μΉ)λ μ£Όμ΄μ§ λ§€κ°λ³μμ λν μμ€ ν¨μμ **λ³νλ(gradient)**\ μ
λ°λΌ μ‘°μ λ©λλ€.
μ΄λ¬ν λ³νλλ₯Ό κ³μ°νκΈ° μν΄ PyTorchμλ ``torch.autograd``\ λΌκ³ λΆλ¦¬λ μλ λ―ΈλΆ μμ§μ΄
λ΄μ₯λμ΄ μμ΅λλ€. μ΄λ λͺ¨λ κ³μ° κ·Έλνμ λν λ³νλμ μλ κ³μ°μ μ§μν©λλ€.
μ
λ ₯ ``x``, λ§€κ°λ³μ ``w``\ μ ``b`` , κ·Έλ¦¬κ³ μΌλΆ μμ€ ν¨μκ° μλ κ°μ₯ κ°λ¨ν λ¨μΌ κ³μΈ΅
μ κ²½λ§μ κ°μ νκ² μ΅λλ€. PyTorchμμλ λ€μκ³Ό κ°μ΄ μ μν μ μμ΅λλ€:
"""
import torch
x = torch.ones(5) # input tensor
y = torch.zeros(3) # expected output
w = torch.randn(5, 3, requires_grad=True)
b = torch.randn(3, requires_grad=True)
z = torch.matmul(x, w)+b
loss = torch.nn.functional.binary_cross_entropy_with_logits(z, y)
######################################################################
# Tensor, Functionκ³Ό μ°μ°κ·Έλν(Computational graph)
# --------------------------------------------------------------
#
# μ΄ μ½λλ λ€μμ **μ°μ° κ·Έλν** λ₯Ό μ μν©λλ€:
#
# .. figure:: /_static/img/basics/comp-graph.png
# :alt:
#
# μ΄ μ κ²½λ§μμ, ``w``\ μ ``b``\ λ μ΅μ νλ₯Ό ν΄μΌ νλ **λ§€κ°λ³μ**\ μ
λλ€. λ°λΌμ
# μ΄λ¬ν λ³μλ€μ λν μμ€ ν¨μμ λ³νλλ₯Ό κ³μ°ν μ μμ΄μΌ ν©λλ€. μ΄λ₯Ό μν΄μ ν΄λΉ ν
μμ
# ``requires_grad`` μμ±μ μ€μ ν©λλ€.
#######################################################################
# .. note:: ``requires_grad``\ μ κ°μ ν
μλ₯Ό μμ±ν λ μ€μ νκ±°λ, λμ€μ
# ``x.requires_grad_(True)`` λ©μλλ₯Ό μ¬μ©νμ¬ λμ€μ μ€μ ν μλ μμ΅λλ€.
#######################################################################
# μ°μ° κ·Έλνλ₯Ό ꡬμ±νκΈ° μν΄ ν
μμ μ μ©νλ ν¨μλ μ¬μ€ ``Function`` ν΄λμ€μ κ°μ²΄μ
λλ€.
# μ΄ κ°μ²΄λ *μμ ν* λ°©ν₯μΌλ‘ ν¨μλ₯Ό κ³μ°νλ λ°©λ²κ³Ό, *μλ°©ν₯ μ ν* λ¨κ³μμ λν¨μ(derivative)λ₯Ό
# κ³μ°νλ λ°©λ²μ μκ³ μμ΅λλ€. μλ°©ν₯ μ ν ν¨μμ λν μ°Έμ‘°(reference)λ ν
μμ ``grad_fn``
# μμ±μ μ μ₯λ©λλ€. ``Function``\ μ λν μμΈν μ 보λ
# `μ΄ λ¬Έμ <https://pytorch.org/docs/stable/autograd.html#function>`__
# μμ μ°Ύμλ³Ό μ μμ΅λλ€.
#
print(f"Gradient function for z = {z.grad_fn}")
print(f"Gradient function for loss = {loss.grad_fn}")
######################################################################
# λ³νλ(Gradient) κ³μ°νκΈ°
# --------------------------------------------------------------
#
# μ κ²½λ§μμ λ§€κ°λ³μμ κ°μ€μΉλ₯Ό μ΅μ ννλ €λ©΄ λ§€κ°λ³μμ λν μμ€ν¨μμ λν¨μ(derivative)λ₯Ό
# κ³μ°ν΄μΌ ν©λλ€. μ¦, ``x``\ μ ``y``\ μ μΌλΆ κ³ μ κ°μμ :math:`\frac{\partial loss}{\partial w}`\ μ
# :math:`\frac{\partial loss}{\partial b}` κ° νμν©λλ€.
# μ΄λ¬ν λν¨μλ₯Ό κ³μ°νκΈ° μν΄, ``loss.backward()`` λ₯Ό νΈμΆν λ€μ ``w.grad``\ μ
# ``b.grad``\ μμ κ°μ κ°μ Έμ΅λλ€:
#
loss.backward()
print(w.grad)
print(b.grad)
######################################################################
# .. note::
# - μ°μ° κ·Έλνμ μ(leaf) λ
Έλλ€ μ€ ``requires_grad`` μμ±μ΄ ``True``\ λ‘ μ€μ λ
# λ
Έλλ€μ ``grad`` μμ±λ§ ꡬν μ μμ΅λλ€. κ·Έλνμ λ€λ₯Έ λͺ¨λ λ
Έλμμλ λ³νλκ°
# μ ν¨νμ§ μμ΅λλ€.
# - μ±λ₯ μμ μ΄μ λ‘, μ£Όμ΄μ§ κ·Έλνμμμ ``backward``\ λ₯Ό μ¬μ©ν λ³νλ κ³μ°μ ν λ²λ§
# μνν μ μμ΅λλ€. λ§μ½ λμΌν κ·Έλνμμ μ¬λ¬λ²μ ``backward`` νΈμΆμ΄ νμνλ©΄,
# ``backward`` νΈμΆ μμ ``retrain_graph=True``\ λ₯Ό μ λ¬ν΄μΌ ν©λλ€.
#
######################################################################
# λ³νλ μΆμ λ©μΆκΈ°
# --------------------------------------------------------------
#
# κΈ°λ³Έμ μΌλ‘, ``requires_grad=True``\ μΈ λͺ¨λ ν
μλ€μ μ°μ° κΈ°λ‘μ μΆμ νκ³ λ³νλ κ³μ°μ
# μ§μν©λλ€. κ·Έλ¬λ λͺ¨λΈμ νμ΅ν λ€ μ
λ ₯ λ°μ΄ν°λ₯Ό λ¨μν μ μ©νκΈ°λ§ νλ κ²½μ°μ κ°μ΄ *μμ ν*
# μ°μ°λ§ νμν κ²½μ°μλ, μ΄λ¬ν μΆμ μ΄λ μ§μμ΄ νμ μμ μ μμ΅λλ€.
# μ°μ° μ½λλ₯Ό ``torch.no_grad()`` λΈλ‘μΌλ‘ λλ¬μΈμ μ°μ° μΆμ μ λ©μΆ μ μμ΅λλ€:
#
z = torch.matmul(x, w)+b
print(z.requires_grad)
with torch.no_grad():
z = torch.matmul(x, w)+b
print(z.requires_grad)
######################################################################
# λμΌν κ²°κ³Όλ₯Ό μ»λ λ€λ₯Έ λ°©λ²μ ν
μμ ``detach()`` λ©μλλ₯Ό μ¬μ©νλ κ²μ
λλ€:
#
z = torch.matmul(x, w)+b
z_det = z.detach()
print(z_det.requires_grad)
######################################################################
# λ³νλ μΆμ μ λ©μΆ°μΌ νλ μ΄μ λ€μ λ€μκ³Ό κ°μ΅λλ€:
# - μ κ²½λ§μ μΌλΆ λ§€κ°λ³μλ₯Ό **κ³ μ λ λ§€κ°λ³μ(frozen parameter)**\ λ‘ νμν©λλ€.
# - λ³νλλ₯Ό μΆμ νμ§ μλ ν
μμ μ°μ°μ΄ λ ν¨μ¨μ μ΄κΈ° λλ¬Έμ, μμ ν λ¨κ³λ§ μνν λ
# **μ°μ° μλκ° ν₯μλ©λλ€.**
######################################################################
######################################################################
# μ°μ° κ·Έλνμ λν μΆκ° μ 보
# --------------------------------------------------------------
#
# κ°λ
μ μΌλ‘, autogradλ λ°μ΄ν°(ν
μ)μ λ° μ€νλ λͺ¨λ μ°μ°λ€(λ° μ°μ° κ²°κ³Όκ° μλ‘μ΄ ν
μμΈ κ²½μ°λ ν¬ν¨νμ¬)μ
# κΈ°λ‘μ `Function <https://pytorch.org/docs/stable/autograd.html#torch.autograd.Function>`__ κ°μ²΄λ‘
# ꡬμ±λ λ°©ν₯μ± λΉμν κ·Έλν(DAG; Directed Acyclic Graph)μ μ μ₯(keep)ν©λλ€.
# μ΄ λ°©ν₯μ± λΉμν κ·Έλν(DAG)μ μ(leave)μ μ
λ ₯ ν
μμ΄κ³ , λΏλ¦¬(root)λ κ²°κ³Ό ν
μμ
λλ€.
# μ΄ κ·Έλνλ₯Ό λΏλ¦¬μμλΆν° μκΉμ§ μΆμ νλ©΄ μ°μ λ²μΉ(chain rule)μ λ°λΌ λ³νλλ₯Ό μλμΌλ‘ κ³μ°ν μ μμ΅λλ€.
#
# μμ ν λ¨κ³μμ, autogradλ λ€μ λ κ°μ§ μμ
μ λμμ μνν©λλ€:
#
# - μμ²λ μ°μ°μ μννμ¬ κ²°κ³Ό ν
μλ₯Ό κ³μ°νκ³ ,
# - DAGμ μ°μ°μ *λ³νλ κΈ°λ₯(gradient function)* λ₯Ό μ μ§(maintain)ν©λλ€.
#
# μμ ν λ¨κ³λ DAG λΏλ¦¬(root)μμ ``.backward()`` κ° νΈμΆλ λ μμλ©λλ€. ``autograd``\ λ μ΄ λ:
#
# - κ° ``.grad_fn`` μΌλ‘λΆν° λ³νλλ₯Ό κ³μ°νκ³ ,
# - κ° ν
μμ ``.grad`` μμ±μ κ³μ° κ²°κ³Όλ₯Ό μκ³ (accumulate),
# - μ°μ λ²μΉμ μ¬μ©νμ¬, λͺ¨λ μ(leaf) ν
μλ€κΉμ§ μ ν(propagate)ν©λλ€.
#
# .. note::
# **PyTorchμμ DAGλ€μ λμ (dynamic)μ
λλ€.**
# μ£Όλͺ©ν΄μΌ ν μ€μν μ μ κ·Έλνκ° μ²μλΆν°(from scratch) λ€μ μμ±λλ€λ κ²μ
λλ€; λ§€λ² ``.backward()`` κ°
# νΈμΆλκ³ λλ©΄, autogradλ μλ‘μ΄ κ·Έλνλ₯Ό μ±μ°κΈ°(populate) μμν©λλ€. μ΄λ¬ν μ λλΆμ λͺ¨λΈμμ
# νλ¦ μ μ΄(control flow) ꡬ문λ€μ μ¬μ©ν μ μκ² λλ κ²μ
λλ€; λ§€λ² λ°λ³΅(iteration)ν λλ§λ€ νμνλ©΄
# λͺ¨μ(shape)μ΄λ ν¬κΈ°(size), μ°μ°(operation)μ λ°κΏ μ μμ΅λλ€.
######################################################################
# μ νμ μΌλ‘ μ½κΈ°(Optional Reading): ν
μ λ³νλμ μΌμ½λΉμ κ³± (Jacobian Product)
# ------------------------------------------------------------------------------------------
#
# λλΆλΆμ κ²½μ°, μ€μΉΌλΌ μμ€ ν¨μλ₯Ό κ°μ§κ³ μΌλΆ λ§€κ°λ³μμ κ΄λ ¨ν λ³νλλ₯Ό κ³μ°ν΄μΌ ν©λλ€.
# κ·Έλ¬λ μΆλ ₯ ν¨μκ° μμμ ν
μμΈ κ²½μ°κ° μμ΅λλ€. μ΄λ΄ λ, PyTorchλ μ€μ λ³νλκ° μλ
# **μΌμ½λΉμ κ³±(Jacobian product)**\ μ κ³μ°ν©λλ€.
#
# :math:`\vec{x}=\langle x_1,\dots,x_n\rangle`\ μ΄κ³ ,
# :math:`\vec{y}=\langle y_1,\dots,y_m\rangle`\ μΌ λ
# λ²‘ν° ν¨μ :math:`\vec{y}=f(\vec{x})`\ μμ :math:`\vec{x}`\ μ λν
# :math:`\vec{y}` μ λ³νλλ **μΌμ½λΉμ νλ ¬(Jacobian matrix)**\ λ‘ μ£Όμ΄μ§λλ€:
#
# .. math::
#
#
# J=\left(\begin{array}{ccc}
# \frac{\partial y_{1}}{\partial x_{1}} & \cdots & \frac{\partial y_{1}}{\partial x_{n}}\\
# \vdots & \ddots & \vdots\\
# \frac{\partial y_{m}}{\partial x_{1}} & \cdots & \frac{\partial y_{m}}{\partial x_{n}}
# \end{array}\right)
#
# μΌμ½λΉμ νλ ¬ μ체λ₯Ό κ³μ°νλ λμ , PyTorchλ μ£Όμ΄μ§ μ
λ ₯ λ²‘ν° :math:`v=(v_1 \dots v_m)`\ μ λν
# **μΌμ½λΉμ κ³±(Jacobian Product)** :math:`v^T\cdot J`\ μ κ³μ°ν©λλ€.
# μ΄ κ³Όμ μ :math:`v`\ λ₯Ό μΈμλ‘ ``backward``\ λ₯Ό νΈμΆνλ©΄ μ΄λ€μ§λλ€. :math:`v`\ μ ν¬κΈ°λ
# κ³±(product)μ κ³μ°νλ €κ³ νλ μλ ν
μμ ν¬κΈ°μ κ°μμΌ ν©λλ€.
#
inp = torch.eye(4, 5, requires_grad=True)
out = (inp+1).pow(2).t()
out.backward(torch.ones_like(out), retain_graph=True)
print(f"First call\n{inp.grad}")
out.backward(torch.ones_like(out), retain_graph=True)
print(f"\nSecond call\n{inp.grad}")
inp.grad.zero_()
out.backward(torch.ones_like(out), retain_graph=True)
print(f"\nCall after zeroing gradients\n{inp.grad}")
######################################################################
# λμΌν μΈμλ‘ ``backward``\ λ₯Ό λμ°¨λ‘ νΈμΆνλ©΄ λ³νλ κ°μ΄ λ¬λΌμ§λλ€.
# μ΄λ ``μλ°©ν₯`` μ νλ₯Ό μνν λ, PyTorchκ° **λ³νλλ₯Ό λμ (accumulate)ν΄μ£ΌκΈ° λλ¬Έ**\
# μ
λλ€. μ¦, κ³μ°λ λ³νλμ κ°μ΄ μ°μ° κ·Έλνμ λͺ¨λ μ(leaf) λ
Έλμ ``grad`` μμ±μ
# μΆκ°λ©λλ€. λ°λΌμ μ λλ‘ λ λ³νλλ₯Ό κ³μ°νκΈ° μν΄μλ ``grad`` μμ±μ λ¨Όμ 0μΌλ‘ λ§λ€μ΄μΌ
# ν©λλ€. μ€μ νμ΅ κ³Όμ μμλ *μ΅ν°λ§μ΄μ (optimizer)*\ κ° μ΄ κ³Όμ μ λμμ€λλ€.
######################################################################
# .. note:: μ΄μ μλ λ§€κ°λ³μ μμ΄ ``backward()`` ν¨μλ₯Ό νΈμΆνμ΅λλ€. μ΄λ λ³Έμ§μ μΌλ‘
# ``backward(torch.tensor(1.0))`` μ νΈμΆνλ κ²κ³Ό λμΌνλ©°,
# μ κ²½λ§ νλ ¨ μ€μ μμ€κ³Ό κ°μ μ€μΉΌλΌ-κ° ν¨μμ λ³νλλ₯Ό κ³μ°νλ μ μ©ν λ°©λ²μ
λλ€.
#
######################################################################
# --------------
#
#################################################################
# λ μ½μ΄λ³΄κΈ°
# ~~~~~~~~~~~~~~~~~
# - `Autograd Mechanics <https://pytorch.org/docs/stable/notes/autograd.html>`_