├── README.md ├── colab_tutorial ├── README.md ├── TutorialMNIST_Chainer.ipynb ├── fig001.png ├── fig002.png └── fig003.png ├── lec2_1 └── perceptron.ipynb ├── lec2_2 └── linear_regression.ipynb ├── lec2_3 └── lec2_3.ipynb ├── lec2_4 ├── lec2_4_1.ipynb ├── lec2_4_2.ipynb └── lec2_4_3.ipynb ├── lec2_5 ├── lec5_1.ipynb ├── lec5_1_colab.ipynb ├── lec5_1_data.txt ├── lec5_2.ipynb └── lec5_3.ipynb ├── lec2_6 ├── 06-k_means.ipynb ├── 06_k_means_colab.ipynb ├── Q_learning_test2019Nov15.ipynb ├── lec2_6_1.ipynb ├── lec2_6_1_colab.ipynb ├── lec2_6_3.ipynb ├── photo.jpg └── qtdbsel102.txt ├── lec2_7 ├── lec2_7_1.ipynb └── lec2_7_2.ipynb ├── lec_2_8 └── convolution_matmul.ipynb ├── report ├── README.txt ├── report1.ipynb ├── report1_macos.ipynb ├── report2.ipynb └── report2_macos.ipynb ├── report2019 ├── README.txt └── Report_FY2019.ipynb ├── report2020 ├── README.txt └── Report_FY2020.ipynb └── report2021 └── README.txt /README.md: -------------------------------------------------------------------------------- 1 | # MachineLearning_Lecture 2 | Machine learning lecture (3Q) materials in Tokyo Tech 3 | -------------------------------------------------------------------------------- /colab_tutorial/README.md: -------------------------------------------------------------------------------- 1 | ## 機械学習の演習 2 | Google社Colaboratoryを使って演習を行います。機械学習ライブラリscikit-learnを使いながらPythonでプログラミングします。 3 | 4 | ## 必要な環境 5 | - インターネットに接続したPC(タブレットも使用可能だと思いますが、各自で対応してください。スマフォも設定すれば対応可能です。) 6 | - Googleアカウント 7 | - Google Chorme ブラウザ(他のブラウザでも可能ですが、Chromeを使うことを奨励) 8 | 9 | ## 演習のやり方 10 | 1. このリポジトリを自分のPCにダウンロードする (Colaboratoryから直接参照もできますが、アクセス制限数に達するのでやめてください!) 11 | 2. Googleの検索ページから自身のアカウントのGoogle ドライブを起動 12 | 13 | ![Example](https://github.com/HirokiNakahara/MachineLearning_Lecture/blob/master/colab_tutorial/fig001.png) 14 | 15 | 3. Googleドライブで新規→その他→Google Colaboratory を選択 16 | 17 | ![Example](https://github.com/HirokiNakahara/MachineLearning_Lecture/blob/master/colab_tutorial/fig002.png) 18 | 19 | 4. Google Colaboratoryが起動するので、ファイル→ノートブックをアップロード を選択して、1. でダウンロードしたノートブックを選択 20 | - 注意: このレポジトリから直接参照もできますが、Githubのアクセス制限数を超える可能性があるので、必ず各自のPC(ローカル)にダウンロードしてからアップロードてください 21 | 22 | ![Example](https://github.com/HirokiNakahara/MachineLearning_Lecture/blob/master/colab_tutorial/fig003.png) 23 | 24 | 25 | 5. ノートブックを上から実行していく 26 | 27 | ## 必須ではないが奨励知識 28 | - Pythonプログラミング (+ Jupyter Notebook) 29 | - Githubを使ったソースコードの管理 30 | - クラウド上でプログラムが実行される仕組み 31 | 32 | ## 履歴 33 | 31/Oct./2019 コードの整備, Colabratory化, チュートリアルのドキュメント作成. 34 | -------------------------------------------------------------------------------- /colab_tutorial/fig001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HirokiNakahara/MachineLearning_Lecture/467f1b2b759775acf59961ab77e143cb01e05c0e/colab_tutorial/fig001.png -------------------------------------------------------------------------------- /colab_tutorial/fig002.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HirokiNakahara/MachineLearning_Lecture/467f1b2b759775acf59961ab77e143cb01e05c0e/colab_tutorial/fig002.png -------------------------------------------------------------------------------- /colab_tutorial/fig003.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HirokiNakahara/MachineLearning_Lecture/467f1b2b759775acf59961ab77e143cb01e05c0e/colab_tutorial/fig003.png -------------------------------------------------------------------------------- /lec2_4/lec2_4_1.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "データ前処理について\n", 8 | "\n", 9 | "Source: https://github.com/rasbt/python-machine-learning-book\n" 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": 1, 15 | "metadata": { 16 | "collapsed": true 17 | }, 18 | "outputs": [], 19 | "source": [ 20 | "#グラフ描画用のおまじない\n", 21 | "from IPython.display import Image\n", 22 | "%matplotlib inline" 23 | ] 24 | }, 25 | { 26 | "cell_type": "code", 27 | "execution_count": 2, 28 | "metadata": { 29 | "collapsed": true 30 | }, 31 | "outputs": [], 32 | "source": [ 33 | "# Added version check for recent scikit-learn 0.18 checks\n", 34 | "from distutils.version import LooseVersion as Version\n", 35 | "from sklearn import __version__ as sklearn_version" 36 | ] 37 | }, 38 | { 39 | "cell_type": "markdown", 40 | "metadata": {}, 41 | "source": [ 42 | "欠損データの扱い" 43 | ] 44 | }, 45 | { 46 | "cell_type": "code", 47 | "execution_count": 4, 48 | "metadata": {}, 49 | "outputs": [ 50 | { 51 | "data": { 52 | "text/html": [ 53 | "
\n", 54 | "\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 | "
ABCD
01.02.03.04.0
15.06.0NaN8.0
210.011.012.0NaN
\n", 101 | "
" 102 | ], 103 | "text/plain": [ 104 | " A B C D\n", 105 | "0 1.0 2.0 3.0 4.0\n", 106 | "1 5.0 6.0 NaN 8.0\n", 107 | "2 10.0 11.0 12.0 NaN" 108 | ] 109 | }, 110 | "execution_count": 4, 111 | "metadata": {}, 112 | "output_type": "execute_result" 113 | } 114 | ], 115 | "source": [ 116 | "import pandas as pd\n", 117 | "from io import StringIO\n", 118 | "\n", 119 | "csv_data = '''A,B,C,D\n", 120 | "1.0,2.0,3.0,4.0\n", 121 | "5.0,6.0,,8.0\n", 122 | "10.0,11.0,12.0,'''\n", 123 | "\n", 124 | "df = pd.read_csv(StringIO(csv_data))\n", 125 | "df" 126 | ] 127 | }, 128 | { 129 | "cell_type": "code", 130 | "execution_count": 5, 131 | "metadata": {}, 132 | "outputs": [ 133 | { 134 | "data": { 135 | "text/plain": [ 136 | "A 0\n", 137 | "B 0\n", 138 | "C 1\n", 139 | "D 1\n", 140 | "dtype: int64" 141 | ] 142 | }, 143 | "execution_count": 5, 144 | "metadata": {}, 145 | "output_type": "execute_result" 146 | } 147 | ], 148 | "source": [ 149 | "#各行毎の欠損データをカウント\n", 150 | "df.isnull().sum()" 151 | ] 152 | }, 153 | { 154 | "cell_type": "code", 155 | "execution_count": 6, 156 | "metadata": {}, 157 | "outputs": [ 158 | { 159 | "data": { 160 | "text/html": [ 161 | "
\n", 162 | "\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 | "
ABCD
01.02.03.04.0
\n", 195 | "
" 196 | ], 197 | "text/plain": [ 198 | " A B C D\n", 199 | "0 1.0 2.0 3.0 4.0" 200 | ] 201 | }, 202 | "execution_count": 6, 203 | "metadata": {}, 204 | "output_type": "execute_result" 205 | } 206 | ], 207 | "source": [ 208 | "#欠損データを含む行を削除\n", 209 | "df.dropna()" 210 | ] 211 | }, 212 | { 213 | "cell_type": "code", 214 | "execution_count": 7, 215 | "metadata": {}, 216 | "outputs": [ 217 | { 218 | "data": { 219 | "text/html": [ 220 | "
\n", 221 | "\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 | "
AB
01.02.0
15.06.0
210.011.0
\n", 260 | "
" 261 | ], 262 | "text/plain": [ 263 | " A B\n", 264 | "0 1.0 2.0\n", 265 | "1 5.0 6.0\n", 266 | "2 10.0 11.0" 267 | ] 268 | }, 269 | "execution_count": 7, 270 | "metadata": {}, 271 | "output_type": "execute_result" 272 | } 273 | ], 274 | "source": [ 275 | "#欠損データを含む列を削除\n", 276 | "df.dropna(axis=1)" 277 | ] 278 | }, 279 | { 280 | "cell_type": "code", 281 | "execution_count": 8, 282 | "metadata": {}, 283 | "outputs": [ 284 | { 285 | "data": { 286 | "text/html": [ 287 | "
\n", 288 | "\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 | " \n", 320 | " \n", 321 | " \n", 322 | " \n", 323 | " \n", 324 | " \n", 325 | " \n", 326 | " \n", 327 | " \n", 328 | " \n", 329 | " \n", 330 | " \n", 331 | " \n", 332 | " \n", 333 | " \n", 334 | "
ABCD
01.02.03.04.0
15.06.0NaN8.0
210.011.012.0NaN
\n", 335 | "
" 336 | ], 337 | "text/plain": [ 338 | " A B C D\n", 339 | "0 1.0 2.0 3.0 4.0\n", 340 | "1 5.0 6.0 NaN 8.0\n", 341 | "2 10.0 11.0 12.0 NaN" 342 | ] 343 | }, 344 | "execution_count": 8, 345 | "metadata": {}, 346 | "output_type": "execute_result" 347 | } 348 | ], 349 | "source": [ 350 | "#全て欠損データを含む行を削除\n", 351 | "df.dropna(how='all') " 352 | ] 353 | }, 354 | { 355 | "cell_type": "code", 356 | "execution_count": 9, 357 | "metadata": {}, 358 | "outputs": [ 359 | { 360 | "data": { 361 | "text/html": [ 362 | "
\n", 363 | "\n", 376 | "\n", 377 | " \n", 378 | " \n", 379 | " \n", 380 | " \n", 381 | " \n", 382 | " \n", 383 | " \n", 384 | " \n", 385 | " \n", 386 | " \n", 387 | " \n", 388 | " \n", 389 | " \n", 390 | " \n", 391 | " \n", 392 | " \n", 393 | " \n", 394 | " \n", 395 | " \n", 396 | " \n", 397 | " \n", 398 | " \n", 399 | " \n", 400 | " \n", 401 | " \n", 402 | "
ABCD
01.02.03.04.0
210.011.012.0NaN
\n", 403 | "
" 404 | ], 405 | "text/plain": [ 406 | " A B C D\n", 407 | "0 1.0 2.0 3.0 4.0\n", 408 | "2 10.0 11.0 12.0 NaN" 409 | ] 410 | }, 411 | "execution_count": 9, 412 | "metadata": {}, 413 | "output_type": "execute_result" 414 | } 415 | ], 416 | "source": [ 417 | "#特定の列に欠損データを含む行を削除\n", 418 | "df.dropna(subset=['C'])" 419 | ] 420 | }, 421 | { 422 | "cell_type": "markdown", 423 | "metadata": {}, 424 | "source": [ 425 | "欠損データの補完" 426 | ] 427 | }, 428 | { 429 | "cell_type": "code", 430 | "execution_count": 10, 431 | "metadata": {}, 432 | "outputs": [ 433 | { 434 | "data": { 435 | "text/plain": [ 436 | "array([[ 1. , 2. , 3. , 4. ],\n", 437 | " [ 5. , 6. , 7.5, 8. ],\n", 438 | " [ 10. , 11. , 12. , 6. ]])" 439 | ] 440 | }, 441 | "execution_count": 10, 442 | "metadata": {}, 443 | "output_type": "execute_result" 444 | } 445 | ], 446 | "source": [ 447 | "from sklearn.preprocessing import Imputer\n", 448 | "\n", 449 | "imr = Imputer(missing_values='NaN', strategy='mean', axis=0)\n", 450 | "imr = imr.fit(df)\n", 451 | "imputed_data = imr.transform(df.values)\n", 452 | "imputed_data" 453 | ] 454 | }, 455 | { 456 | "cell_type": "markdown", 457 | "metadata": {}, 458 | "source": [ 459 | "カテゴリデータの扱い" 460 | ] 461 | }, 462 | { 463 | "cell_type": "code", 464 | "execution_count": 11, 465 | "metadata": {}, 466 | "outputs": [ 467 | { 468 | "data": { 469 | "text/html": [ 470 | "
\n", 471 | "\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 | "
colorsizepriceclasslabel
0greenM10.1class1
1redL13.5class2
2blueXL15.3class1
\n", 518 | "
" 519 | ], 520 | "text/plain": [ 521 | " color size price classlabel\n", 522 | "0 green M 10.1 class1\n", 523 | "1 red L 13.5 class2\n", 524 | "2 blue XL 15.3 class1" 525 | ] 526 | }, 527 | "execution_count": 11, 528 | "metadata": {}, 529 | "output_type": "execute_result" 530 | } 531 | ], 532 | "source": [ 533 | "import pandas as pd\n", 534 | "\n", 535 | "df = pd.DataFrame([['green', 'M', 10.1, 'class1'],\n", 536 | " ['red', 'L', 13.5, 'class2'],\n", 537 | " ['blue', 'XL', 15.3, 'class1']])\n", 538 | "\n", 539 | "df.columns = ['color', 'size', 'price', 'classlabel']\n", 540 | "df" 541 | ] 542 | }, 543 | { 544 | "cell_type": "code", 545 | "execution_count": 12, 546 | "metadata": {}, 547 | "outputs": [ 548 | { 549 | "data": { 550 | "text/html": [ 551 | "
\n", 552 | "\n", 565 | "\n", 566 | " \n", 567 | " \n", 568 | " \n", 569 | " \n", 570 | " \n", 571 | " \n", 572 | " \n", 573 | " \n", 574 | " \n", 575 | " \n", 576 | " \n", 577 | " \n", 578 | " \n", 579 | " \n", 580 | " \n", 581 | " \n", 582 | " \n", 583 | " \n", 584 | " \n", 585 | " \n", 586 | " \n", 587 | " \n", 588 | " \n", 589 | " \n", 590 | " \n", 591 | " \n", 592 | " \n", 593 | " \n", 594 | " \n", 595 | " \n", 596 | " \n", 597 | " \n", 598 | "
colorsizepriceclasslabel
0green110.1class1
1red213.5class2
2blue315.3class1
\n", 599 | "
" 600 | ], 601 | "text/plain": [ 602 | " color size price classlabel\n", 603 | "0 green 1 10.1 class1\n", 604 | "1 red 2 13.5 class2\n", 605 | "2 blue 3 15.3 class1" 606 | ] 607 | }, 608 | "execution_count": 12, 609 | "metadata": {}, 610 | "output_type": "execute_result" 611 | } 612 | ], 613 | "source": [ 614 | "#順序特徴量を設定する\n", 615 | "size_mapping = {'XL': 3,\n", 616 | " 'L': 2,\n", 617 | " 'M': 1}\n", 618 | "\n", 619 | "df['size'] = df['size'].map(size_mapping)\n", 620 | "df" 621 | ] 622 | }, 623 | { 624 | "cell_type": "code", 625 | "execution_count": 13, 626 | "metadata": {}, 627 | "outputs": [ 628 | { 629 | "data": { 630 | "text/plain": [ 631 | "0 M\n", 632 | "1 L\n", 633 | "2 XL\n", 634 | "Name: size, dtype: object" 635 | ] 636 | }, 637 | "execution_count": 13, 638 | "metadata": {}, 639 | "output_type": "execute_result" 640 | } 641 | ], 642 | "source": [ 643 | "inv_size_mapping = {v: k for k, v in size_mapping.items()} #内包的表現\n", 644 | "df['size'].map(inv_size_mapping) #sizeをキー値として呼び出し、ラベルを表示" 645 | ] 646 | }, 647 | { 648 | "cell_type": "markdown", 649 | "metadata": {}, 650 | "source": [ 651 | "クラスラベルの符号化" 652 | ] 653 | }, 654 | { 655 | "cell_type": "code", 656 | "execution_count": 14, 657 | "metadata": {}, 658 | "outputs": [ 659 | { 660 | "data": { 661 | "text/plain": [ 662 | "{'class1': 0, 'class2': 1}" 663 | ] 664 | }, 665 | "execution_count": 14, 666 | "metadata": {}, 667 | "output_type": "execute_result" 668 | } 669 | ], 670 | "source": [ 671 | "import numpy as np\n", 672 | "\n", 673 | "class_mapping = {label: idx for idx, label in enumerate(np.unique(df['classlabel']))}\n", 674 | "class_mapping" 675 | ] 676 | }, 677 | { 678 | "cell_type": "code", 679 | "execution_count": 15, 680 | "metadata": {}, 681 | "outputs": [ 682 | { 683 | "data": { 684 | "text/html": [ 685 | "
\n", 686 | "\n", 699 | "\n", 700 | " \n", 701 | " \n", 702 | " \n", 703 | " \n", 704 | " \n", 705 | " \n", 706 | " \n", 707 | " \n", 708 | " \n", 709 | " \n", 710 | " \n", 711 | " \n", 712 | " \n", 713 | " \n", 714 | " \n", 715 | " \n", 716 | " \n", 717 | " \n", 718 | " \n", 719 | " \n", 720 | " \n", 721 | " \n", 722 | " \n", 723 | " \n", 724 | " \n", 725 | " \n", 726 | " \n", 727 | " \n", 728 | " \n", 729 | " \n", 730 | " \n", 731 | " \n", 732 | "
colorsizepriceclasslabel
0green110.10
1red213.51
2blue315.30
\n", 733 | "
" 734 | ], 735 | "text/plain": [ 736 | " color size price classlabel\n", 737 | "0 green 1 10.1 0\n", 738 | "1 red 2 13.5 1\n", 739 | "2 blue 3 15.3 0" 740 | ] 741 | }, 742 | "execution_count": 15, 743 | "metadata": {}, 744 | "output_type": "execute_result" 745 | } 746 | ], 747 | "source": [ 748 | "df['classlabel'] = df['classlabel'].map(class_mapping)\n", 749 | "df" 750 | ] 751 | }, 752 | { 753 | "cell_type": "code", 754 | "execution_count": 16, 755 | "metadata": {}, 756 | "outputs": [ 757 | { 758 | "data": { 759 | "text/html": [ 760 | "
\n", 761 | "\n", 774 | "\n", 775 | " \n", 776 | " \n", 777 | " \n", 778 | " \n", 779 | " \n", 780 | " \n", 781 | " \n", 782 | " \n", 783 | " \n", 784 | " \n", 785 | " \n", 786 | " \n", 787 | " \n", 788 | " \n", 789 | " \n", 790 | " \n", 791 | " \n", 792 | " \n", 793 | " \n", 794 | " \n", 795 | " \n", 796 | " \n", 797 | " \n", 798 | " \n", 799 | " \n", 800 | " \n", 801 | " \n", 802 | " \n", 803 | " \n", 804 | " \n", 805 | " \n", 806 | " \n", 807 | "
colorsizepriceclasslabel
0green110.1class1
1red213.5class2
2blue315.3class1
\n", 808 | "
" 809 | ], 810 | "text/plain": [ 811 | " color size price classlabel\n", 812 | "0 green 1 10.1 class1\n", 813 | "1 red 2 13.5 class2\n", 814 | "2 blue 3 15.3 class1" 815 | ] 816 | }, 817 | "execution_count": 16, 818 | "metadata": {}, 819 | "output_type": "execute_result" 820 | } 821 | ], 822 | "source": [ 823 | "# 符号化したクラスからラベルを再度割り当てる\n", 824 | "inv_class_mapping = {v: k for k, v in class_mapping.items()}\n", 825 | "df['classlabel'] = df['classlabel'].map(inv_class_mapping)\n", 826 | "df" 827 | ] 828 | }, 829 | { 830 | "cell_type": "code", 831 | "execution_count": 17, 832 | "metadata": {}, 833 | "outputs": [ 834 | { 835 | "data": { 836 | "text/plain": [ 837 | "array([0, 1, 0], dtype=int64)" 838 | ] 839 | }, 840 | "execution_count": 17, 841 | "metadata": {}, 842 | "output_type": "execute_result" 843 | } 844 | ], 845 | "source": [ 846 | "from sklearn.preprocessing import LabelEncoder\n", 847 | "\n", 848 | "#ラベルエンコーダのインスタンシエーション\n", 849 | "class_le = LabelEncoder()\n", 850 | "\n", 851 | "#クラスラベルに整数を割り当て\n", 852 | "y = class_le.fit_transform(df['classlabel'].values)\n", 853 | "y" 854 | ] 855 | }, 856 | { 857 | "cell_type": "code", 858 | "execution_count": 18, 859 | "metadata": {}, 860 | "outputs": [ 861 | { 862 | "data": { 863 | "text/plain": [ 864 | "array(['class1', 'class2', 'class1'], dtype=object)" 865 | ] 866 | }, 867 | "execution_count": 18, 868 | "metadata": {}, 869 | "output_type": "execute_result" 870 | } 871 | ], 872 | "source": [ 873 | "#クラスラベルに戻す\n", 874 | "class_le.inverse_transform(y)" 875 | ] 876 | }, 877 | { 878 | "cell_type": "code", 879 | "execution_count": 19, 880 | "metadata": {}, 881 | "outputs": [ 882 | { 883 | "data": { 884 | "text/plain": [ 885 | "array([[1, 1, 10.1],\n", 886 | " [2, 2, 13.5],\n", 887 | " [0, 3, 15.3]], dtype=object)" 888 | ] 889 | }, 890 | "execution_count": 19, 891 | "metadata": {}, 892 | "output_type": "execute_result" 893 | } 894 | ], 895 | "source": [ 896 | "# color, size, price を抽出\n", 897 | "X = df[['color', 'size', 'price']].values\n", 898 | "\n", 899 | "# blue\n", 900 | "# green\n", 901 | "# red -> 2\n", 902 | "color_le = LabelEncoder()\n", 903 | "X[:, 0] = color_le.fit_transform(X[:, 0])\n", 904 | "X" 905 | ] 906 | }, 907 | { 908 | "cell_type": "code", 909 | "execution_count": null, 910 | "metadata": { 911 | "collapsed": true 912 | }, 913 | "outputs": [], 914 | "source": [] 915 | } 916 | ], 917 | "metadata": { 918 | "kernelspec": { 919 | "display_name": "Python 3", 920 | "language": "python", 921 | "name": "python3" 922 | }, 923 | "language_info": { 924 | "codemirror_mode": { 925 | "name": "ipython", 926 | "version": 3 927 | }, 928 | "file_extension": ".py", 929 | "mimetype": "text/x-python", 930 | "name": "python", 931 | "nbconvert_exporter": "python", 932 | "pygments_lexer": "ipython3", 933 | "version": "3.6.3" 934 | } 935 | }, 936 | "nbformat": 4, 937 | "nbformat_minor": 2 938 | } 939 | -------------------------------------------------------------------------------- /lec2_4/lec2_4_3.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "過適合に対するパラメータ調整" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": 11, 13 | "metadata": { 14 | "collapsed": true 15 | }, 16 | "outputs": [], 17 | "source": [ 18 | "from IPython.display import Image\n", 19 | "%matplotlib inline\n", 20 | "# Added version check for recent scikit-learn 0.18 checks\n", 21 | "from distutils.version import LooseVersion as Version\n", 22 | "from sklearn import __version__ as sklearn_version\n", 23 | "import numpy as np" 24 | ] 25 | }, 26 | { 27 | "cell_type": "code", 28 | "execution_count": 8, 29 | "metadata": {}, 30 | "outputs": [ 31 | { 32 | "name": "stdout", 33 | "output_type": "stream", 34 | "text": [ 35 | "rows, columns: (569, 32)\n" 36 | ] 37 | }, 38 | { 39 | "data": { 40 | "text/html": [ 41 | "
\n", 42 | "\n", 55 | "\n", 56 | " \n", 57 | " \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 | " \n", 119 | " \n", 120 | " \n", 121 | " \n", 122 | " \n", 123 | " \n", 124 | " \n", 125 | " \n", 126 | " \n", 127 | " \n", 128 | " \n", 129 | " \n", 130 | " \n", 131 | " \n", 132 | " \n", 133 | " \n", 134 | " \n", 135 | " \n", 136 | " \n", 137 | " \n", 138 | " \n", 139 | " \n", 140 | " \n", 141 | " \n", 142 | " \n", 143 | " \n", 144 | " \n", 145 | " \n", 146 | " \n", 147 | " \n", 148 | " \n", 149 | " \n", 150 | " \n", 151 | " \n", 152 | " \n", 153 | " \n", 154 | " \n", 155 | " \n", 156 | " \n", 157 | " \n", 158 | " \n", 159 | " \n", 160 | " \n", 161 | " \n", 162 | " \n", 163 | " \n", 164 | " \n", 165 | " \n", 166 | " \n", 167 | " \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 | "
0123456789...22232425262728293031
0842302M17.9910.38122.801001.00.118400.277600.30010.14710...25.3817.33184.602019.00.16220.66560.71190.26540.46010.11890
1842517M20.5717.77132.901326.00.084740.078640.08690.07017...24.9923.41158.801956.00.12380.18660.24160.18600.27500.08902
284300903M19.6921.25130.001203.00.109600.159900.19740.12790...23.5725.53152.501709.00.14440.42450.45040.24300.36130.08758
384348301M11.4220.3877.58386.10.142500.283900.24140.10520...14.9126.5098.87567.70.20980.86630.68690.25750.66380.17300
484358402M20.2914.34135.101297.00.100300.132800.19800.10430...22.5416.67152.201575.00.13740.20500.40000.16250.23640.07678
\n", 205 | "

5 rows × 32 columns

\n", 206 | "
" 207 | ], 208 | "text/plain": [ 209 | " 0 1 2 3 4 5 6 7 8 \\\n", 210 | "0 842302 M 17.99 10.38 122.80 1001.0 0.11840 0.27760 0.3001 \n", 211 | "1 842517 M 20.57 17.77 132.90 1326.0 0.08474 0.07864 0.0869 \n", 212 | "2 84300903 M 19.69 21.25 130.00 1203.0 0.10960 0.15990 0.1974 \n", 213 | "3 84348301 M 11.42 20.38 77.58 386.1 0.14250 0.28390 0.2414 \n", 214 | "4 84358402 M 20.29 14.34 135.10 1297.0 0.10030 0.13280 0.1980 \n", 215 | "\n", 216 | " 9 ... 22 23 24 25 26 27 28 \\\n", 217 | "0 0.14710 ... 25.38 17.33 184.60 2019.0 0.1622 0.6656 0.7119 \n", 218 | "1 0.07017 ... 24.99 23.41 158.80 1956.0 0.1238 0.1866 0.2416 \n", 219 | "2 0.12790 ... 23.57 25.53 152.50 1709.0 0.1444 0.4245 0.4504 \n", 220 | "3 0.10520 ... 14.91 26.50 98.87 567.7 0.2098 0.8663 0.6869 \n", 221 | "4 0.10430 ... 22.54 16.67 152.20 1575.0 0.1374 0.2050 0.4000 \n", 222 | "\n", 223 | " 29 30 31 \n", 224 | "0 0.2654 0.4601 0.11890 \n", 225 | "1 0.1860 0.2750 0.08902 \n", 226 | "2 0.2430 0.3613 0.08758 \n", 227 | "3 0.2575 0.6638 0.17300 \n", 228 | "4 0.1625 0.2364 0.07678 \n", 229 | "\n", 230 | "[5 rows x 32 columns]" 231 | ] 232 | }, 233 | "execution_count": 8, 234 | "metadata": {}, 235 | "output_type": "execute_result" 236 | } 237 | ], 238 | "source": [ 239 | "#データの読み込み\n", 240 | "import pandas as pd\n", 241 | "import urllib\n", 242 | "\n", 243 | "try:\n", 244 | " df = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases'\n", 245 | " '/breast-cancer-wisconsin/wdbc.data', header=None)\n", 246 | "\n", 247 | "except urllib.error.URLError:\n", 248 | " df = pd.read_csv('https://raw.githubusercontent.com/rasbt/'\n", 249 | " 'python-machine-learning-book/master/code/'\n", 250 | " 'datasets/wdbc/wdbc.data', header=None)\n", 251 | " \n", 252 | "print('rows, columns:', df.shape)\n", 253 | "df.head()" 254 | ] 255 | }, 256 | { 257 | "cell_type": "code", 258 | "execution_count": 9, 259 | "metadata": { 260 | "collapsed": true 261 | }, 262 | "outputs": [], 263 | "source": [ 264 | "# データ前処理\n", 265 | "\n", 266 | "# 符号化\n", 267 | "from sklearn.preprocessing import LabelEncoder\n", 268 | "\n", 269 | "X = df.loc[:, 2:].values\n", 270 | "y = df.loc[:, 1].values\n", 271 | "le = LabelEncoder()\n", 272 | "y = le.fit_transform(y)\n", 273 | "le.transform(['M', 'B'])\n", 274 | "\n", 275 | "# 訓練データとテストデータに分割\n", 276 | "if Version(sklearn_version) < '0.18':\n", 277 | " from sklearn.cross_validation import train_test_split\n", 278 | "else:\n", 279 | " from sklearn.model_selection import train_test_split\n", 280 | "\n", 281 | "X_train, X_test, y_train, y_test = \\\n", 282 | " train_test_split(X, y, test_size=0.20, random_state=1)" 283 | ] 284 | }, 285 | { 286 | "cell_type": "markdown", 287 | "metadata": {}, 288 | "source": [ 289 | "学習曲線を使った過学習のチェック" 290 | ] 291 | }, 292 | { 293 | "cell_type": "code", 294 | "execution_count": 12, 295 | "metadata": {}, 296 | "outputs": [ 297 | { 298 | "data": { 299 | "image/png": "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\neJL/B9ALUVU0A3OVAAAAAElFTkSuQmCC\n", 300 | "text/plain": [ 301 | "" 302 | ] 303 | }, 304 | "metadata": {}, 305 | "output_type": "display_data" 306 | } 307 | ], 308 | "source": [ 309 | "from sklearn.preprocessing import StandardScaler\n", 310 | "from sklearn.pipeline import Pipeline\n", 311 | "from sklearn.linear_model import LogisticRegression\n", 312 | "import matplotlib.pyplot as plt\n", 313 | "\n", 314 | "if Version(sklearn_version) < '0.18':\n", 315 | " from sklearn.learning_curve import learning_curve\n", 316 | "else:\n", 317 | " from sklearn.model_selection import learning_curve\n", 318 | "\n", 319 | "\n", 320 | "\n", 321 | "pipe_lr = Pipeline([('scl', StandardScaler()),\n", 322 | " ('clf', LogisticRegression(penalty='l2', random_state=0, solver='liblinear'))])\n", 323 | "\n", 324 | "train_sizes, train_scores, test_scores =\\\n", 325 | " learning_curve(estimator=pipe_lr,\n", 326 | " X=X_train,\n", 327 | " y=y_train,\n", 328 | " train_sizes=np.linspace(0.1, 1.0, 10),\n", 329 | " cv=10,\n", 330 | " n_jobs=1)\n", 331 | "\n", 332 | "train_mean = np.mean(train_scores, axis=1)\n", 333 | "train_std = np.std(train_scores, axis=1)\n", 334 | "test_mean = np.mean(test_scores, axis=1)\n", 335 | "test_std = np.std(test_scores, axis=1)\n", 336 | "\n", 337 | "plt.plot(train_sizes, train_mean,\n", 338 | " color='blue', marker='o',\n", 339 | " markersize=5, label='training accuracy')\n", 340 | "\n", 341 | "plt.fill_between(train_sizes,\n", 342 | " train_mean + train_std,\n", 343 | " train_mean - train_std,\n", 344 | " alpha=0.15, color='blue')\n", 345 | "\n", 346 | "plt.plot(train_sizes, test_mean,\n", 347 | " color='green', linestyle='--',\n", 348 | " marker='s', markersize=5,\n", 349 | " label='validation accuracy')\n", 350 | "\n", 351 | "plt.fill_between(train_sizes,\n", 352 | " test_mean + test_std,\n", 353 | " test_mean - test_std,\n", 354 | " alpha=0.15, color='green')\n", 355 | "\n", 356 | "plt.grid()\n", 357 | "plt.xlabel('Number of training samples')\n", 358 | "plt.ylabel('Accuracy')\n", 359 | "plt.legend(loc='lower right')\n", 360 | "plt.ylim([0.8, 1.0])\n", 361 | "plt.tight_layout()\n", 362 | "# plt.savefig('./figures/learning_curve.png', dpi=300)\n", 363 | "plt.show()" 364 | ] 365 | }, 366 | { 367 | "cell_type": "markdown", 368 | "metadata": {}, 369 | "source": [ 370 | "検証曲線による過学習の確認" 371 | ] 372 | }, 373 | { 374 | "cell_type": "code", 375 | "execution_count": null, 376 | "metadata": { 377 | "collapsed": true 378 | }, 379 | "outputs": [], 380 | "source": [ 381 | "if Version(sklearn_version) < '0.18':\n", 382 | " from sklearn.learning_curve import validation_curve\n", 383 | "else:\n", 384 | " from sklearn.model_selection import validation_curve\n", 385 | "\n", 386 | "\n", 387 | "\n", 388 | "param_range = [0.001, 0.01, 0.1, 1.0, 10.0, 100.0]\n", 389 | "train_scores, test_scores = validation_curve(\n", 390 | " estimator=pipe_lr, \n", 391 | " X=X_train, \n", 392 | " y=y_train, \n", 393 | " param_name='clf__C', \n", 394 | " param_range=param_range,\n", 395 | " cv=10)\n", 396 | "\n", 397 | "train_mean = np.mean(train_scores, axis=1)\n", 398 | "train_std = np.std(train_scores, axis=1)\n", 399 | "test_mean = np.mean(test_scores, axis=1)\n", 400 | "test_std = np.std(test_scores, axis=1)\n", 401 | "\n", 402 | "plt.plot(param_range, train_mean, \n", 403 | " color='blue', marker='o', \n", 404 | " markersize=5, label='training accuracy')\n", 405 | "\n", 406 | "plt.fill_between(param_range, train_mean + train_std,\n", 407 | " train_mean - train_std, alpha=0.15,\n", 408 | " color='blue')\n", 409 | "\n", 410 | "plt.plot(param_range, test_mean, \n", 411 | " color='green', linestyle='--', \n", 412 | " marker='s', markersize=5, \n", 413 | " label='validation accuracy')\n", 414 | "\n", 415 | "plt.fill_between(param_range, \n", 416 | " test_mean + test_std,\n", 417 | " test_mean - test_std, \n", 418 | " alpha=0.15, color='green')\n", 419 | "\n", 420 | "plt.grid()\n", 421 | "plt.xscale('log')\n", 422 | "plt.legend(loc='lower right')\n", 423 | "plt.xlabel('Parameter C')\n", 424 | "plt.ylabel('Accuracy')\n", 425 | "plt.ylim([0.8, 1.0])\n", 426 | "plt.tight_layout()\n", 427 | "# plt.savefig('./figures/validation_curve.png', dpi=300)\n", 428 | "plt.show()" 429 | ] 430 | } 431 | ], 432 | "metadata": { 433 | "kernelspec": { 434 | "display_name": "Python 3", 435 | "language": "python", 436 | "name": "python3" 437 | }, 438 | "language_info": { 439 | "codemirror_mode": { 440 | "name": "ipython", 441 | "version": 3 442 | }, 443 | "file_extension": ".py", 444 | "mimetype": "text/x-python", 445 | "name": "python", 446 | "nbconvert_exporter": "python", 447 | "pygments_lexer": "ipython3", 448 | "version": "3.6.3" 449 | } 450 | }, 451 | "nbformat": 4, 452 | "nbformat_minor": 2 453 | } 454 | -------------------------------------------------------------------------------- /lec2_5/lec5_1_data.txt: -------------------------------------------------------------------------------- 1 | A,Score,Y 2 | 0,69,0.286 3 | 1,145,0.196 4 | 0,125,0.261 5 | 1,86,0.109 6 | 1,158,0.23 7 | 0,133,0.35 8 | 0,111,0.33 9 | 1,147,0.194 10 | 0,146,0.413 11 | 0,145,0.36 12 | 1,141,0.225 13 | 0,137,0.423 14 | 1,118,0.186 15 | 0,111,0.287 16 | 0,109,0.371 17 | 1,99,0.183 18 | 0,114,0.345 19 | 0,82,0.264 20 | 0,185,0.413 21 | 1,156,0.316 22 | 1,86,0.062 23 | 1,108,0.272 24 | 1,106,0.229 25 | 1,143,0.195 26 | 1,117,0.097 27 | 1,128,0.137 28 | 0,119,0.337 29 | 0,119,0.307 30 | 0,161,0.383 31 | 0,113,0.253 32 | 1,165,0.249 33 | 1,74,0.027 34 | 1,138,0.099 35 | 1,124,0.149 36 | 0,126,0.391 37 | 0,131,0.311 38 | 1,105,0.171 39 | 0,110,0.207 40 | 0,89,0.26 41 | 0,88,0.293 42 | 0,129,0.36 43 | 0,133,0.356 44 | 0,122,0.289 45 | 0,148,0.328 46 | 0,182,0.383 47 | 0,105,0.302 48 | 0,51,0.133 49 | 0,150,0.353 50 | 0,99,0.268 51 | 1,99,0.234 -------------------------------------------------------------------------------- /lec2_5/lec5_2.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "LDAによるニュース分類\n", 8 | "\n", 9 | "Source: https://dev.classmethod.jp/machine-learning/2017ad_20171221_lda_python/\n", 10 | "\n", 11 | "機械学習_潜在意味解析_pythonで実装" 12 | ] 13 | }, 14 | { 15 | "cell_type": "markdown", 16 | "metadata": {}, 17 | "source": [ 18 | "データのロード" 19 | ] 20 | }, 21 | { 22 | "cell_type": "code", 23 | "execution_count": 1, 24 | "metadata": {}, 25 | "outputs": [ 26 | { 27 | "name": "stdout", 28 | "output_type": "stream", 29 | "text": [ 30 | "['comp.sys.mac.hardware', 'comp.windows.x', 'rec.sport.baseball', 'rec.sport.hockey']\n", 31 | "2368\n", 32 | "1576\n", 33 | "From: pkeenan@s.psych.uiuc.edu (Patricia Keenan)\n", 34 | "Subject: Re: Quick easy question!\n", 35 | "Organization: UIUC Department of Psychology\n", 36 | "Lines: 16\n", 37 | "\n", 38 | "rauser@fraser.sfu.ca (Richard John Rauser) writes:\n", 39 | "\n", 40 | "\n", 41 | "\n", 42 | "> Here's an easy question for someone who knows nothing about baseball...\n", 43 | "\n", 44 | "> What city do the California Angels play out of?\n", 45 | "\n", 46 | " Anaheim.\n", 47 | "\n", 48 | ">-- \n", 49 | ">Richard J. Rauser \"You have no idea what you're doing.\"\n", 50 | ">rauser@sfu.ca \"Oh, don't worry about that. We're professional\n", 51 | ">WNI outlaws - we do this for a living.\"\n", 52 | ">-----------------\n", 53 | ">\"Remember, no matter where you go, there you are.\" -Dr.Banzai\n", 54 | "\n", 55 | "rec.sport.baseball\n" 56 | ] 57 | } 58 | ], 59 | "source": [ 60 | "'''1.必要なモジュールとデータセットの準備\n", 61 | "sklearnに用意されている「ニュース」のデータセットを利用します\n", 62 | "'''\n", 63 | " \n", 64 | "# モジュールのインポート\n", 65 | "from sklearn.datasets import fetch_20newsgroups \n", 66 | " \n", 67 | "'''\n", 68 | "sklearnに用意されている「ニュース」のデータセットを利用します。\n", 69 | "'''\n", 70 | " \n", 71 | "# カテゴリーの絞り込み\n", 72 | "categories = ['rec.sport.baseball', 'rec.sport.hockey', 'comp.sys.mac.hardware', 'comp.windows.x']\n", 73 | " \n", 74 | "# トレーニング用、検証用のデータセット作成\n", 75 | "twenty_train = fetch_20newsgroups(subset='train',categories=categories, shuffle=True, random_state=42)\n", 76 | "twenty_test = fetch_20newsgroups(subset='test',categories=categories, shuffle=True, random_state=42)\n", 77 | " \n", 78 | "# データの中身確認\n", 79 | "print(twenty_train.target_names) # カテゴリの確認(どんなカテゴリがあるのか)\n", 80 | "print (len(twenty_train.data)) # ニュースデータが何本あるのか(2,368本のニュースデータ)\n", 81 | "print (len(twenty_test.data)) # ニュースデータが何本あるのか(1,576本のニュースデータ)\n", 82 | "print(\"\\n\".join(twenty_train.data[0].split(\"\\n\"))) #データの内容を確認(1個の文書の中身を確認)\n", 83 | "print(twenty_train.target_names[twenty_train.target[0]]) #データのカテゴリーを確認" 84 | ] 85 | }, 86 | { 87 | "cell_type": "markdown", 88 | "metadata": {}, 89 | "source": [ 90 | "データの前処理" 91 | ] 92 | }, 93 | { 94 | "cell_type": "code", 95 | "execution_count": 2, 96 | "metadata": {}, 97 | "outputs": [ 98 | { 99 | "name": "stdout", 100 | "output_type": "stream", 101 | "text": [ 102 | "tf-idfの計算結果の概要\n", 103 | ":<2368x7562 sparse matrix of type ''\n", 104 | "\twith 159495 stored elements in Compressed Sparse Row format>\n", 105 | "\n", 106 | "最初の30個の単語\n", 107 | ":['00', '000', '0062', '00mbstultz', '01', '02', '0200', '0223', '024222', '03', '030', '04', '040', '0400', '05', '051', '06', '065', '0666', '07', '08', '09', '0ha', '100', '1000', '101', '1010', '102', '1020', '1024']\n", 108 | "\n", 109 | "500-530\n", 110 | ":['636', '637', '64', '640', '643', '645', '647', '649', '64k', '65', '650', '653', '655', '656', '657', '66', '660', '664', '666', '667', '66mhz', '67', '672', '675', '678', '68', '680', '68000', '68020', '68030']\n", 111 | "\n", 112 | "1000-1030\n", 113 | ":['ask', 'asked', 'asking', 'asks', 'aspect', 'aspects', 'ass', 'assat', 'assembled', 'assessment', 'asshole', 'assholes', 'assist', 'assistance', 'assistant', 'assists', 'associated', 'associates', 'association', 'assume', 'assumed', 'assumes', 'assuming', 'ast', 'astro', 'astronomy', 'astros', 'asynchronous', 'atd', 'athena']\n" 114 | ] 115 | } 116 | ], 117 | "source": [ 118 | "'''2.前処理\n", 119 | "前処理で実施したものは下記の4点。\n", 120 | "・文字を全て小文字化\n", 121 | "・stop words削除\n", 122 | "・全文書の1割以上の文書に出現する単語の削除\n", 123 | "・5回以上出現する単語のみ\n", 124 | "'''\n", 125 | " \n", 126 | "# tf-idf計算した時の単語数を確認してみる\n", 127 | "from sklearn.feature_extraction.text import TfidfVectorizer\n", 128 | " \n", 129 | "tfidf_vec = TfidfVectorizer(lowercase=True, stop_words='english', max_df = 0.1, min_df = 5).fit(twenty_train.data) # \n", 130 | "X_train = tfidf_vec.transform(twenty_train.data) \n", 131 | "X_test = tfidf_vec.transform(twenty_test.data) \n", 132 | " \n", 133 | "print('tf-idfの計算結果の概要\\n:{}'.format(repr(X_train))) # 2,368行7,562列の疎行列\n", 134 | " \n", 135 | "# 各単語の中身を確認する\n", 136 | "feature_names = tfidf_vec.get_feature_names()\n", 137 | "print('\\n最初の30個の単語\\n:{}'.format(feature_names[:30]))\n", 138 | "print('\\n500-530\\n:{}'.format(feature_names[500:530]))\n", 139 | "print('\\n1000-1030\\n:{}'.format(feature_names[1000:1030]))" 140 | ] 141 | }, 142 | { 143 | "cell_type": "markdown", 144 | "metadata": {}, 145 | "source": [ 146 | "モデルの生成と評価(注意!実行にかなり時間がかかる)" 147 | ] 148 | }, 149 | { 150 | "cell_type": "code", 151 | "execution_count": 3, 152 | "metadata": {}, 153 | "outputs": [ 154 | { 155 | "name": "stdout", 156 | "output_type": "stream", 157 | "text": [ 158 | "トピック数:2,反復回数:50回,処理時間:0.38分,exp(-1. * log-likelihood per word)(perplexity):11768.51\n", 159 | "トピック数:2,反復回数:100回,処理時間:0.62分,exp(-1. * log-likelihood per word)(perplexity):11768.57\n", 160 | "トピック数:2,反復回数:300回,処理時間:1.66分,exp(-1. * log-likelihood per word)(perplexity):11768.57\n", 161 | "トピック数:2,反復回数:500回,処理時間:2.61分,exp(-1. * log-likelihood per word)(perplexity):11768.57\n", 162 | "トピック数:3,反復回数:50回,処理時間:0.37分,exp(-1. * log-likelihood per word)(perplexity):17218.32\n", 163 | "トピック数:3,反復回数:100回,処理時間:0.62分,exp(-1. * log-likelihood per word)(perplexity):17215.31\n", 164 | "トピック数:3,反復回数:300回,処理時間:1.66分,exp(-1. * log-likelihood per word)(perplexity):17210.34\n", 165 | "トピック数:3,反復回数:500回,処理時間:2.64分,exp(-1. * log-likelihood per word)(perplexity):17210.34\n", 166 | "トピック数:4,反復回数:50回,処理時間:0.36分,exp(-1. * log-likelihood per word)(perplexity):19769.88\n", 167 | "トピック数:4,反復回数:100回,処理時間:0.62分,exp(-1. * log-likelihood per word)(perplexity):19660.65\n", 168 | "トピック数:4,反復回数:300回,処理時間:1.51分,exp(-1. * log-likelihood per word)(perplexity):19552.25\n", 169 | "トピック数:4,反復回数:500回,処理時間:2.57分,exp(-1. * log-likelihood per word)(perplexity):19552.25\n", 170 | "トピック数:5,反復回数:50回,処理時間:0.41分,exp(-1. * log-likelihood per word)(perplexity):27679.2\n", 171 | "トピック数:5,反復回数:100回,処理時間:0.62分,exp(-1. * log-likelihood per word)(perplexity):27635.09\n", 172 | "トピック数:5,反復回数:300回,処理時間:1.61分,exp(-1. * log-likelihood per word)(perplexity):27582.52\n", 173 | "トピック数:5,反復回数:500回,処理時間:2.63分,exp(-1. * log-likelihood per word)(perplexity):27583.2\n", 174 | "トピック数:6,反復回数:50回,処理時間:0.35分,exp(-1. * log-likelihood per word)(perplexity):28876.65\n", 175 | "トピック数:6,反復回数:100回,処理時間:0.59分,exp(-1. * log-likelihood per word)(perplexity):28715.61\n", 176 | "トピック数:6,反復回数:300回,処理時間:1.64分,exp(-1. * log-likelihood per word)(perplexity):28685.25\n", 177 | "トピック数:6,反復回数:500回,処理時間:2.5分,exp(-1. * log-likelihood per word)(perplexity):28685.25\n", 178 | "トピック数:10,反復回数:50回,処理時間:0.36分,exp(-1. * log-likelihood per word)(perplexity):71089.24\n", 179 | "トピック数:10,反復回数:100回,処理時間:0.63分,exp(-1. * log-likelihood per word)(perplexity):70729.3\n", 180 | "トピック数:10,反復回数:300回,処理時間:1.64分,exp(-1. * log-likelihood per word)(perplexity):70563.57\n", 181 | "トピック数:10,反復回数:500回,処理時間:2.6分,exp(-1. * log-likelihood per word)(perplexity):70688.6\n" 182 | ] 183 | } 184 | ], 185 | "source": [ 186 | "''' 3.モデル生成と評価\n", 187 | "「perplexity」を評価指標とします。\n", 188 | "パラメータは、「トピック数」と「反復回数」を指定します。\n", 189 | "本来は「反復回数」は推移を確認したほうがいいとは思うのですが...\n", 190 | "'''\n", 191 | " \n", 192 | "# 3-1.パラメータの調整\n", 193 | "from sklearn.decomposition import LatentDirichletAllocation\n", 194 | "import time\n", 195 | "n_comp = [2, 3, 4, 5, 6,10] # トピック数の指定\n", 196 | "max_iter = [50, 100, 300, 500] # 反復回数の指定\n", 197 | " \n", 198 | "for comp in n_comp:\n", 199 | " for max_i in max_iter:\n", 200 | " \n", 201 | " # 実行時間計測開始\n", 202 | " start = time.time()\n", 203 | " \n", 204 | " lda =LatentDirichletAllocation(n_components=comp, max_iter=max_i, learning_method='batch', random_state=0, n_jobs=-1)\n", 205 | " lda_fit = lda.fit(X_train)\n", 206 | " lda_perp = lda.perplexity(X_test)\n", 207 | " \n", 208 | " # 実行時間計測終了\n", 209 | " elapsed_time = time.time() - start \n", 210 | " \n", 211 | " # 結果の表示\n", 212 | " print(\"トピック数:{0},反復回数:{1}回,処理時間:{2}分,exp(-1. * log-likelihood per word)(perplexity):{3}\".format(comp, max_i, round(elapsed_time/60, 2), round(lda_perp, 2)))\n" 213 | ] 214 | }, 215 | { 216 | "cell_type": "markdown", 217 | "metadata": {}, 218 | "source": [ 219 | "トピックの確認と可視化" 220 | ] 221 | }, 222 | { 223 | "cell_type": "code", 224 | "execution_count": 5, 225 | "metadata": {}, 226 | "outputs": [], 227 | "source": [ 228 | "''' 3.モデル生成と評価\n", 229 | "上記の結果から、トピック数を2とします。\n", 230 | "また、反復回数は100回くらいで良さそうですね\n", 231 | "'''\n", 232 | " \n", 233 | "# 3-2.先ほど求めたパラメータに応じたモデルの生成\n", 234 | " \n", 235 | "# データの用意(トレーニング用、検証用と分けずに全セット)\n", 236 | "twenty_train = fetch_20newsgroups(categories=categories, shuffle=True, random_state=42)\n", 237 | "X = tfidf_vec.transform(twenty_train.data) \n", 238 | " \n", 239 | "# クラスの生成\n", 240 | "from sklearn.decomposition import LatentDirichletAllocation\n", 241 | "lda =LatentDirichletAllocation(n_components=2, max_iter=100, learning_method='batch', random_state=0, n_jobs=-1)\n", 242 | " \n", 243 | "# モデルの生成\n", 244 | "lda.fit(X)\n", 245 | "lda_X = lda.transform(X)" 246 | ] 247 | }, 248 | { 249 | "cell_type": "code", 250 | "execution_count": 7, 251 | "metadata": {}, 252 | "outputs": [ 253 | { 254 | "name": "stdout", 255 | "output_type": "stream", 256 | "text": [ 257 | "['From: tedward@cs', 'cornell', 'edu (Edward [Ted] Fischer)\\nSubject: Old Predictions to laugh at', '', '', '\\nSummary: LONG!\\nOrganization: Cornell Univ', ' CS Dept, Ithaca NY 14853\\nLines: 404\\n\\n\\nOops! I came across this file from last year', ' Thought you might\\nenjoy some of these thoughts', ' The predictions were made on the\\ndate indicated', ' They are largely out of order', '\\n\\n------------------------------------------------------------------------------\\n\\nJune 11, 1992\\ntedward@cs', 'cornell', 'edu (ME!)\\n>What have I done? I computed the \"expected winning percentage\" for\\n>each team from their OBP, total bases, and runs allowed', ' I use the\\n>basic RC formula and the pythagorean projection', ' I then compare this\\n>with their actual winning percentage', ' All stats through June 7', '\\n>\\n>Team OBP TB RA W L XWP Diff\\n>baltimore 0', '351 768 199 33 21 0', '647 -36\\n>boston 0', '334 580 176 26 25 0', '548 -38\\n>toronto 0', '319 750 221 34 22 0', '540 68\\n>new york 0', '327 759 237 28 26 0', '523 -5\\n>milwaukee 0', '325 692 226 28 25 0', '498 31\\n>detroit 0', '328 782 285 24 31 0', '448 -11\\n>cleveland 0', '316 688 274 22 34 0']\n", 258 | "\n", 259 | "------------------------------\n", 260 | "['From: dxf12@po', 'CWRU', 'Edu (Douglas Fowler)\\nSubject: (ATAS) N', 'L', ' games 8/2-8/5 & standings of all\\nArticle-I', 'D', ': usenet', '1pqf84$caf\\nOrganization: Case Western Reserve University, Cleveland, Ohio (USA)\\nLines: 237\\nNNTP-Posting-Host: slc12', 'ins', 'cwru', 'edu\\n\\n\\n Philadelphia at Chicago: Teams tied for 1st after Sunday\\n Dick Redding battled Chet Brewer in the first game of a dramatic four\\ngame series', ' One Friday, one Saturday, and a good-old Sunday doubleheader', '\\n\"What could be better,\" declared Ernie Banks', ' Perhaps the fact that the Cubs\\nare challenging?\\n \"It\\'s pitching, it\\'s always been pitching that we\\'ve lacked,\" announced\\nRyne Sandberg', ' \"If we can get by Brewer, then beat Carlton, Alexander, or\\nBunning - preferrably 2 of the last three - we\\'ll know we might be able to\\nwin', '\\n \"Lord, I hope we pull it off', '\"\\n The Phils scored once in the top of the first; Richie Ashburn singled, Pete\\nRose followed with a hit, sending Ashburn around second', ' Kiki Cuyler cut\\nthe ball off in left center, and threw a bullet in to Ernie Banks, who threw\\nto Ron Santo to get Ashburn at third', ' Rose went to second on the play', '\\n Christobel Torrienti lifted a long fly to center, moving Pete Rose to\\nthird', ' Schmidt was walked - the Cubs were absolutely refusing to let him\\nbeat them', ' Both Torrienti and Schmidt will likely draw 130-150 walks this\\nyear', ' Chuck Klein is starting to hit very well, and he lashed a double into a\\ngap in right-center', ' \"Cool Papa\" Bell\\'s speed allowed him to cut the ball off\\nand prevent Schmidt from scoring', ' Nellie Fox was walked, and Bob Boone\\ngrounded out to second, ending the threat', ' \\n \"Teams are starting to realize that you don\\'t have to pitch to Schmidt or\\nTorrienti, and that is lowering their run total', \" It puts a lot of pressure on\\nKlein and Dick Allen (who platoons with Chuck Klein and occasionally spells\\nRose at first), and it's a credit to the Phillies that they've been able to\\nsustain their pace\", ' The picthers have slumped at times', '\" So came the\\nanalysis from Frank Chance', \"\\n The Cubs got that run back when Bell bunted for a hit, Thomas' grounder\\nmoved him to second, and - after Sandberg made out - Billy Williams singled\\nhome a run\"]\n", 261 | "\n", 262 | "------------------------------\n" 263 | ] 264 | } 265 | ], 266 | "source": [ 267 | "''' 4.トピックの確認\n", 268 | "各トピックに実際にどのような単語、文書が割り当てられているのかを確認します。\n", 269 | "'''\n", 270 | "import numpy as np\n", 271 | "\n", 272 | "# 4-2.各トピックごとにどんな文書が割り当てられているか\n", 273 | " \n", 274 | "# トピック0\n", 275 | "topic_0 = np.argsort(lda_X[:, 0])[::-1] # このトピックでもっとも重要度が高い順にソート\n", 276 | " \n", 277 | "for i in range(0,2):\n", 278 | " print(twenty_train.data[topic_0[i]].split('.')[:30])\n", 279 | " print('\\n' + '------------------------------')" 280 | ] 281 | }, 282 | { 283 | "cell_type": "markdown", 284 | "metadata": {}, 285 | "source": [ 286 | "テストデータによる評価" 287 | ] 288 | }, 289 | { 290 | "cell_type": "code", 291 | "execution_count": 8, 292 | "metadata": {}, 293 | "outputs": [ 294 | { 295 | "name": "stdout", 296 | "output_type": "stream", 297 | "text": [ 298 | "[[0.83430136 0.16569864]\n", 299 | " [0.83230705 0.16769295]]\n" 300 | ] 301 | } 302 | ], 303 | "source": [ 304 | "'''5.テストデータを入れて確認\n", 305 | "yahooニュースをgoogle翻訳で英語にしたものを入れてみた\n", 306 | "'''\n", 307 | " \n", 308 | "# 5-1.大谷選手がエンゼルス入団を決めたニュースでテスト\n", 309 | " \n", 310 | "test = [\n", 311 | "'Nippon Ham\\'s Shohei Otani pitcher (23) who was aiming for a major transfer in the posting system decided to contract with Angels. On August 8, agent Mr. Barzero announced. In addition, Angels also announced the following statement.',\n", 312 | "'The U.S. major league, Angels announced that the shoulder number of Shohei Otani pitcher (23) whose entry was decided will be \"17\".', \n", 313 | "]\n", 314 | " \n", 315 | " \n", 316 | "X_test = tfidf_vec.transform(test) \n", 317 | "lda_test = lda.transform(X_test)\n", 318 | "print(lda_test)" 319 | ] 320 | }, 321 | { 322 | "cell_type": "code", 323 | "execution_count": 9, 324 | "metadata": {}, 325 | "outputs": [ 326 | { 327 | "name": "stdout", 328 | "output_type": "stream", 329 | "text": [ 330 | "[[0.36815481 0.63184519]\n", 331 | " [0.12606953 0.87393047]]\n" 332 | ] 333 | } 334 | ], 335 | "source": [ 336 | "'''5.テストデータを入れて確認\n", 337 | "yahooニュースをgoogle翻訳で英語にしたものを入れてみた\n", 338 | "'''\n", 339 | " \n", 340 | "# 5-2.macpro発売、macへの不正ログインのニュース\n", 341 | " \n", 342 | "test=[\n", 343 | "'Apple announced on December 12 (local time) that December 14 will release a new desktop iMac Pro that will be \"the most powerful Mac ever\". Although the selling price in Japan is unpublished, it is 4,999 dollars (about 570,000 yen) in the United States.',\n", 344 | "'Developer Lemi Orhan Ergin discovered a vulnerability in macOS High Sierra 10.13.1. When you click on the lock button from \"User and group\" in the system environment setting and enter \"user name\" and password in order to unlock the preference setting, enter \"root\" for the user name, enter the password Even without it, the lock is released.'\n", 345 | "]\n", 346 | " \n", 347 | " \n", 348 | "X_test = tfidf_vec.transform(test) \n", 349 | "lda_test = lda.transform(X_test)\n", 350 | "print(lda_test)" 351 | ] 352 | }, 353 | { 354 | "cell_type": "code", 355 | "execution_count": null, 356 | "metadata": {}, 357 | "outputs": [], 358 | "source": [] 359 | } 360 | ], 361 | "metadata": { 362 | "kernelspec": { 363 | "display_name": "Python 3", 364 | "language": "python", 365 | "name": "python3" 366 | }, 367 | "language_info": { 368 | "codemirror_mode": { 369 | "name": "ipython", 370 | "version": 3 371 | }, 372 | "file_extension": ".py", 373 | "mimetype": "text/x-python", 374 | "name": "python", 375 | "nbconvert_exporter": "python", 376 | "pygments_lexer": "ipython3", 377 | "version": "3.7.0" 378 | } 379 | }, 380 | "nbformat": 4, 381 | "nbformat_minor": 2 382 | } 383 | -------------------------------------------------------------------------------- /lec2_5/lec5_3.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "ベイズ推定の例題" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "データの準備とモデルの構築、学習" 15 | ] 16 | }, 17 | { 18 | "cell_type": "code", 19 | "execution_count": 8, 20 | "metadata": {}, 21 | "outputs": [ 22 | { 23 | "data": { 24 | "text/plain": [ 25 | "GaussianNB(priors=None)" 26 | ] 27 | }, 28 | "execution_count": 8, 29 | "metadata": {}, 30 | "output_type": "execute_result" 31 | } 32 | ], 33 | "source": [ 34 | "import numpy as np\n", 35 | "from sklearn.naive_bayes import GaussianNB # ガウシアン\n", 36 | "X = np.array([[1,2,3,4,5,6,7,8],\n", 37 | " [1,1,3,4,5,6,6,7],\n", 38 | " [2,1,2,4,5,8,8,8]]) # 特徴ベクトル\n", 39 | "y = np.array([1, 2, 3]) # そのラベル\n", 40 | "\n", 41 | "clf = GaussianNB() # 正規分布を仮定したベイズ分類\n", 42 | "clf.fit(X, y) # 学習をする" 43 | ] 44 | }, 45 | { 46 | "cell_type": "markdown", 47 | "metadata": {}, 48 | "source": [ 49 | "モデルの評価" 50 | ] 51 | }, 52 | { 53 | "cell_type": "code", 54 | "execution_count": 7, 55 | "metadata": {}, 56 | "outputs": [ 57 | { 58 | "data": { 59 | "text/plain": [ 60 | "array([3])" 61 | ] 62 | }, 63 | "execution_count": 7, 64 | "metadata": {}, 65 | "output_type": "execute_result" 66 | } 67 | ], 68 | "source": [ 69 | "t = np.array([[2,2,4,5,6,8,8,8]]) # テストデータ, 2次元にする必要があることに注意!\n", 70 | "\n", 71 | "clf.predict(t) # => [3]" 72 | ] 73 | }, 74 | { 75 | "cell_type": "code", 76 | "execution_count": null, 77 | "metadata": {}, 78 | "outputs": [], 79 | "source": [] 80 | } 81 | ], 82 | "metadata": { 83 | "kernelspec": { 84 | "display_name": "Python 3", 85 | "language": "python", 86 | "name": "python3" 87 | }, 88 | "language_info": { 89 | "codemirror_mode": { 90 | "name": "ipython", 91 | "version": 3 92 | }, 93 | "file_extension": ".py", 94 | "mimetype": "text/x-python", 95 | "name": "python", 96 | "nbconvert_exporter": "python", 97 | "pygments_lexer": "ipython3", 98 | "version": "3.7.0" 99 | } 100 | }, 101 | "nbformat": 4, 102 | "nbformat_minor": 2 103 | } 104 | -------------------------------------------------------------------------------- /lec2_6/lec2_6_3.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "k分割交差検証\n", 8 | "\n", 9 | "Source: http://www.cs.nthu.edu.tw/~shwu/courses/ml/labs/08_CV_Ensembling/08_CV_Ensembling.html" 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": 1, 15 | "metadata": {}, 16 | "outputs": [], 17 | "source": [ 18 | "from IPython.display import Image\n", 19 | "from IPython.display import display\n", 20 | "import pandas as pd\n", 21 | "import numpy as np\n", 22 | "import matplotlib.pyplot as plt\n", 23 | "\n", 24 | "# inline plotting instead of popping out\n", 25 | "%matplotlib inline\n", 26 | "\n", 27 | "# load utility classes/functions that has been taught in previous labs\n", 28 | "# e.g., plot_decision_regions()\n", 29 | "import os, sys\n", 30 | "module_path = os.path.abspath(os.path.join('.'))\n", 31 | "sys.path.append(module_path)\n", 32 | "#from lib import *" 33 | ] 34 | }, 35 | { 36 | "cell_type": "markdown", 37 | "metadata": {}, 38 | "source": [ 39 | "データセットの準備. Irisデータセットを読み込み" 40 | ] 41 | }, 42 | { 43 | "cell_type": "code", 44 | "execution_count": 4, 45 | "metadata": {}, 46 | "outputs": [], 47 | "source": [ 48 | "from sklearn.datasets import load_iris\n", 49 | "from sklearn.model_selection import cross_val_score\n", 50 | "from sklearn.model_selection import train_test_split\n", 51 | "from sklearn.preprocessing import StandardScaler\n", 52 | "import numpy as np\n", 53 | "\n", 54 | "iris = load_iris()\n", 55 | "X, y = iris.data[:,[1,2]], iris.target\n", 56 | "\n", 57 | "# hold out testing set\n", 58 | "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=1)" 59 | ] 60 | }, 61 | { 62 | "cell_type": "markdown", 63 | "metadata": {}, 64 | "source": [ 65 | "学習. パイプライン処理+グリッドサーチ+k分割交差検証" 66 | ] 67 | }, 68 | { 69 | "cell_type": "code", 70 | "execution_count": 7, 71 | "metadata": {}, 72 | "outputs": [ 73 | { 74 | "name": "stdout", 75 | "output_type": "stream", 76 | "text": [ 77 | "[1-NN]\n", 78 | "Validation accuracy: 0.894 [0.91304348 0.95454545 0.85 0.85 0.9 ]\n", 79 | "[15-NN]\n", 80 | "Validation accuracy: 0.914 [0.95652174 0.86363636 0.85 0.9 1. ]\n", 81 | "[50-NN]\n", 82 | "Validation accuracy: 0.801 [0.73913043 0.86363636 0.75 0.75 0.9 ]\n" 83 | ] 84 | } 85 | ], 86 | "source": [ 87 | "from sklearn.pipeline import Pipeline\n", 88 | "from sklearn.neighbors import KNeighborsClassifier\n", 89 | "from sklearn.metrics import accuracy_score\n", 90 | "\n", 91 | "best_k, best_score = -1, -1\n", 92 | "clfs = {}\n", 93 | "\n", 94 | "for k in [1, 15, 50]: # experiment different hyperparameter\n", 95 | " pipe = Pipeline([['sc', StandardScaler()], ['clf', KNeighborsClassifier(n_neighbors=k)]])\n", 96 | " pipe.fit(X_train, y_train)\n", 97 | " # K-Fold CV\n", 98 | " scores = cross_val_score(pipe, X_train, y_train, cv=5)\n", 99 | " print('[%d-NN]\\nValidation accuracy: %.3f %s' % (k, scores.mean(), scores))\n", 100 | " if scores.mean() > best_score:\n", 101 | " best_k, best_score = k, scores.mean()\n", 102 | " clfs[k] = pipe" 103 | ] 104 | }, 105 | { 106 | "cell_type": "markdown", 107 | "metadata": {}, 108 | "source": [ 109 | "学習結果の評価. テスト用データを用いて汎化誤差を評価する." 110 | ] 111 | }, 112 | { 113 | "cell_type": "code", 114 | "execution_count": 8, 115 | "metadata": {}, 116 | "outputs": [ 117 | { 118 | "name": "stdout", 119 | "output_type": "stream", 120 | "text": [ 121 | "Test accuracy: 0.93 (n_neighbors=15 selected by 5-fold CV)\n" 122 | ] 123 | } 124 | ], 125 | "source": [ 126 | "best_clf = clfs[best_k]\n", 127 | "best_clf.fit(X_train, y_train)\n", 128 | "\n", 129 | "# performance reporting\n", 130 | "y_pred = best_clf.predict(X_test)\n", 131 | "print('Test accuracy: %.2f (n_neighbors=%d selected by 5-fold CV)' % \n", 132 | " (accuracy_score(y_test, y_pred), best_k))" 133 | ] 134 | }, 135 | { 136 | "cell_type": "code", 137 | "execution_count": null, 138 | "metadata": {}, 139 | "outputs": [], 140 | "source": [] 141 | } 142 | ], 143 | "metadata": { 144 | "kernelspec": { 145 | "display_name": "Python 3", 146 | "language": "python", 147 | "name": "python3" 148 | }, 149 | "language_info": { 150 | "codemirror_mode": { 151 | "name": "ipython", 152 | "version": 3 153 | }, 154 | "file_extension": ".py", 155 | "mimetype": "text/x-python", 156 | "name": "python", 157 | "nbconvert_exporter": "python", 158 | "pygments_lexer": "ipython3", 159 | "version": "3.7.0" 160 | } 161 | }, 162 | "nbformat": 4, 163 | "nbformat_minor": 2 164 | } 165 | -------------------------------------------------------------------------------- /lec2_6/photo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HirokiNakahara/MachineLearning_Lecture/467f1b2b759775acf59961ab77e143cb01e05c0e/lec2_6/photo.jpg -------------------------------------------------------------------------------- /lec2_7/lec2_7_2.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "lec2_7_2.ipynb", 7 | "provenance": [] 8 | }, 9 | "kernelspec": { 10 | "name": "python3", 11 | "display_name": "Python 3" 12 | } 13 | }, 14 | "cells": [ 15 | { 16 | "cell_type": "markdown", 17 | "metadata": { 18 | "id": "hiQMk0XCkhn4", 19 | "colab_type": "text" 20 | }, 21 | "source": [ 22 | "## 2層スタッキングによる分類" 23 | ] 24 | }, 25 | { 26 | "cell_type": "code", 27 | "metadata": { 28 | "id": "Tn0mGyPmkf5-", 29 | "colab_type": "code", 30 | "colab": {} 31 | }, 32 | "source": [ 33 | "from sklearn import datasets\n", 34 | "\n", 35 | "iris = datasets.load_iris()\n", 36 | "X, y = iris.data[:, 1:3], iris.target" 37 | ], 38 | "execution_count": 0, 39 | "outputs": [] 40 | }, 41 | { 42 | "cell_type": "markdown", 43 | "metadata": { 44 | "id": "Qt0wP_cjlDCm", 45 | "colab_type": "text" 46 | }, 47 | "source": [ 48 | "### MLextend ライブラリを使ってStackingを実装\n", 49 | "MLextendはscikit-learnのAPI準拠なので、pipelineやgridsearchとも組み合わせ可能" 50 | ] 51 | }, 52 | { 53 | "cell_type": "code", 54 | "metadata": { 55 | "id": "KE9CVdOikqbY", 56 | "colab_type": "code", 57 | "colab": { 58 | "base_uri": "https://localhost:8080/", 59 | "height": 173 60 | }, 61 | "outputId": "e4ba6b3b-e371-466b-d6c7-77e259a2bdc0" 62 | }, 63 | "source": [ 64 | "from sklearn import model_selection\n", 65 | "from sklearn.linear_model import LogisticRegression\n", 66 | "from sklearn.neighbors import KNeighborsClassifier\n", 67 | "from sklearn.naive_bayes import GaussianNB \n", 68 | "from sklearn.ensemble import RandomForestClassifier\n", 69 | "from mlxtend.classifier import StackingClassifier\n", 70 | "import numpy as np\n", 71 | "import warnings\n", 72 | "\n", 73 | "warnings.simplefilter('ignore')\n", 74 | "\n", 75 | "clf1 = KNeighborsClassifier(n_neighbors=1)\n", 76 | "clf2 = RandomForestClassifier(random_state=1)\n", 77 | "clf3 = GaussianNB()\n", 78 | "lr = LogisticRegression()\n", 79 | "sclf = StackingClassifier(classifiers=[clf1, clf2, clf3], \n", 80 | " meta_classifier=lr)\n", 81 | "\n", 82 | "print('3-fold cross validation:\\n')\n", 83 | "\n", 84 | "for clf, label in zip([clf1, clf2, clf3, sclf], \n", 85 | " ['KNN', \n", 86 | " 'Random Forest', \n", 87 | " 'Naive Bayes',\n", 88 | " 'StackingClassifier']):\n", 89 | "\n", 90 | " scores = model_selection.cross_val_score(clf, X, y, \n", 91 | " cv=3, scoring='accuracy')\n", 92 | " print(\"Accuracy: %0.2f (+/- %0.2f) [%s]\" \n", 93 | " % (scores.mean(), scores.std(), label))" 94 | ], 95 | "execution_count": 2, 96 | "outputs": [ 97 | { 98 | "output_type": "stream", 99 | "text": [ 100 | "3-fold cross validation:\n", 101 | "\n", 102 | "Accuracy: 0.91 (+/- 0.01) [KNN]\n", 103 | "Accuracy: 0.93 (+/- 0.05) [Random Forest]\n", 104 | "Accuracy: 0.92 (+/- 0.03) [Naive Bayes]\n", 105 | "Accuracy: 0.95 (+/- 0.03) [StackingClassifier]\n" 106 | ], 107 | "name": "stdout" 108 | }, 109 | { 110 | "output_type": "stream", 111 | "text": [ 112 | "/usr/local/lib/python3.6/dist-packages/sklearn/externals/six.py:31: DeprecationWarning: The module is deprecated in version 0.21 and will be removed in version 0.23 since we've dropped support for Python 2.7. Please rely on the official version of six (https://pypi.org/project/six/).\n", 113 | " \"(https://pypi.org/project/six/).\", DeprecationWarning)\n" 114 | ], 115 | "name": "stderr" 116 | } 117 | ] 118 | }, 119 | { 120 | "cell_type": "markdown", 121 | "metadata": { 122 | "id": "B_sDgx_Jlcc2", 123 | "colab_type": "text" 124 | }, 125 | "source": [ 126 | "### MLextendの決定境界機能を使って描画" 127 | ] 128 | }, 129 | { 130 | "cell_type": "code", 131 | "metadata": { 132 | "id": "20yt33oikzy-", 133 | "colab_type": "code", 134 | "colab": { 135 | "base_uri": "https://localhost:8080/", 136 | "height": 499 137 | }, 138 | "outputId": "c4e0dc6e-34cc-4e94-e9e0-9619fc488edd" 139 | }, 140 | "source": [ 141 | "import matplotlib.pyplot as plt\n", 142 | "from mlxtend.plotting import plot_decision_regions\n", 143 | "import matplotlib.gridspec as gridspec\n", 144 | "import itertools\n", 145 | "\n", 146 | "gs = gridspec.GridSpec(2, 2)\n", 147 | "\n", 148 | "fig = plt.figure(figsize=(10,8))\n", 149 | "\n", 150 | "for clf, lab, grd in zip([clf1, clf2, clf3, sclf], \n", 151 | " ['KNN', \n", 152 | " 'Random Forest', \n", 153 | " 'Naive Bayes',\n", 154 | " 'StackingClassifier'],\n", 155 | " itertools.product([0, 1], repeat=2)):\n", 156 | "\n", 157 | " clf.fit(X, y)\n", 158 | " ax = plt.subplot(gs[grd[0], grd[1]])\n", 159 | " fig = plot_decision_regions(X=X, y=y, clf=clf)\n", 160 | " plt.title(lab)" 161 | ], 162 | "execution_count": 3, 163 | "outputs": [ 164 | { 165 | "output_type": "display_data", 166 | "data": { 167 | "image/png": "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\n/v4K3NuymOPRlFKPKaUKlFI1SqnPlVJntHnsty2rRiul3lFK3XHUczcrpS7z/jxCKbXSe7a4Uyk1\nx5/itNYuPCtUj2pz3ElKqU+VUlVKqSKl1JNKqQjvY08ppf52VB1vKaV+4v05Qyn1hlKqTCm1Xyl1\n11HH/cz7XkuUUn12AU8hQsAwAK31y1prl9a6QWu9AmgG/gV8y9ubXAWglLpIKfWl9/tZoJT6bduD\ntemVqvI+fsPRL6iUsimlPlBKPe7t+Wm9BKaUmubt/fmpt4e9SCn1/TbPTfRewqpRSm1USv2xpbdL\nKTUU+BFwtdb6fa21Q2td7+3BechHHQlKqSXeHKr0/jywzeM3KKX2KaVqvTl1rXf7EKXUh96et3Kl\n1KttnqO9j/8O+DVwpffz+8HRPXPHymPvZ/K0UmqZUqoOONv//6TiaNJICn+f4empubeTxzcCE/Cc\nGc0HXlNKWX3s9zJwdcsvSqlReM5mlirP5byV3uen4Flx+p/efY7J2/i5FljXZrML+AmQBHwLOBe4\n3fvYPOBqpZTB+/wk4Dxgvnfb28BmPGet5wJ3K6XO9z73MeAxrXUsMBhYcLz6hBBdtgtwKaXmKaVm\nKqUSALTWXwG3Ap96LyG1nMDVAdcD8Xh6Z25TSl0KoJTKBt7B0yuVjCezNrV9MaVUIrAKWKO1vkv7\nXng0DYjDkw8/AJ5qqQt4yltDGvA9758W5wKHtNYb/HzvBuA5PBk5CGgAnvTWGQ08DszUWtuAqW3e\nyx+AFUACMND7ftvRWv8G+BPwqvfz+89Rn4M/eXwN8CBgA3r9smdfJo2kvuHXwJ1KqeSjH9Bav6i1\nPqK1dmqt/wZYgOE+jrEQmOANK/A0bN7UWjuAWUC+1vo573G+BN4AvnOMmh73nkHWAnfg6YZvqelz\nrfU677HygWeAs7yPbQCq8YQWeAJgtda6BJgIJGutf6+1bvJev3/Wuw94zmCHKKWStNZ2rXXbhpkQ\nogdprWuA0wGN53tY5u31Te1k/9Va661aa7fWegueE7OzvA9fA7zn7ZVq9mZW20ZSBvAh8JrW+lfH\nKKsZ+L33GMsAOzBceS45XQ78xttDtAPPCVmLRKAogPd+RGv9hvdYtXgaJGe12cUNjFFKRWqti7TW\n29vUlw1kaK0btdZdacD4k8eLtdZrvJ91YxdeQ3hJI6kP0FpvwzM24IGjH1NK3auU+srbvVuF5ywr\n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\n", 168 | "text/plain": [ 169 | "
" 170 | ] 171 | }, 172 | "metadata": { 173 | "tags": [] 174 | } 175 | } 176 | ] 177 | } 178 | ] 179 | } -------------------------------------------------------------------------------- /lec_2_8/convolution_matmul.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "convolution_matmul.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | }, 14 | "language_info": { 15 | "name": "python" 16 | } 17 | }, 18 | "cells": [ 19 | { 20 | "cell_type": "markdown", 21 | "metadata": { 22 | "id": "d7QpmYMyKLUs" 23 | }, 24 | "source": [ 25 | "#im2colを使った畳み込み演算の行列計算処理\n" 26 | ] 27 | }, 28 | { 29 | "cell_type": "code", 30 | "metadata": { 31 | "id": "PvubZvulKKSY" 32 | }, 33 | "source": [ 34 | "import numpy as np\n", 35 | "\n", 36 | "def im2col(input_data, filter_h, filter_w, stride_h=1, stride_w=1, pad_h=0, pad_w=0):\n", 37 | "\n", 38 | " N, C, H, W = input_data.shape\n", 39 | " out_h = (H + 2*pad_h - filter_h)//stride_h + 1\n", 40 | " out_w = (W + 2*pad_w - filter_w)//stride_w + 1\n", 41 | "\n", 42 | " img = np.pad(input_data, [(0,0), (0,0), (pad_h, pad_h), (pad_w, pad_w)], 'constant')\n", 43 | " col = np.zeros((N, C, filter_h, filter_w, out_h, out_w))\n", 44 | "\n", 45 | " for y in range(filter_h):\n", 46 | " y_max = y + stride_h*out_h\n", 47 | " for x in range(filter_w):\n", 48 | " x_max = x + stride_w*out_w\n", 49 | " col[:, :, y, x, :, :] = img[:, :, y:y_max:stride_h, x:x_max:stride_w]\n", 50 | "\n", 51 | " col = col.transpose(0, 4, 5, 1, 2, 3).reshape(N*out_h*out_w, -1)\n", 52 | " return col, out_h, out_w " 53 | ], 54 | "execution_count": 1, 55 | "outputs": [] 56 | }, 57 | { 58 | "cell_type": "code", 59 | "metadata": { 60 | "id": "_HktXhtPKZv1" 61 | }, 62 | "source": [ 63 | "# 畳み込み演算する画像 ( img.shape = (1, 1, 4, 4) )\n", 64 | "img =np.array([[[\n", 65 | " [0, 1, 2, 3],\n", 66 | " [4, 5, 6, 7],\n", 67 | " [8, 9, 0, 1],\n", 68 | " [2, 3, 4, 5],\n", 69 | "]]])\n", 70 | "\n", 71 | "# フィルター画像 ( kernel.shape = (2, 2) )\n", 72 | "kernel = np.array([\n", 73 | " [1, 0],\n", 74 | " [0, 1]\n", 75 | "])" 76 | ], 77 | "execution_count": 2, 78 | "outputs": [] 79 | }, 80 | { 81 | "cell_type": "code", 82 | "metadata": { 83 | "id": "77CIeSQHKea6" 84 | }, 85 | "source": [ 86 | "# im2col関数を使って、画像をスライシング\n", 87 | "img_col, out_h, out_w= im2col(img, 2, 2, 1, 1, 0, 0)" 88 | ], 89 | "execution_count": 3, 90 | "outputs": [] 91 | }, 92 | { 93 | "cell_type": "markdown", 94 | "metadata": { 95 | "id": "xJl5DwnDKqwK" 96 | }, 97 | "source": [ 98 | " 画像は、im2col関数で展開しましたが、フィルターの方は、kernel_col = kernel.reshape(k_n, -1).T だけでOK" 99 | ] 100 | }, 101 | { 102 | "cell_type": "code", 103 | "metadata": { 104 | "id": "esCfK3hsKhC_" 105 | }, 106 | "source": [ 107 | "# フィルター個数=1\n", 108 | "k_n = 1 \n", 109 | "\n", 110 | "# フィルターを転置\n", 111 | "kernel_col = kernel.reshape(k_n, -1).T \n" 112 | ], 113 | "execution_count": 4, 114 | "outputs": [] 115 | }, 116 | { 117 | "cell_type": "code", 118 | "metadata": { 119 | "id": "PQizdR1YKiXH" 120 | }, 121 | "source": [ 122 | "# 画像のスライシング結果と転置したフィルターの内積を取る\n", 123 | "conv = np.dot(img_col, kernel_col)" 124 | ], 125 | "execution_count": 5, 126 | "outputs": [] 127 | }, 128 | { 129 | "cell_type": "code", 130 | "metadata": { 131 | "colab": { 132 | "base_uri": "https://localhost:8080/" 133 | }, 134 | "id": "6tRnLx5mKkpq", 135 | "outputId": "c39ae42c-dd12-4b29-b4ad-0879766b4925" 136 | }, 137 | "source": [ 138 | "# 内積結果の行列を整形\n", 139 | "conv = conv.reshape(img.shape[0], out_h, out_w, -1).transpose(0, 3, 2, 1)\n", 140 | "print(conv)" 141 | ], 142 | "execution_count": 6, 143 | "outputs": [ 144 | { 145 | "output_type": "stream", 146 | "name": "stdout", 147 | "text": [ 148 | "[[[[ 5. 13. 11.]\n", 149 | " [ 7. 5. 13.]\n", 150 | " [ 9. 7. 5.]]]]\n" 151 | ] 152 | } 153 | ] 154 | }, 155 | { 156 | "cell_type": "code", 157 | "metadata": { 158 | "id": "3YUqBhsFKuAa" 159 | }, 160 | "source": [ 161 | "" 162 | ], 163 | "execution_count": null, 164 | "outputs": [] 165 | } 166 | ] 167 | } -------------------------------------------------------------------------------- /report/README.txt: -------------------------------------------------------------------------------- 1 | レポート課題(2018年度) 2 | 3 | ・内容 4 | 2つの課題に関して、機械学習の手法を適用し、スコアを報告。 5 | 開発に用いたjupyter notebookも添付で(googleフォーム)に提出。 6 | 提出は1度限りなので、注意して投稿すること。 7 | 8 | ・課題 9 | このレポジトリに置いている2つのノートブックを使用。 10 | 11 | ・提出先 12 | https://goo.gl/forms/xv8xDsbr3fHYbbYR2 13 | 14 | ・提出〆切 15 | 11月30日(JST 23:59) 16 | 17 | ・評価 18 | 提出点(2つの課題クリア)+上位5位の成績に加点 19 | 20 | ・コンタクト 21 | nakahara at ict.e.titech.ac.jp 22 | -------------------------------------------------------------------------------- /report/report1.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "レポート課題1:手書き文字認識" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "データセットのロード" 15 | ] 16 | }, 17 | { 18 | "cell_type": "code", 19 | "execution_count": 2, 20 | "metadata": {}, 21 | "outputs": [], 22 | "source": [ 23 | "from sklearn import datasets\n", 24 | "images = datasets.load_digits()\n", 25 | "\n", 26 | "# 学習データ\n", 27 | "data = images.data\n", 28 | "\n", 29 | "# 教師データ(ラベル)\n", 30 | "target = images.target" 31 | ] 32 | }, 33 | { 34 | "cell_type": "markdown", 35 | "metadata": {}, 36 | "source": [ 37 | "データセットの準備" 38 | ] 39 | }, 40 | { 41 | "cell_type": "code", 42 | "execution_count": 20, 43 | "metadata": {}, 44 | "outputs": [], 45 | "source": [ 46 | "from sklearn.linear_model import LogisticRegression\n", 47 | "from sklearn.cross_validation import train_test_split\n", 48 | "\n", 49 | "logreg = LogisticRegression()\n", 50 | "\n", 51 | "X_train, X_test, Y_train, Y_test = train_test_split(data, target, test_size=0.2,random_state=3)" 52 | ] 53 | }, 54 | { 55 | "cell_type": "markdown", 56 | "metadata": {}, 57 | "source": [ 58 | "分類器の学習(ここでよい方法を探す)" 59 | ] 60 | }, 61 | { 62 | "cell_type": "code", 63 | "execution_count": 26, 64 | "metadata": {}, 65 | "outputs": [], 66 | "source": [ 67 | "predicted = logreg.fit(X_train, Y_train)" 68 | ] 69 | }, 70 | { 71 | "cell_type": "markdown", 72 | "metadata": {}, 73 | "source": [ 74 | "認識精度のチェック(検証)" 75 | ] 76 | }, 77 | { 78 | "cell_type": "code", 79 | "execution_count": 27, 80 | "metadata": {}, 81 | "outputs": [ 82 | { 83 | "name": "stdout", 84 | "output_type": "stream", 85 | "text": [ 86 | "[[47 0 0 0 0 0 0 0 0 0]\n", 87 | " [ 0 34 0 0 2 0 0 0 1 0]\n", 88 | " [ 0 0 31 0 0 0 0 0 0 0]\n", 89 | " [ 0 0 0 39 0 0 0 0 0 0]\n", 90 | " [ 0 0 0 0 39 0 0 1 0 0]\n", 91 | " [ 0 0 0 0 0 34 0 0 0 1]\n", 92 | " [ 0 0 0 0 1 0 24 0 0 0]\n", 93 | " [ 0 0 0 0 1 0 0 41 1 0]\n", 94 | " [ 0 1 0 1 1 1 1 0 27 1]\n", 95 | " [ 0 0 0 0 0 3 0 0 0 27]]\n", 96 | "0.9527777777777777\n" 97 | ] 98 | } 99 | ], 100 | "source": [ 101 | "from sklearn import metrics\n", 102 | "\n", 103 | "# テストデータを予測\n", 104 | "Y_pred = logreg.predict(X_test)\n", 105 | "\n", 106 | "# 各クラスごとの認識率を確認\n", 107 | "from sklearn import metrics\n", 108 | "\n", 109 | "print(metrics.confusion_matrix(Y_pred, Y_test))\n", 110 | "\n", 111 | "# 精度を計算 (この数値を報告)\n", 112 | "print(metrics.accuracy_score(Y_test,Y_pred))" 113 | ] 114 | }, 115 | { 116 | "cell_type": "code", 117 | "execution_count": null, 118 | "metadata": {}, 119 | "outputs": [], 120 | "source": [] 121 | } 122 | ], 123 | "metadata": { 124 | "kernelspec": { 125 | "display_name": "Python 3", 126 | "language": "python", 127 | "name": "python3" 128 | }, 129 | "language_info": { 130 | "codemirror_mode": { 131 | "name": "ipython", 132 | "version": 3 133 | }, 134 | "file_extension": ".py", 135 | "mimetype": "text/x-python", 136 | "name": "python", 137 | "nbconvert_exporter": "python", 138 | "pygments_lexer": "ipython3", 139 | "version": "3.7.0" 140 | } 141 | }, 142 | "nbformat": 4, 143 | "nbformat_minor": 2 144 | } 145 | -------------------------------------------------------------------------------- /report/report1_macos.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "レポート課題1:手書き文字認識" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "データセットのロード" 15 | ] 16 | }, 17 | { 18 | "cell_type": "code", 19 | "execution_count": 1, 20 | "metadata": {}, 21 | "outputs": [], 22 | "source": [ 23 | "from sklearn import datasets\n", 24 | "images = datasets.load_digits()\n", 25 | "\n", 26 | "# 学習データ\n", 27 | "data = images.data\n", 28 | "\n", 29 | "# 教師データ(ラベル)\n", 30 | "target = images.target" 31 | ] 32 | }, 33 | { 34 | "cell_type": "markdown", 35 | "metadata": {}, 36 | "source": [ 37 | "データセットの準備" 38 | ] 39 | }, 40 | { 41 | "cell_type": "code", 42 | "execution_count": 8, 43 | "metadata": {}, 44 | "outputs": [], 45 | "source": [ 46 | "# Added version check for recent scikit-learn 0.18 checks\n", 47 | "from distutils.version import LooseVersion as Version\n", 48 | "from sklearn import __version__ as sklearn_version\n", 49 | "\n", 50 | "#データを学習用とテスト用に分ける\n", 51 | "if Version(sklearn_version) < '0.18':\n", 52 | " from sklearn.cross_validation import train_test_split\n", 53 | "else:\n", 54 | " from sklearn.model_selection import train_test_split" 55 | ] 56 | }, 57 | { 58 | "cell_type": "code", 59 | "execution_count": 9, 60 | "metadata": {}, 61 | "outputs": [], 62 | "source": [ 63 | "from sklearn.linear_model import LogisticRegression\n", 64 | "#from sklearn.cross_validation import train_test_split\n", 65 | "\n", 66 | "logreg = LogisticRegression()\n", 67 | "\n", 68 | "X_train, X_test, Y_train, Y_test = train_test_split(data, target, test_size=0.2,random_state=3)" 69 | ] 70 | }, 71 | { 72 | "cell_type": "markdown", 73 | "metadata": {}, 74 | "source": [ 75 | "分類器の学習(ここでよい方法を探す)" 76 | ] 77 | }, 78 | { 79 | "cell_type": "code", 80 | "execution_count": 10, 81 | "metadata": {}, 82 | "outputs": [ 83 | { 84 | "name": "stderr", 85 | "output_type": "stream", 86 | "text": [ 87 | "/usr/local/lib/python3.7/site-packages/sklearn/linear_model/logistic.py:432: FutureWarning: Default solver will be changed to 'lbfgs' in 0.22. Specify a solver to silence this warning.\n", 88 | " FutureWarning)\n", 89 | "/usr/local/lib/python3.7/site-packages/sklearn/linear_model/logistic.py:459: FutureWarning: Default multi_class will be changed to 'auto' in 0.22. Specify the multi_class option to silence this warning.\n", 90 | " \"this warning.\", FutureWarning)\n" 91 | ] 92 | } 93 | ], 94 | "source": [ 95 | "predicted = logreg.fit(X_train, Y_train)" 96 | ] 97 | }, 98 | { 99 | "cell_type": "markdown", 100 | "metadata": {}, 101 | "source": [ 102 | "認識精度のチェック(検証)" 103 | ] 104 | }, 105 | { 106 | "cell_type": "code", 107 | "execution_count": 11, 108 | "metadata": {}, 109 | "outputs": [ 110 | { 111 | "name": "stdout", 112 | "output_type": "stream", 113 | "text": [ 114 | "[[47 0 0 0 0 0 0 0 0 0]\n", 115 | " [ 0 34 0 0 2 0 0 0 1 0]\n", 116 | " [ 0 0 31 0 0 0 0 0 0 0]\n", 117 | " [ 0 0 0 39 0 0 0 0 0 0]\n", 118 | " [ 0 0 0 0 39 0 0 1 0 0]\n", 119 | " [ 0 0 0 0 0 34 0 0 0 1]\n", 120 | " [ 0 0 0 0 1 0 24 0 0 0]\n", 121 | " [ 0 0 0 0 1 0 0 41 1 0]\n", 122 | " [ 0 1 0 1 1 1 1 0 27 1]\n", 123 | " [ 0 0 0 0 0 3 0 0 0 27]]\n", 124 | "0.9527777777777777\n" 125 | ] 126 | } 127 | ], 128 | "source": [ 129 | "from sklearn import metrics\n", 130 | "\n", 131 | "# テストデータを予測\n", 132 | "Y_pred = logreg.predict(X_test)\n", 133 | "\n", 134 | "# 各クラスごとの認識率を確認\n", 135 | "from sklearn import metrics\n", 136 | "\n", 137 | "print(metrics.confusion_matrix(Y_pred, Y_test))\n", 138 | "\n", 139 | "# 精度を計算 (この数値を報告)\n", 140 | "print(metrics.accuracy_score(Y_test,Y_pred))" 141 | ] 142 | }, 143 | { 144 | "cell_type": "code", 145 | "execution_count": null, 146 | "metadata": {}, 147 | "outputs": [], 148 | "source": [] 149 | } 150 | ], 151 | "metadata": { 152 | "kernelspec": { 153 | "display_name": "Python 3", 154 | "language": "python", 155 | "name": "python3" 156 | }, 157 | "language_info": { 158 | "codemirror_mode": { 159 | "name": "ipython", 160 | "version": 3 161 | }, 162 | "file_extension": ".py", 163 | "mimetype": "text/x-python", 164 | "name": "python", 165 | "nbconvert_exporter": "python", 166 | "pygments_lexer": "ipython3", 167 | "version": "3.7.0" 168 | } 169 | }, 170 | "nbformat": 4, 171 | "nbformat_minor": 2 172 | } 173 | -------------------------------------------------------------------------------- /report2019/README.txt: -------------------------------------------------------------------------------- 1 | レポート課題(2019年度) 2 | 3 | ・内容 4 | MNIST手書き文字分類問題に対して機械学習の手法(どんな手法を用いても良い、講義で扱ったもの以外でも可)を適用し、スコアと用いた手法を報告。 5 | 開発に用いたjupyter notebookも添付で(googleフォーム)に提出。 6 | 提出は1度限りなので、注意して投稿すること。 7 | 8 | ・課題 9 | このレポジトリに置いているノートブックを使用。 10 | 11 | ・提出先 12 | https://docs.google.com/forms/d/1l9WpR_f0ZC4mroiZsBjkVwym-tgMvu0lvY8-ZTW_q0o/edit 13 | (提出は一度限りです。注意してください) 14 | 15 | ・提出〆切 16 | 12月2日(JST 23:59) 17 | 18 | ・評価 19 | 提出点(課題クリア)+上位10位の成績に加点 20 | 21 | ・コンタクト 22 | nakahara at ict.e.titech.ac.jp 23 | -------------------------------------------------------------------------------- /report2020/README.txt: -------------------------------------------------------------------------------- 1 | レポート課題(2020年度) 2 | 3 | ・内容 4 | MNIST手書き文字分類問題に対して機械学習の手法(どんな手法を用いても良い、講義で扱ったもの以外でも可)を適用し、スコアと用いた手法を報告。 5 | 開発に用いたjupyter notebookも添付で(googleフォーム)に提出。 6 | 提出は1度限りなので、注意して投稿すること。 7 | 8 | ・課題 9 | このレポジトリに置いているノートブックを使用。 10 | 11 | ・提出先 12 | https://docs.google.com/forms/d/e/1FAIpQLSdPxrXXxPZVFdFCZNxNwOjptVb4s870CqrFgm0-YAZLGqvZjg/viewform?usp=sf_link 13 | (提出は一度限りです。注意してください) 14 | 15 | ・提出〆切 16 | 11月26日(JST 23:59) 17 | 18 | ・評価 19 | 提出点(課題クリア) 20 | ボーナス点(独自で調査していたり、高いスコアを出していたりする場合) 21 | 22 | ・コンタクト 23 | nakahara at ict.e.titech.ac.jp 24 | -------------------------------------------------------------------------------- /report2021/README.txt: -------------------------------------------------------------------------------- 1 | レポート課題(2021年度) 2 | 3 | ・内容 4 | 1 演習 5 | 機械学習一般に関する問題を回答してgoogleフォームに提出。 6 | 最低限知識として覚えて欲しいことなので、調べながら回答して構いません。 7 | 8 | https://drive.google.com/file/d/16syJxp32ttg13la3rI3q3d0FWLjpmd59/view?usp=sharing 9 | 10 | 2 機械学習モデルのプログラミング 11 | 下記のJupyterNotebookを使って、MNIST手書き文字分類問題をプログラミングし、 12 | 機械学習の手法(どんな手法を用いても良い、講義で扱ったもの以外でも可)を適用し、スコアと主に使った方法、 13 | 開発に用いたjupyter notebookも添付で(googleフォーム)に提出。 14 | 15 | https://drive.google.com/file/d/1R65mutZnIMdMhYp2d2XE_vNSnu_wW4iZ/view?usp=sharing 16 | 17 | 18 | ・提出先 19 | 提出は1度限りなので、注意して投稿すること。 20 | 21 | https://forms.gle/BZFyZSzijackyQ817 22 | 23 | ・提出〆切 24 | 11月29日(月)(JST 23:59) 25 | 26 | ・評価 27 | 提出点(課題クリア) 28 | ボーナス点(独自で調査していたり、高いスコアを出していたりする場合) 29 | 30 | ・コンタクト 31 | nakahara at ict.e.titech.ac.jp 32 | --------------------------------------------------------------------------------