Skip to content

Commit 72262bd

Browse files
committed
no message
1 parent 172b8d9 commit 72262bd

File tree

4 files changed

+411
-33
lines changed

4 files changed

+411
-33
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,338 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "code",
5+
"execution_count": 6,
6+
"metadata": {},
7+
"outputs": [],
8+
"source": [
9+
"import torch\n",
10+
"import torch.nn as nn\n",
11+
"# 네트워크와 레이어들을 정리하기 위한 모듈\n",
12+
"import torch.nn.functional as F\n",
13+
"# 구조 상에서 표현하기 힘든 경우나 loss function을 바로 가져다 쓰고 싶은 경우\n",
14+
"import torch.autograd as autograd\n",
15+
"# backprop과정과 gradient를 직접 수정하고 싶은 경우"
16+
]
17+
},
18+
{
19+
"cell_type": "markdown",
20+
"metadata": {},
21+
"source": [
22+
"## 1. 네트워크 정의"
23+
]
24+
},
25+
{
26+
"cell_type": "code",
27+
"execution_count": 7,
28+
"metadata": {},
29+
"outputs": [
30+
{
31+
"name": "stdout",
32+
"output_type": "stream",
33+
"text": [
34+
"NN(\n",
35+
" (layers): Sequential(\n",
36+
" (0): Linear(in_features=25, out_features=128, bias=True)\n",
37+
" (1): Dropout(p=0.5)\n",
38+
" (2): ReLU()\n",
39+
" (3): Linear(in_features=128, out_features=128, bias=True)\n",
40+
" (4): ReLU()\n",
41+
" (5): Linear(in_features=128, out_features=10, bias=True)\n",
42+
" )\n",
43+
")\n"
44+
]
45+
}
46+
],
47+
"source": [
48+
"class NN(nn.Module):\n",
49+
" # 네트워크는 nn.Module을 상속받아서 정의하는게 일반적입니다.\n",
50+
" def __init__(self, input_dim=25, hidden_dim=128, output_dim=10):\n",
51+
" super().__init__()\n",
52+
" self.layers = nn.Sequential(\n",
53+
" nn.Linear(input_dim, hidden_dim),\n",
54+
" # Dropout을 정의하고 싶으면 다음과 같이 할 수 있습니다.\n",
55+
" nn.Dropout(),\n",
56+
" nn.ReLU(),\n",
57+
" nn.Linear(hidden_dim, hidden_dim),\n",
58+
" nn.ReLU(),\n",
59+
" nn.Linear(hidden_dim, output_dim)\n",
60+
" )\n",
61+
" \n",
62+
" # 네트워크 파라미터 정의는 다음과 같이 할 수 있습니다.\n",
63+
" for m in self.modules():\n",
64+
"# print(m)\n",
65+
" if isinstance(m, nn.Linear):\n",
66+
" nn.init.xavier_normal_(m.weight)\n",
67+
" nn.init.constant_(m.bias, 0.0)\n",
68+
" \n",
69+
" def forward(self, x):\n",
70+
" # x 는 input을 의미하며, 일반적인 경우에는 (mini_batch, input_dim)\n",
71+
" # 이미지의 경우에는 (mini_batch, Channel, Height, Width) 의 형태를 가정합니다.\n",
72+
" x = self.layers(x)\n",
73+
" return x\n",
74+
"net = NN()\n",
75+
"print(net)"
76+
]
77+
},
78+
{
79+
"cell_type": "code",
80+
"execution_count": 13,
81+
"metadata": {},
82+
"outputs": [
83+
{
84+
"name": "stdout",
85+
"output_type": "stream",
86+
"text": [
87+
"torch.Size([32, 25]) torch.Size([32, 10])\n"
88+
]
89+
}
90+
],
91+
"source": [
92+
"x = torch.rand((32, 25))\n",
93+
"y = net(x)\n",
94+
"print(x.shape, y.shape)"
95+
]
96+
},
97+
{
98+
"cell_type": "markdown",
99+
"metadata": {},
100+
"source": [
101+
"## 2. 네트워크 셋팅"
102+
]
103+
},
104+
{
105+
"cell_type": "code",
106+
"execution_count": 14,
107+
"metadata": {},
108+
"outputs": [
109+
{
110+
"name": "stdout",
111+
"output_type": "stream",
112+
"text": [
113+
"False\n",
114+
"True\n"
115+
]
116+
}
117+
],
118+
"source": [
119+
"# Dropout/BatchNorm 등의 layer는 다음과 같이 제어할 수 있습니다.\n",
120+
"net.eval()\n",
121+
"print(net.training)\n",
122+
"net.train()\n",
123+
"print(net.training)"
124+
]
125+
},
126+
{
127+
"cell_type": "markdown",
128+
"metadata": {},
129+
"source": [
130+
"## 3. Loss 정의하기"
131+
]
132+
},
133+
{
134+
"cell_type": "code",
135+
"execution_count": 15,
136+
"metadata": {},
137+
"outputs": [
138+
{
139+
"name": "stdout",
140+
"output_type": "stream",
141+
"text": [
142+
"tensor(1.1736, grad_fn=<MseLossBackward>)\n",
143+
"tensor(1.1736, grad_fn=<MseLossBackward>)\n"
144+
]
145+
}
146+
],
147+
"source": [
148+
"target = torch.randn_like(y)\n",
149+
"\n",
150+
"# 보통 loss는 다음 2가지의 형태로 정의합니다.\n",
151+
"# 1. nn에서 함수 형태로 가져오는 경우\n",
152+
"cost_func = nn.MSELoss()\n",
153+
"loss = cost_func(y, target)\n",
154+
"print(loss)\n",
155+
"\n",
156+
"# 2. functional에서 바로 부르는 경우\n",
157+
"loss = F.mse_loss(y, target)\n",
158+
"print(loss)"
159+
]
160+
},
161+
{
162+
"cell_type": "markdown",
163+
"metadata": {},
164+
"source": [
165+
"## 4. Gradient 조작"
166+
]
167+
},
168+
{
169+
"cell_type": "code",
170+
"execution_count": 16,
171+
"metadata": {},
172+
"outputs": [
173+
{
174+
"name": "stdout",
175+
"output_type": "stream",
176+
"text": [
177+
"torch.Size([128, 25])\n",
178+
"torch.Size([128])\n",
179+
"torch.Size([128, 128])\n",
180+
"torch.Size([128])\n",
181+
"torch.Size([10, 128])\n",
182+
"torch.Size([10])\n"
183+
]
184+
}
185+
],
186+
"source": [
187+
"# 많은 경우 gradient계산은 다음과 같이 실행합니다.\n",
188+
"loss.backward()\n",
189+
"for param in net.parameters():\n",
190+
" print(param.grad.shape)"
191+
]
192+
},
193+
{
194+
"cell_type": "code",
195+
"execution_count": 7,
196+
"metadata": {},
197+
"outputs": [
198+
{
199+
"name": "stdout",
200+
"output_type": "stream",
201+
"text": [
202+
"torch.Size([32, 25])\n"
203+
]
204+
}
205+
],
206+
"source": [
207+
"# 한편 필요에 의해서는 명시적으로 gradient를 구해야할 필요가 있습니다. 이때는 다음과 같이 조절할 수 있습니다.\n",
208+
"x = torch.rand((32, 25)).requires_grad_(True)\n",
209+
"y = net(x)\n",
210+
"grad = autograd.grad(y, x,\\\n",
211+
" grad_outputs=torch.ones_like(y), retain_graph=None, create_graph=False,\\\n",
212+
" only_inputs=True, allow_unused=False)[0]\n",
213+
"print(grad.shape)"
214+
]
215+
},
216+
{
217+
"cell_type": "markdown",
218+
"metadata": {},
219+
"source": [
220+
"## 5. Tensor 조작"
221+
]
222+
},
223+
{
224+
"cell_type": "code",
225+
"execution_count": 17,
226+
"metadata": {},
227+
"outputs": [],
228+
"source": [
229+
"# numpy의 데이터들은 대부분 다음과 같이 pytorch의 tensor로 만들 수 있습니다.\n",
230+
"import numpy as np\n",
231+
"x = np.random.randn(32, 25)\n",
232+
"x = torch.FloatTensor(x)\n",
233+
"# 바뀐 tensor는 다음과 같이 GPU로 올라갈 수 있습니다.\n",
234+
"# x = x.cuda()\n",
235+
"# x.cuda_()\n",
236+
"# 한편 네트워크를 GPU에 올릴 때는 cuda함수만 호출해도 충분합니다.\n",
237+
"# net.cuda()\n",
238+
"# GPU에 올라간 tensor는 다음 코드로 다시 numpy로 바꿀 수 있습니다.\n",
239+
"# x = x.detach().cpu().numpy()\n",
240+
"# print(x.shape)"
241+
]
242+
},
243+
{
244+
"cell_type": "code",
245+
"execution_count": 18,
246+
"metadata": {},
247+
"outputs": [
248+
{
249+
"name": "stdout",
250+
"output_type": "stream",
251+
"text": [
252+
"torch.Size([32, 25])\n",
253+
"torch.Size([32, 1])\n"
254+
]
255+
}
256+
],
257+
"source": [
258+
"# 한편 tensor에서의 indexing은 다음과 같이 vectorize할 수 있습니다.\n",
259+
"indices = [np.random.choice(25) for _ in range(32)]\n",
260+
"indices = torch.LongTensor(indices) # (32)\n",
261+
"x_selected = x.gather(1, indices.unsqueeze(1))\n",
262+
"print(x.shape)\n",
263+
"print(x_selected.shape)"
264+
]
265+
},
266+
{
267+
"cell_type": "code",
268+
"execution_count": 10,
269+
"metadata": {},
270+
"outputs": [
271+
{
272+
"name": "stdout",
273+
"output_type": "stream",
274+
"text": [
275+
"torch.Size([32, 25])\n",
276+
"torch.Size([32, 1, 25])\n",
277+
"torch.Size([32, 1, 25])\n",
278+
"torch.Size([32, 25])\n"
279+
]
280+
}
281+
],
282+
"source": [
283+
"# 위에서 unsqueeze/squeeze 함수는 데이터의 전체 크기는 유지하되 axis를 추가/제거하는 함수입니다.\n",
284+
"x = torch.randn((32, 25))\n",
285+
"print(x.shape)\n",
286+
"x.unsqueeze_(1)\n",
287+
"print(x.shape)\n",
288+
"x.squeeze_(2)\n",
289+
"print(x.shape)\n",
290+
"x.squeeze_(1)\n",
291+
"print(x.shape)"
292+
]
293+
},
294+
{
295+
"cell_type": "code",
296+
"execution_count": 11,
297+
"metadata": {},
298+
"outputs": [
299+
{
300+
"name": "stdout",
301+
"output_type": "stream",
302+
"text": [
303+
"torch.Size([32, 1, 25])\n",
304+
"torch.Size([800])\n"
305+
]
306+
}
307+
],
308+
"source": [
309+
"# 비슷하게 view 함수를 사용할 수도 있지만, dim이 섞일 위험이 있으니 조심하세요!\n",
310+
"x = x.view(x.size(0), 1, -1)\n",
311+
"print(x.shape)\n",
312+
"x = x.view(-1)\n",
313+
"print(x.shape)"
314+
]
315+
}
316+
],
317+
"metadata": {
318+
"kernelspec": {
319+
"display_name": "Python 3",
320+
"language": "python",
321+
"name": "python3"
322+
},
323+
"language_info": {
324+
"codemirror_mode": {
325+
"name": "ipython",
326+
"version": 3
327+
},
328+
"file_extension": ".py",
329+
"mimetype": "text/x-python",
330+
"name": "python",
331+
"nbconvert_exporter": "python",
332+
"pygments_lexer": "ipython3",
333+
"version": "3.6.5"
334+
}
335+
},
336+
"nbformat": 4,
337+
"nbformat_minor": 2
338+
}

0 commit comments

Comments
 (0)