├── .gitignore ├── 1-1_Virtualenv.txt ├── 1-2_Basic_Autograd.ipynb ├── 2-1_MNIST_MLP.ipynb ├── 3-1_MNIST_MLP_Dropout.ipynb ├── 3-2_MNIST_MLP_Dropout_ReLU.ipynb ├── 3-3_MNIST_MLP_Dropout_ReLU_BN.ipynb ├── 3-4_MNIST_MLP_Dropout_ReLU_BN_He.ipynb ├── 3-5_MNIST_MLP_Dropout_ReLU_BN_HE_Adam.ipynb ├── 3-6_MNIST_AutoEncoder.ipynb ├── 4-1_CIFAR_MLP.ipynb ├── 4-2_CIFAR_CNN.ipynb ├── 4-3_CIFAR_CNN_Augmentation.ipynb ├── 4-4_CIFAR_ResNet.ipynb ├── 4-5_Load-Pre-trained_Model.ipynb ├── 4-6_Transfer_Learning.ipynb ├── 5-1_tokenization.ipynb ├── 5-2_model_imdb_scratch.ipynb ├── 5-3_model_imdb_glove.ipynb ├── 5-4_model_imdb_fasttext.ipynb ├── 5-5_model_imdb_BERT.ipynb ├── 5_NLP_v2.ipynb ├── LICENSE.md └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .ipynb_checkpoints/ -------------------------------------------------------------------------------- /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 -------------------------------------------------------------------------------- /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-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": "iVBORw0KGgoAAAANSUhEUgAAAjwAAABNCAYAAACi7r7XAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8vihELAAAACXBIWXMAAAsTAAALEwEAmpwYAABAW0lEQVR4nO29d3Bc15no+bud0I1Go7sRGjlnAiABUAwiqURRVrJkOUmWn2fkGVft7kzJZc/T1JZ3duw3mvcmeDxT4/V47HHZO7a2bNkjWVayRAVSJCXmCAIgiETk1AAa6IBO6HD3D/AeARQDSIJEA76/Kpat7nsvztfnnnO+850vSLIso6KioqKioqKyltGsdANUVFRUVFRUVG41qsKjoqKioqKisuZRFR4VFRUVFRWVNY+q8KioqKioqKiseVSFR0VFRUVFRWXNoyo8KioqKioqKmuem1Z4JEn6G0mSfrkcjUlUVBlXP2tdPlBlXCusdRnXunygypioLEnhkSTpy5IknZQkaVaSpDFJknZLkrTjVjduCe0qvNimhf9kSZKeu4FnJaSMC5Ek6Z6L8v2vG7w/IWVcrn5MVPkAJEkqliRpnyRJAUmSOiRJ2nWDz0lkGfdJkjQpSZJXkqSzkiR95gafo8q4gkiS1CBJ0keSJHkkSRqWJOnbN/CMRJZvmyRJxyVJ8kmS1HKj7UpwGf+nJEmtkiRFJUn6m5t4TiLLeN1j8ZoKjyRJ/x34PvD3QBZQCPwIuKGBvpzIsjwoy3KK8g+oB+LAK9fznESWUUGSJD3w/wDHbvD+hJVxOfoxkeW7yK+BM0A68H8Dv5UkKfN6HrAKZPwGkCPLcirwvwG/lCQp53oeoMqYELwIfAikAfcAfy5J0uNLvTmR5ZMkKQ14E/geYAP+CXhTkiT7dT4nYWW8SA/wfwJv3egDVoGM1z8WZVm+4j/ACswCX7zKNX8D/HLBf78MjAMe5gdN7YLvHgHaAR8wAvzlxc8zgN8DbmAa+AjQXK1tV2jL/wD2Xec9q0JG4FvMD85fAP9rLcp4o/2Y6PIBlUAYsCz47CPg/1grMl6mLZuBELBZlXF1yQgEgHWX/P3/ay3IB3waOHfJZ13A19ZSHy549i+Bv7mBd3vVyHjxOUsai9ey8NwJGIFXr3HdQnYDFYADOA38asF3/y/wv8uybAHqgA8ufv4cMAxkMq9J/hUgA0iS9CNJkn50rT8qSZIE/DHwwnW0FVaBjJIkFQF/CvztdbRxIQkvo8IN9mOiy1cL9Mqy7Fvw2dmLny+VRJeRi9f8XpKkEPOWyP3Ayetoryrj5bndMn4f+GNJkvSSJFVdbPOeJbZ1NcgnXea/666jvatBxptlVch4vWNRdw0B0oEpWZaj17hOIMvyfy5ozN8AM5IkWWVZ9gARYJ0kSWdlWZ4BZi5eGgFygCJZlnuY1/KU5/35Ev/0DuZ/sN8uta0XWQ0y/gD4tizLs/P6wHWzGmRUuJF+THT5Upjf9SzEA+Qttb0kvozKNZ++ePy6C6iRZTm+1Paiynilv3e7Zfw98P8Bfwlogb+VZfnEEpub6PIdAXIlSXqa+Tnmy0AZkLzU9pL4Mi4Hq0LG6x2L17LwuIAMSZKupRgBIEmSVpKkf5Qk6YIkSV6g/+JXGRf/9/PMm7YGJEk6IEnSnRc//x7zZ47vSZLUK0nSt5by9y7hGeAVWZZnr/O+hJZRkqTHmD8K+a8lynM5ElrGS7iRfkx0+WaB1Es+S2XevLtUEl1GgSzLEVmWdwOfkq7D9wNVxk+wAvNNGvAO89ZkI1AAPChJ0lIX2ISWT5ZlF/M+KP8dcAIPMW+9Gl7K/RdJaBmXiVUj43WNxWuci1kBP/CFq1zzN1w8xwP+CDgPlDBvJrQxb54qv+QePfAXwNBlnlcHTAD3X61tl9xjYn7HvHOp96wWGZk3L3uZPxsdB4LML6CvrxUZb7YfE10+5n14Qiz24fmQ6/fhSVgZr9CePcBfqDKuHhmBO4CZSz77JvD7tSDfZe7VAYPAg2ulDy+572Z8eFaFjAvuv+ZYvKqFR543RX0H+HdJkp6QJClZmj/XfViSpH+6zC0W5p0zXcybCP9e+UKSJIMkSf/tookrwvwiHr/43aclSSqXJElifsGLKd8tkc8ybyLbdx33rBYZv838gtlw8d8bwE+BP1lDMircUD8munyyLHcBzcD/kCTJKEnSZ4H1XEcUWqLLKElS9cW2mC626yvA3cABVcbVIyPzDrySNB+OrJEkKRt4CmhZI/IhSVLjxTalAv/M/OL77lLuXUUy6iVJMjJ/iqO7OO9o14qMNzwWl6g5/TfmnYH8zFsZ3gK2XUbLSwFeZ95UP8C886kMlAMG5k2lMxcFPgHsuHjfXzBvAvMzb1r89oK//R/Af1yjfe8C//NGtMLVIuOCa3/BdUZprRYZb7YfE1k+oJh5p7og0AnsWksyAjXMOw76mI+4OAF8VpVxdcl48fudF5/ludi2nwLJa0i+X1+UzQP8F+BYg334i4t/Y+G/r64VGbnBsShdvFlFRUVFRUVFZc2i1tJSUVFRUVFRWfOoCo+KioqKiorKmkdVeFRUVFRUVFTWPKrCo6KioqKiorLmURUeFRUVFRUVlTXPtbIorvYQrqXUYVBlTHxUGde+fKDKuBpQZVz78sEalVG18KioqKioqKiseVSFR0VFRUVFRWXNoyo8KioqKioqKmseVeFRUVFRUVFRWfMsqfS7yvIQjUaJRCL09fURj8fJy8vDZDJhNBpXumkqF5FlmWg0isfjweVyEYlEAEhLS0On06HRaDCbzRiNRubr3amoqKjcPmZmZpicnESr1aLX68nLy0OrXXJd0D9oVIXnNuJ2uxkfH+eZZ54hEonw/PPPU1VVxbp161a6aSoXiUajTExM8O677/LLX/6S6elpJEnic5/7HDabDYvFwh133EFVVRU6nU5VelRUVG4b0WiUffv28bOf/YzU1FSysrJ4/vnnsdlsK920VYGq8NxGotEoc3NzhMNh3G43p06dwmQyqQpPghAIBBgfH+fVV1/lzJkz9PX1EQgEkCSJgwcPCmvc0NAQ5eXlPPDAA6SlpaHRqCfDK0EkEiEajRIMBhkdHWVmZgaLxYLJZCI3N5fJyUmGh4eB+bE3MDAAgNFoFMprcXExKSkp6oKRwMRiMSKRiOjjzs5OQqEQc3NzlJSUkJeXR1lZGSaTaaWbeksJBAJ0dXXR3t5OT08PRqORyclJurq6KCgoICcnZ6WbCMCFCxcYHh5mZmYGWZYxm81MT0/jdDrR6/UYjUZqa2vJzMyktLT0trZNVXhuI9FolHA4TDweZ3Z2lg8//JDs7OyVbtayI8vyFS0fV/tuJZFlGa/XS3d3N9///veZmZnB7/eL79977z3x/wsKCigsLKS+vh6r1bqqFR5ZvnK6jUTsJwVZlgmHwwQCAaampjh27Bjt7e0UFBTgcDgwGAy0trZy4MABAILBIO+++y4AdrudiooKCgsLefjhh8nLy8NqtSa0vNfLlfp1NcoYiUTw+/20trbS1dXFiy++yMzMDB6Ph09/+tPs2LGDrKysNX/M7Pf7OXr0KKdPn6a7uxuYf5fPnj1LLBZLGIWnpaWFDz/8kI6ODtGujo4OTpw4QUpKCmlpafzpn/4pDQ0NlJSU3NY+S2iFx+v14nK58Hq9hEIhwuEw09PT9PT0AKDVarnnnntwOBzk5eUl9Msej8c5c+YMH330ETMzMyvdnGUlFovhdDo5deoUfX19TExMUFRURFZWFtu2bRMT1nvvvcfo6Ci1tbUUFBSwefNm4Rez0kSjUX7/+99z+vRpXC4X0WgUvV5PWVkZNpuNlJQU/H4/o6OjBINBOjs7eeGFF9iwYQNf+tKX0OkSbyjFYjGCwSDhcJhwOExLSwsej4fZ2Vnm5uYIhUK0trbicrnEPbIsk5KSQkpKCnV1dSQnJwPgcDjIz88nJydHfL9S4y0YDOLz+di9ezc9PT0cOnRIKKhGo5GkpCReeOEF4YcF8/07NTUFzPtATExM0NzcTCQSoba2ltLS0oTsw6Xi9Xrxer0cPHiQsbExuru7cbvdzM7OIkkSycnJVFZWUldXx5YtW8jMzESv1zM4OMj4+Djnzp2jqamJqqoqkpOTV3xMhkIhPB4Pzc3NtLS0cOTIEcbGxpidncXr9TI3N4csyxw8eJD29nZsNhs1NTXU1dWteNtvFdPT07zyyitcuHBBfJaUlERNTQ1FRUUr2LJ5YrEYoVCIoaEhzp07JyxxnZ2dzM3NYbVaKSwsxGw288orr7Bnzx5ee+01ioqKyMvL44knniAjI+OWtvGWj/B4PE4sFiMQCFx1Nwkf79qU66amphgbG2N6eppgMIjf72diYoKWlhZgXuHJzs4mEomQm5t7yyZgWZaZnZ0lGo0CoNPpMBqNaLXaJQ0uxRF2eHiYtrY2QqEQsiwLk3w0GkWr1Sa0wnY5IpEIkUiE2dlZBgcHOXPmDO3t7QwODlJdXU1RURG5ublEo1FmZ2c5evQovb29hMNhIpEIDQ0NSJK04hOU0j/nz5+no6ODaDSK0WgkNTWV8vJysrOzSU1NxefzYTKZ6OnpYXx8nObmZjQaDV/4whcSrv+i0Sh+vx+n04nf78fv93P27FlcLhdut5tQKITf7+fIkSOMj48DH1sFbDYbVqsVj8dDamoqAPn5+WLjkZ6eTn5+PgaDAb1ef9tlC4fDeDwezp49y7lz5zhw4AAGg0E4bmo0mkVOnHq9HkmSiEajxONxAoEAHo8HvV7PwMAA6enp15ybEpVYLEY0GmV8fJzx8XFOnDhBf38/zc3NuFwuPB4PABaLhdHRUebm5nA4HBiNRsxmM0NDQ/T29nLkyBHMZjMWi4Xc3FyMRuOKKYCxWIypqSnGx8dpaWnhxIkTHDp0CFmW0Wq1OBwOIpEIOp2OqakpRkdH6e/vX9X9eC0CgQAul4uOjg6xYVaOYh0OB1ardYVbOD9/xGIxwuGw2GjNzc0hSRJGoxG73U5JSQlGo5G9e/cyODhIT08PNTU1VFRUsHPnTux2+y11wL6lb7Qsy0xPTzM8PMxLL70kFIbLoSz8Bw8exOfzATA3Nyf+xeNx4OPzXJg3z7a3t9PY2MjPf/5zkpKSll2Gubk5AoEAL7zwAufPnwegtLSURx55hNzcXNLS0pb0DI/HQ2trK/v37ycSiaDVahkYGKC/v5/+/n5yc3PFbnq10NbWRn9/P6+//jr9/f2cPXuWSCRCLBajtbUVvV7Piy++iNlsxmazcf78eTweD4ODg4yNjbF9+3ax01xJfD4fU1NTHDlyhI6ODqxWK7t27eLJJ5+kvr6e9PR0NBqN2MH867/+Ky+//DLNzc2Ew2HGx8dJT0/HYrGsqBwKir/KiRMn+PGPf8zExIRQcmRZJh6PI8sysiwzNzcn7pMkSSj3gUCAt99+WyhxWq0WnU5HRkYG2dnZfPOb36S0tJT6+vrbLt/k5CQXLlzg7bffZmJigqSkJKqqqsQu12QyiYnVYDBQVFSELMv84Ac/YHR0lJGRESFvcXExxcXFCaWsXg/j4+NcuHCBH/7wh5w6dUpYJ+fm5ojFYuI6v9/P8ePH6erqYvfu3Tz33HOUlZXxox/9iL6+Ps6fP8/hw4fJzc3lm9/8JlVVVVRWVt723yUUCuHz+fjHf/xHzp07R3t7O7m5uezcuZPt27dTXFxMQ0MDY2Nj7N27l9dff53Tp0/jdrvXnOVcIRqN8rvf/Y4zZ84wNTVFOBwG4HOf+xybNm0iJycnIdYOnU6HxWKhoaGBWCzG5OQkycnJbN68GaPRiNFoFBtgk8lER0cHJ0+eJBwOMzQ0xOOPP45Wq6WwsPCWvXe3XIUPhUJ4vV76+/sJhUKEQiGx4wqHw2i1WpKSksRE7Ha7CQQCwMdOiYFA4BPKkslkEhPbrZ6wNBoNXq+X8fFxZmZmCIVCwkluKQqPJElotVqsVitZWVmMj4+L44aJiQl6enpITU1NiJdWIR6PE41GcTqdzMzMkJKSIjRvv98vzM1DQ0N0dXURCATIycnBarViMpno6urC7/czNjaGyWQSRymKVSgej6PX61fcuqPIMz09jd/vZ25ujvT0dBwOBxUVFWRlZQlFRtnBOBwOMjMz8Xg8zMzM0NHRQXl5ecIoPMqOKh6PMzg4yMzMjNhEXA6tVovZbBbWtuTkZHQ6HS6Xi7m5ObHBgPkxGQqFOHToED6fj+LiYoxG421VWpOTk0lPT2fLli14vV4A4bwK82b+3Nxc9Ho9er2e7OxsQqEQycnJop16vR6TyURxcTGFhYUJ8R5eD7FYTPicHTx4kO7ubpxOJ8FgEIPBQHp6+qJ+iUQiYu4aGRnh+PHjjIyM0NPTw8TEhLAGKpszxSJ/OxWeWCxGT08Pvb299PT04Ha7qa2tpaKigrq6Ourr68nJySE7OxuNRkN5eTk5OTnYbDaSk5NvyYZ3pfF6vbjdbnFEFIvFSEpKEo75eXl5Yj1NBCRJIicnh7q6OmZnZzEajVRWVoqxaLfbCQaD2O12kpOTicViwiKr/LuV3HKFx+/343K56O3tZWJiApfLhdlsRqvVMjk5iclkIjs7G71eL5QCxTwXiUQIBoOMjY0tUnj0ej1ZWVnk5+fz53/+59TU1NyyCVer1WIwGIhEIng8Hk6cOMHg4CAajQabzUZZWdk1n6HT6UhJSaG2tpZ7772Xt956S/gmdXR08M4775Cfn4/D4bglMtwISi6affv2cfLkSSoqKkQUxIULFzh79ix9fX243W6CwSClpaU89dRTNDQ0kJ+fz9///d9z/vx5Ojs7mZ2dZXJyEpj/LUwmExaLhbS0tISYpKampujt7cXn8xGLxbDb7RQUFFBXV7foOkmS0Ol05OXlUVNTw4ULF3A6nbz22ms88MADlJeXr5AEi9FqteTl5ZGamsr09LTYEV7t+pycnEW7MKvVyoEDB5ienl6k8Ph8Pnw+H//2b//GfffdR0NDw5ItnctFXl4eOTk5/NM//ZOw/KampmI2m694z+TkJCkpKRgMBmBeaUpLS2P79u2r0u9D8Y14++23+clPfkIwGBRzpM1m44477sDhcIh+8Xg8HDlyhKmpKZxOJz//+c/RarXMzs6KYyCPx0MoFMLtdi9y2L8dKEchu3fv5ne/+x0DAwMUFhby/PPPU1hY+AkfFZvNRlNTE2fPnmV8fFy8g4my8C8X/f39dHR08Oabb9Lb20skEiE9PZ3i4mJKS0spLCxMuBw8dXV1n5g7FxKPx0WUJMyPXaX/LBbLLe3DW6rwSJKEw+FAr9fz3HPP4Xa7mZ6exmw2o9FocLlcGI1GMjMz0el0nzgzPn/+PMePH2d2dpZgMIgkSZSVlfHQQw9RVlZGQUEB9fX12Gy2W/YjaTQa9Ho9KSkpWCwWNBoNwWCQgYEB4Vt0regA5Rk1NTXE43EOHDggnCmDwSBTU1OLjhZWElmWRfjj66+/TktLC729vbS0tAgNfOEO22q1otPpsNlsVFZWkpmZSXJyMjt27CA1NZULFy6IBTMpKQmr1cqXvvQlGhsbSUpKSojBeuHCBQ4fPozf78dkMlFVVUVWVtYVr1f68dChQ0xPTwsrSqKRlZXFQw89RHp6OqmpqUQiEfR6PQ6HY9H7qijvSiIzZXz6fD56eno4d+7couMRrVYr/AdycnKuqmjcKiRJIjU1VSzWiiKzEOXY7vTp03R1dQkriCzLwsJjMBhWpbNyIBCgra2NoaEhwuGw2PnX19dTW1vL5z//eZKTk8XvMjs7S2FhIYcPH+add94RvhULfV4sFgt2u53s7GwyMzNvm/Igy7LY2I6NjeF2u3n66aepqqqirKzsspZTg8FARkYGlZWVuFwuMY96vV5MJlNCbKRuhng8ztzcHC0tLezdu5epqSmi0SgGg4F169bxxBNPsHHjRgoKChJiDl0qc3NzzM7O0tvby9jYGDC/+VACQ251aoFbPtLtdjt2u53S0lL8fj9ut1tEAbjdbmF+XRitoziR7tmzh4GBAaFQmM1miouL+cxnPkN1dTX5+fm3uvniOMpkMgmzfzgcFn4Rign5Wi+dRqOhsLAQg8GwaIEIhUJMT0+LqIOV3qHE43E8Hg/d3d28+uqrjI6O4nK5xO9gMBior6+ntLSU+++/n8rKSlJSUoTJEuZ3a+vWrSMUCi2SR3Fc27lzJ6WlpSvuu6MwPDxMS0sLwWBQvGPp6elXvL64uJjk5GQsFgsulwun04nX602I/ltIWloa27Zto6Kigry8PMLhMElJSZSXl3/CorHw/VVy2+zbtw+Px/MJ5Uir1WK320lPT7/q73QrkSTpmpNjPB4nEolw7tw5Tp06xcjIiIhaMhqNWCyWJY3dRCQcDtPT0yOOoWBeCaitreXOO+/k05/+9KLr/X4/VquVqakp3nnnncv6UyqJ7DIzM29rXqKFCo+yidy1a5c4wrrcmNLpdKSmppKTk0NxcTF+v5/JyUncbjfAqld4lECPrq4ujh49isfjIRqNkpKSQnl5Obt27aKgoICUlJSVbuqSUTbT09PTjIyMiKhJo9GI1WpdpKDfKm7r1kbZUSmTrclkEscEC19qp9PJf/3Xf3HkyBH27t2LyWRiw4YNfP3rX6e8vJzGxsYVLcfg9/vp6+ujr6+PgYEBqqurb1gzdblctLa20tPTI8J+V2oCnp2dZWJigr/7u7+jq6uLCxcuiJ1geXk5+fn5PP7441RVVVFXV4fNZsNoNKLRaBb1Xzwep7W1ldbWVuLxuDhzfvTRR1m/fj0bNmxImKiCaDSK2+0Wx6Y2m4377rvvqsdTqampaDQaTCYTsViM7u5uenp66OvrIzs7O2F8sfLz83n66aeFL0c8Hkej0ZCUlHTZRUQJu//ggw84ceIE+/fvZ3p6etHimJWVRV5eHs8///xtTxp2vfT29tLc3MyLL75IS0sLoVBIWBm/+MUv8tBDD5Gbm7vSzbwhvF4vH3zwgUisaLVayc/P52tf+xrFxcWfuF6r1ZKenk5aWho2mw2/37/oqBLgiSee4POf/zwbNmy45UcLCoqy09/fz6uvvorX66WsrIy0tDSxwbzSfbFYjBMnTvCb3/wGj8dDSkoKp06dYteuXXzhC1+45W2/lfT19fHSSy+xb98+4f9qNpupra2lqqqKkpKSW64cLCfBYJDZ2Vn+4z/+gxMnTnDq1CmCwSCyLJOXl0d9ff1tSRx5WxUejUazaGd56cIuyzITExP09/dz+vRp+vv7CQaDlJWVUVpaKvwFVto5VFkolZDQpYZCKrtjvV6PwWAQEWher5dAICCiaG43SuoAp9PJwMAA586dY3h4mEAgIHbCNTU1lJWV0djYSGFh4RWta9FoVDhGjo2NieMDs9lMWVkZNTU1Yme90ij9GAgE8Pl8yLIsHF6vppApli673U5KSgpTU1O43W6mpqZIS0tLGIUnKSlpSX5h8XicyclJJicn6ezs5OzZs7S0tDAxMSECCJKSkjCbzVRWVgon0pWy7lwLxaF3cHCQ1tZWBgcHmZiYAOZDeQsLC6msrKS6unrV1rGLRqPMzMwQDAYByMjIIC8vj8LCwk/kMlFSFPT29jI1NbVojjEYDJhMJux2u/hNLBbLbTvmi8fjzMzMMD4+Tm9vLzabjaKiIqxW61XnCGXcKtm03W43NpttkS/TaiUSiYiN8Pj4OKFQCJg/+qmvr6ewsHDVvLexWAy/34/X62V6eprz589z7tw5EcAC8/5YivP1rSahDq8jkQgvvfQSZ86c4aWXXsJms1FVVcWf/Mmf0NTURG1tbUIslHq9HqvVKo7rlmqRUY6zsrKymJiYwOl0ijBuJWfBSqCEgr711lsil47itFhUVERZWRl//dd/TVlZmbBuXAmPx4PT6eTDDz+kvb2dWCxGcnIy2dnZ3HnnnezYsSNhzM1KpNzU1BQjIyNCuSsvL7+m0qLVarnjjjvQaDTs3r1b5OXJyspadWUKAoEAL730Eq2trbz//vvCaXWh305+fj719fU8++yzNDQ0JHSGacX6sX//ft54441FiRWLior44z/+Y+68807y8/MT6gjyZti2bRubNm0iLS1t0WKopAZpaWnh61//OlNTUyI3j06nIzMzk9raWp566im2bNmCw+G4rf06NzfH0aNHOXnyJKdPn+Y73/kOzzzzzDUjj/x+P93d3YyMjDA9PQ1Aeno6n//856msrLxdzV92lI1nZ2cn7777rlBoYd5Z/2//9m8Twjq+VJTs0E6nk9HRUbEBicfjwoesrKyMbdu23ZbjuRVXeBTTZFdXF729vRw+fJihoSEKCwupqqpi48aN1NbWrlj4nZLTYnBwkN7eXqLRKElJSULZUZw9l4Ki8GRmZpKeno7T6RTfKWH5K4GSvbq5uZm2tjbi8Tjp6enCqlZdXU12draIrrscit+H8jsFAgEhj91up6amhrS0NAwGQ8IsMj6fj87OTuFwnJ2djcPhWFJ/SpJEdnY2WVlZaDQa/H4/g4ODiyaoREXxbQmHw5w8eZK+vj72798vahUpTrBKZfiamhrq6+vZunUrRUVFwqk5kVBq1LW3tzM8PMyePXtE3qdIJIJGo8FisWA2m8Wco4TYS5K04lbj5WLh2HK5XLhcLt577z3a29uZmpoS1oKkpCRSUlJoaGigvr6e9evXk5GRcVv7VZZlQqEQzc3N9Pf3izpo19rUxuNxcfy6MJpMp9OJJKGrkZmZGVwuF2+88QanT58WFv+kpCTuvvtuGhsbF0UaJjLxeJyOjg4GBwd56623RJ6kqampReucJEn09/dz4sQJ6uvrSUlJEakxboUCtOIKTzweJxwOc+zYMd5//33effddZFlm586d3HfffTz++ONkZmauWGG4SCSCz+eju7ubc+fOMTc3h8ViEblYricVtuI7kZOTw/j4uEhkuNJMTExw8uRJjh8/zvnz5zGZTOTl5fHAAw+wfft26uvrRbTdlVDyfHR3d9Pc3Izf7xem8+zsbDZu3EhGRkbCOCrDvDXq1KlTTE5OCqfyoqKiJSlkGo2G/Px8nE4nkiThdruFopfIKMd4Si6ll156iSNHjtDV1SWOaeFjZ3273c6uXbu48847uf/++xMmd9KlBINBZmZmeOeddzh//jwffPABs7OzYoFXonpSUlIIhUIEg0GCwSAul0vkIUpEuZbK5Y7XR0ZGOH/+PD/84Q/FZk3BYrGQnp7OXXfdRX19PRs3blyRNgcCAQ4dOoTH48HhcFzTsqpkqPf5fAwMDCzKL2UwGEQusNXI+Pg43d3d/OAHPxDO6AaDgeTkZJ5++mkaGhowmUyrwsk+Ho9z7Ngxzpw5wwsvvEA4HL7iUeP58+fR6/UisamSdmZNKjxOp5MjR47w/vvvc/DgQex2O0VFRTzzzDOUlJSQmZm5okcgiuVF8bdZ65jNZr785S9TW1srqoGnpqYu+Uz//Pnz7N27F7fbLSrBb9++nbvvvjvhfD58Ph8dHR1MT0+j0WjIysr6RMj2WiEej9PZ2cnQ0BDvv/8+ExMTi2ouxWKxRTltLBYLjz32GJWVlTz44IOkp6cnpLIzMTHB6dOn2bdvH2fOnGFoaAifz4fX6yUWiwkFIBKJMDY2htfrZXh4mDfeeAOLxSLymjz66KOsW7eOxsbGhJNxKWRkZJCTk4Msy3R3d/Puu++KIpNKolNA1B184oknqK6uZsOGDSt2BKv4+01OTuL1eolGo0xOTjIxMUFaWho6nU5Y2BW/QJfLxfHjx+nt7eXQoUMia3ZWVpbIOJxIm6qloFgbX3nlFQ4fPrwom/I999zD1q1b2bp1K7m5uatC2YGP/XEnJiZEotlLSUpKwmKxMDw8jNPp5OzZsyI7+vbt23nkkUeoqKhYVgV2xRQeJUTN6XTS0tJCT08Pw8PDbNy4kaKiIqqqqkhLS0Or1S7SDBXH39u1KClOxQs1VCUPiV6vF+bxWCwmQssBUbfn0nDzcDiMz+cTL7SiUCm1wmKx2G2vy6TT6TCbzdjtdubm5ti4cSM1NTVUV1cv+RnKbk1xfFaKxVVUVFBWVkZhYeGKWemuxNzcHNPT0+JYQzmmXGsKTzQaJRwOc+HCBTo7O9m/fz/j4+OMjo4uuk7JTeNwOHA4HGzZsoWqqiqqqqoSVgnwer20trZy+PBhDh06JD5XxpByhKrU0lJygS20hihHkwaDgdLSUjG2ExnF7L/weCMejzM9PU1/fz+HDx+mra2Nvr4+QqGQiCrMzs5m3bp1bN26lbq6OnEkuxIoc59ytOjz+RgfH6evr49wOCwSvioRPhcuXGB8fJwzZ84wMjLC8PCwOEI2GAwir1eivqtXQvEl7Ozs5MyZM4vqTubn59PU1LSqLVeAUHiSkpLQ6XRotVosFgvZ2dm4XC58Ph/T09PE43Hi8TjJyclUV1eTkZEhCgIvByum8AQCAV555RVOnDjBL3/5SwKBAHq9ngceeIDq6mpR5PDSl9disVBQUCB+uFtNa2srb775JkNDQ+KzoqIivvrVr1JeXi78ViYmJjh+/LjYSXV1dTE5OcnZs2dFaLeC4qGuKFCyLPPee+8xNjZGQUEBNptNJGK8HYO3tLSU9PR0KisrCQQCbNu27bqTyY2OjvLqq6/S0dFBMBjEZDKRn5/PV77yFUpLS7Hb7Qk9EWk0GjZv3kxTU1NCt/NGUFL1//M//zMXLlxgampqkUOyQmlpKU8++SQbN26kqqqKnJwckpKSEvr36O/v5z//8z8X+cMpEXQWiwWr1bpo7CmFR2dmZvB6vUiShMvl4he/+AXnz59neHiYJ554YkkZ1FcSu93Oo48+ytGjR9m/fz/79++nvb2dN998E6fTybFjx8QcI8syDoeDxx57jLvuuouHH35YREquZN8q0Y45OTmEQiEGBwf5/ve/z09/+lMKCwtJSkoiEomIKJ/Z2Vk0Gg333HMPTU1NPPnkk/z2t7/lwIEDjIyMkJGRwezsrDgeWS243W4GBgaEpWNhMk0lEWSiK+CXotVq+dSnPoXD4WDfvn1ik79p0yaKioooLi6moqKCBx98kOPHjwt/n+HhYd5++23a2tr41a9+xczMDNXV1WzdunVZlJ6beisWVke9dAL1+XyiBtalodZKAsKjR4/S0dEhkkXpdDqGhoaIxWLCVAnzi5FOpyMrK4uCggIKCwtvptlLRjGxtra2ipo9MD9pTk5O0tzcTGdnJ8PDw0xPT9Pe3i402aGhIZHfJRKJXNNqMDo6ilarZffu3WKyrqyspKCg4JZPSkpukuLiYiKRCBaLZckDLB6PMzU1xcDAAK2trUxMTBCLxaiurmbdunVCgUvkRRM+ztybmpq65iw8ExMTYnes1MdaiMFgoKGhgXXr1tHU1CRqFK0Gvxar1Up9fT0WiwWn0ykShFZWVopISvjYmTcUCjEzM8PAwICoMB4KhZidnWVoaIhTp05RX19PcnLyilo/roXihK1EZCnHIErJmkAggE6nw2AwkJ2dTVFRkbDYKcVwVxrFSrVlyxYsFosocOv3+zEYDBiNRmRZRqfTYbVaRbmUpqYm7Ha7yOoOCMvAaquWHo/HmZiYoK2tDbfbLdqfmpoq6rxlZGSsKgUOPq6yUFFRwaOPPiqqp2/YsIGsrCyys7NFOaWKigrxnubl5TE0NEQkEqG/v59jx44xPT1NbW2tqFhwM9zUr6iYIicnJz/hrHn+/Hn6+/tFfaKFKBlCT5w4IZwKYV7B+O1vfwuw6HMlB8hjjz3Gli1buPPOO2/5gI3H44RCIXp6enjvvfeAjyfNyclJ3nvvPQYHB3E6nZddRBSU46xrLaJdXV10dXWxd+9erFYrRUVFPPfcczz55JO3PDpNyZJ8I05ic3NzNDc3c/DgQd58803m5ubQaDR87nOfo7GxkcrKylVz7pyWlrYm6/Eo/g6Tk5OXratltVr51re+RWVlJTU1NSvQwhunqqqK73znO7zzzjucOnWKgoIC8vPzefTRR7Hb7Z+o8aUoPMePH6e1tVVkE5+amqKrq0skAA0Ggzz44IMJm+9EkiRRfxD4xPEkfByJtWvXLtavXy/CvRMFnU5Heno6zz33HB999JHY4StHjkq5jPLycjZs2MD27dspKCigoKCA2dlZ+vr6VlWm4UtRHLA7Ojp46aWXFvVhbm4uX/ziF9m+fXvC1Oi7HiRJIi8vj7y8PHbs2HHVa5Vjc5jfnKWmprJnzx5effVVWlpayM7O5qGHHkKj0dx0zb6bUnhOnz7N7t27GRsbY3Z2dtF3MzMzIh32pQqP1+sVmT4VjVY5wklJSRHps5OSkjAYDJSUlOBwOGhsbCQnJ+cTmZlvN16vl5aWFvx+P4FA4LLHA6mpqSIqy2QykZGRIapWKxEVC61GC1lY2XilQtWXwuzsLG63m7a2Nnp7e8W5u8VioaqqioqKioTYSf6h43A4qKyspKWlhXg8zuzs7KLdcDAY5K233qKvr49oNEpubm7COZhfCaVq9P333y8sPUrqh8uZwJUcWuvXryc3NxebzUZ3dze//vWvmZ2dJRwOc+rUKSKRCPfee2/CKjyK9fnSeRfmAw8cDgcbN26kurqabdu2JazDq5ISoL6+nm984xtMT0/j8/lEMVvF+qw4Za/mciCXEgwGaW9vp7W1lfb2drxeLxqNhoKCAjZs2CDKR/whoQQXLIy+W05uSuHp6enhjTfeoL+//7IDT0ExN37ij+t0IvJDebltNhuZmZls3bpVFOxsamoiNzeXvLy82/aiK8d1l2u33+//RDVhJYu0UmZBqfyq1+uxWCwUFxczPDzMxMQE4XBYOOJd+nyNRoMsy8zNzS2KMklEfD4fk5OTwuE8EomIyamoqIi8vLxVZS250nt6OZTClIncPwpKdeXs7GzhwKxk147FYoRCIQ4fPozH4yEvLw+DwSAi8xK9//R6vbDMLQWl+G1JSYmomab46Sm5ibq7u0XAQSKi5Lyampr6xDykBFQUFxezfft2tm/fzrp16xIm+/elKBvC0tJSsrKyhNKpKKxXyjmz2jdSSi4hpajt4OAgMG+VKygooKKigqamplV3lHUzKOvexMQEPp9PnIws5xx0U7/mXXfdRUZGBvv37xfZExeieOG7XC72798vFgebzYbNZmPHjh3k5uaKcgPJycnk5ORgMpmwWCzC414JNbydWv3s7CwfffQRFy5cuOa1ZrMZq9VKY2Mj+fn5lJaW0tTUJJLYKWfpSnK0wcFBzp07x3e+851Fk6pOpyM3N5e6ujqefPJJNm3adM1K7CvJ73//e44fP87u3btFccI/+qM/4tFHH6WsrCyhzOfXQpZlent7hd/HUibU6elpZmZmEl7pqa2tpbS0lLvuuks4lw8MDNDb28vg4CBer5f+/n4mJyc5d+4cmzdvpq6uji984QtkZWUlTGbs5UaSJPLz8/F6vUIZ9Hg8YkOSaP2qLAivvPIKLS0tvP3224s2mgaDgZqaGtavX89TTz0lisYmqpVqIYp1Pzk5WfjtJOq8d7PE43FOnTpFR0cHP/vZz4Syo1gmv/a1r1FdXb0iiXZXClmWGR4epqOjg4MHD4pSMKmpqSIlxnKs/zel8KSlpVFTU4Pb7cbhcHzCIiHLMi6XSzQ2Fouh1+vJz88nLy9PKAjV1dWYzWZMJhOZmZkJsVBGIhGhaV6KEl2gZAZVqkY3NTUJhaeuru6ymUuV2lJut/sTL7Ner6e6upq6ujqR+TQRX3gllHRwcJCuri6mpqbQ6/Xk5ORQWlpKbW0tycnJCdn2hSjHG0lJSciyzPj4+KIoiashyzKzs7NiwVEc6xNR5uTkZJKTk0XxyIGBAdLT00V5CKfTyfT0NG63G5/Ph9lsJhKJsH79eiKRCCUlJat+R30lFOdYJaQZVjbr+eVQfD1cLhdTU1OcPXuW9vZ2pqenFxUA1el0ohRMZWXlIqfe1YBWq10TR1XXIh6PMzIyIgpQK6U+8vPzKSkpobKycknW8bm5OVGcORHnneslGAzi8/lwuVzCJ7igoECU+lkOa9dNPcFisZCSkkJ+fv5lJ4hIJMLvfvc7YrEYkiSRnJyM3W7ny1/+Mlu2bGHLli3CgqF0WKJ03NzcnChKdylms5n8/HzuuusuNmzYQFVVFRkZGVRUVIj8H5dWEF8KFouFb33rW5SWlpKXl5ewi4zf72d6epqOjg7a29uJRCLk5uby4IMPUl9fT1ZWVsL049VIS0tj69at9PT00N7ezpEjRwiHwzz00EPXnHiVHcnw8DDxeByDwUBKSkrCm6DT09P58pe/LI62XnvtNc6ePcuvf/1rPB4PoVCI06dP09raytTUFI2NjXz7299O+PD0myER55+FhEIhXC4XL7/8Mh988AFHjx4V/pELSUpK4uGHH6a2tpaysrKElOUPHSXT+fHjxzl9+jRjY2Ni/vjqV7/KPffcQ2Nj45KsquPj4wSDQUpKSla9NUiWZcLhMIFAQFhZNRoNX/3qV9m5cycFBQXLYgi56dlZSUG/cHcUjUYZHBxkdHSUQ4cO0dXVhclkoqysjI0bN7JhwwaKi4sxGo0Jq9EbjUYqKiro6ekRn+l0OnJycigpKWHnzp1UV1dTWFhIVlYWZrP5pk3/sViMgYEBzGZzQjqrKZFr7e3tHDp0iP7+fubm5sjJyRFnzqspU3FKSgo1NTXk5uaSmpoqkvEplsirEY/HGR0dFROWzWajoqLiuvMXrQRK4i+dTkd9fb2oMj0wMEBLSwter5dgMEhvby96vZ7jx4+L3BlrCcUCPTExQTAYFMEHyhH1Sit4SnLWvr4+PvjgA44cOUJPTw+zs7OXTdMfj8fxeDz4/f5VMwb/0Ojs7BR1C5UgAaVocVpaGna7fcmWYiUtwe1OVHsrWLiBlGUZq9VKZmYmhYWF5OTkLJuesOzbUcUJsq2tjWPHjvHaa6/hcrlElNVXvvIV6urqEj4KJDk5maamJlpbW8XEp9frqaysZNu2bTz77LMkJycvq39DJBLh7NmzGAwG7rjjjmV77nIRi8Xwer0cO3aMH//4x4yPjxONRikpKaG2tpYdO3bgcDhWuplLxmq10tDQQHFxMXa7naGhIaxWK5FI5JpJ2eLxOAMDAwwMDADzlpMNGzasmsKFkiSh0+loamqirq6O/Px8zpw5g8/no6+vD7/fT09PD4FAgD179rBjx441qfCMjIwwNDSE3+8X/nQ2m+22F9K8HPF4XERB/vjHP8bpdF7W4qygHMverjxlKtfPyZMneeeddzh69KgoWmw0GklPT8dut1+Xoq3kmFoLxONxenp6uHDhArIsk5GRQV1dHcXFxWRlZS3b31l2hefcuXP85Cc/obOzk8HBQdxuNzk5OTz77LOsX7+eurq6VbEoKBlAH3/8cbKzs4F5haesrIzs7GxSUlJuWOs0mUykpKRgs9lEgkaY73QldD2RkGWZwcFBRkZGeOeddzh58iTj4+OEw2GSk5PZvHkzjY2N5ObmrioHV8XvprCwkA0bNvDhhx8yODjIT3/6UzZt2sRdd9112fvGxsYYGRkRNajy8/OpqKigtrZ2VVbd1uv1lJeXo9frCQaD/O53v2NsbAyYTy/x2muvEY1GKSoqIj8/PyFznwQCAQKBAGfPnhWh9ZmZmWLsXu56j8fDv//7v9Pa2srQ0JDI/bVjxw7uvPPOFS+FEg6H2bdvH8ePH2d0dFTkUEpJSSEtLU200Wg0snv3brGAqiQe4XAYt9uN0+lkYmKCaDQq8hA1NTVxzz33UFtbS1pa2oor2rcbj8fD9PQ0x48fp62tjVgsRnp6+i2ZT5dN4ZFlWRR427dvn9iN2O12CgoK2LJlC0VFRQlv2VHQaDQiH5AywSvZno1G402dJyYlJZGcnExqaqo4t4SPf8OFjoiJgCzLjI2N0dPTw7Fjx+jv7xfhsJIkCWdYo9G46garRqPB4XBQWlrK0aNHmZ2d5fjx49hsNnGWrpiMleNap9NJb28vfr8fjUZDRkYGmZmZpKenJ+wR7dWQJEmYkC9VaMLhMD09PQwMDDA5OZmwFjwlRUJbW5tI6aDX6y+r8CiWk5GREU6cOEFHR4eoTJ2amkpZWRnV1dUr7o8VjUbp6+sTBVFh3rE3IyODgoIC7rjjDhG6feTIEVXhSWCCwSDDw8NMTk7idruJRqOinlRBQQGNjY0rXih7OZBlGb/fTygUIhaLodPpRKb9Kx27zczMMDg4yODgIOPj4+j1eqE3LPemY9lGdCgUEhXP+/r6kCQJm83Gd7/7XTZs2EB9fX1CRF9dD0pmx4XVhG92QZMkSSwsFRUVSJJ0VTN1IqBU8m1ububIkSOLFLJoNEpbWxtGo5GmpiZSU1NXVWQIwM6dO2loaODkyZO0tbXx9ttv4/F4RF0xJaW9z+ejv7+fl19+mb179zI2NobVauW+++6jqqpqxRfIm2ViYoL3339fhMkCIh+Nz+fD6XQmbNbXDz74gPfee499+/ah1Wp5+OGHuf/++z9RAFfZaf/qV79i9+7dolAlwLp167j33nvZuXMnNTU1Kz5fRSIRuru7GR4eBuatzmazmb/6q7+ivr6empoahoeH6erqumK+GpWVJxqN0trayj/8wz/Q0dEhcpalpKSQmZlJRUUFW7ZsWRX+f1cjGo0SCAT49a9/zZ49exgZGaGoqIjvfe972Gy2K1qGX3/9dV5++WXOnTuHJEls3bqVXbt28cQTTyx7wdRlmaEDgQDT09M0NzfT09NDLBajrKyMkpISqqqqRLHP1ehYpSQTXO5nJiUlkZGRwfj4uPg8Go0yPj4uSgAoSRlXEo/Hg8vlore3l6GhIcLhsAjFT01NxWw2k5KSIrKfrnR7bwRFnjvvvBOz2cyRI0cYHx/n2LFj+P1+MjMzMZvNBAIBxsfHaW1tFcqOsjvLz89faTGuirLz8vv9DA8Pi7o0SgLCmZkZOjo66OzsXKSAK4n9srOzcTgcCbuwKlFnPp+PeDxOZ2en2FgsxOfzMTw8zJkzZ+jv7xfZwTMyMqisrGTjxo0i70ciEI1GhYPywqKLBQUFpKSkEAwGuXDhwidK+/whEg6H6e/vR5blhFEeotGoKN7b19fHzMwMkUgEo9FIRkYGW7dupby8HJPJtCqtwwtR/AKVNApjY2OEw2EOHz4s3l2bzYbBYCAUChEMBnG5XPT39zMyMiKO+LZu3UplZSUWi2XZN5HL8rSJiQl6e3t56aWXGBsbQ5IkHnjgAT7zmc/Q0NCwKv0abjVJSUmUlpYuUngikYg4TvF6vYuKA64Uvb29tLW10dzcTH9/PwDZ2dnU1tZSVVUlMtzm5OSI7LyrDY1Gg8lk4rnnnqOtrY1vfOMbjI6O0tzcfNV77r77bhobG3nqqacSVhGAj7OGDw8P09vby4svviiymivVqE+cOMH09LSo56NsTpKTk9m0aRObN29m8+bNCSun2WzGZrOh1+uZnJzkgw8+YHh4mPb29kXXOZ1OTp8+TTgcFpZKu93O5s2buf/++/nsZz+bcMcKSiTsvffey2OPPUZDQwOpqanEYjG6u7tFPbA/dDweD++//z47duxIGMftUCjEu+++KyqCKyg+Kn/5l38plIDVjpLFXClWe/ToUbq6uvjud7/L9u3beeihh7jjjjtIT08Xis6hQ4c4c+YMTqeTwsJC1q9fz7PPPovVar0la99NrU7K7vDDDz/k9OnTTExMYLVaeeCBB9i2bRvV1dUrvmAnKikpKWzevJmpqSmOHz8uQkkbGxtFls2VspbE43Fh+j958iQHDx7E6/Wi1+vJyMigqamJT3/60xQWFgozpdVqRafTrUoLD8wvKikpKZSVlfFnf/ZntLe3c+bMGXp7e3G73QSDQYxGI5mZmZSUlFBQUMCnPvUpSktLE1rJi8fjtLW10d3dzd69exkdHaWzs1OUdVH8kpSq4TBv1TEYDGzatImysjIeffRR4dScqFba2tpaDAYDzc3NyLLM1NQUTqeTM2fOLGpzIBAgHA4jSRJGo5Fdu3ZRUlLC3XffLao2J5qMSiLEnp4ePvroI9xuN3q9nvHxcU6ePElvby+BQACLxcLWrVs/cYz3h4Lib5Yo8nd2djIwMMCePXvo7e0VnyclJfGpT31KKK5rQdlZSFFREZs2bWJ4eJiRkRGGh4c5evQoU1NTtLW1Ybfb6evrw+l00tnZyfDwsJhvNmzYgMViuWWbjpuaqZWaLs3NzXz00UeiFs+9995LfX19wpv5VxKj0ci6devo6OjA4XDgcrnQaDTU1tZSUlKyospDLBZjdnaW4eFhzp07x4kTJwgGg+j1ejIzM6mpqeG+++4jPT19TSm0JpNJRObl5uai0WiIRCJoNBo8Hg8pKSkUFhZyxx13sGHDBh555BHS09MTboFUUPxvOjs7+eijj3j11VdFyvZLUd41nU6H0WjEbDaLEhMPP/xwQhyvXg2lLlZxcTFutxuPx4PH4xHHcwv7SKvVotfrSU5OZseOHdTV1bF9+/aEzQumOMwrVseZmRlisRg9PT0MDQ0JK3F6ejo1NTUJY924lVwuuatSUDVRolxHRkbo7Ozk/PnzuFwucWxlMpnYunUrGzZsIDk5OaHH1Y2gBAoMDg5iNptFbq/+/n7GxsZITU2lr68Pt9vN8PAwycnJWCwWamtrRZb+WzUOb0rhaWlpYe/evRw4cICenh7sdjvl5eXce++9yxo7vxZRIkiefvpp7r//fpGN2maziVIAKzEQotEo3d3dHDlyhH/5l38RYfJKUdcHHniAxsZGHA5HQls2bhSdTofD4eDee++lqakJv99PJBIhFosJ3yuz2Syi7BJV2YH58PnDhw/zyiuvcODAgStG8Wi1WhwOB3a7neLiYjZt2kRtbS0NDQ3Y7faEtHpcisFgwGq18swzz7BlyxZ+85vfMDo6ytDQ0KLrLBaLCBgoLi7mkUceobCwELPZnHALj9IvikKjLBiKFSscDovcQampqdjtdpKSktbkuLwUo9FIXl6e8CVUSqLs2LGDsrKylW4eAJs2baK+vp777rtPFKJWsnrn5eVhMpkS7p1bDjIyMrDZbOTk5NDa2iqskh6PhzNnzmAymairq0Ov1zM8PMyuXbu4++67eeyxx8jKyrqlm46bGhmxWIxwOEx6errIfbFu3ToyMzNXPIdFoiNJEnq9HofDkVChvvF4HK/Xi9PppKOjQyzuhYWFFBQUiMzEieLUudwo/WK1Wpc9QuB2E41G8fl8BINB5ubmFtUIU2pIKTXsysvLycjIoLS0VByr5ufnJ5w/y5VQHCZLSkrQarVs3LiRnJwcsfFSFDYli3lZWZnI4pqoecG0Wi1FRUX4/X4RMDA3N4fX6xUFNpOTk8nIyCAvL4+ioqI14fy6FHQ6HWazWWTvV4ILlBpiiYDFYsFisSRMe24Xer0evV6PyWRidnaWxsZG3G63SGViMBiora3F6/Wi1WppbGxk/fr1ZGdn33J/X+kahRKv+qXT6WRwcJBQKIRWq6W+vv6mc9QsM0vZliZWSeTrZ1llDIVC7Nmzh48++ojvfe97NDQ0UF1dzQMPPEBJSQnbtm1bieM2tR9vQD7Fx+PEiRO0trZy4MABccRTUFBARUUFGzdupKioiAcffBCr1UpqaqqITFxmq85t6UPF30UpZHxpjT9lh63It8zWkGWVUZZlvF4vY2NjnDx5kr6+PkZGRjh48CB+vx+73U5ZWRnr1q3j/vvvp6SkhNzc3Fut8CTUWFSsr7Isi/5chsjaZR+LCcZt60NZlsVmS9E1lPGnjE+lz5b5vb2sjDc12s1mMzk5OcRiMeGh/Yewu1jLaLVaiouLRWhhfn4+DoeD6upqEa6b6McbKvOYzWZKS0vR6/WUlpaybt06Eb5st9txOBwUFBSQlpYm/LESaLNyQ1xa2281I0kSJpOJzMxM6urqyMnJwe12U1paytzcnLDuKFExdrt9TR6RXA3FmqCSmEiSlFBW4puy8KwCEmo3cotQZZxnrcu41uUDVcbVgCrj2pcP1qiMf1jbARUVFRUVFZU/SFSFR0VFRUVFRWXNc60jLRUVFRUVFRWVVY9q4VFRUVFRUVFZ86gKj4qKioqKisqaR1V4VFRUVFRUVNY8qsKjoqKioqKisuZRFR4VFRUVFRWVNY+q8KioqKioqKisef5/UA9Ds8zZV9kAAAAASUVORK5CYII=\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": "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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.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 | -------------------------------------------------------------------------------- /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"]}]}]} -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | ![Image01](https://user-images.githubusercontent.com/35527874/95832687-9a89f800-0d75-11eb-9866-d1067e594a78.jpg) 27 | ![Image02](https://user-images.githubusercontent.com/35527874/95832694-9e1d7f00-0d75-11eb-9705-a066dd48687c.jpg) 28 | ![Image03](https://user-images.githubusercontent.com/35527874/95832700-9fe74280-0d75-11eb-8418-34f5aef31b8a.jpg) 29 | ![Image04](https://user-images.githubusercontent.com/35527874/95832706-a1b10600-0d75-11eb-856a-8f10e192749a.jpg) 30 | ![Image05](https://user-images.githubusercontent.com/35527874/95832713-a2e23300-0d75-11eb-971e-8409fced8707.jpg) 31 | ![Image06](https://user-images.githubusercontent.com/35527874/95832720-a4abf680-0d75-11eb-93e3-03c8408eb658.jpg) 32 | --------------------------------------------------------------------------------