|
1 | 1 | # -*- coding: utf-8 -*- |
2 | 2 | r""" |
3 | | -Introduction to PyTorch |
| 3 | +PyTorch ์๊ฐ |
4 | 4 | *********************** |
| 5 | +**๋ฒ์ญ**: `๋ฐ๋ณด์ <https://github.com/2kkeullim>`_ |
5 | 6 |
|
6 | | -Introduction to Torch's tensor library |
| 7 | +Torch์ tensor ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์๊ฐ |
7 | 8 | ====================================== |
8 | 9 |
|
9 | | -All of deep learning is computations on tensors, which are |
10 | | -generalizations of a matrix that can be indexed in more than 2 |
11 | | -dimensions. We will see exactly what this means in-depth later. First, |
12 | | -let's look what we can do with tensors. |
| 10 | +๋ฅ๋ฌ๋์ ๋ชจ๋ tensor์ ๋ํ ์ฐ์ฐ์ผ๋ก, |
| 11 | +2์ฐจ์ ์ด์์์ ์ธ๋ฑ์ฑํ ์ ์๋ ํ๋ ฌ์ ์ผ๋ฐํ์
๋๋ค. |
| 12 | +์ด๊ฒ์ด ์ ํํ ๋ฌด์์ ์๋ฏธํ๋์ง๋ ๋์ค์ ์์ธํ ์์๋ณด๊ฒ ์ต๋๋ค. |
| 13 | +๋จผ์ tensor๋ก ๋ฌด์์ ํ ์ ์๋์ง ์์๋ณด๊ฒ ์ต๋๋ค. |
13 | 14 | """ |
14 | 15 | # Author: Robert Guthrie |
15 | 16 |
|
|
19 | 20 |
|
20 | 21 |
|
21 | 22 | ###################################################################### |
22 | | -# Creating Tensors |
| 23 | +# Tensor ์์ฑํ๊ธฐ |
23 | 24 | # ~~~~~~~~~~~~~~~~ |
24 | 25 | # |
25 | | -# Tensors can be created from Python lists with the torch.tensor() |
26 | | -# function. |
| 26 | +# torch.tensor() ํจ์๋ฅผ ์ฌ์ฉํ์ฌ Python ๋ฆฌ์คํธ๋ก๋ถํฐ |
| 27 | +# tensor๋ฅผ ์์ฑํ ์ ์์ต๋๋ค. |
27 | 28 | # |
28 | 29 |
|
29 | | -# torch.tensor(data) creates a torch.Tensor object with the given data. |
| 30 | +# torch.tensor(data)๋ฅผ ํตํด ์ฃผ์ด์ง ๋ฐ์ดํฐ๋ก๋ถํฐ torch.Tensor object๋ฅผ ์์ฑํฉ๋๋ค. |
30 | 31 | V_data = [1., 2., 3.] |
31 | 32 | V = torch.tensor(V_data) |
32 | 33 | print(V) |
33 | 34 |
|
34 | | -# Creates a matrix |
| 35 | +# ํ๋ ฌ์ ์์ฑํฉ๋๋ค |
35 | 36 | M_data = [[1., 2., 3.], [4., 5., 6]] |
36 | 37 | M = torch.tensor(M_data) |
37 | 38 | print(M) |
38 | 39 |
|
39 | | -# Create a 3D tensor of size 2x2x2. |
| 40 | +# 2x2x2 ํฌ๊ธฐ์ 3D tensor๋ฅผ ์์ฑํฉ๋๋ค. |
40 | 41 | T_data = [[[1., 2.], [3., 4.]], |
41 | 42 | [[5., 6.], [7., 8.]]] |
42 | 43 | T = torch.tensor(T_data) |
43 | 44 | print(T) |
44 | 45 |
|
45 | 46 |
|
46 | 47 | ###################################################################### |
47 | | -# What is a 3D tensor anyway? Think about it like this. If you have a |
48 | | -# vector, indexing into the vector gives you a scalar. If you have a |
49 | | -# matrix, indexing into the matrix gives you a vector. If you have a 3D |
50 | | -# tensor, then indexing into the tensor gives you a matrix! |
| 48 | +# ๋๋์ฒด 3D tensor๋ ๋ฌด์์ผ๊น์? ์ด๋ ๊ฒ ์๊ฐํด ๋ณด์ธ์. |
| 49 | +# ๋ฒกํฐ์ ๊ฒฝ์ฐ, ์ธ๋ฑ์ฑํ๋ฉด ์ค์นผ๋ผ๊ฐ ์ถ๋ ฅ๋ฉ๋๋ค. |
| 50 | +# ํ๋ ฌ์ ๊ฒฝ์ฐ, ์ธ๋ฑ์ฑํ๋ฉด ๋ฒกํฐ๊ฐ ์ถ๋ ฅ๋ฉ๋๋ค. |
| 51 | +# 3D tensor์ ๊ฒฝ์ฐ, ์ธ๋ฑ์ฑํ๋ฉด ํ๋ ฌ์ด ์ถ๋ ฅ๋ฉ๋๋ค! |
51 | 52 | # |
52 | | -# A note on terminology: |
53 | | -# when I say "tensor" in this tutorial, it refers |
54 | | -# to any torch.Tensor object. Matrices and vectors are special cases of |
55 | | -# torch.Tensors, where their dimension is 2 and 1 respectively. When I am |
56 | | -# talking about 3D tensors, I will explicitly use the term "3D tensor". |
| 53 | +# ์ฉ์ด ๋
ธํธ: |
| 54 | +# ์ด ํํ ๋ฆฌ์ผ์์ "tensor" ๋ผ๋ ์ฉ์ด๋ torch.Tensor object๋ฅผ |
| 55 | +# ๋ํ๋
๋๋ค. ํ๋ ฌ๊ณผ ๋ฒกํฐ๋ torch.Tensor์ ์ฐจ์์ด 2, 1์ธ |
| 56 | +# ํน๋ณํ ๊ฒฝ์ฐ์
๋๋ค. 3D tensor์ ๋ํ |
| 57 | +# ์ฉ์ด๋ฅผ ํํํ ๋๋ ๋ช
๋ฐฑํ๊ฒ "3D tensor" ๋ผ๋ ์ฉ์ด๋ฅผ ์ฌ์ฉํ ๊ฒ์
๋๋ค. |
57 | 58 | # |
58 | 59 |
|
59 | | -# Index into V and get a scalar (0 dimensional tensor) |
| 60 | +# V์์ ์ธ๋ฑ์ฑํ์ฌ ์ค์นผ๋ผ ์ป๊ธฐ (0 ์ฐจ์ tensor) |
60 | 61 | print(V[0]) |
61 | | -# Get a Python number from it |
62 | | -print(V[0].item()) |
| 62 | +# ๋ฒกํฐ๋ก๋ถํฐ Python ์ซ์ ์ป๊ธฐ |
63 | 63 |
|
64 | | -# Index into M and get a vector |
| 64 | +# M์์ ์ธ๋ฑ์ฑํ์ฌ ๋ฒกํฐ ์ป๊ธฐ |
65 | 65 | print(M[0]) |
66 | 66 |
|
67 | | -# Index into T and get a matrix |
| 67 | +# T์์ ์ธ๋ฑ์ฑํ์ฌ ํ๋ ฌ ์ป๊ธฐ |
68 | 68 | print(T[0]) |
69 | 69 |
|
70 | 70 |
|
71 | 71 | ###################################################################### |
72 | | -# You can also create tensors of other data types. To create a tensor of integer types, try |
73 | | -# torch.tensor([[1, 2], [3, 4]]) (where all elements in the list are integers). |
74 | | -# You can also specify a data type by passing in ``dtype=torch.data_type``. |
75 | | -# Check the documentation for more data types, but |
76 | | -# Float and Long will be the most common. |
| 72 | +# ๋ค๋ฅธ ๋ฐ์ดํฐ ํ์
์ tensor๋ฅผ ์์ฑํ ์๋ ์์ต๋๋ค. integer ํ์
์ tensor๋ |
| 73 | +# torch.tensor([[1, 2], [3, 4]])์ผ๋ก ๋ง๋ค ์ ์์ต๋๋ค. (์ด ๋, ๋ฆฌ์คํธ์ ๋ชจ๋ ์์๋ integer) |
| 74 | +# ๋ํ ``dtype=torch.data_type`` ์ ์ด์ฉํด ๋ฐ์ดํฐ ํ์
์ ์ง์ ํ ์๋ ์์ต๋๋ค. |
| 75 | +# ์ถ๊ฐ์ ์ธ ๋ฐ์ดํฐ ํ์
์ ๋ํด์๋ ๋ฌธ์๋ก ํ์ธํ ์ ์์ผ๋ฉฐ, |
| 76 | +# Float์ Long์ด ๊ฐ์ฅ ์ผ๋ฐ์ ์
๋๋ค. |
77 | 77 | # |
78 | 78 |
|
79 | 79 |
|
80 | 80 | ###################################################################### |
81 | | -# You can create a tensor with random data and the supplied dimensionality |
82 | | -# with torch.randn() |
| 81 | +# torch.randn() ์ผ๋ก ์ ๊ณตํ ์ฐจ์์ ์ฌ์ฉํด |
| 82 | +# ๋๋ค ๋ฐ์ดํฐ๋ก tensor๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค. |
83 | 83 | # |
84 | 84 |
|
85 | 85 | x = torch.randn((3, 4, 5)) |
86 | 86 | print(x) |
87 | 87 |
|
88 | 88 |
|
89 | 89 | ###################################################################### |
90 | | -# Operations with Tensors |
| 90 | +# Tensor ๋ฅผ ์ฌ์ฉํ ์ฐ์ฐ |
91 | 91 | # ~~~~~~~~~~~~~~~~~~~~~~~ |
92 | 92 | # |
93 | | -# You can operate on tensors in the ways you would expect. |
| 93 | +# tensor๋ ์ํ๋ ๋ฐฉ์์ผ๋ก ์ฐ์ฐํ ์ ์์ต๋๋ค. |
94 | 94 |
|
95 | 95 | x = torch.tensor([1., 2., 3.]) |
96 | 96 | y = torch.tensor([4., 5., 6.]) |
|
99 | 99 |
|
100 | 100 |
|
101 | 101 | ###################################################################### |
102 | | -# See `the documentation <https://pytorch.org/docs/torch.html>`__ for a |
103 | | -# complete list of the massive number of operations available to you. They |
104 | | -# expand beyond just mathematical operations. |
| 102 | +# `๋ฌธ์ <https://pytorch.org/docs/torch.html>`__ ์์ |
| 103 | +# ์ฌ์ฉํ ์ ์๋ ์์ฒญ๋ ์์ ์ฐ์ฐ๋ค์ ์ ์ฒด ๋ชฉ๋ก์ ๋ณผ ์ ์์ต๋๋ค. |
| 104 | +# ํด๋น ์ฐ์ฐ ๋ชฉ๋ก์ ๋จ์ํ ์ํ์ ์ธ ์ฐ์ฐ์ ๋ฐ์ด๋์ต๋๋ค. |
105 | 105 | # |
106 | | -# One helpful operation that we will make use of later is concatenation. |
| 106 | +# ๋์ค์ ์ฌ์ฉํ ์ ์ฉํ ์ฐ์ฐ ์ค ํ๋๋ ๊ฒฐํฉ(concatenation)์
๋๋ค. |
107 | 107 | # |
108 | 108 |
|
109 | | -# By default, it concatenates along the first axis (concatenates rows) |
| 109 | +# ๊ธฐ๋ณธ์ ์ผ๋ก ์ฒซ ๋ฒ์งธ ์ถ์ ๋ฐ๋ผ ๊ฒฐํฉ๋ฉ๋๋ค (ํ(row) ๊ฒฐํฉ) |
110 | 110 | x_1 = torch.randn(2, 5) |
111 | 111 | y_1 = torch.randn(3, 5) |
112 | 112 | z_1 = torch.cat([x_1, y_1]) |
113 | 113 | print(z_1) |
114 | 114 |
|
115 | | -# Concatenate columns: |
| 115 | +# ์ด(column) ๊ฒฐํฉ |
116 | 116 | x_2 = torch.randn(2, 3) |
117 | 117 | y_2 = torch.randn(2, 5) |
118 | | -# second arg specifies which axis to concat along |
| 118 | +# ๋ ๋ฒ์งธ ์ธ์๋ ์ฐ๊ฒฐํ ์ถ์ ์ง์ ํฉ๋๋ค |
119 | 119 | z_2 = torch.cat([x_2, y_2], 1) |
120 | 120 | print(z_2) |
121 | 121 |
|
122 | | -# If your tensors are not compatible, torch will complain. Uncomment to see the error |
| 122 | +# tensor๊ฐ ํธํ๋์ง ์์ผ๋ฉด torch๊ฐ ๋ถํํ ๊ฒ๋๋ค. ๋ฐ์ ๋ช
๋ น์ด๋ฅผ ์ฃผ์ ํด์ ํ์ฌ ์๋ฌ๋ฅผ ์ถ๋ ฅํด๋ณด์ธ์ |
123 | 123 | # torch.cat([x_1, x_2]) |
124 | 124 |
|
125 | | - |
126 | 125 | ###################################################################### |
127 | | -# Reshaping Tensors |
| 126 | +# Tensor ๊ตฌ์กฐ ๋ฐ๊พธ๊ธฐ |
128 | 127 | # ~~~~~~~~~~~~~~~~~ |
129 | 128 | # |
130 | | -# Use the .view() method to reshape a tensor. This method receives heavy |
131 | | -# use, because many neural network components expect their inputs to have |
132 | | -# a certain shape. Often you will need to reshape before passing your data |
133 | | -# to the component. |
| 129 | +# .view() ๋ฉ์๋๋ฅผ ์ฌ์ฉํด tensor์ ๊ตฌ์กฐ๋ฅผ ๋ฐ๊ฟ๋ด
์๋ค. ๋ง์ ์ ๊ฒฝ๋ง ๊ตฌ์ฑ ์์๋ค์ |
| 130 | +# ํน์ ํ ๊ตฌ์กฐ์ ์
๋ ฅ์ ์ํ๊ธฐ์, ์ด ๋ฉ์๋๋ ์์ฃผ ๋ง์ด ์ฌ์ฉ๋ฉ๋๋ค. |
| 131 | +# ์ข
์ข
๋ฐ์ดํฐ๋ฅผ ๊ตฌ์ฑ ์์๋ก ์ ๋ฌํ๊ธฐ ์ ๊ตฌ์กฐ๋ฅผ ๋ฐ๊ฟ์ผ ํ๋ ๊ฒฝ์ฐ๊ฐ |
| 132 | +# ์์ต๋๋ค. |
134 | 133 | # |
135 | 134 |
|
136 | 135 | x = torch.randn(2, 3, 4) |
137 | 136 | print(x) |
138 | | -print(x.view(2, 12)) # Reshape to 2 rows, 12 columns |
139 | | -# Same as above. If one of the dimensions is -1, its size can be inferred |
| 137 | +print(x.view(2, 12)) # 2์ด 12ํ์ผ๋ก ๊ตฌ์กฐ ๋ฐ๊พธ๊ธฐ |
| 138 | +# ์์ ๊ฐ์ต๋๋ค. ์ฐจ์ ์ค ํ๋๊ฐ -1์ธ ๊ฒฝ์ฐ ๊ทธ ํฌ๊ธฐ๋ฅผ ์ ์ถํ ์ ์์ต๋๋ค |
140 | 139 | print(x.view(2, -1)) |
141 | 140 |
|
142 | 141 |
|
143 | 142 | ###################################################################### |
144 | | -# Computation Graphs and Automatic Differentiation |
| 143 | +# ๊ณ์ฐ ๊ทธ๋ํ(Computation Graph) ์ ์๋ ๋ฏธ๋ถ(Automatic Differentiation) |
145 | 144 | # ================================================ |
146 | 145 | # |
147 | | -# The concept of a computation graph is essential to efficient deep |
148 | | -# learning programming, because it allows you to not have to write the |
149 | | -# back propagation gradients yourself. A computation graph is simply a |
150 | | -# specification of how your data is combined to give you the output. Since |
151 | | -# the graph totally specifies what parameters were involved with which |
152 | | -# operations, it contains enough information to compute derivatives. This |
153 | | -# probably sounds vague, so let's see what is going on using the |
154 | | -# fundamental flag ``requires_grad``. |
| 146 | +# ๊ณ์ฐ ๊ทธ๋ํ์ ๊ฐ๋
์ ์ง์ ์ญ์ ํ ๋ณํ๋(gradient)๋ฅผ ์ธ ํ์๊ฐ ์๊ฒ ํด์ฃผ๋ฉฐ |
| 147 | +# ํจ์จ์ ์ธ ๋ฅ๋ฌ๋ ํ๋ก๊ทธ๋๋ฐ์ ํ์์ ์
๋๋ค. |
| 148 | +# ๊ณ์ฐ ๊ทธ๋ํ๋ ๊ฐ๋จํ ๋งํ์๋ฉด ์ถ๋ ฅ์ ๋ด๊ธฐ ์ํด |
| 149 | +# ์ด๋ป๊ฒ ๋ฐ์ดํฐ๋ฅผ ๊ฒฐํฉํ๋์ง์ ๋ํ ์ค๋ช
์์
๋๋ค. |
| 150 | +# ๊ทธ๋ํ๋ ์ด๋ค ๋งค๊ฐ๋ณ์๊ฐ ์ด๋ค ์ฐ์ฐ์ ๊ด์ฌํ๋์ง๋ฅผ ๋ชจ๋ ๋งํด์ฃผ๋ฏ๋ก |
| 151 | +# ๋ํจ์๋ฅผ ๊ณ์ฐํ๊ธฐ์ ์ถฉ๋ถํ ์ ๋ณด๋ฅผ ๊ฐ์ง๋๋ค. |
| 152 | +# ์ด ๋ง์ด ๋ชจํธํ ์ ์์ผ๋, ํต์ฌ ํ๋๊ทธ์ธ |
| 153 | +# ``requires_grad`` ๋ฅผ ์ฌ์ฉํ์ฌ ๋ฌด์จ ์ผ์ด ์ผ์ด๋๋์ง ์์๋ด
์๋ค. |
155 | 154 | # |
156 | | -# First, think from a programmers perspective. What is stored in the |
157 | | -# torch.Tensor objects we were creating above? Obviously the data and the |
158 | | -# shape, and maybe a few other things. But when we added two tensors |
159 | | -# together, we got an output tensor. All this output tensor knows is its |
160 | | -# data and shape. It has no idea that it was the sum of two other tensors |
161 | | -# (it could have been read in from a file, it could be the result of some |
162 | | -# other operation, etc.) |
| 155 | +# ๋จผ์ ํ๋ก๊ทธ๋๋จธ์ ๊ด์ ์์ ์๊ฐํด๋ด
์๋ค. ์์์ ์ฐ๋ฆฌ๊ฐ ๋ง๋ |
| 156 | +# torch.Tensor ์ค๋ธ์ ํธ์๋ ๋ฌด์์ด ์ ์ฅ๋์ด ์์๊น์? ๋ถ๋ช
ํ ๋ฐ์ดํฐ์ |
| 157 | +# ๊ตฌ์กฐ, ๋ช ๊ฐ์ง ๋ค๋ฅธ ๊ฒ๋ค์ด ์์ ๊ฒ๋๋ค. ํ์ง๋ง 2๊ฐ์ tensor๋ฅผ |
| 158 | +# ํจ๊ป ์ถ๊ฐํ๋ฉด ํ๋์ ๊ฒฐ๊ณผ tensor๋ฅผ ์ป๊ฒ ๋๋๋ฐ, ๊ฒฐ๊ณผ tensor๊ฐ ์๋ ๊ฒ์ |
| 159 | +# ์์ ์ ๋ฐ์ดํฐ์ ๊ตฌ์กฐ๋ฟ์
๋๋ค. ๋ค๋ฅธ ๋ tensor์ ํฉ์ด๋ผ๋ ๊ฒ์ ์ ํ ์์ง ๋ชปํฉ๋๋ค |
| 160 | +# (ํ์ผ์์ ์ฝ์์ ์๋ ์๊ณ , |
| 161 | +# ๋ค๋ฅธ ์ฐ์ฐ์ ๊ฒฐ๊ณผ์ผ ์๋ ์์) |
163 | 162 | # |
164 | | -# If ``requires_grad=True``, the Tensor object keeps track of how it was |
165 | | -# created. Let's see it in action. |
| 163 | +# ``requires_grad=True`` ์ธ ๊ฒฝ์ฐ, Tensor ๊ฐ์ฒด๋ ์์ ์ด ์ด๋ป๊ฒ ์์ฑ๋์๋์ง |
| 164 | +# ์ถ์ ํฉ๋๋ค. ํ๋ฒ ๋ด
์๋ค. |
166 | 165 | # |
167 | 166 |
|
168 | | -# Tensor factory methods have a ``requires_grad`` flag |
| 167 | +# Tensor factory ๋ฉ์๋๋ ``requires_grad`` ํ๋๊ทธ๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค |
169 | 168 | x = torch.tensor([1., 2., 3], requires_grad=True) |
170 | 169 |
|
171 | | -# With requires_grad=True, you can still do all the operations you previously |
172 | | -# could |
| 170 | +# requires_grad=True ๋ฅผ ์ฌ์ฉํด๋ ์ด์ ์ ํ ์ ์์๋ ๋ชจ๋ ์ฐ์ฐ์ |
| 171 | +# ์ฌ์ ํ ์ํํ ์ ์์ต๋๋ค |
173 | 172 | y = torch.tensor([4., 5., 6], requires_grad=True) |
174 | 173 | z = x + y |
175 | 174 | print(z) |
176 | 175 |
|
177 | | -# BUT z knows something extra. |
| 176 | +# ํ์ง๋ง, z๋ ๋ญ๊ฐ๋ฅผ ๋ ์๊ณ ์์ต๋๋ค. |
178 | 177 | print(z.grad_fn) |
179 | 178 |
|
180 | 179 |
|
181 | 180 | ###################################################################### |
182 | | -# So Tensors know what created them. z knows that it wasn't read in from |
183 | | -# a file, it wasn't the result of a multiplication or exponential or |
184 | | -# whatever. And if you keep following z.grad_fn, you will find yourself at |
185 | | -# x and y. |
| 181 | +# ์ฆ Tensor๋ ๋ฌด์์ผ๋ก ๊ทธ๋ค์ด ๋ง๋ค์ด์ก๋์ง ์๋๋ค. z๋ Tensor๊ฐ ํ์ผ์์ |
| 182 | +# ์ฝํ์ง ์์๋ค๋ ๊ฒ์ ์๊ณ ์์ผ๋ฉฐ, ๊ณฑ์
์ด๋ ์ง์ ๊ฐ์ ๊ฒ์ ๊ฒฐ๊ณผ๋ ์๋๋๋ค. |
| 183 | +# ๊ทธ๋ฆฌ๊ณ z.grad_fn ์ ๊ณ์ ๋ฐ๋ผ๊ฐ๋ค ๋ณด๋ฉด, |
| 184 | +# x์ y๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค. |
186 | 185 | # |
187 | | -# But how does that help us compute a gradient? |
| 186 | +# ๊ทธ๋ฌ๋ฉด ์ด ์ ๋ณด๊ฐ ์ด๋ป๊ฒ ๋ณํ๋๋ฅผ ๊ณ์ฐํ๋๋ฐ ๋์์ ์ค๊น์? |
188 | 187 | # |
189 | 188 |
|
190 | | -# Let's sum up all the entries in z |
| 189 | +# z์ ๋ชจ๋ ํญ๋ชฉ์ ํ๋๋ก ๋ํด๋ด
์๋ค. |
191 | 190 | s = z.sum() |
192 | 191 | print(s) |
193 | 192 | print(s.grad_fn) |
194 | 193 |
|
195 | 194 |
|
196 | 195 | ###################################################################### |
197 | | -# So now, what is the derivative of this sum with respect to the first |
198 | | -# component of x? In math, we want |
| 196 | +# ๊ทธ๋ ๋ค๋ฉด, x์ ์ฒซ๋ฒ์งธ ๊ตฌ์ฑ ์์์ ๋ํด ์ด ๋ง์
์ ๋ฏธ๋ถ์ |
| 197 | +# ๋ฌด์์ผ๊น์? ์ํ์ ์ผ๋ก๋, ์ฐ๋ฆฌ๊ฐ ์ํ๋ ๊ฒ์ ๋ค์์ ์์
๋๋ค. |
199 | 198 | # |
200 | 199 | # .. math:: |
201 | 200 | # |
202 | 201 | # \frac{\partial s}{\partial x_0} |
203 | 202 | # |
204 | 203 | # |
205 | 204 | # |
206 | | -# Well, s knows that it was created as a sum of the tensor z. z knows |
207 | | -# that it was the sum x + y. So |
| 205 | +# ์, s๋ ์์ ์ด tensor z์ ํฉ์ผ๋ก ๋ง๋ค์ด์ก๋ค๋ ๊ฒ์ ์๊ณ ์์ต๋๋ค. z๋ |
| 206 | +# ์์ ์ด x + y์ ํฉ์ด๋ผ๋ ๊ฒ์ ์๊ณ ์์ต๋๋ค. ๊ทธ๋์ |
208 | 207 | # |
209 | 208 | # .. math:: s = \overbrace{x_0 + y_0}^\text{$z_0$} + \overbrace{x_1 + y_1}^\text{$z_1$} + \overbrace{x_2 + y_2}^\text{$z_2$} |
210 | 209 | # |
211 | | -# And so s contains enough information to determine that the derivative |
212 | | -# we want is 1! |
| 210 | +# ๋ฐ๋ผ์, s๋ ๋ํจ์๋ฅผ ๊ฒฐ์ ํ๊ธฐ์ ์ถฉ๋ถํ ์ ๋ณด๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค. |
| 211 | +# ์ฐ๋ฆฌ๊ฐ ์ํ๋ ๋ํจ์์ ๊ฐ์ 1 ์
๋๋ค! |
213 | 212 | # |
214 | | -# Of course this glosses over the challenge of how to actually compute |
215 | | -# that derivative. The point here is that s is carrying along enough |
216 | | -# information that it is possible to compute it. In reality, the |
217 | | -# developers of Pytorch program the sum() and + operations to know how to |
218 | | -# compute their gradients, and run the back propagation algorithm. An |
219 | | -# in-depth discussion of that algorithm is beyond the scope of this |
220 | | -# tutorial. |
| 213 | +# ๋ฌผ๋ก ์ด๊ฒ์ ๊ทธ ๋ฏธ๋ถ์ ์ค์ ๋ก ๊ณ์ฐํ๋ ๋ฐฉ๋ฒ์ ๋ํ ๋์ ์ |
| 214 | +# ์จ๊น๋๋ค. ์ฌ๊ธฐ์ ์์ ์ s๊ฐ ๋ฏธ๋ถ์ ๊ณ์ฐํ๊ธฐ์ ์ถฉ๋ถํ |
| 215 | +# ์ ๋ณด๋ฅผ ๊ฐ์ง๊ณ ๋ค๋๋ค๋ ๊ฒ๋๋ค. ์ค์ ๋ก |
| 216 | +# Pytorch ๊ฐ๋ฐ์๋ sum() ๊ณผ + ์ฐ์ฐ์์ |
| 217 | +# ๋ณํ๋๋ฅผ ๊ณ์ฐํ๋ ๋ฒ์ ํ๋ก๊ทธ๋๋ฐํ๊ณ , ์ญ์ ํ ์๊ณ ๋ฆฌ์ฆ์ ์คํํฉ๋๋ค. |
| 218 | +# ์ด ์๊ณ ๋ฆฌ์ฆ์ ๋ํ ๊น์ด์๋ ์ค๋ช
์ ์ด ํํ ๋ฆฌ์ผ์ ๋ฒ์๋ฅผ |
| 219 | +# ๋ฒ์ด๋ฉ๋๋ค. |
221 | 220 | # |
222 | 221 |
|
223 | 222 |
|
224 | 223 | ###################################################################### |
225 | | -# Let's have Pytorch compute the gradient, and see that we were right: |
226 | | -# (note if you run this block multiple times, the gradient will increment. |
227 | | -# That is because Pytorch *accumulates* the gradient into the .grad |
228 | | -# property, since for many models this is very convenient.) |
| 224 | +# Pytorch๋ก ๋ณํ๋๋ฅผ ๊ณ์ฐํ๊ณ , ๋ง์๋์ง ํ์ธํด ๋ด
์๋ค. |
| 225 | +# (์ด ๋ธ๋ก์ ์ฌ๋ฌ๋ฒ ์คํํ๋ฉด ๋ณํ๋๊ฐ ์ฆ๊ฐํ ๊ฒ์
๋๋ค. |
| 226 | +# ๊ทธ ์ด์ ๋ Pytorch๊ฐ ๋ณํ๋๋ฅผ .grad ์์ฑ์ *์ถ์ * ํ๊ธฐ ๋๋ฌธ์ด๋ฉฐ, |
| 227 | +# ์ด๋ ๋ง์ ๋ชจ๋ธ์์ ๋งค์ฐ ํธ๋ฆฌํ๊ธฐ ๋๋ฌธ์
๋๋ค.) |
229 | 228 | # |
230 | 229 |
|
231 | | -# calling .backward() on any variable will run backprop, starting from it. |
| 230 | +# ์ด๋ค ๋ณ์์์๋ ์ง .backward()๋ฅผ ํธ์ถํ๋ฉด ํด๋น ๋ณ์์์ ์์ํ๋ ์ญ์ ํ๊ฐ ์คํ๋ฉ๋๋ค. |
232 | 231 | s.backward() |
233 | 232 | print(x.grad) |
234 | 233 |
|
235 | 234 |
|
236 | 235 | ###################################################################### |
237 | | -# Understanding what is going on in the block below is crucial for being a |
238 | | -# successful programmer in deep learning. |
| 236 | +# ๋ฅ๋ฌ๋์์ ์ฑ๊ณตํ ํ๋ก๊ทธ๋๋จธ๊ฐ ๋๊ธฐ ์ํด์๋ |
| 237 | +# ์๋ ๋ธ๋ก์์ ๋ฌด์จ ์ผ์ด ์ผ์ด๋๊ณ ์๋์ง ์ดํดํ๋ ๊ฒ์ด ํ์์ ์
๋๋ค. |
239 | 238 | # |
240 | 239 |
|
241 | 240 | x = torch.randn(2, 2) |
242 | 241 | y = torch.randn(2, 2) |
243 | | -# By default, user created Tensors have ``requires_grad=False`` |
| 242 | +# ์ฌ์ฉ์๊ฐ ์์ฑํ Tensor๋ ๊ธฐ๋ณธ์ ์ผ๋ก ``requires_grad=False`` ๋ฅผ ๊ฐ์ง๋๋ค |
244 | 243 | print(x.requires_grad, y.requires_grad) |
245 | 244 | z = x + y |
246 | | -# So you can't backprop through z |
| 245 | +# ๊ทธ๋์ z๋ฅผ ํตํด ์ญ์ ํ๋ฅผ ํ ์ ์์ต๋๋ค |
247 | 246 | print(z.grad_fn) |
248 | 247 |
|
249 | | -# ``.requires_grad_( ... )`` changes an existing Tensor's ``requires_grad`` |
250 | | -# flag in-place. The input flag defaults to ``True`` if not given. |
| 248 | +# ``.requires_grad_( ... )`` ๋ ๊ธฐ์กด ํ
์์ ``requires_grad`` |
| 249 | +# ํ๋๊ทธ๋ฅผ ์ ์๋ฆฌ์์(in-place) ๋ฐ๊ฟ๋๋ค. ์
๋ ฅ ํ๋๊ทธ๊ฐ ์ง์ ๋์ง ์์ ๊ฒฝ์ฐ ๊ธฐ๋ณธ๊ฐ์ ``True`` ์
๋๋ค. |
251 | 250 | x = x.requires_grad_() |
252 | 251 | y = y.requires_grad_() |
253 | | -# z contains enough information to compute gradients, as we saw above |
| 252 | +# z๋ ์์์ ๋ณธ ๊ฒ์ฒ๋ผ ๋ณํ๋๋ฅผ ๊ณ์ฐํ๊ธฐ์ ์ถฉ๋ถํ ์ ๋ณด๊ฐ ํฌํจ๋์ด ์์ต๋๋ค |
254 | 253 | z = x + y |
255 | 254 | print(z.grad_fn) |
256 | | -# If any input to an operation has ``requires_grad=True``, so will the output |
| 255 | +# ์ฐ์ฐ์ ๋ํ ์
๋ ฅ์ด ``requires_grad=True`` ์ธ ๊ฒฝ์ฐ ์ถ๋ ฅ๋ ๋ง์ฐฌ๊ฐ์ง์
๋๋ค |
257 | 256 | print(z.requires_grad) |
258 | 257 |
|
259 | | -# Now z has the computation history that relates itself to x and y |
260 | | -# Can we just take its values, and **detach** it from its history? |
| 258 | +# ์ด์ z๋ x์ y์ ๋ํ ๊ณ์ฐ ๊ธฐ๋ก์ ๊ฐ์ง๊ณ ์์ต๋๋ค |
| 259 | +# z์ ๊ฐ๋ง ๊ฐ์ ธ๊ฐ๊ณ , ๊ธฐ๋ก์์ **๋ถ๋ฆฌ** ํ ์ ์์๊น์? |
261 | 260 | new_z = z.detach() |
262 | 261 |
|
263 | | -# ... does new_z have information to backprop to x and y? |
264 | | -# NO! |
| 262 | +# ... new_z ๊ฐ x์ y๋ก์ ์ญ์ ํ๋ฅผ ์ํ ์ ๋ณด๋ฅผ ๊ฐ๊ณ ์์๊น์? |
| 263 | +# ์๋๋๋ค! |
265 | 264 | print(new_z.grad_fn) |
266 | | -# And how could it? ``z.detach()`` returns a tensor that shares the same storage |
267 | | -# as ``z``, but with the computation history forgotten. It doesn't know anything |
268 | | -# about how it was computed. |
269 | | -# In essence, we have broken the Tensor away from its past history |
| 265 | +# ์ด๋ป๊ฒ ๊ทธ๋ด ์๊ฐ ์์๊น์? ``z.detach()`` ๋ ``z`` ์ ๋์ผํ ์ ์ฅ๊ณต๊ฐ์ ์ฌ์ฉํ์ง๋ง |
| 266 | +# ๊ณ์ฐ ๊ธฐ๋ก์ ์๋ tensor๋ฅผ ๋ฐํํฉ๋๋ค. ๊ทธ tensor๋ ์์ ์ด ์ด๋ป๊ฒ ๊ณ์ฐ๋์๋์ง |
| 267 | +# ์๋ฌด๊ฒ๋ ์์ง ๋ชปํฉ๋๋ค. |
| 268 | +# ๋ณธ์ง์ ์ผ๋ก๋ Tensor๋ฅผ ๊ณผ๊ฑฐ ๊ธฐ๋ก์ผ๋ก๋ถํฐ ๋ผ์ด๋ธ ๊ฒ๋๋ค |
270 | 269 |
|
271 | 270 | ############################################################### |
272 | | -# You can also stop autograd from tracking history on Tensors |
273 | | -# with ``.requires_grad=True`` by wrapping the code block in |
274 | | -# ``with torch.no_grad():`` |
| 271 | +# ๋ํ ์ฝ๋ ๋ธ๋ก์ ``with torch.no_grad():`` ๋ก ๊ฐ์ธ |
| 272 | +# ``.requires_grad=True`` ์ธ ํ
์์ ๊ธฐ๋ก์ ์ถ์ ํ์ง ๋ชปํ๊ฒ๋ |
| 273 | +# autograd๋ฅผ ๋ฉ์ถ ์ ์์ต๋๋ค. |
275 | 274 | print(x.requires_grad) |
276 | 275 | print((x ** 2).requires_grad) |
277 | 276 |
|
|
0 commit comments