├── data ├── pkl │ ├── basketball_test.pkl │ └── basketball_train.pkl └── csv │ └── basketball_stat.csv ├── wikiml_mac.yml ├── wikiml_win.yml └── jupyter_notebook ├── 6.2_LSTM_텐서플로우.ipynb ├── 4.9_다중입력_로지스틱회귀_실습.ipynb ├── 5.다층퍼셉트론_XOR_실습.ipynb ├── 4.9_단일입력_로지스틱회귀_실습.ipynb ├── 5.퍼셉트론_AND_연산.ipynb ├── 5.퍼셉트론_XOR_연산.ipynb ├── 6.2_RNN_기초_텐서플로우_실습.ipynb ├── 4.6_보팅_앙상블_손글씨분류.ipynb ├── 4.5_베르누이_나이브베이즈_스팸필터_실습.ipynb ├── 4.6_랜덤포레스트_손글씨분류.ipynb ├── 6.1_CNN_MNIST_손글씨_예측모델.ipynb ├── 4.5_다항분포_나이브베이즈_영화리뷰_감정분류_실습.ipynb ├── 4.8_선형회귀_실습.ipynb ├── 4.9_소프트맥스_실습.ipynb └── 4.2_knn_농구선수_포지션_예측_실습.ipynb /data/pkl/basketball_test.pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wikibook/machine-learning/HEAD/data/pkl/basketball_test.pkl -------------------------------------------------------------------------------- /data/pkl/basketball_train.pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wikibook/machine-learning/HEAD/data/pkl/basketball_train.pkl -------------------------------------------------------------------------------- /wikiml_mac.yml: -------------------------------------------------------------------------------- 1 | name: wikiml 2 | channels: 3 | - conda-forge 4 | - anaconda 5 | - defaults 6 | dependencies: 7 | - appnope=0.1.0=py36hf537a9a_0 8 | - backcall=0.1.0=py36_0 9 | - ca-certificates=2018.03.07=0 10 | - certifi=2018.4.16=py36_0 11 | - decorator=4.3.0=py36_0 12 | - entrypoints=0.2.3=py36hd81d71f_2 13 | - ipykernel=4.8.2=py36_0 14 | - ipython=6.4.0=py36_0 15 | - ipython_genutils=0.2.0=py36h241746c_0 16 | - jedi=0.12.0=py36_1 17 | - jinja2=2.10=py36hd36f9c5_0 18 | - jsonschema=2.6.0=py36hb385e00_0 19 | - jupyter_client=5.2.3=py36_0 20 | - jupyter_core=4.4.0=py36h79cf704_0 21 | - libsodium=1.0.16=h3efe00b_0 22 | - mistune=0.8.3=py36h1de35cc_1 23 | - nbconvert=5.3.1=py36h810822e_0 24 | - nbformat=4.4.0=py36h827af21_0 25 | - notebook=5.5.0=py36_0 26 | - openssl=1.0.2o=h26aff7b_0 27 | - pandoc=1.19.2.1=ha5e8f32_1 28 | - pandocfilters=1.4.2=py36h3b0b094_1 29 | - parso=0.2.1=py36_0 30 | - pexpect=4.6.0=py36_0 31 | - pickleshare=0.7.4=py36hf512f8e_0 32 | - prompt_toolkit=1.0.15=py36haeda067_0 33 | - ptyprocess=0.5.2=py36he6521c3_0 34 | - pygments=2.2.0=py36h240cd3f_0 35 | - pyzmq=17.0.0=py36h1de35cc_1 36 | - send2trash=1.5.0=py36_0 37 | - simplegeneric=0.8.1=py36_2 38 | - terminado=0.8.1=py36_1 39 | - testpath=0.3.1=py36h625a49b_0 40 | - traitlets=4.3.2=py36h65bd3ce_0 41 | - wcwidth=0.1.7=py36h8c6ec74_0 42 | - zeromq=4.2.5=h378b8a2_0 43 | - absl-py=0.2.2=py_0 44 | - astor=0.6.2=py_0 45 | - bleach=1.5.0=py36_0 46 | - gast=0.2.0=py_0 47 | - h5py=2.8.0=py36h470a237_0 48 | - hdf5=1.10.1=2 49 | - html5lib=0.9999999=py36_0 50 | - keras=2.1.6=py36_0 51 | - libgpuarray=0.7.6=0 52 | - libprotobuf=3.5.2=0 53 | - mako=1.0.7=py36_0 54 | - markdown=2.6.11=py_0 55 | - markupsafe=1.0=py36_0 56 | - protobuf=3.5.2=py36_0 57 | - pygpu=0.7.6=py36_0 58 | - pyyaml=3.12=py36_1 59 | - tensorboard=1.8.0=py36_1 60 | - tensorflow=1.8.0=py36_1 61 | - termcolor=1.1.0=py36_1 62 | - theano=1.0.2=py36_0 63 | - webencodings=0.5.1=py36_0 64 | - werkzeug=0.14.1=py_0 65 | - yaml=0.1.7=0 66 | - cairo=1.14.12=hab642c4_0 67 | - cycler=0.10.0=py36hfc81398_0 68 | - expat=2.2.5=hb8e80ba_0 69 | - fontconfig=2.12.6=h9850fc5_0 70 | - freetype=2.8=h12048fb_1 71 | - gettext=0.19.8.1=h15daf44_3 72 | - glib=2.53.6=h33f6a65_2 73 | - graphite2=1.3.10=h337f25e_1 74 | - graphviz=2.40.1=h0a44026_0 75 | - grpcio=1.12.0=py36hd9629dc_0 76 | - harfbuzz=1.7.4=h08e020e_0 77 | - icu=58.2=h4b95b61_1 78 | - intel-openmp=2018.0.0=h8158457_8 79 | - jpeg=9b=he5867d9_2 80 | - kiwisolver=1.0.1=py36h792292d_0 81 | - libcxx=4.0.1=h579ed51_0 82 | - libcxxabi=4.0.1=hebd6815_0 83 | - libedit=3.1=hb4e282d_0 84 | - libffi=3.2.1=h475c297_4 85 | - libgfortran=3.0.1=h93005f0_2 86 | - libiconv=1.15=hdd342a3_7 87 | - libpng=1.6.34=he12f830_0 88 | - libtiff=4.0.9=h0dac147_0 89 | - libxml2=2.9.7=hab757c2_0 90 | - matplotlib=2.2.0=py36hfa7797c_0 91 | - mkl=2018.0.1=hfbd8650_4 92 | - ncurses=6.0=hd04f020_2 93 | - numpy=1.14.1=py36ha726252_2 94 | - pandas=0.22.0=py36h0a44026_0 95 | - pango=1.41.0=h3bae10e_0 96 | - patsy=0.5.0=py36_0 97 | - pcre=8.41=hfb6ab37_1 98 | - pip=9.0.1=py36_5 99 | - pixman=0.34.0=hca0a616_3 100 | - pyparsing=2.2.0=py36hb281f35_0 101 | - python=3.6.4=hc167b69_1 102 | - python-dateutil=2.6.1=py36h86d2abb_1 103 | - pytz=2018.3=py36_0 104 | - readline=7.0=hc1231fa_4 105 | - scikit-learn=0.19.1=py36hffbff8c_0 106 | - scipy=1.0.0=py36h1de22e9_0 107 | - seaborn=0.8.1=py36h595ecd9_0 108 | - setuptools=38.5.1=py36_0 109 | - six=1.11.0=py36h0e22d5e_1 110 | - sqlite=3.22.0=h3efe00b_0 111 | - statsmodels=0.8.0=py36h9c68fc9_0 112 | - tk=8.6.7=h35a86e2_3 113 | - tornado=5.0=py36_0 114 | - wheel=0.30.0=py36h5eb2c71_1 115 | - xz=5.2.3=h0278029_2 116 | - zlib=1.2.11=hf3cbc9b_2 117 | - pip: 118 | - autokeras==0.2.1 119 | - pillow==5.2.0 120 | - torch==0.4.0 121 | - torchvision==0.2.1 122 | prefix: /anaconda3/envs/wikiml 123 | 124 | -------------------------------------------------------------------------------- /wikiml_win.yml: -------------------------------------------------------------------------------- 1 | name: wikiml 2 | channels: 3 | - defaults 4 | dependencies: 5 | - _tflow_select=2.2.0=eigen 6 | - absl-py=0.5.0=py36_0 7 | - astor=0.7.1=py36_0 8 | - backcall=0.1.0=py36_0 9 | - blas=1.0=mkl 10 | - bleach=3.0.2=py36_0 11 | - ca-certificates=2018.03.07=0 12 | - certifi=2018.10.15=py36_0 13 | - colorama=0.4.0=py36_0 14 | - cycler=0.10.0=py36h009560c_0 15 | - decorator=4.3.0=py36_0 16 | - entrypoints=0.2.3=py36_2 17 | - freetype=2.9.1=ha9979f8_1 18 | - gast=0.2.0=py36_0 19 | - graphviz=2.38=hfd603c8_2 20 | - grpcio=1.12.1=py36h1a1b453_0 21 | - h5py=2.8.0=py36h3bdd7fb_2 22 | - hdf5=1.10.2=hac2f561_1 23 | - icc_rt=2017.0.4=h97af966_0 24 | - icu=58.2=ha66f8fd_1 25 | - intel-openmp=2019.0=118 26 | - ipykernel=5.1.0=py36h39e3cac_0 27 | - ipython=7.0.1=py36h39e3cac_0 28 | - ipython_genutils=0.2.0=py36h3c5d0ee_0 29 | - ipywidgets=7.4.2=py36_0 30 | - jedi=0.13.1=py36_0 31 | - jinja2=2.10=py36_0 32 | - jpeg=9b=hb83a4c4_2 33 | - jsonschema=2.6.0=py36h7636477_0 34 | - jupyter=1.0.0=py36_7 35 | - jupyter_client=5.2.3=py36_0 36 | - jupyter_console=6.0.0=py36_0 37 | - jupyter_core=4.4.0=py36_0 38 | - keras=2.1.6=py36_0 39 | - keras-applications=1.0.6=py36_0 40 | - keras-preprocessing=1.0.5=py36_0 41 | - kiwisolver=1.0.1=py36h6538335_0 42 | - libpng=1.6.35=h2a8f88b_0 43 | - libprotobuf=3.6.0=h1a1b453_0 44 | - libsodium=1.0.16=h9d3ae62_0 45 | - m2w64-gcc-libgfortran=5.3.0=6 46 | - m2w64-gcc-libs=5.3.0=7 47 | - m2w64-gcc-libs-core=5.3.0=7 48 | - m2w64-gmp=6.1.0=2 49 | - m2w64-libwinpthread-git=5.0.0.4634.697f757=2 50 | - markdown=3.0.1=py36_0 51 | - markupsafe=1.0=py36hfa6e2cd_1 52 | - matplotlib=3.0.0=py36hd159220_0 53 | - mistune=0.8.4=py36he774522_0 54 | - mkl=2019.0=118 55 | - mkl_fft=1.0.6=py36hdbbee80_0 56 | - mkl_random=1.0.1=py36h77b88f5_1 57 | - msys2-conda-epoch=20160418=1 58 | - nbconvert=5.3.1=py36_0 59 | - nbformat=4.4.0=py36h3a5bc1b_0 60 | - notebook=5.7.0=py36_0 61 | - numpy=1.14.1=py36hb69e940_2 62 | - numpy-base=1.15.2=py36h8128ebf_0 63 | - openssl=1.0.2p=hfa6e2cd_0 64 | - pandas=0.22.0=py36h6538335_0 65 | - pandoc=2.2.3.2=0 66 | - pandocfilters=1.4.2=py36_1 67 | - parso=0.3.1=py36_0 68 | - patsy=0.5.0=py36_0 69 | - pickleshare=0.7.5=py36_0 70 | - pip=10.0.1=py36_0 71 | - prometheus_client=0.4.2=py36_0 72 | - prompt_toolkit=2.0.6=py36_0 73 | - protobuf=3.6.0=py36he025d50_0 74 | - pygments=2.2.0=py36hb010967_0 75 | - pyparsing=2.2.2=py36_0 76 | - pyqt=5.9.2=py36h6538335_2 77 | - python=3.6.4=h0c2934d_3 78 | - python-dateutil=2.7.3=py36_0 79 | - pytz=2018.5=py36_0 80 | - pywinpty=0.5.4=py36_0 81 | - pyyaml=3.13=py36hfa6e2cd_0 82 | - pyzmq=17.1.2=py36hfa6e2cd_0 83 | - qt=5.9.6=vc14h1e9a669_2 84 | - qtconsole=4.4.2=py36_0 85 | - scikit-learn=0.19.1=py36hae9bb9f_0 86 | - scipy=1.1.0=py36hc28095f_0 87 | - seaborn=0.8.1=py36_0 88 | - send2trash=1.5.0=py36_0 89 | - setuptools=40.4.3=py36_0 90 | - simplegeneric=0.8.1=py36_2 91 | - sip=4.19.8=py36h6538335_0 92 | - six=1.11.0=py36_1 93 | - sqlite=3.25.2=hfa6e2cd_0 94 | - statsmodels=0.9.0=py36h452e1ab_0 95 | - tensorboard=1.11.0=py36he025d50_0 96 | - tensorflow=1.11.0=eigen_py36h346fd36_0 97 | - tensorflow-base=1.11.0=eigen_py36h45df0d8_0 98 | - termcolor=1.1.0=py36_1 99 | - terminado=0.8.1=py36_1 100 | - testpath=0.4.2=py36_0 101 | - tornado=5.1.1=py36hfa6e2cd_0 102 | - traitlets=4.3.2=py36h096827d_0 103 | - vc=14.1=h0510ff6_4 104 | - vs2015_runtime=14.15.26706=h3a45250_0 105 | - wcwidth=0.1.7=py36h3d5aa90_0 106 | - webencodings=0.5.1=py36_1 107 | - werkzeug=0.14.1=py36_0 108 | - wheel=0.32.1=py36_0 109 | - widgetsnbextension=3.4.2=py36_0 110 | - wincertstore=0.2=py36h7fe50ca_0 111 | - winpty=0.4.3=4 112 | - yaml=0.1.7=hc54c509_2 113 | - zeromq=4.2.5=he025d50_1 114 | - zlib=1.2.11=h8395fce_2 115 | - pip: 116 | - cython==0.29 117 | - html5lib==0.9999999 118 | - ipython-genutils==0.2.0 119 | - jupyter-client==5.2.3 120 | - jupyter-console==6.0.0 121 | - jupyter-core==4.4.0 122 | - mkl-fft==1.0.6 123 | - mkl-random==1.0.1 124 | - prometheus-client==0.4.2 125 | - prompt-toolkit==2.0.6 126 | - pydot==1.2.4 127 | - pydot-ng==2.0.0 128 | - pydotplus==2.0.2 129 | prefix: C:\Users\JH\Anaconda3\envs\wikiml 130 | 131 | -------------------------------------------------------------------------------- /data/csv/basketball_stat.csv: -------------------------------------------------------------------------------- 1 | Player,Pos,3P,2P,TRB,AST,STL,BLK 2 | Alex Abrines,SG,1.4,0.6,1.3,0.6,0.5,0.1 3 | Steven Adams,C,0.0,4.7,7.7,1.1,1.1,1.0 4 | Alexis Ajinca,C,0.0,2.3,4.5,0.3,0.5,0.6 5 | Chris Andersen,C,0.0,0.8,2.6,0.4,0.4,0.6 6 | Will Barton,SG,1.5,3.5,4.3,3.4,0.8,0.5 7 | Nicolas Batum,SG,1.8,3.4,6.2,5.9,1.1,0.4 8 | Bradley Beal,SG,2.9,5.4,3.1,3.5,1.1,0.3 9 | Marco Belinelli,SG,1.4,2.2,2.4,2.0,0.6,0.1 10 | Patrick Beverley,SG,1.6,1.8,5.9,4.2,1.5,0.4 11 | Bismack Biyombo,C,0.0,2.2,7.0,0.9,0.3,1.1 12 | Tarik Black,C,0.0,2.2,5.1,0.6,0.4,0.7 13 | Andrew Bogut,C,0.0,1.4,8.1,1.8,0.5,0.9 14 | Devin Booker,SG,1.9,5.9,3.2,3.4,0.9,0.3 15 | Avery Bradley,SG,2.0,4.6,6.1,2.2,1.2,0.2 16 | Kentavious Caldwell-Pope,SG,2.0,2.9,3.3,2.5,1.2,0.2 17 | Clint Capela,C,0.0,5.6,8.1,1.0,0.5,1.2 18 | Willie Cauley-Stein,C,0.0,3.4,4.5,1.1,0.7,0.6 19 | Jordan Clarkson,SG,1.4,4.4,3.0,2.6,1.1,0.1 20 | DeMarcus Cousins,C,1.8,7.2,11.0,4.6,1.4,1.3 21 | Allen Crabbe,SG,1.7,2.1,2.9,1.2,0.7,0.3 22 | Jamal Crawford,SG,1.4,3.0,1.6,2.6,0.7,0.2 23 | Jordan Crawford,SG,1.9,3.6,1.8,3.0,0.6,0.1 24 | Troy Daniels,SG,2.1,0.7,1.5,0.7,0.3,0.1 25 | Anthony Davis,C,0.5,9.7,11.8,2.1,1.3,2.2 26 | Dewayne Dedmon,C,0.0,2.1,6.5,0.6,0.5,0.8 27 | Andre Drummond,C,0.0,5.9,13.8,1.1,1.5,1.1 28 | Wayne Ellington,SG,2.4,1.3,2.1,1.1,0.6,0.1 29 | Joel Embiid,C,1.2,5.3,7.8,2.1,0.9,2.5 30 | Evan Fournier,SG,1.9,4.1,3.1,3.0,1.0,0.1 31 | Channing Frye,C,1.9,1.4,3.9,0.6,0.4,0.5 32 | Marc Gasol,C,1.4,5.8,6.3,4.6,0.9,1.3 33 | Pau Gasol,C,0.9,3.9,7.8,2.3,0.4,1.1 34 | Manu Ginobili,SG,1.3,1.2,2.3,2.7,1.2,0.2 35 | Rudy Gobert,C,0.0,5.1,12.8,1.2,0.6,2.6 36 | Eric Gordon,SG,3.3,2.2,2.7,2.5,0.6,0.5 37 | Marcin Gortat,C,0.0,4.8,10.4,1.5,0.5,0.7 38 | Danny Green,SG,1.7,0.9,3.3,1.8,1.0,0.8 39 | Justin Hamilton,C,0.9,1.9,4.1,0.9,0.5,0.7 40 | A.J. Hammons,C,0.2,0.5,1.6,0.2,0.0,0.6 41 | Tim Hardaway,SG,1.9,3.4,2.8,2.3,0.7,0.2 42 | Montrezl Harrell,C,0.0,3.9,3.8,1.1,0.3,0.7 43 | Gary Harris,SG,1.9,3.7,3.1,2.9,1.2,0.1 44 | Joe Harris,SG,1.6,1.3,2.8,1.0,0.6,0.2 45 | John Henson,C,0.0,2.7,5.1,1.0,0.5,1.3 46 | Roy Hibbert,C,0.0,1.7,3.2,0.4,0.2,1.0 47 | Buddy Hield,SG,1.8,2.2,3.3,1.5,0.5,0.1 48 | Nene Hilario,C,0.0,3.6,4.2,1.0,0.8,0.6 49 | Justin Holiday,SG,1.2,1.7,2.7,1.2,0.8,0.4 50 | Richaun Holmes,C,0.5,3.6,5.5,1.0,0.7,1.0 51 | Rodney Hood,SG,1.9,2.7,3.4,1.6,0.6,0.2 52 | Al Horford,C,1.3,4.3,6.8,5.0,0.8,1.3 53 | Dwight Howard,C,0.0,5.2,12.7,1.4,0.9,1.2 54 | Nikola Jokic,C,0.6,6.2,9.8,4.9,0.8,0.8 55 | DeAndre Jordan,C,0.0,5.1,13.8,1.2,0.6,1.7 56 | Frank Kaminsky,C,1.5,2.7,4.5,2.2,0.6,0.5 57 | Sean Kilpatrick,SG,1.5,2.9,4.0,2.2,0.6,0.1 58 | Kyle Korver,SG,2.4,1.1,2.8,1.6,0.5,0.3 59 | Kosta Koufos,C,0.0,3.0,5.7,0.7,0.5,0.7 60 | Zach LaVine,SG,2.6,4.4,3.4,3.0,0.9,0.2 61 | Courtney Lee,SG,1.4,2.8,3.4,2.3,1.1,0.3 62 | Alex Len,C,0.0,2.9,6.6,0.6,0.5,1.3 63 | Brook Lopez,C,1.8,5.6,5.4,2.3,0.5,1.7 64 | Robin Lopez,C,0.0,4.7,6.4,1.0,0.2,1.4 65 | Ian Mahinmi,C,0.0,2.1,4.8,0.6,1.1,0.8 66 | Wesley Matthews,SG,2.4,2.2,3.5,2.9,1.1,0.2 67 | C.J. McCollum,SG,2.3,6.3,3.6,3.6,0.9,0.5 68 | JaVale McGee,C,0.0,2.7,3.2,0.2,0.2,0.9 69 | Ben McLemore,SG,1.1,1.9,2.1,0.8,0.5,0.1 70 | Jodie Meeks,SG,1.6,1.3,2.1,1.3,0.9,0.1 71 | Salah Mejri,C,0.0,1.2,4.2,0.2,0.4,0.8 72 | E'Twaun Moore,SG,1.1,2.8,2.1,2.2,0.7,0.4 73 | Timofey Mozgov,C,0.0,3.1,4.9,0.8,0.3,0.6 74 | Jamal Murray,SG,1.4,2.2,2.6,2.1,0.6,0.3 75 | Victor Oladipo,SG,1.9,4.3,4.3,2.6,1.2,0.3 76 | Georgios Papagiannis,C,0.0,2.5,3.9,0.9,0.1,0.8 77 | Mason Plumlee,C,0.0,4.1,7.5,3.5,0.9,1.1 78 | J.J. Redick,SG,2.6,2.5,2.2,1.4,0.7,0.2 79 | Willie Reed,C,0.0,2.3,4.7,0.4,0.3,0.7 80 | Josh Richardson,SG,1.4,2.4,3.2,2.6,1.1,0.7 81 | Austin Rivers,SG,1.5,2.9,2.2,2.8,0.6,0.1 82 | Iman Shumpert,SG,1.2,1.4,2.9,1.4,0.8,0.4 83 | Marcus Smart,SG,1.2,2.2,3.9,4.6,1.6,0.4 84 | J.R. Smith,SG,2.3,0.7,2.8,1.5,1.0,0.3 85 | Jason Smith,C,0.5,1.9,3.5,0.5,0.3,0.7 86 | Tony Snell,SG,1.8,1.3,3.1,1.2,0.7,0.2 87 | Marreese Speights,C,1.3,1.7,4.5,0.8,0.3,0.5 88 | Nik Stauskas,SG,1.7,1.5,2.8,2.4,0.6,0.4 89 | Edy Tavares,C,0.0,2.0,5.5,0.5,0.0,3.0 90 | Garrett Temple,SG,1.3,1.6,2.8,2.6,1.3,0.4 91 | Klay Thompson,SG,3.4,4.8,3.7,2.1,0.8,0.5 92 | Tristan Thompson,C,0.0,3.4,9.2,1.0,0.5,1.1 93 | Karl-Anthony Towns,C,1.2,8.5,12.3,2.7,0.7,1.3 94 | Myles Turner,C,0.5,5.0,7.3,1.3,0.9,2.1 95 | Jonas Valanciunas,C,0.0,4.9,9.5,0.7,0.5,0.8 96 | Denzel Valentine,SG,1.3,0.5,2.6,1.1,0.5,0.1 97 | Nikola Vucevic,C,0.3,6.1,10.4,2.8,1.0,1.0 98 | Dwyane Wade,SG,0.8,6.2,4.5,3.8,1.4,0.7 99 | Dion Waiters,SG,1.8,4.3,3.3,4.3,0.9,0.4 100 | Hassan Whiteside,C,0.0,7.0,14.1,0.7,0.7,2.1 101 | Lou Williams,SG,2.0,3.3,2.5,3.0,1.0,0.2 102 | -------------------------------------------------------------------------------- /jupyter_notebook/6.2_LSTM_텐서플로우.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "import numpy as np\n", 10 | "from IPython.display import Image" 11 | ] 12 | }, 13 | { 14 | "cell_type": "code", 15 | "execution_count": 2, 16 | "metadata": {}, 17 | "outputs": [], 18 | "source": [ 19 | "inputs = np.array([\n", 20 | " [ [1,0] ]\n", 21 | "])" 22 | ] 23 | }, 24 | { 25 | "cell_type": "markdown", 26 | "metadata": {}, 27 | "source": [ 28 | "# LSTM\n", 29 | "LSTM은 gradient vanishing 또는 gradient exploding과 같은 기존 RNN의 단점을 극복하고자 만들어진 조금 더 진화된 RNN 셀입니다. LSTM 셀 내부를 살펴보면 기존 RNN의 단점을 극복하기 위해 이전 정보를 지우거나 기억하기 위한 로직과 현재 정보를 기억하기 위한 로직이 구현되어 있습니다. \n", 30 | "아래 그림에서 보시면 기존 RNN에서 보지 못했던 주황색 선과 조금 더 많아진 활성화함수와 수학 기호들을 보실 수 있습니다. 주황색 선은 메모리 셀이라고 부릅니다. 주황색 선상의 곱하기 기호에서, 0부터 1까지의 값인 시그모이드 출력값이 곱해지게 되어, 메모리 셀의 기존 정보를 어느정도까지 기억할 지 결정하게 됩니다. 주황색 선상의 더하기 기호는 새로운 정보를 메모리셀의 기존 정보에 더하는 로직입니다. 그리고 **h**t 선상의 곱하기 기호에서 메모리셀의 정보와 현재 정보가 함께 계산되어 상태값을 출력하는 것을 확인할 수 있습니다." 31 | ] 32 | }, 33 | { 34 | "cell_type": "code", 35 | "execution_count": 3, 36 | "metadata": {}, 37 | "outputs": [ 38 | { 39 | "data": { 40 | "text/html": [ 41 | "" 42 | ], 43 | "text/plain": [ 44 | "" 45 | ] 46 | }, 47 | "execution_count": 3, 48 | "metadata": {}, 49 | "output_type": "execute_result" 50 | } 51 | ], 52 | "source": [ 53 | "Image(url= \"https://raw.githubusercontent.com/captainchargers/deeplearning/master/img/lstm_detail.png\", width=500, height=250)" 54 | ] 55 | }, 56 | { 57 | "cell_type": "markdown", 58 | "metadata": {}, 59 | "source": [ 60 | "텐서플로우 사용 시, 이미 LSTM은 구현되어 있기 때문에 직접 위 그림을 구현하실 필요는 없습니다. \n", 61 | "텐서플로우 LSTM을 사용 시 아래 그림만 잘 이해하셔도, 사용에 큰 무리가 없습니다." 62 | ] 63 | }, 64 | { 65 | "cell_type": "code", 66 | "execution_count": 4, 67 | "metadata": {}, 68 | "outputs": [ 69 | { 70 | "data": { 71 | "text/html": [ 72 | "" 73 | ], 74 | "text/plain": [ 75 | "" 76 | ] 77 | }, 78 | "execution_count": 4, 79 | "metadata": {}, 80 | "output_type": "execute_result" 81 | } 82 | ], 83 | "source": [ 84 | "Image(url= \"https://raw.githubusercontent.com/captainchargers/deeplearning/master/img/lstm_cell2.png\", width=500, height=250)" 85 | ] 86 | }, 87 | { 88 | "cell_type": "markdown", 89 | "metadata": {}, 90 | "source": [ 91 | "아래 코드를 실행하여 LSTM의 출력값(y) 및 상태값(hidden state), 메모리셀(memory cell)값을 출력할 수 있습니다." 92 | ] 93 | }, 94 | { 95 | "cell_type": "code", 96 | "execution_count": 5, 97 | "metadata": {}, 98 | "outputs": [ 99 | { 100 | "name": "stdout", 101 | "output_type": "stream", 102 | "text": [ 103 | "output values\n", 104 | "[[[0.09927537]]]\n", 105 | "\n", 106 | "memory cell value \n", 107 | "[[0.18134572]]\n", 108 | "\n", 109 | "hidden state value \n", 110 | "[[0.09927537]]\n" 111 | ] 112 | } 113 | ], 114 | "source": [ 115 | "import tensorflow as tf\n", 116 | "tf.reset_default_graph()\n", 117 | "tf.set_random_seed(777)\n", 118 | "\n", 119 | "tf_inputs = tf.constant(inputs, dtype=tf.float32)\n", 120 | "lstm_cell = tf.nn.rnn_cell.LSTMCell(num_units=1)\n", 121 | "outputs, state = tf.nn.dynamic_rnn(\n", 122 | " cell=lstm_cell, dtype=tf.float32, inputs=tf_inputs)\n", 123 | "\n", 124 | "with tf.Session() as sess:\n", 125 | " sess.run(tf.global_variables_initializer())\n", 126 | " _output, _state = sess.run([outputs, state])\n", 127 | " print(\"output values\")\n", 128 | " print(_output)\n", 129 | " print(\"\\nmemory cell value \")\n", 130 | " print(_state.c)\n", 131 | " print(\"\\nhidden state value \")\n", 132 | " print(_state.h)" 133 | ] 134 | } 135 | ], 136 | "metadata": { 137 | "kernelspec": { 138 | "display_name": "Python 3", 139 | "language": "python", 140 | "name": "python3" 141 | }, 142 | "language_info": { 143 | "codemirror_mode": { 144 | "name": "ipython", 145 | "version": 3 146 | }, 147 | "file_extension": ".py", 148 | "mimetype": "text/x-python", 149 | "name": "python", 150 | "nbconvert_exporter": "python", 151 | "pygments_lexer": "ipython3", 152 | "version": "3.6.4" 153 | } 154 | }, 155 | "nbformat": 4, 156 | "nbformat_minor": 2 157 | } 158 | -------------------------------------------------------------------------------- /jupyter_notebook/4.9_다중입력_로지스틱회귀_실습.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# 다중 입력 로지스틱 회귀 모델\n", 8 | "2개의 입력을 받아 0 또는 1을 출력하는 로지스틱 회귀 모델을 케라스로 구현해보도록 하겠습니다. \n", 9 | "2개의 입력을 받아 1개의 출력을 내는 예제로는 대표적으로 AND 연산이 있습니다. \n", 10 | "AND 연산 로지스틱 회귀를 케라스로 구현해보도록 하겠습니다." 11 | ] 12 | }, 13 | { 14 | "cell_type": "code", 15 | "execution_count": 10, 16 | "metadata": {}, 17 | "outputs": [], 18 | "source": [ 19 | "from keras.models import Sequential\n", 20 | "from keras.layers import Dense, Activation\n", 21 | "import numpy as np" 22 | ] 23 | }, 24 | { 25 | "cell_type": "code", 26 | "execution_count": 11, 27 | "metadata": {}, 28 | "outputs": [], 29 | "source": [ 30 | "model = Sequential()\n", 31 | "model.add(Dense(input_dim=2, units = 1))\n", 32 | "model.add(Activation('sigmoid'))\n", 33 | "model.compile(loss='binary_crossentropy', optimizer='sgd', metrics=['binary_accuracy'])" 34 | ] 35 | }, 36 | { 37 | "cell_type": "markdown", 38 | "metadata": {}, 39 | "source": [ 40 | "모델을 학습시키기 위한 데이터를 생성합니다." 41 | ] 42 | }, 43 | { 44 | "cell_type": "code", 45 | "execution_count": 12, 46 | "metadata": {}, 47 | "outputs": [], 48 | "source": [ 49 | "X = np.array([(0,0), (0,1), (1,0), (1,1)]) \n", 50 | "Y = np.array([0, 0, 0, 1])" 51 | ] 52 | }, 53 | { 54 | "cell_type": "markdown", 55 | "metadata": {}, 56 | "source": [ 57 | "모델 학습을 진행합니다. \n", 58 | "5000번의 반복 학습을 통해, 최적의 w1, w2, b를 찾습니다." 59 | ] 60 | }, 61 | { 62 | "cell_type": "code", 63 | "execution_count": 13, 64 | "metadata": {}, 65 | "outputs": [ 66 | { 67 | "data": { 68 | "text/plain": [ 69 | "" 70 | ] 71 | }, 72 | "execution_count": 13, 73 | "metadata": {}, 74 | "output_type": "execute_result" 75 | } 76 | ], 77 | "source": [ 78 | "model.fit(X, Y, epochs=5000, verbose=0)" 79 | ] 80 | }, 81 | { 82 | "cell_type": "markdown", 83 | "metadata": {}, 84 | "source": [ 85 | "학습 데이터에 따른 실제 모델의 출력값을 확인해봅니다. \n", 86 | "(0,0), (0,1), (1,0)에 해당하는 값은 0.5보다 작고, (1,1)은 0.5보다 큰 것을 확인할 수 있습니다." 87 | ] 88 | }, 89 | { 90 | "cell_type": "code", 91 | "execution_count": 14, 92 | "metadata": {}, 93 | "outputs": [ 94 | { 95 | "data": { 96 | "text/plain": [ 97 | "array([[0.03742706],\n", 98 | " [0.21346988],\n", 99 | " [0.22765201],\n", 100 | " [0.6729292 ]], dtype=float32)" 101 | ] 102 | }, 103 | "execution_count": 14, 104 | "metadata": {}, 105 | "output_type": "execute_result" 106 | } 107 | ], 108 | "source": [ 109 | "model.predict(X)" 110 | ] 111 | }, 112 | { 113 | "cell_type": "markdown", 114 | "metadata": {}, 115 | "source": [ 116 | "아래 model.summary() 명령어를 사용하여, 모델의 구성이 어떻게 이뤄졌는 지 확인합니다. " 117 | ] 118 | }, 119 | { 120 | "cell_type": "code", 121 | "execution_count": 15, 122 | "metadata": {}, 123 | "outputs": [ 124 | { 125 | "name": "stdout", 126 | "output_type": "stream", 127 | "text": [ 128 | "_________________________________________________________________\n", 129 | "Layer (type) Output Shape Param # \n", 130 | "=================================================================\n", 131 | "dense_2 (Dense) (None, 1) 3 \n", 132 | "_________________________________________________________________\n", 133 | "activation_2 (Activation) (None, 1) 0 \n", 134 | "=================================================================\n", 135 | "Total params: 3\n", 136 | "Trainable params: 3\n", 137 | "Non-trainable params: 0\n", 138 | "_________________________________________________________________\n" 139 | ] 140 | } 141 | ], 142 | "source": [ 143 | "model.summary()" 144 | ] 145 | }, 146 | { 147 | "cell_type": "markdown", 148 | "metadata": {}, 149 | "source": [ 150 | "첫번째 레이어에 존재하는 w1, w2, b는 아래의 명령어로 확인하실 수 있습니다." 151 | ] 152 | }, 153 | { 154 | "cell_type": "code", 155 | "execution_count": 16, 156 | "metadata": {}, 157 | "outputs": [ 158 | { 159 | "data": { 160 | "text/plain": [ 161 | "[,\n", 162 | " ]" 163 | ] 164 | }, 165 | "execution_count": 16, 166 | "metadata": {}, 167 | "output_type": "execute_result" 168 | } 169 | ], 170 | "source": [ 171 | "model.layers[0].weights" 172 | ] 173 | }, 174 | { 175 | "cell_type": "markdown", 176 | "metadata": {}, 177 | "source": [ 178 | "학습을 통해 얻어진 최적의 w1, w2, b는 get_weights() 함수로 확인 가능합니다." 179 | ] 180 | }, 181 | { 182 | "cell_type": "code", 183 | "execution_count": 17, 184 | "metadata": {}, 185 | "outputs": [ 186 | { 187 | "data": { 188 | "text/plain": [ 189 | "[array([[2.0255988],\n", 190 | " [1.9430805]], dtype=float32), array([-3.2472157], dtype=float32)]" 191 | ] 192 | }, 193 | "execution_count": 17, 194 | "metadata": {}, 195 | "output_type": "execute_result" 196 | } 197 | ], 198 | "source": [ 199 | "model.layers[0].get_weights()" 200 | ] 201 | } 202 | ], 203 | "metadata": { 204 | "kernelspec": { 205 | "display_name": "Python 3", 206 | "language": "python", 207 | "name": "python3" 208 | }, 209 | "language_info": { 210 | "codemirror_mode": { 211 | "name": "ipython", 212 | "version": 3 213 | }, 214 | "file_extension": ".py", 215 | "mimetype": "text/x-python", 216 | "name": "python", 217 | "nbconvert_exporter": "python", 218 | "pygments_lexer": "ipython3", 219 | "version": "3.6.4" 220 | } 221 | }, 222 | "nbformat": 4, 223 | "nbformat_minor": 2 224 | } 225 | -------------------------------------------------------------------------------- /jupyter_notebook/5.다층퍼셉트론_XOR_실습.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# 다층퍼셉트론 XOR 실습" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "텐서플로우로 직접 다층퍼셉트론을 구현하여 XOR 연산을 다뤄보겠습니다." 15 | ] 16 | }, 17 | { 18 | "cell_type": "markdown", 19 | "metadata": {}, 20 | "source": [ 21 | "# 텐서플로우 실습" 22 | ] 23 | }, 24 | { 25 | "cell_type": "code", 26 | "execution_count": 2, 27 | "metadata": {}, 28 | "outputs": [], 29 | "source": [ 30 | "import tensorflow as tf" 31 | ] 32 | }, 33 | { 34 | "cell_type": "markdown", 35 | "metadata": {}, 36 | "source": [ 37 | "# 텐서플로우 그래프 정의하기\n", 38 | "가장 먼저 입력 레이어를 정의하겠습니다. \n", 39 | "XOR 연산 입력 데이터를 X, 결과값을 Y라고 정의하겠습니다. \n", 40 | "\n", 41 | "XOR 연산을 위해 입력값 X는 아래와 같이 [4,2]의 형태를 갖습니다.\n", 42 | " \n", 43 | "[0, 0], \n", 44 | "[0, 1], \n", 45 | "[1, 0], \n", 46 | "[1, 1] \n", 47 | "\n", 48 | "입력값에 따른 출력값 Y는 [4,1]의 형태를 갖습니다. \n", 49 | "[[0], [1], [1], [0]] " 50 | ] 51 | }, 52 | { 53 | "cell_type": "code", 54 | "execution_count": 3, 55 | "metadata": {}, 56 | "outputs": [], 57 | "source": [ 58 | "X = tf.placeholder(tf.float32, shape=[4,2])\n", 59 | "Y = tf.placeholder(tf.float32, shape=[4,1])" 60 | ] 61 | }, 62 | { 63 | "cell_type": "markdown", 64 | "metadata": {}, 65 | "source": [ 66 | "# 첫번째 히든 레이어" 67 | ] 68 | }, 69 | { 70 | "cell_type": "code", 71 | "execution_count": 4, 72 | "metadata": {}, 73 | "outputs": [], 74 | "source": [ 75 | "# 두개의 입력값을 받는 두개의 뉴론을 만듭니다. \n", 76 | "W1 = tf.Variable(tf.random_uniform([2,2]))\n", 77 | "# 각각의 뉴론은 한개의 편향값을 갖습니다.\n", 78 | "B1 = tf.Variable(tf.zeros([2]))\n", 79 | "# 출력값으로 Z를 리턴하도록 합니다. sigmoid(W1 * X + B1)\n", 80 | "Z = tf.sigmoid(tf.matmul(X, W1) + B1)" 81 | ] 82 | }, 83 | { 84 | "cell_type": "markdown", 85 | "metadata": {}, 86 | "source": [ 87 | "# 두번째 히든 레이어" 88 | ] 89 | }, 90 | { 91 | "cell_type": "code", 92 | "execution_count": 5, 93 | "metadata": {}, 94 | "outputs": [], 95 | "source": [ 96 | "# Z를 입력값으로 받는 하나의 뉴론을 두번째 히든레이어에 만듭니다.\n", 97 | "W2 = tf.Variable(tf.random_uniform([2,1]))\n", 98 | "# 뉴론은 한개의 편향값을 갖습니다.\n", 99 | "B2 = tf.Variable(tf.zeros([1]))\n", 100 | "# 출력값으로 Y_hat을 리턴합니다. sigmoid(W2 * Z + B2)\n", 101 | "Y_hat = tf.sigmoid(tf.matmul(Z, W2) + B2)" 102 | ] 103 | }, 104 | { 105 | "cell_type": "markdown", 106 | "metadata": {}, 107 | "source": [ 108 | "# 손실 함수\n", 109 | "크로스 엔트로피를 손실함수로 사용하도록 하겠습니다." 110 | ] 111 | }, 112 | { 113 | "cell_type": "code", 114 | "execution_count": 7, 115 | "metadata": {}, 116 | "outputs": [], 117 | "source": [ 118 | "# cross entropy\n", 119 | "loss = tf.reduce_mean(-1*((Y*tf.log(Y_hat))+((1-Y)*tf.log(1.0-Y_hat))))" 120 | ] 121 | }, 122 | { 123 | "cell_type": "markdown", 124 | "metadata": {}, 125 | "source": [ 126 | "# 최적화\n", 127 | "경사하강법으로 모델의 매개변수(가중치, 편향값)을 최적화합니다." 128 | ] 129 | }, 130 | { 131 | "cell_type": "code", 132 | "execution_count": 8, 133 | "metadata": {}, 134 | "outputs": [], 135 | "source": [ 136 | "# 경사하강법\n", 137 | "train_step = tf.train.GradientDescentOptimizer(0.05).minimize(loss)" 138 | ] 139 | }, 140 | { 141 | "cell_type": "markdown", 142 | "metadata": {}, 143 | "source": [ 144 | "# 학습" 145 | ] 146 | }, 147 | { 148 | "cell_type": "code", 149 | "execution_count": 9, 150 | "metadata": {}, 151 | "outputs": [], 152 | "source": [ 153 | "# 학습데이터를 만듭니다.\n", 154 | "train_X = [[0,0],[0,1],[1,0],[1,1]]\n", 155 | "train_Y = [[0],[1],[1],[0]]" 156 | ] 157 | }, 158 | { 159 | "cell_type": "code", 160 | "execution_count": 32, 161 | "metadata": {}, 162 | "outputs": [ 163 | { 164 | "name": "stdout", 165 | "output_type": "stream", 166 | "text": [ 167 | "train data: [[0, 0], [0, 1], [1, 0], [1, 1]]\n", 168 | "Epoch : 0\n", 169 | "Output : [[0.5230039]\n", 170 | " [0.524582 ]\n", 171 | " [0.5268023]\n", 172 | " [0.5280755]]\n", 173 | "Epoch : 5000\n", 174 | "Output : [[0.44640082]\n", 175 | " [0.51405567]\n", 176 | " [0.52132326]\n", 177 | " [0.5457807 ]]\n", 178 | "Epoch : 10000\n", 179 | "Output : [[0.13913684]\n", 180 | " [0.76280355]\n", 181 | " [0.762544 ]\n", 182 | " [0.36348855]]\n", 183 | "Epoch : 15000\n", 184 | "Output : [[0.04414607]\n", 185 | " [0.96044695]\n", 186 | " [0.96046036]\n", 187 | " [0.04712832]]\n", 188 | "Final Output : [[0.02394469]\n", 189 | " [0.98076755]\n", 190 | " [0.9807724 ]\n", 191 | " [0.02158156]]\n" 192 | ] 193 | } 194 | ], 195 | "source": [ 196 | "# 텐서플로우 매개변수를 초기화를 선언합니다.\n", 197 | "init = tf.global_variables_initializer()\n", 198 | "# 학습을 시작합니다.\n", 199 | "with tf.Session() as sess:\n", 200 | " # 매개변수를 초기화합니다.\n", 201 | " sess.run(init)\n", 202 | " print(\"train data: \"+str(train_X))\n", 203 | " # 2만번의 반복학습을 진행합니다.\n", 204 | " for i in range(20000):\n", 205 | " sess.run(train_step, feed_dict={X: train_X, Y: train_Y})\n", 206 | " if i % 5000 == 0:\n", 207 | " print('Epoch : ', i)\n", 208 | " print('Output : ', sess.run(Y_hat, feed_dict={X: train_X, Y: train_Y}))\n", 209 | " \n", 210 | " print('Final Output : ', sess.run(Y_hat, feed_dict={X: train_X, Y: train_Y}))" 211 | ] 212 | }, 213 | { 214 | "cell_type": "markdown", 215 | "metadata": {}, 216 | "source": [ 217 | "학습 결과를 통해, [0,0], [1,1]은 0에 상당히 가까운 값을 출력하고, \n", 218 | "[0,1], [1,0]은 1에 상당히 가까운 값을 출력하는 것을 확인할 수 있습니다." 219 | ] 220 | }, 221 | { 222 | "cell_type": "code", 223 | "execution_count": null, 224 | "metadata": {}, 225 | "outputs": [], 226 | "source": [] 227 | } 228 | ], 229 | "metadata": { 230 | "kernelspec": { 231 | "display_name": "Python 3", 232 | "language": "python", 233 | "name": "python3" 234 | }, 235 | "language_info": { 236 | "codemirror_mode": { 237 | "name": "ipython", 238 | "version": 3 239 | }, 240 | "file_extension": ".py", 241 | "mimetype": "text/x-python", 242 | "name": "python", 243 | "nbconvert_exporter": "python", 244 | "pygments_lexer": "ipython3", 245 | "version": "3.6.4" 246 | } 247 | }, 248 | "nbformat": 4, 249 | "nbformat_minor": 2 250 | } 251 | -------------------------------------------------------------------------------- /jupyter_notebook/4.9_단일입력_로지스틱회귀_실습.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# 단일 입력 로지스틱 회귀 모델\n", 8 | "1개의 입력을 받아 0 또는 1을 출력하는 로지스틱 회귀 모델을 케라스로 구현해보도록 하겠습니다." 9 | ] 10 | }, 11 | { 12 | "cell_type": "code", 13 | "execution_count": 28, 14 | "metadata": {}, 15 | "outputs": [], 16 | "source": [ 17 | "from keras.models import Sequential\n", 18 | "from keras.layers import Dense, Activation\n", 19 | "import numpy as np" 20 | ] 21 | }, 22 | { 23 | "cell_type": "markdown", 24 | "metadata": {}, 25 | "source": [ 26 | "sigmoid(wx+b)의 형태를 갖는 간단한 로지스틱 회귀를 케라스로 구현합니다. " 27 | ] 28 | }, 29 | { 30 | "cell_type": "code", 31 | "execution_count": 29, 32 | "metadata": {}, 33 | "outputs": [], 34 | "source": [ 35 | "model = Sequential()\n", 36 | "model.add(Dense(input_dim=1, units = 1))\n", 37 | "model.add(Activation('sigmoid'))\n", 38 | "model.compile(loss='binary_crossentropy', optimizer='sgd', metrics=['binary_accuracy'])" 39 | ] 40 | }, 41 | { 42 | "cell_type": "markdown", 43 | "metadata": {}, 44 | "source": [ 45 | "모델을 학습시키기 위한 데이터를 생성합니다." 46 | ] 47 | }, 48 | { 49 | "cell_type": "code", 50 | "execution_count": 30, 51 | "metadata": {}, 52 | "outputs": [], 53 | "source": [ 54 | "X = np.array([-2, -1.5, -1, 1.25, 1.62, 2]) \n", 55 | "Y = np.array([0, 0, 0, 1, 1, 1])" 56 | ] 57 | }, 58 | { 59 | "cell_type": "markdown", 60 | "metadata": {}, 61 | "source": [ 62 | "모델 학습을 진행합니다. " 63 | ] 64 | }, 65 | { 66 | "cell_type": "code", 67 | "execution_count": 31, 68 | "metadata": {}, 69 | "outputs": [ 70 | { 71 | "data": { 72 | "text/plain": [ 73 | "" 74 | ] 75 | }, 76 | "execution_count": 31, 77 | "metadata": {}, 78 | "output_type": "execute_result" 79 | } 80 | ], 81 | "source": [ 82 | "model.fit(X, Y, epochs=300, verbose=0)" 83 | ] 84 | }, 85 | { 86 | "cell_type": "markdown", 87 | "metadata": {}, 88 | "source": [ 89 | "학습 데이터에 따른 실제 모델의 출력값을 확인해봅니다. \n", 90 | "-2, -1.5, -1에 해당하는 값은 0.5보다 작고, 나머지 값들은 0.5보다 큰 것을 확인할 수 있습니다." 91 | ] 92 | }, 93 | { 94 | "cell_type": "code", 95 | "execution_count": 32, 96 | "metadata": {}, 97 | "outputs": [ 98 | { 99 | "data": { 100 | "text/plain": [ 101 | "array([[0.13920194],\n", 102 | " [0.20290251],\n", 103 | " [0.28606588],\n", 104 | " [0.7552856 ],\n", 105 | " [0.8119498 ],\n", 106 | " [0.85906285]], dtype=float32)" 107 | ] 108 | }, 109 | "execution_count": 32, 110 | "metadata": {}, 111 | "output_type": "execute_result" 112 | } 113 | ], 114 | "source": [ 115 | "model.predict([-2, -1.5, -1, 1.25, 1.62, 2])" 116 | ] 117 | }, 118 | { 119 | "cell_type": "markdown", 120 | "metadata": {}, 121 | "source": [ 122 | "시그모이드의 특성상 왼쪽 극한의 값은 0으로 수렴하며, 오른쪽 극한의 값은 1로 확인하는 것을 확인합니다." 123 | ] 124 | }, 125 | { 126 | "cell_type": "code", 127 | "execution_count": 33, 128 | "metadata": {}, 129 | "outputs": [ 130 | { 131 | "data": { 132 | "text/plain": [ 133 | "array([[0.],\n", 134 | " [1.]], dtype=float32)" 135 | ] 136 | }, 137 | "execution_count": 33, 138 | "metadata": {}, 139 | "output_type": "execute_result" 140 | } 141 | ], 142 | "source": [ 143 | "model.predict([-1000, 1000])" 144 | ] 145 | }, 146 | { 147 | "cell_type": "markdown", 148 | "metadata": {}, 149 | "source": [ 150 | "아래 model.summary() 명령어를 사용하여, 모델의 구성이 어떻게 이뤄졌는 지 확인합니다. " 151 | ] 152 | }, 153 | { 154 | "cell_type": "code", 155 | "execution_count": 34, 156 | "metadata": {}, 157 | "outputs": [ 158 | { 159 | "name": "stdout", 160 | "output_type": "stream", 161 | "text": [ 162 | "_________________________________________________________________\n", 163 | "Layer (type) Output Shape Param # \n", 164 | "=================================================================\n", 165 | "dense_4 (Dense) (None, 1) 2 \n", 166 | "_________________________________________________________________\n", 167 | "activation_4 (Activation) (None, 1) 0 \n", 168 | "=================================================================\n", 169 | "Total params: 2\n", 170 | "Trainable params: 2\n", 171 | "Non-trainable params: 0\n", 172 | "_________________________________________________________________\n" 173 | ] 174 | } 175 | ], 176 | "source": [ 177 | "model.summary()" 178 | ] 179 | }, 180 | { 181 | "cell_type": "markdown", 182 | "metadata": {}, 183 | "source": [ 184 | "첫번째 레이어에 존재하는 w와 b는 아래의 명령어로 확인하실 수 있습니다." 185 | ] 186 | }, 187 | { 188 | "cell_type": "code", 189 | "execution_count": 35, 190 | "metadata": {}, 191 | "outputs": [ 192 | { 193 | "data": { 194 | "text/plain": [ 195 | "[,\n", 196 | " ]" 197 | ] 198 | }, 199 | "execution_count": 35, 200 | "metadata": {}, 201 | "output_type": "execute_result" 202 | } 203 | ], 204 | "source": [ 205 | "model.layers[0].weights" 206 | ] 207 | }, 208 | { 209 | "cell_type": "markdown", 210 | "metadata": {}, 211 | "source": [ 212 | "학습을 통해 얻어진 최적의 w와 b는 get_weights() 함수로 확인 가능합니다." 213 | ] 214 | }, 215 | { 216 | "cell_type": "code", 217 | "execution_count": 36, 218 | "metadata": {}, 219 | "outputs": [ 220 | { 221 | "data": { 222 | "text/plain": [ 223 | "[array([[0.9073657]], dtype=float32), array([-0.00720286], dtype=float32)]" 224 | ] 225 | }, 226 | "execution_count": 36, 227 | "metadata": {}, 228 | "output_type": "execute_result" 229 | } 230 | ], 231 | "source": [ 232 | "model.layers[0].get_weights()" 233 | ] 234 | } 235 | ], 236 | "metadata": { 237 | "kernelspec": { 238 | "display_name": "Python 3", 239 | "language": "python", 240 | "name": "python3" 241 | }, 242 | "language_info": { 243 | "codemirror_mode": { 244 | "name": "ipython", 245 | "version": 3 246 | }, 247 | "file_extension": ".py", 248 | "mimetype": "text/x-python", 249 | "name": "python", 250 | "nbconvert_exporter": "python", 251 | "pygments_lexer": "ipython3", 252 | "version": "3.6.4" 253 | } 254 | }, 255 | "nbformat": 4, 256 | "nbformat_minor": 2 257 | } 258 | -------------------------------------------------------------------------------- /jupyter_notebook/5.퍼셉트론_AND_연산.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# 퍼셉트론 실습\n", 8 | "실습에 앞서, 먼저 텐서플로우를 임포트합니다." 9 | ] 10 | }, 11 | { 12 | "cell_type": "code", 13 | "execution_count": 1, 14 | "metadata": {}, 15 | "outputs": [], 16 | "source": [ 17 | "import tensorflow as tf" 18 | ] 19 | }, 20 | { 21 | "cell_type": "markdown", 22 | "metadata": {}, 23 | "source": [ 24 | "# 상수 설정\n", 25 | "코드의 이해도를 높히기 위해서, 1은 True, 0은 False, 그리고 편형값(bias)은 1로 지정합니다." 26 | ] 27 | }, 28 | { 29 | "cell_type": "code", 30 | "execution_count": 2, 31 | "metadata": {}, 32 | "outputs": [], 33 | "source": [ 34 | "T = 1.0\n", 35 | "F = 0.0\n", 36 | "bias = 1.0" 37 | ] 38 | }, 39 | { 40 | "cell_type": "markdown", 41 | "metadata": {}, 42 | "source": [ 43 | "# AND, OR 연산의 이해\n", 44 | "실습에 앞서서, AND, OR 연산의 입력값과 그에 따른 출력값을 알아봅시다.\n", 45 | "![Image of Perceptron](https://raw.githubusercontent.com/captainchargers/deeplearning/master/img/truth_table.png)" 46 | ] 47 | }, 48 | { 49 | "cell_type": "markdown", 50 | "metadata": {}, 51 | "source": [ 52 | "# 데이터 획득\n", 53 | "아래 AND, OR, XOR 실습 데이터를 함수를 호출하여 받으실 수 있습니다." 54 | ] 55 | }, 56 | { 57 | "cell_type": "code", 58 | "execution_count": 3, 59 | "metadata": {}, 60 | "outputs": [], 61 | "source": [ 62 | "def get_AND_data():\n", 63 | " X = [\n", 64 | " [F, F, bias],\n", 65 | " [F, T, bias],\n", 66 | " [T, F, bias],\n", 67 | " [T, T, bias]\n", 68 | " ]\n", 69 | " \n", 70 | " Y = [\n", 71 | " [F],\n", 72 | " [F],\n", 73 | " [F],\n", 74 | " [T]\n", 75 | " ]\n", 76 | " \n", 77 | " return X, Y\n", 78 | "\n", 79 | "def get_OR_data():\n", 80 | " X = [\n", 81 | " [F, F, bias],\n", 82 | " [F, T, bias],\n", 83 | " [T, F, bias],\n", 84 | " [T, T, bias]\n", 85 | " ]\n", 86 | " \n", 87 | " Y = [\n", 88 | " [F],\n", 89 | " [T],\n", 90 | " [T],\n", 91 | " [T]\n", 92 | " ]\n", 93 | " \n", 94 | " return X, Y\n", 95 | "\n", 96 | "def get_XOR_data():\n", 97 | " X = [\n", 98 | " [F, F, bias],\n", 99 | " [F, T, bias],\n", 100 | " [T, F, bias],\n", 101 | " [T, T, bias]\n", 102 | " ]\n", 103 | " \n", 104 | " Y = [\n", 105 | " [F],\n", 106 | " [T],\n", 107 | " [T],\n", 108 | " [F]\n", 109 | " ]\n", 110 | " \n", 111 | " return X, Y" 112 | ] 113 | }, 114 | { 115 | "cell_type": "markdown", 116 | "metadata": {}, 117 | "source": [ 118 | "실습할 연산을 선택합니다." 119 | ] 120 | }, 121 | { 122 | "cell_type": "code", 123 | "execution_count": 4, 124 | "metadata": {}, 125 | "outputs": [], 126 | "source": [ 127 | "X, Y = get_AND_data()\n", 128 | "#X, Y = get_OR_data()\n", 129 | "#X, Y = get_XOR_data()" 130 | ] 131 | }, 132 | { 133 | "cell_type": "markdown", 134 | "metadata": {}, 135 | "source": [ 136 | "# 퍼셉트론 구성하기\n", 137 | "논리 연산용 퍼셉트론을 구현해보도록 하겠습니다. \n", 138 | "논리연산을 위한 입력값 X, Y와 편향값 (b)를 받을 것이므로, weight를 [3,1]로 설정합니다. \n", 139 | "3은 세개의 입력을 의미하고, 1은 한개의 뉴론임을 의미합니다." 140 | ] 141 | }, 142 | { 143 | "cell_type": "code", 144 | "execution_count": 5, 145 | "metadata": {}, 146 | "outputs": [], 147 | "source": [ 148 | "W = tf.Variable(tf.random_normal([3, 1]))" 149 | ] 150 | }, 151 | { 152 | "cell_type": "markdown", 153 | "metadata": {}, 154 | "source": [ 155 | "# 활성화 함수\n", 156 | "퍼셉트론은 아래 스텝함수를 활성화함수로 사용합니다. \n", 157 | "step(x) = { 1 if x > 0; 0 otherwise }" 158 | ] 159 | }, 160 | { 161 | "cell_type": "code", 162 | "execution_count": 6, 163 | "metadata": {}, 164 | "outputs": [], 165 | "source": [ 166 | "def step(x):\n", 167 | " return tf.to_float(tf.greater(x, 0))" 168 | ] 169 | }, 170 | { 171 | "cell_type": "markdown", 172 | "metadata": {}, 173 | "source": [ 174 | "# 손실 함수\n", 175 | "평균 제곱 오차(MSE)를 손실함수로 사용하도록 하겠습니다." 176 | ] 177 | }, 178 | { 179 | "cell_type": "code", 180 | "execution_count": 7, 181 | "metadata": {}, 182 | "outputs": [], 183 | "source": [ 184 | "f = tf.matmul(X, W)\n", 185 | "output = step(f)\n", 186 | "error = tf.subtract(Y, output)\n", 187 | "mse = tf.reduce_mean(tf.square(error))" 188 | ] 189 | }, 190 | { 191 | "cell_type": "markdown", 192 | "metadata": {}, 193 | "source": [ 194 | "# 최적화\n", 195 | "퍼셉트론은 경사하강법을 사용한 최적화가 불가능합니다.\n", 196 | "매번 학습을 진행할 때마다 가중치를 아래의 룰에 맞게 업데이트합니다. \n", 197 | "\n", 198 | "if target == 1 and activation == 0: \n", 199 | " w_new = w_old + input \n", 200 | " \n", 201 | "if target == 0 and activation == 1: \n", 202 | " w_new = w_old - input " 203 | ] 204 | }, 205 | { 206 | "cell_type": "code", 207 | "execution_count": 8, 208 | "metadata": {}, 209 | "outputs": [], 210 | "source": [ 211 | "delta = tf.matmul(X, error, transpose_a=True)\n", 212 | "train = tf.assign(W, tf.add(W, delta))" 213 | ] 214 | }, 215 | { 216 | "cell_type": "markdown", 217 | "metadata": {}, 218 | "source": [ 219 | "# 학습 및 테스트\n", 220 | "아래의 코드를 실행시켜 테스트를 진행합니다." 221 | ] 222 | }, 223 | { 224 | "cell_type": "code", 225 | "execution_count": 9, 226 | "metadata": {}, 227 | "outputs": [ 228 | { 229 | "name": "stdout", 230 | "output_type": "stream", 231 | "text": [ 232 | "epoch: 1 mse: 0.25\n", 233 | "epoch: 2 mse: 0.25\n", 234 | "epoch: 3 mse: 0.25\n", 235 | "epoch: 4 mse: 0.5\n", 236 | "epoch: 5 mse: 0.25\n", 237 | "epoch: 6 mse: 0.0\n", 238 | "\n", 239 | "Testing Result:\n", 240 | "[array([[0.],\n", 241 | " [0.],\n", 242 | " [0.],\n", 243 | " [1.]], dtype=float32)]\n" 244 | ] 245 | } 246 | ], 247 | "source": [ 248 | "# Initialize the variables (i.e. assign their default value)\n", 249 | "init = tf.global_variables_initializer()\n", 250 | "\n", 251 | "# Start training\n", 252 | "with tf.Session() as sess:\n", 253 | " # Run the initializer\n", 254 | " sess.run(init)\n", 255 | " err = 1\n", 256 | " epoch, max_epochs = 0, 20\n", 257 | " while err > 0.0 and epoch < max_epochs:\n", 258 | " epoch += 1\n", 259 | " err = sess.run(mse)\n", 260 | " sess.run(train)\n", 261 | " print('epoch:', epoch, 'mse:', err)\n", 262 | " \n", 263 | " print(\"\\nTesting Result:\")\n", 264 | " print(sess.run([output]))" 265 | ] 266 | } 267 | ], 268 | "metadata": { 269 | "kernelspec": { 270 | "display_name": "Python 3", 271 | "language": "python", 272 | "name": "python3" 273 | }, 274 | "language_info": { 275 | "codemirror_mode": { 276 | "name": "ipython", 277 | "version": 3 278 | }, 279 | "file_extension": ".py", 280 | "mimetype": "text/x-python", 281 | "name": "python", 282 | "nbconvert_exporter": "python", 283 | "pygments_lexer": "ipython3", 284 | "version": "3.6.4" 285 | } 286 | }, 287 | "nbformat": 4, 288 | "nbformat_minor": 2 289 | } 290 | -------------------------------------------------------------------------------- /jupyter_notebook/5.퍼셉트론_XOR_연산.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# 퍼셉트론 실습\n", 8 | "실습에 앞서, 먼저 텐서플로우를 임포트합니다." 9 | ] 10 | }, 11 | { 12 | "cell_type": "code", 13 | "execution_count": 1, 14 | "metadata": {}, 15 | "outputs": [], 16 | "source": [ 17 | "import tensorflow as tf" 18 | ] 19 | }, 20 | { 21 | "cell_type": "markdown", 22 | "metadata": {}, 23 | "source": [ 24 | "# 상수 설정\n", 25 | "코드의 이해도를 높히기 위해서, 1은 True, 0은 False, 그리고 편형값(bias)은 1로 지정합니다." 26 | ] 27 | }, 28 | { 29 | "cell_type": "code", 30 | "execution_count": 2, 31 | "metadata": {}, 32 | "outputs": [], 33 | "source": [ 34 | "T = 1.0\n", 35 | "F = 0.0\n", 36 | "bias = 1.0" 37 | ] 38 | }, 39 | { 40 | "cell_type": "markdown", 41 | "metadata": {}, 42 | "source": [ 43 | "# AND, OR 연산의 이해\n", 44 | "실습에 앞서서, AND, OR 연산의 입력값과 그에 따른 출력값을 알아봅시다.\n", 45 | "![Image of Perceptron](https://raw.githubusercontent.com/captainchargers/deeplearning/master/img/truth_table.png)" 46 | ] 47 | }, 48 | { 49 | "cell_type": "markdown", 50 | "metadata": {}, 51 | "source": [ 52 | "# 데이터 획득\n", 53 | "아래 AND, OR, XOR 실습 데이터를 함수를 호출하여 받으실 수 있습니다." 54 | ] 55 | }, 56 | { 57 | "cell_type": "code", 58 | "execution_count": 3, 59 | "metadata": {}, 60 | "outputs": [], 61 | "source": [ 62 | "def get_AND_data():\n", 63 | " X = [\n", 64 | " [F, F, bias],\n", 65 | " [F, T, bias],\n", 66 | " [T, F, bias],\n", 67 | " [T, T, bias]\n", 68 | " ]\n", 69 | " \n", 70 | " Y = [\n", 71 | " [F],\n", 72 | " [F],\n", 73 | " [F],\n", 74 | " [T]\n", 75 | " ]\n", 76 | " \n", 77 | " return X, Y\n", 78 | "\n", 79 | "def get_OR_data():\n", 80 | " X = [\n", 81 | " [F, F, bias],\n", 82 | " [F, T, bias],\n", 83 | " [T, F, bias],\n", 84 | " [T, T, bias]\n", 85 | " ]\n", 86 | " \n", 87 | " Y = [\n", 88 | " [F],\n", 89 | " [T],\n", 90 | " [T],\n", 91 | " [T]\n", 92 | " ]\n", 93 | " \n", 94 | " return X, Y\n", 95 | "\n", 96 | "def get_XOR_data():\n", 97 | " X = [\n", 98 | " [F, F, bias],\n", 99 | " [F, T, bias],\n", 100 | " [T, F, bias],\n", 101 | " [T, T, bias]\n", 102 | " ]\n", 103 | " \n", 104 | " Y = [\n", 105 | " [F],\n", 106 | " [T],\n", 107 | " [T],\n", 108 | " [F]\n", 109 | " ]\n", 110 | " \n", 111 | " return X, Y" 112 | ] 113 | }, 114 | { 115 | "cell_type": "markdown", 116 | "metadata": {}, 117 | "source": [ 118 | "실습할 연산을 선택합니다." 119 | ] 120 | }, 121 | { 122 | "cell_type": "code", 123 | "execution_count": 4, 124 | "metadata": {}, 125 | "outputs": [], 126 | "source": [ 127 | "#X, Y = get_AND_data()\n", 128 | "#X, Y = get_OR_data()\n", 129 | "X, Y = get_XOR_data()" 130 | ] 131 | }, 132 | { 133 | "cell_type": "markdown", 134 | "metadata": {}, 135 | "source": [ 136 | "# 퍼셉트론 구성하기\n", 137 | "논리 연산용 퍼셉트론을 구현해보도록 하겠습니다. \n", 138 | "논리연산을 위한 입력값 X, Y와 편향값 (b)를 받을 것이므로, weight를 [3,1]로 설정합니다. \n", 139 | "3은 세개의 입력을 의미하고, 1은 한개의 뉴론임을 의미합니다." 140 | ] 141 | }, 142 | { 143 | "cell_type": "code", 144 | "execution_count": 5, 145 | "metadata": {}, 146 | "outputs": [], 147 | "source": [ 148 | "W = tf.Variable(tf.random_normal([3, 1]))" 149 | ] 150 | }, 151 | { 152 | "cell_type": "markdown", 153 | "metadata": {}, 154 | "source": [ 155 | "# 활성화 함수\n", 156 | "퍼셉트론은 아래 스텝함수를 활성화함수로 사용합니다. \n", 157 | "step(x) = { 1 if x > 0; 0 otherwise }" 158 | ] 159 | }, 160 | { 161 | "cell_type": "code", 162 | "execution_count": 6, 163 | "metadata": {}, 164 | "outputs": [], 165 | "source": [ 166 | "def step(x):\n", 167 | " return tf.to_float(tf.greater(x, 0))" 168 | ] 169 | }, 170 | { 171 | "cell_type": "markdown", 172 | "metadata": {}, 173 | "source": [ 174 | "# 손실 함수\n", 175 | "평균 제곱 오차(MSE)를 손실함수로 사용하도록 하겠습니다." 176 | ] 177 | }, 178 | { 179 | "cell_type": "code", 180 | "execution_count": 7, 181 | "metadata": {}, 182 | "outputs": [], 183 | "source": [ 184 | "f = tf.matmul(X, W)\n", 185 | "output = step(f)\n", 186 | "error = tf.subtract(Y, output)\n", 187 | "mse = tf.reduce_mean(tf.square(error))" 188 | ] 189 | }, 190 | { 191 | "cell_type": "markdown", 192 | "metadata": {}, 193 | "source": [ 194 | "# 최적화\n", 195 | "퍼셉트론은 경사하강법을 사용한 최적화가 불가능합니다.\n", 196 | "매번 학습을 진행할 때마다 가중치를 아래의 룰에 맞게 업데이트합니다. \n", 197 | "\n", 198 | "if target == 1 and activation == 0: \n", 199 | " w_new = w_old + input \n", 200 | " \n", 201 | "if target == 0 and activation == 1: \n", 202 | " w_new = w_old - input " 203 | ] 204 | }, 205 | { 206 | "cell_type": "code", 207 | "execution_count": 8, 208 | "metadata": {}, 209 | "outputs": [], 210 | "source": [ 211 | "delta = tf.matmul(X, error, transpose_a=True)\n", 212 | "train = tf.assign(W, tf.add(W, delta))" 213 | ] 214 | }, 215 | { 216 | "cell_type": "markdown", 217 | "metadata": {}, 218 | "source": [ 219 | "# 학습 및 테스트\n", 220 | "아래의 코드를 실행시켜 테스트를 진행합니다." 221 | ] 222 | }, 223 | { 224 | "cell_type": "code", 225 | "execution_count": 9, 226 | "metadata": {}, 227 | "outputs": [ 228 | { 229 | "name": "stdout", 230 | "output_type": "stream", 231 | "text": [ 232 | "epoch: 1 mse: 0.75\n", 233 | "epoch: 2 mse: 0.5\n", 234 | "epoch: 3 mse: 0.5\n", 235 | "epoch: 4 mse: 0.5\n", 236 | "epoch: 5 mse: 0.5\n", 237 | "epoch: 6 mse: 0.5\n", 238 | "epoch: 7 mse: 0.5\n", 239 | "epoch: 8 mse: 0.5\n", 240 | "epoch: 9 mse: 0.5\n", 241 | "epoch: 10 mse: 0.5\n", 242 | "epoch: 11 mse: 0.5\n", 243 | "epoch: 12 mse: 0.5\n", 244 | "epoch: 13 mse: 0.5\n", 245 | "epoch: 14 mse: 0.5\n", 246 | "epoch: 15 mse: 0.5\n", 247 | "epoch: 16 mse: 0.5\n", 248 | "epoch: 17 mse: 0.5\n", 249 | "epoch: 18 mse: 0.5\n", 250 | "epoch: 19 mse: 0.5\n", 251 | "epoch: 20 mse: 0.5\n", 252 | "\n", 253 | "Testing Result:\n", 254 | "[array([[0.],\n", 255 | " [0.],\n", 256 | " [0.],\n", 257 | " [0.]], dtype=float32)]\n" 258 | ] 259 | } 260 | ], 261 | "source": [ 262 | "# Initialize the variables (i.e. assign their default value)\n", 263 | "init = tf.global_variables_initializer()\n", 264 | "\n", 265 | "# Start training\n", 266 | "with tf.Session() as sess:\n", 267 | " # Run the initializer\n", 268 | " sess.run(init)\n", 269 | " err = 1\n", 270 | " epoch, max_epochs = 0, 20\n", 271 | " while err > 0.0 and epoch < max_epochs:\n", 272 | " epoch += 1\n", 273 | " err = sess.run(mse)\n", 274 | " sess.run(train)\n", 275 | " print('epoch:', epoch, 'mse:', err)\n", 276 | " \n", 277 | " print(\"\\nTesting Result:\")\n", 278 | " print(sess.run([output]))" 279 | ] 280 | }, 281 | { 282 | "cell_type": "markdown", 283 | "metadata": {}, 284 | "source": [ 285 | "결과에서 볼 수 있듯이, 퍼셉트론 하나로는 XOR 연산을 구현할 수 없습니다." 286 | ] 287 | } 288 | ], 289 | "metadata": { 290 | "kernelspec": { 291 | "display_name": "Python 3", 292 | "language": "python", 293 | "name": "python3" 294 | }, 295 | "language_info": { 296 | "codemirror_mode": { 297 | "name": "ipython", 298 | "version": 3 299 | }, 300 | "file_extension": ".py", 301 | "mimetype": "text/x-python", 302 | "name": "python", 303 | "nbconvert_exporter": "python", 304 | "pygments_lexer": "ipython3", 305 | "version": "3.6.4" 306 | } 307 | }, 308 | "nbformat": 4, 309 | "nbformat_minor": 2 310 | } 311 | -------------------------------------------------------------------------------- /jupyter_notebook/6.2_RNN_기초_텐서플로우_실습.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "이번 실습을 통해, 텐서플로우로 구현된 RNN을 직접 탐구해보도록 하겠습니다." 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": 1, 13 | "metadata": {}, 14 | "outputs": [], 15 | "source": [ 16 | "import numpy as np\n", 17 | "from IPython.display import Image" 18 | ] 19 | }, 20 | { 21 | "cell_type": "markdown", 22 | "metadata": {}, 23 | "source": [ 24 | "기본적으로 RNN은 아래의 다이어그램과 같이 구현됩니다. \n", 25 | "보시다시피, RNN은 입력값(x), 출력값(output), 상태값(state), 가중치(W), 편향값(b), 그리고 활성화함수(tanh)로 구성되어 있습니다." 26 | ] 27 | }, 28 | { 29 | "cell_type": "code", 30 | "execution_count": 2, 31 | "metadata": {}, 32 | "outputs": [ 33 | { 34 | "data": { 35 | "text/html": [ 36 | "" 37 | ], 38 | "text/plain": [ 39 | "" 40 | ] 41 | }, 42 | "execution_count": 2, 43 | "metadata": {}, 44 | "output_type": "execute_result" 45 | } 46 | ], 47 | "source": [ 48 | "Image(url= \"https://raw.githubusercontent.com/captainchargers/deeplearning/master/img/simple_rnn.png\", width=450, height=200)" 49 | ] 50 | }, 51 | { 52 | "cell_type": "markdown", 53 | "metadata": {}, 54 | "source": [ 55 | "# RNN 텐서플로우 코드 구현\n", 56 | "위에서 다뤄보았던 예제를 직접 텐서플로우로 구현하여 입력값, 출력값, 상태값, 편향값을 확인해보도록 하겠습니다." 57 | ] 58 | }, 59 | { 60 | "cell_type": "code", 61 | "execution_count": 3, 62 | "metadata": {}, 63 | "outputs": [], 64 | "source": [ 65 | "import tensorflow as tf" 66 | ] 67 | }, 68 | { 69 | "cell_type": "code", 70 | "execution_count": 4, 71 | "metadata": {}, 72 | "outputs": [], 73 | "source": [ 74 | "inputs = np.array([\n", 75 | " [ [1,2] ]\n", 76 | "])" 77 | ] 78 | }, 79 | { 80 | "cell_type": "code", 81 | "execution_count": 5, 82 | "metadata": {}, 83 | "outputs": [ 84 | { 85 | "name": "stdout", 86 | "output_type": "stream", 87 | "text": [ 88 | "Tensor(\"rnn/transpose_1:0\", shape=(1, 1, 3), dtype=float32)\n", 89 | "Tensor(\"rnn/while/Exit_3:0\", shape=(1, 3), dtype=float32)\n", 90 | "weights\n", 91 | "\n", 92 | "\n", 93 | "output values\n", 94 | "[[[-0.9314169 0.75578666 -0.6819246 ]]]\n", 95 | "\n", 96 | "state value\n", 97 | "[[-0.9314169 0.75578666 -0.6819246 ]]\n", 98 | "weights\n", 99 | "rnn/basic_rnn_cell/kernel:0 [[-0.62831575 0.38538355 0.79733914]\n", 100 | " [-0.5203329 0.30046564 -0.8150209 ]\n", 101 | " [ 0.39399797 0.16670114 0.4062907 ]\n", 102 | " [-0.6391754 0.8460203 0.5266966 ]\n", 103 | " [ 0.41124135 0.66347724 -0.0210759 ]]\n", 104 | "rnn/basic_rnn_cell/bias:0 [0. 0. 0.]\n" 105 | ] 106 | } 107 | ], 108 | "source": [ 109 | "tf.reset_default_graph()\n", 110 | "tf.set_random_seed(777)\n", 111 | "tf_inputs = tf.constant(inputs, dtype=tf.float32)\n", 112 | "rnn_cell = tf.nn.rnn_cell.BasicRNNCell(num_units=3)\n", 113 | "outputs, state = tf.nn.dynamic_rnn(\n", 114 | " cell=rnn_cell, dtype=tf.float32, inputs=tf_inputs)\n", 115 | "variables_names =[v.name for v in tf.trainable_variables()]\n", 116 | "\n", 117 | "print(outputs)\n", 118 | "print(state)\n", 119 | "print(\"weights\")\n", 120 | "for v in tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES):\n", 121 | " print(v)\n", 122 | "\n", 123 | "with tf.Session() as sess:\n", 124 | " sess.run(tf.global_variables_initializer())\n", 125 | " output_run, state_run = sess.run([outputs, state])\n", 126 | " print(\"output values\")\n", 127 | " print(output_run)\n", 128 | " print(\"\\nstate value\")\n", 129 | " print(state_run)\n", 130 | " print(\"weights\")\n", 131 | " values = sess.run(variables_names)\n", 132 | " for k,v in zip(variables_names, values):\n", 133 | " print(k, v)" 134 | ] 135 | }, 136 | { 137 | "cell_type": "markdown", 138 | "metadata": {}, 139 | "source": [ 140 | "# RNN 텐서플로우 코드 출력 이해하기\n", 141 | "위 코드의 출력값을 통해, 텐서플로우 RNN이 우리가 이론으로 다룬 RNN과 같은 것을 확인할 수 있습니다.. \n", 142 | "1. RNN 셀이 한개일 경우 그 출력값과 상태값이 동일합니다. \n", 143 | " output values [[[-0.9314169 0.75578666 -0.6819246 ]]] \n", 144 | " state value [[-0.9314169 0.75578666 -0.6819246 ]] \n", 145 | " \n", 146 | " \n", 147 | "2. 입력값이 1x2행렬이고, RNN의 상태값이 1x3의 행렬일 경우, **W**는 총 5개의 행을 가지게 됩니다. \n", 148 | " [[-0.62831575 0.38538355 0.79733914] \n", 149 | " [-0.5203329 0.30046564 -0.8150209 ] \n", 150 | " [ 0.39399797 0.16670114 0.4062907 ] \n", 151 | " [-0.6391754 0.8460203 0.5266966 ] \n", 152 | " [ 0.41124135 0.66347724 -0.0210759 ]] \n", 153 | " \n", 154 | " \n", 155 | "3. 입력값이 1x2행렬이고, RNN의 상태값이 1x3의 행렬일 경우, 편향값은 총 3개가 필요합니다. \n", 156 | " rnn/basic_rnn_cell/bias:0 [0. 0. 0.]" 157 | ] 158 | }, 159 | { 160 | "cell_type": "markdown", 161 | "metadata": {}, 162 | "source": [ 163 | "# 텐서플로우로 단어 품사 구분하기 예제 구현하기\n", 164 | "이론에서 다뤘던 \"I work at google\", \"I google at work\"의 단어 품사를 구분하는 RNN 코드를 텐서플로우로 구현해보도록 하겠습니다. \n", 165 | "각 단어는 one hot encoding으로 표현합니다." 166 | ] 167 | }, 168 | { 169 | "cell_type": "code", 170 | "execution_count": 6, 171 | "metadata": {}, 172 | "outputs": [], 173 | "source": [ 174 | "# I [1,0,0,0]\n", 175 | "# work [0,1,0,0]\n", 176 | "# at [0,0,1,0]\n", 177 | "# google [0,0,0,1]\n", 178 | "#\n", 179 | "# I work at google = [ [1,0,0,0], [0,1,0,0], [0,0,1,0], [0,0,0,1] ]\n", 180 | "# I google at work = [ [1,0,0,0], [0,0,0,1], [0,0,1,0], [0,1,0,0] ]\n", 181 | "\n", 182 | "inputs = np.array([\n", 183 | " [ [1,0,0,0], [0,1,0,0], [0,0,1,0], [0,0,0,1] ],\n", 184 | " [ [1,0,0,0], [0,0,0,1], [0,0,1,0], [0,1,0,0] ]\n", 185 | "])" 186 | ] 187 | }, 188 | { 189 | "cell_type": "markdown", 190 | "metadata": {}, 191 | "source": [ 192 | "아래의 코드를 실행하여, 결과값을 확인합니다." 193 | ] 194 | }, 195 | { 196 | "cell_type": "code", 197 | "execution_count": 7, 198 | "metadata": {}, 199 | "outputs": [ 200 | { 201 | "name": "stdout", 202 | "output_type": "stream", 203 | "text": [ 204 | "Tensor(\"rnn/transpose_1:0\", shape=(2, 4, 3), dtype=float32)\n", 205 | "Tensor(\"rnn/while/Exit_3:0\", shape=(2, 3), dtype=float32)\n", 206 | "weights\n", 207 | "\n", 208 | "\n", 209 | "output values\n", 210 | "[[[-0.50944704 0.33166462 0.6126557 ]\n", 211 | " [-0.20793891 0.24406303 -0.75278705]\n", 212 | " [-0.06346128 -0.52844936 0.68356085]\n", 213 | " [-0.36491966 0.8857268 -0.02324398]]\n", 214 | "\n", 215 | " [[-0.50944704 0.33166462 0.6126557 ]\n", 216 | " [-0.30707452 0.62735885 0.21719742]\n", 217 | " [ 0.5043804 -0.14038289 0.3744523 ]\n", 218 | " [-0.11641283 0.70696247 -0.7512605 ]]]\n", 219 | "\n", 220 | "state value\n", 221 | "[[-0.36491966 0.8857268 -0.02324398]\n", 222 | " [-0.11641283 0.70696247 -0.7512605 ]]\n", 223 | "weights\n", 224 | "rnn/basic_rnn_cell/kernel:0 [[-0.56198275 0.34469748 0.7131618 ]\n", 225 | " [-0.4653999 0.2687447 -0.7289769 ]\n", 226 | " [ 0.35240245 0.14910203 0.36339748]\n", 227 | " [-0.57169586 0.7567036 0.47109187]\n", 228 | " [ 0.3678255 0.5934322 -0.01885086]\n", 229 | " [ 0.31208777 -0.40880746 0.22867584]\n", 230 | " [ 0.5521256 0.682691 -0.5481483 ]]\n", 231 | "rnn/basic_rnn_cell/bias:0 [0. 0. 0.]\n" 232 | ] 233 | } 234 | ], 235 | "source": [ 236 | "tf.reset_default_graph()\n", 237 | "tf.set_random_seed(777)\n", 238 | "tf_inputs = tf.constant(inputs, dtype=tf.float32)\n", 239 | "rnn_cell = tf.contrib.rnn.BasicRNNCell(num_units=3)\n", 240 | "outputs, state = tf.nn.dynamic_rnn(\n", 241 | " cell=rnn_cell, dtype=tf.float32, inputs=tf_inputs)\n", 242 | "variables_names =[v.name for v in tf.trainable_variables()]\n", 243 | "\n", 244 | "print(outputs)\n", 245 | "print(state)\n", 246 | "print(\"weights\")\n", 247 | "for v in tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES):\n", 248 | " print(v)\n", 249 | " \n", 250 | "with tf.Session() as sess:\n", 251 | " sess.run(tf.global_variables_initializer())\n", 252 | " output_run, state_run = sess.run([outputs, state])\n", 253 | " print(\"output values\")\n", 254 | " print(output_run)\n", 255 | " print(\"\\nstate value\")\n", 256 | " print(state_run)\n", 257 | " print(\"weights\")\n", 258 | " values = sess.run(variables_names)\n", 259 | " for k,v in zip(variables_names, values):\n", 260 | " print(k, v)" 261 | ] 262 | }, 263 | { 264 | "cell_type": "markdown", 265 | "metadata": {}, 266 | "source": [ 267 | "# 텐서플로우 코드 출력 이해하기\n", 268 | "1. 두 문장의 첫단어 출력값이 동일합니다. 이는 첫단어에는 이전 상태값이 존재하지 않기 때문입니다. \n", 269 | " [-0.50944704 0.33166462 0.6126557 ] \n", 270 | " \n", 271 | "2. 두번째 단어부터의 출력값은 두 문장이 다르게 나타납니다. 이는 이전 상태값이 현재 출력값에 영향을 주기 때문입니다.\n", 272 | "3. 상태값은 항상 마지막 단어의 출력값과 동일합니다. \n", 273 | " 첫번째 문장: [-0.36491966 0.8857268 -0.02324398] \n", 274 | " 두번째 문장: [-0.11641283 0.70696247 -0.7512605 ]" 275 | ] 276 | }, 277 | { 278 | "cell_type": "code", 279 | "execution_count": null, 280 | "metadata": {}, 281 | "outputs": [], 282 | "source": [] 283 | } 284 | ], 285 | "metadata": { 286 | "kernelspec": { 287 | "display_name": "Python 3", 288 | "language": "python", 289 | "name": "python3" 290 | }, 291 | "language_info": { 292 | "codemirror_mode": { 293 | "name": "ipython", 294 | "version": 3 295 | }, 296 | "file_extension": ".py", 297 | "mimetype": "text/x-python", 298 | "name": "python", 299 | "nbconvert_exporter": "python", 300 | "pygments_lexer": "ipython3", 301 | "version": "3.6.4" 302 | } 303 | }, 304 | "nbformat": 4, 305 | "nbformat_minor": 2 306 | } 307 | -------------------------------------------------------------------------------- /jupyter_notebook/4.6_보팅_앙상블_손글씨분류.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# 보팅 앙상블\n", 8 | "단일 모델을 앙상블하여 더 나은 예측을 하는 앙상블 모델을 만들어 보겠습니다." 9 | ] 10 | }, 11 | { 12 | "cell_type": "code", 13 | "execution_count": 1, 14 | "metadata": {}, 15 | "outputs": [], 16 | "source": [ 17 | "from sklearn import datasets\n", 18 | "from sklearn import tree\n", 19 | "from sklearn.neighbors import KNeighborsClassifier\n", 20 | "from sklearn.svm import SVC\n", 21 | "from sklearn.ensemble import VotingClassifier\n", 22 | "from sklearn.model_selection import train_test_split\n", 23 | "from sklearn.metrics import accuracy_score" 24 | ] 25 | }, 26 | { 27 | "cell_type": "markdown", 28 | "metadata": {}, 29 | "source": [ 30 | "# 손글씨 데이터 로드" 31 | ] 32 | }, 33 | { 34 | "cell_type": "code", 35 | "execution_count": 2, 36 | "metadata": {}, 37 | "outputs": [], 38 | "source": [ 39 | "mnist = datasets.load_digits()\n", 40 | "features, labels = mnist.data, mnist.target\n", 41 | "X_train,X_test,y_train,y_test=train_test_split(features,labels,test_size=0.2)" 42 | ] 43 | }, 44 | { 45 | "cell_type": "markdown", 46 | "metadata": {}, 47 | "source": [ 48 | "# 단일 모델 정확도 측정\n", 49 | "의사결정트리, knn, svm 모델의 정확도를 측정합니다." 50 | ] 51 | }, 52 | { 53 | "cell_type": "code", 54 | "execution_count": 3, 55 | "metadata": {}, 56 | "outputs": [], 57 | "source": [ 58 | "dtree = tree.DecisionTreeClassifier(\n", 59 | " criterion=\"gini\", max_depth=8, max_features=32,random_state=35)\n", 60 | "\n", 61 | "dtree = dtree.fit(X_train, y_train)\n", 62 | "dtree_predicted = dtree.predict(X_test)\n", 63 | "\n", 64 | "knn = KNeighborsClassifier(n_neighbors=299).fit(X_train, y_train)\n", 65 | "knn_predicted = knn.predict(X_test)\n", 66 | "\n", 67 | "svm = SVC(C=0.1, gamma=0.003,\n", 68 | " probability=True,random_state=35).fit(X_train, y_train)\n", 69 | "svm_predicted = svm.predict(X_test)" 70 | ] 71 | }, 72 | { 73 | "cell_type": "code", 74 | "execution_count": 4, 75 | "metadata": {}, 76 | "outputs": [ 77 | { 78 | "name": "stdout", 79 | "output_type": "stream", 80 | "text": [ 81 | "[accuarcy]\n", 82 | "d-tree: 0.8027777777777778\n", 83 | "knn : 0.8222222222222222\n", 84 | "svm : 0.8722222222222222\n" 85 | ] 86 | } 87 | ], 88 | "source": [ 89 | "print(\"[accuarcy]\")\n", 90 | "print(\"d-tree: \",accuracy_score(y_test, dtree_predicted))\n", 91 | "print(\"knn : \",accuracy_score(y_test, knn_predicted))\n", 92 | "print(\"svm : \",accuracy_score(y_test, svm_predicted))" 93 | ] 94 | }, 95 | { 96 | "cell_type": "markdown", 97 | "metadata": {}, 98 | "source": [ 99 | "소프트 보팅 또는 하드 보팅은 sklearn의 voting classifier를 사용하여 쉽게 구현할 수 있습니다. \n", 100 | "직접 소프트 보팅을 구현하실 때는 predict_proba 함수를 사용하여 테스트 수행 시 측정된 분류값 별 확률을 사용하시면 됩니다. \n", 101 | "아래 SVM으로부터 나온 테스트 데이터 2개의 0부터 9까지의 확률을 보실 수 있습니다." 102 | ] 103 | }, 104 | { 105 | "cell_type": "code", 106 | "execution_count": 5, 107 | "metadata": {}, 108 | "outputs": [ 109 | { 110 | "name": "stdout", 111 | "output_type": "stream", 112 | "text": [ 113 | "[[0.01045564 0.06913434 0.03714309 0.03658384 0.03749445 0.5259726\n", 114 | " 0.01507642 0.0497424 0.17792086 0.04047637]\n", 115 | " [0.00116351 0.00497346 0.95622888 0.00356861 0.00241151 0.00610898\n", 116 | " 0.00140285 0.00280495 0.01868073 0.00265652]]\n" 117 | ] 118 | } 119 | ], 120 | "source": [ 121 | "svm_proba = svm.predict_proba(X_test)\n", 122 | "print(svm_proba[0:2])" 123 | ] 124 | }, 125 | { 126 | "cell_type": "markdown", 127 | "metadata": {}, 128 | "source": [ 129 | "# 하드 보팅\n", 130 | "하드 보팅은 일반적인 투표와 같이, 각각의 분류기의 예측값들을 모아, 가장 많은 득표를 받은 예측값으로 최종 결론을 내는 방식입니다." 131 | ] 132 | }, 133 | { 134 | "cell_type": "code", 135 | "execution_count": 6, 136 | "metadata": {}, 137 | "outputs": [ 138 | { 139 | "name": "stderr", 140 | "output_type": "stream", 141 | "text": [ 142 | "/anaconda3/envs/wikiml/lib/python3.6/site-packages/sklearn/preprocessing/label.py:151: DeprecationWarning: The truth value of an empty array is ambiguous. Returning False, but in future this will result in an error. Use `array.size > 0` to check that an array is not empty.\n", 143 | " if diff:\n" 144 | ] 145 | }, 146 | { 147 | "data": { 148 | "text/plain": [ 149 | "0.9083333333333333" 150 | ] 151 | }, 152 | "execution_count": 6, 153 | "metadata": {}, 154 | "output_type": "execute_result" 155 | } 156 | ], 157 | "source": [ 158 | "voting_clf = VotingClassifier(estimators=[\n", 159 | " ('decision_tree', dtree), ('knn', knn), ('svm', svm)], \n", 160 | " weights=[1,1,1], voting='hard').fit(X_train, y_train)\n", 161 | "hard_voting_predicted = voting_clf.predict(X_test)\n", 162 | "accuracy_score(y_test, hard_voting_predicted)" 163 | ] 164 | }, 165 | { 166 | "cell_type": "markdown", 167 | "metadata": {}, 168 | "source": [ 169 | "# 소프트 보팅\n", 170 | "소프트 보팅은 각각의 분류모델의 predict_proba을 활용하여, 모든 분류값들의 확률들을 더해서, \n", 171 | "가장 높은 점수를 획득한 분류값으로 최종 결론을 내는 방식입니다." 172 | ] 173 | }, 174 | { 175 | "cell_type": "code", 176 | "execution_count": 7, 177 | "metadata": {}, 178 | "outputs": [ 179 | { 180 | "name": "stderr", 181 | "output_type": "stream", 182 | "text": [ 183 | "/anaconda3/envs/wikiml/lib/python3.6/site-packages/sklearn/preprocessing/label.py:151: DeprecationWarning: The truth value of an empty array is ambiguous. Returning False, but in future this will result in an error. Use `array.size > 0` to check that an array is not empty.\n", 184 | " if diff:\n" 185 | ] 186 | }, 187 | { 188 | "data": { 189 | "text/plain": [ 190 | "0.8916666666666667" 191 | ] 192 | }, 193 | "execution_count": 7, 194 | "metadata": {}, 195 | "output_type": "execute_result" 196 | } 197 | ], 198 | "source": [ 199 | "voting_clf = VotingClassifier(estimators=[\n", 200 | " ('decision_tree', dtree), ('knn', knn), ('svm', svm)], \n", 201 | " weights=[1,1,1], voting='soft').fit(X_train, y_train)\n", 202 | "soft_voting_predicted = voting_clf.predict(X_test)\n", 203 | "accuracy_score(y_test, soft_voting_predicted)" 204 | ] 205 | }, 206 | { 207 | "cell_type": "markdown", 208 | "metadata": {}, 209 | "source": [ 210 | "# 정확도 비교 시각화" 211 | ] 212 | }, 213 | { 214 | "cell_type": "code", 215 | "execution_count": 8, 216 | "metadata": {}, 217 | "outputs": [ 218 | { 219 | "data": { 220 | "image/png": "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\n", 221 | "text/plain": [ 222 | "
" 223 | ] 224 | }, 225 | "metadata": { 226 | "needs_background": "light" 227 | }, 228 | "output_type": "display_data" 229 | } 230 | ], 231 | "source": [ 232 | "import matplotlib.pyplot as plt\n", 233 | "import numpy as np\n", 234 | "%matplotlib inline\n", 235 | "\n", 236 | "x = np.arange(5)\n", 237 | "plt.bar(x, height= [accuracy_score(y_test, dtree_predicted),\n", 238 | " accuracy_score(y_test, knn_predicted),\n", 239 | " accuracy_score(y_test, svm_predicted),\n", 240 | " accuracy_score(y_test, hard_voting_predicted),\n", 241 | " accuracy_score(y_test, soft_voting_predicted)])\n", 242 | "plt.xticks(x, ['decision tree','knn','svm','hard voting','soft voting']);" 243 | ] 244 | } 245 | ], 246 | "metadata": { 247 | "kernelspec": { 248 | "display_name": "Python 3", 249 | "language": "python", 250 | "name": "python3" 251 | }, 252 | "language_info": { 253 | "codemirror_mode": { 254 | "name": "ipython", 255 | "version": 3 256 | }, 257 | "file_extension": ".py", 258 | "mimetype": "text/x-python", 259 | "name": "python", 260 | "nbconvert_exporter": "python", 261 | "pygments_lexer": "ipython3", 262 | "version": "3.6.4" 263 | } 264 | }, 265 | "nbformat": 4, 266 | "nbformat_minor": 2 267 | } 268 | -------------------------------------------------------------------------------- /jupyter_notebook/4.5_베르누이_나이브베이즈_스팸필터_실습.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 27, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "import numpy as np\n", 10 | "import pandas as pd\n", 11 | "\n", 12 | "# 베르누이 나이브베이즈를 위한 라이브러리를 임포트합니다\n", 13 | "from sklearn.feature_extraction.text import CountVectorizer\n", 14 | "from sklearn.naive_bayes import BernoulliNB\n", 15 | "\n", 16 | "# 모델의 정확도 평가를 위해 임포트합니다\n", 17 | "from sklearn.metrics import accuracy_score" 18 | ] 19 | }, 20 | { 21 | "cell_type": "markdown", 22 | "metadata": {}, 23 | "source": [ 24 | "# 문제 정의\n", 25 | "베르누이 나이브베이즈 분류 모델을 사용하여 스팸 메일을 분류해보겠습니다." 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "metadata": {}, 31 | "source": [ 32 | "# 데이터 수집\n", 33 | "이번 실습에서는 간단한 스팸 메일 분류 실습을 위해 아래 이메일 타이틀과 스팸 여부가 있는 데이터를 사용하겠습니다." 34 | ] 35 | }, 36 | { 37 | "cell_type": "code", 38 | "execution_count": 28, 39 | "metadata": {}, 40 | "outputs": [], 41 | "source": [ 42 | "email_list = [\n", 43 | " {'email title': 'free game only today', 'spam': True},\n", 44 | " {'email title': 'cheapest flight deal', 'spam': True},\n", 45 | " {'email title': 'limited time offer only today only today', 'spam': True},\n", 46 | " {'email title': 'today meeting schedule', 'spam': False},\n", 47 | " {'email title': 'your flight schedule attached', 'spam': False},\n", 48 | " {'email title': 'your credit card statement', 'spam': False}\n", 49 | " ]\n", 50 | "df = pd.DataFrame(email_list)" 51 | ] 52 | }, 53 | { 54 | "cell_type": "code", 55 | "execution_count": 29, 56 | "metadata": {}, 57 | "outputs": [ 58 | { 59 | "data": { 60 | "text/html": [ 61 | "
\n", 62 | "\n", 75 | "\n", 76 | " \n", 77 | " \n", 78 | " \n", 79 | " \n", 80 | " \n", 81 | " \n", 82 | " \n", 83 | " \n", 84 | " \n", 85 | " \n", 86 | " \n", 87 | " \n", 88 | " \n", 89 | " \n", 90 | " \n", 91 | " \n", 92 | " \n", 93 | " \n", 94 | " \n", 95 | " \n", 96 | " \n", 97 | " \n", 98 | " \n", 99 | " \n", 100 | " \n", 101 | " \n", 102 | " \n", 103 | " \n", 104 | " \n", 105 | " \n", 106 | " \n", 107 | " \n", 108 | " \n", 109 | " \n", 110 | " \n", 111 | " \n", 112 | " \n", 113 | " \n", 114 | " \n", 115 | "
email titlespam
0free game only todayTrue
1cheapest flight dealTrue
2limited time offer only today only todayTrue
3today meeting scheduleFalse
4your flight schedule attachedFalse
5your credit card statementFalse
\n", 116 | "
" 117 | ], 118 | "text/plain": [ 119 | " email title spam\n", 120 | "0 free game only today True\n", 121 | "1 cheapest flight deal True\n", 122 | "2 limited time offer only today only today True\n", 123 | "3 today meeting schedule False\n", 124 | "4 your flight schedule attached False\n", 125 | "5 your credit card statement False" 126 | ] 127 | }, 128 | "execution_count": 29, 129 | "metadata": {}, 130 | "output_type": "execute_result" 131 | } 132 | ], 133 | "source": [ 134 | "df" 135 | ] 136 | }, 137 | { 138 | "cell_type": "markdown", 139 | "metadata": {}, 140 | "source": [ 141 | "# 데이터 다듬기\n", 142 | "sklearn의 베르누이 나이브베이즈 분류기(BernoulliNB)는 숫자만을 다루기 때문에, \n", 143 | "True와 False를 1과 0으로 치환하겠습니다." 144 | ] 145 | }, 146 | { 147 | "cell_type": "code", 148 | "execution_count": 30, 149 | "metadata": {}, 150 | "outputs": [ 151 | { 152 | "data": { 153 | "text/html": [ 154 | "
\n", 155 | "\n", 168 | "\n", 169 | " \n", 170 | " \n", 171 | " \n", 172 | " \n", 173 | " \n", 174 | " \n", 175 | " \n", 176 | " \n", 177 | " \n", 178 | " \n", 179 | " \n", 180 | " \n", 181 | " \n", 182 | " \n", 183 | " \n", 184 | " \n", 185 | " \n", 186 | " \n", 187 | " \n", 188 | " \n", 189 | " \n", 190 | " \n", 191 | " \n", 192 | " \n", 193 | " \n", 194 | " \n", 195 | " \n", 196 | " \n", 197 | " \n", 198 | " \n", 199 | " \n", 200 | " \n", 201 | " \n", 202 | " \n", 203 | " \n", 204 | " \n", 205 | " \n", 206 | " \n", 207 | " \n", 208 | " \n", 209 | " \n", 210 | " \n", 211 | " \n", 212 | " \n", 213 | " \n", 214 | " \n", 215 | "
email titlespamlabel
0free game only todayTrue1
1cheapest flight dealTrue1
2limited time offer only today only todayTrue1
3today meeting scheduleFalse0
4your flight schedule attachedFalse0
5your credit card statementFalse0
\n", 216 | "
" 217 | ], 218 | "text/plain": [ 219 | " email title spam label\n", 220 | "0 free game only today True 1\n", 221 | "1 cheapest flight deal True 1\n", 222 | "2 limited time offer only today only today True 1\n", 223 | "3 today meeting schedule False 0\n", 224 | "4 your flight schedule attached False 0\n", 225 | "5 your credit card statement False 0" 226 | ] 227 | }, 228 | "execution_count": 30, 229 | "metadata": {}, 230 | "output_type": "execute_result" 231 | } 232 | ], 233 | "source": [ 234 | "df['label'] = df['spam'].map({True:1,False:0})\n", 235 | "df" 236 | ] 237 | }, 238 | { 239 | "cell_type": "code", 240 | "execution_count": 31, 241 | "metadata": {}, 242 | "outputs": [], 243 | "source": [ 244 | "# 학습에 사용될 데이터와 분류값을 나눕니다\n", 245 | "df_x=df[\"email title\"]\n", 246 | "df_y=df[\"label\"]" 247 | ] 248 | }, 249 | { 250 | "cell_type": "markdown", 251 | "metadata": {}, 252 | "source": [ 253 | "베르누이 나이브베이즈의 입력 데이터는 고정된 크기의 벡터로써, 0과 1로 구분된 데이터이여야 합니다. \n", 254 | "sklearn의 CountVectorizer를 사용하여 쉽게 구현할 수 있습니다. \n", 255 | "CountVectorizer는 입력된 데이터(6개의 이메일)에 출현된 모든 단어의 갯수만큼의 크기의 벡터를 만든 후, \n", 256 | "각각의 이메일을 그 고정된 벡터로 표현합니다. \n", 257 | "binary=True를 파라미터를 넘겨줌으로써, 각각의 이메일마다 단어가 한번 이상 출현하면 1, 출현하지 않을 경우 0으로 표시하게 합니다." 258 | ] 259 | }, 260 | { 261 | "cell_type": "code", 262 | "execution_count": 32, 263 | "metadata": {}, 264 | "outputs": [], 265 | "source": [ 266 | "cv = CountVectorizer(binary=True)\n", 267 | "x_traincv=cv.fit_transform(df_x)" 268 | ] 269 | }, 270 | { 271 | "cell_type": "markdown", 272 | "metadata": {}, 273 | "source": [ 274 | "아래의 행렬에서 볼 수 있듯, 데이터에서 총 17개의 단어가 발견되어, 각각의 이메일이 17개의 크기를 갖는 벡터로 표현되었습니다. \n", 275 | "또한 베르누이 나이브베이즈에 사용하기 위해 중복된 단어가 이메일 제목에 있더라도, 1로 표현된 것을 확인할 수 있습니다. \n", 276 | "limited time offer only today only today: [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0]" 277 | ] 278 | }, 279 | { 280 | "cell_type": "code", 281 | "execution_count": 33, 282 | "metadata": {}, 283 | "outputs": [ 284 | { 285 | "data": { 286 | "text/plain": [ 287 | "array([[0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0],\n", 288 | " [0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n", 289 | " [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0],\n", 290 | " [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0],\n", 291 | " [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1],\n", 292 | " [0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1]], dtype=int64)" 293 | ] 294 | }, 295 | "execution_count": 33, 296 | "metadata": {}, 297 | "output_type": "execute_result" 298 | } 299 | ], 300 | "source": [ 301 | "encoded_input=x_traincv.toarray()\n", 302 | "encoded_input" 303 | ] 304 | }, 305 | { 306 | "cell_type": "markdown", 307 | "metadata": {}, 308 | "source": [ 309 | "벡터로 인코딩된 이메일 제목에 어떤 단어들이 포함되어 있는 지 알고 싶을 경우, 아래의 명령어로 알 수 있습니다." 310 | ] 311 | }, 312 | { 313 | "cell_type": "code", 314 | "execution_count": 34, 315 | "metadata": {}, 316 | "outputs": [ 317 | { 318 | "data": { 319 | "text/plain": [ 320 | "[array(['free', 'game', 'only', 'today'], dtype='" 108 | ] 109 | }, 110 | "execution_count": 7, 111 | "metadata": {}, 112 | "output_type": "execute_result" 113 | }, 114 | { 115 | "data": { 116 | "image/png": "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+OKLmT17NhC04K+++mpefPFFqqqqePrppxk2bBi7du3i8ssvp6ioiAkTJuDe0Bnxy1/+kocffhiAb3zjG9x8881s2LCBadOmMXnyZN577z1Gjx7NNddcw6xZs9ixYwePP/44EyZMaFbPHTt2cMUVV1BUVMSYMWN49tln2bBhA7fccgvV1dWMHz+e++67j65du5Kdnc21117Lq6++yo033sj48eO54YYbKCoqIjU1lQcffJBhw4bx9NNPM3v2bBITE+nVqxevv/46t99+O2VlZbz99tvcdtttMe9cYnHYlr67VwM3Aq8AqwhG6awwszlmNiNS7PvAN81sKfAEMNODT/1eoAfwAcHO4xF3X9ZmtReRTmP16tVcddVVLF68mP/6r/8iPz+fZcuW8eabb7JsWUNsZGRksGjRIr71rW8xd+5cAGbPns3kyZNZvHgxM2bMYNOmTQAUFBTwyCOP8P777/Pee+/x4IMPsnjxYgDWrVvHTTfdxLJly/jwww/5wx/+wNtvv83cuXP52c9+1mId+/fvz0MPPcTZZ5/NkiVLGDhwIDNnzuTJJ59k+fLlVFdXc99999WXT0lJ4e233+ayyy7juuuu41e/+hUFBQXMnTuXb3/72wDMmTOHV155haVLlzJv3jySk5OZM2cOl1566REdTcQqpnH67j6f4ARt9LLbo+6vBCa18LpSgmGbInKcOFSLvD1lZWVx5plnAvDUU0/xwAMPUF1dzbZt21i5ciVnnHEGAF/60pcAyM3N5bnnngPgrbfeqr//uc99jvT0dADefvttLrroIrp3717/2n/84x/MmDGDnJwcRo0aBcDIkSOZOnUqZsaoUaPYsGFDTHVevXo1OTk5DB06FICrr76ae++9l5tvvhmgPrBLS0t59913ueSShjisqKgAYNKkScycOZOvfOUr9dvWnnRFroh0CHXB/PHHHzN37lwWLlxIeno6M2fObDQuvWvXrgAkJiZSXV1dv7yloYzR3TxN1b0PQEJCQv3jhISERu97KId6f2jYptraWnr37s2SJUualbn//vt5//33eemllxgzZkyLZdqS5t4RkQ6luLiY7t2706tXL7Zv387LL7982Necc845PP744wC8/PLL7Nmzp375n/70Jw4cOMD+/ft5/vnnOfvss9usrsOGDWPDhg2sW7cOgN/97ndMmTKlWbmePXuSk5PD008/DQQ7i6VLlwLw0UcfMXHiRObMmUNGRgabN28mLS2NkpKSNqtnNIW+iHQoo0ePZuzYsYwcOZJrr72WSZOa9Rw3M2vWLN566y3GjRvHq6++yuDBgwEYN24cM2fOZMKECUycOJFvfOMbjB07ts3qmpKSwiOPPMIll1zCqFGjSEhI4Prrr2+x7OOPP85vfvMbRo8ezciRI3nhhRcAuPXWWxk1ahSnn34655xzDqNHj+bTn/40K1eubJdhoXa4w5NjLS8vz/Pz8+NdDZFQWbVqFcOHD493NSRGLf2+zKzA3ZsNiW9KLX0RkRDRiVwRkRY88sgj3H333Y2WTZo0iXvvvTdONWobCn0RkRZcc801XHPNNfGuRptT946ISIgo9EVEQkShLyISIgp9EZEQUeiLSIdzxx131E+mdiTOOuusQz4/ffp09u7d29pqNfPoo4+ydWvTmeY7NoW+iHQa77777iGfnz9/Pr17926z9R0q9I90Dv1jRUM2RaSxl38Enyxv2/c8cRRc8O+HLHLnnXfy2GOPMWjQIPr160dubi4fffRRi3PQb9++neuvv57169cDcN9993HWWWfRo0cPSktL2bZtG5deeinFxcX10x2fffbZZGdnk5+fT0ZGxkHn2b/ggguYPHky7777LgMHDuSFF16gW7duzer7zDPPkJ+fz9e+9jW6devGggULGD58eExz6BcVFXH99dfXTwF91113xTTdRFtQ6ItI3BUUFPDHP/6RxYsXU11dzbhx48jNzeW6667j/vvvZ8iQIbz//vt8+9vf5m9/+xvf/e53mTJlCs8//zw1NTWUlpY2er8//OEPnH/++fzkJz+hpqaGAwcONFtf3Tz77s7EiROZMmUK6enprF27lieeeIIHH3yQr3zlKzz77LNcccUVzep88cUXc8899zB37lzy8hpmP6ibQx9g6tSpLdb/pptu4nvf+x6TJ09m06ZNnH/++axataodPtnmFPoi0thhWuTt4R//+AcXXXQRqampAMyYMYPy8vKDzkH/t7/9jcceewyg/hunoo0fP55rr72WqqoqvvjFLzJmzJhGzx9unv268rm5uTHPrV8nljn0X3/9dVauXFm/vLi4mJKSEtLS0o5oXa2h0BeRDqHpfPiHmoP+cM455xzeeustXnrpJa688kpuvfVWrrrqqvrnY51nPzExkbKysiNadyxz6NfW1rJgwYIWu43am07kikjcnXPOOTz//POUlZVRUlLCiy++SGpq6kHnoJ86dWr91xLW1NRQXNz4O303btxI//79+eY3v8nXv/51Fi1a1Gx9bTHP/qHmvT/UHPrnnXce99xzT33Z9v7ilGgKfRGJu3HjxnHppZcyZswYvvzlL9cH8MHmoL/77rt54403GDVqFLm5uaxYsaLR+/39739nzJgxjB07lmeffZabbrqp2fraYp79mTNncv311zNmzJgWjwgOVv//+Z//IT8/nzPOOIMRI0Zw//33H/G6W0vz6YuI5tM/zmg+fRERiYlO5IqIHMYNN9zAO++802jZTTfddFxOvazQFxEgONHYdASNBDrSF6ccbZe8undEhJSUFHbt2nXUgSLty93ZtWsXKSkprX4PtfRFhMzMTAoLCykqKop3VeQwUlJSyMzMbPXrFfoiQpcuXcjJyYl3NeQYUPeOiEiIKPRFREJEoS8iEiIKfRGREFHoi4iESEyhb2bTzGy1ma0zsx+18PxgM3vDzBab2TIzmx713BlmtsDMVpjZcjNr/QBTERE5KocdsmlmicC9wGeBQmChmc1z95VRxX4KPOXu95nZCGA+kG1mScDvgSvdfamZ9QWq2nwrREQkJrG09CcA69x9vbtXAn8ELmxSxoGekfu9gLpvCj4PWObuSwHcfZe7d8xvCxYRCYFYQn8gsDnqcWFkWbQ7gCvMrJCglf+dyPKhgJvZK2a2yMx+0NIKzOw6M8s3s3xdESgi0n5iCf2WZmBqOkHH5cCj7p4JTAd+Z2YJBN1Hk4GvRW4vMrOpzd7M/QF3z3P3vH79+h3RBoiISOxiCf1CYFDU40waum/qfB14CsDdFwApQEbktW+6+053P0BwFDDuaCstIiKtE0voLwSGmFmOmSUDlwHzmpTZBEwFMLPhBKFfBLwCnGFmqZGTulOAlYiISFwcdvSOu1eb2Y0EAZ4IPOzuK8xsDpDv7vOA7wMPmtn3CLp+ZnowR+seM/slwY7Dgfnu/lJ7bYyIiByaviNXRKQT0HfkiohIMwp9EZEQUeiLiISIQl9EJEQU+iIiIaLQFxEJEYW+iEiIKPRFREJEoS8iEiIKfRGREFHoi4iEiEJfRCREFPoiIiGi0BcRCRGFvohIiCj0RURCRKEvIhIiCn0RkRBR6IuIhIhCX0QkRBT6IiIhotAXEQkRhb6ISIgo9EVEQkShLyISIgp9EZEQUeiLiISIQl9EJEQU+iIiIaLQFxEJEYW+iEiIxBT6ZjbNzFab2Toz+1ELzw82szfMbLGZLTOz6S08X2pmt7RVxUVE5MgdNvTNLBG4F7gAGAFcbmYjmhT7KfCUu48FLgN+3eT5/wZePvrqiojI0YilpT8BWOfu6929EvgjcGGTMg70jNzvBWyte8LMvgisB1YcfXVFRORoxBL6A4HNUY8LI8ui3QFcYWaFwHzgOwBm1h34ITD7UCsws+vMLN/M8ouKimKsuoiIHKlYQt9aWOZNHl8OPOrumcB04HdmlkAQ9v/t7qWHWoG7P+Duee6e169fv1jqLSIirZAUQ5lCYFDU40yium8ivg5MA3D3BWaWAmQAE4GLzew/gd5ArZmVu/s9R11zERE5YrGE/kJgiJnlAFsITtR+tUmZTcBU4FEzGw6kAEXufnZdATO7AyhV4IuIxM9hu3fcvRq4EXgFWEUwSmeFmc0xsxmRYt8HvmlmS4EngJnu3rQLSERE4sw6Wjbn5eV5fn5+vKshInJcMbMCd887XDldkSsiEiIKfRGREOlcob97PXSw7iqRDqe2Fkq2638lpGIZvXN8KNkO94yHfsMh92oYdQl06x3vWonEX3kxbMmHzf8MfrbkQ/k+GDoNPv/f0HNAvGsox1DnOZFbUQrLnoRFv4VtSyGpG4z8Ioy7GgafCdbSNWYSGrW1wd9AZ/87cIeda6EwEvCFC2HHKoLrKQ36j4BB4yG1Lyz4NSQmw/l3wtgrOv9n08nFeiK384R+tK1LgvBf9jRUlkDGUBh3FYz+KnTv2zYVlY6vbC+sex3W/AXWvgY1lZAxBDJOg35Dod+w4H6fHEjsEu/atk5FCWwpgM0LG4K+fG/wXEovyBwPmRNg0AQYmAspPRteu+sjmPcd2PgOnDIVvnA39B7U8nqkwwt36Nep3A8rnoeC3wb/EAldYPjng9Z/zhRI6FynNIQgyNb8BVa/DJsWQG110Kodch6k9Iadq6FoDRQXNrwmIQn6nBLsCDJOg36nBQ2FjCGQ3D1+29KUe7B9jVrxK8Frg+f7DQ9a8XUh33fI4f/Ga2th4UPw+h1gCXDeHMi9Rq3+45BCv6ntK2HRY7D0iaAllJ4NY68MDmvTTmz79cmxUVMNm9+HNS/D6r/ArrXB8n7D4bRpMPQCyMyDhMTGr6sohZ1rgp+i1ZHbD2H3x+A1DeV6DY7aGUTtFFL7tP+2VZTC1kUNAb/5n1C2O3iua89guzInBEE/MO/ozmHt2RC0+j9+C3LOgRm/Cv5H5Lih0D+YqnJY9WLQ/bPhH2CJwQmt3Kvh1HObh4N0PE27bcr3Bkdx2ZPhtAtg6PmtD6zqStj9UdSOYHVwdLBzHVSXNZRLzQi6h5ruEHoOaF0r2T0YfVYX7oX/hO0rGlrxGUMbAn7QxGBdbX2k6g4Fj8Kr/zdY77l3wPhv6Ij4OKHQj8Wuj4LwX/IH2F8EPQcGLf+xV6pvs6M5VLfN0Gll9ZtMAAAJg0lEQVRwymca91e3tdpa2Lcp6BraubrxTqGuDx0gOS3oFqrrIup3WhDQ6dmQGDVYrvJA81b8gZ2R9+gR1YqP9MUfiyOLOns3w4s3wUd/haxJQau/7ynHbv3SKgr9I1FTFYTJot/Cur8Gy06dGvT9n3bB8XuS73jW2m6bY80dSnc03xHsXAMl2xrKJSYH5w36ngL7NsMnHzR0I/U9taEVnzkB+g/vGNu1+Pfwyk+CE+BTb4eJ/xL/eslBKfRba++m4I998e+heAt07w9jvhqM/jkeWjs11UG993wMB3ZBjxMg7aTgvEVHOinZkvpum1dg7auNu22GTgu6bfrkxLuWsSvfFwyfrOsiKloDu9YFv4tBE4Jumszxx7YVf6SKt8KLN8PaV4L6XnhvcCQjHY5C/2jV1gQBVPDboFvBayD7bMidCcM+D11S4le3ygPBibc9HwcnHqNv924Kuj5a0rVXEDhpJwZ9z2knNuwQ0iKPe5wAScnHblvi3W0jh+cOy56Cl38AVWXw6R/Dp25s3F0lcafQb0vF22DJ48Hon70boVs6jL486P7pP6zt1+cOB3a3HOq7P4bSTxqXT+kF6TlBKzj6NrUv7N8BJZ8EXQ3F24Lbuscln0BtVfP1p2ZAz5Oa7xDqHvccEJRpzQm+6G6bNa8E3SDQ8bptpLmS7fDSv8KHf4YB4+CLvw66oqRDUOi3h9pa+PjNoO9/1Z+DwBw0MQj/kV88su6T2hrYV9hCsG8IfiqKG5dPGxAV6tlNwr2V3QO1tcEQwOKtjXcEJVsb7yj2F9HsGzITkhp3HUXvEOofnxTskMr3BScFV/8F1r0GZXsi3TaTgpA/3rptwswdPngW5t8KlaUw5Ycw6Sad9+oAFPrtbf/OYMx/wW+Dk4xdewbz/Yy7CgaMCcpUlQUB3lJrfe+mxq3shC6QntVyiz09C7p0i8tmAsGJ7tIdLe8Qoo8cokex1EnqFmxnbTV06xMEvLptjn+lRTD/Flj5JzhpNFz4azjx9HjXKtQU+seKe9AXveix4Orf6vJgNEbl/sajNyDoU2/aSq+77Tng+O/SqDwQdD2VfNL46CGpa9BHnzn++N9GaWzlC/DS94Ojt3Nuhcn/emzPCUk9hX48lO2F5U8HI0+692se7t3SdXm7dD77d8Fffhj87Z9wejDCp+5oV44Zhb6IHFsfzoc/fy84BzT5ezDlB8FRnhwT+rpEETm2hk2HG96DMy6Ff8yF/50ChQXxrpU0odAXkbbTLR0uug++9kwwaus358JrtwdzXkmHoNAXkbY35LNBq3/sFfDO3XD/ZNj0frxr1fHU1gTX5Oz6KDgq2rKo3VepS+pEpH2k9Aomaxt5Ecz7Ljx8Ppz5bfjMTyE5Nd61a1s11cGQ5bI9QYiX7Yntp3wfja6BGZgH3/xru1ZVoS8i7euUz8C3F8Brs+C9e4OrsWfcE1yc19FUV8Qe2PU/e5tfTNmIBd910C09+EntE8zjVfc4+ucYfLeHQl9E2l/XNPj8L4Mr11+4ER6dDhOug6mzoGuPxmXdg4v5qsuDEK6/rWi8rKayFWVaeE1NRXBdTdleqNp/8G2wxMYB3ePEYPqQlsK7WzqkRm679upQ30mg0BeRYyfnnKDV/9c58P7/wvJngtBvGsZNp/1ojaSUYMhoYteG+0kpwcVjSSnBFeF1y7ukRsK690FCvE+w4+oE19ko9EXk2EruDhf8B4y4EPIfCb6bN6lr1M/BwvoIyiQmd4qAbg8KfRGJj6yzgh85pjpOR5OIiLQ7hb6ISIjEFPpmNs3MVpvZOjP7UQvPDzazN8xssZktM7PpkeWfNbMCM1seuf1MW2+AiIjE7rB9+maWCNwLfBYoBBaa2Tx3XxlV7KfAU+5+n5mNAOYD2cBO4AvuvtXMTgdeAQa28TaIiEiMYmnpTwDWuft6d68E/ghc2KSMA3XfiNEL2Arg7ovdfWtk+Qogxcw07Z6ISJzEMnpnILA56nEhMLFJmTuAV83sO0B34NwW3ufLwGJ3r2hFPUVEpA3E0tJvabBr0ysnLgcedfdMYDrwOzOrf28zGwn8B/AvLa7A7Dozyzez/KKiothqLiIiRyyW0C8EBkU9ziTSfRPl68BTAO6+AEgBMgDMLBN4HrjK3T9qaQXu/oC757l7Xr9+/Y5sC0REJGaxdO8sBIaYWQ6wBbgM+GqTMpuAqcCjZjacIPSLzKw38BJwm7u/E0uFCgoKdprZxlg3oAUZBCeQRZ9FU/o8GtPn0aAzfBZZsRSK6esSI0Mw7wISgYfd/U4zmwPku/u8yIidB4EeBF0/P3D3V83sp8BtwNqotzvP3Xcc2bbEzszyY/nKsDDQZ9GYPo/G9Hk0CNNn0eG+I/dohemXdzj6LBrT59GYPo8GYfosdEWuiEiIdMbQfyDeFehA9Fk0ps+jMX0eDULzWXS67h0RETm4ztjSFxGRg+g0oX+4SeHCxMwGRSbAW2VmK8zspnjXKd7MLDEyIeCf412XeDOz3mb2jJl9GPkb+VS86xRPZva9yP/JB2b2hJmlxLtO7alThH7UpHAXACOAyyPDSMOqGvi+uw8HzgRuCPnnAXATsCrelegg7gb+4u7DgNGE+HMxs4HAd4E8dz+dYFj6ZfGtVfvqFKFPbJPChYa7b3P3RZH7JQT/1KGd3TRyVfjngIfiXZd4M7OewDnAbwDcvdLd98a3VnGXBHQzsyQgleYzDnQqnSX0W5oULrQhF83MsoGxwPvxrUlc3QX8AKiNd0U6gJOBIuCRSHfXQ2bWPd6Vihd33wLMJZhVYBuwz91fjW+t2ldnCf1YJoULHTPrATwL3OzuxfGuTzyY2eeBHe5eEO+6dBBJwDjgPncfC+wHQnsOzMzSCXoFcoABQHczuyK+tWpfnSX0Y5kULlTMrAtB4D/u7s/Fuz5xNAmYYWYbCLr9PmNmv49vleKqECh097ojv2cIdgJhdS7wsbsXuXsV8BzQqb+tvbOEfv2kcGaWTHAiZl6c6xQ3ZmYEfbar3P2X8a5PPLn7be6e6e7ZBH8Xf3P3Tt2SOxR3/wTYbGanRRZNBVYe4iWd3SbgTDNLjfzfTKWTn9iOZZbNDs/dq83sRoKvY6ybFG5FnKsVT5OAK4HlZrYksuzH7j4/jnWSjuM7wOORBtJ64Jo41ydu3P19M3sGWEQw6m0xnfzqXF2RKyISIp2le0dERGKg0BcRCRGFvohIiCj0RURCRKEvIhIiCn0RkRBR6IuIhIhCX0QkRP4/jCmRgT3uGTgAAAAASUVORK5CYII=\n", 117 | "text/plain": [ 118 | "
" 119 | ] 120 | }, 121 | "metadata": { 122 | "needs_background": "light" 123 | }, 124 | "output_type": "display_data" 125 | } 126 | ], 127 | "source": [ 128 | "df.plot()" 129 | ] 130 | }, 131 | { 132 | "cell_type": "markdown", 133 | "metadata": {}, 134 | "source": [ 135 | "# 의사결정트리 정확도" 136 | ] 137 | }, 138 | { 139 | "cell_type": "code", 140 | "execution_count": 8, 141 | "metadata": {}, 142 | "outputs": [ 143 | { 144 | "data": { 145 | "text/plain": [ 146 | "0.8299843603306816" 147 | ] 148 | }, 149 | "execution_count": 8, 150 | "metadata": {}, 151 | "output_type": "execute_result" 152 | } 153 | ], 154 | "source": [ 155 | "np.mean(dt_cv_scores)" 156 | ] 157 | }, 158 | { 159 | "cell_type": "markdown", 160 | "metadata": {}, 161 | "source": [ 162 | "# 랜덤포레스트 정확도" 163 | ] 164 | }, 165 | { 166 | "cell_type": "code", 167 | "execution_count": 9, 168 | "metadata": {}, 169 | "outputs": [ 170 | { 171 | "data": { 172 | "text/plain": [ 173 | "0.9184765057826823" 174 | ] 175 | }, 176 | "execution_count": 9, 177 | "metadata": {}, 178 | "output_type": "execute_result" 179 | } 180 | ], 181 | "source": [ 182 | "np.mean(rf_cv_scores)" 183 | ] 184 | } 185 | ], 186 | "metadata": { 187 | "kernelspec": { 188 | "display_name": "Python 3", 189 | "language": "python", 190 | "name": "python3" 191 | }, 192 | "language_info": { 193 | "codemirror_mode": { 194 | "name": "ipython", 195 | "version": 3 196 | }, 197 | "file_extension": ".py", 198 | "mimetype": "text/x-python", 199 | "name": "python", 200 | "nbconvert_exporter": "python", 201 | "pygments_lexer": "ipython3", 202 | "version": "3.6.4" 203 | } 204 | }, 205 | "nbformat": 4, 206 | "nbformat_minor": 2 207 | } 208 | -------------------------------------------------------------------------------- /jupyter_notebook/6.1_CNN_MNIST_손글씨_예측모델.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# CNN (Convolutional Neural Network)" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": 5, 13 | "metadata": {}, 14 | "outputs": [], 15 | "source": [ 16 | "from IPython.display import Image" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "## 텐서플로우로 CNN 실습하기\n", 24 | "텐서플로우로 아래 그림과 동일한 CNN을 직접 구현하고, MNIST 손글씨로 학습 및 테스트를 진행보도록 하겠습니다." 25 | ] 26 | }, 27 | { 28 | "cell_type": "code", 29 | "execution_count": 6, 30 | "metadata": {}, 31 | "outputs": [ 32 | { 33 | "data": { 34 | "text/html": [ 35 | "" 36 | ], 37 | "text/plain": [ 38 | "" 39 | ] 40 | }, 41 | "execution_count": 6, 42 | "metadata": {}, 43 | "output_type": "execute_result" 44 | } 45 | ], 46 | "source": [ 47 | "Image(url= \"https://raw.githubusercontent.com/captainchargers/deeplearning/master/img/practice_cnn.png\", width=800, height=200)" 48 | ] 49 | }, 50 | { 51 | "cell_type": "code", 52 | "execution_count": 7, 53 | "metadata": {}, 54 | "outputs": [], 55 | "source": [ 56 | "import tensorflow as tf" 57 | ] 58 | }, 59 | { 60 | "cell_type": "markdown", 61 | "metadata": {}, 62 | "source": [ 63 | "### 데이터 획득" 64 | ] 65 | }, 66 | { 67 | "cell_type": "code", 68 | "execution_count": 8, 69 | "metadata": {}, 70 | "outputs": [], 71 | "source": [ 72 | "(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()" 73 | ] 74 | }, 75 | { 76 | "cell_type": "markdown", 77 | "metadata": {}, 78 | "source": [ 79 | "### 학습데이터에서 검증 데이터 분리하기\n", 80 | "학습 중간마다 검증 데이터로 모델의 성능을 측정하면 다음과 같은 장점이 있습니다. \n", 81 | "1) 모델 학습이 제대로 진행되는 지 검증 정확도로 확인할 수 있습니다. \n", 82 | "2) 학습 정확도는 올라가는 데 검증 정확도가 안올라가거나 떨어질 시, 조기 종료를 구현할 수 있습니다." 83 | ] 84 | }, 85 | { 86 | "cell_type": "code", 87 | "execution_count": 9, 88 | "metadata": {}, 89 | "outputs": [], 90 | "source": [ 91 | "x_val = x_train[50000:60000]\n", 92 | "x_train = x_train[0:50000]\n", 93 | "y_val = y_train[50000:60000]\n", 94 | "y_train = y_train[0:50000]" 95 | ] 96 | }, 97 | { 98 | "cell_type": "code", 99 | "execution_count": 10, 100 | "metadata": {}, 101 | "outputs": [ 102 | { 103 | "name": "stdout", 104 | "output_type": "stream", 105 | "text": [ 106 | "train data has 50000 samples\n", 107 | "every train data is 28 * 28 image\n" 108 | ] 109 | } 110 | ], 111 | "source": [ 112 | "print(\"train data has \" + str(x_train.shape[0]) + \" samples\")\n", 113 | "print(\"every train data is \" + str(x_train.shape[1]) \n", 114 | " + \" * \" + str(x_train.shape[2]) + \" image\")" 115 | ] 116 | }, 117 | { 118 | "cell_type": "code", 119 | "execution_count": 11, 120 | "metadata": {}, 121 | "outputs": [ 122 | { 123 | "name": "stdout", 124 | "output_type": "stream", 125 | "text": [ 126 | "validation data has 10000 samples\n", 127 | "every train data is 28 * 28 image\n" 128 | ] 129 | } 130 | ], 131 | "source": [ 132 | "print(\"validation data has \" + str(x_val.shape[0]) + \" samples\")\n", 133 | "print(\"every train data is \" + str(x_val.shape[1]) \n", 134 | " + \" * \" + str(x_train.shape[2]) + \" image\")" 135 | ] 136 | }, 137 | { 138 | "cell_type": "markdown", 139 | "metadata": {}, 140 | "source": [ 141 | "**0** 부터 **255** 까지의 그레이 스케일을 확인할 수 있습니다." 142 | ] 143 | }, 144 | { 145 | "cell_type": "code", 146 | "execution_count": 12, 147 | "metadata": {}, 148 | "outputs": [ 149 | { 150 | "name": "stdout", 151 | "output_type": "stream", 152 | "text": [ 153 | "[ 0 0 0 0 0 0 0 18 219 253 253 253 253 253 198 182 247 241\n", 154 | " 0 0 0 0 0 0 0 0 0 0]\n" 155 | ] 156 | } 157 | ], 158 | "source": [ 159 | "# sample to show gray scale values\n", 160 | "print(x_train[0][8])" 161 | ] 162 | }, 163 | { 164 | "cell_type": "markdown", 165 | "metadata": {}, 166 | "source": [ 167 | "**0** 부터 **9**까지의 이미지에 해당하는 숫자를 확인할 수 있습니다." 168 | ] 169 | }, 170 | { 171 | "cell_type": "code", 172 | "execution_count": 13, 173 | "metadata": {}, 174 | "outputs": [ 175 | { 176 | "name": "stdout", 177 | "output_type": "stream", 178 | "text": [ 179 | "[5 0 4 1 9 2 1 3 1]\n" 180 | ] 181 | } 182 | ], 183 | "source": [ 184 | "# sample to show labels for first train data to 10th train data\n", 185 | "print(y_train[0:9])" 186 | ] 187 | }, 188 | { 189 | "cell_type": "markdown", 190 | "metadata": {}, 191 | "source": [ 192 | "테스트 데이터는 **10000** 개의 샘플을 가지고 있습니다. \n", 193 | "모든 테스트 데이터는 **28 * 28** 의 이미지입니다." 194 | ] 195 | }, 196 | { 197 | "cell_type": "code", 198 | "execution_count": 14, 199 | "metadata": {}, 200 | "outputs": [ 201 | { 202 | "name": "stdout", 203 | "output_type": "stream", 204 | "text": [ 205 | "test data has 10000 samples\n", 206 | "every test data is 28 * 28 image\n" 207 | ] 208 | } 209 | ], 210 | "source": [ 211 | "print(\"test data has \" + str(x_test.shape[0]) + \" samples\")\n", 212 | "print(\"every test data is \" + str(x_test.shape[1]) \n", 213 | " + \" * \" + str(x_test.shape[2]) + \" image\")" 214 | ] 215 | }, 216 | { 217 | "cell_type": "markdown", 218 | "metadata": {}, 219 | "source": [ 220 | "### 데이터 구조 변경하기\n", 221 | "입력 레이어에 데이터를 넣기 위해서 데이터의 구조를 변경해줍니다." 222 | ] 223 | }, 224 | { 225 | "cell_type": "code", 226 | "execution_count": 15, 227 | "metadata": {}, 228 | "outputs": [ 229 | { 230 | "name": "stdout", 231 | "output_type": "stream", 232 | "text": [ 233 | "(50000, 28, 28, 1)\n", 234 | "(10000, 28, 28, 1)\n" 235 | ] 236 | } 237 | ], 238 | "source": [ 239 | "import numpy as np\n", 240 | "x_train = np.reshape(x_train, (50000,28,28,1))\n", 241 | "x_val = np.reshape(x_val, (10000,28,28,1))\n", 242 | "x_test = np.reshape(x_test, (10000,28,28,1))\n", 243 | "\n", 244 | "print(x_train.shape)\n", 245 | "print(x_test.shape)" 246 | ] 247 | }, 248 | { 249 | "cell_type": "markdown", 250 | "metadata": {}, 251 | "source": [ 252 | "### 데이터 정규화\n", 253 | "데이터 정규화는 보통 학습 시간을 단축하고, 더 나은 성능을 구하도록 도와줍니다. \n", 254 | "MNIST 데이터의 모든 값은 0부터 255의 범위 안에 있으므로, 255로 값을 나눠줌으로써, 모든 값을 0부터 1 사이의 값으로 정규화합니다. " 255 | ] 256 | }, 257 | { 258 | "cell_type": "code", 259 | "execution_count": 16, 260 | "metadata": {}, 261 | "outputs": [], 262 | "source": [ 263 | "x_train = x_train.astype('float32')\n", 264 | "x_val = x_val.astype('float32')\n", 265 | "x_test = x_test.astype('float32')\n", 266 | "\n", 267 | "gray_scale = 255\n", 268 | "x_train /= gray_scale\n", 269 | "x_val /= gray_scale\n", 270 | "x_test /= gray_scale" 271 | ] 272 | }, 273 | { 274 | "cell_type": "markdown", 275 | "metadata": {}, 276 | "source": [ 277 | "### 실제값을 one hot encoding으로 변경하기\n", 278 | "손실 함수에서 크로스 엔트로피를 계산하기 위해, 실제값은 one hot encoding 값으로 변경합니다." 279 | ] 280 | }, 281 | { 282 | "cell_type": "code", 283 | "execution_count": 17, 284 | "metadata": {}, 285 | "outputs": [], 286 | "source": [ 287 | "num_classes = 10\n", 288 | "y_train = tf.keras.utils.to_categorical(y_train, num_classes)\n", 289 | "y_val = tf.keras.utils.to_categorical(y_val, num_classes)\n", 290 | "y_test = tf.keras.utils.to_categorical(y_test, num_classes)" 291 | ] 292 | }, 293 | { 294 | "cell_type": "markdown", 295 | "metadata": {}, 296 | "source": [ 297 | "### CNN 텐서플로우로 구현하기" 298 | ] 299 | }, 300 | { 301 | "cell_type": "code", 302 | "execution_count": 18, 303 | "metadata": {}, 304 | "outputs": [ 305 | { 306 | "data": { 307 | "text/html": [ 308 | "" 309 | ], 310 | "text/plain": [ 311 | "" 312 | ] 313 | }, 314 | "execution_count": 18, 315 | "metadata": {}, 316 | "output_type": "execute_result" 317 | } 318 | ], 319 | "source": [ 320 | "Image(url= \"https://raw.githubusercontent.com/captainchargers/deeplearning/master/img/practice_cnn.png\", width=800, height=200)" 321 | ] 322 | }, 323 | { 324 | "cell_type": "markdown", 325 | "metadata": {}, 326 | "source": [ 327 | "MNIST 데이터 형태 그대로 28 X 28의 포맷을 그대로 입력 데이터로 사용합니다. \n", 328 | "타겟은 0부터 9까지의 숫자입니다." 329 | ] 330 | }, 331 | { 332 | "cell_type": "code", 333 | "execution_count": 19, 334 | "metadata": {}, 335 | "outputs": [], 336 | "source": [ 337 | "x = tf.placeholder(tf.float32, shape=[None, 28, 28, 1])\n", 338 | "y_ = tf.placeholder(tf.float32, shape=[None, 10])" 339 | ] 340 | }, 341 | { 342 | "cell_type": "markdown", 343 | "metadata": {}, 344 | "source": [ 345 | "다음으로 파라미터(weight, bias) 초기값을 설정해줍니다." 346 | ] 347 | }, 348 | { 349 | "cell_type": "code", 350 | "execution_count": 20, 351 | "metadata": {}, 352 | "outputs": [], 353 | "source": [ 354 | "def weight_variable(shape):\n", 355 | " initial = tf.truncated_normal(shape, stddev=0.1)\n", 356 | " return tf.Variable(initial)\n", 357 | "\n", 358 | "def bias_variable(shape):\n", 359 | " initial = tf.constant(0.1, shape=shape)\n", 360 | " return tf.Variable(initial)" 361 | ] 362 | }, 363 | { 364 | "cell_type": "markdown", 365 | "metadata": {}, 366 | "source": [ 367 | "padding='SAME'은 레이어에 입력된 피쳐맵의 사이즈와 동일하게 피쳐맵을 출력하도록 설정해줍니다.\n", 368 | "예를 들어, CONV1에 28 X 28의 이미지 데이터가 입력되면, 동일한 크기인 28 X 28 형태의 피쳐맵이 출력되게 됩니다." 369 | ] 370 | }, 371 | { 372 | "cell_type": "code", 373 | "execution_count": 21, 374 | "metadata": {}, 375 | "outputs": [], 376 | "source": [ 377 | "def conv2d(x, W):\n", 378 | " return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')\n", 379 | "\n", 380 | "def max_pool_2x2(x):\n", 381 | " return tf.nn.max_pool(x, ksize=[1, 2, 2, 1],\n", 382 | " strides=[1, 2, 2, 1], padding='SAME')" 383 | ] 384 | }, 385 | { 386 | "cell_type": "markdown", 387 | "metadata": {}, 388 | "source": [ 389 | "첫번째 CONV 레이어는 총 16개의 필터를 가지고 있고 필터의 사이즈는 5 X 5입니다.\n", 390 | "편향값(bias)는 필터의 갯수만큼 만들어줍니다." 391 | ] 392 | }, 393 | { 394 | "cell_type": "code", 395 | "execution_count": 22, 396 | "metadata": {}, 397 | "outputs": [], 398 | "source": [ 399 | "W_conv1 = weight_variable([5, 5, 1, 16])\n", 400 | "b_conv1 = bias_variable([16])" 401 | ] 402 | }, 403 | { 404 | "cell_type": "markdown", 405 | "metadata": {}, 406 | "source": [ 407 | "활성화함수로 relu를 사용합니다." 408 | ] 409 | }, 410 | { 411 | "cell_type": "code", 412 | "execution_count": 23, 413 | "metadata": {}, 414 | "outputs": [], 415 | "source": [ 416 | "h_conv1 = tf.nn.relu(conv2d(x, W_conv1) + b_conv1)" 417 | ] 418 | }, 419 | { 420 | "cell_type": "markdown", 421 | "metadata": {}, 422 | "source": [ 423 | "CONV 레이어 다음으로 풀링 레이어를 적용하여 activation map의 크기를 줄여줍니다. activation map의 크기를 줄여줌으로써, 파라미터가 줄어들어 모델 크기가 작아지고, 과대적합의 위험도 감소시켜줍니다." 424 | ] 425 | }, 426 | { 427 | "cell_type": "code", 428 | "execution_count": 24, 429 | "metadata": {}, 430 | "outputs": [], 431 | "source": [ 432 | "h_pool1 = max_pool_2x2(h_conv1)" 433 | ] 434 | }, 435 | { 436 | "cell_type": "markdown", 437 | "metadata": {}, 438 | "source": [ 439 | "풀링레이어의 영향으로, activation map의 사이즈는 14 X 14가 되었습니다. 이 값은 다음에 이어지는 CONV2의 입력으로 들어가게 됩니다. CONV2는 총 32개의 필터를 가지고 있습니다." 440 | ] 441 | }, 442 | { 443 | "cell_type": "code", 444 | "execution_count": 25, 445 | "metadata": {}, 446 | "outputs": [], 447 | "source": [ 448 | "W_conv2 = weight_variable([5, 5, 16, 32])\n", 449 | "b_conv2 = bias_variable([32])\n", 450 | "\n", 451 | "h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)\n", 452 | "h_pool2 = max_pool_2x2(h_conv2)" 453 | ] 454 | }, 455 | { 456 | "cell_type": "markdown", 457 | "metadata": {}, 458 | "source": [ 459 | "풀링레이어 이후의 activation map의 사이즈는 7 X 7이 됩니다. \n", 460 | "\n", 461 | "#### FC (Fully Connected Layer)\n", 462 | "FC는 CONV를 통해 추출된 이미지의 특징들을 입력으로 받아 0부터 9까지의 숫자 중 하나로 이미지를 분류합니다.\n", 463 | "아래 코드에서 tf.reshape를 사용하여 모든 특징들을 하나의 배열로 형변환합니다. 형변환된 특징들은 FC의 입력값이 됩니다." 464 | ] 465 | }, 466 | { 467 | "cell_type": "code", 468 | "execution_count": 26, 469 | "metadata": {}, 470 | "outputs": [], 471 | "source": [ 472 | "W_fc1 = weight_variable([7 * 7 * 32, 128])\n", 473 | "b_fc1 = bias_variable([128])\n", 474 | "\n", 475 | "h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*32])\n", 476 | "h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)" 477 | ] 478 | }, 479 | { 480 | "cell_type": "markdown", 481 | "metadata": {}, 482 | "source": [ 483 | "FC 영역에는 FC1, FC2 총 2개의 히든 레이어가 존재합니다. FC1은 128개의 노드, FC2에는 10개의 노드가 존재합니다. FC2에 10개의 노드가 존재하는 이유는 FC2의 10개 노드의 값들을 소프트맥스에 입력시켜서 각 노드별 확률을 구하기 위해서입니다. 각 노드는 숫자 0부터 9를 의미하며, 이 예측값은 크로스 엔트로피를 통해 실제값과의 차이를 계산하는 데 사용됩니다." 484 | ] 485 | }, 486 | { 487 | "cell_type": "code", 488 | "execution_count": 27, 489 | "metadata": {}, 490 | "outputs": [], 491 | "source": [ 492 | "W_fc2 = weight_variable([128, 10])\n", 493 | "b_fc2 = bias_variable([10])\n", 494 | "\n", 495 | "y_conv = tf.matmul(h_fc1, W_fc2) + b_fc2" 496 | ] 497 | }, 498 | { 499 | "cell_type": "markdown", 500 | "metadata": {}, 501 | "source": [ 502 | "아래와 같이 크로스엔트로피를 설정해줍니다." 503 | ] 504 | }, 505 | { 506 | "cell_type": "code", 507 | "execution_count": 28, 508 | "metadata": {}, 509 | "outputs": [], 510 | "source": [ 511 | "cross_entropy = tf.reduce_mean(\n", 512 | " tf.nn.softmax_cross_entropy_with_logits_v2(\n", 513 | " labels=y_, logits=y_conv))" 514 | ] 515 | }, 516 | { 517 | "cell_type": "markdown", 518 | "metadata": {}, 519 | "source": [ 520 | "아담 옵티마이저를 사용해서 모델을 최적화합니다. 학습률은 0.001로 설정하였습니다." 521 | ] 522 | }, 523 | { 524 | "cell_type": "code", 525 | "execution_count": 29, 526 | "metadata": {}, 527 | "outputs": [], 528 | "source": [ 529 | "train_step = tf.train.AdamOptimizer(0.001).minimize(cross_entropy)" 530 | ] 531 | }, 532 | { 533 | "cell_type": "markdown", 534 | "metadata": {}, 535 | "source": [ 536 | "아래 코드는 정확도를 구하기 위해서 사용합니다." 537 | ] 538 | }, 539 | { 540 | "cell_type": "code", 541 | "execution_count": 30, 542 | "metadata": {}, 543 | "outputs": [], 544 | "source": [ 545 | "correct_prediction = tf.equal(tf.argmax(y_conv,1), tf.argmax(y_,1))\n", 546 | "accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))" 547 | ] 548 | }, 549 | { 550 | "cell_type": "markdown", 551 | "metadata": {}, 552 | "source": [ 553 | "### 학습 및 테스트\n", 554 | "이제 CNN 모델을 MNIST 데이터로 학습해보도록 하겠습니다. 단 3번의 주기만으로도 놀라온 정확도가 확인됩니다. 이번 실습에서는 미니배치를 사용하여 모델을 최적화합니다. 미니배치는 총 500개의 학습데이터가 들어있고, 미니배치마다 파라미터를 조정해줍니다." 555 | ] 556 | }, 557 | { 558 | "cell_type": "code", 559 | "execution_count": 31, 560 | "metadata": {}, 561 | "outputs": [ 562 | { 563 | "name": "stdout", 564 | "output_type": "stream", 565 | "text": [ 566 | "step 0: train acc: 0.11\n", 567 | "step 10: train acc: 0.646\n", 568 | "step 20: train acc: 0.83\n", 569 | "step 30: train acc: 0.866\n", 570 | "step 40: train acc: 0.89\n", 571 | "step 50: train acc: 0.914\n", 572 | "step 60: train acc: 0.92\n", 573 | "step 70: train acc: 0.942\n", 574 | "step 80: train acc: 0.94\n", 575 | "step 90: train acc: 0.926\n", 576 | "validation accuracy: 0.9535\n", 577 | "step 0: train acc: 0.948\n", 578 | "step 10: train acc: 0.952\n", 579 | "step 20: train acc: 0.946\n", 580 | "step 30: train acc: 0.958\n", 581 | "step 40: train acc: 0.958\n", 582 | "step 50: train acc: 0.972\n", 583 | "step 60: train acc: 0.968\n", 584 | "step 70: train acc: 0.968\n", 585 | "step 80: train acc: 0.972\n", 586 | "step 90: train acc: 0.97\n", 587 | "validation accuracy: 0.9717\n", 588 | "step 0: train acc: 0.968\n", 589 | "step 10: train acc: 0.982\n", 590 | "step 20: train acc: 0.96\n", 591 | "step 30: train acc: 0.966\n", 592 | "step 40: train acc: 0.982\n", 593 | "step 50: train acc: 0.976\n", 594 | "step 60: train acc: 0.978\n", 595 | "step 70: train acc: 0.97\n", 596 | "step 80: train acc: 0.978\n", 597 | "step 90: train acc: 0.97\n", 598 | "validation accuracy: 0.9787\n", 599 | "test accuracy: 0.9778\n" 600 | ] 601 | } 602 | ], 603 | "source": [ 604 | "# initialize\n", 605 | "init = tf.global_variables_initializer()\n", 606 | "\n", 607 | "# train hyperparameters\n", 608 | "epoch_cnt = 3\n", 609 | "batch_size = 500\n", 610 | "iteration = len(x_train) // batch_size\n", 611 | "\n", 612 | "# Start training\n", 613 | "with tf.Session() as sess:\n", 614 | " tf.set_random_seed(777)\n", 615 | " # Run the initializer\n", 616 | " sess.run(init)\n", 617 | " for epoch in range(epoch_cnt):\n", 618 | " avg_loss = 0.\n", 619 | " start = 0; end = batch_size\n", 620 | " \n", 621 | " for i in range(iteration):\n", 622 | " if i%10 == 0:\n", 623 | " train_acc = accuracy.eval(\n", 624 | " feed_dict={x:x_train[start: end], \n", 625 | " y_: y_train[start: end]})\n", 626 | " print(\"step \"+str(i)+ \": train acc: \"+str(train_acc))\n", 627 | " train_step.run(\n", 628 | " feed_dict={\n", 629 | " x:x_train[start: end], y_: y_train[start: end]})\n", 630 | " start += batch_size; end += batch_size \n", 631 | " \n", 632 | " # Validate model\n", 633 | " val_accuracy = accuracy.eval(feed_dict={x:x_val, y_: y_val})\n", 634 | " print(\"validation accuracy: \"+str(val_accuracy))\n", 635 | " \n", 636 | " test_accuracy = accuracy.eval(feed_dict={x:x_test, y_: y_test}) \n", 637 | " print(\"test accuracy: \"+str(test_accuracy))" 638 | ] 639 | }, 640 | { 641 | "cell_type": "markdown", 642 | "metadata": {}, 643 | "source": [ 644 | "단 **3** 번의 주기만으로도, **97.7%** 의 정확도를 확인할 수 있습니다." 645 | ] 646 | }, 647 | { 648 | "cell_type": "code", 649 | "execution_count": null, 650 | "metadata": {}, 651 | "outputs": [], 652 | "source": [] 653 | } 654 | ], 655 | "metadata": { 656 | "kernelspec": { 657 | "display_name": "Python 3", 658 | "language": "python", 659 | "name": "python3" 660 | }, 661 | "language_info": { 662 | "codemirror_mode": { 663 | "name": "ipython", 664 | "version": 3 665 | }, 666 | "file_extension": ".py", 667 | "mimetype": "text/x-python", 668 | "name": "python", 669 | "nbconvert_exporter": "python", 670 | "pygments_lexer": "ipython3", 671 | "version": "3.6.4" 672 | } 673 | }, 674 | "nbformat": 4, 675 | "nbformat_minor": 2 676 | } 677 | -------------------------------------------------------------------------------- /jupyter_notebook/4.5_다항분포_나이브베이즈_영화리뷰_감정분류_실습.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "import numpy as np\n", 10 | "import pandas as pd\n", 11 | "\n", 12 | "# 다항분포 나이브베이즈를 위한 라이브러리를 임포트합니다\n", 13 | "from sklearn.feature_extraction.text import CountVectorizer\n", 14 | "from sklearn.naive_bayes import MultinomialNB\n", 15 | "\n", 16 | "# 모델의 정확도 평가를 위해 임포트합니다\n", 17 | "from sklearn.metrics import accuracy_score" 18 | ] 19 | }, 20 | { 21 | "cell_type": "markdown", 22 | "metadata": {}, 23 | "source": [ 24 | "# 문제 정의\n", 25 | "다항분포 나이브베이즈 분류 모델(MultinomialNB)을 사용하여 스팸 메일을 분류해보겠습니다." 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "metadata": {}, 31 | "source": [ 32 | "# 데이터 수집\n", 33 | "이번 실습에서는 간단한 영화리뷰 분류 실습을 위해 아래 영화리뷰와 함께 영화에 대한 평가(긍정적/부정적) 정보가 있는 데이터를 사용하겠습니다." 34 | ] 35 | }, 36 | { 37 | "cell_type": "code", 38 | "execution_count": 2, 39 | "metadata": {}, 40 | "outputs": [ 41 | { 42 | "data": { 43 | "text/html": [ 44 | "
\n", 45 | "\n", 58 | "\n", 59 | " \n", 60 | " \n", 61 | " \n", 62 | " \n", 63 | " \n", 64 | " \n", 65 | " \n", 66 | " \n", 67 | " \n", 68 | " \n", 69 | " \n", 70 | " \n", 71 | " \n", 72 | " \n", 73 | " \n", 74 | " \n", 75 | " \n", 76 | " \n", 77 | " \n", 78 | " \n", 79 | " \n", 80 | " \n", 81 | " \n", 82 | " \n", 83 | " \n", 84 | " \n", 85 | " \n", 86 | " \n", 87 | " \n", 88 | " \n", 89 | " \n", 90 | " \n", 91 | " \n", 92 | " \n", 93 | " \n", 94 | " \n", 95 | " \n", 96 | " \n", 97 | " \n", 98 | " \n", 99 | " \n", 100 | " \n", 101 | " \n", 102 | " \n", 103 | " \n", 104 | " \n", 105 | " \n", 106 | " \n", 107 | " \n", 108 | " \n", 109 | " \n", 110 | " \n", 111 | " \n", 112 | " \n", 113 | " \n", 114 | " \n", 115 | " \n", 116 | " \n", 117 | " \n", 118 | "
movie_reviewtype
0this is great great movie. I will watch againpositive
1I like this moviepositive
2amazing movie in this yearpositive
3cool my boyfriend also said the movie is coolpositive
4awesome of the awesome movie everpositive
5shame I wasted money and timenegative
6regret on this move. I will never never what m...negative
7I do not like this movienegative
8I do not like actors in this movienegative
9boring boring sleeping movienegative
\n", 119 | "
" 120 | ], 121 | "text/plain": [ 122 | " movie_review type\n", 123 | "0 this is great great movie. I will watch again positive\n", 124 | "1 I like this movie positive\n", 125 | "2 amazing movie in this year positive\n", 126 | "3 cool my boyfriend also said the movie is cool positive\n", 127 | "4 awesome of the awesome movie ever positive\n", 128 | "5 shame I wasted money and time negative\n", 129 | "6 regret on this move. I will never never what m... negative\n", 130 | "7 I do not like this movie negative\n", 131 | "8 I do not like actors in this movie negative\n", 132 | "9 boring boring sleeping movie negative" 133 | ] 134 | }, 135 | "execution_count": 2, 136 | "metadata": {}, 137 | "output_type": "execute_result" 138 | } 139 | ], 140 | "source": [ 141 | "review_list = [\n", 142 | " {'movie_review': 'this is great great movie. I will watch again', 'type': 'positive'},\n", 143 | " {'movie_review': 'I like this movie', 'type': 'positive'},\n", 144 | " {'movie_review': 'amazing movie in this year', 'type': 'positive'},\n", 145 | " {'movie_review': 'cool my boyfriend also said the movie is cool', 'type': 'positive'},\n", 146 | " {'movie_review': 'awesome of the awesome movie ever', 'type': 'positive'},\n", 147 | " {'movie_review': 'shame I wasted money and time', 'type': 'negative'},\n", 148 | " {'movie_review': 'regret on this move. I will never never what movie from this director', 'type': 'negative'},\n", 149 | " {'movie_review': 'I do not like this movie', 'type': 'negative'},\n", 150 | " {'movie_review': 'I do not like actors in this movie', 'type': 'negative'},\n", 151 | " {'movie_review': 'boring boring sleeping movie', 'type': 'negative'}\n", 152 | " ]\n", 153 | "df = pd.DataFrame(review_list)\n", 154 | "df" 155 | ] 156 | }, 157 | { 158 | "cell_type": "markdown", 159 | "metadata": {}, 160 | "source": [ 161 | "sklearn의 다항분포 나이브베이즈 모델은 숫자만을 다루므로 type에 해당하는 데이터를 숫자로 매핑합니다." 162 | ] 163 | }, 164 | { 165 | "cell_type": "code", 166 | "execution_count": 3, 167 | "metadata": {}, 168 | "outputs": [ 169 | { 170 | "data": { 171 | "text/html": [ 172 | "
\n", 173 | "\n", 186 | "\n", 187 | " \n", 188 | " \n", 189 | " \n", 190 | " \n", 191 | " \n", 192 | " \n", 193 | " \n", 194 | " \n", 195 | " \n", 196 | " \n", 197 | " \n", 198 | " \n", 199 | " \n", 200 | " \n", 201 | " \n", 202 | " \n", 203 | " \n", 204 | " \n", 205 | " \n", 206 | " \n", 207 | " \n", 208 | " \n", 209 | " \n", 210 | " \n", 211 | " \n", 212 | " \n", 213 | " \n", 214 | " \n", 215 | " \n", 216 | " \n", 217 | " \n", 218 | " \n", 219 | " \n", 220 | " \n", 221 | " \n", 222 | " \n", 223 | " \n", 224 | " \n", 225 | " \n", 226 | " \n", 227 | " \n", 228 | " \n", 229 | " \n", 230 | " \n", 231 | " \n", 232 | " \n", 233 | " \n", 234 | " \n", 235 | " \n", 236 | " \n", 237 | " \n", 238 | " \n", 239 | " \n", 240 | " \n", 241 | " \n", 242 | " \n", 243 | " \n", 244 | " \n", 245 | " \n", 246 | " \n", 247 | " \n", 248 | " \n", 249 | " \n", 250 | " \n", 251 | " \n", 252 | " \n", 253 | " \n", 254 | " \n", 255 | " \n", 256 | " \n", 257 | "
movie_reviewtypelabel
0this is great great movie. I will watch againpositive1
1I like this moviepositive1
2amazing movie in this yearpositive1
3cool my boyfriend also said the movie is coolpositive1
4awesome of the awesome movie everpositive1
5shame I wasted money and timenegative0
6regret on this move. I will never never what m...negative0
7I do not like this movienegative0
8I do not like actors in this movienegative0
9boring boring sleeping movienegative0
\n", 258 | "
" 259 | ], 260 | "text/plain": [ 261 | " movie_review type label\n", 262 | "0 this is great great movie. I will watch again positive 1\n", 263 | "1 I like this movie positive 1\n", 264 | "2 amazing movie in this year positive 1\n", 265 | "3 cool my boyfriend also said the movie is cool positive 1\n", 266 | "4 awesome of the awesome movie ever positive 1\n", 267 | "5 shame I wasted money and time negative 0\n", 268 | "6 regret on this move. I will never never what m... negative 0\n", 269 | "7 I do not like this movie negative 0\n", 270 | "8 I do not like actors in this movie negative 0\n", 271 | "9 boring boring sleeping movie negative 0" 272 | ] 273 | }, 274 | "execution_count": 3, 275 | "metadata": {}, 276 | "output_type": "execute_result" 277 | } 278 | ], 279 | "source": [ 280 | "df['label'] = df['type'].map({\"positive\":1,\"negative\":0})\n", 281 | "df" 282 | ] 283 | }, 284 | { 285 | "cell_type": "markdown", 286 | "metadata": {}, 287 | "source": [ 288 | "학습을 위해, 학습에 사용될 특징값과 분류값을 분리합니다." 289 | ] 290 | }, 291 | { 292 | "cell_type": "code", 293 | "execution_count": 4, 294 | "metadata": {}, 295 | "outputs": [], 296 | "source": [ 297 | "df_x=df[\"movie_review\"]\n", 298 | "df_y=df[\"label\"]" 299 | ] 300 | }, 301 | { 302 | "cell_type": "markdown", 303 | "metadata": {}, 304 | "source": [ 305 | "다항분포 나이브베이즈의 입력 데이터는 고정된 크기의 벡터로써, 각각의 인덱스는 단어의 빈도수로 구분된 데이터이여야 합니다. \n", 306 | "sklearn의 CountVectorizer를 사용하여 쉽게 구현할 수 있습니다. \n", 307 | "CountVectorizer는 입력된 데이터(10개의 영화 리뷰)에 출현된 모든 단어의 갯수만큼의 크기의 벡터를 만든 후, \n", 308 | "각각의 리뷰를 그 고정된 벡터로 표현합니다. " 309 | ] 310 | }, 311 | { 312 | "cell_type": "code", 313 | "execution_count": 5, 314 | "metadata": {}, 315 | "outputs": [], 316 | "source": [ 317 | "cv = CountVectorizer()\n", 318 | "x_traincv=cv.fit_transform(df_x)\n", 319 | "encoded_input=x_traincv.toarray()" 320 | ] 321 | }, 322 | { 323 | "cell_type": "markdown", 324 | "metadata": {}, 325 | "source": [ 326 | "아래의 행렬에서 볼 수 있듯, 데이터에서 총 37개의 단어가 발견되어, 각각의 영화 리뷰가 37개의 크기를 갖는 벡터로 표현되었습니다. \n", 327 | "또한 다항분포 나이브베이즈에 사용하기 위해 단어의 빈도수만큼의 수치로 각 단어의 인덱스에 수치가 할당되었습니다. \n", 328 | "this is great great movie. I will watch again: \n", 329 | "[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 1, 0, 0, 0, 1, 0, 0,\n", 330 | " 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0]" 331 | ] 332 | }, 333 | { 334 | "cell_type": "code", 335 | "execution_count": 6, 336 | "metadata": {}, 337 | "outputs": [ 338 | { 339 | "data": { 340 | "text/plain": [ 341 | "array([[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 1, 0, 0, 0, 1, 0, 0,\n", 342 | " 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0],\n", 343 | " [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0,\n", 344 | " 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0],\n", 345 | " [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0,\n", 346 | " 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1],\n", 347 | " [0, 0, 1, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0,\n", 348 | " 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0],\n", 349 | " [0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,\n", 350 | " 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0],\n", 351 | " [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,\n", 352 | " 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0],\n", 353 | " [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 2,\n", 354 | " 0, 0, 1, 1, 0, 0, 0, 0, 2, 0, 0, 0, 1, 1, 0],\n", 355 | " [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0,\n", 356 | " 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0],\n", 357 | " [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0,\n", 358 | " 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0],\n", 359 | " [0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,\n", 360 | " 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=int64)" 361 | ] 362 | }, 363 | "execution_count": 6, 364 | "metadata": {}, 365 | "output_type": "execute_result" 366 | } 367 | ], 368 | "source": [ 369 | "encoded_input" 370 | ] 371 | }, 372 | { 373 | "cell_type": "markdown", 374 | "metadata": {}, 375 | "source": [ 376 | "벡터로 인코딩된 이메일 제목에 어떤 단어들이 포함되어 있는 지 알고 싶을 경우, 아래의 명령어로 알 수 있습니다." 377 | ] 378 | }, 379 | { 380 | "cell_type": "code", 381 | "execution_count": 7, 382 | "metadata": {}, 383 | "outputs": [ 384 | { 385 | "data": { 386 | "text/plain": [ 387 | "[array(['again', 'great', 'is', 'movie', 'this', 'watch', 'will'],\n", 388 | " dtype='" 198 | ] 199 | }, 200 | "execution_count": 7, 201 | "metadata": {}, 202 | "output_type": "execute_result" 203 | } 204 | ], 205 | "source": [ 206 | "model.fit(X, Y, batch_size=10,epochs=10, verbose=1)" 207 | ] 208 | }, 209 | { 210 | "cell_type": "markdown", 211 | "metadata": {}, 212 | "source": [ 213 | "학습된 선형 회귀 모델의, w(기울기)를 조회해보도록 하겠습니다." 214 | ] 215 | }, 216 | { 217 | "cell_type": "code", 218 | "execution_count": 8, 219 | "metadata": {}, 220 | "outputs": [ 221 | { 222 | "name": "stdout", 223 | "output_type": "stream", 224 | "text": [ 225 | "trained w is : 0.99236614\n" 226 | ] 227 | } 228 | ], 229 | "source": [ 230 | "weights = model.layers[0].get_weights()\n", 231 | "w = weights[0][0][0]\n", 232 | "\n", 233 | "print('trained w is : ' + str(w))" 234 | ] 235 | }, 236 | { 237 | "cell_type": "markdown", 238 | "metadata": {}, 239 | "source": [ 240 | "# 선형회귀 시각화\n", 241 | "아래의 코드를 선형 회귀 모델을 시각화할 수 있습니다. \n", 242 | "x값에 해당하는 선형 모델의 예측값이 우리가 랜덤으로 생성한 데이터 y와 상당히 비슷합니다. \n", 243 | "이처럼 관찰된 데이터를 통해 얻어진 데이터 분포의 패턴을 파악하는 것을 선형 회귀라 하며, \n", 244 | "이를 통해 관찰되지 않은 데이터에 대한 예측을 하는 것이 선형 회귀의 목적이라고 할 수 있습니다." 245 | ] 246 | }, 247 | { 248 | "cell_type": "code", 249 | "execution_count": 9, 250 | "metadata": {}, 251 | "outputs": [ 252 | { 253 | "data": { 254 | "image/png": "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\n", 255 | "text/plain": [ 256 | "
" 257 | ] 258 | }, 259 | "metadata": { 260 | "needs_background": "light" 261 | }, 262 | "output_type": "display_data" 263 | } 264 | ], 265 | "source": [ 266 | "plt.plot(X, Y, label='data')\n", 267 | "plt.plot(X, w*X, label='prediction')\n", 268 | "plt.legend()\n", 269 | "plt.show()" 270 | ] 271 | }, 272 | { 273 | "cell_type": "code", 274 | "execution_count": null, 275 | "metadata": {}, 276 | "outputs": [], 277 | "source": [] 278 | } 279 | ], 280 | "metadata": { 281 | "kernelspec": { 282 | "display_name": "Python 3", 283 | "language": "python", 284 | "name": "python3" 285 | }, 286 | "language_info": { 287 | "codemirror_mode": { 288 | "name": "ipython", 289 | "version": 3 290 | }, 291 | "file_extension": ".py", 292 | "mimetype": "text/x-python", 293 | "name": "python", 294 | "nbconvert_exporter": "python", 295 | "pygments_lexer": "ipython3", 296 | "version": "3.6.4" 297 | } 298 | }, 299 | "nbformat": 4, 300 | "nbformat_minor": 2 301 | } 302 | -------------------------------------------------------------------------------- /jupyter_notebook/4.9_소프트맥스_실습.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# 소프트맥스 (다중 분류 로지스틱 회귀 모델)\n", 8 | "M개의 입력을 받아 N개의 클래스로 출력하는 로지스틱 회귀 모델을 케라스로 구현해보도록 하겠습니다. \n", 9 | "보통 다중 분류 로지스틱 회귀 모델을 소프트맥스(softmax)라고 부릅니다. \n", 10 | "케라스에서 제공하는 MNIST 데이터를 사용하여 숫자를 0에서부터 9까지 분류해보도록 하겠습니다. " 11 | ] 12 | }, 13 | { 14 | "cell_type": "code", 15 | "execution_count": 1, 16 | "metadata": {}, 17 | "outputs": [ 18 | { 19 | "name": "stderr", 20 | "output_type": "stream", 21 | "text": [ 22 | "Using TensorFlow backend.\n" 23 | ] 24 | } 25 | ], 26 | "source": [ 27 | "from keras.models import Sequential\n", 28 | "from keras.layers import Dense, Activation\n", 29 | "from keras.utils import to_categorical\n", 30 | "from keras.datasets import mnist" 31 | ] 32 | }, 33 | { 34 | "cell_type": "markdown", 35 | "metadata": {}, 36 | "source": [ 37 | "MNIST 손글씨 데이터를 다운로드 받아서 변수에 저장합니다." 38 | ] 39 | }, 40 | { 41 | "cell_type": "code", 42 | "execution_count": 2, 43 | "metadata": {}, 44 | "outputs": [], 45 | "source": [ 46 | "(X_train, y_train), (X_test, y_test) = mnist.load_data()" 47 | ] 48 | }, 49 | { 50 | "cell_type": "markdown", 51 | "metadata": {}, 52 | "source": [ 53 | "손글씨 데이터(X_train, X_test)가 가로 28픽셀, 세로 28픽셀로 구성된 것을 확인할 수 있습니다. \n", 54 | "학습에 사용될 X_train은 총 60000개의 데이터, 테스트에 사용될 X_test는 총 10000개의 데이터가 있습니다." 55 | ] 56 | }, 57 | { 58 | "cell_type": "code", 59 | "execution_count": 3, 60 | "metadata": {}, 61 | "outputs": [ 62 | { 63 | "name": "stdout", 64 | "output_type": "stream", 65 | "text": [ 66 | "train data (count, row, column) : (60000, 28, 28)\n", 67 | "test data (count, row, column) : (10000, 28, 28)\n" 68 | ] 69 | } 70 | ], 71 | "source": [ 72 | "print(\"train data (count, row, column) : \" + str(X_train.shape) )\n", 73 | "print(\"test data (count, row, column) : \" + str(X_test.shape) )" 74 | ] 75 | }, 76 | { 77 | "cell_type": "markdown", 78 | "metadata": {}, 79 | "source": [ 80 | "학습 데이터의 하나를 샘플로 보도록 하겠습니다. 아래 보시는 것처럼, 각각의 픽셀은 0부터 255까지의 값을 가지고 있습니다." 81 | ] 82 | }, 83 | { 84 | "cell_type": "code", 85 | "execution_count": 4, 86 | "metadata": {}, 87 | "outputs": [ 88 | { 89 | "name": "stdout", 90 | "output_type": "stream", 91 | "text": [ 92 | "[[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", 93 | " 0 0 0 0 0 0 0 0 0 0]\n", 94 | " [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", 95 | " 0 0 0 0 0 0 0 0 0 0]\n", 96 | " [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", 97 | " 0 0 0 0 0 0 0 0 0 0]\n", 98 | " [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", 99 | " 0 0 0 0 0 0 0 0 0 0]\n", 100 | " [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", 101 | " 0 0 0 0 0 0 0 0 0 0]\n", 102 | " [ 0 0 0 0 0 0 0 0 0 0 0 0 3 18 18 18 126 136\n", 103 | " 175 26 166 255 247 127 0 0 0 0]\n", 104 | " [ 0 0 0 0 0 0 0 0 30 36 94 154 170 253 253 253 253 253\n", 105 | " 225 172 253 242 195 64 0 0 0 0]\n", 106 | " [ 0 0 0 0 0 0 0 49 238 253 253 253 253 253 253 253 253 251\n", 107 | " 93 82 82 56 39 0 0 0 0 0]\n", 108 | " [ 0 0 0 0 0 0 0 18 219 253 253 253 253 253 198 182 247 241\n", 109 | " 0 0 0 0 0 0 0 0 0 0]\n", 110 | " [ 0 0 0 0 0 0 0 0 80 156 107 253 253 205 11 0 43 154\n", 111 | " 0 0 0 0 0 0 0 0 0 0]\n", 112 | " [ 0 0 0 0 0 0 0 0 0 14 1 154 253 90 0 0 0 0\n", 113 | " 0 0 0 0 0 0 0 0 0 0]\n", 114 | " [ 0 0 0 0 0 0 0 0 0 0 0 139 253 190 2 0 0 0\n", 115 | " 0 0 0 0 0 0 0 0 0 0]\n", 116 | " [ 0 0 0 0 0 0 0 0 0 0 0 11 190 253 70 0 0 0\n", 117 | " 0 0 0 0 0 0 0 0 0 0]\n", 118 | " [ 0 0 0 0 0 0 0 0 0 0 0 0 35 241 225 160 108 1\n", 119 | " 0 0 0 0 0 0 0 0 0 0]\n", 120 | " [ 0 0 0 0 0 0 0 0 0 0 0 0 0 81 240 253 253 119\n", 121 | " 25 0 0 0 0 0 0 0 0 0]\n", 122 | " [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 45 186 253 253\n", 123 | " 150 27 0 0 0 0 0 0 0 0]\n", 124 | " [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 16 93 252\n", 125 | " 253 187 0 0 0 0 0 0 0 0]\n", 126 | " [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 249\n", 127 | " 253 249 64 0 0 0 0 0 0 0]\n", 128 | " [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 46 130 183 253\n", 129 | " 253 207 2 0 0 0 0 0 0 0]\n", 130 | " [ 0 0 0 0 0 0 0 0 0 0 0 0 39 148 229 253 253 253\n", 131 | " 250 182 0 0 0 0 0 0 0 0]\n", 132 | " [ 0 0 0 0 0 0 0 0 0 0 24 114 221 253 253 253 253 201\n", 133 | " 78 0 0 0 0 0 0 0 0 0]\n", 134 | " [ 0 0 0 0 0 0 0 0 23 66 213 253 253 253 253 198 81 2\n", 135 | " 0 0 0 0 0 0 0 0 0 0]\n", 136 | " [ 0 0 0 0 0 0 18 171 219 253 253 253 253 195 80 9 0 0\n", 137 | " 0 0 0 0 0 0 0 0 0 0]\n", 138 | " [ 0 0 0 0 55 172 226 253 253 253 253 244 133 11 0 0 0 0\n", 139 | " 0 0 0 0 0 0 0 0 0 0]\n", 140 | " [ 0 0 0 0 136 253 253 253 212 135 132 16 0 0 0 0 0 0\n", 141 | " 0 0 0 0 0 0 0 0 0 0]\n", 142 | " [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", 143 | " 0 0 0 0 0 0 0 0 0 0]\n", 144 | " [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", 145 | " 0 0 0 0 0 0 0 0 0 0]\n", 146 | " [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", 147 | " 0 0 0 0 0 0 0 0 0 0]]\n" 148 | ] 149 | } 150 | ], 151 | "source": [ 152 | "print(X_train[0])" 153 | ] 154 | }, 155 | { 156 | "cell_type": "markdown", 157 | "metadata": {}, 158 | "source": [ 159 | "모델 학습 시작에 앞서, 데이터를 정규화합니다. \n", 160 | "정규화는 입력값을 0부터 1의 값으로 변경하게 됩니다. \n", 161 | "정규화된 입력값은 경사하강법으로 모델 학습 시, 보다 쉽고 빠르게 최적의 W,B를 찾는 데 도움을 줍니다." 162 | ] 163 | }, 164 | { 165 | "cell_type": "code", 166 | "execution_count": 5, 167 | "metadata": {}, 168 | "outputs": [], 169 | "source": [ 170 | "X_train = X_train.astype('float32') \n", 171 | "X_test = X_test.astype('float32') \n", 172 | "X_train /= 255 \n", 173 | "X_test /= 255" 174 | ] 175 | }, 176 | { 177 | "cell_type": "markdown", 178 | "metadata": {}, 179 | "source": [ 180 | "아래의 명령어를 통해 정규화된 데이터를 확인할 수 있습니다." 181 | ] 182 | }, 183 | { 184 | "cell_type": "code", 185 | "execution_count": 6, 186 | "metadata": {}, 187 | "outputs": [ 188 | { 189 | "name": "stdout", 190 | "output_type": "stream", 191 | "text": [ 192 | "[[0. 0. 0. 0. 0. 0.\n", 193 | " 0. 0. 0. 0. 0. 0.\n", 194 | " 0. 0. 0. 0. 0. 0.\n", 195 | " 0. 0. 0. 0. 0. 0.\n", 196 | " 0. 0. 0. 0. ]\n", 197 | " [0. 0. 0. 0. 0. 0.\n", 198 | " 0. 0. 0. 0. 0. 0.\n", 199 | " 0. 0. 0. 0. 0. 0.\n", 200 | " 0. 0. 0. 0. 0. 0.\n", 201 | " 0. 0. 0. 0. ]\n", 202 | " [0. 0. 0. 0. 0. 0.\n", 203 | " 0. 0. 0. 0. 0. 0.\n", 204 | " 0. 0. 0. 0. 0. 0.\n", 205 | " 0. 0. 0. 0. 0. 0.\n", 206 | " 0. 0. 0. 0. ]\n", 207 | " [0. 0. 0. 0. 0. 0.\n", 208 | " 0. 0. 0. 0. 0. 0.\n", 209 | " 0. 0. 0. 0. 0. 0.\n", 210 | " 0. 0. 0. 0. 0. 0.\n", 211 | " 0. 0. 0. 0. ]\n", 212 | " [0. 0. 0. 0. 0. 0.\n", 213 | " 0. 0. 0. 0. 0. 0.\n", 214 | " 0. 0. 0. 0. 0. 0.\n", 215 | " 0. 0. 0. 0. 0. 0.\n", 216 | " 0. 0. 0. 0. ]\n", 217 | " [0. 0. 0. 0. 0. 0.\n", 218 | " 0. 0. 0. 0. 0. 0.\n", 219 | " 0.01176471 0.07058824 0.07058824 0.07058824 0.49411765 0.53333336\n", 220 | " 0.6862745 0.10196079 0.6509804 1. 0.96862745 0.49803922\n", 221 | " 0. 0. 0. 0. ]\n", 222 | " [0. 0. 0. 0. 0. 0.\n", 223 | " 0. 0. 0.11764706 0.14117648 0.36862746 0.6039216\n", 224 | " 0.6666667 0.99215686 0.99215686 0.99215686 0.99215686 0.99215686\n", 225 | " 0.88235295 0.6745098 0.99215686 0.9490196 0.7647059 0.2509804\n", 226 | " 0. 0. 0. 0. ]\n", 227 | " [0. 0. 0. 0. 0. 0.\n", 228 | " 0. 0.19215687 0.93333334 0.99215686 0.99215686 0.99215686\n", 229 | " 0.99215686 0.99215686 0.99215686 0.99215686 0.99215686 0.9843137\n", 230 | " 0.3647059 0.32156864 0.32156864 0.21960784 0.15294118 0.\n", 231 | " 0. 0. 0. 0. ]\n", 232 | " [0. 0. 0. 0. 0. 0.\n", 233 | " 0. 0.07058824 0.85882354 0.99215686 0.99215686 0.99215686\n", 234 | " 0.99215686 0.99215686 0.7764706 0.7137255 0.96862745 0.94509804\n", 235 | " 0. 0. 0. 0. 0. 0.\n", 236 | " 0. 0. 0. 0. ]\n", 237 | " [0. 0. 0. 0. 0. 0.\n", 238 | " 0. 0. 0.3137255 0.6117647 0.41960785 0.99215686\n", 239 | " 0.99215686 0.8039216 0.04313726 0. 0.16862746 0.6039216\n", 240 | " 0. 0. 0. 0. 0. 0.\n", 241 | " 0. 0. 0. 0. ]\n", 242 | " [0. 0. 0. 0. 0. 0.\n", 243 | " 0. 0. 0. 0.05490196 0.00392157 0.6039216\n", 244 | " 0.99215686 0.3529412 0. 0. 0. 0.\n", 245 | " 0. 0. 0. 0. 0. 0.\n", 246 | " 0. 0. 0. 0. ]\n", 247 | " [0. 0. 0. 0. 0. 0.\n", 248 | " 0. 0. 0. 0. 0. 0.54509807\n", 249 | " 0.99215686 0.74509805 0.00784314 0. 0. 0.\n", 250 | " 0. 0. 0. 0. 0. 0.\n", 251 | " 0. 0. 0. 0. ]\n", 252 | " [0. 0. 0. 0. 0. 0.\n", 253 | " 0. 0. 0. 0. 0. 0.04313726\n", 254 | " 0.74509805 0.99215686 0.27450982 0. 0. 0.\n", 255 | " 0. 0. 0. 0. 0. 0.\n", 256 | " 0. 0. 0. 0. ]\n", 257 | " [0. 0. 0. 0. 0. 0.\n", 258 | " 0. 0. 0. 0. 0. 0.\n", 259 | " 0.13725491 0.94509804 0.88235295 0.627451 0.42352942 0.00392157\n", 260 | " 0. 0. 0. 0. 0. 0.\n", 261 | " 0. 0. 0. 0. ]\n", 262 | " [0. 0. 0. 0. 0. 0.\n", 263 | " 0. 0. 0. 0. 0. 0.\n", 264 | " 0. 0.31764707 0.9411765 0.99215686 0.99215686 0.46666667\n", 265 | " 0.09803922 0. 0. 0. 0. 0.\n", 266 | " 0. 0. 0. 0. ]\n", 267 | " [0. 0. 0. 0. 0. 0.\n", 268 | " 0. 0. 0. 0. 0. 0.\n", 269 | " 0. 0. 0.1764706 0.7294118 0.99215686 0.99215686\n", 270 | " 0.5882353 0.10588235 0. 0. 0. 0.\n", 271 | " 0. 0. 0. 0. ]\n", 272 | " [0. 0. 0. 0. 0. 0.\n", 273 | " 0. 0. 0. 0. 0. 0.\n", 274 | " 0. 0. 0. 0.0627451 0.3647059 0.9882353\n", 275 | " 0.99215686 0.73333335 0. 0. 0. 0.\n", 276 | " 0. 0. 0. 0. ]\n", 277 | " [0. 0. 0. 0. 0. 0.\n", 278 | " 0. 0. 0. 0. 0. 0.\n", 279 | " 0. 0. 0. 0. 0. 0.9764706\n", 280 | " 0.99215686 0.9764706 0.2509804 0. 0. 0.\n", 281 | " 0. 0. 0. 0. ]\n", 282 | " [0. 0. 0. 0. 0. 0.\n", 283 | " 0. 0. 0. 0. 0. 0.\n", 284 | " 0. 0. 0.18039216 0.50980395 0.7176471 0.99215686\n", 285 | " 0.99215686 0.8117647 0.00784314 0. 0. 0.\n", 286 | " 0. 0. 0. 0. ]\n", 287 | " [0. 0. 0. 0. 0. 0.\n", 288 | " 0. 0. 0. 0. 0. 0.\n", 289 | " 0.15294118 0.5803922 0.8980392 0.99215686 0.99215686 0.99215686\n", 290 | " 0.98039216 0.7137255 0. 0. 0. 0.\n", 291 | " 0. 0. 0. 0. ]\n", 292 | " [0. 0. 0. 0. 0. 0.\n", 293 | " 0. 0. 0. 0. 0.09411765 0.44705883\n", 294 | " 0.8666667 0.99215686 0.99215686 0.99215686 0.99215686 0.7882353\n", 295 | " 0.30588236 0. 0. 0. 0. 0.\n", 296 | " 0. 0. 0. 0. ]\n", 297 | " [0. 0. 0. 0. 0. 0.\n", 298 | " 0. 0. 0.09019608 0.25882354 0.8352941 0.99215686\n", 299 | " 0.99215686 0.99215686 0.99215686 0.7764706 0.31764707 0.00784314\n", 300 | " 0. 0. 0. 0. 0. 0.\n", 301 | " 0. 0. 0. 0. ]\n", 302 | " [0. 0. 0. 0. 0. 0.\n", 303 | " 0.07058824 0.67058825 0.85882354 0.99215686 0.99215686 0.99215686\n", 304 | " 0.99215686 0.7647059 0.3137255 0.03529412 0. 0.\n", 305 | " 0. 0. 0. 0. 0. 0.\n", 306 | " 0. 0. 0. 0. ]\n", 307 | " [0. 0. 0. 0. 0.21568628 0.6745098\n", 308 | " 0.8862745 0.99215686 0.99215686 0.99215686 0.99215686 0.95686275\n", 309 | " 0.52156866 0.04313726 0. 0. 0. 0.\n", 310 | " 0. 0. 0. 0. 0. 0.\n", 311 | " 0. 0. 0. 0. ]\n", 312 | " [0. 0. 0. 0. 0.53333336 0.99215686\n", 313 | " 0.99215686 0.99215686 0.83137256 0.5294118 0.5176471 0.0627451\n", 314 | " 0. 0. 0. 0. 0. 0.\n", 315 | " 0. 0. 0. 0. 0. 0.\n", 316 | " 0. 0. 0. 0. ]\n", 317 | " [0. 0. 0. 0. 0. 0.\n", 318 | " 0. 0. 0. 0. 0. 0.\n", 319 | " 0. 0. 0. 0. 0. 0.\n", 320 | " 0. 0. 0. 0. 0. 0.\n", 321 | " 0. 0. 0. 0. ]\n", 322 | " [0. 0. 0. 0. 0. 0.\n", 323 | " 0. 0. 0. 0. 0. 0.\n", 324 | " 0. 0. 0. 0. 0. 0.\n", 325 | " 0. 0. 0. 0. 0. 0.\n", 326 | " 0. 0. 0. 0. ]\n", 327 | " [0. 0. 0. 0. 0. 0.\n", 328 | " 0. 0. 0. 0. 0. 0.\n", 329 | " 0. 0. 0. 0. 0. 0.\n", 330 | " 0. 0. 0. 0. 0. 0.\n", 331 | " 0. 0. 0. 0. ]]\n" 332 | ] 333 | } 334 | ], 335 | "source": [ 336 | "print(X_train[0])" 337 | ] 338 | }, 339 | { 340 | "cell_type": "markdown", 341 | "metadata": {}, 342 | "source": [ 343 | "y_train, y_test는 손글씨 데이터 (28*28 픽셀 데이터)에 해당하는 숫자를 나타냅니다. \n", 344 | "y_train은 총 6만개, y_test는 총 1만개의 숫자를 가지고 있습니다." 345 | ] 346 | }, 347 | { 348 | "cell_type": "code", 349 | "execution_count": 7, 350 | "metadata": {}, 351 | "outputs": [ 352 | { 353 | "name": "stdout", 354 | "output_type": "stream", 355 | "text": [ 356 | "train target (count) : (60000,)\n", 357 | "test target (count) : (10000,)\n" 358 | ] 359 | } 360 | ], 361 | "source": [ 362 | "print(\"train target (count) : \" + str(y_train.shape) )\n", 363 | "print(\"test target (count) : \" + str(y_test.shape) )" 364 | ] 365 | }, 366 | { 367 | "cell_type": "markdown", 368 | "metadata": {}, 369 | "source": [ 370 | "아래의 코드를 실행하여, y_train과 y_test에서 샘플로 숫자를 출력해봅니다." 371 | ] 372 | }, 373 | { 374 | "cell_type": "code", 375 | "execution_count": 8, 376 | "metadata": {}, 377 | "outputs": [ 378 | { 379 | "name": "stdout", 380 | "output_type": "stream", 381 | "text": [ 382 | "sample from train : 5\n", 383 | "sample from test : 7\n" 384 | ] 385 | } 386 | ], 387 | "source": [ 388 | "print(\"sample from train : \" + str(y_train[0]) )\n", 389 | "print(\"sample from test : \" + str(y_test[0]) )" 390 | ] 391 | }, 392 | { 393 | "cell_type": "markdown", 394 | "metadata": {}, 395 | "source": [ 396 | "이번 실습에서는 28*28 픽셀의 지역적인 정보를 사용하지 않고, 단순히 정규화된 입력값만을 가지고, \n", 397 | "숫자 분류를 할 것이기 때문에, 행과 열의 구분 없이, 단순히 784 길이의 배열로 데이터를 단순화시킵니다." 398 | ] 399 | }, 400 | { 401 | "cell_type": "code", 402 | "execution_count": 9, 403 | "metadata": {}, 404 | "outputs": [], 405 | "source": [ 406 | "input_dim = 784 #28*28 \n", 407 | "X_train = X_train.reshape(60000, input_dim) \n", 408 | "X_test = X_test.reshape(10000, input_dim) " 409 | ] 410 | }, 411 | { 412 | "cell_type": "markdown", 413 | "metadata": {}, 414 | "source": [ 415 | "아래의 명령어를 실행하여, 현재 우리의 데이터가 2차원 데이터가 아닌 단순한 1차원 데이터로 변경된 것을 확인할 수 있습니다." 416 | ] 417 | }, 418 | { 419 | "cell_type": "code", 420 | "execution_count": 10, 421 | "metadata": {}, 422 | "outputs": [ 423 | { 424 | "name": "stdout", 425 | "output_type": "stream", 426 | "text": [ 427 | "(60000, 784)\n", 428 | "(60000,)\n", 429 | "(10000, 784)\n", 430 | "(10000,)\n" 431 | ] 432 | } 433 | ], 434 | "source": [ 435 | "print(X_train.shape)\n", 436 | "print(y_train.shape)\n", 437 | "print(X_test.shape)\n", 438 | "print(y_test.shape)" 439 | ] 440 | }, 441 | { 442 | "cell_type": "markdown", 443 | "metadata": {}, 444 | "source": [ 445 | "학습 시, y값과의 cross entropy를 측정해야하므로, 아래의 코드를 실행하여 y를 one hot encoding으로 변환시켜줍니다." 446 | ] 447 | }, 448 | { 449 | "cell_type": "code", 450 | "execution_count": 11, 451 | "metadata": {}, 452 | "outputs": [], 453 | "source": [ 454 | "num_classes = 10\n", 455 | "y_train = to_categorical(y_train, num_classes)\n", 456 | "y_test = to_categorical(y_test, num_classes)" 457 | ] 458 | }, 459 | { 460 | "cell_type": "markdown", 461 | "metadata": {}, 462 | "source": [ 463 | "아래 코드를 실행하여, 5였던 값이, one hot encoding으로 변환되어, \n", 464 | "클래스 갯수만큼의 길이를 갖는 벡터로 변경이 되었고, 5에 해당되는 인덱스의 값만 1인 것을 확인할 수 있습니다." 465 | ] 466 | }, 467 | { 468 | "cell_type": "code", 469 | "execution_count": 12, 470 | "metadata": {}, 471 | "outputs": [ 472 | { 473 | "name": "stdout", 474 | "output_type": "stream", 475 | "text": [ 476 | "[0. 0. 0. 0. 0. 1. 0. 0. 0. 0.]\n" 477 | ] 478 | } 479 | ], 480 | "source": [ 481 | "print(y_train[0])" 482 | ] 483 | }, 484 | { 485 | "cell_type": "markdown", 486 | "metadata": {}, 487 | "source": [ 488 | "케라스의 Sequential()을 사용하여 간단하게 소프트맥스를 구현할 수 있습니다. \n", 489 | "총 784개(28*28)의 입력을 받아서, 10개의 시그모이드 값을 출력하는 모델을 아래의 코드를 실행하여 구현합니다." 490 | ] 491 | }, 492 | { 493 | "cell_type": "code", 494 | "execution_count": 13, 495 | "metadata": {}, 496 | "outputs": [], 497 | "source": [ 498 | "model = Sequential() \n", 499 | "model.add(Dense(input_dim=input_dim, units = 10, activation='softmax'))" 500 | ] 501 | }, 502 | { 503 | "cell_type": "markdown", 504 | "metadata": {}, 505 | "source": [ 506 | "모델의 학습을 진행합니다. \n", 507 | "10개의 클래스로 분류할 것이기 때문에, categorical_crossentropy를 비용함수로 사용한 경사하강법으로 최적의 W와 biases를 학습합니다." 508 | ] 509 | }, 510 | { 511 | "cell_type": "code", 512 | "execution_count": 14, 513 | "metadata": {}, 514 | "outputs": [ 515 | { 516 | "data": { 517 | "text/plain": [ 518 | "" 519 | ] 520 | }, 521 | "execution_count": 14, 522 | "metadata": {}, 523 | "output_type": "execute_result" 524 | } 525 | ], 526 | "source": [ 527 | "model.compile(optimizer='sgd', loss='categorical_crossentropy', metrics=['accuracy']) \n", 528 | "model.fit(X_train, y_train, batch_size=2048, epochs=100, verbose=0) " 529 | ] 530 | }, 531 | { 532 | "cell_type": "markdown", 533 | "metadata": {}, 534 | "source": [ 535 | "테스트를 진행하여, 정확도를 측정합니다." 536 | ] 537 | }, 538 | { 539 | "cell_type": "code", 540 | "execution_count": 15, 541 | "metadata": {}, 542 | "outputs": [ 543 | { 544 | "name": "stdout", 545 | "output_type": "stream", 546 | "text": [ 547 | "10000/10000 [==============================] - 1s 50us/step\n", 548 | "Test accuracy: 0.8927\n" 549 | ] 550 | } 551 | ], 552 | "source": [ 553 | "score = model.evaluate(X_test, y_test) \n", 554 | "print('Test accuracy:', score[1])" 555 | ] 556 | }, 557 | { 558 | "cell_type": "markdown", 559 | "metadata": {}, 560 | "source": [ 561 | "아래의 코드를 실행하여, 소프트맥스 모델의 구조를 쉽게 시각화 할 수 있습니다. \n", 562 | "총 10개의 로지스틱회귀가 있고, 각 로지스틱회귀는 784개의 weight와 1개의 bias를 갖고 있기 때문에, \n", 563 | "총 7850 (785*10)개의 Param이 있는 것을 보실 수 있습니다." 564 | ] 565 | }, 566 | { 567 | "cell_type": "code", 568 | "execution_count": 16, 569 | "metadata": {}, 570 | "outputs": [ 571 | { 572 | "name": "stdout", 573 | "output_type": "stream", 574 | "text": [ 575 | "_________________________________________________________________\n", 576 | "Layer (type) Output Shape Param # \n", 577 | "=================================================================\n", 578 | "dense_1 (Dense) (None, 10) 7850 \n", 579 | "=================================================================\n", 580 | "Total params: 7,850\n", 581 | "Trainable params: 7,850\n", 582 | "Non-trainable params: 0\n", 583 | "_________________________________________________________________\n" 584 | ] 585 | } 586 | ], 587 | "source": [ 588 | "model.summary()" 589 | ] 590 | }, 591 | { 592 | "cell_type": "markdown", 593 | "metadata": {}, 594 | "source": [ 595 | "첫번째 레이어에 존재하는 w1, w2,...,w784, b1, b2,..., b10은 아래의 명령어로 확인하실 수 있습니다." 596 | ] 597 | }, 598 | { 599 | "cell_type": "code", 600 | "execution_count": 17, 601 | "metadata": {}, 602 | "outputs": [ 603 | { 604 | "data": { 605 | "text/plain": [ 606 | "[,\n", 607 | " ]" 608 | ] 609 | }, 610 | "execution_count": 17, 611 | "metadata": {}, 612 | "output_type": "execute_result" 613 | } 614 | ], 615 | "source": [ 616 | "model.layers[0].weights" 617 | ] 618 | } 619 | ], 620 | "metadata": { 621 | "kernelspec": { 622 | "display_name": "Python 3", 623 | "language": "python", 624 | "name": "python3" 625 | }, 626 | "language_info": { 627 | "codemirror_mode": { 628 | "name": "ipython", 629 | "version": 3 630 | }, 631 | "file_extension": ".py", 632 | "mimetype": "text/x-python", 633 | "name": "python", 634 | "nbconvert_exporter": "python", 635 | "pygments_lexer": "ipython3", 636 | "version": "3.6.4" 637 | } 638 | }, 639 | "nbformat": 4, 640 | "nbformat_minor": 2 641 | } 642 | -------------------------------------------------------------------------------- /jupyter_notebook/4.2_knn_농구선수_포지션_예측_실습.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "import pandas as pd\n", 10 | "import pickle\n", 11 | "import matplotlib.pyplot as plt\n", 12 | "import seaborn as sns\n", 13 | "%matplotlib inline" 14 | ] 15 | }, 16 | { 17 | "cell_type": "markdown", 18 | "metadata": {}, 19 | "source": [ 20 | "# 데이터 불러오기 (학습 데이터, 테스트 데이터)\n", 21 | "데이터 분석 단계(4.2_농구선수_데이터분석.ipynb)에서 생성한 농구 선수 포지션 예측하기의 \n", 22 | "학습 데이터 및 테스트 데이터를 로드합니다." 23 | ] 24 | }, 25 | { 26 | "cell_type": "code", 27 | "execution_count": 2, 28 | "metadata": {}, 29 | "outputs": [], 30 | "source": [ 31 | "with open('../data/pkl/basketball_train.pkl', 'rb') as train_data:\n", 32 | " train = pickle.load(train_data)\n", 33 | " \n", 34 | "with open('../data/pkl/basketball_test.pkl', 'rb') as test_data:\n", 35 | " test = pickle.load(test_data)" 36 | ] 37 | }, 38 | { 39 | "cell_type": "markdown", 40 | "metadata": {}, 41 | "source": [ 42 | "# 최적의 k 찾기 (교차 검증 - cross validation)" 43 | ] 44 | }, 45 | { 46 | "cell_type": "code", 47 | "execution_count": 3, 48 | "metadata": {}, 49 | "outputs": [ 50 | { 51 | "data": { 52 | "text/plain": [ 53 | "[0.9196428571428573,\n", 54 | " 0.9214285714285715,\n", 55 | " 0.9339285714285716,\n", 56 | " 0.9339285714285716,\n", 57 | " 0.9371031746031747,\n", 58 | " 0.9228174603174605,\n", 59 | " 0.9371031746031747,\n", 60 | " 0.9117063492063492,\n", 61 | " 0.9259920634920636,\n", 62 | " 0.9259920634920636,\n", 63 | " 0.9117063492063492,\n", 64 | " 0.884920634920635,\n", 65 | " 0.884920634920635,\n", 66 | " 0.8438492063492063,\n", 67 | " 0.8438492063492063,\n", 68 | " 0.8438492063492063,\n", 69 | " 0.8313492063492063,\n", 70 | " 0.8313492063492063,\n", 71 | " 0.8202380952380952]" 72 | ] 73 | }, 74 | "execution_count": 3, 75 | "metadata": {}, 76 | "output_type": "execute_result" 77 | } 78 | ], 79 | "source": [ 80 | "# import kNN library\n", 81 | "from sklearn.neighbors import KNeighborsClassifier\n", 82 | "from sklearn.model_selection import cross_val_score\n", 83 | "\n", 84 | "# find best k, range from 3 to half of the number of data\n", 85 | "max_k_range = train.shape[0] // 2\n", 86 | "k_list = []\n", 87 | "for i in range(3, max_k_range, 2):\n", 88 | " k_list.append(i)\n", 89 | "\n", 90 | "cross_validation_scores = []\n", 91 | "x_train = train[['3P', 'BLK' , 'TRB']]\n", 92 | "y_train = train[['Pos']]\n", 93 | "\n", 94 | "# 10-fold cross validation\n", 95 | "for k in k_list:\n", 96 | " knn = KNeighborsClassifier(n_neighbors=k)\n", 97 | " scores = cross_val_score(knn, x_train, y_train.values.ravel(),\n", 98 | " cv=10, scoring='accuracy')\n", 99 | " cross_validation_scores.append(scores.mean())\n", 100 | "\n", 101 | "cross_validation_scores" 102 | ] 103 | }, 104 | { 105 | "cell_type": "code", 106 | "execution_count": 4, 107 | "metadata": {}, 108 | "outputs": [ 109 | { 110 | "data": { 111 | "image/png": "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\n", 112 | "text/plain": [ 113 | "
" 114 | ] 115 | }, 116 | "metadata": { 117 | "needs_background": "light" 118 | }, 119 | "output_type": "display_data" 120 | } 121 | ], 122 | "source": [ 123 | "# visualize accuracy according to k\n", 124 | "plt.plot(k_list, cross_validation_scores)\n", 125 | "plt.xlabel('the number of k')\n", 126 | "plt.ylabel('Accuracy')\n", 127 | "plt.show()" 128 | ] 129 | }, 130 | { 131 | "cell_type": "code", 132 | "execution_count": 5, 133 | "metadata": {}, 134 | "outputs": [ 135 | { 136 | "name": "stdout", 137 | "output_type": "stream", 138 | "text": [ 139 | "The best number of k : 11\n" 140 | ] 141 | } 142 | ], 143 | "source": [ 144 | "# find best k\n", 145 | "cvs = cross_validation_scores\n", 146 | "k = k_list[cvs.index(max(cross_validation_scores))]\n", 147 | "print(\"The best number of k : \" + str(k) )" 148 | ] 149 | }, 150 | { 151 | "cell_type": "markdown", 152 | "metadata": {}, 153 | "source": [ 154 | "# 2개의 특징으로 예측하기 (3점슛, 블로킹)" 155 | ] 156 | }, 157 | { 158 | "cell_type": "code", 159 | "execution_count": 6, 160 | "metadata": {}, 161 | "outputs": [], 162 | "source": [ 163 | "# import libraries\n", 164 | "from sklearn.neighbors import KNeighborsClassifier\n", 165 | "from sklearn.metrics import accuracy_score\n", 166 | "\n", 167 | "knn = KNeighborsClassifier(n_neighbors=k)\n", 168 | "\n", 169 | "# select data features\n", 170 | "x_train = train[['3P', 'BLK']]\n", 171 | "# select target value\n", 172 | "y_train = train[['Pos']]\n", 173 | "\n", 174 | "# setup knn using train data\n", 175 | "knn.fit(x_train, y_train.values.ravel())\n", 176 | "\n", 177 | "# select data feature to be used for prediction\n", 178 | "x_test = test[['3P', 'BLK']]\n", 179 | "\n", 180 | "# select target value\n", 181 | "y_test = test[['Pos']]\n", 182 | "\n", 183 | "# test\n", 184 | "pred = knn.predict(x_test)" 185 | ] 186 | }, 187 | { 188 | "cell_type": "code", 189 | "execution_count": 7, 190 | "metadata": {}, 191 | "outputs": [ 192 | { 193 | "data": { 194 | "text/html": [ 195 | "
\n", 196 | "\n", 209 | "\n", 210 | " \n", 211 | " \n", 212 | " \n", 213 | " \n", 214 | " \n", 215 | " \n", 216 | " \n", 217 | " \n", 218 | " \n", 219 | " \n", 220 | " \n", 221 | " \n", 222 | " \n", 223 | " \n", 224 | " \n", 225 | " \n", 226 | " \n", 227 | " \n", 228 | " \n", 229 | " \n", 230 | " \n", 231 | " \n", 232 | " \n", 233 | " \n", 234 | " \n", 235 | " \n", 236 | " \n", 237 | " \n", 238 | " \n", 239 | " \n", 240 | " \n", 241 | " \n", 242 | " \n", 243 | " \n", 244 | " \n", 245 | " \n", 246 | " \n", 247 | " \n", 248 | " \n", 249 | " \n", 250 | " \n", 251 | " \n", 252 | " \n", 253 | " \n", 254 | " \n", 255 | " \n", 256 | " \n", 257 | " \n", 258 | " \n", 259 | " \n", 260 | " \n", 261 | " \n", 262 | " \n", 263 | " \n", 264 | " \n", 265 | " \n", 266 | " \n", 267 | " \n", 268 | " \n", 269 | " \n", 270 | " \n", 271 | " \n", 272 | " \n", 273 | " \n", 274 | " \n", 275 | " \n", 276 | " \n", 277 | " \n", 278 | " \n", 279 | " \n", 280 | " \n", 281 | " \n", 282 | " \n", 283 | " \n", 284 | " \n", 285 | " \n", 286 | " \n", 287 | " \n", 288 | " \n", 289 | " \n", 290 | " \n", 291 | " \n", 292 | " \n", 293 | " \n", 294 | " \n", 295 | " \n", 296 | " \n", 297 | " \n", 298 | " \n", 299 | " \n", 300 | " \n", 301 | " \n", 302 | " \n", 303 | " \n", 304 | " \n", 305 | " \n", 306 | " \n", 307 | " \n", 308 | " \n", 309 | " \n", 310 | " \n", 311 | " \n", 312 | " \n", 313 | " \n", 314 | " \n", 315 | " \n", 316 | " \n", 317 | " \n", 318 | " \n", 319 | "
ground_truthprediction
0SGC
1SGSG
2SGSG
3CC
4SGSG
5SGSG
6SGSG
7SGSG
8CC
9CC
10SGSG
11CC
12CSG
13SGSG
14SGSG
15SGSG
16SGSG
17CC
18CC
19SGSG
\n", 320 | "
" 321 | ], 322 | "text/plain": [ 323 | " ground_truth prediction\n", 324 | "0 SG C\n", 325 | "1 SG SG\n", 326 | "2 SG SG\n", 327 | "3 C C\n", 328 | "4 SG SG\n", 329 | "5 SG SG\n", 330 | "6 SG SG\n", 331 | "7 SG SG\n", 332 | "8 C C\n", 333 | "9 C C\n", 334 | "10 SG SG\n", 335 | "11 C C\n", 336 | "12 C SG\n", 337 | "13 SG SG\n", 338 | "14 SG SG\n", 339 | "15 SG SG\n", 340 | "16 SG SG\n", 341 | "17 C C\n", 342 | "18 C C\n", 343 | "19 SG SG" 344 | ] 345 | }, 346 | "execution_count": 7, 347 | "metadata": {}, 348 | "output_type": "execute_result" 349 | } 350 | ], 351 | "source": [ 352 | "# check ground_truth with knn prediction\n", 353 | "comparison = pd.DataFrame(\n", 354 | " {'prediction':pred, 'ground_truth':y_test.values.ravel()}) \n", 355 | "comparison" 356 | ] 357 | }, 358 | { 359 | "cell_type": "code", 360 | "execution_count": 8, 361 | "metadata": {}, 362 | "outputs": [ 363 | { 364 | "name": "stdout", 365 | "output_type": "stream", 366 | "text": [ 367 | "accuracy : 0.9\n" 368 | ] 369 | } 370 | ], 371 | "source": [ 372 | "# check accuracy\n", 373 | "print(\"accuracy : \"+ \n", 374 | " str(accuracy_score(y_test.values.ravel(), pred)) )" 375 | ] 376 | }, 377 | { 378 | "cell_type": "markdown", 379 | "metadata": {}, 380 | "source": [ 381 | "# 3개의 특징으로 예측하기 (3점슛, 블로킹, 리바운드)" 382 | ] 383 | }, 384 | { 385 | "cell_type": "code", 386 | "execution_count": 9, 387 | "metadata": {}, 388 | "outputs": [], 389 | "source": [ 390 | "knn = KNeighborsClassifier(n_neighbors=k)\n", 391 | "\n", 392 | "# select data features to be used in train\n", 393 | "x_train = train[['3P', 'BLK', 'TRB']]\n", 394 | "# select target\n", 395 | "y_train = train[['Pos']]\n", 396 | "\n", 397 | "# build knn model\n", 398 | "knn.fit(x_train, y_train.values.ravel())\n", 399 | "\n", 400 | "# select features to be used for prediction\n", 401 | "x_test = test[['3P', 'BLK', 'TRB']]\n", 402 | "\n", 403 | "# select target\n", 404 | "y_test = test[['Pos']]\n", 405 | "\n", 406 | "# test\n", 407 | "pred = knn.predict(x_test)" 408 | ] 409 | }, 410 | { 411 | "cell_type": "code", 412 | "execution_count": 10, 413 | "metadata": {}, 414 | "outputs": [ 415 | { 416 | "data": { 417 | "text/html": [ 418 | "
\n", 419 | "\n", 432 | "\n", 433 | " \n", 434 | " \n", 435 | " \n", 436 | " \n", 437 | " \n", 438 | " \n", 439 | " \n", 440 | " \n", 441 | " \n", 442 | " \n", 443 | " \n", 444 | " \n", 445 | " \n", 446 | " \n", 447 | " \n", 448 | " \n", 449 | " \n", 450 | " \n", 451 | " \n", 452 | " \n", 453 | " \n", 454 | " \n", 455 | " \n", 456 | " \n", 457 | " \n", 458 | " \n", 459 | " \n", 460 | " \n", 461 | " \n", 462 | " \n", 463 | " \n", 464 | " \n", 465 | " \n", 466 | " \n", 467 | " \n", 468 | " \n", 469 | " \n", 470 | " \n", 471 | " \n", 472 | " \n", 473 | " \n", 474 | " \n", 475 | " \n", 476 | " \n", 477 | " \n", 478 | " \n", 479 | " \n", 480 | " \n", 481 | " \n", 482 | " \n", 483 | " \n", 484 | " \n", 485 | " \n", 486 | " \n", 487 | " \n", 488 | " \n", 489 | " \n", 490 | " \n", 491 | " \n", 492 | " \n", 493 | " \n", 494 | " \n", 495 | " \n", 496 | " \n", 497 | " \n", 498 | " \n", 499 | " \n", 500 | " \n", 501 | " \n", 502 | " \n", 503 | " \n", 504 | " \n", 505 | " \n", 506 | " \n", 507 | " \n", 508 | " \n", 509 | " \n", 510 | " \n", 511 | " \n", 512 | " \n", 513 | " \n", 514 | " \n", 515 | " \n", 516 | " \n", 517 | " \n", 518 | " \n", 519 | " \n", 520 | " \n", 521 | " \n", 522 | " \n", 523 | " \n", 524 | " \n", 525 | " \n", 526 | " \n", 527 | " \n", 528 | " \n", 529 | " \n", 530 | " \n", 531 | " \n", 532 | " \n", 533 | " \n", 534 | " \n", 535 | " \n", 536 | " \n", 537 | " \n", 538 | " \n", 539 | " \n", 540 | " \n", 541 | " \n", 542 | "
ground_truthprediction
0SGC
1SGSG
2SGSG
3CC
4SGSG
5SGSG
6SGSG
7SGSG
8CC
9CC
10SGSG
11CC
12CSG
13SGSG
14SGSG
15SGSG
16SGSG
17CC
18CC
19SGC
\n", 543 | "
" 544 | ], 545 | "text/plain": [ 546 | " ground_truth prediction\n", 547 | "0 SG C\n", 548 | "1 SG SG\n", 549 | "2 SG SG\n", 550 | "3 C C\n", 551 | "4 SG SG\n", 552 | "5 SG SG\n", 553 | "6 SG SG\n", 554 | "7 SG SG\n", 555 | "8 C C\n", 556 | "9 C C\n", 557 | "10 SG SG\n", 558 | "11 C C\n", 559 | "12 C SG\n", 560 | "13 SG SG\n", 561 | "14 SG SG\n", 562 | "15 SG SG\n", 563 | "16 SG SG\n", 564 | "17 C C\n", 565 | "18 C C\n", 566 | "19 SG C" 567 | ] 568 | }, 569 | "execution_count": 10, 570 | "metadata": {}, 571 | "output_type": "execute_result" 572 | } 573 | ], 574 | "source": [ 575 | "# check ground_truth with knn prediction\n", 576 | "comparison = pd.DataFrame(\n", 577 | " {'prediction':pred, 'ground_truth':y_test.values.ravel()}) \n", 578 | "comparison" 579 | ] 580 | }, 581 | { 582 | "cell_type": "code", 583 | "execution_count": 11, 584 | "metadata": {}, 585 | "outputs": [ 586 | { 587 | "name": "stdout", 588 | "output_type": "stream", 589 | "text": [ 590 | "accuracy : 0.85\n" 591 | ] 592 | } 593 | ], 594 | "source": [ 595 | "# check accuracy\n", 596 | "print(\"accuracy : \" + \n", 597 | " str( accuracy_score(y_test.values.ravel(), pred)) )" 598 | ] 599 | } 600 | ], 601 | "metadata": { 602 | "kernelspec": { 603 | "display_name": "Python 3", 604 | "language": "python", 605 | "name": "python3" 606 | }, 607 | "language_info": { 608 | "codemirror_mode": { 609 | "name": "ipython", 610 | "version": 3 611 | }, 612 | "file_extension": ".py", 613 | "mimetype": "text/x-python", 614 | "name": "python", 615 | "nbconvert_exporter": "python", 616 | "pygments_lexer": "ipython3", 617 | "version": "3.6.4" 618 | } 619 | }, 620 | "nbformat": 4, 621 | "nbformat_minor": 2 622 | } 623 | --------------------------------------------------------------------------------