├── .gitignore
├── LICENSE.md
├── 1-1_Virtualenv.txt
├── README.md
├── 1-2_Basic_Autograd.ipynb
├── 3-5_MNIST_MLP_Dropout_ReLU_BN_HE_Adam.ipynb
├── 5_NLP_v2.ipynb
├── 3-1_MNIST_MLP_Dropout.ipynb
├── 3-2_MNIST_MLP_Dropout_ReLU.ipynb
└── 3-3_MNIST_MLP_Dropout_ReLU_BN.ipynb
/.gitignore:
--------------------------------------------------------------------------------
1 | .ipynb_checkpoints/
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Justin
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/1-1_Virtualenv.txt:
--------------------------------------------------------------------------------
1 | # Python Virtualenv - Windows
2 | - pip install virtualenv
3 | - virtualenv [name of virtualenv]
4 | - virtualenv [name of virtualenv] --python=3.6
5 | - call [name of virtualenv]/scripts/activate
6 | - deactivate
7 |
8 | # Python Virtualenv - Linux
9 | - pip install virtualenv
10 | - virtualenv [name of virtualenv]
11 | - virtualenv [name of virtualenv] --python=3.6
12 | - source [name of virtualenv]/bin/activate
13 | - deactivate
14 |
15 | # Anaconda Virtualenv - Windows
16 | - conda create [name of virtualenv]
17 | - conda create [name of virtualenv] pandas torch
18 | - conda create [name of virtualenv] python=3.6
19 | - activate [name of virtualenv]
20 | - deactivate
21 |
22 | # Anaconda Virtualenv - Linux
23 | - conda create [name of virtualenv]
24 | - conda create [name of virtualenv] pandas torch
25 | - conda create [name of virtualenv] python=3.6
26 | - source activate [name of virtualenv]
27 | - source deactivate
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | > 현재, 출판된 책 내용의 **일부 소스 코드 속 콜론(:)** 이 누락되었습니다.
2 | > 확인 결과, 편집 과정 중 발생한 오류였으며 다음번 인쇄에 수정 예정입니다.
3 | > 독자분들께서는 책 속 코드를 직접 타이핑 하시기보단 현재 저장소에 저장된 코드를 참고하시길 바랍니다.
4 | > 불편을 드려 대단히 죄송합니다.
5 |
6 | # DeepLearning101
7 | - Python, Deep Learning, PyTorch
8 |
9 |
10 |
11 |
12 | # Authors
13 | ### 이경택
14 | - e-mail : lgt5512@naver.com
15 | - github : https://github.com/LeeGyeongTak
16 | - blog : https://bluediary8.tistory.com
17 |
18 | ### 방성수
19 | - e-mail : twilight057@gmail.com
20 | - github : https://github.com/8a496b
21 |
22 | ### 안상준
23 | - e-mail : justin_a@yonsei.ac.kr
24 | - github : https://github.com/Justin-A
25 |
26 | 
27 | 
28 | 
29 | 
30 | 
31 | 
32 |
--------------------------------------------------------------------------------
/1-2_Basic_Autograd.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 1,
6 | "metadata": {},
7 | "outputs": [],
8 | "source": [
9 | "import torch"
10 | ]
11 | },
12 | {
13 | "cell_type": "markdown",
14 | "metadata": {},
15 | "source": [
16 | "# Scalar"
17 | ]
18 | },
19 | {
20 | "cell_type": "code",
21 | "execution_count": 2,
22 | "metadata": {},
23 | "outputs": [
24 | {
25 | "name": "stdout",
26 | "output_type": "stream",
27 | "text": [
28 | "tensor([1.])\n"
29 | ]
30 | }
31 | ],
32 | "source": [
33 | "scalar1 = torch.tensor([1.])\n",
34 | "print(scalar1)"
35 | ]
36 | },
37 | {
38 | "cell_type": "code",
39 | "execution_count": 3,
40 | "metadata": {},
41 | "outputs": [
42 | {
43 | "name": "stdout",
44 | "output_type": "stream",
45 | "text": [
46 | "tensor([3.])\n"
47 | ]
48 | }
49 | ],
50 | "source": [
51 | "scalar2 = torch.tensor([3.]) \n",
52 | "print(scalar2)"
53 | ]
54 | },
55 | {
56 | "cell_type": "code",
57 | "execution_count": 4,
58 | "metadata": {},
59 | "outputs": [
60 | {
61 | "name": "stdout",
62 | "output_type": "stream",
63 | "text": [
64 | "tensor([4.])\n"
65 | ]
66 | }
67 | ],
68 | "source": [
69 | "add_scalar = scalar1 + scalar2\n",
70 | "print(add_scalar)"
71 | ]
72 | },
73 | {
74 | "cell_type": "code",
75 | "execution_count": 5,
76 | "metadata": {},
77 | "outputs": [
78 | {
79 | "name": "stdout",
80 | "output_type": "stream",
81 | "text": [
82 | "tensor([-2.])\n"
83 | ]
84 | }
85 | ],
86 | "source": [
87 | "sub_scalar = scalar1 - scalar2\n",
88 | "print(sub_scalar)"
89 | ]
90 | },
91 | {
92 | "cell_type": "code",
93 | "execution_count": 6,
94 | "metadata": {},
95 | "outputs": [
96 | {
97 | "name": "stdout",
98 | "output_type": "stream",
99 | "text": [
100 | "tensor([3.])\n"
101 | ]
102 | }
103 | ],
104 | "source": [
105 | "mul_scalar = scalar1 * scalar2\n",
106 | "print(mul_scalar)"
107 | ]
108 | },
109 | {
110 | "cell_type": "code",
111 | "execution_count": 7,
112 | "metadata": {},
113 | "outputs": [
114 | {
115 | "name": "stdout",
116 | "output_type": "stream",
117 | "text": [
118 | "tensor([0.3333])\n"
119 | ]
120 | }
121 | ],
122 | "source": [
123 | "div_scalar = scalar1 / scalar2\n",
124 | "print(div_scalar)"
125 | ]
126 | },
127 | {
128 | "cell_type": "code",
129 | "execution_count": 8,
130 | "metadata": {},
131 | "outputs": [
132 | {
133 | "data": {
134 | "text/plain": [
135 | "tensor([4.])"
136 | ]
137 | },
138 | "execution_count": 8,
139 | "metadata": {},
140 | "output_type": "execute_result"
141 | }
142 | ],
143 | "source": [
144 | "torch.add(scalar1, scalar2)"
145 | ]
146 | },
147 | {
148 | "cell_type": "code",
149 | "execution_count": 9,
150 | "metadata": {},
151 | "outputs": [
152 | {
153 | "data": {
154 | "text/plain": [
155 | "tensor([-2.])"
156 | ]
157 | },
158 | "execution_count": 9,
159 | "metadata": {},
160 | "output_type": "execute_result"
161 | }
162 | ],
163 | "source": [
164 | "torch.sub(scalar1, scalar2)"
165 | ]
166 | },
167 | {
168 | "cell_type": "code",
169 | "execution_count": 10,
170 | "metadata": {},
171 | "outputs": [
172 | {
173 | "data": {
174 | "text/plain": [
175 | "tensor([3.])"
176 | ]
177 | },
178 | "execution_count": 10,
179 | "metadata": {},
180 | "output_type": "execute_result"
181 | }
182 | ],
183 | "source": [
184 | "torch.mul(scalar1, scalar2)"
185 | ]
186 | },
187 | {
188 | "cell_type": "code",
189 | "execution_count": 11,
190 | "metadata": {},
191 | "outputs": [
192 | {
193 | "data": {
194 | "text/plain": [
195 | "tensor([0.3333])"
196 | ]
197 | },
198 | "execution_count": 11,
199 | "metadata": {},
200 | "output_type": "execute_result"
201 | }
202 | ],
203 | "source": [
204 | "torch.div(scalar1, scalar2)"
205 | ]
206 | },
207 | {
208 | "cell_type": "markdown",
209 | "metadata": {},
210 | "source": [
211 | "# Vector"
212 | ]
213 | },
214 | {
215 | "cell_type": "code",
216 | "execution_count": 12,
217 | "metadata": {},
218 | "outputs": [
219 | {
220 | "name": "stdout",
221 | "output_type": "stream",
222 | "text": [
223 | "tensor([1., 2., 3.])\n"
224 | ]
225 | }
226 | ],
227 | "source": [
228 | "vector1 = torch.tensor([1., 2., 3.])\n",
229 | "print(vector1)"
230 | ]
231 | },
232 | {
233 | "cell_type": "code",
234 | "execution_count": 13,
235 | "metadata": {},
236 | "outputs": [
237 | {
238 | "name": "stdout",
239 | "output_type": "stream",
240 | "text": [
241 | "tensor([4., 5., 6.])\n"
242 | ]
243 | }
244 | ],
245 | "source": [
246 | "vector2 = torch.tensor([4., 5., 6.])\n",
247 | "print(vector2)"
248 | ]
249 | },
250 | {
251 | "cell_type": "code",
252 | "execution_count": 14,
253 | "metadata": {},
254 | "outputs": [
255 | {
256 | "name": "stdout",
257 | "output_type": "stream",
258 | "text": [
259 | "tensor([5., 7., 9.])\n"
260 | ]
261 | }
262 | ],
263 | "source": [
264 | "add_vector = vector1 + vector2\n",
265 | "print(add_vector)"
266 | ]
267 | },
268 | {
269 | "cell_type": "code",
270 | "execution_count": 15,
271 | "metadata": {},
272 | "outputs": [
273 | {
274 | "name": "stdout",
275 | "output_type": "stream",
276 | "text": [
277 | "tensor([-3., -3., -3.])\n"
278 | ]
279 | }
280 | ],
281 | "source": [
282 | "sub_vector = vector1 - vector2\n",
283 | "print(sub_vector)"
284 | ]
285 | },
286 | {
287 | "cell_type": "code",
288 | "execution_count": 16,
289 | "metadata": {},
290 | "outputs": [
291 | {
292 | "name": "stdout",
293 | "output_type": "stream",
294 | "text": [
295 | "tensor([ 4., 10., 18.])\n"
296 | ]
297 | }
298 | ],
299 | "source": [
300 | "mul_vector = vector1 * vector2\n",
301 | "print(mul_vector)"
302 | ]
303 | },
304 | {
305 | "cell_type": "code",
306 | "execution_count": 17,
307 | "metadata": {},
308 | "outputs": [
309 | {
310 | "name": "stdout",
311 | "output_type": "stream",
312 | "text": [
313 | "tensor([0.2500, 0.4000, 0.5000])\n"
314 | ]
315 | }
316 | ],
317 | "source": [
318 | "div_vector = vector1 / vector2\n",
319 | "print(div_vector)"
320 | ]
321 | },
322 | {
323 | "cell_type": "code",
324 | "execution_count": 18,
325 | "metadata": {},
326 | "outputs": [
327 | {
328 | "data": {
329 | "text/plain": [
330 | "tensor([5., 7., 9.])"
331 | ]
332 | },
333 | "execution_count": 18,
334 | "metadata": {},
335 | "output_type": "execute_result"
336 | }
337 | ],
338 | "source": [
339 | "torch.add(vector1, vector2)"
340 | ]
341 | },
342 | {
343 | "cell_type": "code",
344 | "execution_count": 19,
345 | "metadata": {},
346 | "outputs": [
347 | {
348 | "data": {
349 | "text/plain": [
350 | "tensor([-3., -3., -3.])"
351 | ]
352 | },
353 | "execution_count": 19,
354 | "metadata": {},
355 | "output_type": "execute_result"
356 | }
357 | ],
358 | "source": [
359 | "torch.sub(vector1, vector2)"
360 | ]
361 | },
362 | {
363 | "cell_type": "code",
364 | "execution_count": 20,
365 | "metadata": {},
366 | "outputs": [
367 | {
368 | "data": {
369 | "text/plain": [
370 | "tensor([ 4., 10., 18.])"
371 | ]
372 | },
373 | "execution_count": 20,
374 | "metadata": {},
375 | "output_type": "execute_result"
376 | }
377 | ],
378 | "source": [
379 | "torch.mul(vector1, vector2)"
380 | ]
381 | },
382 | {
383 | "cell_type": "code",
384 | "execution_count": 21,
385 | "metadata": {},
386 | "outputs": [
387 | {
388 | "data": {
389 | "text/plain": [
390 | "tensor([0.2500, 0.4000, 0.5000])"
391 | ]
392 | },
393 | "execution_count": 21,
394 | "metadata": {},
395 | "output_type": "execute_result"
396 | }
397 | ],
398 | "source": [
399 | "torch.div(vector1, vector2)"
400 | ]
401 | },
402 | {
403 | "cell_type": "code",
404 | "execution_count": 22,
405 | "metadata": {},
406 | "outputs": [
407 | {
408 | "data": {
409 | "text/plain": [
410 | "tensor(32.)"
411 | ]
412 | },
413 | "execution_count": 22,
414 | "metadata": {},
415 | "output_type": "execute_result"
416 | }
417 | ],
418 | "source": [
419 | "torch.dot(vector1, vector2)"
420 | ]
421 | },
422 | {
423 | "cell_type": "markdown",
424 | "metadata": {},
425 | "source": [
426 | "# Matrix"
427 | ]
428 | },
429 | {
430 | "cell_type": "code",
431 | "execution_count": 23,
432 | "metadata": {},
433 | "outputs": [
434 | {
435 | "name": "stdout",
436 | "output_type": "stream",
437 | "text": [
438 | "tensor([[1., 2.],\n",
439 | " [3., 4.]])\n"
440 | ]
441 | }
442 | ],
443 | "source": [
444 | "matrix1 = torch.tensor([[1., 2.], [3., 4.]])\n",
445 | "print(matrix1)"
446 | ]
447 | },
448 | {
449 | "cell_type": "code",
450 | "execution_count": 24,
451 | "metadata": {},
452 | "outputs": [
453 | {
454 | "name": "stdout",
455 | "output_type": "stream",
456 | "text": [
457 | "tensor([[5., 6.],\n",
458 | " [7., 8.]])\n"
459 | ]
460 | }
461 | ],
462 | "source": [
463 | "matrix2 = torch.tensor([[5., 6.], [7., 8.]])\n",
464 | "print(matrix2)"
465 | ]
466 | },
467 | {
468 | "cell_type": "code",
469 | "execution_count": 25,
470 | "metadata": {},
471 | "outputs": [
472 | {
473 | "name": "stdout",
474 | "output_type": "stream",
475 | "text": [
476 | "tensor([[ 6., 8.],\n",
477 | " [10., 12.]])\n"
478 | ]
479 | }
480 | ],
481 | "source": [
482 | "sum_matrix = matrix1 + matrix2\n",
483 | "print(sum_matrix)"
484 | ]
485 | },
486 | {
487 | "cell_type": "code",
488 | "execution_count": 26,
489 | "metadata": {},
490 | "outputs": [
491 | {
492 | "name": "stdout",
493 | "output_type": "stream",
494 | "text": [
495 | "tensor([[-4., -4.],\n",
496 | " [-4., -4.]])\n"
497 | ]
498 | }
499 | ],
500 | "source": [
501 | "sub_matrix = matrix1 - matrix2\n",
502 | "print(sub_matrix)"
503 | ]
504 | },
505 | {
506 | "cell_type": "code",
507 | "execution_count": 27,
508 | "metadata": {},
509 | "outputs": [
510 | {
511 | "name": "stdout",
512 | "output_type": "stream",
513 | "text": [
514 | "tensor([[ 5., 12.],\n",
515 | " [21., 32.]])\n"
516 | ]
517 | }
518 | ],
519 | "source": [
520 | "mul_matrix = matrix1 * matrix2\n",
521 | "print(mul_matrix)"
522 | ]
523 | },
524 | {
525 | "cell_type": "code",
526 | "execution_count": 28,
527 | "metadata": {},
528 | "outputs": [
529 | {
530 | "name": "stdout",
531 | "output_type": "stream",
532 | "text": [
533 | "tensor([[0.2000, 0.3333],\n",
534 | " [0.4286, 0.5000]])\n"
535 | ]
536 | }
537 | ],
538 | "source": [
539 | "div_matrix = matrix1 / matrix2\n",
540 | "print(div_matrix)"
541 | ]
542 | },
543 | {
544 | "cell_type": "code",
545 | "execution_count": 29,
546 | "metadata": {},
547 | "outputs": [
548 | {
549 | "data": {
550 | "text/plain": [
551 | "tensor([[ 6., 8.],\n",
552 | " [10., 12.]])"
553 | ]
554 | },
555 | "execution_count": 29,
556 | "metadata": {},
557 | "output_type": "execute_result"
558 | }
559 | ],
560 | "source": [
561 | "torch.add(matrix1, matrix2)"
562 | ]
563 | },
564 | {
565 | "cell_type": "code",
566 | "execution_count": 30,
567 | "metadata": {},
568 | "outputs": [
569 | {
570 | "data": {
571 | "text/plain": [
572 | "tensor([[-4., -4.],\n",
573 | " [-4., -4.]])"
574 | ]
575 | },
576 | "execution_count": 30,
577 | "metadata": {},
578 | "output_type": "execute_result"
579 | }
580 | ],
581 | "source": [
582 | "torch.sub(matrix1, matrix2)"
583 | ]
584 | },
585 | {
586 | "cell_type": "code",
587 | "execution_count": 31,
588 | "metadata": {},
589 | "outputs": [
590 | {
591 | "data": {
592 | "text/plain": [
593 | "tensor([[ 5., 12.],\n",
594 | " [21., 32.]])"
595 | ]
596 | },
597 | "execution_count": 31,
598 | "metadata": {},
599 | "output_type": "execute_result"
600 | }
601 | ],
602 | "source": [
603 | "torch.mul(matrix1, matrix2)"
604 | ]
605 | },
606 | {
607 | "cell_type": "code",
608 | "execution_count": 32,
609 | "metadata": {},
610 | "outputs": [
611 | {
612 | "data": {
613 | "text/plain": [
614 | "tensor([[0.2000, 0.3333],\n",
615 | " [0.4286, 0.5000]])"
616 | ]
617 | },
618 | "execution_count": 32,
619 | "metadata": {},
620 | "output_type": "execute_result"
621 | }
622 | ],
623 | "source": [
624 | "torch.div(matrix1, matrix2)"
625 | ]
626 | },
627 | {
628 | "cell_type": "code",
629 | "execution_count": 33,
630 | "metadata": {},
631 | "outputs": [
632 | {
633 | "data": {
634 | "text/plain": [
635 | "tensor([[19., 22.],\n",
636 | " [43., 50.]])"
637 | ]
638 | },
639 | "execution_count": 33,
640 | "metadata": {},
641 | "output_type": "execute_result"
642 | }
643 | ],
644 | "source": [
645 | "torch.matmul(matrix1, matrix2)"
646 | ]
647 | },
648 | {
649 | "cell_type": "markdown",
650 | "metadata": {},
651 | "source": [
652 | "# Tensor"
653 | ]
654 | },
655 | {
656 | "cell_type": "code",
657 | "execution_count": 34,
658 | "metadata": {},
659 | "outputs": [
660 | {
661 | "name": "stdout",
662 | "output_type": "stream",
663 | "text": [
664 | "tensor([[[1., 2.],\n",
665 | " [3., 4.]],\n",
666 | "\n",
667 | " [[5., 6.],\n",
668 | " [7., 8.]]])\n"
669 | ]
670 | }
671 | ],
672 | "source": [
673 | "tensor1 = torch.tensor([[[1., 2.], [3., 4.]], [[5., 6.], [7., 8.]]])\n",
674 | "print(tensor1)"
675 | ]
676 | },
677 | {
678 | "cell_type": "code",
679 | "execution_count": 35,
680 | "metadata": {},
681 | "outputs": [
682 | {
683 | "name": "stdout",
684 | "output_type": "stream",
685 | "text": [
686 | "tensor([[[ 9., 10.],\n",
687 | " [11., 12.]],\n",
688 | "\n",
689 | " [[13., 14.],\n",
690 | " [15., 16.]]])\n"
691 | ]
692 | }
693 | ],
694 | "source": [
695 | "tensor2 = torch.tensor([[[9., 10.], [11., 12.]], [[13., 14.], [15., 16.]]])\n",
696 | "print(tensor2)"
697 | ]
698 | },
699 | {
700 | "cell_type": "code",
701 | "execution_count": 36,
702 | "metadata": {},
703 | "outputs": [
704 | {
705 | "name": "stdout",
706 | "output_type": "stream",
707 | "text": [
708 | "tensor([[[10., 12.],\n",
709 | " [14., 16.]],\n",
710 | "\n",
711 | " [[18., 20.],\n",
712 | " [22., 24.]]])\n"
713 | ]
714 | }
715 | ],
716 | "source": [
717 | "sum_tensor = tensor1 + tensor2\n",
718 | "print(sum_tensor)"
719 | ]
720 | },
721 | {
722 | "cell_type": "code",
723 | "execution_count": 37,
724 | "metadata": {},
725 | "outputs": [
726 | {
727 | "name": "stdout",
728 | "output_type": "stream",
729 | "text": [
730 | "tensor([[[-8., -8.],\n",
731 | " [-8., -8.]],\n",
732 | "\n",
733 | " [[-8., -8.],\n",
734 | " [-8., -8.]]])\n"
735 | ]
736 | }
737 | ],
738 | "source": [
739 | "sub_tensor = tensor1 - tensor2\n",
740 | "print(sub_tensor)"
741 | ]
742 | },
743 | {
744 | "cell_type": "code",
745 | "execution_count": 38,
746 | "metadata": {},
747 | "outputs": [
748 | {
749 | "name": "stdout",
750 | "output_type": "stream",
751 | "text": [
752 | "tensor([[[ 9., 20.],\n",
753 | " [ 33., 48.]],\n",
754 | "\n",
755 | " [[ 65., 84.],\n",
756 | " [105., 128.]]])\n"
757 | ]
758 | }
759 | ],
760 | "source": [
761 | "mul_tensor = tensor1 * tensor2\n",
762 | "print(mul_tensor)"
763 | ]
764 | },
765 | {
766 | "cell_type": "code",
767 | "execution_count": 39,
768 | "metadata": {},
769 | "outputs": [
770 | {
771 | "name": "stdout",
772 | "output_type": "stream",
773 | "text": [
774 | "tensor([[[0.1111, 0.2000],\n",
775 | " [0.2727, 0.3333]],\n",
776 | "\n",
777 | " [[0.3846, 0.4286],\n",
778 | " [0.4667, 0.5000]]])\n"
779 | ]
780 | }
781 | ],
782 | "source": [
783 | "div_tensor = tensor1 / tensor2\n",
784 | "print(div_tensor)"
785 | ]
786 | },
787 | {
788 | "cell_type": "code",
789 | "execution_count": 40,
790 | "metadata": {},
791 | "outputs": [
792 | {
793 | "data": {
794 | "text/plain": [
795 | "tensor([[[ 31., 34.],\n",
796 | " [ 71., 78.]],\n",
797 | "\n",
798 | " [[155., 166.],\n",
799 | " [211., 226.]]])"
800 | ]
801 | },
802 | "execution_count": 40,
803 | "metadata": {},
804 | "output_type": "execute_result"
805 | }
806 | ],
807 | "source": [
808 | "torch.matmul(tensor1, tensor2)"
809 | ]
810 | },
811 | {
812 | "cell_type": "code",
813 | "execution_count": 41,
814 | "metadata": {},
815 | "outputs": [
816 | {
817 | "data": {
818 | "text/plain": [
819 | "tensor([[[10., 12.],\n",
820 | " [14., 16.]],\n",
821 | "\n",
822 | " [[18., 20.],\n",
823 | " [22., 24.]]])"
824 | ]
825 | },
826 | "execution_count": 41,
827 | "metadata": {},
828 | "output_type": "execute_result"
829 | }
830 | ],
831 | "source": [
832 | "torch.add(tensor1, tensor2)"
833 | ]
834 | },
835 | {
836 | "cell_type": "code",
837 | "execution_count": 42,
838 | "metadata": {},
839 | "outputs": [
840 | {
841 | "data": {
842 | "text/plain": [
843 | "tensor([[[-8., -8.],\n",
844 | " [-8., -8.]],\n",
845 | "\n",
846 | " [[-8., -8.],\n",
847 | " [-8., -8.]]])"
848 | ]
849 | },
850 | "execution_count": 42,
851 | "metadata": {},
852 | "output_type": "execute_result"
853 | }
854 | ],
855 | "source": [
856 | "torch.sub(tensor1, tensor2)"
857 | ]
858 | },
859 | {
860 | "cell_type": "code",
861 | "execution_count": 43,
862 | "metadata": {},
863 | "outputs": [
864 | {
865 | "data": {
866 | "text/plain": [
867 | "tensor([[[ 9., 20.],\n",
868 | " [ 33., 48.]],\n",
869 | "\n",
870 | " [[ 65., 84.],\n",
871 | " [105., 128.]]])"
872 | ]
873 | },
874 | "execution_count": 43,
875 | "metadata": {},
876 | "output_type": "execute_result"
877 | }
878 | ],
879 | "source": [
880 | "torch.mul(tensor1, tensor2)"
881 | ]
882 | },
883 | {
884 | "cell_type": "code",
885 | "execution_count": 44,
886 | "metadata": {},
887 | "outputs": [
888 | {
889 | "data": {
890 | "text/plain": [
891 | "tensor([[[0.1111, 0.2000],\n",
892 | " [0.2727, 0.3333]],\n",
893 | "\n",
894 | " [[0.3846, 0.4286],\n",
895 | " [0.4667, 0.5000]]])"
896 | ]
897 | },
898 | "execution_count": 44,
899 | "metadata": {},
900 | "output_type": "execute_result"
901 | }
902 | ],
903 | "source": [
904 | "torch.div(tensor1, tensor2)"
905 | ]
906 | },
907 | {
908 | "cell_type": "code",
909 | "execution_count": 45,
910 | "metadata": {},
911 | "outputs": [
912 | {
913 | "data": {
914 | "text/plain": [
915 | "tensor([[[1., 2.],\n",
916 | " [3., 4.]],\n",
917 | "\n",
918 | " [[5., 6.],\n",
919 | " [7., 8.]]])"
920 | ]
921 | },
922 | "execution_count": 45,
923 | "metadata": {},
924 | "output_type": "execute_result"
925 | }
926 | ],
927 | "source": [
928 | "tensor1"
929 | ]
930 | },
931 | {
932 | "cell_type": "code",
933 | "execution_count": 46,
934 | "metadata": {},
935 | "outputs": [
936 | {
937 | "data": {
938 | "text/plain": [
939 | "tensor([[[ 9., 10.],\n",
940 | " [11., 12.]],\n",
941 | "\n",
942 | " [[13., 14.],\n",
943 | " [15., 16.]]])"
944 | ]
945 | },
946 | "execution_count": 46,
947 | "metadata": {},
948 | "output_type": "execute_result"
949 | }
950 | ],
951 | "source": [
952 | "tensor2"
953 | ]
954 | },
955 | {
956 | "cell_type": "code",
957 | "execution_count": 47,
958 | "metadata": {},
959 | "outputs": [
960 | {
961 | "data": {
962 | "text/plain": [
963 | "tensor([[[ 31., 34.],\n",
964 | " [ 71., 78.]],\n",
965 | "\n",
966 | " [[155., 166.],\n",
967 | " [211., 226.]]])"
968 | ]
969 | },
970 | "execution_count": 47,
971 | "metadata": {},
972 | "output_type": "execute_result"
973 | }
974 | ],
975 | "source": [
976 | "torch.matmul(tensor1, tensor2)"
977 | ]
978 | },
979 | {
980 | "cell_type": "code",
981 | "execution_count": 48,
982 | "metadata": {},
983 | "outputs": [
984 | {
985 | "name": "stdout",
986 | "output_type": "stream",
987 | "text": [
988 | "Iteration: 100 \t Loss: 527.76318359375\n",
989 | "Iteration: 200 \t Loss: 3.209841728210449\n",
990 | "Iteration: 300 \t Loss: 0.03574322536587715\n",
991 | "Iteration: 400 \t Loss: 0.0007254641968756914\n",
992 | "Iteration: 500 \t Loss: 8.230483217630535e-05\n"
993 | ]
994 | }
995 | ],
996 | "source": [
997 | "import torch\n",
998 | "\n",
999 | "if torch.cuda.is_available():\n",
1000 | " DEVICE = torch.device('cuda')\n",
1001 | "else:\n",
1002 | " DEVICE = torch.device('cpu')\n",
1003 | "\n",
1004 | "BATCH_SIZE = 64\n",
1005 | "INPUT_SIZE = 1000\n",
1006 | "HIDDEN_SIZE = 100\n",
1007 | "OUTPUT_SIZE = 10\n",
1008 | "\n",
1009 | "x = torch.randn(BATCH_SIZE, \n",
1010 | " INPUT_SIZE, \n",
1011 | " device = DEVICE, \n",
1012 | " dtype = torch.float, \n",
1013 | " requires_grad = False) \n",
1014 | "\n",
1015 | "y = torch.randn(BATCH_SIZE, \n",
1016 | " OUTPUT_SIZE, \n",
1017 | " device = DEVICE,\n",
1018 | " dtype = torch.float, \n",
1019 | " requires_grad = False) \n",
1020 | "\n",
1021 | "w1 = torch.randn(INPUT_SIZE, \n",
1022 | " HIDDEN_SIZE, \n",
1023 | " device = DEVICE, \n",
1024 | " dtype = torch.float,\n",
1025 | " requires_grad = True) \n",
1026 | "\n",
1027 | "w2 = torch.randn(HIDDEN_SIZE,\n",
1028 | " OUTPUT_SIZE, \n",
1029 | " device = DEVICE,\n",
1030 | " dtype = torch.float,\n",
1031 | " requires_grad = True) \n",
1032 | "\n",
1033 | "learning_rate = 1e-6 \n",
1034 | "for t in range(1, 501): \n",
1035 | " y_pred = x.mm(w1).clamp(min = 0).mm(w2) \n",
1036 | "\n",
1037 | " loss = (y_pred - y).pow(2).sum() \n",
1038 | " if t % 100 == 0:\n",
1039 | " print(\"Iteration: \", t, \"\\t\", \"Loss: \", loss.item()) \n",
1040 | " loss.backward() \n",
1041 | "\n",
1042 | " with torch.no_grad(): \n",
1043 | " w1 -= learning_rate * w1.grad \n",
1044 | " w2 -= learning_rate * w2.grad \n",
1045 | "\n",
1046 | " w1.grad.zero_() \n",
1047 | " w2.grad.zero_() "
1048 | ]
1049 | },
1050 | {
1051 | "cell_type": "code",
1052 | "execution_count": 49,
1053 | "metadata": {},
1054 | "outputs": [],
1055 | "source": [
1056 | "# Iteration: 100 \t Loss: 976.0719604492188\n",
1057 | "# Iteration: 200 \t Loss: 5.061180114746094\n",
1058 | "# Iteration: 300 \t Loss: 0.04102771729230881\n",
1059 | "# Iteration: 400 \t Loss: 0.0006718397489748895\n",
1060 | "# Iteration: 500 \t Loss: 6.94335249136202e-05"
1061 | ]
1062 | }
1063 | ],
1064 | "metadata": {
1065 | "kernelspec": {
1066 | "display_name": "Python 3",
1067 | "language": "python",
1068 | "name": "python3"
1069 | },
1070 | "language_info": {
1071 | "codemirror_mode": {
1072 | "name": "ipython",
1073 | "version": 3
1074 | },
1075 | "file_extension": ".py",
1076 | "mimetype": "text/x-python",
1077 | "name": "python",
1078 | "nbconvert_exporter": "python",
1079 | "pygments_lexer": "ipython3",
1080 | "version": "3.6.8"
1081 | }
1082 | },
1083 | "nbformat": 4,
1084 | "nbformat_minor": 4
1085 | }
1086 |
--------------------------------------------------------------------------------
/3-5_MNIST_MLP_Dropout_ReLU_BN_HE_Adam.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 1,
6 | "metadata": {},
7 | "outputs": [],
8 | "source": [
9 | "''' 1. Module Import '''\n",
10 | "import numpy as np\n",
11 | "import matplotlib.pyplot as plt\n",
12 | "\n",
13 | "import torch\n",
14 | "import torch.nn as nn\n",
15 | "import torch.nn.functional as F\n",
16 | "from torchvision import transforms, datasets"
17 | ]
18 | },
19 | {
20 | "cell_type": "code",
21 | "execution_count": 2,
22 | "metadata": {},
23 | "outputs": [
24 | {
25 | "name": "stdout",
26 | "output_type": "stream",
27 | "text": [
28 | "Using PyTorch version: 1.6.0+cu101 Device: cuda\n"
29 | ]
30 | }
31 | ],
32 | "source": [
33 | "''' 2. 딥러닝 모델을 설계할 때 활용하는 장비 확인 '''\n",
34 | "if torch.cuda.is_available():\n",
35 | " DEVICE = torch.device('cuda')\n",
36 | "else:\n",
37 | " DEVICE = torch.device('cpu')\n",
38 | "print('Using PyTorch version:', torch.__version__, ' Device:', DEVICE)"
39 | ]
40 | },
41 | {
42 | "cell_type": "code",
43 | "execution_count": 3,
44 | "metadata": {},
45 | "outputs": [],
46 | "source": [
47 | "BATCH_SIZE = 32\n",
48 | "EPOCHS = 10"
49 | ]
50 | },
51 | {
52 | "cell_type": "code",
53 | "execution_count": 4,
54 | "metadata": {},
55 | "outputs": [],
56 | "source": [
57 | "''' 3. MNIST 데이터 다운로드 (Train set, Test set 분리하기) '''\n",
58 | "train_dataset = datasets.MNIST(root = \"../data/MNIST\",\n",
59 | " train = True,\n",
60 | " download = True,\n",
61 | " transform = transforms.ToTensor())\n",
62 | "\n",
63 | "test_dataset = datasets.MNIST(root = \"../data/MNIST\",\n",
64 | " train = False,\n",
65 | " transform = transforms.ToTensor())\n",
66 | "\n",
67 | "train_loader = torch.utils.data.DataLoader(dataset = train_dataset,\n",
68 | " batch_size = BATCH_SIZE,\n",
69 | " shuffle = True)\n",
70 | "\n",
71 | "test_loader = torch.utils.data.DataLoader(dataset = test_dataset,\n",
72 | " batch_size = BATCH_SIZE,\n",
73 | " shuffle = False)"
74 | ]
75 | },
76 | {
77 | "cell_type": "code",
78 | "execution_count": 5,
79 | "metadata": {},
80 | "outputs": [
81 | {
82 | "name": "stdout",
83 | "output_type": "stream",
84 | "text": [
85 | "X_train: torch.Size([32, 1, 28, 28]) type: torch.FloatTensor\n",
86 | "y_train: torch.Size([32]) type: torch.LongTensor\n"
87 | ]
88 | }
89 | ],
90 | "source": [
91 | "''' 4. 데이터 확인하기 (1) '''\n",
92 | "for (X_train, y_train) in train_loader:\n",
93 | " print('X_train:', X_train.size(), 'type:', X_train.type())\n",
94 | " print('y_train:', y_train.size(), 'type:', y_train.type())\n",
95 | " break"
96 | ]
97 | },
98 | {
99 | "cell_type": "code",
100 | "execution_count": 6,
101 | "metadata": {},
102 | "outputs": [
103 | {
104 | "data": {
105 | "image/png": "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\n",
106 | "text/plain": [
107 | ""
108 | ]
109 | },
110 | "metadata": {
111 | "needs_background": "light"
112 | },
113 | "output_type": "display_data"
114 | }
115 | ],
116 | "source": [
117 | "''' 5. 데이터 확인하기 (2) '''\n",
118 | "pltsize = 1\n",
119 | "plt.figure(figsize=(10 * pltsize, pltsize))\n",
120 | "for i in range(10):\n",
121 | " plt.subplot(1, 10, i + 1)\n",
122 | " plt.axis('off')\n",
123 | " plt.imshow(X_train[i, :, :, :].numpy().reshape(28, 28), cmap = \"gray_r\")\n",
124 | " plt.title('Class: ' + str(y_train[i].item()))"
125 | ]
126 | },
127 | {
128 | "cell_type": "code",
129 | "execution_count": 7,
130 | "metadata": {},
131 | "outputs": [],
132 | "source": [
133 | "''' 6. Multi Layer Perceptron (MLP) 모델 설계하기 '''\n",
134 | "class Net(nn.Module):\n",
135 | " def __init__(self):\n",
136 | " super(Net, self).__init__()\n",
137 | " self.fc1 = nn.Linear(28 * 28, 512)\n",
138 | " self.fc2 = nn.Linear(512, 256)\n",
139 | " self.fc3 = nn.Linear(256, 10)\n",
140 | " self.dropout_prob = 0.5\n",
141 | " self.batch_norm1 = nn.BatchNorm1d(512)\n",
142 | " self.batch_norm2 = nn.BatchNorm1d(256)\n",
143 | "\n",
144 | " def forward(self, x):\n",
145 | " x = x.view(-1, 28 * 28)\n",
146 | " x = self.fc1(x)\n",
147 | " x = self.batch_norm1(x)\n",
148 | " x = F.relu(x)\n",
149 | " x = F.dropout(x, training = self.training, p = self.dropout_prob)\n",
150 | " x = self.fc2(x)\n",
151 | " x = self.batch_norm2(x)\n",
152 | " x = F.relu(x)\n",
153 | " x = F.dropout(x, training = self.training, p = self.dropout_prob)\n",
154 | " x = self.fc3(x)\n",
155 | " x = F.log_softmax(x, dim = 1)\n",
156 | " return x"
157 | ]
158 | },
159 | {
160 | "cell_type": "code",
161 | "execution_count": 8,
162 | "metadata": {},
163 | "outputs": [
164 | {
165 | "name": "stdout",
166 | "output_type": "stream",
167 | "text": [
168 | "Net(\n",
169 | " (fc1): Linear(in_features=784, out_features=512, bias=True)\n",
170 | " (fc2): Linear(in_features=512, out_features=256, bias=True)\n",
171 | " (fc3): Linear(in_features=256, out_features=10, bias=True)\n",
172 | " (batch_norm1): BatchNorm1d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
173 | " (batch_norm2): BatchNorm1d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
174 | ")\n"
175 | ]
176 | }
177 | ],
178 | "source": [
179 | "''' 7. Optimizer, Objective Function 설정하기 '''\n",
180 | "import torch.nn.init as init\n",
181 | "def weight_init(m):\n",
182 | " if isinstance(m, nn.Linear):\n",
183 | " init.kaiming_uniform_(m.weight.data)\n",
184 | "\n",
185 | "model = Net().to(DEVICE)\n",
186 | "model.apply(weight_init)\n",
187 | "optimizer = torch.optim.Adam(model.parameters(), lr = 0.01)\n",
188 | "criterion = nn.CrossEntropyLoss()\n",
189 | "\n",
190 | "print(model)"
191 | ]
192 | },
193 | {
194 | "cell_type": "code",
195 | "execution_count": 9,
196 | "metadata": {},
197 | "outputs": [],
198 | "source": [
199 | "''' 8. MLP 모델 학습을 진행하며 학습 데이터에 대한 모델 성능을 확인하는 함수 정의 '''\n",
200 | "def train(model, train_loader, optimizer, log_interval):\n",
201 | " model.train()\n",
202 | " for batch_idx, (image, label) in enumerate(train_loader):\n",
203 | " image = image.to(DEVICE)\n",
204 | " label = label.to(DEVICE)\n",
205 | " optimizer.zero_grad()\n",
206 | " output = model(image)\n",
207 | " loss = criterion(output, label)\n",
208 | " loss.backward()\n",
209 | " optimizer.step()\n",
210 | "\n",
211 | " if batch_idx % log_interval == 0:\n",
212 | " print(\"Train Epoch: {} [{}/{} ({:.0f}%)]\\tTrain Loss: {:.6f}\".format(\n",
213 | " epoch, batch_idx * len(image), \n",
214 | " len(train_loader.dataset), 100. * batch_idx / len(train_loader), \n",
215 | " loss.item()))"
216 | ]
217 | },
218 | {
219 | "cell_type": "code",
220 | "execution_count": 10,
221 | "metadata": {},
222 | "outputs": [],
223 | "source": [
224 | "''' 9. 학습되는 과정 속에서 검증 데이터에 대한 모델 성능을 확인하는 함수 정의 '''\n",
225 | "def evaluate(model, test_loader):\n",
226 | " model.eval()\n",
227 | " test_loss = 0\n",
228 | " correct = 0\n",
229 | "\n",
230 | " with torch.no_grad():\n",
231 | " for image, label in test_loader:\n",
232 | " image = image.to(DEVICE)\n",
233 | " label = label.to(DEVICE)\n",
234 | " output = model(image)\n",
235 | " test_loss += criterion(output, label).item()\n",
236 | " prediction = output.max(1, keepdim = True)[1]\n",
237 | " correct += prediction.eq(label.view_as(prediction)).sum().item()\n",
238 | " \n",
239 | " test_loss /= (len(test_loader.dataset) / BATCH_SIZE)\n",
240 | " test_accuracy = 100. * correct / len(test_loader.dataset)\n",
241 | " return test_loss, test_accuracy"
242 | ]
243 | },
244 | {
245 | "cell_type": "code",
246 | "execution_count": 11,
247 | "metadata": {},
248 | "outputs": [
249 | {
250 | "name": "stdout",
251 | "output_type": "stream",
252 | "text": [
253 | "Train Epoch: 1 [0/60000 (0%)]\tTrain Loss: 3.199550\n",
254 | "Train Epoch: 1 [6400/60000 (11%)]\tTrain Loss: 0.513148\n",
255 | "Train Epoch: 1 [12800/60000 (21%)]\tTrain Loss: 0.923122\n",
256 | "Train Epoch: 1 [19200/60000 (32%)]\tTrain Loss: 0.233807\n",
257 | "Train Epoch: 1 [25600/60000 (43%)]\tTrain Loss: 0.355385\n",
258 | "Train Epoch: 1 [32000/60000 (53%)]\tTrain Loss: 0.256300\n",
259 | "Train Epoch: 1 [38400/60000 (64%)]\tTrain Loss: 0.213376\n",
260 | "Train Epoch: 1 [44800/60000 (75%)]\tTrain Loss: 0.442577\n",
261 | "Train Epoch: 1 [51200/60000 (85%)]\tTrain Loss: 0.195819\n",
262 | "Train Epoch: 1 [57600/60000 (96%)]\tTrain Loss: 0.126851\n",
263 | "\n",
264 | "[EPOCH: 1], \tTest Loss: 0.0043, \tTest Accuracy: 95.85 % \n",
265 | "\n",
266 | "Train Epoch: 2 [0/60000 (0%)]\tTrain Loss: 0.416017\n",
267 | "Train Epoch: 2 [6400/60000 (11%)]\tTrain Loss: 0.328205\n",
268 | "Train Epoch: 2 [12800/60000 (21%)]\tTrain Loss: 0.197520\n",
269 | "Train Epoch: 2 [19200/60000 (32%)]\tTrain Loss: 0.068057\n",
270 | "Train Epoch: 2 [25600/60000 (43%)]\tTrain Loss: 0.609262\n",
271 | "Train Epoch: 2 [32000/60000 (53%)]\tTrain Loss: 0.211904\n",
272 | "Train Epoch: 2 [38400/60000 (64%)]\tTrain Loss: 0.098402\n",
273 | "Train Epoch: 2 [44800/60000 (75%)]\tTrain Loss: 0.043566\n",
274 | "Train Epoch: 2 [51200/60000 (85%)]\tTrain Loss: 0.084222\n",
275 | "Train Epoch: 2 [57600/60000 (96%)]\tTrain Loss: 0.069517\n",
276 | "\n",
277 | "[EPOCH: 2], \tTest Loss: 0.0035, \tTest Accuracy: 96.63 % \n",
278 | "\n",
279 | "Train Epoch: 3 [0/60000 (0%)]\tTrain Loss: 0.120982\n",
280 | "Train Epoch: 3 [6400/60000 (11%)]\tTrain Loss: 0.034953\n",
281 | "Train Epoch: 3 [12800/60000 (21%)]\tTrain Loss: 0.106771\n",
282 | "Train Epoch: 3 [19200/60000 (32%)]\tTrain Loss: 0.325835\n",
283 | "Train Epoch: 3 [25600/60000 (43%)]\tTrain Loss: 0.071694\n",
284 | "Train Epoch: 3 [32000/60000 (53%)]\tTrain Loss: 0.203136\n",
285 | "Train Epoch: 3 [38400/60000 (64%)]\tTrain Loss: 0.087571\n",
286 | "Train Epoch: 3 [44800/60000 (75%)]\tTrain Loss: 0.578591\n",
287 | "Train Epoch: 3 [51200/60000 (85%)]\tTrain Loss: 0.058942\n",
288 | "Train Epoch: 3 [57600/60000 (96%)]\tTrain Loss: 0.083058\n",
289 | "\n",
290 | "[EPOCH: 3], \tTest Loss: 0.0030, \tTest Accuracy: 97.25 % \n",
291 | "\n",
292 | "Train Epoch: 4 [0/60000 (0%)]\tTrain Loss: 0.292411\n",
293 | "Train Epoch: 4 [6400/60000 (11%)]\tTrain Loss: 0.265194\n",
294 | "Train Epoch: 4 [12800/60000 (21%)]\tTrain Loss: 0.247585\n",
295 | "Train Epoch: 4 [19200/60000 (32%)]\tTrain Loss: 0.247720\n",
296 | "Train Epoch: 4 [25600/60000 (43%)]\tTrain Loss: 0.201436\n",
297 | "Train Epoch: 4 [32000/60000 (53%)]\tTrain Loss: 0.208042\n",
298 | "Train Epoch: 4 [38400/60000 (64%)]\tTrain Loss: 0.104799\n",
299 | "Train Epoch: 4 [44800/60000 (75%)]\tTrain Loss: 0.095104\n",
300 | "Train Epoch: 4 [51200/60000 (85%)]\tTrain Loss: 0.321322\n",
301 | "Train Epoch: 4 [57600/60000 (96%)]\tTrain Loss: 0.575262\n",
302 | "\n",
303 | "[EPOCH: 4], \tTest Loss: 0.0027, \tTest Accuracy: 97.41 % \n",
304 | "\n",
305 | "Train Epoch: 5 [0/60000 (0%)]\tTrain Loss: 0.342820\n",
306 | "Train Epoch: 5 [6400/60000 (11%)]\tTrain Loss: 0.028762\n",
307 | "Train Epoch: 5 [12800/60000 (21%)]\tTrain Loss: 0.215698\n",
308 | "Train Epoch: 5 [19200/60000 (32%)]\tTrain Loss: 0.226103\n",
309 | "Train Epoch: 5 [25600/60000 (43%)]\tTrain Loss: 0.128261\n",
310 | "Train Epoch: 5 [32000/60000 (53%)]\tTrain Loss: 0.232673\n",
311 | "Train Epoch: 5 [38400/60000 (64%)]\tTrain Loss: 0.109379\n",
312 | "Train Epoch: 5 [44800/60000 (75%)]\tTrain Loss: 0.319595\n",
313 | "Train Epoch: 5 [51200/60000 (85%)]\tTrain Loss: 0.329783\n",
314 | "Train Epoch: 5 [57600/60000 (96%)]\tTrain Loss: 0.254121\n",
315 | "\n",
316 | "[EPOCH: 5], \tTest Loss: 0.0026, \tTest Accuracy: 97.50 % \n",
317 | "\n",
318 | "Train Epoch: 6 [0/60000 (0%)]\tTrain Loss: 0.168219\n",
319 | "Train Epoch: 6 [6400/60000 (11%)]\tTrain Loss: 0.187313\n",
320 | "Train Epoch: 6 [12800/60000 (21%)]\tTrain Loss: 0.226820\n",
321 | "Train Epoch: 6 [19200/60000 (32%)]\tTrain Loss: 0.088462\n",
322 | "Train Epoch: 6 [25600/60000 (43%)]\tTrain Loss: 0.336217\n",
323 | "Train Epoch: 6 [32000/60000 (53%)]\tTrain Loss: 0.395337\n",
324 | "Train Epoch: 6 [38400/60000 (64%)]\tTrain Loss: 0.034127\n",
325 | "Train Epoch: 6 [44800/60000 (75%)]\tTrain Loss: 0.181321\n",
326 | "Train Epoch: 6 [51200/60000 (85%)]\tTrain Loss: 0.183680\n",
327 | "Train Epoch: 6 [57600/60000 (96%)]\tTrain Loss: 0.409360\n",
328 | "\n",
329 | "[EPOCH: 6], \tTest Loss: 0.0024, \tTest Accuracy: 97.73 % \n",
330 | "\n",
331 | "Train Epoch: 7 [0/60000 (0%)]\tTrain Loss: 0.041711\n",
332 | "Train Epoch: 7 [6400/60000 (11%)]\tTrain Loss: 0.208485\n",
333 | "Train Epoch: 7 [12800/60000 (21%)]\tTrain Loss: 0.121613\n",
334 | "Train Epoch: 7 [19200/60000 (32%)]\tTrain Loss: 0.011681\n",
335 | "Train Epoch: 7 [25600/60000 (43%)]\tTrain Loss: 0.573379\n",
336 | "Train Epoch: 7 [32000/60000 (53%)]\tTrain Loss: 0.144857\n",
337 | "Train Epoch: 7 [38400/60000 (64%)]\tTrain Loss: 0.083845\n",
338 | "Train Epoch: 7 [44800/60000 (75%)]\tTrain Loss: 0.326227\n",
339 | "Train Epoch: 7 [51200/60000 (85%)]\tTrain Loss: 0.051569\n",
340 | "Train Epoch: 7 [57600/60000 (96%)]\tTrain Loss: 0.037317\n",
341 | "\n",
342 | "[EPOCH: 7], \tTest Loss: 0.0023, \tTest Accuracy: 97.89 % \n",
343 | "\n",
344 | "Train Epoch: 8 [0/60000 (0%)]\tTrain Loss: 0.041605\n",
345 | "Train Epoch: 8 [6400/60000 (11%)]\tTrain Loss: 0.199083\n",
346 | "Train Epoch: 8 [12800/60000 (21%)]\tTrain Loss: 0.359119\n",
347 | "Train Epoch: 8 [19200/60000 (32%)]\tTrain Loss: 0.054514\n",
348 | "Train Epoch: 8 [25600/60000 (43%)]\tTrain Loss: 0.007979\n",
349 | "Train Epoch: 8 [32000/60000 (53%)]\tTrain Loss: 0.043286\n",
350 | "Train Epoch: 8 [38400/60000 (64%)]\tTrain Loss: 0.201188\n",
351 | "Train Epoch: 8 [44800/60000 (75%)]\tTrain Loss: 0.095515\n",
352 | "Train Epoch: 8 [51200/60000 (85%)]\tTrain Loss: 0.122469\n",
353 | "Train Epoch: 8 [57600/60000 (96%)]\tTrain Loss: 0.061429\n",
354 | "\n",
355 | "[EPOCH: 8], \tTest Loss: 0.0024, \tTest Accuracy: 97.64 % \n",
356 | "\n",
357 | "Train Epoch: 9 [0/60000 (0%)]\tTrain Loss: 0.152112\n",
358 | "Train Epoch: 9 [6400/60000 (11%)]\tTrain Loss: 0.136112\n",
359 | "Train Epoch: 9 [12800/60000 (21%)]\tTrain Loss: 0.071809\n",
360 | "Train Epoch: 9 [19200/60000 (32%)]\tTrain Loss: 0.021181\n",
361 | "Train Epoch: 9 [25600/60000 (43%)]\tTrain Loss: 0.035105\n",
362 | "Train Epoch: 9 [32000/60000 (53%)]\tTrain Loss: 0.632621\n",
363 | "Train Epoch: 9 [38400/60000 (64%)]\tTrain Loss: 0.077700\n",
364 | "Train Epoch: 9 [44800/60000 (75%)]\tTrain Loss: 0.144102\n",
365 | "Train Epoch: 9 [51200/60000 (85%)]\tTrain Loss: 0.061276\n",
366 | "Train Epoch: 9 [57600/60000 (96%)]\tTrain Loss: 0.066728\n",
367 | "\n",
368 | "[EPOCH: 9], \tTest Loss: 0.0024, \tTest Accuracy: 97.69 % \n",
369 | "\n",
370 | "Train Epoch: 10 [0/60000 (0%)]\tTrain Loss: 0.429119\n",
371 | "Train Epoch: 10 [6400/60000 (11%)]\tTrain Loss: 0.043460\n",
372 | "Train Epoch: 10 [12800/60000 (21%)]\tTrain Loss: 0.073910\n",
373 | "Train Epoch: 10 [19200/60000 (32%)]\tTrain Loss: 0.212445\n",
374 | "Train Epoch: 10 [25600/60000 (43%)]\tTrain Loss: 0.062954\n",
375 | "Train Epoch: 10 [32000/60000 (53%)]\tTrain Loss: 0.282957\n",
376 | "Train Epoch: 10 [38400/60000 (64%)]\tTrain Loss: 0.425912\n",
377 | "Train Epoch: 10 [44800/60000 (75%)]\tTrain Loss: 0.247884\n",
378 | "Train Epoch: 10 [51200/60000 (85%)]\tTrain Loss: 0.166647\n",
379 | "Train Epoch: 10 [57600/60000 (96%)]\tTrain Loss: 0.081299\n",
380 | "\n",
381 | "[EPOCH: 10], \tTest Loss: 0.0021, \tTest Accuracy: 97.97 % \n",
382 | "\n"
383 | ]
384 | }
385 | ],
386 | "source": [
387 | "''' 10. MLP 학습 실행하며 Train, Test set의 Loss 및 Test set Accuracy 확인하기 '''\n",
388 | "for epoch in range(1, EPOCHS + 1):\n",
389 | " train(model, train_loader, optimizer, log_interval = 200)\n",
390 | " test_loss, test_accuracy = evaluate(model, test_loader)\n",
391 | " print(\"\\n[EPOCH: {}], \\tTest Loss: {:.4f}, \\tTest Accuracy: {:.2f} % \\n\".format(\n",
392 | " epoch, test_loss, test_accuracy))"
393 | ]
394 | }
395 | ],
396 | "metadata": {
397 | "kernelspec": {
398 | "display_name": "Python 3",
399 | "language": "python",
400 | "name": "python3"
401 | },
402 | "language_info": {
403 | "codemirror_mode": {
404 | "name": "ipython",
405 | "version": 3
406 | },
407 | "file_extension": ".py",
408 | "mimetype": "text/x-python",
409 | "name": "python",
410 | "nbconvert_exporter": "python",
411 | "pygments_lexer": "ipython3",
412 | "version": "3.6.8"
413 | }
414 | },
415 | "nbformat": 4,
416 | "nbformat_minor": 4
417 | }
418 |
--------------------------------------------------------------------------------
/5_NLP_v2.ipynb:
--------------------------------------------------------------------------------
1 | {"nbformat":4,"nbformat_minor":0,"metadata":{"accelerator":"GPU","colab":{"name":"5_NLP_v2.ipynb","provenance":[],"collapsed_sections":[]},"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.6.8"}},"cells":[{"cell_type":"code","metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"2XWOHqwyv9Kn","executionInfo":{"elapsed":811,"status":"ok","timestamp":1647777651500,"user":{"displayName":"seongsu bang","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"12261094723698722963"},"user_tz":-540},"outputId":"96d225df-49cb-4d65-9e8c-97a3123055af"},"source":["# ! pip list | grep \"torch\"\n","# torch 1.10.0+cu111\n","# torchaudio 0.10.0+cu111\n","# torchsummary 1.5.1\n","# torchtext 0.11.0\n","# torchvision 0.11.1+cu111\n","\n","https://pytorch.org/tutorials/beginner/text_sentiment_ngrams_tutorial.html\n","https://tutorials.pytorch.kr/beginner/text_sentiment_ngrams_tutorial.html\n","\n","# 해당 코드는 위 페이지를 기반으로 만들어진 코드입니다. \n","# torchtext가 편한 부분도 많지만, 버전 변화에 따른 코드 변화도 많네요. 앞으로도 버전 변경으로 인한 오류가 생길 가능성이 있습니다.\n","# 해당 파일의 리팩토링 피드백이 늦는다면, 위 공식 문서를 참고하여 변경 부분을 확인하시거나 위 library 버전을 사용하시길 권장합니다.\n","\n","# 이 파일에는 from_scratch, recurrent 모델들을 모두 선택해서 학습할 수 있도록 작성 했습니다. \n","# 그 과정에서 코드가 복잡해진 점에 대해 미리 사과드립니다."],"execution_count":1,"outputs":[{"output_type":"stream","name":"stdout","text":["torch 1.10.0+cu111\n","torchaudio 0.10.0+cu111\n","torchsummary 1.5.1\n","torchtext 0.11.0\n","torchvision 0.11.1+cu111\n"]}]},{"cell_type":"code","source":["import os\n","import time\n","import torch\n","from tqdm import tqdm\n","\n","from torch import nn\n","from torch.utils.data import DataLoader\n","from torch.nn.utils.rnn import pad_sequence\n","from torch.utils.data.dataset import random_split\n","\n","from torchtext.datasets import IMDB\n","from torchtext.data.utils import get_tokenizer\n","from torchtext.data.functional import to_map_style_dataset\n","from torchtext.vocab import build_vocab_from_iterator, Vectors\n","\n","\n","\n","config = {'pre_trained' : 'glove', # 'glove','fasttext', None \n"," 'max_length': 300,\n"," 'batch_size': 64,\n"," 'model_type': 'gru', # 'rnn', 'lstm', 'gru','avg_not_pad', None\n"," 'emb_dim' : 300,\n"," 'hidden_dim':128,\n"," 'is_bidirectional':True,\n"," 'epoch' : 15,\n"," 'LR': 5\n"," }\n"],"metadata":{"id":"Nd6V2m4QCJ4G","executionInfo":{"status":"ok","timestamp":1647959741676,"user_tz":-540,"elapsed":230,"user":{"displayName":"seongsu bang","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"12261094723698722963"}}},"execution_count":11,"outputs":[]},{"cell_type":"code","source":["\n","device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n","# device = torch.device(\"cpu\")\n","\n","# Tokenize & Vocab setup\n","tokenizer = get_tokenizer('basic_english')\n","train_iter = IMDB(split='train')\n","def yield_tokens(data_iter):\n"," for _, text in data_iter:\n"," yield tokenizer(text)\n","\n","vocab = build_vocab_from_iterator(yield_tokens(train_iter), min_freq= 2, specials=[\"\", \"\"])\n","vocab.set_default_index(vocab[\"\"]) # This index will be returned when OOV token is queried.\n","\n","num_class = 2\n","vocab_size = len(vocab)\n","idx_pad = vocab.get_stoi()['']"],"metadata":{"id":"zmeuB_A-dhMm","executionInfo":{"status":"ok","timestamp":1647959017797,"user_tz":-540,"elapsed":23064,"user":{"displayName":"seongsu bang","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"12261094723698722963"}}},"execution_count":1,"outputs":[]},{"cell_type":"code","source":["# 사이즈가 작은 파일들만 가져왔습니다. 다른 모델을 써보고 싶다면, 아래 링크를 참고해서 코드를 변경해서 사용하세요.\n","# https://pytorch.org/text/stable/_modules/torchtext/vocab/vectors.html#Vectors\n","\n","if config['pre_trained'] == 'glove':\n"," pretrained_vectors = Vectors(name = 'glove.6B.300d.txt', \n"," # cache = '[my_path]',\n"," url = 'http://nlp.stanford.edu/data/glove.6B.zip')\n"," pretrained_emb = pretrained_vectors.get_vecs_by_tokens(vocab.get_itos(), lower_case_backup=True)\n","\n","elif config['pre_trained'] == 'fasttext':\n"," pretrained_vectors = Vectors(name = 'wiki.simple.vec', \n"," # cache = '[my_path]',\n"," url = 'https://dl.fbaipublicfiles.com/fasttext/vectors-wiki/wiki.simple.vec')\n"," pretrained_emb = pretrained_vectors.get_vecs_by_tokens(vocab.get_itos(), lower_case_backup=True)\n","else:\n"," pass\n"," "],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"Gn-4UlcPo2Sm","executionInfo":{"status":"ok","timestamp":1647959271331,"user_tz":-540,"elapsed":245850,"user":{"displayName":"seongsu bang","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"12261094723698722963"}},"outputId":"dd7d63e7-4ea9-474e-c80b-ddf889fe8bc7"},"execution_count":2,"outputs":[{"output_type":"stream","name":"stderr","text":[".vector_cache/glove.6B.zip: 862MB [02:40, 5.36MB/s] \n","100%|█████████▉| 399999/400000 [00:56<00:00, 7128.51it/s]\n"]}]},{"cell_type":"code","source":["config = {'pre_trained' : 'glove', # 'glove','fasttext', None \n"," 'max_length': 300,\n"," 'batch_size': 64,\n"," 'model_type': 'lstm', # 'rnn', 'lstm', 'gru','avg_not_pad', None\n"," 'emb_dim' : 300,\n"," 'hidden_dim':128,\n"," 'is_bidirectional':True,\n"," 'epoch' : 10,\n"," 'LR': 5\n"," }"],"metadata":{"id":"qEFzPiWFIIZC","executionInfo":{"status":"ok","timestamp":1647961775746,"user_tz":-540,"elapsed":325,"user":{"displayName":"seongsu bang","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"12261094723698722963"}}},"execution_count":39,"outputs":[]},{"cell_type":"code","source":["# DataLoader Setup\n","text_pipeline = lambda x: vocab(tokenizer(x))[:config['max_length']]\n","label_pipeline = lambda x: {\"neg\":0, \"pos\":1}.get(x)\n","\n","def collate_batch(batch):\n"," label_list, text_list = [], [] \n"," for (_label, _text) in batch:\n"," processed_text = torch.tensor(text_pipeline(_text), dtype=torch.int64)\n"," text_list.append(processed_text)\n"," label_list.append(label_pipeline(_label))\n"," \n"," text_list = pad_sequence(text_list, batch_first= True, padding_value= idx_pad)\n"," label_list = torch.tensor(label_list, dtype=torch.int64)\n"," return text_list.to(device), label_list.to(device)\n","\n","train_iter, test_iter = IMDB()\n","train_dataset = to_map_style_dataset(train_iter)\n","test_dataset = to_map_style_dataset(test_iter)\n","\n","num_train = int(len(train_dataset) * 0.95)\n","split_train_, split_valid_ = random_split(train_dataset, [num_train, len(train_dataset) - num_train])\n","\n","train_dataloader = DataLoader(split_train_, batch_size=config['batch_size'], shuffle=True, collate_fn=collate_batch)\n","valid_dataloader = DataLoader(split_valid_, batch_size=config['batch_size'], shuffle=True, collate_fn=collate_batch)\n","test_dataloader = DataLoader(test_dataset, batch_size=config['batch_size'], shuffle=True, collate_fn=collate_batch)\n"],"metadata":{"id":"woxfsknMdlvp","executionInfo":{"status":"ok","timestamp":1647959771286,"user_tz":-540,"elapsed":24464,"user":{"displayName":"seongsu bang","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"12261094723698722963"}}},"execution_count":12,"outputs":[]},{"cell_type":"code","source":["# Model setup\n","class TextClassificationModel(nn.Module):\n"," def __init__(self, vocab_size, num_class, **config):\n"," super(TextClassificationModel, self).__init__()\n"," self.model_type = config['model_type']\n"," self.pretrained = config['pre_trained']\n"," self.is_bidirectional = config['is_bidirectional']\n"," self.embed_dim = config['emb_dim']\n"," self.hidden_dim = config['hidden_dim']\n"," \n"," self.embedding = nn.Embedding(vocab_size, self.embed_dim,)\n"," if self.pretrained:\n"," self.embedding = nn.Embedding(vocab_size, self.embed_dim,).from_pretrained(pretrained_emb, freeze = False)\n","\n"," if self.model_type is None:\n"," self.fc = nn.Linear(self.embed_dim, num_class)\n","\n"," elif self.model_type == 'avg_not_pad':\n"," self.embedding = nn.EmbeddingBag(vocab_size, self.embed_dim, sparse=True, padding_idx = idx_pad)\n"," if self.pretrained:\n"," self.embedding = self.embedding.from_pretrained(pretrained_emb, freeze = False, sparse=True)\n"," self.fc = nn.Linear(self.embed_dim, num_class)\n","\n"," elif self.model_type in ['rnn','lstm','gru']:\n"," if self.model_type == 'rnn':\n"," self.Recurrent = nn.RNN(input_size = self.embed_dim, hidden_size = self.hidden_dim, \n"," bidirectional = self.is_bidirectional, batch_first = True)\n"," elif self.model_type == 'lstm':\n"," self.Recurrent = nn.LSTM(input_size = self.embed_dim, hidden_size = self.hidden_dim, \n"," bidirectional = self.is_bidirectional, batch_first = True)\n"," else:\n"," self.Recurrent = nn.GRU(input_size = self.embed_dim, hidden_size = self.hidden_dim, \n"," bidirectional = self.is_bidirectional, batch_first = True)\n","\n"," last_input_dim = self.hidden_dim * 2 if self.is_bidirectional else self.hidden_dim \n"," self.fc = nn.Linear(last_input_dim, num_class)\n","\n"," else:\n"," raise NameError('Select model_type in [rnn, lstm, gru, avg_not_pad]')\n","\n"," self.init_weights()\n","\n"," def init_weights(self):\n"," initrange = 0.5\n"," if self.pretrained:\n"," self.embedding.weight.data.uniform_(-initrange, initrange)\n"," self.fc.weight.data.uniform_(-initrange, initrange)\n"," self.fc.bias.data.zero_()\n","\n"," def forward(self, text):\n"," embedded = self.embedding(text)\n"," if self.model_type is None:\n"," embedded = torch.mean(embedded, dim=1)\n"," return self.fc(embedded)\n"," elif self.model_type == 'avg_not_pad':\n"," return self.fc(embedded)\n"," else:\n"," output, _ = self.Recurrent(embedded)\n"," last_output = output[:,-1,:]\n"," return self.fc(last_output)\n","\n","\n","model = TextClassificationModel(vocab_size, num_class, **config).to(device)\n","model"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"UMfu_mmiyIIW","executionInfo":{"status":"ok","timestamp":1647961777737,"user_tz":-540,"elapsed":526,"user":{"displayName":"seongsu bang","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"12261094723698722963"}},"outputId":"83accf31-ead6-4845-8fa0-8b99a915f75d"},"execution_count":40,"outputs":[{"output_type":"execute_result","data":{"text/plain":["TextClassificationModel(\n"," (embedding): Embedding(51718, 300)\n"," (Recurrent): LSTM(300, 128, batch_first=True, bidirectional=True)\n"," (fc): Linear(in_features=256, out_features=2, bias=True)\n",")"]},"metadata":{},"execution_count":40}]},{"cell_type":"code","source":["# Training Setup\n","# Hyperparameters\n","EPOCHS = config['epoch']\n","LR = config['LR'] \n","\n","total_accu = None\n","\n","criterion = torch.nn.CrossEntropyLoss()\n","optimizer = torch.optim.SGD(model.parameters(), lr=LR)\n","scheduler = torch.optim.lr_scheduler.StepLR(optimizer, 1.0, gamma=0.1)\n","\n","for epoch in range(1, EPOCHS + 1):\n"," epoch_start_time = time.time()\n","\n"," model.train()\n"," total_acc, total_count = 0, 0\n"," log_interval = 50\n"," start_time = time.time()\n","\n"," for idx, (text, label) in tqdm(enumerate(train_dataloader)):\n"," # Training\n"," optimizer.zero_grad()\n"," predicted_label = model(text)\n"," loss = criterion(predicted_label, label)\n"," loss.backward()\n"," \n"," torch.nn.utils.clip_grad_norm_(model.parameters(), 0.1)\n"," optimizer.step()\n"," total_acc += (predicted_label.argmax(1) == label).sum().item()\n"," total_count += label.size(0)\n"," if idx % log_interval == 0 and idx > 0:\n"," elapsed = time.time() - start_time\n"," print(f'| epoch {epoch:3d} | {idx:5d}/{len(train_dataloader):5d} batches | accuracy {total_acc/total_count:8.3f}') \n"," total_acc, total_count = 0, 0\n"," start_time = time.time()\n"," \n"," # Evaluation\n"," model.eval()\n"," total_acc, total_count = 0, 0\n"," with torch.no_grad():\n"," for idx, (text, label) in enumerate(valid_dataloader):\n"," predicted_label = model(text)\n"," loss = criterion(predicted_label, label)\n"," total_acc += (predicted_label.argmax(1) == label).sum().item()\n"," total_count += label.size(0)\n"," accu_val = total_acc/total_count \n"," \n"," if total_accu is not None and total_accu > accu_val:\n"," scheduler.step()\n"," else:\n"," total_accu = accu_val\n"," print('-' * 59)\n"," print(f'| end of epoch {epoch:3d} | time: {time.time() - epoch_start_time:5.2f}s | valid accuracy {accu_val:8.3f}')\n"," print('-' * 59)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"j611wMOaGFRN","executionInfo":{"status":"ok","timestamp":1647962358199,"user_tz":-540,"elapsed":579480,"user":{"displayName":"seongsu bang","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"12261094723698722963"}},"outputId":"020f6dc7-acd0-408f-c6cb-17d8e95f19c5"},"execution_count":41,"outputs":[{"output_type":"stream","name":"stderr","text":["52it [00:05, 10.12it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 1 | 50/ 372 batches | accuracy 0.493\n"]},{"output_type":"stream","name":"stderr","text":["102it [00:10, 10.07it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 1 | 100/ 372 batches | accuracy 0.500\n"]},{"output_type":"stream","name":"stderr","text":["152it [00:15, 10.05it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 1 | 150/ 372 batches | accuracy 0.503\n"]},{"output_type":"stream","name":"stderr","text":["202it [00:20, 10.10it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 1 | 200/ 372 batches | accuracy 0.503\n"]},{"output_type":"stream","name":"stderr","text":["253it [00:25, 9.93it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 1 | 250/ 372 batches | accuracy 0.505\n"]},{"output_type":"stream","name":"stderr","text":["303it [00:30, 10.15it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 1 | 300/ 372 batches | accuracy 0.500\n"]},{"output_type":"stream","name":"stderr","text":["353it [00:35, 10.07it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 1 | 350/ 372 batches | accuracy 0.510\n"]},{"output_type":"stream","name":"stderr","text":["372it [00:37, 9.91it/s]\n"]},{"output_type":"stream","name":"stdout","text":["-----------------------------------------------------------\n","| end of epoch 1 | time: 38.28s | valid accuracy 0.486\n","-----------------------------------------------------------\n"]},{"output_type":"stream","name":"stderr","text":["52it [00:05, 10.10it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 2 | 50/ 372 batches | accuracy 0.495\n"]},{"output_type":"stream","name":"stderr","text":["102it [00:10, 9.97it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 2 | 100/ 372 batches | accuracy 0.523\n"]},{"output_type":"stream","name":"stderr","text":["151it [00:14, 10.07it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 2 | 150/ 372 batches | accuracy 0.498\n"]},{"output_type":"stream","name":"stderr","text":["202it [00:20, 9.76it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 2 | 200/ 372 batches | accuracy 0.517\n"]},{"output_type":"stream","name":"stderr","text":["253it [00:25, 9.98it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 2 | 250/ 372 batches | accuracy 0.503\n"]},{"output_type":"stream","name":"stderr","text":["303it [00:30, 10.00it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 2 | 300/ 372 batches | accuracy 0.516\n"]},{"output_type":"stream","name":"stderr","text":["353it [00:35, 10.01it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 2 | 350/ 372 batches | accuracy 0.519\n"]},{"output_type":"stream","name":"stderr","text":["372it [00:37, 9.96it/s]\n"]},{"output_type":"stream","name":"stdout","text":["-----------------------------------------------------------\n","| end of epoch 2 | time: 38.11s | valid accuracy 0.498\n","-----------------------------------------------------------\n"]},{"output_type":"stream","name":"stderr","text":["53it [00:05, 10.14it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 3 | 50/ 372 batches | accuracy 0.527\n"]},{"output_type":"stream","name":"stderr","text":["102it [00:10, 10.01it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 3 | 100/ 372 batches | accuracy 0.516\n"]},{"output_type":"stream","name":"stderr","text":["152it [00:15, 9.65it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 3 | 150/ 372 batches | accuracy 0.515\n"]},{"output_type":"stream","name":"stderr","text":["202it [00:20, 9.48it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 3 | 200/ 372 batches | accuracy 0.522\n"]},{"output_type":"stream","name":"stderr","text":["253it [00:25, 10.02it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 3 | 250/ 372 batches | accuracy 0.509\n"]},{"output_type":"stream","name":"stderr","text":["302it [00:30, 9.70it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 3 | 300/ 372 batches | accuracy 0.515\n"]},{"output_type":"stream","name":"stderr","text":["352it [00:35, 9.81it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 3 | 350/ 372 batches | accuracy 0.526\n"]},{"output_type":"stream","name":"stderr","text":["372it [00:37, 9.85it/s]\n"]},{"output_type":"stream","name":"stdout","text":["-----------------------------------------------------------\n","| end of epoch 3 | time: 38.53s | valid accuracy 0.514\n","-----------------------------------------------------------\n"]},{"output_type":"stream","name":"stderr","text":["52it [00:05, 9.81it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 4 | 50/ 372 batches | accuracy 0.537\n"]},{"output_type":"stream","name":"stderr","text":["102it [00:10, 9.69it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 4 | 100/ 372 batches | accuracy 0.538\n"]},{"output_type":"stream","name":"stderr","text":["152it [00:15, 9.31it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 4 | 150/ 372 batches | accuracy 0.526\n"]},{"output_type":"stream","name":"stderr","text":["202it [00:20, 9.61it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 4 | 200/ 372 batches | accuracy 0.538\n"]},{"output_type":"stream","name":"stderr","text":["252it [00:26, 9.74it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 4 | 250/ 372 batches | accuracy 0.551\n"]},{"output_type":"stream","name":"stderr","text":["303it [00:31, 9.82it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 4 | 300/ 372 batches | accuracy 0.648\n"]},{"output_type":"stream","name":"stderr","text":["352it [00:36, 9.55it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 4 | 350/ 372 batches | accuracy 0.723\n"]},{"output_type":"stream","name":"stderr","text":["372it [00:38, 9.68it/s]\n"]},{"output_type":"stream","name":"stdout","text":["-----------------------------------------------------------\n","| end of epoch 4 | time: 39.19s | valid accuracy 0.738\n","-----------------------------------------------------------\n"]},{"output_type":"stream","name":"stderr","text":["53it [00:05, 9.92it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 5 | 50/ 372 batches | accuracy 0.776\n"]},{"output_type":"stream","name":"stderr","text":["102it [00:10, 9.81it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 5 | 100/ 372 batches | accuracy 0.803\n"]},{"output_type":"stream","name":"stderr","text":["152it [00:15, 9.50it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 5 | 150/ 372 batches | accuracy 0.810\n"]},{"output_type":"stream","name":"stderr","text":["202it [00:20, 9.75it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 5 | 200/ 372 batches | accuracy 0.814\n"]},{"output_type":"stream","name":"stderr","text":["253it [00:25, 9.97it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 5 | 250/ 372 batches | accuracy 0.821\n"]},{"output_type":"stream","name":"stderr","text":["302it [00:31, 9.55it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 5 | 300/ 372 batches | accuracy 0.817\n"]},{"output_type":"stream","name":"stderr","text":["351it [00:35, 10.11it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 5 | 350/ 372 batches | accuracy 0.832\n"]},{"output_type":"stream","name":"stderr","text":["372it [00:38, 9.77it/s]\n"]},{"output_type":"stream","name":"stdout","text":["-----------------------------------------------------------\n","| end of epoch 5 | time: 38.81s | valid accuracy 0.810\n","-----------------------------------------------------------\n"]},{"output_type":"stream","name":"stderr","text":["52it [00:05, 9.70it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 6 | 50/ 372 batches | accuracy 0.855\n"]},{"output_type":"stream","name":"stderr","text":["103it [00:10, 10.12it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 6 | 100/ 372 batches | accuracy 0.853\n"]},{"output_type":"stream","name":"stderr","text":["152it [00:15, 9.70it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 6 | 150/ 372 batches | accuracy 0.857\n"]},{"output_type":"stream","name":"stderr","text":["202it [00:20, 9.82it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 6 | 200/ 372 batches | accuracy 0.839\n"]},{"output_type":"stream","name":"stderr","text":["252it [00:25, 9.87it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 6 | 250/ 372 batches | accuracy 0.857\n"]},{"output_type":"stream","name":"stderr","text":["302it [00:30, 9.64it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 6 | 300/ 372 batches | accuracy 0.845\n"]},{"output_type":"stream","name":"stderr","text":["352it [00:36, 9.68it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 6 | 350/ 372 batches | accuracy 0.858\n"]},{"output_type":"stream","name":"stderr","text":["372it [00:38, 9.77it/s]\n"]},{"output_type":"stream","name":"stdout","text":["-----------------------------------------------------------\n","| end of epoch 6 | time: 38.83s | valid accuracy 0.822\n","-----------------------------------------------------------\n"]},{"output_type":"stream","name":"stderr","text":["52it [00:05, 9.57it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 7 | 50/ 372 batches | accuracy 0.878\n"]},{"output_type":"stream","name":"stderr","text":["102it [00:10, 9.74it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 7 | 100/ 372 batches | accuracy 0.878\n"]},{"output_type":"stream","name":"stderr","text":["152it [00:15, 9.82it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 7 | 150/ 372 batches | accuracy 0.869\n"]},{"output_type":"stream","name":"stderr","text":["202it [00:20, 9.58it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 7 | 200/ 372 batches | accuracy 0.873\n"]},{"output_type":"stream","name":"stderr","text":["252it [00:25, 9.68it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 7 | 250/ 372 batches | accuracy 0.883\n"]},{"output_type":"stream","name":"stderr","text":["302it [00:31, 9.36it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 7 | 300/ 372 batches | accuracy 0.882\n"]},{"output_type":"stream","name":"stderr","text":["352it [00:36, 9.53it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 7 | 350/ 372 batches | accuracy 0.873\n"]},{"output_type":"stream","name":"stderr","text":["372it [00:38, 9.70it/s]\n"]},{"output_type":"stream","name":"stdout","text":["-----------------------------------------------------------\n","| end of epoch 7 | time: 39.10s | valid accuracy 0.850\n","-----------------------------------------------------------\n"]},{"output_type":"stream","name":"stderr","text":["52it [00:05, 9.84it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 8 | 50/ 372 batches | accuracy 0.901\n"]},{"output_type":"stream","name":"stderr","text":["102it [00:10, 9.62it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 8 | 100/ 372 batches | accuracy 0.892\n"]},{"output_type":"stream","name":"stderr","text":["152it [00:15, 9.83it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 8 | 150/ 372 batches | accuracy 0.898\n"]},{"output_type":"stream","name":"stderr","text":["202it [00:20, 9.63it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 8 | 200/ 372 batches | accuracy 0.892\n"]},{"output_type":"stream","name":"stderr","text":["252it [00:25, 9.92it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 8 | 250/ 372 batches | accuracy 0.904\n"]},{"output_type":"stream","name":"stderr","text":["303it [00:31, 10.18it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 8 | 300/ 372 batches | accuracy 0.893\n"]},{"output_type":"stream","name":"stderr","text":["353it [00:36, 10.18it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 8 | 350/ 372 batches | accuracy 0.897\n"]},{"output_type":"stream","name":"stderr","text":["372it [00:37, 9.80it/s]\n"]},{"output_type":"stream","name":"stdout","text":["-----------------------------------------------------------\n","| end of epoch 8 | time: 38.70s | valid accuracy 0.810\n","-----------------------------------------------------------\n"]},{"output_type":"stream","name":"stderr","text":["52it [00:05, 9.78it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 9 | 50/ 372 batches | accuracy 0.926\n"]},{"output_type":"stream","name":"stderr","text":["102it [00:10, 9.66it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 9 | 100/ 372 batches | accuracy 0.927\n"]},{"output_type":"stream","name":"stderr","text":["152it [00:15, 9.81it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 9 | 150/ 372 batches | accuracy 0.932\n"]},{"output_type":"stream","name":"stderr","text":["203it [00:20, 10.08it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 9 | 200/ 372 batches | accuracy 0.924\n"]},{"output_type":"stream","name":"stderr","text":["252it [00:25, 9.86it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 9 | 250/ 372 batches | accuracy 0.934\n"]},{"output_type":"stream","name":"stderr","text":["303it [00:31, 9.93it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 9 | 300/ 372 batches | accuracy 0.937\n"]},{"output_type":"stream","name":"stderr","text":["352it [00:35, 9.70it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 9 | 350/ 372 batches | accuracy 0.935\n"]},{"output_type":"stream","name":"stderr","text":["372it [00:37, 9.79it/s]\n"]},{"output_type":"stream","name":"stdout","text":["-----------------------------------------------------------\n","| end of epoch 9 | time: 38.73s | valid accuracy 0.853\n","-----------------------------------------------------------\n"]},{"output_type":"stream","name":"stderr","text":["52it [00:05, 9.84it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 10 | 50/ 372 batches | accuracy 0.945\n"]},{"output_type":"stream","name":"stderr","text":["102it [00:10, 9.41it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 10 | 100/ 372 batches | accuracy 0.935\n"]},{"output_type":"stream","name":"stderr","text":["152it [00:15, 9.63it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 10 | 150/ 372 batches | accuracy 0.933\n"]},{"output_type":"stream","name":"stderr","text":["202it [00:20, 9.75it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 10 | 200/ 372 batches | accuracy 0.941\n"]},{"output_type":"stream","name":"stderr","text":["252it [00:25, 9.73it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 10 | 250/ 372 batches | accuracy 0.938\n"]},{"output_type":"stream","name":"stderr","text":["302it [00:31, 9.78it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 10 | 300/ 372 batches | accuracy 0.939\n"]},{"output_type":"stream","name":"stderr","text":["352it [00:36, 9.74it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 10 | 350/ 372 batches | accuracy 0.939\n"]},{"output_type":"stream","name":"stderr","text":["372it [00:38, 9.74it/s]\n"]},{"output_type":"stream","name":"stdout","text":["-----------------------------------------------------------\n","| end of epoch 10 | time: 38.95s | valid accuracy 0.857\n","-----------------------------------------------------------\n"]},{"output_type":"stream","name":"stderr","text":["52it [00:05, 9.53it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 11 | 50/ 372 batches | accuracy 0.941\n"]},{"output_type":"stream","name":"stderr","text":["102it [00:10, 9.73it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 11 | 100/ 372 batches | accuracy 0.940\n"]},{"output_type":"stream","name":"stderr","text":["152it [00:15, 9.61it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 11 | 150/ 372 batches | accuracy 0.944\n"]},{"output_type":"stream","name":"stderr","text":["202it [00:20, 9.79it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 11 | 200/ 372 batches | accuracy 0.948\n"]},{"output_type":"stream","name":"stderr","text":["252it [00:26, 9.87it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 11 | 250/ 372 batches | accuracy 0.935\n"]},{"output_type":"stream","name":"stderr","text":["302it [00:31, 9.54it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 11 | 300/ 372 batches | accuracy 0.943\n"]},{"output_type":"stream","name":"stderr","text":["352it [00:36, 9.55it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 11 | 350/ 372 batches | accuracy 0.947\n"]},{"output_type":"stream","name":"stderr","text":["372it [00:38, 9.64it/s]\n"]},{"output_type":"stream","name":"stdout","text":["-----------------------------------------------------------\n","| end of epoch 11 | time: 39.34s | valid accuracy 0.853\n","-----------------------------------------------------------\n"]},{"output_type":"stream","name":"stderr","text":["52it [00:05, 9.48it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 12 | 50/ 372 batches | accuracy 0.949\n"]},{"output_type":"stream","name":"stderr","text":["102it [00:10, 9.60it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 12 | 100/ 372 batches | accuracy 0.948\n"]},{"output_type":"stream","name":"stderr","text":["152it [00:15, 9.57it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 12 | 150/ 372 batches | accuracy 0.948\n"]},{"output_type":"stream","name":"stderr","text":["202it [00:20, 9.45it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 12 | 200/ 372 batches | accuracy 0.944\n"]},{"output_type":"stream","name":"stderr","text":["252it [00:26, 9.65it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 12 | 250/ 372 batches | accuracy 0.952\n"]},{"output_type":"stream","name":"stderr","text":["302it [00:31, 10.11it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 12 | 300/ 372 batches | accuracy 0.949\n"]},{"output_type":"stream","name":"stderr","text":["353it [00:36, 10.05it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 12 | 350/ 372 batches | accuracy 0.947\n"]},{"output_type":"stream","name":"stderr","text":["372it [00:38, 9.76it/s]\n"]},{"output_type":"stream","name":"stdout","text":["-----------------------------------------------------------\n","| end of epoch 12 | time: 38.83s | valid accuracy 0.854\n","-----------------------------------------------------------\n"]},{"output_type":"stream","name":"stderr","text":["51it [00:05, 10.17it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 13 | 50/ 372 batches | accuracy 0.942\n"]},{"output_type":"stream","name":"stderr","text":["103it [00:10, 10.08it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 13 | 100/ 372 batches | accuracy 0.949\n"]},{"output_type":"stream","name":"stderr","text":["151it [00:14, 10.04it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 13 | 150/ 372 batches | accuracy 0.952\n"]},{"output_type":"stream","name":"stderr","text":["202it [00:20, 9.68it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 13 | 200/ 372 batches | accuracy 0.943\n"]},{"output_type":"stream","name":"stderr","text":["251it [00:25, 10.03it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 13 | 250/ 372 batches | accuracy 0.955\n"]},{"output_type":"stream","name":"stderr","text":["302it [00:30, 9.61it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 13 | 300/ 372 batches | accuracy 0.957\n"]},{"output_type":"stream","name":"stderr","text":["352it [00:35, 9.82it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 13 | 350/ 372 batches | accuracy 0.945\n"]},{"output_type":"stream","name":"stderr","text":["372it [00:37, 9.96it/s]\n"]},{"output_type":"stream","name":"stdout","text":["-----------------------------------------------------------\n","| end of epoch 13 | time: 38.08s | valid accuracy 0.854\n","-----------------------------------------------------------\n"]},{"output_type":"stream","name":"stderr","text":["51it [00:05, 10.12it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 14 | 50/ 372 batches | accuracy 0.954\n"]},{"output_type":"stream","name":"stderr","text":["103it [00:10, 10.14it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 14 | 100/ 372 batches | accuracy 0.953\n"]},{"output_type":"stream","name":"stderr","text":["152it [00:15, 10.14it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 14 | 150/ 372 batches | accuracy 0.945\n"]},{"output_type":"stream","name":"stderr","text":["203it [00:20, 10.16it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 14 | 200/ 372 batches | accuracy 0.951\n"]},{"output_type":"stream","name":"stderr","text":["251it [00:24, 10.21it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 14 | 250/ 372 batches | accuracy 0.944\n"]},{"output_type":"stream","name":"stderr","text":["303it [00:30, 10.24it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 14 | 300/ 372 batches | accuracy 0.950\n"]},{"output_type":"stream","name":"stderr","text":["353it [00:35, 10.16it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 14 | 350/ 372 batches | accuracy 0.948\n"]},{"output_type":"stream","name":"stderr","text":["372it [00:36, 10.10it/s]\n"]},{"output_type":"stream","name":"stdout","text":["-----------------------------------------------------------\n","| end of epoch 14 | time: 37.58s | valid accuracy 0.854\n","-----------------------------------------------------------\n"]},{"output_type":"stream","name":"stderr","text":["53it [00:05, 10.11it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 15 | 50/ 372 batches | accuracy 0.950\n"]},{"output_type":"stream","name":"stderr","text":["102it [00:10, 9.56it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 15 | 100/ 372 batches | accuracy 0.958\n"]},{"output_type":"stream","name":"stderr","text":["153it [00:15, 9.95it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 15 | 150/ 372 batches | accuracy 0.943\n"]},{"output_type":"stream","name":"stderr","text":["202it [00:20, 9.64it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 15 | 200/ 372 batches | accuracy 0.944\n"]},{"output_type":"stream","name":"stderr","text":["251it [00:25, 10.10it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 15 | 250/ 372 batches | accuracy 0.948\n"]},{"output_type":"stream","name":"stderr","text":["303it [00:30, 9.78it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 15 | 300/ 372 batches | accuracy 0.944\n"]},{"output_type":"stream","name":"stderr","text":["353it [00:35, 10.06it/s]"]},{"output_type":"stream","name":"stdout","text":["| epoch 15 | 350/ 372 batches | accuracy 0.961\n"]},{"output_type":"stream","name":"stderr","text":["372it [00:37, 9.94it/s]\n"]},{"output_type":"stream","name":"stdout","text":["-----------------------------------------------------------\n","| end of epoch 15 | time: 38.16s | valid accuracy 0.854\n","-----------------------------------------------------------\n"]}]},{"cell_type":"code","source":["print('Checking the results of test dataset.')\n","model.eval()\n","total_acc, total_count = 0, 0\n","with torch.no_grad():\n"," for idx, (text, label) in enumerate(test_dataloader):\n"," predicted_label = model(text, )\n"," loss = criterion(predicted_label, label)\n"," total_acc += (predicted_label.argmax(1) == label).sum().item()\n"," total_count += label.size(0)\n","accu_test = total_acc/total_count\n","print('test accuracy {:8.3f}'.format(accu_test))"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"817s3toZH_dl","executionInfo":{"status":"ok","timestamp":1647962376760,"user_tz":-540,"elapsed":14116,"user":{"displayName":"seongsu bang","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"12261094723698722963"}},"outputId":"c32fe972-36e3-444e-aff9-01d787a1cb34"},"execution_count":42,"outputs":[{"output_type":"stream","name":"stdout","text":["Checking the results of test dataset.\n","test accuracy 0.853\n"]}]},{"cell_type":"code","source":["def predict(text, text_pipeline):\n"," with torch.no_grad():\n"," text = torch.tensor(text_pipeline(text))\n"," text = pad_sequence([text], batch_first=True, padding_value=idx_pad)\n"," output = model(text)\n"," return output.argmax(1).item()\n","\n","ex_text_str = \"It was very bad movie\"\n","\n","model = model.to(\"cpu\")\n","label_dict = {0:'neg', 1:'pos'}\n","print(f\"This is a {label_dict.get(predict(ex_text_str, text_pipeline))} comment\")"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"9Ehwb31w43wr","executionInfo":{"status":"ok","timestamp":1647962376761,"user_tz":-540,"elapsed":17,"user":{"displayName":"seongsu bang","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"12261094723698722963"}},"outputId":"e038ef02-3313-4f3d-9c15-4ce2bdb6083f"},"execution_count":43,"outputs":[{"output_type":"stream","name":"stdout","text":["This is a neg comment\n"]}]}]}
--------------------------------------------------------------------------------
/3-1_MNIST_MLP_Dropout.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 1,
6 | "metadata": {},
7 | "outputs": [],
8 | "source": [
9 | "''' 1. Module Import '''\n",
10 | "import numpy as np\n",
11 | "import matplotlib.pyplot as plt\n",
12 | "\n",
13 | "import torch\n",
14 | "import torch.nn as nn\n",
15 | "import torch.nn.functional as F\n",
16 | "from torchvision import transforms, datasets"
17 | ]
18 | },
19 | {
20 | "cell_type": "code",
21 | "execution_count": 2,
22 | "metadata": {},
23 | "outputs": [
24 | {
25 | "name": "stdout",
26 | "output_type": "stream",
27 | "text": [
28 | "Using PyTorch version: 1.6.0+cu101 Device: cuda\n"
29 | ]
30 | }
31 | ],
32 | "source": [
33 | "''' 2. 딥러닝 모델을 설계할 때 활용하는 장비 확인 '''\n",
34 | "if torch.cuda.is_available():\n",
35 | " DEVICE = torch.device('cuda')\n",
36 | "else:\n",
37 | " DEVICE = torch.device('cpu')\n",
38 | "print('Using PyTorch version:', torch.__version__, ' Device:', DEVICE)"
39 | ]
40 | },
41 | {
42 | "cell_type": "code",
43 | "execution_count": 3,
44 | "metadata": {},
45 | "outputs": [],
46 | "source": [
47 | "BATCH_SIZE = 32\n",
48 | "EPOCHS = 10"
49 | ]
50 | },
51 | {
52 | "cell_type": "code",
53 | "execution_count": 4,
54 | "metadata": {},
55 | "outputs": [],
56 | "source": [
57 | "''' 3. MNIST 데이터 다운로드 (Train set, Test set 분리하기) '''\n",
58 | "train_dataset = datasets.MNIST(root = \"../data/MNIST\",\n",
59 | " train = True,\n",
60 | " download = True,\n",
61 | " transform = transforms.ToTensor())\n",
62 | "\n",
63 | "test_dataset = datasets.MNIST(root = \"../data/MNIST\",\n",
64 | " train = False,\n",
65 | " transform = transforms.ToTensor())\n",
66 | "\n",
67 | "train_loader = torch.utils.data.DataLoader(dataset = train_dataset,\n",
68 | " batch_size = BATCH_SIZE,\n",
69 | " shuffle = True)\n",
70 | "\n",
71 | "test_loader = torch.utils.data.DataLoader(dataset = test_dataset,\n",
72 | " batch_size = BATCH_SIZE,\n",
73 | " shuffle = False)"
74 | ]
75 | },
76 | {
77 | "cell_type": "code",
78 | "execution_count": 5,
79 | "metadata": {},
80 | "outputs": [
81 | {
82 | "name": "stdout",
83 | "output_type": "stream",
84 | "text": [
85 | "X_train: torch.Size([32, 1, 28, 28]) type: torch.FloatTensor\n",
86 | "y_train: torch.Size([32]) type: torch.LongTensor\n"
87 | ]
88 | }
89 | ],
90 | "source": [
91 | "''' 4. 데이터 확인하기 (1) '''\n",
92 | "for (X_train, y_train) in train_loader:\n",
93 | " print('X_train:', X_train.size(), 'type:', X_train.type())\n",
94 | " print('y_train:', y_train.size(), 'type:', y_train.type())\n",
95 | " break"
96 | ]
97 | },
98 | {
99 | "cell_type": "code",
100 | "execution_count": 6,
101 | "metadata": {},
102 | "outputs": [
103 | {
104 | "data": {
105 | "image/png": "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\n",
106 | "text/plain": [
107 | ""
108 | ]
109 | },
110 | "metadata": {
111 | "needs_background": "light"
112 | },
113 | "output_type": "display_data"
114 | }
115 | ],
116 | "source": [
117 | "''' 5. 데이터 확인하기 (2) '''\n",
118 | "pltsize = 1\n",
119 | "plt.figure(figsize=(10 * pltsize, pltsize))\n",
120 | "for i in range(10):\n",
121 | " plt.subplot(1, 10, i + 1)\n",
122 | " plt.axis('off')\n",
123 | " plt.imshow(X_train[i, :, :, :].numpy().reshape(28, 28), cmap = \"gray_r\")\n",
124 | " plt.title('Class: ' + str(y_train[i].item()))"
125 | ]
126 | },
127 | {
128 | "cell_type": "code",
129 | "execution_count": 7,
130 | "metadata": {},
131 | "outputs": [],
132 | "source": [
133 | "''' 6. Multi Layer Perceptron (MLP) 모델 설계하기 '''\n",
134 | "class Net(nn.Module):\n",
135 | " def __init__(self):\n",
136 | " super(Net, self).__init__()\n",
137 | " self.fc1 = nn.Linear(28 * 28, 512)\n",
138 | " self.fc2 = nn.Linear(512, 256)\n",
139 | " self.fc3 = nn.Linear(256, 10)\n",
140 | " self.dropout_prob = 0.5\n",
141 | "\n",
142 | " def forward(self, x):\n",
143 | " x = x.view(-1, 28 * 28)\n",
144 | " x = self.fc1(x)\n",
145 | " x = F.sigmoid(x)\n",
146 | " x = F.dropout(x, training = self.training, p = self.dropout_prob)\n",
147 | " x = self.fc2(x)\n",
148 | " x = F.sigmoid(x)\n",
149 | " x = F.dropout(x, training = self.training, p = self.dropout_prob)\n",
150 | " x = self.fc3(x)\n",
151 | " x = F.log_softmax(x, dim = 1)\n",
152 | " return x"
153 | ]
154 | },
155 | {
156 | "cell_type": "code",
157 | "execution_count": 8,
158 | "metadata": {},
159 | "outputs": [
160 | {
161 | "name": "stdout",
162 | "output_type": "stream",
163 | "text": [
164 | "Net(\n",
165 | " (fc1): Linear(in_features=784, out_features=512, bias=True)\n",
166 | " (fc2): Linear(in_features=512, out_features=256, bias=True)\n",
167 | " (fc3): Linear(in_features=256, out_features=10, bias=True)\n",
168 | ")\n"
169 | ]
170 | }
171 | ],
172 | "source": [
173 | "''' 7. Optimizer, Objective Function 설정하기 '''\n",
174 | "model = Net().to(DEVICE)\n",
175 | "optimizer = torch.optim.SGD(model.parameters(), lr = 0.01, momentum = 0.5)\n",
176 | "criterion = nn.CrossEntropyLoss()\n",
177 | "\n",
178 | "print(model)"
179 | ]
180 | },
181 | {
182 | "cell_type": "code",
183 | "execution_count": 9,
184 | "metadata": {},
185 | "outputs": [],
186 | "source": [
187 | "''' 8. MLP 모델 학습을 진행하며 학습 데이터에 대한 모델 성능을 확인하는 함수 정의 '''\n",
188 | "def train(model, train_loader, optimizer, log_interval):\n",
189 | " model.train()\n",
190 | " for batch_idx, (image, label) in enumerate(train_loader):\n",
191 | " image = image.to(DEVICE)\n",
192 | " label = label.to(DEVICE)\n",
193 | " optimizer.zero_grad()\n",
194 | " output = model(image)\n",
195 | " loss = criterion(output, label)\n",
196 | " loss.backward()\n",
197 | " optimizer.step()\n",
198 | "\n",
199 | " if batch_idx % log_interval == 0:\n",
200 | " print(\"Train Epoch: {} [{}/{} ({:.0f}%)]\\tTrain Loss: {:.6f}\".format(\n",
201 | " epoch, batch_idx * len(image), \n",
202 | " len(train_loader.dataset), 100. * batch_idx / len(train_loader), \n",
203 | " loss.item()))"
204 | ]
205 | },
206 | {
207 | "cell_type": "code",
208 | "execution_count": 10,
209 | "metadata": {},
210 | "outputs": [],
211 | "source": [
212 | "''' 9. 학습되는 과정 속에서 검증 데이터에 대한 모델 성능을 확인하는 함수 정의 '''\n",
213 | "def evaluate(model, test_loader):\n",
214 | " model.eval()\n",
215 | " test_loss = 0\n",
216 | " correct = 0\n",
217 | "\n",
218 | " with torch.no_grad():\n",
219 | " for image, label in test_loader:\n",
220 | " image = image.to(DEVICE)\n",
221 | " label = label.to(DEVICE)\n",
222 | " output = model(image)\n",
223 | " test_loss += criterion(output, label).item()\n",
224 | " prediction = output.max(1, keepdim = True)[1]\n",
225 | " correct += prediction.eq(label.view_as(prediction)).sum().item()\n",
226 | " \n",
227 | " test_loss /= (len(test_loader.dataset) / BATCH_SIZE)\n",
228 | " test_accuracy = 100. * correct / len(test_loader.dataset)\n",
229 | " return test_loss, test_accuracy"
230 | ]
231 | },
232 | {
233 | "cell_type": "code",
234 | "execution_count": 11,
235 | "metadata": {},
236 | "outputs": [
237 | {
238 | "name": "stderr",
239 | "output_type": "stream",
240 | "text": [
241 | "c:\\users\\justin\\101\\lib\\site-packages\\torch\\nn\\functional.py:1625: UserWarning: nn.functional.sigmoid is deprecated. Use torch.sigmoid instead.\n",
242 | " warnings.warn(\"nn.functional.sigmoid is deprecated. Use torch.sigmoid instead.\")\n"
243 | ]
244 | },
245 | {
246 | "name": "stdout",
247 | "output_type": "stream",
248 | "text": [
249 | "Train Epoch: 1 [0/60000 (0%)]\tTrain Loss: 2.465242\n",
250 | "Train Epoch: 1 [6400/60000 (11%)]\tTrain Loss: 2.306811\n",
251 | "Train Epoch: 1 [12800/60000 (21%)]\tTrain Loss: 2.269554\n",
252 | "Train Epoch: 1 [19200/60000 (32%)]\tTrain Loss: 2.332778\n",
253 | "Train Epoch: 1 [25600/60000 (43%)]\tTrain Loss: 2.253882\n",
254 | "Train Epoch: 1 [32000/60000 (53%)]\tTrain Loss: 2.392977\n",
255 | "Train Epoch: 1 [38400/60000 (64%)]\tTrain Loss: 2.271408\n",
256 | "Train Epoch: 1 [44800/60000 (75%)]\tTrain Loss: 2.266852\n",
257 | "Train Epoch: 1 [51200/60000 (85%)]\tTrain Loss: 2.284899\n",
258 | "Train Epoch: 1 [57600/60000 (96%)]\tTrain Loss: 2.321651\n",
259 | "\n",
260 | "[EPOCH: 1], \tTest Loss: 0.0714, \tTest Accuracy: 18.03 % \n",
261 | "\n",
262 | "Train Epoch: 2 [0/60000 (0%)]\tTrain Loss: 2.262630\n",
263 | "Train Epoch: 2 [6400/60000 (11%)]\tTrain Loss: 2.257258\n",
264 | "Train Epoch: 2 [12800/60000 (21%)]\tTrain Loss: 2.291954\n",
265 | "Train Epoch: 2 [19200/60000 (32%)]\tTrain Loss: 2.280940\n",
266 | "Train Epoch: 2 [25600/60000 (43%)]\tTrain Loss: 2.270547\n",
267 | "Train Epoch: 2 [32000/60000 (53%)]\tTrain Loss: 2.244217\n",
268 | "Train Epoch: 2 [38400/60000 (64%)]\tTrain Loss: 2.277828\n",
269 | "Train Epoch: 2 [44800/60000 (75%)]\tTrain Loss: 2.204417\n",
270 | "Train Epoch: 2 [51200/60000 (85%)]\tTrain Loss: 2.264808\n",
271 | "Train Epoch: 2 [57600/60000 (96%)]\tTrain Loss: 2.091909\n",
272 | "\n",
273 | "[EPOCH: 2], \tTest Loss: 0.0646, \tTest Accuracy: 39.75 % \n",
274 | "\n",
275 | "Train Epoch: 3 [0/60000 (0%)]\tTrain Loss: 2.206783\n",
276 | "Train Epoch: 3 [6400/60000 (11%)]\tTrain Loss: 2.064043\n",
277 | "Train Epoch: 3 [12800/60000 (21%)]\tTrain Loss: 1.923739\n",
278 | "Train Epoch: 3 [19200/60000 (32%)]\tTrain Loss: 1.672903\n",
279 | "Train Epoch: 3 [25600/60000 (43%)]\tTrain Loss: 1.902599\n",
280 | "Train Epoch: 3 [32000/60000 (53%)]\tTrain Loss: 1.836077\n",
281 | "Train Epoch: 3 [38400/60000 (64%)]\tTrain Loss: 1.688588\n",
282 | "Train Epoch: 3 [44800/60000 (75%)]\tTrain Loss: 1.541492\n",
283 | "Train Epoch: 3 [51200/60000 (85%)]\tTrain Loss: 1.430701\n",
284 | "Train Epoch: 3 [57600/60000 (96%)]\tTrain Loss: 1.311218\n",
285 | "\n",
286 | "[EPOCH: 3], \tTest Loss: 0.0386, \tTest Accuracy: 61.52 % \n",
287 | "\n",
288 | "Train Epoch: 4 [0/60000 (0%)]\tTrain Loss: 1.305975\n",
289 | "Train Epoch: 4 [6400/60000 (11%)]\tTrain Loss: 1.575562\n",
290 | "Train Epoch: 4 [12800/60000 (21%)]\tTrain Loss: 1.077880\n",
291 | "Train Epoch: 4 [19200/60000 (32%)]\tTrain Loss: 1.361190\n",
292 | "Train Epoch: 4 [25600/60000 (43%)]\tTrain Loss: 1.040486\n",
293 | "Train Epoch: 4 [32000/60000 (53%)]\tTrain Loss: 1.046731\n",
294 | "Train Epoch: 4 [38400/60000 (64%)]\tTrain Loss: 0.939643\n",
295 | "Train Epoch: 4 [44800/60000 (75%)]\tTrain Loss: 1.149699\n",
296 | "Train Epoch: 4 [51200/60000 (85%)]\tTrain Loss: 1.164859\n",
297 | "Train Epoch: 4 [57600/60000 (96%)]\tTrain Loss: 0.875005\n",
298 | "\n",
299 | "[EPOCH: 4], \tTest Loss: 0.0277, \tTest Accuracy: 71.57 % \n",
300 | "\n",
301 | "Train Epoch: 5 [0/60000 (0%)]\tTrain Loss: 1.081894\n",
302 | "Train Epoch: 5 [6400/60000 (11%)]\tTrain Loss: 1.370590\n",
303 | "Train Epoch: 5 [12800/60000 (21%)]\tTrain Loss: 1.087004\n",
304 | "Train Epoch: 5 [19200/60000 (32%)]\tTrain Loss: 1.052157\n",
305 | "Train Epoch: 5 [25600/60000 (43%)]\tTrain Loss: 1.223841\n",
306 | "Train Epoch: 5 [32000/60000 (53%)]\tTrain Loss: 0.740738\n",
307 | "Train Epoch: 5 [38400/60000 (64%)]\tTrain Loss: 0.943647\n",
308 | "Train Epoch: 5 [44800/60000 (75%)]\tTrain Loss: 0.790824\n",
309 | "Train Epoch: 5 [51200/60000 (85%)]\tTrain Loss: 0.729670\n",
310 | "Train Epoch: 5 [57600/60000 (96%)]\tTrain Loss: 0.912352\n",
311 | "\n",
312 | "[EPOCH: 5], \tTest Loss: 0.0237, \tTest Accuracy: 75.84 % \n",
313 | "\n",
314 | "Train Epoch: 6 [0/60000 (0%)]\tTrain Loss: 0.933268\n",
315 | "Train Epoch: 6 [6400/60000 (11%)]\tTrain Loss: 0.947774\n",
316 | "Train Epoch: 6 [12800/60000 (21%)]\tTrain Loss: 0.760683\n",
317 | "Train Epoch: 6 [19200/60000 (32%)]\tTrain Loss: 0.668853\n",
318 | "Train Epoch: 6 [25600/60000 (43%)]\tTrain Loss: 0.722454\n",
319 | "Train Epoch: 6 [32000/60000 (53%)]\tTrain Loss: 0.677378\n",
320 | "Train Epoch: 6 [38400/60000 (64%)]\tTrain Loss: 0.445301\n",
321 | "Train Epoch: 6 [44800/60000 (75%)]\tTrain Loss: 0.844144\n",
322 | "Train Epoch: 6 [51200/60000 (85%)]\tTrain Loss: 0.728118\n",
323 | "Train Epoch: 6 [57600/60000 (96%)]\tTrain Loss: 0.880896\n",
324 | "\n",
325 | "[EPOCH: 6], \tTest Loss: 0.0206, \tTest Accuracy: 80.45 % \n",
326 | "\n",
327 | "Train Epoch: 7 [0/60000 (0%)]\tTrain Loss: 0.751742\n",
328 | "Train Epoch: 7 [6400/60000 (11%)]\tTrain Loss: 0.687919\n",
329 | "Train Epoch: 7 [12800/60000 (21%)]\tTrain Loss: 0.826463\n",
330 | "Train Epoch: 7 [19200/60000 (32%)]\tTrain Loss: 0.584632\n",
331 | "Train Epoch: 7 [25600/60000 (43%)]\tTrain Loss: 0.752852\n",
332 | "Train Epoch: 7 [32000/60000 (53%)]\tTrain Loss: 0.558399\n",
333 | "Train Epoch: 7 [38400/60000 (64%)]\tTrain Loss: 0.810356\n",
334 | "Train Epoch: 7 [44800/60000 (75%)]\tTrain Loss: 0.726763\n",
335 | "Train Epoch: 7 [51200/60000 (85%)]\tTrain Loss: 0.547987\n",
336 | "Train Epoch: 7 [57600/60000 (96%)]\tTrain Loss: 0.431549\n",
337 | "\n",
338 | "[EPOCH: 7], \tTest Loss: 0.0181, \tTest Accuracy: 82.70 % \n",
339 | "\n",
340 | "Train Epoch: 8 [0/60000 (0%)]\tTrain Loss: 0.775636\n",
341 | "Train Epoch: 8 [6400/60000 (11%)]\tTrain Loss: 0.660315\n",
342 | "Train Epoch: 8 [12800/60000 (21%)]\tTrain Loss: 0.631106\n",
343 | "Train Epoch: 8 [19200/60000 (32%)]\tTrain Loss: 0.603776\n",
344 | "Train Epoch: 8 [25600/60000 (43%)]\tTrain Loss: 0.543177\n",
345 | "Train Epoch: 8 [32000/60000 (53%)]\tTrain Loss: 0.548135\n",
346 | "Train Epoch: 8 [38400/60000 (64%)]\tTrain Loss: 0.623748\n",
347 | "Train Epoch: 8 [44800/60000 (75%)]\tTrain Loss: 0.553701\n",
348 | "Train Epoch: 8 [51200/60000 (85%)]\tTrain Loss: 0.534373\n",
349 | "Train Epoch: 8 [57600/60000 (96%)]\tTrain Loss: 0.813260\n",
350 | "\n",
351 | "[EPOCH: 8], \tTest Loss: 0.0161, \tTest Accuracy: 84.64 % \n",
352 | "\n",
353 | "Train Epoch: 9 [0/60000 (0%)]\tTrain Loss: 0.589929\n",
354 | "Train Epoch: 9 [6400/60000 (11%)]\tTrain Loss: 0.443540\n",
355 | "Train Epoch: 9 [12800/60000 (21%)]\tTrain Loss: 0.651524\n",
356 | "Train Epoch: 9 [19200/60000 (32%)]\tTrain Loss: 0.367655\n",
357 | "Train Epoch: 9 [25600/60000 (43%)]\tTrain Loss: 0.863036\n",
358 | "Train Epoch: 9 [32000/60000 (53%)]\tTrain Loss: 0.724021\n",
359 | "Train Epoch: 9 [38400/60000 (64%)]\tTrain Loss: 0.875995\n",
360 | "Train Epoch: 9 [44800/60000 (75%)]\tTrain Loss: 0.445317\n",
361 | "Train Epoch: 9 [51200/60000 (85%)]\tTrain Loss: 0.467477\n",
362 | "Train Epoch: 9 [57600/60000 (96%)]\tTrain Loss: 0.581248\n",
363 | "\n",
364 | "[EPOCH: 9], \tTest Loss: 0.0148, \tTest Accuracy: 85.65 % \n",
365 | "\n",
366 | "Train Epoch: 10 [0/60000 (0%)]\tTrain Loss: 1.041706\n",
367 | "Train Epoch: 10 [6400/60000 (11%)]\tTrain Loss: 0.749753\n",
368 | "Train Epoch: 10 [12800/60000 (21%)]\tTrain Loss: 0.646062\n",
369 | "Train Epoch: 10 [19200/60000 (32%)]\tTrain Loss: 0.527050\n",
370 | "Train Epoch: 10 [25600/60000 (43%)]\tTrain Loss: 0.660469\n",
371 | "Train Epoch: 10 [32000/60000 (53%)]\tTrain Loss: 0.509758\n",
372 | "Train Epoch: 10 [38400/60000 (64%)]\tTrain Loss: 0.559824\n",
373 | "Train Epoch: 10 [44800/60000 (75%)]\tTrain Loss: 0.527527\n",
374 | "Train Epoch: 10 [51200/60000 (85%)]\tTrain Loss: 0.475507\n",
375 | "Train Epoch: 10 [57600/60000 (96%)]\tTrain Loss: 0.651053\n",
376 | "\n",
377 | "[EPOCH: 10], \tTest Loss: 0.0139, \tTest Accuracy: 86.52 % \n",
378 | "\n"
379 | ]
380 | }
381 | ],
382 | "source": [
383 | "''' 10. MLP 학습 실행하며 Train, Test set의 Loss 및 Test set Accuracy 확인하기 '''\n",
384 | "for epoch in range(1, EPOCHS + 1):\n",
385 | " train(model, train_loader, optimizer, log_interval = 200)\n",
386 | " test_loss, test_accuracy = evaluate(model, test_loader)\n",
387 | " print(\"\\n[EPOCH: {}], \\tTest Loss: {:.4f}, \\tTest Accuracy: {:.2f} % \\n\".format(\n",
388 | " epoch, test_loss, test_accuracy))"
389 | ]
390 | },
391 | {
392 | "cell_type": "code",
393 | "execution_count": null,
394 | "metadata": {},
395 | "outputs": [],
396 | "source": []
397 | }
398 | ],
399 | "metadata": {
400 | "kernelspec": {
401 | "display_name": "Python 3",
402 | "language": "python",
403 | "name": "python3"
404 | },
405 | "language_info": {
406 | "codemirror_mode": {
407 | "name": "ipython",
408 | "version": 3
409 | },
410 | "file_extension": ".py",
411 | "mimetype": "text/x-python",
412 | "name": "python",
413 | "nbconvert_exporter": "python",
414 | "pygments_lexer": "ipython3",
415 | "version": "3.6.8"
416 | }
417 | },
418 | "nbformat": 4,
419 | "nbformat_minor": 4
420 | }
421 |
--------------------------------------------------------------------------------
/3-2_MNIST_MLP_Dropout_ReLU.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 1,
6 | "metadata": {},
7 | "outputs": [],
8 | "source": [
9 | "''' 1. Module Import '''\n",
10 | "import numpy as np\n",
11 | "import matplotlib.pyplot as plt\n",
12 | "\n",
13 | "import torch\n",
14 | "import torch.nn as nn\n",
15 | "import torch.nn.functional as F\n",
16 | "from torchvision import transforms, datasets"
17 | ]
18 | },
19 | {
20 | "cell_type": "code",
21 | "execution_count": 2,
22 | "metadata": {},
23 | "outputs": [
24 | {
25 | "name": "stdout",
26 | "output_type": "stream",
27 | "text": [
28 | "Using PyTorch version: 1.6.0+cu101 Device: cuda\n"
29 | ]
30 | }
31 | ],
32 | "source": [
33 | "''' 2. 딥러닝 모델을 설계할 때 활용하는 장비 확인 '''\n",
34 | "if torch.cuda.is_available():\n",
35 | " DEVICE = torch.device('cuda')\n",
36 | "else:\n",
37 | " DEVICE = torch.device('cpu')\n",
38 | "print('Using PyTorch version:', torch.__version__, ' Device:', DEVICE)"
39 | ]
40 | },
41 | {
42 | "cell_type": "code",
43 | "execution_count": 3,
44 | "metadata": {},
45 | "outputs": [],
46 | "source": [
47 | "BATCH_SIZE = 32\n",
48 | "EPOCHS = 10"
49 | ]
50 | },
51 | {
52 | "cell_type": "code",
53 | "execution_count": 4,
54 | "metadata": {},
55 | "outputs": [],
56 | "source": [
57 | "''' 3. MNIST 데이터 다운로드 (Train set, Test set 분리하기) '''\n",
58 | "train_dataset = datasets.MNIST(root = \"../data/MNIST\",\n",
59 | " train = True,\n",
60 | " download = True,\n",
61 | " transform = transforms.ToTensor())\n",
62 | "\n",
63 | "test_dataset = datasets.MNIST(root = \"../data/MNIST\",\n",
64 | " train = False,\n",
65 | " transform = transforms.ToTensor())\n",
66 | "\n",
67 | "train_loader = torch.utils.data.DataLoader(dataset = train_dataset,\n",
68 | " batch_size = BATCH_SIZE,\n",
69 | " shuffle = True)\n",
70 | "\n",
71 | "test_loader = torch.utils.data.DataLoader(dataset = test_dataset,\n",
72 | " batch_size = BATCH_SIZE,\n",
73 | " shuffle = False)"
74 | ]
75 | },
76 | {
77 | "cell_type": "code",
78 | "execution_count": 5,
79 | "metadata": {},
80 | "outputs": [
81 | {
82 | "name": "stdout",
83 | "output_type": "stream",
84 | "text": [
85 | "X_train: torch.Size([32, 1, 28, 28]) type: torch.FloatTensor\n",
86 | "y_train: torch.Size([32]) type: torch.LongTensor\n"
87 | ]
88 | }
89 | ],
90 | "source": [
91 | "''' 4. 데이터 확인하기 (1) '''\n",
92 | "for (X_train, y_train) in train_loader:\n",
93 | " print('X_train:', X_train.size(), 'type:', X_train.type())\n",
94 | " print('y_train:', y_train.size(), 'type:', y_train.type())\n",
95 | " break"
96 | ]
97 | },
98 | {
99 | "cell_type": "code",
100 | "execution_count": 6,
101 | "metadata": {},
102 | "outputs": [
103 | {
104 | "data": {
105 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjwAAABNCAYAAACi7r7XAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8vihELAAAACXBIWXMAAAsTAAALEwEAmpwYAABCm0lEQVR4nO29eXQb+X3g+SmAIACCAAGCJEjwvknxEEmpdd9Xq+Vud8eOz8Tj18nGSea9vNl4kp3Z3ZedeOx444zzshtfs57Yb9w+2m6723YfUrf6kNSSqFsixVO8CV7gBZIgiBuo/YOqMqmTksgmSNfnPb5ugVWF35dV9ft9f99TEEURBQUFBQUFBYX1jGq1B6CgoKCgoKCgsNIoCo+CgoKCgoLCukdReBQUFBQUFBTWPYrCo6CgoKCgoLDuURQeBQUFBQUFhXWPovAoKCgoKCgorHueWOERBOHvBUH4yXIMJlZRZFz7rHf5QJFxvbDeZVzv8oEiY6yyJIVHEITPC4JwVRAEjyAII4IgnBAEYddKD26pCILwHwRB6BUEYU4QhDZBEEoe4xoxK6MgCKcEQRgXBMEtCEKjIAjPP+Z1YlnGPkEQfLfH5hEE4eRjXCOW5dshCMJlQRBmBUG4+bjjilUZBUHIWXDvpB9REIT/+BjXikkZFyIIwt7b8n3tMc+PWRkFQagRBOGsIAgzgiAMCoLwd49xjXUt3+3rxKyM8HuxLubdXhu9giC0C4Jw6GHnPFThEQThy8D/A3wdsAE5wHeBx1p0lxtBEP4X4E+BjwGJwLPAxCNeI6ZlBP4DkCGKogn4EvATQRAyHuUCa0BGgOdEUUy8/XPkUU6MZfkEQUgG3gD+G2AG/gl4QxAEyyNeJ2ZlFEXRseDeJQJVQBR49VGuE8sySgiCoAH+X+DSY54f6zL+DPgQSAb2Av9eEISPL/Xk9S4fxL6Mvyfr4svADcAK/J/ArwRBSH3gGaIo3vcHSAI8wKcecMzfAz9Z8O9fAk5ghvmHqmLB744BrcAsMAT8ze3PU4A3gWnABZwFVA8a2+3zVMAAcPBhx65VGe8xli2AH9iynmQE+oBD6/EeMj/ZtNzxWQfwp+tFxnuM5b8Ap9bTfVxw3f/MvNL6P4GvrTcZAS+w4Y7v/98V+daGjPwerItACRAAjAs+Owv8xYPOe5iFZzugA379kOMWcgIoBtKA68BPF/zuB8Cfi6JoBCqBD25//h+BQSCVeU3y/wBEAEEQvisIwnfv811Zt38qBUEYuG2++4ogCI8SmxTrMnL7mDcFQfAzv6s8DVx9hPGuCRmBn9523Z0UBGHjI4x1Lcgn3OPflY8w3rUgI7ePE4B/B/zoEcYKa0BGQRBygT8B/usjjHEhMS8j87v6fycIgkYQhNLbY35viWNd7/JB7Mv4+7AuVgA9oijOLvis8fbn9yXuIQJYgQlRFMMPOU5GFMUfSv8vCMLfA1OCICSJojgDhIANgiA0iqI4BUzdPjQEZAC5oih2Ma+pSdf79w/4uqzb/z3CvAndDJxk/g/4P5Y45FiXUTrm2dum9ENAuSiK0aWOl7Uh4x8x/5IIzLvw3hEEoUwUxeklDDfW5bsA2AVB+BzwK+DzQCGQsNTxEvsyLmQX85PXr5Y61tusBRn/Ffg7URQ983rdI7MWZHwTeAn4G0AN/FdRFK8scbjrXT6IfRl/H9bFROYtSQuZATIfNMaHaXyTQIogCA9TjAAQBEEtCMI/CoLQLQiCm3k3BcybrQA+ybxpq18QhDOCIGy//fl/A7qAk4Ig9AiC8J+X8n2A7/Z//0kUxWlRFPuA/+/2dyyVWJdRRhTFkCiKJ4Ajj+hzjnkZRVE8L4qiTxRFryiK/zfzJs7dSzw9puUTRXGSeb/3l4FR4CjzO8rBpZx/m5iW8Q6+CLwqiqLnEc+LaRkFQXiOeRP6L5Yoz72IdRmTgbeZt2DpgGzgaUEQlqrsrnf5IMZl5PdjXfQApjs+MzHvMrs/D/GTJQFzwB8+4Ji/57YfD/gC0AbkM79TNzNvniq64xwN8NfAwD2uVwmMsQT/I/M75ACwZ8FnXwZ+/bBz14qM9xnPe8Bfr3MZ24CPr0f5mLesOoCn19s9BPTM77QOPMbfJaZlZN4V4mY+TsHJ/MLiAX67jmTcDEzd8dn/CrypyLdmZFz36yLzMTx+FsfwfMiTxPCI86ao/wv4jiAILwiCkCDM+z2fEQThn+5xivH2H3ry9h/969IvBEGIFwThj26buELMTxzR2797VhCEIkEQBOYny4j0u4eMzwv8AvjfBEEwCoKQxXwW05sPO3etyCgIQtntsehvj+uPgT3AmXUkY44gCDtvX1snCMLfMr8zOL8e5Lt9bu3tMZmAbzL/wr+zlHPXioy3+QPmzdWnHuGctSLj3zE/0dbc/nmdeRfBi+tIxo7504XPC4KgEgQhHfgMcFORb23I+PuwLoqi2AE0AP/l9prxB0A1D8sKXaK290fMB8nOMb+zeQvYcQ8tLxH4LfNmpX7mAxdFoAiIZ96UOHVb4CvArtvn/TXzJrA55s38f7fgu/878N8fMDYT8PPb3znA/E0SlqrJxrqMQDnzgcqzzLt5rgB/8KjyxbiMFcxPOHPMvzDvA5vXi3y3f/8y8y/0DPOTUdp6uocLjnkH+OrjyLZWZFxw7P/kEbO01oKMwIHb15q5Pbb/ASQo8q0pGdf1unj793nMJ/D4gFssIctXuH2igoKCgoKCgsK6RemlpaCgoKCgoLDuURQeBQUFBQUFhXWPovAoKCgoKCgorHsUhUdBQUFBQUFh3aMoPAoKCgoKCgrrnodVUVzrKVxLqf2uyBj7KDKuf/lAkXEtoMi4/uWDdSqjYuFRUFBQUFBQWPcsqU+GgoKCgoKCwsoTDodpa2vj5Zdfxu/3E41GqaqqIjs7m4MHD6JWq1d7iGuWFVd4RFEkGo0SDodRqVSo1WpUKsWwpKCgoKCgsBBRFPH7/XR0dPCDH/wAt9tNOBzm2Wefpa6ujv379ysKzxOwogqPKIoMDAzQ39/Pj3/8YzZs2MCuXbsoKirCbDav5FcrKCgoKCisGQKBALOzs7z99ttcunSJmZkZQqEQAH19fSQnJxONPkpbO4U7WXGFZ3Jykv7+fm7cuAFAZmYmdrtdUXgUFBRigmg0is/nw+VyMTY2RlZWFiaTCZ1Ox3xPQwWFlcfr9TI1NUVzczPd3d2EQiHi4uKIj4/HYDCQkJCgPI9PyIoqPNFolKamJq5fv05TUxNzc3MEAgGKioqw2+0r+dUKCgoKS8Ln89HU1MQvf/lLvv/97/MP//AP7Nu3j/LycjQazWoPT+H3BIfDQXt7Oz/60Y9wuVwAWCwWUlJSOHr0KBUVFYo76wlZMYUnEong9/tpbW2lra2NUChEUlISxcXFJCYmrtTXfiSIokgkEiEYDBIMBunu7sbj8TA3N8f09DTj4+PysWq1GrPZTF5e3qJrxMXFkZycjNFoJCkpCY1GI8c4rScikQgej4fp6WmGh4eZmZnB4XAQiUQQBIGCggLsdjtFRUXodLrVHu6aJRKJEA6H6ejoYHJyEpfLRSQSIRqN4na78fl8ZGdno9friY+PR6fTkZCQQFZWFkajEa1Wu9oirBqiKBIOhwmHw3i9Xtrb20lOTqaoqCgmFJ5QKMTc3Bwul4vp6Wna29vxeDz4fL75DtCCgNVqJTExEYvFgtVqpbS09PciXjIQCODz+XjjjTeYnJwEICMjg/z8fPLz80lKSiI+Pn6VR/lgIpEIoVCI9vZ2bty4gc/nIxwOA1BUVER1dTV1dXXk5OSs+/spvYvd3d00NTURDofRarUcOHAAg8HwxO/jiik8oVAIr9fL9evXaWxsJBqNkpGRwZYtW9a8OysajRIIBHC73bjdbt577z2Gh4dxOp10dHTQ2NgIgCAIaLVaCgsLOXr0qGyOFEURg8FAaWkp2dnZFBYWyjdzPZnRo9EowWCQsbExuru7qa+vp6uriw8++AC/348gCDz//PPs2bOHjIyMmFZ4RPH+ZSli4X6Fw2F8Ph/nz5+nubmZ1tZWQqEQoVCIvr4+xsfHOXz4MCkpKRiNRiwWCzabjb1795KTkyMr3ArQ0tICwLPPPktCQsIqj2Z+UR8dHaW9vZ2uri5+8pOfMDQ0JG+sBEFg48aNZGRkUFxcTFVVFbm5ueh0unV/T30+H2NjY3zjG9+Q79u2bds4duwYzz77LFqtFo1GExPv6P2QFO3r169TX19PIBCQf1ddXc0LL7zAtm3bMJlMqzjK5WXhfLrw3oiiiM/n48qVK3z/+9/H7/djNpuprKwkIyMjdhUejUZDYmIiX/jCF9izZw89PT0YDAbOnTtHbm4uqampK/XVK86tW7f48Y9/TH9/P+Pj4/j9fiKRiGydkaw5giDIVpvGxkZCoRDhcJhAIIAoihw/flzeaefl5ZGcnExpaSmZmZls3LgRo9EY80qA9CPJ6vV6mZub4+LFiwwODnLhwgVcLpdsdfB6vUxPTxONRhEEgdnZWebm5mIuGE+ymLS2tuJwOPj5z3/O3NzcXROn1Wrl6NGjlJWVUV1dvUqjnScSidDY2MjZs2cZHx8nHA7L98dsNjMzM4Pb7cbpdKLRaNBqtVy8eBG73c6hQ4ewWq2kp6djsVgwGo2rKstHidfrpaGhgYGBgdUeyl0Eg0Fu3LjBN7/5TVwul7zJslqt7N27V7biSIvhjRs3aGtro76+nqeffpqnnnqKrKysmLdyLIWpqSk8Hg89PT1otVoyMjI4c+YM165dW2RVv3XrFtPT0yQlJeHz+di8eXNMyi+KIsFgkPr6et58801OnTrFwMAA4XCYwsJCPvaxj3HkyBFqa2tjQvF+EmZmZhgfH+fKlSs4HA4aGxuJj4/HbrdTXl5Ofn4+NTU1eL1eXnnlFerr62ltbSUajWIymXj99deprq7myJEjTzSOFVN4VCoVGo2GoqIiDAYDkUiEmZkZBgcH8fl8K/W1Hwkul4tLly7R1dXFyMgIRUVFmEwmjEYjBoMBm80G3K3FSua6YDBIIBBgamqKUChEJBJhaGgIq9WK2+1menqa9PR01Gp1TCs8Ho+HQCBAOBxGrVaj1WpxuVy4XC4aGhro7Ozk3XffZW5uDp/PR1xcHIIgEAwG0Wg0JCQkkJCQQHx8fMztwCQ3QldXFy0tLbz//vt4PB40Gg1xcXFoNBrcbjdpaWmkpaWRmJi46gqPIAiyoibtbAESExPR6/WYTCZZ6ZbcIaFQiP7+flJTU0lPT8fr9VJQUIBOp5Pv13omGo3i9Xrp7e2V4yZihWg0yszMDAMDA5w9exa1Wo1arSY9PR2bzUZdXd0iy5zX66W1tZWJiQmcTidZWVmkpKRgsVhQqVTExf1uupcUYa/XC8zP1/Hx8YuOWW2i0SihUIhAIIDf72d0dJTp6WmamppISEjA5/PR2NjI5cuXZTlgXjGampqit7eXjIwMamtrV1GK+xMKhWTL3fnz5+nr62NmZgaNRkNKSgrbtm2juLh4zRoHotEokUiEubk5RkZG6Ovr48qVK3R2dvLhhx+i1+vJz8/H4/Hg9XrJzMzE4/Fw48YNurq65PcxHA7T3Ny8LBauFXu6pYmys7OTtrY2Tp48SVJSEmlpaUQikZX62o8EKatDEASMRiNf/vKXqayspLCw8IEmZK/Xi8/nY3Z2Fq/Xi9PpZHh4mL6+Pi5evEhPTw+NjY1kZWXR2dnJpz71Kfbu3fsRSrY0pEX15ZdfpqmpicHBQZKSkigtLaW1tZXu7m66u7tlRScxMRG73U5FRQUGg4GTJ0+Sn5/PZz/7WXbu3ElVVVXMWRQGBwe5ceMG3/3ud2lra6OqqoqUlBQyMzOpqakhOzubb3/72/T19fGzn/2M+Ph4Dh48uGquIUnB+drXvobP5yMajcoKt2QFiIuLQxRFAoEA09PTjI2N8S//8i9cv36df/qnf0Kr1WI0GnnxxRc5duwYJSUl6PX6j1yWjwpRFBkbG6Orq4sTJ04wMTGx2kNahNfr5dVXX+XGjRtoNBpeeOEF9u3bx5YtW0hKSkKr1S5SSKPRKF/4whfo7+/nww8/5MqVK7z++ut89atfZcOGDRQUFMjHBwIBZmZmePXVV4lEIlgsFp566ilKS0tXS9xFRCIR3G43N27c4OLFi7z33nvMzMwQCAQYGRkhPj4es9mMy+ViZmaGYDB41zWkUIrDhw/H5HPc39/P3/zN39Dd3U1XV5eclVVQUEBNTQ0HDx5cs/GuoijicrlwOBy89NJLtLe309jYiNfrJRgM4vf7mZ2dZXp6mra2NvR6PQ0NDQiCwOnTp5mampKv5fV6eeedd9BoNHzpS196onGtaNByIBCgo6ODtrY2xsbG0Ov1coDuWiYxMZGysjLi4+NxuVxYLBaSkpJITU194I44EAgQDAZlxUelUhGNRvF4PAiCQCAQYG5uDo/Hg8fjkWswxBo+n4+pqSlu3bpFc3Mzo6OjJCYmMjs7i8PhwOl0olKpsFgsFBcXY7PZyMzMJD8/n/j4eGZmZsjOzqampkYOmo2VYO1IJMLs7Czd3d1cuHABv99Pamoqu3btIiUlhdTUVIqKimTlZ3p6mq6uLsbGxhgYGCAjIwODwbAqY1epVPet1SG5HKVCoElJSZhMJjZv3kxcXBwtLS2yEn7z5k2MRiOpqamyRWu9Ir2PU1NTspVAssBGIhHZXbsaRCIRBgcHmZqawmAwkJ2dTVlZGXa7/b4LuOS6qaiooKmpicnJSZxOJ6mpqeTl5eF2uxkfH6e3t5fR0VEuX76MWq0mKyuLkpKSj1K8eyIlhHR3dzMyMsKZM2doamqS07QlJV6n05GRkUFKSgrhcJi5uTlCoRB+v5+ZmRmmpqbkhTWWiEQiRCIRJiYm6Ovro7u7m7GxMYLBIGq1Gr1eT1lZGYWFhSQmJq7JtVLyZLS3t9PZ2UlTUxMDAwNMTEyg0WhkZVWKWZ2cnGR6epqBgQFZXikdX7rnfr9/UWzT47JiM5m0izxx4gTNzc0Eg0Fyc3MpKChY8/7IzMxMPvWpT3H9+nV6enqIj4+X4yUeNDlqtVp5F+33+/H5fHi9XqxWK2q1mmAw+MDg2FhhYmKC5uZm6uvruXjxovz5lStXgPmFd8uWLeTl5XHgwAHKysqoqakhGo3i9/uprq4mOTmZLVu2rJYI98Xv99PZ2cl7773H9773Pfbv38/u3bv58pe/TFJSknxcKBSiqKgIt9vNuXPn6O3t5ezZsxw6dGjVFB5gycpJcnIyycnJ/OVf/iVDQ0N85zvfoaOjg0uXLvHWW29x4cIFampqMBgMi+Reb/h8Pjwej2w9WPhZIBAgFAqtWvxHOByms7OTiYkJ7HY7ZWVlD3XP6HQ6srKysFqtnDt3Tr6GXq+ntraWjo4O3n//fX71q1/R2dnJ3NwcqampbNy4kbq6uo9IsvsTiUTw+Xy8+eabNDQ08Itf/ELe+JlMJvR6PQUFBRQWFnL48GE5w7C3t5fp6WmGhoZobm5eNC/FEsFgkLm5OS5cuEBjYyNdXV0Eg0E5wcVisfD8889TXl4e0+EMD0K6h6+99hoNDQ2cPXtWzjpLTU3FbDZTWFiI2WwmIyOD06dPc/PmTfr7+0lISCAlJQWNRiNn+C7nxn/FFJ6RkRHZrSEN2Gg0kpmZGZPmxUfBZDJRUVFBamoqbrebgoICTCbTklwZ0WhUDoQ9ceIE4+PjjI2N0dPTQzQapaKigrKyMp5++mlyc3M/AmkeHa/Xy9jY2KLdk9FoxG63k5ubS2ZmJnv37sVms5GTk4PFYkGn0yGKIvHx8WzYsCEmX2ZRFJmenubdd99lYGAAu93OwYMH2bJly5p/Zu+H2WxGFEWqq6sJhUJcunRJdndcvnyZYDDIvn37Yjbbx+1209fXR2dnJyMjI1RUVJCSkkJxcTEajeaxLIeSu29ubg6TybTqAa8+n4+RkRFGRkYYHR3FarU+ULGVYl/C4TCRSASVSsXExATf/va36erqoqGhgampKSwWC8888wxZWVlUV1fHhDtLKgB58eJFOS05JSWF9PR0tm3bRnZ2NsXFxSQnJ5OdnU18fDxqtZrc3FxGR0c5ceKE/LcpLi6mpqYmpqwkXV1ddHR08Oqrr9LT00MkEiEuLo64uDgOHDhAeXk5dXV1pKWlrfZQHxnJOnf58mWam5u5fPkyDoeDaDRKcXExlZWVPPXUU7JlTqvVYjAYEEURtVpNNBolNTWVF154QXZ5vfbaa3R1dS2blXXFFB4pFVkKjlSpVCQmJpKRkfHINT+kADvJihKNRuXJbDXMzXq9ntzc3EdSSBbW7rl16xZNTU385je/YXZ2ltnZWTmIt6SkhI0bN7J161ZSUlJWUIrHR1oQJa09Li4Ok8lEcXExmzdvpry8nEOHDmGxWO55f3Jycj7qIS+JUCjE1NQUly5dYnZ2FrvdzlNPPcX27dvvucBEo1HZfSQIwqo9j0+CwWBApVJRXFyM0+lEEAS5pERzczPx8fHs2bMnJhUeKai3ra2NM2fO0NraisfjobCwELvdjsFgeKDCI72Td8YUer1e2eIjPeOrhVqtJhwOMzo6ysjICE6nU666e797IpXNkJSeaDTK5OQk77//PiMjIwwODpKamorNZuPAgQPk5+dTWVkZE+VCpPYKbW1t3Lp1C5jfTBUUFHDgwAEqKiruWRAyFAphNBpRqVQIgoAgCLJyFCsu2Wg0Sn9/P9euXeP06dM4nU5g3iqXmJjIU089xbZt2ygpKVmTdbEkC35LSwvvvvsuLS0tzMzMoNVqZWv/oUOH5JIJ0lzZ19fHxMQEPT09mM1mnnvuOTmgvrGxEafTuWyuyRV7Eq5cucIvf/lLXC4XRqORzZs3s2PHDjZt2rRkk384HCYUCjE2NsbExAS//e1vcTqdOBwOPve5z3Hw4EFsNltMafB3Eo1GmZubY3R0lPr6ehoaGjh16hTj4+NMTEyg0+mw2+0cOXKEDRs2cOzYMSwWC8nJyTHzot6J3W5nx44d/PrXv0an07FlyxY2b97Ml770JRITE0lISMBkMq2pxT8SiXDx4kUaGhq4cOECW7du5bnnniM3N/ee9yESidDQ0LCoxtT27duxWCyrMPonQ6PRUFFRwfDwMFqtVi7Cd/r0aTweD3/2Z38Wc89iMBjk6tWrXL16lR/+8IdMTk4yOztLT08PdrudwcFBNm/ezO7du+97jUgkwtmzZ7l+/fqiuKf8/HzKy8tJS0tb1WB6nU7HkSNHMJlMNDQ08Otf/5qGhgY+//nPU1JSwubNm++p9Hg8Hm7duoXf70en0/Hyyy8TiUTwer2kp6dz6NAhnnnmGUpKSqipqSEhIQG9Xh8TcXQLS3nExcURDocxGAykpaWRnZ191/soxT2+8sortLS08OqrrzI3N4dGo8Fut5OXlxcTckmWyJMnT/LGG28sCsqtrKzkwIEDPPPMM5SWlq66RfFxGRoa4oMPPuDNN9/kww8/lJ+3T3/602zbto2DBw/KLsiFa0NxcTGBQIDx8XHUajVGo5H4+HgikQhpaWlYLBZZOXxSln0WkywxLpeLoaEhgsEgBoOB9PR0UlNTlxygKrkXpCymkZERrl+/zujoKP39/dTV1VFWVobFYokphWdhd3hJWXO5XPT09HD9+nVu3rzJ0NAQgUBA/ptkZmayadMmSkpKKCgoiHntXpqUJKuGFJBcVFQkf76WkJ5Zh8PB4OAggiCQnJxMWVnZPbMkpqen5WBQt9tNcnIyKSkpWK3WNTlZqVQqzGYziYmJxMXFycG6Um+pmZkZubdULCBlmknugZ6eHoLBIKFQiNnZWURRZHx8nLm5uYdeR6oPtTB2zmazkZ2djU6nW9XFMi4ujvz8fEZHR8nIyGBubk7OdpFiIqUNhvTOSdadmZkZ/H6/bN2RApOlyr3V1dUUFBSQmpoaEwqBRFxcHDqdjuTkZMxmMxMTE7I8w8PDmEwm0tPT0ev1GI1GPB6PHFPY1taGz+fDYDCQmZkpK6yxYJ2cm5ujp6eHgYEBnE4n4XCYuLg4DAaD7FLMyMiIuWzVR8Hr9dLf3y+XDzCZTKSlpVFbW0tJScl90+sNBgPJyckkJCSg1WplF5+k9C6n5XzZFZ5gMMjU1BTT09PMzs4SjUbRarWP9HJJC9D58+f50Y9+xLVr1+SHRHJvXbp0CZVKRXZ29qoGid5JMBjE5/MxMTHB2NgYL730Eh0dHVy8eFHeRWZkZFBWVsYnP/lJampq2LZtm3xTY2nyuR/SBON2u9FoNFRVVVFYWLgmxn4vgsEgs7Oz1NfX09fXx9atW9m1axe7du2652R57tw5PvzwQxobG4lEIhw9epS6ujqSk5NXYfRPjkqlwmq1YjabF00ukmXy0qVLlJSUxESMB8wHlk9MTPDLX/6Srq6uuxQbtVotT6APQyrkJyEF3O/bt2/VFTytVsvu3buxWq3Mzc3xwQcfcO3aNb797W/LxU0rKirYuHGjXMsqEAjg8Xhkq7jL5ZJjXP7Tf/pPVFRUUFNTI9/nWNucJCUlodPpOHDgAGazmTfffJOuri76+vpoaGjAbrfz2c9+lvLycvbu3SvHJB0/fpypqSmqqqrYtGmTnL6flpYWEzIODg7y8ssv09raKqfQm0wmtmzZwoEDB3j++edX/Xl7UmZnZ2ltbcXlcqFSqSgpKaGuro5PfepTD5RNSuTJzMzEaDSu6P1aEYVnYmJC7t8TiUTQarVkZmYuKdsjHA4zOzvLzZs3uXbtGu3t7bjdbtRqNQUFBfh8Pvr7++XAvFjLahofH6erq4tr164xMDBAQ0MDk5OTiKKIzWbDarWyb98+cnJy2LRpE1lZWTFv0bkTl8tFZ2cnBoOBvLw8ysrKyMrKWu1hPTa9vb10dXVx69Yt5ubm2LFjBzab7S5lR4r5GB0dpaurC7/fT3x8vLwrWatEo1HGx8dxuVzypgKQe3FJ1pPVRipkdunSJdrb2+nr67tnsUApZmApCujCauHSd3R2dmI0GklLS5Otd6uFSqUiLS2NXbt2yRlKZ8+exefzcfLkScbGxggEAmzYsAGj0UhXVxetra289957DAwMoFar2b59O2VlZVRWVmK322PKIn4v1Go1drudiYkJ0tPTZaV0fHycUCjEu+++S3NzMzdv3qS3t5fBwUFmZmbQ6XRs2rSJjRs3UlJSsuKL51KIRqNy9titW7eYmpqSn7XExES2bdtGQUEBwKK0a8kFlpmZSUpKSky3HJIK5/b09NDT0yNvhCsrK6msrCQ+Pv6hVjbJqn4/C1cwGMTj8eB0OklKSnrsJJJln6X9fj9jY2NMTU3JOy9pArJarQ89X+q99NZbb3H58mW5KFFSUhJbt27F6XTS39+/aJKKJYaGhjh79iw/+9nP5KA7jUaDXq+nqKiIyspK/vzP/5zs7Ow1mZ4vmcibmpowmUzk5ORQW1u7JrMKJNra2jh16hQtLS0kJCRQVVVFZmbmXcdJi//Q0BDt7e0EAgG54N9atW4BsjvP6XQSCoUWxbNIMsdC6w/JXXPy5EnOnTsnp/TeiU6no6ysDJvN9sA54n4yXb9+ncnJSXJycigoKFj15IG0tDSOHDlCZWUlQ0NDjIyM0N7eziuvvEJfXx9zc3MkJyfLLWzq6+v5xS9+Ic87zzzzDLW1tdTW1q6J51QQBHJycvB6veTm5jI4OChXoJ+enqavr08upLkwcaC4uJi9e/dSWlpKeXn5KksxTyQSwel00tfXx82bNxf9zmg0cvjwYWw2G6FQiGAwKAfQ9/X18c4777Br1y55QxWriqrU+LSlpYWWlhYikQgajYatW7dSW1u7JJeiIAiyC/Jeip3k1nQ4HOTl5cWGwiMVynrttdfo7u4G5tNe09PT5WJtDyIcDnP8+HFaWlr47W9/i9frJSUlhQMHDshF3qQJLi8vj82bN8eM0uD3+3E4HNTX1/Pqq6/K/Yrsdjv5+fns2bOHjRs3UlxcTGZm5pqz6sD8/ZEKRN26dQuz2YxWq0Wv169JeSQkN2R8fDxWq5Xq6mrsdvtdx42OjnL+/HkaGhoYGhqSd99Hjx6NiaJtj4sgCHKBwVjdRcL8xOrz+ejp6aGtre2+GVQOh4O//du/RafTLXouJeVnYbxLU1MT09PTixSjgYEBPB6P3Mhx48aNKyjV0klOTkav1/Onf/qntLa28tJLLzE6Osorr7xCb28vZrOZa9euMTk5iU6n47nnnmP37t0cPHiQtLS0NaHswLxVq6amhoKCAsrKyrh06RIffPABbW1tuFwuWQGXrI6iKKLRaDAajTHnWhZFUa6sL7UXkpAK8549e5bOzk6mpqbkbCSp9MepU6dITk6mrq4Oi8WC2WyWreqxUDIB5t/LtrY2ent7CYVCFBcXU1RUxObNm+W4zgchJegkJiai1WrvaVmX7vfCMjePw7IqPFKaaEtLi2xqtlgsWK1WLBbLA5UTqeJpc3MzDQ0NdHV1kZSUJLckyMrK4oMPPpD7cCUlJS1L99TlQqqYPDY2Rm9vL36/X642nJuby/bt2ykvL4/ZlOylIFUhnp6eZmJiArVaLVeNDgaDa7ZWjaTwJCQkYDabsdlsd5lWJVdtY2Mjg4ODzM7OkpSURFJSUkxYAZ6UewWbS8HpsdJJXer9NTMzc1eg8UI8Hg9nzpy5S6Z7FQaVLFoLW3G43W6i0SgjIyMx1V9LUuBqa2vR6XS89957DA0N0dnZSTgcJiEhQa5ZItUK27dvH/n5+Wvq3RQEgdTUVKxWKzabTbaSjIyMMDMzIysOd/YqVKvVGAyGmFACJKR1QVq3Fj5/wWCQvr4+ueDn+Pj4XX0mpcK2UoFam82G1+slISFBDnI2GAyrtlGRSlg4HA5GR0cJh8OkpaVRXFxMenr6kkod6PV6eZ5ZuOla6G6WfqSEisdl2RQeKdB4fHycCxcuEAqF0Gg0HDlyhLq6uodqo21tbbS0tMi7FYDq6mo+/vGPs337dlQqFV/5ylcYGxtDq9WSkJBAYmJizOxadDodpaWlFBQUYLfbGR4eJhKJYLfbKS0tZe/evTGjnD0ufr+ftrY2HA4H09PT+Hw+pqeneemll6iurubYsWPExcXFxOL4KDidTjo6OtiyZQvl5eWkpqYuelaDwSDXrl3j7NmzfPe738Xn8y3KTltrC8q9kOJ1Fk4mWq0Ws9lMWVkZ6enpqzi63yEF2kr1ae6FVFvnTmVHkm3h83m/yVMqhhYr84uEIAgUFhaSlJTEX/zFX/Duu+/yq1/9isHBQVkhzM3N5cCBA3LszlqNL1OpVBgMBrnju+R2vVdNFikj9rXXXmPjxo0xUcVdannR0NAgezwWMjo6yr/+67/KGb33ep6lzxc2jzWZTFitVvbs2UNpaSlf/OIXVy1xp62tjY6ODn7zm9/IHetLSkrYv3//kjPOJEVeOl6qBRYIBOT4LZVKhV6vx2q1PlFw97K/CVIPLZhPMZRqyjxs4pBKgktBXbm5ueTn51NQUCBnfXk8HrRaLTk5OdjtdjmrJBZQqVRotVqys7PZtm0bp0+fZmJigvHxcfr6+rhx4wY2m43k5GRZUYtl98G9EASBuLg4rFYrpaWlcgppX18fcXFxZGRkkJubi81mWxOyRSIR/H4/U1NTTE5OysUf77QMSDVf2tvbF7lFbDYb6enpMWMBeVxEUZQbvUrmY/hdPxspc2a1UavVcg+lrKwsBgcHH1gY8EHKzIOQngOpgGGsIZn/i4uL5bizhSX4w+GwXBg01t2UD0MQBCYnJ+W1IRqNkpiYKKeuT05O4na7ZXdnU1MTKSkpRCKRmFgbpJjHhZmAEuFwWE7IiYuLIy0tTX7PNBoNBoMBr9crr6eiKMp93gYHB2lqamJ2dpaioiJycnIoKyv7SGWD+QLDDoeD2dlZBEEgLy+PnJwccnJyHsnSdmfGoNSewuv14vV65XffYrE8UfjEiqr+kmkyJSXlgS9dJBKhsbGRN954Q87fP3ToENu2bWPjxo289NJLXL9+nWAwSHZ2Nn/wB3/Ali1byM/PX8nhPzJxcXHybmR0dJSzZ8/K5bUHBwc5evSoXEnzYVVgY5G4uDiSk5PZtGmTrI17vV7effddOctJKgi5FiZav9/P8PAwg4ODDAwMyLv6O8ft8Xj4wQ9+gMvlwmazMTY2htfrpbq6mqqqqjWt7AByM0OXy7XIPx4XF4deryc1NTUmFB6pF922bdsQRZFf/epXD621I7HQnfWw5zIhIYG0tDSOHTsWsy5oqTLvrVu3SEtLk4NeYb5O1PXr13n22Wfl1gVrmUuXLvGNb3yDgYEBfD4fubm5ZGdns3PnTs6ePUtjYyMej4epqSneeOMNkpOTOXr0qNx2YrUQBIFoNMrw8LBs/bgXkgJbU1ODzWYDkPtNORwOxsbGgHlrz+TkJA6Hg46ODs6cOcPFixfp7OzkwIEDfOUrX/lI5FpIV1cXN2/exOPxYLPZOHz4MDt37qS6uvqJriv14hwbG2N8fFwOH8jNzX2idWXV3wQp/a6np0cuLJWfn8+xY8fw+/2cOHGCCxcu0NvbS0FBAXV1dRw7dkyuQxFrGAwGMjIyePrpp8nIyKCjowOPx0NLSwtzc3PU19dz5MgR8vLy2Llz55pQDCTi4+Pl3ljS39/v95OSkkJHRwenTp2Ss5t27NiByWRaxdE+nPj4eFJTU9Hr9XJw4dTUFE6nk2g0itfr5fTp07S3tzM5OYnZbGbbtm1cuHCBzs7O1R7+siGKIj6fLyZSz5fCU089RWpqKnFxcTidTnp6emQL1YNYaNm51/GSy+D555+ntraWrKysmC0E5/V66ezspKuri9HRUZKSkrBarfj9frnw64cffohKpeLYsWNYrdY1p5hL82Zrayujo6NymYDPfe5zi6zJGzZs4NVXX5WVdqn+22ojZZLpdLpF1g6VSiXHCebl5ZGfn09ZWRnZ2dny86bVaklKSsLtdssuvEgkwtzcHK2trVy7dk3OJuzr6+PMmTP84z/+Izt37qSyshKTybTiyp4oivT09NDU1EQkEiE+Pp7k5OQVS2BZjrpRq67weDweOjs7GRoawuVykZ+fj91uZ9OmTVy6dIlz587R3NzM5OQkhw8fpqKigq1bt672sO+LTqdDp9OxdetWbDYbBoOBrq4u2tvb5cwejUZDTU0NTz31lFxGfS0gmV0XpqCHQiE5MO3f/u3faGhoQK/Xs3HjxphXeDQaDWazWQ6a83g8uFwuRkZGZFfXr3/9a7l9RFJSEhs2bJDLDawXpL41d8ZGxGJhOoDS0lIyMzMJh8P09PSgVqvv6za4E8ll53Q671J4pMq3u3fvZt++fTFXhXghUqXpwcFBpqam5ABRKa5OKtQXCATYtm0bZrN5TSk8krunsbGR7u5uXC4XRUVFlJeX88ILL5CamorBYMBkMpGZmck777zD2NgYbrebQCAQEwqPFGuWkJAgW0glS2NycrLcjqa2tpZdu3aRmJj4wDhPKUZLKrYrVXofHR3F4/EwOTmJXq8nMzOThISEj0ThGR4epre3l3A4jEajISkpaVkUHqnmlvT3Wq4K/quu8AwMDPDjH/+YtrY2VCoV+fn5mM1mTpw4QX19PW+//TahUAir1cqnP/3pmKmv8DCqqqooKSlhy5Yt9PX1sWnTJk6ePMnVq1c5ceIE/f397NmzB7vdTkZGxmoP97GJi4ujoKCA6upqDh48yPT0NMePH+f5559fM60WioqK2LlzJ83NzTQ2NvLhhx/K8T0zMzPo9Xr+6q/+ikgkwq1bt5ieno5JReBxCQQCnD9/ntbWVvkztVqNzWaLyXgsnU6HRqPh0KFDBAIBPvnJT96zCei9kAIhv/Wtb/Haa68Bv4u/27p1K0ePHmXHjh1kZWXFrLID81Vtz549KwfDVlRUsGHDBiorK2lsbOSf//mf6e7uxul08uKLL2I2m2Om6vDDiEQiXLhwgaamJv7lX/5Frtz7h3/4h+zfv5/09HR5XklNTSUcDsdsWQy9Xs8LL7xAUlIS77//PvC7AHqz2czHP/5xbDYbJpNpScX5pL53OTk5mEwmmpqa+OlPf4rH46G7u5tz584hiiKf+cxnVrQUgVQI0uVy4ff7Zdd3VVXVsmSsDg4OUl9fj8vlQqPRyOVcnpQVVXhEUWRmZoaZmRkikchdN1RKMZWqM8J8gOj09DRNTU309PTIu5fMzEwKCwtjJlvkYRgMBgwGg9zLxel0cvXqVQAmJyeZmJjA5/OtejfmJ0UQBHQ6HSaTCZvNJveZipVidUshPT2dsrIyuWLr6OiovLuw2+1yrxun08nFixdly4BGo0Gj0ayJReRBSNVgPR7Pos9TUlJITk6OOfmk4HnJsijFPSyFQCCAy+ValC6rVqtJTEwkKyuLjRs3kpKSErMLKPyu6mxfXx9utxuj0UhWVhbFxcWUl5fj9/vJy8vD6XTKVX7T0tJITU2NuXt5J5IVo7e3l87OTvr7+zEYDBQVFVFYWEheXt6iyr1SccVYVU7VajUZGRmkpaWRkJAgFxf0er3Mzs7idDrlgNyEhISHJkAIgkBCQgIJCQmUlpaiUqm4evUqQ0ND9Pf3MzAwQEtLCxMTE7IFbCWQNg6BQABRFOXiwBkZGctSG29ubo7h4WG5vEt6evqyKFIrqvCEw2HOnTuHz+fjwIED8kQF81r82NgYAwMDi4qInT9/XjZhSTu23bt3s2nTJioqKmLWp34/NBoNFouFDRs2LOqkLaXZrfVUdZiXJSEhAbvdjsPhiMmWHw9iy5YtZGZmotPpcDqdeL1e4uPj0el0fPGLX6SyshKr1crp06e5desWLpdLNkvHUpGz5UStVlNTU7PkSqlrGa1WS1FREZs2beLgwYMxu3jCvEIwNjZGV1cXZ86cwWg0UlFRweHDh9m+fTsmkwmj0UgkEuGnP/0pZ86c4fjx44yOjrJhw4aYv5d+vx+32827774r96rbtWsXL774Ilu3bl1z75tarZYbRBcUFMi1nRwOB0NDQ1y4cIHDhw/z6U9/mrq6Omw226JmsA9ix44d1NXVkZeXx5kzZ/jqV7/K9evXaWtrY+vWrQSDwRV7f30+n5y8EY1GZYOE1KftSXG5XLS1teF2u9FqtezYsYPKysonvu6yKTySv9Jms7Fv3z66uroYHh7G4XCg1Wq5ePEimZmZ2O12uUT4uXPnuH79+l1Wjvj4eDIyMrBYLKSlpbFnzx4qKiruaisf60QiEYaHh+np6eGDDz6Q4w2qqqqorq4mJSUlZipFS0jm1keJ35CCXoeHhwkGg+h0ujVVjycpKQlBENi3b5+c4qpWq9FoNOTn52MymeTg8oWFrzIyMsjIyFhTz+Sd+Hw+3G63HOwJyHWuysrKKC4uXjP3cSnMzs7KQegSer2e8vJyMjIyYlrZgXlrXGtrK62trQQCAWw2G1lZWXIsmlqtxmg0UlpaisViIRKJMDAwQFpaGoFAIOZjBqVCdk6nk/Hxcdn1U1xcTGJi4l3Hu91uuSWKwWCgtLSU3NxcuZlqLKDT6cjKyuLpp5/m+vXrdHV1MTY2RjAYRBRF2tvbefPNN+nv7yc1NZXExETMZjO5ubly5/C0tLS7NsdTU1PyfCVZ0yORiJyxd6+2K8uFFJCtVqsRRZGpqSn5Ryob8DhIxW1HRkbo6uoiFAqh1+vlAPUnZVktPFIWzyc+8Qlee+01nE4nXV1deDwe3n77bWpra9FoNNy6dQuHw8G//du/MTo6etc1kpKSqKqqorS0lOrqavbs2UNWVtaam3hDoRAdHR3U19fzve99D4/Hg1qtZu/evdTV1cVUpWj4nbIjuR+XOjFGo1FmZ2fp7u7G5/NhNBrXVH8pKeUxOzt7yedIHahzcnLW3HO5EClQ2+l0MjU1BcxP0GazmZqaGiorK9e0fHcyNTXF1atXF6UJ6/V66urqHun+rxaRSETO0AmFQhiNRgoKCrBYLPIiYzKZ2LBhA8nJyYiiSH9/PxaLBa/XKy9SsUowGGRubo6RkRGcTicw33qgtLT0nnPl5OQk/f39BAIBjEYj+/bto7y8PGZckpLLv7CwkM9//vMYDAZEUcTtdstNeZubm2lpaaGwsBCLxSJXb3/66afR6/UkJCTIm66FDA8PMzY2xszMzF3lGcLh8IqGS6jVarRarazwjI6OMjw8zPDwsGwtfxykApJ9fX20trbKHpKYjeHJyMjg2WefZXR0lKmpKblD7G9+8xs++OADLBaLnBIqPagSGo2Gz33uc5SVlbF3715MJhNJSUkkJyevmUk3FArh9/u5cuUK3d3dvPzyy4yMjOB2uzGbzSQnJ7Nr1y42bNgQUynpoihy7do1eZJJT09n8+bNDz0vEongcDjo7u6mtbWVzZs3U1lZSVJS0pq5Z4+K3W5Hr9djNptjoj7Nk3Dt2jVu3rwpBx8CbN++nV27dpGTkxNzFsgnIRKJMD09TXNzMxMTE/LnGo0Gq9W6atVqHxWXy8Xk5CTRaBS73c6uXbvu6+qRdt/SggTE9DPb0NDAxYsXmZ6eRqvVYrPZsFgsd80lk5OTtLW18frrr3P27FkmJibkLKdYnHcMBgMFBQV84hOfYNu2bdTX19Pf38/Zs2eZnp5mZmYGp9PJxMQE8fHxdHZ20tDQIDcNLS4uXvQuiqJIb28v09PTckaphNTSyGKxrNj6kpycLHtizGazHIv7wx/+kEOHDrFlyxa5R9ZScbvdDA0N8fLLL3Pp0iWCwaC8ZqakpCxLPNKyKzwJCQnk5+dTXFxMSUkJMzMzciDr5OQkvb29cu+ahVqpVORMihvYsmXLqj+4oigSCATw+Xzo9XrZvHgnUgqd3++Xe001NTXR2trK1atX8fl8xMXFkZKSQn5+Prm5uWRkZKy6fAsRRZGBgQF6enoeyeoUDoflPjculwuTyURxcTF6vT5mlLnlxmAwkJycLLvu1jKDg4N0dnYuCqDPzs6muroao9G45uVbiFRbaXBwEK/XK3+uUqnkzK9YRxRF/H6/rJzqdLqHZkMGAgF5HltJN8dyMDY2Jj+PUoDundYaqWbWrVu3aGpqorGxkUAgQFJSUsxaluPi4khKSqKkpISsrCxEUSQtLY3h4WG5In8wGCQcDsv3d2pqSg4KHhwcvOvvMDQ0hNfrlV3wWq1WTiAxm833dAEuF1qtlvj4eDmxQepmf/36dXJyckhPTycuLk6+fw9bC6TEieHhYW7cuMHAwACCIGCxWOTyLsuR8btis9knPvEJjhw5woULF5iYmGBsbGxRcz6Xy8XLL78sZ7xkZWWRl5fHgQMH5Ojz1URSyOrr6zl+/DjHjh2jqKiIvLy8RS+UKIpMTk7idDp59913uXnzJpcuXZK7+iYkJGCz2cjMzOTTn/40+/fvJy8vL6Z2WZIr68qVK9y4cYNt27YtsrzdD8nf+otf/IKbN28CUF5ezuHDh9dccPmjoNPpMBqNq17J9UkRRZGmpibOnz9PMBiUS9xLDVTXggKwVKSy/GNjY1y4cGFJKexrgdHRUa5cuSLHPN4Lo9EoL4Kx3vNN2jRKfd3m5uYWzUWiKOLxeLh16xY/+clP6OrqkpU/jUYjp3jHKlIRwv3797Nz506ee+45gsGg7BWQ3FRSTM65c+e4efMmDofjLqVB6n8HYLVaqa6uZv/+/dTV1bFp0yZMJtOKbjoFQeDgwYNYrVa+//3vMzMzw+XLl+nr6+OnP/0pL774olyaRapPdy8kY8E777xDY2MjZ86cIRqNYjKZ+JM/+RN27dq1bOvJiik8UuBSSUkJ6enpi7oOezweJiYmqK+vl11f6enpVFRUYDabY6J2i9QMdWxsjKamJsrLy9Hr9bKlB+ZT5+bm5ujo6GB4eJirV6/S3d3N8PAwoiii0WjYsGED6enplJaWsmHDBjIyMmIqoE5CUvAk86rX65Vjee4cq/SCSj5bqTZNfn6+XABtPVkG7mQ5C2GtFlKHeJfLJfcokiwdkht5LStz90JKrNDpdPh8PrnibWZmplzILtaR2vXYbDbUarXsShgfHyclJQWdTofH42FgYAC32y13Tpd6+MVKbMv9sFgsZGZmEh8fj8fjYW5uDofDwcWLF7FarcTFxdHb28uNGzcYHBzE4/EgiqL83BYUFGC1WldbjAcivWeSlSQSiRAOh/F6vaSlpTE9PS0rMlqtloKCgode02w2U1RURE1NDUVFRRgMho9kDs7LyyMajbJjxw4cDgdNTU3MzMwQCAS4fPkyo6OjzMzMyD01FxZXjEajhEIhOdj52rVrsnUvJSWFvLw8CgsLyc7OXra5aMX+IlKRpHulkgWDQSYmJmhqaqKlpYXz589TW1vL888/v6R28h8F0o5Q8rPm5ubi8/nweDzyg9Td3Y3D4eD48eM4nU5cLpf8oKalpZGens4f//EfU1ZWxvbt22N2gZRccrOzs7hcLoaGhsjMzCQQCBAfH3/Xi+N2uxkeHubEiRO0tLRw9uxZufdQeXl5TDV1XQlitQLxozA7O8vQ0BBDQ0Oy9VXqji6lmK4npJIYRqOR3NxchoeHmZ6e5qmnnqK2tpaqqqqYsrreD7VazcaNG4lEIrz99ts4nU7OnTvHpk2bSExMxG63Mzg4yHvvvSe7BSTruc1mi4nN5IMoLi4mGo1y/PhxxsbGcLlcnDp1irGxMTZv3ozRaOStt95iaGiIrq4uYP7ems1msrKyOHDgwJq4j/C7gGaJWO4gcD9qa2uprKykqKiIDz/8kK997WvMzs7idrv58Y9/THx8PFarlby8PMrKyigqKpLX+EAgwMzMDDdv3qS7u1tWdlQqFWVlZXz84x+npqaGrKysZRvvqmzDJX/mZz/7WVwuF5/5zGeoqqqisLAwJh/WaDTKpUuX6OnpWVSifWZmRk6hCwQCcvGywsJCNm7cSFZWFlu2bHlo89TVRlrApbYRTU1NjI2N4XQ65awOKWBOSmOempqip6eHmZkZcnJyqKqq4mMf+xj5+fmr7o5cKaTg1ljfJS8Fh8PBqVOnmJiYkF3NiYmJlJSU3Nc1staRFJ6ioiLm5uZwu93k5+dTUFAQs7Efd6JSqaiurkar1bJ7926cTieDg4P8/Oc/5/Tp01gsFqanp+no6MDhcGAwGPjYxz62bPVRVpq0tDSi0SglJSWEw2EGBgZwuVy0tLQwPj5OfHw8fX19eDweVCoVBoOBxMREPvvZz7Jx48Z1bVmOVdRqNZmZmWzbto2//uu/prm5WU5ikdaL3t5epqamaGtrk9f4SCRCIBBgYmICt9st9zbcsWMHW7ZsYf/+/ctSbHAhq/J0SA/q/v37V+Prl4xkApei5u/VQ0lK39ZqtSQnJ1NcXMyuXbvYu3cvOTk5a6Zpn2QqT0tLo7m5WS4IKf0NjEYjgiAwOzsrB0BKJd23b99ORUUF27dvX3LRrLVIfHy8nDGylgor3gun08mVK1cWZXdICQexHAPxJKhUKhITE8nLy2NwcJDJyUlycnLIyspaMxWzBUEgPz8fjUZDXV0dly9fpr29nVOnTskbk1AohNvtJiEhAbPZzI4dO6iurl4TCk9SUpJc8kHqli25zx0Oh2xBV6lU8vtos9k4cuQI5eXla0LG9YZKpSIlJQW9Xi9nVCUmJuJ0OpmcnCQUCuFyuRZlRi68j4C84c7MzOTgwYNUV1dTU1Oz7GMVHjJxr+1ZHZYyg91TRqnE+blz53j99dd566236OnpWXRMdnY26enpVFdXy+ZUq9WK1WolMTHxnu6gFeCxZVx0wO1aCi6Xi3PnzjE4OEhzczPBYJBAIEBzczMAGzZskIMgc3Nz5cKQVqtVzjxbgYVjWWR8UoaGhjh37hwXL16kp6eHb37zmxQVFS2XvA+7yLLIF4lEcLvdvPLKK3zrW99iYGBALji4Z88evv71r1NQULASLVxi4h76/X4mJyfxeDz4/X65FP4yZbR8ZDIGAgEcDgfnz5/n+PHjXLhwgeHhYdRqNQaDAZvNxnPPPcfu3bvZuXMnSUlJyzUXraiM0rx78uRJhoaGuHXrlpxUcfLkSRwOB16vl9zcXA4fPsz+/fupra3Fbrff1ZX8CfhI3sVVZEXuoRSTMzs7y9zcHJ2dnUxNTdHf34/D4aCzsxOYn4MmJyeJj4+XA6s1Gg3PP/88+fn5VFdXYzAYnrQkxj1lVOx/90Hy+aenp1NXV8fIyMhdtS4yMzNlhSczM1OOA1iLLg9BEOSaFx6PR+4UHQgE5CwIQRCoqKiQMz7y8vJITU2luLhYLkK1njEYDBQWFtLS0iIHGkYikTVnRhcEQQ7wtFgschZMVVUVubm56z7DbjkKmK02Go2GzMxMSkpKGB0dJRAIyEpqYmIiGRkZcmzSWiovIM270nMoFeqD+fpDqamp+Hw+srOzqauro6qqirKyslUetQL8rgmvVqvFarWi0+mYnZ3FarUuqqMTiUTkpqDSZxqNhurqaux2+4qGgCgWnofIKFUeXpgCKCFZM6T/rtKCv+zaupQSKsm78P8XWnAWyr/CxIR1QNrBfOc73+Htt9/m61//OiUlJcvlAvpId5VSCXpAXlCkdhorNNnExD1cYT5yGaWEA6m2GfwuJk+tVqNWq5f7fn4kMkqyLJxzpbYuoijKoQQrIB8oFh5YBhmleUVaPxb+e9Fgbt8/6V6upMV8baj9q4i041grO6TlQFJg1rvF5lFRqVRoNBo2bdok11eK9ayX+yEtFgprG5VKtSZiBB8VSaaFsv0+zcHrAUlx+Yg2xUtCsfAoMq4FFBnXv3ygyLgWUGRc//LBOpUxNtQuBQUFBQUFBYUVRFF4FBQUFBQUFNY9D3NpKSgoKCgoKCiseRQLj4KCgoKCgsK6R1F4FBQUFBQUFNY9isKjoKCgoKCgsO5RFB4FBQUFBQWFdY+i8CgoKCgoKCisexSFR0FBQUFBQWHd8/8DJ+Rvysvqu/kAAAAASUVORK5CYII=\n",
106 | "text/plain": [
107 | ""
108 | ]
109 | },
110 | "metadata": {
111 | "needs_background": "light"
112 | },
113 | "output_type": "display_data"
114 | }
115 | ],
116 | "source": [
117 | "''' 5. 데이터 확인하기 (2) '''\n",
118 | "pltsize = 1\n",
119 | "plt.figure(figsize=(10 * pltsize, pltsize))\n",
120 | "for i in range(10):\n",
121 | " plt.subplot(1, 10, i + 1)\n",
122 | " plt.axis('off')\n",
123 | " plt.imshow(X_train[i, :, :, :].numpy().reshape(28, 28), cmap = \"gray_r\")\n",
124 | " plt.title('Class: ' + str(y_train[i].item()))"
125 | ]
126 | },
127 | {
128 | "cell_type": "code",
129 | "execution_count": 7,
130 | "metadata": {},
131 | "outputs": [],
132 | "source": [
133 | "''' 6. Multi Layer Perceptron (MLP) 모델 설계하기 '''\n",
134 | "class Net(nn.Module):\n",
135 | " def __init__(self):\n",
136 | " super(Net, self).__init__()\n",
137 | " self.fc1 = nn.Linear(28 * 28, 512)\n",
138 | " self.fc2 = nn.Linear(512, 256)\n",
139 | " self.fc3 = nn.Linear(256, 10)\n",
140 | " self.dropout_prob = 0.5\n",
141 | "\n",
142 | " def forward(self, x):\n",
143 | " x = x.view(-1, 28 * 28)\n",
144 | " x = self.fc1(x)\n",
145 | " x = F.relu(x)\n",
146 | " x = F.dropout(x, training = self.training, p = self.dropout_prob)\n",
147 | " x = self.fc2(x)\n",
148 | " x = F.relu(x)\n",
149 | " x = F.dropout(x, training = self.training, p = self.dropout_prob)\n",
150 | " x = self.fc3(x)\n",
151 | " x = F.log_softmax(x, dim = 1)\n",
152 | " return x"
153 | ]
154 | },
155 | {
156 | "cell_type": "code",
157 | "execution_count": 8,
158 | "metadata": {},
159 | "outputs": [
160 | {
161 | "name": "stdout",
162 | "output_type": "stream",
163 | "text": [
164 | "Net(\n",
165 | " (fc1): Linear(in_features=784, out_features=512, bias=True)\n",
166 | " (fc2): Linear(in_features=512, out_features=256, bias=True)\n",
167 | " (fc3): Linear(in_features=256, out_features=10, bias=True)\n",
168 | ")\n"
169 | ]
170 | }
171 | ],
172 | "source": [
173 | "''' 7. Optimizer, Objective Function 설정하기 '''\n",
174 | "model = Net().to(DEVICE)\n",
175 | "optimizer = torch.optim.SGD(model.parameters(), lr = 0.01, momentum = 0.5)\n",
176 | "criterion = nn.CrossEntropyLoss()\n",
177 | "\n",
178 | "print(model)"
179 | ]
180 | },
181 | {
182 | "cell_type": "code",
183 | "execution_count": 9,
184 | "metadata": {},
185 | "outputs": [],
186 | "source": [
187 | "''' 8. MLP 모델 학습을 진행하며 학습 데이터에 대한 모델 성능을 확인하는 함수 정의 '''\n",
188 | "def train(model, train_loader, optimizer, log_interval):\n",
189 | " model.train()\n",
190 | " for batch_idx, (image, label) in enumerate(train_loader):\n",
191 | " image = image.to(DEVICE)\n",
192 | " label = label.to(DEVICE)\n",
193 | " optimizer.zero_grad()\n",
194 | " output = model(image)\n",
195 | " loss = criterion(output, label)\n",
196 | " loss.backward()\n",
197 | " optimizer.step()\n",
198 | "\n",
199 | " if batch_idx % log_interval == 0:\n",
200 | " print(\"Train Epoch: {} [{}/{} ({:.0f}%)]\\tTrain Loss: {:.6f}\".format(\n",
201 | " epoch, batch_idx * len(image), \n",
202 | " len(train_loader.dataset), 100. * batch_idx / len(train_loader), \n",
203 | " loss.item()))"
204 | ]
205 | },
206 | {
207 | "cell_type": "code",
208 | "execution_count": 10,
209 | "metadata": {},
210 | "outputs": [],
211 | "source": [
212 | "''' 9. 학습되는 과정 속에서 검증 데이터에 대한 모델 성능을 확인하는 함수 정의 '''\n",
213 | "def evaluate(model, test_loader):\n",
214 | " model.eval()\n",
215 | " test_loss = 0\n",
216 | " correct = 0\n",
217 | "\n",
218 | " with torch.no_grad():\n",
219 | " for image, label in test_loader:\n",
220 | " image = image.to(DEVICE)\n",
221 | " label = label.to(DEVICE)\n",
222 | " output = model(image)\n",
223 | " test_loss += criterion(output, label).item()\n",
224 | " prediction = output.max(1, keepdim = True)[1]\n",
225 | " correct += prediction.eq(label.view_as(prediction)).sum().item()\n",
226 | " \n",
227 | " test_loss /= (len(test_loader.dataset) / BATCH_SIZE)\n",
228 | " test_accuracy = 100. * correct / len(test_loader.dataset)\n",
229 | " return test_loss, test_accuracy"
230 | ]
231 | },
232 | {
233 | "cell_type": "code",
234 | "execution_count": 11,
235 | "metadata": {},
236 | "outputs": [
237 | {
238 | "name": "stdout",
239 | "output_type": "stream",
240 | "text": [
241 | "Train Epoch: 1 [0/60000 (0%)]\tTrain Loss: 2.293252\n",
242 | "Train Epoch: 1 [6400/60000 (11%)]\tTrain Loss: 2.103498\n",
243 | "Train Epoch: 1 [12800/60000 (21%)]\tTrain Loss: 1.014423\n",
244 | "Train Epoch: 1 [19200/60000 (32%)]\tTrain Loss: 0.739293\n",
245 | "Train Epoch: 1 [25600/60000 (43%)]\tTrain Loss: 0.824886\n",
246 | "Train Epoch: 1 [32000/60000 (53%)]\tTrain Loss: 0.373551\n",
247 | "Train Epoch: 1 [38400/60000 (64%)]\tTrain Loss: 0.590951\n",
248 | "Train Epoch: 1 [44800/60000 (75%)]\tTrain Loss: 0.609839\n",
249 | "Train Epoch: 1 [51200/60000 (85%)]\tTrain Loss: 0.725992\n",
250 | "Train Epoch: 1 [57600/60000 (96%)]\tTrain Loss: 0.316456\n",
251 | "\n",
252 | "[EPOCH: 1], \tTest Loss: 0.0099, \tTest Accuracy: 91.00 % \n",
253 | "\n",
254 | "Train Epoch: 2 [0/60000 (0%)]\tTrain Loss: 0.434049\n",
255 | "Train Epoch: 2 [6400/60000 (11%)]\tTrain Loss: 0.423664\n",
256 | "Train Epoch: 2 [12800/60000 (21%)]\tTrain Loss: 0.223913\n",
257 | "Train Epoch: 2 [19200/60000 (32%)]\tTrain Loss: 0.185579\n",
258 | "Train Epoch: 2 [25600/60000 (43%)]\tTrain Loss: 0.516311\n",
259 | "Train Epoch: 2 [32000/60000 (53%)]\tTrain Loss: 0.170941\n",
260 | "Train Epoch: 2 [38400/60000 (64%)]\tTrain Loss: 0.679857\n",
261 | "Train Epoch: 2 [44800/60000 (75%)]\tTrain Loss: 0.206488\n",
262 | "Train Epoch: 2 [51200/60000 (85%)]\tTrain Loss: 0.293542\n",
263 | "Train Epoch: 2 [57600/60000 (96%)]\tTrain Loss: 0.532575\n",
264 | "\n",
265 | "[EPOCH: 2], \tTest Loss: 0.0070, \tTest Accuracy: 93.47 % \n",
266 | "\n",
267 | "Train Epoch: 3 [0/60000 (0%)]\tTrain Loss: 0.494590\n",
268 | "Train Epoch: 3 [6400/60000 (11%)]\tTrain Loss: 0.692674\n",
269 | "Train Epoch: 3 [12800/60000 (21%)]\tTrain Loss: 0.141787\n",
270 | "Train Epoch: 3 [19200/60000 (32%)]\tTrain Loss: 0.254909\n",
271 | "Train Epoch: 3 [25600/60000 (43%)]\tTrain Loss: 0.143211\n",
272 | "Train Epoch: 3 [32000/60000 (53%)]\tTrain Loss: 0.290160\n",
273 | "Train Epoch: 3 [38400/60000 (64%)]\tTrain Loss: 0.370776\n",
274 | "Train Epoch: 3 [44800/60000 (75%)]\tTrain Loss: 0.711377\n",
275 | "Train Epoch: 3 [51200/60000 (85%)]\tTrain Loss: 0.091218\n",
276 | "Train Epoch: 3 [57600/60000 (96%)]\tTrain Loss: 0.176025\n",
277 | "\n",
278 | "[EPOCH: 3], \tTest Loss: 0.0054, \tTest Accuracy: 94.96 % \n",
279 | "\n",
280 | "Train Epoch: 4 [0/60000 (0%)]\tTrain Loss: 0.298294\n",
281 | "Train Epoch: 4 [6400/60000 (11%)]\tTrain Loss: 0.155041\n",
282 | "Train Epoch: 4 [12800/60000 (21%)]\tTrain Loss: 0.358912\n",
283 | "Train Epoch: 4 [19200/60000 (32%)]\tTrain Loss: 0.178691\n",
284 | "Train Epoch: 4 [25600/60000 (43%)]\tTrain Loss: 0.085475\n",
285 | "Train Epoch: 4 [32000/60000 (53%)]\tTrain Loss: 0.272500\n",
286 | "Train Epoch: 4 [38400/60000 (64%)]\tTrain Loss: 0.203928\n",
287 | "Train Epoch: 4 [44800/60000 (75%)]\tTrain Loss: 0.455426\n",
288 | "Train Epoch: 4 [51200/60000 (85%)]\tTrain Loss: 0.123246\n",
289 | "Train Epoch: 4 [57600/60000 (96%)]\tTrain Loss: 0.114354\n",
290 | "\n",
291 | "[EPOCH: 4], \tTest Loss: 0.0044, \tTest Accuracy: 95.63 % \n",
292 | "\n",
293 | "Train Epoch: 5 [0/60000 (0%)]\tTrain Loss: 0.124653\n",
294 | "Train Epoch: 5 [6400/60000 (11%)]\tTrain Loss: 0.157264\n",
295 | "Train Epoch: 5 [12800/60000 (21%)]\tTrain Loss: 0.202116\n",
296 | "Train Epoch: 5 [19200/60000 (32%)]\tTrain Loss: 0.063491\n",
297 | "Train Epoch: 5 [25600/60000 (43%)]\tTrain Loss: 0.215543\n",
298 | "Train Epoch: 5 [32000/60000 (53%)]\tTrain Loss: 0.039489\n",
299 | "Train Epoch: 5 [38400/60000 (64%)]\tTrain Loss: 0.062817\n",
300 | "Train Epoch: 5 [44800/60000 (75%)]\tTrain Loss: 0.074638\n",
301 | "Train Epoch: 5 [51200/60000 (85%)]\tTrain Loss: 0.100656\n",
302 | "Train Epoch: 5 [57600/60000 (96%)]\tTrain Loss: 0.263398\n",
303 | "\n",
304 | "[EPOCH: 5], \tTest Loss: 0.0038, \tTest Accuracy: 96.28 % \n",
305 | "\n",
306 | "Train Epoch: 6 [0/60000 (0%)]\tTrain Loss: 0.243492\n",
307 | "Train Epoch: 6 [6400/60000 (11%)]\tTrain Loss: 0.134330\n",
308 | "Train Epoch: 6 [12800/60000 (21%)]\tTrain Loss: 0.132107\n",
309 | "Train Epoch: 6 [19200/60000 (32%)]\tTrain Loss: 0.210380\n",
310 | "Train Epoch: 6 [25600/60000 (43%)]\tTrain Loss: 0.166309\n",
311 | "Train Epoch: 6 [32000/60000 (53%)]\tTrain Loss: 0.154378\n",
312 | "Train Epoch: 6 [38400/60000 (64%)]\tTrain Loss: 0.415324\n",
313 | "Train Epoch: 6 [44800/60000 (75%)]\tTrain Loss: 0.091827\n",
314 | "Train Epoch: 6 [51200/60000 (85%)]\tTrain Loss: 0.088081\n",
315 | "Train Epoch: 6 [57600/60000 (96%)]\tTrain Loss: 0.156756\n",
316 | "\n",
317 | "[EPOCH: 6], \tTest Loss: 0.0035, \tTest Accuracy: 96.58 % \n",
318 | "\n",
319 | "Train Epoch: 7 [0/60000 (0%)]\tTrain Loss: 0.311500\n",
320 | "Train Epoch: 7 [6400/60000 (11%)]\tTrain Loss: 0.153611\n",
321 | "Train Epoch: 7 [12800/60000 (21%)]\tTrain Loss: 0.182327\n",
322 | "Train Epoch: 7 [19200/60000 (32%)]\tTrain Loss: 0.109722\n",
323 | "Train Epoch: 7 [25600/60000 (43%)]\tTrain Loss: 0.357384\n",
324 | "Train Epoch: 7 [32000/60000 (53%)]\tTrain Loss: 0.124124\n",
325 | "Train Epoch: 7 [38400/60000 (64%)]\tTrain Loss: 0.139059\n",
326 | "Train Epoch: 7 [44800/60000 (75%)]\tTrain Loss: 0.094896\n",
327 | "Train Epoch: 7 [51200/60000 (85%)]\tTrain Loss: 0.069713\n",
328 | "Train Epoch: 7 [57600/60000 (96%)]\tTrain Loss: 0.060162\n",
329 | "\n",
330 | "[EPOCH: 7], \tTest Loss: 0.0031, \tTest Accuracy: 97.02 % \n",
331 | "\n",
332 | "Train Epoch: 8 [0/60000 (0%)]\tTrain Loss: 0.219568\n",
333 | "Train Epoch: 8 [6400/60000 (11%)]\tTrain Loss: 0.265314\n",
334 | "Train Epoch: 8 [12800/60000 (21%)]\tTrain Loss: 0.136442\n",
335 | "Train Epoch: 8 [19200/60000 (32%)]\tTrain Loss: 0.182477\n",
336 | "Train Epoch: 8 [25600/60000 (43%)]\tTrain Loss: 0.057788\n",
337 | "Train Epoch: 8 [32000/60000 (53%)]\tTrain Loss: 0.180467\n",
338 | "Train Epoch: 8 [38400/60000 (64%)]\tTrain Loss: 0.163830\n",
339 | "Train Epoch: 8 [44800/60000 (75%)]\tTrain Loss: 0.146127\n",
340 | "Train Epoch: 8 [51200/60000 (85%)]\tTrain Loss: 0.078550\n",
341 | "Train Epoch: 8 [57600/60000 (96%)]\tTrain Loss: 0.366327\n",
342 | "\n",
343 | "[EPOCH: 8], \tTest Loss: 0.0028, \tTest Accuracy: 97.16 % \n",
344 | "\n",
345 | "Train Epoch: 9 [0/60000 (0%)]\tTrain Loss: 0.032364\n",
346 | "Train Epoch: 9 [6400/60000 (11%)]\tTrain Loss: 0.049485\n",
347 | "Train Epoch: 9 [12800/60000 (21%)]\tTrain Loss: 0.083032\n",
348 | "Train Epoch: 9 [19200/60000 (32%)]\tTrain Loss: 0.120306\n",
349 | "Train Epoch: 9 [25600/60000 (43%)]\tTrain Loss: 0.236849\n",
350 | "Train Epoch: 9 [32000/60000 (53%)]\tTrain Loss: 0.034962\n",
351 | "Train Epoch: 9 [38400/60000 (64%)]\tTrain Loss: 0.355975\n",
352 | "Train Epoch: 9 [44800/60000 (75%)]\tTrain Loss: 0.098553\n",
353 | "Train Epoch: 9 [51200/60000 (85%)]\tTrain Loss: 0.739664\n",
354 | "Train Epoch: 9 [57600/60000 (96%)]\tTrain Loss: 0.029625\n",
355 | "\n",
356 | "[EPOCH: 9], \tTest Loss: 0.0027, \tTest Accuracy: 97.21 % \n",
357 | "\n",
358 | "Train Epoch: 10 [0/60000 (0%)]\tTrain Loss: 0.316167\n",
359 | "Train Epoch: 10 [6400/60000 (11%)]\tTrain Loss: 0.184830\n",
360 | "Train Epoch: 10 [12800/60000 (21%)]\tTrain Loss: 0.160652\n",
361 | "Train Epoch: 10 [19200/60000 (32%)]\tTrain Loss: 0.162540\n",
362 | "Train Epoch: 10 [25600/60000 (43%)]\tTrain Loss: 0.044575\n",
363 | "Train Epoch: 10 [32000/60000 (53%)]\tTrain Loss: 0.090206\n",
364 | "Train Epoch: 10 [38400/60000 (64%)]\tTrain Loss: 0.021095\n",
365 | "Train Epoch: 10 [44800/60000 (75%)]\tTrain Loss: 0.275242\n",
366 | "Train Epoch: 10 [51200/60000 (85%)]\tTrain Loss: 0.117553\n",
367 | "Train Epoch: 10 [57600/60000 (96%)]\tTrain Loss: 0.028020\n",
368 | "\n",
369 | "[EPOCH: 10], \tTest Loss: 0.0026, \tTest Accuracy: 97.40 % \n",
370 | "\n"
371 | ]
372 | }
373 | ],
374 | "source": [
375 | "''' 10. MLP 학습 실행하며 Train, Test set의 Loss 및 Test set Accuracy 확인하기 '''\n",
376 | "for epoch in range(1, EPOCHS + 1):\n",
377 | " train(model, train_loader, optimizer, log_interval = 200)\n",
378 | " test_loss, test_accuracy = evaluate(model, test_loader)\n",
379 | " print(\"\\n[EPOCH: {}], \\tTest Loss: {:.4f}, \\tTest Accuracy: {:.2f} % \\n\".format(\n",
380 | " epoch, test_loss, test_accuracy))"
381 | ]
382 | }
383 | ],
384 | "metadata": {
385 | "kernelspec": {
386 | "display_name": "Python 3",
387 | "language": "python",
388 | "name": "python3"
389 | },
390 | "language_info": {
391 | "codemirror_mode": {
392 | "name": "ipython",
393 | "version": 3
394 | },
395 | "file_extension": ".py",
396 | "mimetype": "text/x-python",
397 | "name": "python",
398 | "nbconvert_exporter": "python",
399 | "pygments_lexer": "ipython3",
400 | "version": "3.6.8"
401 | }
402 | },
403 | "nbformat": 4,
404 | "nbformat_minor": 4
405 | }
406 |
--------------------------------------------------------------------------------
/3-3_MNIST_MLP_Dropout_ReLU_BN.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 1,
6 | "metadata": {},
7 | "outputs": [],
8 | "source": [
9 | "''' 1. Module Import '''\n",
10 | "import numpy as np\n",
11 | "import matplotlib.pyplot as plt\n",
12 | "\n",
13 | "import torch\n",
14 | "import torch.nn as nn\n",
15 | "import torch.nn.functional as F\n",
16 | "from torchvision import transforms, datasets"
17 | ]
18 | },
19 | {
20 | "cell_type": "code",
21 | "execution_count": 2,
22 | "metadata": {},
23 | "outputs": [
24 | {
25 | "name": "stdout",
26 | "output_type": "stream",
27 | "text": [
28 | "Using PyTorch version: 1.6.0+cu101 Device: cuda\n"
29 | ]
30 | }
31 | ],
32 | "source": [
33 | "''' 2. 딥러닝 모델을 설계할 때 활용하는 장비 확인 '''\n",
34 | "if torch.cuda.is_available():\n",
35 | " DEVICE = torch.device('cuda')\n",
36 | "else:\n",
37 | " DEVICE = torch.device('cpu')\n",
38 | "print('Using PyTorch version:', torch.__version__, ' Device:', DEVICE)"
39 | ]
40 | },
41 | {
42 | "cell_type": "code",
43 | "execution_count": 3,
44 | "metadata": {},
45 | "outputs": [],
46 | "source": [
47 | "BATCH_SIZE = 32\n",
48 | "EPOCHS = 10"
49 | ]
50 | },
51 | {
52 | "cell_type": "code",
53 | "execution_count": 4,
54 | "metadata": {},
55 | "outputs": [],
56 | "source": [
57 | "''' 3. MNIST 데이터 다운로드 (Train set, Test set 분리하기) '''\n",
58 | "train_dataset = datasets.MNIST(root = \"../data/MNIST\",\n",
59 | " train = True,\n",
60 | " download = True,\n",
61 | " transform = transforms.ToTensor())\n",
62 | "\n",
63 | "test_dataset = datasets.MNIST(root = \"../data/MNIST\",\n",
64 | " train = False,\n",
65 | " transform = transforms.ToTensor())\n",
66 | "\n",
67 | "train_loader = torch.utils.data.DataLoader(dataset = train_dataset,\n",
68 | " batch_size = BATCH_SIZE,\n",
69 | " shuffle = True)\n",
70 | "\n",
71 | "test_loader = torch.utils.data.DataLoader(dataset = test_dataset,\n",
72 | " batch_size = BATCH_SIZE,\n",
73 | " shuffle = False)"
74 | ]
75 | },
76 | {
77 | "cell_type": "code",
78 | "execution_count": 5,
79 | "metadata": {},
80 | "outputs": [
81 | {
82 | "name": "stdout",
83 | "output_type": "stream",
84 | "text": [
85 | "X_train: torch.Size([32, 1, 28, 28]) type: torch.FloatTensor\n",
86 | "y_train: torch.Size([32]) type: torch.LongTensor\n"
87 | ]
88 | }
89 | ],
90 | "source": [
91 | "''' 4. 데이터 확인하기 (1) '''\n",
92 | "for (X_train, y_train) in train_loader:\n",
93 | " print('X_train:', X_train.size(), 'type:', X_train.type())\n",
94 | " print('y_train:', y_train.size(), 'type:', y_train.type())\n",
95 | " break"
96 | ]
97 | },
98 | {
99 | "cell_type": "code",
100 | "execution_count": 6,
101 | "metadata": {},
102 | "outputs": [
103 | {
104 | "data": {
105 | "image/png": "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\n",
106 | "text/plain": [
107 | ""
108 | ]
109 | },
110 | "metadata": {
111 | "needs_background": "light"
112 | },
113 | "output_type": "display_data"
114 | }
115 | ],
116 | "source": [
117 | "''' 5. 데이터 확인하기 (2) '''\n",
118 | "pltsize = 1\n",
119 | "plt.figure(figsize=(10 * pltsize, pltsize))\n",
120 | "for i in range(10):\n",
121 | " plt.subplot(1, 10, i + 1)\n",
122 | " plt.axis('off')\n",
123 | " plt.imshow(X_train[i, :, :, :].numpy().reshape(28, 28), cmap = \"gray_r\")\n",
124 | " plt.title('Class: ' + str(y_train[i].item()))"
125 | ]
126 | },
127 | {
128 | "cell_type": "code",
129 | "execution_count": 7,
130 | "metadata": {},
131 | "outputs": [],
132 | "source": [
133 | "''' 6. Multi Layer Perceptron (MLP) 모델 설계하기 '''\n",
134 | "class Net(nn.Module):\n",
135 | " def __init__(self):\n",
136 | " super(Net, self).__init__()\n",
137 | " self.fc1 = nn.Linear(28 * 28, 512)\n",
138 | " self.fc2 = nn.Linear(512, 256)\n",
139 | " self.fc3 = nn.Linear(256, 10)\n",
140 | " self.dropout_prob = 0.5\n",
141 | " self.batch_norm1 = nn.BatchNorm1d(512)\n",
142 | " self.batch_norm2 = nn.BatchNorm1d(256)\n",
143 | "\n",
144 | " def forward(self, x):\n",
145 | " x = x.view(-1, 28 * 28)\n",
146 | " x = self.fc1(x)\n",
147 | " x = self.batch_norm1(x)\n",
148 | " x = F.relu(x)\n",
149 | " x = F.dropout(x, training = self.training, p = self.dropout_prob)\n",
150 | " x = self.fc2(x)\n",
151 | " x = self.batch_norm2(x)\n",
152 | " x = F.relu(x)\n",
153 | " x = F.dropout(x, training = self.training, p = self.dropout_prob)\n",
154 | " x = self.fc3(x)\n",
155 | " x = F.log_softmax(x, dim = 1)\n",
156 | " return x"
157 | ]
158 | },
159 | {
160 | "cell_type": "code",
161 | "execution_count": 8,
162 | "metadata": {},
163 | "outputs": [
164 | {
165 | "name": "stdout",
166 | "output_type": "stream",
167 | "text": [
168 | "Net(\n",
169 | " (fc1): Linear(in_features=784, out_features=512, bias=True)\n",
170 | " (fc2): Linear(in_features=512, out_features=256, bias=True)\n",
171 | " (fc3): Linear(in_features=256, out_features=10, bias=True)\n",
172 | " (batch_norm1): BatchNorm1d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
173 | " (batch_norm2): BatchNorm1d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
174 | ")\n"
175 | ]
176 | }
177 | ],
178 | "source": [
179 | "''' 7. Optimizer, Objective Function 설정하기 '''\n",
180 | "model = Net().to(DEVICE)\n",
181 | "optimizer = torch.optim.SGD(model.parameters(), lr = 0.01, momentum = 0.5)\n",
182 | "criterion = nn.CrossEntropyLoss()\n",
183 | "\n",
184 | "print(model)"
185 | ]
186 | },
187 | {
188 | "cell_type": "code",
189 | "execution_count": 9,
190 | "metadata": {},
191 | "outputs": [],
192 | "source": [
193 | "''' 8. MLP 모델 학습을 진행하며 학습 데이터에 대한 모델 성능을 확인하는 함수 정의 '''\n",
194 | "def train(model, train_loader, optimizer, log_interval):\n",
195 | " model.train()\n",
196 | " for batch_idx, (image, label) in enumerate(train_loader):\n",
197 | " image = image.to(DEVICE)\n",
198 | " label = label.to(DEVICE)\n",
199 | " optimizer.zero_grad()\n",
200 | " output = model(image)\n",
201 | " loss = criterion(output, label)\n",
202 | " loss.backward()\n",
203 | " optimizer.step()\n",
204 | "\n",
205 | " if batch_idx % log_interval == 0:\n",
206 | " print(\"Train Epoch: {} [{}/{} ({:.0f}%)]\\tTrain Loss: {:.6f}\".format(\n",
207 | " epoch, batch_idx * len(image), \n",
208 | " len(train_loader.dataset), 100. * batch_idx / len(train_loader), \n",
209 | " loss.item()))"
210 | ]
211 | },
212 | {
213 | "cell_type": "code",
214 | "execution_count": 10,
215 | "metadata": {},
216 | "outputs": [],
217 | "source": [
218 | "''' 9. 학습되는 과정 속에서 검증 데이터에 대한 모델 성능을 확인하는 함수 정의 '''\n",
219 | "def evaluate(model, test_loader):\n",
220 | " model.eval()\n",
221 | " test_loss = 0\n",
222 | " correct = 0\n",
223 | "\n",
224 | " with torch.no_grad():\n",
225 | " for image, label in test_loader:\n",
226 | " image = image.to(DEVICE)\n",
227 | " label = label.to(DEVICE)\n",
228 | " output = model(image)\n",
229 | " test_loss += criterion(output, label).item()\n",
230 | " prediction = output.max(1, keepdim = True)[1]\n",
231 | " correct += prediction.eq(label.view_as(prediction)).sum().item()\n",
232 | " \n",
233 | " test_loss /= (len(test_loader.dataset) / BATCH_SIZE)\n",
234 | " test_accuracy = 100. * correct / len(test_loader.dataset)\n",
235 | " return test_loss, test_accuracy"
236 | ]
237 | },
238 | {
239 | "cell_type": "code",
240 | "execution_count": 11,
241 | "metadata": {},
242 | "outputs": [
243 | {
244 | "name": "stdout",
245 | "output_type": "stream",
246 | "text": [
247 | "Train Epoch: 1 [0/60000 (0%)]\tTrain Loss: 2.408397\n",
248 | "Train Epoch: 1 [6400/60000 (11%)]\tTrain Loss: 0.565749\n",
249 | "Train Epoch: 1 [12800/60000 (21%)]\tTrain Loss: 0.529340\n",
250 | "Train Epoch: 1 [19200/60000 (32%)]\tTrain Loss: 0.337603\n",
251 | "Train Epoch: 1 [25600/60000 (43%)]\tTrain Loss: 0.587682\n",
252 | "Train Epoch: 1 [32000/60000 (53%)]\tTrain Loss: 0.371249\n",
253 | "Train Epoch: 1 [38400/60000 (64%)]\tTrain Loss: 0.757439\n",
254 | "Train Epoch: 1 [44800/60000 (75%)]\tTrain Loss: 0.523711\n",
255 | "Train Epoch: 1 [51200/60000 (85%)]\tTrain Loss: 0.288144\n",
256 | "Train Epoch: 1 [57600/60000 (96%)]\tTrain Loss: 0.253793\n",
257 | "\n",
258 | "[EPOCH: 1], \tTest Loss: 0.0048, \tTest Accuracy: 95.26 % \n",
259 | "\n",
260 | "Train Epoch: 2 [0/60000 (0%)]\tTrain Loss: 0.408605\n",
261 | "Train Epoch: 2 [6400/60000 (11%)]\tTrain Loss: 0.290822\n",
262 | "Train Epoch: 2 [12800/60000 (21%)]\tTrain Loss: 0.197596\n",
263 | "Train Epoch: 2 [19200/60000 (32%)]\tTrain Loss: 0.256635\n",
264 | "Train Epoch: 2 [25600/60000 (43%)]\tTrain Loss: 0.263706\n",
265 | "Train Epoch: 2 [32000/60000 (53%)]\tTrain Loss: 0.269775\n",
266 | "Train Epoch: 2 [38400/60000 (64%)]\tTrain Loss: 0.330976\n",
267 | "Train Epoch: 2 [44800/60000 (75%)]\tTrain Loss: 0.063536\n",
268 | "Train Epoch: 2 [51200/60000 (85%)]\tTrain Loss: 0.278092\n",
269 | "Train Epoch: 2 [57600/60000 (96%)]\tTrain Loss: 0.370884\n",
270 | "\n",
271 | "[EPOCH: 2], \tTest Loss: 0.0037, \tTest Accuracy: 96.38 % \n",
272 | "\n",
273 | "Train Epoch: 3 [0/60000 (0%)]\tTrain Loss: 0.473225\n",
274 | "Train Epoch: 3 [6400/60000 (11%)]\tTrain Loss: 0.359397\n",
275 | "Train Epoch: 3 [12800/60000 (21%)]\tTrain Loss: 0.335095\n",
276 | "Train Epoch: 3 [19200/60000 (32%)]\tTrain Loss: 0.061883\n",
277 | "Train Epoch: 3 [25600/60000 (43%)]\tTrain Loss: 0.148324\n",
278 | "Train Epoch: 3 [32000/60000 (53%)]\tTrain Loss: 0.295295\n",
279 | "Train Epoch: 3 [38400/60000 (64%)]\tTrain Loss: 0.143966\n",
280 | "Train Epoch: 3 [44800/60000 (75%)]\tTrain Loss: 0.027375\n",
281 | "Train Epoch: 3 [51200/60000 (85%)]\tTrain Loss: 0.296227\n",
282 | "Train Epoch: 3 [57600/60000 (96%)]\tTrain Loss: 0.146117\n",
283 | "\n",
284 | "[EPOCH: 3], \tTest Loss: 0.0031, \tTest Accuracy: 96.92 % \n",
285 | "\n",
286 | "Train Epoch: 4 [0/60000 (0%)]\tTrain Loss: 0.128434\n",
287 | "Train Epoch: 4 [6400/60000 (11%)]\tTrain Loss: 0.144728\n",
288 | "Train Epoch: 4 [12800/60000 (21%)]\tTrain Loss: 0.251649\n",
289 | "Train Epoch: 4 [19200/60000 (32%)]\tTrain Loss: 0.080718\n",
290 | "Train Epoch: 4 [25600/60000 (43%)]\tTrain Loss: 0.185179\n",
291 | "Train Epoch: 4 [32000/60000 (53%)]\tTrain Loss: 0.388055\n",
292 | "Train Epoch: 4 [38400/60000 (64%)]\tTrain Loss: 0.169363\n",
293 | "Train Epoch: 4 [44800/60000 (75%)]\tTrain Loss: 0.044224\n",
294 | "Train Epoch: 4 [51200/60000 (85%)]\tTrain Loss: 0.206786\n",
295 | "Train Epoch: 4 [57600/60000 (96%)]\tTrain Loss: 0.246572\n",
296 | "\n",
297 | "[EPOCH: 4], \tTest Loss: 0.0028, \tTest Accuracy: 97.29 % \n",
298 | "\n",
299 | "Train Epoch: 5 [0/60000 (0%)]\tTrain Loss: 0.072247\n",
300 | "Train Epoch: 5 [6400/60000 (11%)]\tTrain Loss: 0.243650\n",
301 | "Train Epoch: 5 [12800/60000 (21%)]\tTrain Loss: 0.123755\n",
302 | "Train Epoch: 5 [19200/60000 (32%)]\tTrain Loss: 0.073167\n",
303 | "Train Epoch: 5 [25600/60000 (43%)]\tTrain Loss: 0.055972\n",
304 | "Train Epoch: 5 [32000/60000 (53%)]\tTrain Loss: 0.302183\n",
305 | "Train Epoch: 5 [38400/60000 (64%)]\tTrain Loss: 0.355575\n",
306 | "Train Epoch: 5 [44800/60000 (75%)]\tTrain Loss: 0.080272\n",
307 | "Train Epoch: 5 [51200/60000 (85%)]\tTrain Loss: 0.410138\n",
308 | "Train Epoch: 5 [57600/60000 (96%)]\tTrain Loss: 0.532726\n",
309 | "\n",
310 | "[EPOCH: 5], \tTest Loss: 0.0026, \tTest Accuracy: 97.54 % \n",
311 | "\n",
312 | "Train Epoch: 6 [0/60000 (0%)]\tTrain Loss: 0.082712\n",
313 | "Train Epoch: 6 [6400/60000 (11%)]\tTrain Loss: 0.242383\n",
314 | "Train Epoch: 6 [12800/60000 (21%)]\tTrain Loss: 0.073166\n",
315 | "Train Epoch: 6 [19200/60000 (32%)]\tTrain Loss: 0.065983\n",
316 | "Train Epoch: 6 [25600/60000 (43%)]\tTrain Loss: 0.153423\n",
317 | "Train Epoch: 6 [32000/60000 (53%)]\tTrain Loss: 0.106637\n",
318 | "Train Epoch: 6 [38400/60000 (64%)]\tTrain Loss: 0.181440\n",
319 | "Train Epoch: 6 [44800/60000 (75%)]\tTrain Loss: 0.217991\n",
320 | "Train Epoch: 6 [51200/60000 (85%)]\tTrain Loss: 0.047518\n",
321 | "Train Epoch: 6 [57600/60000 (96%)]\tTrain Loss: 0.152127\n",
322 | "\n",
323 | "[EPOCH: 6], \tTest Loss: 0.0024, \tTest Accuracy: 97.55 % \n",
324 | "\n",
325 | "Train Epoch: 7 [0/60000 (0%)]\tTrain Loss: 0.074586\n",
326 | "Train Epoch: 7 [6400/60000 (11%)]\tTrain Loss: 0.285396\n",
327 | "Train Epoch: 7 [12800/60000 (21%)]\tTrain Loss: 0.101163\n",
328 | "Train Epoch: 7 [19200/60000 (32%)]\tTrain Loss: 0.222260\n",
329 | "Train Epoch: 7 [25600/60000 (43%)]\tTrain Loss: 0.096511\n",
330 | "Train Epoch: 7 [32000/60000 (53%)]\tTrain Loss: 0.184161\n",
331 | "Train Epoch: 7 [38400/60000 (64%)]\tTrain Loss: 0.040291\n",
332 | "Train Epoch: 7 [44800/60000 (75%)]\tTrain Loss: 0.186297\n",
333 | "Train Epoch: 7 [51200/60000 (85%)]\tTrain Loss: 0.321589\n",
334 | "Train Epoch: 7 [57600/60000 (96%)]\tTrain Loss: 0.179110\n",
335 | "\n",
336 | "[EPOCH: 7], \tTest Loss: 0.0022, \tTest Accuracy: 97.74 % \n",
337 | "\n",
338 | "Train Epoch: 8 [0/60000 (0%)]\tTrain Loss: 0.041527\n",
339 | "Train Epoch: 8 [6400/60000 (11%)]\tTrain Loss: 0.089809\n",
340 | "Train Epoch: 8 [12800/60000 (21%)]\tTrain Loss: 0.173585\n",
341 | "Train Epoch: 8 [19200/60000 (32%)]\tTrain Loss: 0.122103\n",
342 | "Train Epoch: 8 [25600/60000 (43%)]\tTrain Loss: 0.102293\n",
343 | "Train Epoch: 8 [32000/60000 (53%)]\tTrain Loss: 0.140654\n",
344 | "Train Epoch: 8 [38400/60000 (64%)]\tTrain Loss: 0.190124\n",
345 | "Train Epoch: 8 [44800/60000 (75%)]\tTrain Loss: 0.364228\n",
346 | "Train Epoch: 8 [51200/60000 (85%)]\tTrain Loss: 0.095618\n",
347 | "Train Epoch: 8 [57600/60000 (96%)]\tTrain Loss: 0.050769\n",
348 | "\n",
349 | "[EPOCH: 8], \tTest Loss: 0.0022, \tTest Accuracy: 97.87 % \n",
350 | "\n",
351 | "Train Epoch: 9 [0/60000 (0%)]\tTrain Loss: 0.289604\n",
352 | "Train Epoch: 9 [6400/60000 (11%)]\tTrain Loss: 0.199143\n",
353 | "Train Epoch: 9 [12800/60000 (21%)]\tTrain Loss: 0.064629\n",
354 | "Train Epoch: 9 [19200/60000 (32%)]\tTrain Loss: 0.038997\n",
355 | "Train Epoch: 9 [25600/60000 (43%)]\tTrain Loss: 0.132849\n",
356 | "Train Epoch: 9 [32000/60000 (53%)]\tTrain Loss: 0.466395\n",
357 | "Train Epoch: 9 [38400/60000 (64%)]\tTrain Loss: 0.095477\n",
358 | "Train Epoch: 9 [44800/60000 (75%)]\tTrain Loss: 0.124449\n",
359 | "Train Epoch: 9 [51200/60000 (85%)]\tTrain Loss: 0.069822\n",
360 | "Train Epoch: 9 [57600/60000 (96%)]\tTrain Loss: 0.073448\n",
361 | "\n",
362 | "[EPOCH: 9], \tTest Loss: 0.0021, \tTest Accuracy: 97.98 % \n",
363 | "\n",
364 | "Train Epoch: 10 [0/60000 (0%)]\tTrain Loss: 0.060481\n",
365 | "Train Epoch: 10 [6400/60000 (11%)]\tTrain Loss: 0.127830\n",
366 | "Train Epoch: 10 [12800/60000 (21%)]\tTrain Loss: 0.053453\n",
367 | "Train Epoch: 10 [19200/60000 (32%)]\tTrain Loss: 0.273952\n",
368 | "Train Epoch: 10 [25600/60000 (43%)]\tTrain Loss: 0.150731\n",
369 | "Train Epoch: 10 [32000/60000 (53%)]\tTrain Loss: 0.040127\n",
370 | "Train Epoch: 10 [38400/60000 (64%)]\tTrain Loss: 0.267848\n",
371 | "Train Epoch: 10 [44800/60000 (75%)]\tTrain Loss: 0.110777\n",
372 | "Train Epoch: 10 [51200/60000 (85%)]\tTrain Loss: 0.167811\n",
373 | "Train Epoch: 10 [57600/60000 (96%)]\tTrain Loss: 0.026505\n",
374 | "\n",
375 | "[EPOCH: 10], \tTest Loss: 0.0021, \tTest Accuracy: 97.92 % \n",
376 | "\n"
377 | ]
378 | }
379 | ],
380 | "source": [
381 | "''' 10. MLP 학습 실행하며 Train, Test set의 Loss 및 Test set Accuracy 확인하기 '''\n",
382 | "for epoch in range(1, EPOCHS + 1):\n",
383 | " train(model, train_loader, optimizer, log_interval = 200)\n",
384 | " test_loss, test_accuracy = evaluate(model, test_loader)\n",
385 | " print(\"\\n[EPOCH: {}], \\tTest Loss: {:.4f}, \\tTest Accuracy: {:.2f} % \\n\".format(\n",
386 | " epoch, test_loss, test_accuracy))"
387 | ]
388 | }
389 | ],
390 | "metadata": {
391 | "kernelspec": {
392 | "display_name": "Python 3",
393 | "language": "python",
394 | "name": "python3"
395 | },
396 | "language_info": {
397 | "codemirror_mode": {
398 | "name": "ipython",
399 | "version": 3
400 | },
401 | "file_extension": ".py",
402 | "mimetype": "text/x-python",
403 | "name": "python",
404 | "nbconvert_exporter": "python",
405 | "pygments_lexer": "ipython3",
406 | "version": "3.6.8"
407 | }
408 | },
409 | "nbformat": 4,
410 | "nbformat_minor": 4
411 | }
412 |
--------------------------------------------------------------------------------