├── LICENSE ├── README.md ├── lecture1 ├── exercise.ipynb └── tensor.ipynb ├── lecture2 ├── exercise.ipynb └── simple_dl.ipynb ├── lecture3 ├── autograd.ipynb ├── dataloader.ipynb └── exercise.ipynb ├── lecture4 ├── cnn.ipynb └── exercise.ipynb ├── lecture5 ├── exercise.ipynb ├── image_generation.ipynb └── simple_rnn.ipynb ├── lecture6 ├── classifier │ ├── Procfile │ ├── classifier.py │ ├── requirements.txt │ ├── runtime.txt │ ├── static │ │ └── images │ │ │ └── truck.jpg │ └── templates │ │ ├── index.html │ │ ├── layout.html │ │ └── result.html └── train_cnn.ipynb └── python_basic ├── 01_python_basic_1.ipynb ├── 02_python_basic_2.ipynb ├── 03_numpy.ipynb └── 04_matplotlib.ipynb /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 yuky_az 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 【PyTorch+Colab】PyTorchで実装するディープラーニング -CNN、RNN、人工知能Webアプリの構築- 2 | 本講座のゴールは、PyTorchを使ってディープラーニングが実装できるようになることです。 3 | PyTorchを使ってCNN(畳み込みニューラルネットワーク)、RNN(再帰型ニューラルネットワーク)などの技術を順を追って幅広く習得し、人工知能を搭載したWebアプリの構築までを行います。 4 | 5 | Section1. イントロダクション 6 | → PyTorchの概要、ディープラーニングの概要、そしてPyTorchの基礎であるTensorについて解説します。 7 | 8 | Section2. PyTorchで実装する簡単なディープラーニング 9 | → 可能な限りシンプルなコードで、ディープラーニングを実装します。 10 | 11 | Section3. PyTorchの様々な機能 12 | → 自動微分、DataLoaderなどのPyTorch特有の機能について解説します。 13 | 14 | Section4. 畳み込みニューラルネットワーク(CNN) 15 | → CNNの原理を学んだ上で、CNNによる画像分類をデータ拡張、ドロップアウトとともに実装します。 16 | 17 | Section5. 再帰型ニューラルネットワーク(RNN) 18 | → RNNの原理を学んだ上で、シンプルなRNNの構築、およびRNNによる画像生成を行います。 19 | 20 | Section6. AIアプリのデプロイ 21 | → 学習済みモデルを活用した人工知能Webアプリを構築します。 22 | 23 | Udemyコース: [【PyTorch+Colab】PyTorchで実装するディープラーニング](https://www.udemy.com/course/ai-pytorch/?referralCode=5106F3FDA2C91D0C1CB5) 24 | 25 | ### 自由研究室 AIRS-Lab(コミュニティ) 26 | 「AI」をテーマに交流し、創造するWeb上のコミュニティです。 27 | https://www.airs-lab.jp/ 28 | 29 | ### News! AIRS-Lab(メルマガ) 30 | AIの話題、講義動画、Udemyコース割引などのAIRS-Lab最新コンテンツをメールで配信します。 31 | https://www.airs-lab.jp/newsletter 32 | 33 | ### AI教室 AIRS-Lab(YouTubeチャンネル) 34 | 毎週月曜日21時に、YouTubeでライブ講義を開催しています。 35 | https://www.youtube.com/channel/UCT_HwlT8bgYrpKrEvw0jH7Q 36 | 37 | ### Udemyコース 38 | オンライン動画学習プラットフォームUdemyで、AI関連のコースを複数展開しています。 39 | https://www.airs-lab.jp/lectures 40 | -------------------------------------------------------------------------------- /lecture1/exercise.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "exercise.ipynb", 7 | "provenance": [], 8 | "authorship_tag": "ABX9TyNCQ+l/BAGr/ETeRri0AyU6", 9 | "include_colab_link": true 10 | }, 11 | "kernelspec": { 12 | "name": "python3", 13 | "display_name": "Python 3" 14 | } 15 | }, 16 | "cells": [ 17 | { 18 | "cell_type": "markdown", 19 | "metadata": { 20 | "id": "view-in-github", 21 | "colab_type": "text" 22 | }, 23 | "source": [ 24 | "\"Open" 25 | ] 26 | }, 27 | { 28 | "cell_type": "markdown", 29 | "metadata": { 30 | "id": "Gyk0pYx-GOTG", 31 | "colab_type": "text" 32 | }, 33 | "source": [ 34 | "# 演習\n", 35 | "第1講の演習です。" 36 | ] 37 | }, 38 | { 39 | "cell_type": "markdown", 40 | "metadata": { 41 | "id": "l1iDDDhCGdRk", 42 | "colab_type": "text" 43 | }, 44 | "source": [ 45 | "## Tensor同士の演算\n", 46 | "以下のTensor`a`と`b`の間で、以下の演算子を使って演算を行い、結果を表示しましょう。 \n", 47 | "和: + \n", 48 | "差: - \n", 49 | "積: * \n", 50 | "商(小数): / \n", 51 | "商(整数): // \n", 52 | "余り: % \n", 53 | "`a`は行列で`b`はベクトルなので、ブロードキャストが必要になります。" 54 | ] 55 | }, 56 | { 57 | "cell_type": "code", 58 | "metadata": { 59 | "id": "vQjm5IIwFzfQ", 60 | "colab_type": "code", 61 | "colab": {} 62 | }, 63 | "source": [ 64 | "import torch\n", 65 | "\n", 66 | "a = torch.tensor([[1, 2, 3],\n", 67 | " [4, 5, 6.]])\n", 68 | "b = torch.tensor([1, 2, 3.]) \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 | ], 87 | "execution_count": 0, 88 | "outputs": [] 89 | }, 90 | { 91 | "cell_type": "markdown", 92 | "metadata": { 93 | "id": "BEW_lUs3PJCQ", 94 | "colab_type": "text" 95 | }, 96 | "source": [ 97 | "## 解答例\n", 98 | "以下は、どうしても手がかりがないときのみ参考にしましょう。" 99 | ] 100 | }, 101 | { 102 | "cell_type": "code", 103 | "metadata": { 104 | "id": "imyJ_CUEPNgW", 105 | "colab_type": "code", 106 | "colab": {} 107 | }, 108 | "source": [ 109 | "import torch\n", 110 | "\n", 111 | "a = torch.tensor([[1, 2, 3],\n", 112 | " [4, 5, 6.]])\n", 113 | "b = torch.tensor([1, 2, 3.]) \n", 114 | "\n", 115 | "# 和\n", 116 | "print(a + b)\n", 117 | "\n", 118 | "# 差\n", 119 | "print(a - b)\n", 120 | "\n", 121 | "# 積\n", 122 | "print(a * b)\n", 123 | "\n", 124 | "# 商(小数)\n", 125 | "print(a / b)\n", 126 | "\n", 127 | "# 商(整数)\n", 128 | "print(a // b)\n", 129 | "\n", 130 | "# 余り\n", 131 | "print(a % b)" 132 | ], 133 | "execution_count": 0, 134 | "outputs": [] 135 | } 136 | ] 137 | } -------------------------------------------------------------------------------- /lecture1/tensor.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "tensor.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [], 9 | "authorship_tag": "ABX9TyOTxejBTppXvhM1e/CJHcYB", 10 | "include_colab_link": true 11 | }, 12 | "kernelspec": { 13 | "name": "python3", 14 | "display_name": "Python 3" 15 | } 16 | }, 17 | "cells": [ 18 | { 19 | "cell_type": "markdown", 20 | "metadata": { 21 | "id": "view-in-github", 22 | "colab_type": "text" 23 | }, 24 | "source": [ 25 | "\"Open" 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "metadata": { 31 | "id": "qBeK8bWc4a_9", 32 | "colab_type": "text" 33 | }, 34 | "source": [ 35 | "# Tensor\n", 36 | "TensorはPyTorchにおいて最も基本となるデータ構造です。 \n", 37 | "今回は、Tensorを生成したり、Tensor同士の計算をしたりするコードを練習します。" 38 | ] 39 | }, 40 | { 41 | "cell_type": "markdown", 42 | "metadata": { 43 | "id": "ztIkOM_N5Bu7", 44 | "colab_type": "text" 45 | }, 46 | "source": [ 47 | "## パッケージの確認\n", 48 | "インストール済みのパッケージを全て表示します。 \n", 49 | "PyTorch(torch)がインストールされていることを確認しましょう。" 50 | ] 51 | }, 52 | { 53 | "cell_type": "code", 54 | "metadata": { 55 | "id": "SLrzxL39qGie", 56 | "colab_type": "code", 57 | "colab": {} 58 | }, 59 | "source": [ 60 | "!pip list" 61 | ], 62 | "execution_count": 0, 63 | "outputs": [] 64 | }, 65 | { 66 | "cell_type": "markdown", 67 | "metadata": { 68 | "id": "EMC135bx6E3u", 69 | "colab_type": "text" 70 | }, 71 | "source": [ 72 | "## Tensorの生成\n", 73 | "torchのtensor関数によりTensorを生成します。 \n", 74 | "以下のセルではPythonのリストからTensorを生成します。 \n", 75 | "また、type( )により型を確認します。 " 76 | ] 77 | }, 78 | { 79 | "cell_type": "code", 80 | "metadata": { 81 | "id": "xCg7mgXPqBc8", 82 | "colab_type": "code", 83 | "colab": {} 84 | }, 85 | "source": [ 86 | "import torch\n", 87 | "a = torch.tensor([1,2,3])\n", 88 | "print(a, type(a))" 89 | ], 90 | "execution_count": 0, 91 | "outputs": [] 92 | }, 93 | { 94 | "cell_type": "markdown", 95 | "metadata": { 96 | "id": "6LcfIq4nWfG2", 97 | "colab_type": "text" 98 | }, 99 | "source": [ 100 | "他にも、様々な方法でTensorを生成することができます。" 101 | ] 102 | }, 103 | { 104 | "cell_type": "code", 105 | "metadata": { 106 | "id": "3X2TN2rYtCTO", 107 | "colab_type": "code", 108 | "colab": {} 109 | }, 110 | "source": [ 111 | "# 2重のリストから生成\n", 112 | "b = torch.tensor([[1, 2],\n", 113 | " [3, 4]])\n", 114 | "print(b)\n", 115 | "\n", 116 | "# dypeを指定し、倍精度のTensorにする\n", 117 | "c = torch.tensor([[1, 2],\n", 118 | " [3, 4]], dtype=torch.float64)\n", 119 | "print(c)\n", 120 | "\n", 121 | "# 0から9までの数値で初期化\n", 122 | "d = torch.arange(0, 10)\n", 123 | "print(d)\n", 124 | "\n", 125 | "# すべての値が0の、2×3のTensor\n", 126 | "e = torch.zeros(2, 3)\n", 127 | "print(e)\n", 128 | "\n", 129 | "# すべての値が乱数の、2×3のTensor\n", 130 | "f = torch.rand(2, 3)\n", 131 | "print(f)\n", 132 | "\n", 133 | "# Tensorの形状はsizeメソッドで取得\n", 134 | "print(f.size())" 135 | ], 136 | "execution_count": 0, 137 | "outputs": [] 138 | }, 139 | { 140 | "cell_type": "markdown", 141 | "metadata": { 142 | "id": "b-TrDK5qewJp", 143 | "colab_type": "text" 144 | }, 145 | "source": [ 146 | "## TensorとNumPyの配列の変換\n", 147 | "numpy()メソッドでTensorをNumPyの配列に変換することができます。 \n", 148 | "また、from_numpy( )関数でNumPyの配列をTensorに変換することができます。" 149 | ] 150 | }, 151 | { 152 | "cell_type": "code", 153 | "metadata": { 154 | "id": "VdQc9-L5gBFZ", 155 | "colab_type": "code", 156 | "colab": {} 157 | }, 158 | "source": [ 159 | "# Tensor → NumPy\n", 160 | "a = torch.tensor([[1, 2],\n", 161 | " [3, 4.]])\n", 162 | "b = a.numpy()\n", 163 | "print(b)\n", 164 | "\n", 165 | "# NumPy → Tensor\n", 166 | "c = torch.from_numpy(b)\n", 167 | "print(c)" 168 | ], 169 | "execution_count": 0, 170 | "outputs": [] 171 | }, 172 | { 173 | "cell_type": "markdown", 174 | "metadata": { 175 | "id": "CgpWSmhXnas_", 176 | "colab_type": "text" 177 | }, 178 | "source": [ 179 | "## 範囲を指定してアクセス\n", 180 | "様々な方法で、Tensorの要素に範囲を指定してアクセスすることができます。" 181 | ] 182 | }, 183 | { 184 | "cell_type": "code", 185 | "metadata": { 186 | "id": "MgWk6RXMoX_l", 187 | "colab_type": "code", 188 | "colab": {} 189 | }, 190 | "source": [ 191 | "a = torch.tensor([[1, 2, 3],\n", 192 | " [4, 5, 6]])\n", 193 | "\n", 194 | "# 2つのインデックスを指定\n", 195 | "print(a[0, 1])\n", 196 | "\n", 197 | "# 範囲を指定\n", 198 | "print(a[1:2, :2])\n", 199 | "\n", 200 | "# リストで複数のインデックスを指定\n", 201 | "print(a[:, [0, 2]])\n", 202 | "\n", 203 | "# 3より大きい要素のみを指定\n", 204 | "print(a[a>3])\n", 205 | "\n", 206 | "# 要素の変更\n", 207 | "a[0, 2] = 11\n", 208 | "print(a)\n", 209 | "\n", 210 | "# 要素の一括変更\n", 211 | "a[:, 1] = 22\n", 212 | "print(a)\n", 213 | "\n", 214 | "# 10より大きい要素のみ変更\n", 215 | "a[a>10] = 33\n", 216 | "print(a)" 217 | ], 218 | "execution_count": 0, 219 | "outputs": [] 220 | }, 221 | { 222 | "cell_type": "markdown", 223 | "metadata": { 224 | "id": "2HQMM_Fh02of", 225 | "colab_type": "text" 226 | }, 227 | "source": [ 228 | "## Tensorの演算\n", 229 | "Tensorによりベクトルや行列を表現することができます。 \n", 230 | "これらの演算は、一定のルールに基づき行われます。 " 231 | ] 232 | }, 233 | { 234 | "cell_type": "code", 235 | "metadata": { 236 | "id": "AQ5IsU0Fz-DJ", 237 | "colab_type": "code", 238 | "colab": {} 239 | }, 240 | "source": [ 241 | "# ベクトル\n", 242 | "a = torch.tensor([1, 2, 3]) \n", 243 | "b = torch.tensor([4, 5, 6])\n", 244 | "\n", 245 | "# 行列\n", 246 | "c = torch.tensor([[6, 5, 4],\n", 247 | " [3, 2, 1]])\n", 248 | "\n", 249 | "# ベクトルとスカラーの演算\n", 250 | "print(a + 3)\n", 251 | "\n", 252 | "# ベクトル同士の演算\n", 253 | "print(a + b) \n", 254 | "\n", 255 | "# 行列とスカラーの演算\n", 256 | "print(c + 2)\n", 257 | "\n", 258 | "# 行列とベクトルの演算(ブロードキャスト)\n", 259 | "print(c + a)\n", 260 | "\n", 261 | "# 行列同士の演算\n", 262 | "print(c + c)" 263 | ], 264 | "execution_count": 0, 265 | "outputs": [] 266 | }, 267 | { 268 | "cell_type": "markdown", 269 | "metadata": { 270 | "id": "r0S-nN_c8MKr", 271 | "colab_type": "text" 272 | }, 273 | "source": [ 274 | "## 様々な値の計算\n", 275 | "平均値、合計値、最大値、最小値など様々な値を計算する関数とメソッドが用意されています。\n" 276 | ] 277 | }, 278 | { 279 | "cell_type": "code", 280 | "metadata": { 281 | "id": "X_LIWIwI59rI", 282 | "colab_type": "code", 283 | "colab": {} 284 | }, 285 | "source": [ 286 | "a = torch.tensor([[1, 2, 3],\n", 287 | " [4, 5, 6.]])\n", 288 | "\n", 289 | "# 平均値を求める関数\n", 290 | "m = torch.mean(a)\n", 291 | "print(m.item()) # item()で値を取り出す\n", 292 | "\n", 293 | "# 平均値を求めるメソッド\n", 294 | "m = a.mean()\n", 295 | "print(m.item())\n", 296 | "\n", 297 | "# 列ごとの平均値\n", 298 | "print(a.mean(0))\n", 299 | "\n", 300 | "# 合計値\n", 301 | "print(torch.sum(a).item())\n", 302 | "\n", 303 | "# 最大値\n", 304 | "print(torch.max(a).item())\n", 305 | "\n", 306 | "# 最小値\n", 307 | "print(torch.min(a).item())" 308 | ], 309 | "execution_count": 0, 310 | "outputs": [] 311 | } 312 | ] 313 | } -------------------------------------------------------------------------------- /lecture2/exercise.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "exercise.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [], 9 | "authorship_tag": "ABX9TyPDbtT3RYuZL9QWBBJD1HqN", 10 | "include_colab_link": true 11 | }, 12 | "kernelspec": { 13 | "name": "python3", 14 | "display_name": "Python 3" 15 | } 16 | }, 17 | "cells": [ 18 | { 19 | "cell_type": "markdown", 20 | "metadata": { 21 | "id": "view-in-github", 22 | "colab_type": "text" 23 | }, 24 | "source": [ 25 | "\"Open" 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "metadata": { 31 | "id": "Niaz8_W6OX34", 32 | "colab_type": "text" 33 | }, 34 | "source": [ 35 | "# 演習\n", 36 | "第2講の演習です。 \n", 37 | "PyTorchを使ってモデルを構築し、最適化アルゴリズムを設定しましょう。\n" 38 | ] 39 | }, 40 | { 41 | "cell_type": "markdown", 42 | "metadata": { 43 | "id": "w40h1X0FXmrh", 44 | "colab_type": "text" 45 | }, 46 | "source": [ 47 | "## データを訓練用とテスト用に分割" 48 | ] 49 | }, 50 | { 51 | "cell_type": "code", 52 | "metadata": { 53 | "id": "GLGwXks542pJ", 54 | "colab_type": "code", 55 | "colab": {} 56 | }, 57 | "source": [ 58 | "import torch\n", 59 | "from sklearn import datasets\n", 60 | "from sklearn.model_selection import train_test_split\n", 61 | "\n", 62 | "digits_data = datasets.load_digits()\n", 63 | "\n", 64 | "digit_images = digits_data.data\n", 65 | "labels = digits_data.target\n", 66 | "x_train, x_test, t_train, t_test = train_test_split(digit_images, labels) # 25%がテスト用\n", 67 | "\n", 68 | "# Tensorに変換\n", 69 | "x_train = torch.tensor(x_train, dtype=torch.float32)\n", 70 | "t_train = torch.tensor(t_train, dtype=torch.int64) \n", 71 | "x_test = torch.tensor(x_test, dtype=torch.float32)\n", 72 | "t_test = torch.tensor(t_test, dtype=torch.int64) " 73 | ], 74 | "execution_count": 0, 75 | "outputs": [] 76 | }, 77 | { 78 | "cell_type": "markdown", 79 | "metadata": { 80 | "id": "FalXNYaJPkoE", 81 | "colab_type": "text" 82 | }, 83 | "source": [ 84 | "## モデルの構築\n", 85 | "`nn`モジュールの`Sequential`クラスを使い、`print(net)`で以下のように表示されるモデルを構築しましょう。\n", 86 | "```\n", 87 | "Sequential(\n", 88 | " (0): Linear(in_features=64, out_features=128, bias=True)\n", 89 | " (1): ReLU()\n", 90 | " (2): Linear(in_features=128, out_features=64, bias=True)\n", 91 | " (3): ReLU()\n", 92 | " (4): Linear(in_features=64, out_features=10, bias=True)\n", 93 | ")\n", 94 | "```" 95 | ] 96 | }, 97 | { 98 | "cell_type": "code", 99 | "metadata": { 100 | "id": "SuqqZmsh_jNK", 101 | "colab_type": "code", 102 | "colab": {} 103 | }, 104 | "source": [ 105 | "from torch import nn\n", 106 | "\n", 107 | "net = nn.Sequential(\n", 108 | " # ------- ここからコードを記述 -------\n", 109 | "\n", 110 | "\n", 111 | "\n", 112 | "\n", 113 | "\n", 114 | " # ------- ここまで -------\n", 115 | ")\n", 116 | "print(net)" 117 | ], 118 | "execution_count": 0, 119 | "outputs": [] 120 | }, 121 | { 122 | "cell_type": "markdown", 123 | "metadata": { 124 | "id": "qsW5zCKhQE9p", 125 | "colab_type": "text" 126 | }, 127 | "source": [ 128 | "## 学習\n", 129 | "モデルを訓練します。 \n", 130 | "最適化アルゴリズムの設定をしましょう。 \n", 131 | "最適化アルゴリズムは、以下のページから好きなものを選択してください。 \n", 132 | "https://pytorch.org/docs/stable/optim.html\n", 133 | "\n", 134 | "\n" 135 | ] 136 | }, 137 | { 138 | "cell_type": "code", 139 | "metadata": { 140 | "id": "u6zwN3nArbGC", 141 | "colab_type": "code", 142 | "colab": {} 143 | }, 144 | "source": [ 145 | "from torch import optim\n", 146 | "\n", 147 | "# 交差エントロピー誤差関数\n", 148 | "loss_fnc = nn.CrossEntropyLoss()\n", 149 | "\n", 150 | "# 最適化アルゴリズム\n", 151 | "optimizer = # ここにコードを記述\n", 152 | "\n", 153 | "# 損失のログ\n", 154 | "record_loss_train = []\n", 155 | "record_loss_test = []\n", 156 | "\n", 157 | "# 1000エポック学習\n", 158 | "for i in range(1000):\n", 159 | "\n", 160 | " # 勾配を0に\n", 161 | " optimizer.zero_grad()\n", 162 | " \n", 163 | " # 順伝播\n", 164 | " y_train = net(x_train)\n", 165 | " y_test = net(x_test)\n", 166 | " \n", 167 | " # 誤差を求める\n", 168 | " loss_train = loss_fnc(y_train, t_train)\n", 169 | " loss_test = loss_fnc(y_test, t_test)\n", 170 | " record_loss_train.append(loss_train.item())\n", 171 | " record_loss_test.append(loss_test.item())\n", 172 | "\n", 173 | " # 逆伝播(勾配を求める)\n", 174 | " loss_train.backward()\n", 175 | " \n", 176 | " # パラメータの更新\n", 177 | " optimizer.step()\n", 178 | "\n", 179 | " if i%100 == 0:\n", 180 | " print(\"Epoch:\", i, \"Loss_Train:\", loss_train.item(), \"Loss_Test:\", loss_test.item())" 181 | ], 182 | "execution_count": 0, 183 | "outputs": [] 184 | }, 185 | { 186 | "cell_type": "markdown", 187 | "metadata": { 188 | "id": "rJwwrWTw43rx", 189 | "colab_type": "text" 190 | }, 191 | "source": [ 192 | "## 誤差の推移" 193 | ] 194 | }, 195 | { 196 | "cell_type": "code", 197 | "metadata": { 198 | "id": "OaJx4swE45XI", 199 | "colab_type": "code", 200 | "colab": {} 201 | }, 202 | "source": [ 203 | "import matplotlib.pyplot as plt\n", 204 | "\n", 205 | "plt.plot(range(len(record_loss_train)), record_loss_train, label=\"Train\")\n", 206 | "plt.plot(range(len(record_loss_test)), record_loss_test, label=\"Test\")\n", 207 | "plt.legend()\n", 208 | "\n", 209 | "plt.xlabel(\"Epochs\")\n", 210 | "plt.ylabel(\"Error\")\n", 211 | "plt.show()" 212 | ], 213 | "execution_count": 0, 214 | "outputs": [] 215 | }, 216 | { 217 | "cell_type": "markdown", 218 | "metadata": { 219 | "id": "iMrpac0m4Nct", 220 | "colab_type": "text" 221 | }, 222 | "source": [ 223 | "## 正解率" 224 | ] 225 | }, 226 | { 227 | "cell_type": "code", 228 | "metadata": { 229 | "id": "IRkGCYMM_N35", 230 | "colab_type": "code", 231 | "colab": {} 232 | }, 233 | "source": [ 234 | "y_test = net(x_test)\n", 235 | "count = (y_test.argmax(1) == t_test).sum().item()\n", 236 | "print(\"正解率:\", str(count/len(y_test)*100) + \"%\")" 237 | ], 238 | "execution_count": 0, 239 | "outputs": [] 240 | }, 241 | { 242 | "cell_type": "markdown", 243 | "metadata": { 244 | "id": "maAJN2wa0l1D", 245 | "colab_type": "text" 246 | }, 247 | "source": [ 248 | "# 解答例\n", 249 | "以下は、どうしても手がかりがないときのみ参考にしましょう。" 250 | ] 251 | }, 252 | { 253 | "cell_type": "code", 254 | "metadata": { 255 | "id": "rQagvzyDmDA5", 256 | "colab_type": "code", 257 | "colab": {} 258 | }, 259 | "source": [ 260 | "from torch import nn\n", 261 | "\n", 262 | "net = nn.Sequential(\n", 263 | " # ------- ここからコードを記述 -------\n", 264 | " nn.Linear(64, 128), # 全結合層\n", 265 | " nn.ReLU(), # ReLU\n", 266 | " nn.Linear(128, 64),\n", 267 | " nn.ReLU(),\n", 268 | " nn.Linear(64, 10)\n", 269 | " # ------- ここまで -------\n", 270 | ")\n", 271 | "print(net)" 272 | ], 273 | "execution_count": 0, 274 | "outputs": [] 275 | }, 276 | { 277 | "cell_type": "code", 278 | "metadata": { 279 | "id": "ARNSvRFTmDI1", 280 | "colab_type": "code", 281 | "colab": {} 282 | }, 283 | "source": [ 284 | "from torch import optim\n", 285 | "\n", 286 | "# 交差エントロピー誤差関数\n", 287 | "loss_fnc = nn.CrossEntropyLoss()\n", 288 | "\n", 289 | "# 最適化アルゴリズム\n", 290 | "optimizer = optim.Adam(net.parameters()) # ここにコードを記述\n", 291 | "\n", 292 | "# 損失のログ\n", 293 | "record_loss_train = []\n", 294 | "record_loss_test = []\n", 295 | "\n", 296 | "# 1000エポック学習\n", 297 | "for i in range(1000):\n", 298 | "\n", 299 | " # 勾配を0に\n", 300 | " optimizer.zero_grad()\n", 301 | " \n", 302 | " # 順伝播\n", 303 | " y_train = net(x_train)\n", 304 | " y_test = net(x_test)\n", 305 | " \n", 306 | " # 誤差を求める\n", 307 | " loss_train = loss_fnc(y_train, t_train)\n", 308 | " loss_test = loss_fnc(y_test, t_test)\n", 309 | " record_loss_train.append(loss_train.item())\n", 310 | " record_loss_test.append(loss_test.item())\n", 311 | "\n", 312 | " # 逆伝播(勾配を求める)\n", 313 | " loss_train.backward()\n", 314 | " \n", 315 | " # パラメータの更新\n", 316 | " optimizer.step()\n", 317 | "\n", 318 | " if i%100 == 0:\n", 319 | " print(\"Epoch:\", i, \"Loss_Train:\", loss_train.item(), \"Loss_Test:\", loss_test.item())" 320 | ], 321 | "execution_count": 0, 322 | "outputs": [] 323 | } 324 | ] 325 | } -------------------------------------------------------------------------------- /lecture2/simple_dl.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "simple_dl.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [], 9 | "authorship_tag": "ABX9TyOg38ElnatmFsST2pi+nOp9", 10 | "include_colab_link": true 11 | }, 12 | "kernelspec": { 13 | "name": "python3", 14 | "display_name": "Python 3" 15 | } 16 | }, 17 | "cells": [ 18 | { 19 | "cell_type": "markdown", 20 | "metadata": { 21 | "id": "view-in-github", 22 | "colab_type": "text" 23 | }, 24 | "source": [ 25 | "\"Open" 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "metadata": { 31 | "id": "Niaz8_W6OX34", 32 | "colab_type": "text" 33 | }, 34 | "source": [ 35 | "# シンプルなディープラーニング\n", 36 | "PyTorchを使って簡単なディープラーニングを実装します。 \n", 37 | "今回は、ディープラーニングにより手書き文字の認識を行います。\n" 38 | ] 39 | }, 40 | { 41 | "cell_type": "markdown", 42 | "metadata": { 43 | "colab_type": "text", 44 | "id": "x9Gzbn25XSlF" 45 | }, 46 | "source": [ 47 | "### 手書き文字画像の確認\n", 48 | "scikit-learnから、手書き数字の画像データを読み込んで表示します。 " 49 | ] 50 | }, 51 | { 52 | "cell_type": "code", 53 | "metadata": { 54 | "colab_type": "code", 55 | "id": "81Il03RNAmbS", 56 | "colab": {} 57 | }, 58 | "source": [ 59 | "import numpy as np\n", 60 | "import matplotlib.pyplot as plt\n", 61 | "from sklearn import datasets\n", 62 | "\n", 63 | "digits_data = datasets.load_digits()\n", 64 | "\n", 65 | "n_img = 10 # 表示する画像の数\n", 66 | "plt.figure(figsize=(10, 4))\n", 67 | "for i in range(n_img):\n", 68 | " ax = plt.subplot(2, 5, i+1)\n", 69 | " plt.imshow(digits_data.data[i].reshape(8, 8), cmap=\"Greys_r\")\n", 70 | " ax.get_xaxis().set_visible(False) # 軸を非表示に\n", 71 | " ax.get_yaxis().set_visible(False)\n", 72 | "plt.show()\n", 73 | "\n", 74 | "print(\"データの形状:\", digits_data.data.shape)\n", 75 | "print(\"ラベル:\", digits_data.target[:n_img])" 76 | ], 77 | "execution_count": 0, 78 | "outputs": [] 79 | }, 80 | { 81 | "cell_type": "markdown", 82 | "metadata": { 83 | "colab_type": "text", 84 | "id": "sFWHMOf2D4b1" 85 | }, 86 | "source": [ 87 | "8×8とサイズは小さいですが、0から9までの手書き数字の画像が表示されました。このような手書き数字の画像が、このデータセットには1797枚含まれています。 \n", 88 | "また、各画像は描かれた数字を表すラベルとペアになっています。 \n", 89 | "\n" 90 | ] 91 | }, 92 | { 93 | "cell_type": "markdown", 94 | "metadata": { 95 | "id": "w40h1X0FXmrh", 96 | "colab_type": "text" 97 | }, 98 | "source": [ 99 | "## データを訓練用とテスト用に分割\n", 100 | "scikit-learnのtrain_test_splitを使って、データを訓練用とテストに分割します。" 101 | ] 102 | }, 103 | { 104 | "cell_type": "code", 105 | "metadata": { 106 | "id": "GLGwXks542pJ", 107 | "colab_type": "code", 108 | "colab": {} 109 | }, 110 | "source": [ 111 | "import torch\n", 112 | "from sklearn.model_selection import train_test_split\n", 113 | "\n", 114 | "digit_images = digits_data.data\n", 115 | "labels = digits_data.target\n", 116 | "x_train, x_test, t_train, t_test = train_test_split(digit_images, labels) # 25%がテスト用\n", 117 | "\n", 118 | "# Tensorに変換\n", 119 | "x_train = torch.tensor(x_train, dtype=torch.float32)\n", 120 | "t_train = torch.tensor(t_train, dtype=torch.int64) \n", 121 | "x_test = torch.tensor(x_test, dtype=torch.float32)\n", 122 | "t_test = torch.tensor(t_test, dtype=torch.int64) " 123 | ], 124 | "execution_count": 0, 125 | "outputs": [] 126 | }, 127 | { 128 | "cell_type": "markdown", 129 | "metadata": { 130 | "id": "FalXNYaJPkoE", 131 | "colab_type": "text" 132 | }, 133 | "source": [ 134 | "## モデルの構築\n", 135 | "`nn`モジュールの`Sequential`クラスによりモデルを構築します。" 136 | ] 137 | }, 138 | { 139 | "cell_type": "code", 140 | "metadata": { 141 | "id": "SuqqZmsh_jNK", 142 | "colab_type": "code", 143 | "colab": {} 144 | }, 145 | "source": [ 146 | "from torch import nn\n", 147 | "\n", 148 | "net = nn.Sequential(\n", 149 | " nn.Linear(64, 32), # 全結合層\n", 150 | " nn.ReLU(), # ReLU\n", 151 | " nn.Linear(32, 16),\n", 152 | " nn.ReLU(),\n", 153 | " nn.Linear(16, 10)\n", 154 | ")\n", 155 | "print(net)" 156 | ], 157 | "execution_count": 0, 158 | "outputs": [] 159 | }, 160 | { 161 | "cell_type": "markdown", 162 | "metadata": { 163 | "id": "qsW5zCKhQE9p", 164 | "colab_type": "text" 165 | }, 166 | "source": [ 167 | "## 学習\n", 168 | "モデルを訓練します。 \n", 169 | "今回は、損失関数に交差エントロピー誤差を、最適化アルゴリズムにSGD(確率的勾配降下法)を設定します。 \n", 170 | "順伝播は訓練データ、テストデータ両者で行い誤差を計算します。 \n", 171 | "逆伝播を行うのは、訓練データのみです。 \n" 172 | ] 173 | }, 174 | { 175 | "cell_type": "code", 176 | "metadata": { 177 | "id": "u6zwN3nArbGC", 178 | "colab_type": "code", 179 | "colab": {} 180 | }, 181 | "source": [ 182 | "from torch import optim\n", 183 | "\n", 184 | "# 交差エントロピー誤差関数\n", 185 | "loss_fnc = nn.CrossEntropyLoss()\n", 186 | "\n", 187 | "# SGD\n", 188 | "optimizer = optim.SGD(net.parameters(), lr=0.01) # 学習率は0.01\n", 189 | "\n", 190 | "# 損失のログ\n", 191 | "record_loss_train = []\n", 192 | "record_loss_test = []\n", 193 | "\n", 194 | "# 1000エポック学習\n", 195 | "for i in range(1000):\n", 196 | "\n", 197 | " # 勾配を0に\n", 198 | " optimizer.zero_grad()\n", 199 | " \n", 200 | " # 順伝播\n", 201 | " y_train = net(x_train)\n", 202 | " y_test = net(x_test)\n", 203 | " \n", 204 | " # 誤差を求める\n", 205 | " loss_train = loss_fnc(y_train, t_train)\n", 206 | " loss_test = loss_fnc(y_test, t_test)\n", 207 | " record_loss_train.append(loss_train.item())\n", 208 | " record_loss_test.append(loss_test.item())\n", 209 | "\n", 210 | " # 逆伝播(勾配を求める)\n", 211 | " loss_train.backward()\n", 212 | " \n", 213 | " # パラメータの更新\n", 214 | " optimizer.step()\n", 215 | "\n", 216 | " if i%100 == 0:\n", 217 | " print(\"Epoch:\", i, \"Loss_Train:\", loss_train.item(), \"Loss_Test:\", loss_test.item())" 218 | ], 219 | "execution_count": 0, 220 | "outputs": [] 221 | }, 222 | { 223 | "cell_type": "markdown", 224 | "metadata": { 225 | "id": "rJwwrWTw43rx", 226 | "colab_type": "text" 227 | }, 228 | "source": [ 229 | "## 誤差の推移\n", 230 | "訓練データ、テストデータで誤差の推移をグラフ表示します。 " 231 | ] 232 | }, 233 | { 234 | "cell_type": "code", 235 | "metadata": { 236 | "id": "OaJx4swE45XI", 237 | "colab_type": "code", 238 | "colab": {} 239 | }, 240 | "source": [ 241 | "plt.plot(range(len(record_loss_train)), record_loss_train, label=\"Train\")\n", 242 | "plt.plot(range(len(record_loss_test)), record_loss_test, label=\"Test\")\n", 243 | "plt.legend()\n", 244 | "\n", 245 | "plt.xlabel(\"Epochs\")\n", 246 | "plt.ylabel(\"Error\")\n", 247 | "plt.show()" 248 | ], 249 | "execution_count": 0, 250 | "outputs": [] 251 | }, 252 | { 253 | "cell_type": "markdown", 254 | "metadata": { 255 | "id": "iMrpac0m4Nct", 256 | "colab_type": "text" 257 | }, 258 | "source": [ 259 | "## 正解率\n", 260 | "モデルの性能を把握するため、テストデータ使い正解率を測定します。 " 261 | ] 262 | }, 263 | { 264 | "cell_type": "code", 265 | "metadata": { 266 | "id": "IRkGCYMM_N35", 267 | "colab_type": "code", 268 | "colab": {} 269 | }, 270 | "source": [ 271 | "y_test = net(x_test)\n", 272 | "count = (y_test.argmax(1) == t_test).sum().item()\n", 273 | "print(\"正解率:\", str(count/len(y_test)*100) + \"%\")" 274 | ], 275 | "execution_count": 0, 276 | "outputs": [] 277 | }, 278 | { 279 | "cell_type": "markdown", 280 | "metadata": { 281 | "id": "LrRAJzwD4zpN", 282 | "colab_type": "text" 283 | }, 284 | "source": [ 285 | "## 訓練済みのモデルを使った予測\n", 286 | "訓練済みのモデルを使ってみましょう。 \n", 287 | "画像を入力し、モデルが機能していることを確かめます。" 288 | ] 289 | }, 290 | { 291 | "cell_type": "code", 292 | "metadata": { 293 | "id": "Pdy9nPckTDik", 294 | "colab_type": "code", 295 | "colab": {} 296 | }, 297 | "source": [ 298 | "img_id = 0\n", 299 | "x_pred = digit_images[img_id]\n", 300 | "image = x_pred.reshape(8, 8)\n", 301 | "plt.imshow(image, cmap=\"Greys_r\")\n", 302 | "plt.show()\n", 303 | "\n", 304 | "x_pred = torch.tensor(x_pred, dtype=torch.float32)\n", 305 | "y_pred = net(x_pred)\n", 306 | "print(\"正解:\", labels[img_id], \"予測結果:\", y_pred.argmax().item())" 307 | ], 308 | "execution_count": 0, 309 | "outputs": [] 310 | }, 311 | { 312 | "cell_type": "markdown", 313 | "metadata": { 314 | "id": "maAJN2wa0l1D", 315 | "colab_type": "text" 316 | }, 317 | "source": [ 318 | "このような訓練済みのモデルは、別途保存しWebアプリなどで活用することができます。" 319 | ] 320 | } 321 | ] 322 | } -------------------------------------------------------------------------------- /lecture3/autograd.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "autograd.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [], 9 | "authorship_tag": "ABX9TyP9pXOTi5I2pvzOCY+CjsYB", 10 | "include_colab_link": true 11 | }, 12 | "kernelspec": { 13 | "name": "python3", 14 | "display_name": "Python 3" 15 | } 16 | }, 17 | "cells": [ 18 | { 19 | "cell_type": "markdown", 20 | "metadata": { 21 | "id": "view-in-github", 22 | "colab_type": "text" 23 | }, 24 | "source": [ 25 | "\"Open" 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "metadata": { 31 | "id": "9FgvuyIa6oBQ", 32 | "colab_type": "text" 33 | }, 34 | "source": [ 35 | "# 自動微分\n", 36 | "自動微分により、ある値の微小変化が結果に与える影響を自動で計算することができます。 \n", 37 | "参考: https://pytorch.org/tutorials/beginner/blitz/autograd_tutorial.html\n" 38 | ] 39 | }, 40 | { 41 | "cell_type": "markdown", 42 | "metadata": { 43 | "id": "fpu9CjtSPaP8", 44 | "colab_type": "text" 45 | }, 46 | "source": [ 47 | "## 自動微分の開始\n", 48 | "Tensorは、requires_grad属性をTrueに設定することで計算過程が記録されるようになります。" 49 | ] 50 | }, 51 | { 52 | "cell_type": "code", 53 | "metadata": { 54 | "id": "3loxKiFXYylA", 55 | "colab_type": "code", 56 | "colab": {} 57 | }, 58 | "source": [ 59 | "import torch\n", 60 | "\n", 61 | "x = torch.ones(2, 3, requires_grad=True)\n", 62 | "print(x)" 63 | ], 64 | "execution_count": 0, 65 | "outputs": [] 66 | }, 67 | { 68 | "cell_type": "markdown", 69 | "metadata": { 70 | "id": "z0aISTAIsbKK", 71 | "colab_type": "text" 72 | }, 73 | "source": [ 74 | "## Tensorの演算と自動微分\n", 75 | "requires_grad属性がTrueであれば、演算によりgrad_fnが記録されます。 \n", 76 | "grad_fnは、このTensorを作った演算です。 \n", 77 | "以下では、`x`に足し算を行って得られた`y`のgrad_fnを表示します。" 78 | ] 79 | }, 80 | { 81 | "cell_type": "code", 82 | "metadata": { 83 | "id": "xQpV46k3tx3R", 84 | "colab_type": "code", 85 | "colab": {} 86 | }, 87 | "source": [ 88 | "y = x + 2\n", 89 | "print(y)\n", 90 | "print(y.grad_fn)" 91 | ], 92 | "execution_count": 0, 93 | "outputs": [] 94 | }, 95 | { 96 | "cell_type": "markdown", 97 | "metadata": { 98 | "id": "9amPZxOid4w5", 99 | "colab_type": "text" 100 | }, 101 | "source": [ 102 | "掛け算、mean関数などの演算も、grad_fnに記録されます。" 103 | ] 104 | }, 105 | { 106 | "cell_type": "code", 107 | "metadata": { 108 | "id": "EKs5LFQMt4zd", 109 | "colab_type": "code", 110 | "colab": {} 111 | }, 112 | "source": [ 113 | "z = y * 3\n", 114 | "print(z)\n", 115 | "\n", 116 | "out = z.mean()\n", 117 | "print(out)" 118 | ], 119 | "execution_count": 0, 120 | "outputs": [] 121 | }, 122 | { 123 | "cell_type": "markdown", 124 | "metadata": { 125 | "id": "83QbuM5xf2Of", 126 | "colab_type": "text" 127 | }, 128 | "source": [ 129 | "## 勾配の計算\n", 130 | "backwardメソッドは、逆伝播により勾配を計算します。 \n", 131 | "その際に、 記録されている演算と経路が使用されます。 \n", 132 | "以下の例では、aに2をかけてbとしていますが、backwardによりaの変化に対するbの変化の割合、すなわち勾配が計算されます。 \n" 133 | ] 134 | }, 135 | { 136 | "cell_type": "code", 137 | "metadata": { 138 | "id": "7_HJnklKt7nt", 139 | "colab_type": "code", 140 | "colab": {} 141 | }, 142 | "source": [ 143 | "a = torch.tensor([1.0], requires_grad=True)\n", 144 | "b = a * 2 # bの変化量はaの2倍\n", 145 | "b.backward() # 逆伝播\n", 146 | "print(a.grad) # aの勾配(aの変化に対するbの変化の割合)  " 147 | ], 148 | "execution_count": 0, 149 | "outputs": [] 150 | }, 151 | { 152 | "cell_type": "markdown", 153 | "metadata": { 154 | "id": "wBcAhTCnqA1Z", 155 | "colab_type": "text" 156 | }, 157 | "source": [ 158 | "より複雑な経路を持つ演算でも、backwardにより勾配を計算することができます。" 159 | ] 160 | }, 161 | { 162 | "cell_type": "code", 163 | "metadata": { 164 | "id": "57kKqrGQt-SP", 165 | "colab_type": "code", 166 | "colab": {} 167 | }, 168 | "source": [ 169 | "def calc(a):\n", 170 | " b = a*2 + 1\n", 171 | " c = b*b \n", 172 | " d = c/(c + 2)\n", 173 | " e = d.mean()\n", 174 | " return e\n", 175 | "\n", 176 | "x = [1.0, 2.0, 3.0]\n", 177 | "x = torch.tensor(x, requires_grad=True)\n", 178 | "y = calc(x)\n", 179 | "y.backward()\n", 180 | "print(x.grad.tolist()) # xの勾配(xの各値の変化に対するyの変化の割合)  " 181 | ], 182 | "execution_count": 0, 183 | "outputs": [] 184 | }, 185 | { 186 | "cell_type": "markdown", 187 | "metadata": { 188 | "id": "hRSyV5hSLZbO", 189 | "colab_type": "text" 190 | }, 191 | "source": [ 192 | "cの各値付近における勾配が計算できました。 \n", 193 | "勾配が正しく計算できていることを確認しましょう。 \n", 194 | "`x`を微小変化させて、`x`の微小変化に対する`y`の微小変化の割合を求めます。\n" 195 | ] 196 | }, 197 | { 198 | "cell_type": "code", 199 | "metadata": { 200 | "id": "mtWE7zoduAnJ", 201 | "colab_type": "code", 202 | "colab": {} 203 | }, 204 | "source": [ 205 | "delta = 0.001 #xの微小変化\n", 206 | "\n", 207 | "x = [1.0, 2.0, 3.0]\n", 208 | "x = torch.tensor(x, requires_grad=True)\n", 209 | "y = calc(x).item()\n", 210 | "\n", 211 | "x_1 = [1.0+delta, 2.0, 3.0]\n", 212 | "x_1 = torch.tensor(x_1, requires_grad=True)\n", 213 | "y_1 = calc(x_1).item()\n", 214 | "\n", 215 | "x_2 = [1.0, 2.0+delta, 3.0]\n", 216 | "x_2 = torch.tensor(x_2, requires_grad=True)\n", 217 | "y_2 = calc(x_2).item()\n", 218 | "\n", 219 | "x_3 = [1.0, 2.0, 3.0+delta]\n", 220 | "x_3 = torch.tensor(x_3, requires_grad=True)\n", 221 | "y_3 = calc(x_3).item()\n", 222 | "\n", 223 | "# 勾配の計算\n", 224 | "grad_1 = (y_1 - y) / delta\n", 225 | "grad_2 = (y_2 - y) / delta\n", 226 | "grad_3 = (y_3 - y) / delta\n", 227 | "\n", 228 | "print(grad_1, grad_2, grad_3)" 229 | ], 230 | "execution_count": 0, 231 | "outputs": [] 232 | }, 233 | { 234 | "cell_type": "markdown", 235 | "metadata": { 236 | "id": "jwdACN7iWQiy", 237 | "colab_type": "text" 238 | }, 239 | "source": [ 240 | "`x`の微小変化を0.001という小さい値にしましたが、`y`の微小変化との割合は backwardによる計算結果とほぼ同じになりました。 \n", 241 | "backwardにより正しく勾配を計算できていることが確認できました。" 242 | ] 243 | } 244 | ] 245 | } -------------------------------------------------------------------------------- /lecture3/dataloader.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "dataloader.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [], 9 | "toc_visible": true, 10 | "authorship_tag": "ABX9TyOCu7tyVRkTdeKcRjzzuBhq", 11 | "include_colab_link": true 12 | }, 13 | "kernelspec": { 14 | "name": "python3", 15 | "display_name": "Python 3" 16 | }, 17 | "accelerator": "GPU" 18 | }, 19 | "cells": [ 20 | { 21 | "cell_type": "markdown", 22 | "metadata": { 23 | "id": "view-in-github", 24 | "colab_type": "text" 25 | }, 26 | "source": [ 27 | "\"Open" 28 | ] 29 | }, 30 | { 31 | "cell_type": "markdown", 32 | "metadata": { 33 | "id": "Niaz8_W6OX34", 34 | "colab_type": "text" 35 | }, 36 | "source": [ 37 | "# DataLoader\n", 38 | "DataLoaderを使うと、データの読み込みやミニバッチ法の実装などが大幅に楽になります。 \n", 39 | "今回は、DataLoaderを使ってデータを扱い、手書き文字の認識を行います。 \n", 40 | "なお、今回から学習はGPUを使って行います。 \n" 41 | ] 42 | }, 43 | { 44 | "cell_type": "markdown", 45 | "metadata": { 46 | "colab_type": "text", 47 | "id": "x9Gzbn25XSlF" 48 | }, 49 | "source": [ 50 | "## データの読み込み\n", 51 | "`torchvision.datasets`を使って手書き文字のデータを読み込み、DataLoaderを設定します。 \n", 52 | "`torchvision.datasets`にはMNISTの他にも様々なデータセットが用意されています。 \n", 53 | "https://pytorch.org/docs/stable/torchvision/datasets.html\n" 54 | ] 55 | }, 56 | { 57 | "cell_type": "code", 58 | "metadata": { 59 | "colab_type": "code", 60 | "id": "81Il03RNAmbS", 61 | "colab": {} 62 | }, 63 | "source": [ 64 | "import torch\n", 65 | "from torchvision.datasets import MNIST\n", 66 | "from torchvision import transforms\n", 67 | "from torch.utils.data import DataLoader\n", 68 | "\n", 69 | "# 訓練データを取得\n", 70 | "mnist_train = MNIST(\"./data\", \n", 71 | " train=True, download=True,\n", 72 | " transform=transforms.ToTensor())\n", 73 | "# テストデータの取得\n", 74 | "mnist_test = MNIST(\"./data\",\n", 75 | " train=False, download=True,\n", 76 | " transform=transforms.ToTensor())\n", 77 | "print(\"訓練データの数:\", len(mnist_train), \"テストデータの数:\", len(mnist_test))\n", 78 | "\n", 79 | "# DataLoaderの設定\n", 80 | "img_size = 28\n", 81 | "batch_size = 256\n", 82 | "train_loader = DataLoader(mnist_train, \n", 83 | " batch_size=batch_size,\n", 84 | " shuffle=True)\n", 85 | "test_loader = DataLoader(mnist_test,\n", 86 | " batch_size=batch_size,\n", 87 | " shuffle=False)" 88 | ], 89 | "execution_count": 0, 90 | "outputs": [] 91 | }, 92 | { 93 | "cell_type": "markdown", 94 | "metadata": { 95 | "colab_type": "text", 96 | "id": "sFWHMOf2D4b1" 97 | }, 98 | "source": [ 99 | "手書き文字の画像サイズは、28×28になります。 \n", 100 | "\n" 101 | ] 102 | }, 103 | { 104 | "cell_type": "markdown", 105 | "metadata": { 106 | "id": "FalXNYaJPkoE", 107 | "colab_type": "text" 108 | }, 109 | "source": [ 110 | "## モデルの構築\n", 111 | "今回は、`nn.Module`モジュールを継承したクラスとして、モデルを構築します。 \n", 112 | "`.cuda()`により、モデルの計算はGPU上で行われるようになります。 " 113 | ] 114 | }, 115 | { 116 | "cell_type": "code", 117 | "metadata": { 118 | "id": "SuqqZmsh_jNK", 119 | "colab_type": "code", 120 | "colab": {} 121 | }, 122 | "source": [ 123 | "import torch.nn as nn\n", 124 | "import torch.nn.functional as F\n", 125 | "\n", 126 | "class Net(nn.Module):\n", 127 | " def __init__(self):\n", 128 | " super().__init__()\n", 129 | " self.fc1 = nn.Linear(img_size*img_size, 1024) # 全結合層\n", 130 | " self.fc2 = nn.Linear(1024, 512)\n", 131 | " self.fc3 = nn.Linear(512, 10)\n", 132 | "\n", 133 | " def forward(self, x):\n", 134 | " x = x.view(-1, img_size*img_size) # バッチサイズ×入力の数\n", 135 | " x = F.relu(self.fc1(x))\n", 136 | " x = F.relu(self.fc2(x))\n", 137 | " x = self.fc3(x)\n", 138 | " return x\n", 139 | "\n", 140 | "net = Net()\n", 141 | "net.cuda() # GPU対応\n", 142 | "print(net)" 143 | ], 144 | "execution_count": 0, 145 | "outputs": [] 146 | }, 147 | { 148 | "cell_type": "markdown", 149 | "metadata": { 150 | "id": "qsW5zCKhQE9p", 151 | "colab_type": "text" 152 | }, 153 | "source": [ 154 | "## 学習\n", 155 | "モデルを訓練します。 \n", 156 | "DataLoaderを使い、ミニバッチを取り出して訓練および評価を行います。 \n", 157 | "1エポックの中で何度もミニバッチを使って訓練が行われるので、ミニバッチ法が実装されていることになります。 \n", 158 | "学習には時間がかかりますので、編集→ノートブックの設定のハードウェアアクセラレーターでGPUを選択しましょう。\n" 159 | ] 160 | }, 161 | { 162 | "cell_type": "code", 163 | "metadata": { 164 | "id": "u6zwN3nArbGC", 165 | "colab_type": "code", 166 | "colab": {} 167 | }, 168 | "source": [ 169 | "from torch import optim\n", 170 | "\n", 171 | "# 交差エントロピー誤差関数\n", 172 | "loss_fnc = nn.CrossEntropyLoss()\n", 173 | "\n", 174 | "# SGD\n", 175 | "optimizer = optim.SGD(net.parameters(), lr=0.01)\n", 176 | "\n", 177 | "# 損失のログ\n", 178 | "record_loss_train = []\n", 179 | "record_loss_test = []\n", 180 | "\n", 181 | "# 学習\n", 182 | "for i in range(10): # 10エポック学習\n", 183 | " net.train() # 訓練モード\n", 184 | " loss_train = 0\n", 185 | " for j, (x, t) in enumerate(train_loader): # ミニバッチ(x, t)を取り出す\n", 186 | " x, t = x.cuda(), t.cuda() # GPU対応\n", 187 | " y = net(x)\n", 188 | " loss = loss_fnc(y, t)\n", 189 | " loss_train += loss.item()\n", 190 | " optimizer.zero_grad()\n", 191 | " loss.backward()\n", 192 | " optimizer.step()\n", 193 | " loss_train /= j+1\n", 194 | " record_loss_train.append(loss_train)\n", 195 | "\n", 196 | " net.eval() # 評価モード\n", 197 | " loss_test = 0\n", 198 | " for j, (x, t) in enumerate(test_loader): # ミニバッチ(x, t)を取り出す\n", 199 | " x, t = x.cuda(), t.cuda()\n", 200 | " y = net(x)\n", 201 | " loss = loss_fnc(y, t)\n", 202 | " loss_test += loss.item()\n", 203 | " loss_test /= j+1\n", 204 | " record_loss_test.append(loss_test)\n", 205 | "\n", 206 | " if i%1 == 0:\n", 207 | " print(\"Epoch:\", i, \"Loss_Train:\", loss_train, \"Loss_Test:\", loss_test)" 208 | ], 209 | "execution_count": 0, 210 | "outputs": [] 211 | }, 212 | { 213 | "cell_type": "markdown", 214 | "metadata": { 215 | "id": "rJwwrWTw43rx", 216 | "colab_type": "text" 217 | }, 218 | "source": [ 219 | "## 誤差の推移\n", 220 | "訓練データ、テストデータで誤差の推移をグラフ表示します。 " 221 | ] 222 | }, 223 | { 224 | "cell_type": "code", 225 | "metadata": { 226 | "id": "OaJx4swE45XI", 227 | "colab_type": "code", 228 | "colab": {} 229 | }, 230 | "source": [ 231 | "import matplotlib.pyplot as plt\n", 232 | "\n", 233 | "plt.plot(range(len(record_loss_train)), record_loss_train, label=\"Train\")\n", 234 | "plt.plot(range(len(record_loss_test)), record_loss_test, label=\"Test\")\n", 235 | "plt.legend()\n", 236 | "\n", 237 | "plt.xlabel(\"Epochs\")\n", 238 | "plt.ylabel(\"Error\")\n", 239 | "plt.show()" 240 | ], 241 | "execution_count": 0, 242 | "outputs": [] 243 | }, 244 | { 245 | "cell_type": "markdown", 246 | "metadata": { 247 | "id": "iMrpac0m4Nct", 248 | "colab_type": "text" 249 | }, 250 | "source": [ 251 | "## 正解率\n", 252 | "モデルの性能を把握するため、テストデータ使い正解率を測定します。 " 253 | ] 254 | }, 255 | { 256 | "cell_type": "code", 257 | "metadata": { 258 | "id": "IRkGCYMM_N35", 259 | "colab_type": "code", 260 | "colab": {} 261 | }, 262 | "source": [ 263 | "correct = 0\n", 264 | "total = 0\n", 265 | "for i, (x, t) in enumerate(test_loader):\n", 266 | " x, t = x.cuda(), t.cuda() # GPU対応\n", 267 | " x = x.view(-1, img_size*img_size)\n", 268 | " y = net(x)\n", 269 | " correct += (y.argmax(1) == t).sum().item()\n", 270 | " total += len(x)\n", 271 | "print(\"正解率:\", str(correct/total*100) + \"%\")" 272 | ], 273 | "execution_count": 0, 274 | "outputs": [] 275 | } 276 | ] 277 | } -------------------------------------------------------------------------------- /lecture3/exercise.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "exercise.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [], 9 | "toc_visible": true, 10 | "authorship_tag": "ABX9TyPF5BEFzOOufGQ17KC2OPFG", 11 | "include_colab_link": true 12 | }, 13 | "kernelspec": { 14 | "name": "python3", 15 | "display_name": "Python 3" 16 | }, 17 | "accelerator": "GPU" 18 | }, 19 | "cells": [ 20 | { 21 | "cell_type": "markdown", 22 | "metadata": { 23 | "id": "view-in-github", 24 | "colab_type": "text" 25 | }, 26 | "source": [ 27 | "\"Open" 28 | ] 29 | }, 30 | { 31 | "cell_type": "markdown", 32 | "metadata": { 33 | "id": "Niaz8_W6OX34", 34 | "colab_type": "text" 35 | }, 36 | "source": [ 37 | "# 演習\n", 38 | "DataLoaderの扱いに慣れていきましょう。 \n", 39 | "DataLoaderのコードを書いて、データの読み込みとミニバッチ法の実装を行います。\n", 40 | "\n" 41 | ] 42 | }, 43 | { 44 | "cell_type": "markdown", 45 | "metadata": { 46 | "colab_type": "text", 47 | "id": "x9Gzbn25XSlF" 48 | }, 49 | "source": [ 50 | "## データの読み込み\n", 51 | "以下のセルにコードを追記し、DataLoaderの設定を行いましょう。 \n", 52 | "以下のセルの`mnist_train`と`mnist_test`に対してDataLoaderを設定します。 " 53 | ] 54 | }, 55 | { 56 | "cell_type": "code", 57 | "metadata": { 58 | "colab_type": "code", 59 | "id": "81Il03RNAmbS", 60 | "colab": {} 61 | }, 62 | "source": [ 63 | "import torch\n", 64 | "from torchvision.datasets import MNIST\n", 65 | "from torchvision import transforms\n", 66 | "from torch.utils.data import DataLoader\n", 67 | "\n", 68 | "# 訓練データを取得\n", 69 | "mnist_train = MNIST(\"./data\", \n", 70 | " train=True, download=True,\n", 71 | " transform=transforms.ToTensor())\n", 72 | "# テストデータの取得\n", 73 | "mnist_test = MNIST(\"./data\",\n", 74 | " train=False, download=True,\n", 75 | " transform=transforms.ToTensor())\n", 76 | "print(\"訓練データの数:\", len(mnist_train), \"テストデータの数:\", len(mnist_test))\n", 77 | "\n", 78 | "# DataLoaderの設定\n", 79 | "img_size = 28\n", 80 | "batch_size = 128\n", 81 | "# ------- 以下にコードを書く -------\n", 82 | "\n", 83 | "\n", 84 | "\n", 85 | "\n", 86 | "# ------- ここまで -------" 87 | ], 88 | "execution_count": 0, 89 | "outputs": [] 90 | }, 91 | { 92 | "cell_type": "markdown", 93 | "metadata": { 94 | "id": "FalXNYaJPkoE", 95 | "colab_type": "text" 96 | }, 97 | "source": [ 98 | "## モデルの構築" 99 | ] 100 | }, 101 | { 102 | "cell_type": "code", 103 | "metadata": { 104 | "id": "SuqqZmsh_jNK", 105 | "colab_type": "code", 106 | "colab": {} 107 | }, 108 | "source": [ 109 | "import torch.nn as nn\n", 110 | "import torch.nn.functional as F\n", 111 | "\n", 112 | "class Net(nn.Module):\n", 113 | " def __init__(self):\n", 114 | " super().__init__()\n", 115 | " self.fc1 = nn.Linear(img_size*img_size, 1024) # 全結合層\n", 116 | " self.fc2 = nn.Linear(1024, 512)\n", 117 | " self.fc3 = nn.Linear(512, 10)\n", 118 | "\n", 119 | " def forward(self, x):\n", 120 | " x = x.view(-1, img_size*img_size) # バッチサイズ×入力の数\n", 121 | " x = F.relu(self.fc1(x))\n", 122 | " x = F.relu(self.fc2(x))\n", 123 | " x = self.fc3(x)\n", 124 | " return x\n", 125 | "\n", 126 | "net = Net()\n", 127 | "net.cuda() # GPU対応\n", 128 | "print(net)" 129 | ], 130 | "execution_count": 0, 131 | "outputs": [] 132 | }, 133 | { 134 | "cell_type": "markdown", 135 | "metadata": { 136 | "id": "qsW5zCKhQE9p", 137 | "colab_type": "text" 138 | }, 139 | "source": [ 140 | "## 学習\n", 141 | "訓練および検証の箇所にfor文のコードを追記し、DataLoaderを使ったミニバッチ法を実装しましょう。 \n" 142 | ] 143 | }, 144 | { 145 | "cell_type": "code", 146 | "metadata": { 147 | "id": "u6zwN3nArbGC", 148 | "colab_type": "code", 149 | "colab": {} 150 | }, 151 | "source": [ 152 | "from torch import optim\n", 153 | "import time\n", 154 | "\n", 155 | "# 交差エントロピー誤差関数\n", 156 | "loss_fnc = nn.CrossEntropyLoss()\n", 157 | "\n", 158 | "# SGD\n", 159 | "optimizer = optim.SGD(net.parameters(), lr=0.01)\n", 160 | "\n", 161 | "# 損失のログ\n", 162 | "record_loss_train = []\n", 163 | "record_loss_test = []\n", 164 | "\n", 165 | "# 学習\n", 166 | "for i in range(10): # 10エポック学習\n", 167 | " net.train() # 訓練モード\n", 168 | " loss_train = 0\n", 169 | " # ← 左にfor文のコードを追記\n", 170 | " x, t = x.cuda(), t.cuda() # GPU対応\n", 171 | " y = net(x)\n", 172 | " loss = loss_fnc(y, t)\n", 173 | " loss_train += loss.item()\n", 174 | " optimizer.zero_grad()\n", 175 | " loss.backward()\n", 176 | " optimizer.step()\n", 177 | " loss_train /= j+1\n", 178 | " record_loss_train.append(loss_train)\n", 179 | "\n", 180 | " net.eval() # 評価モード\n", 181 | " loss_test = 0\n", 182 | " # ← 左にfor文のコードを追記\n", 183 | " x, t = x.cuda(), t.cuda()\n", 184 | " y = net(x)\n", 185 | " loss = loss_fnc(y, t)\n", 186 | " loss_test += loss.item()\n", 187 | " loss_test /= j+1\n", 188 | " record_loss_test.append(loss_test)\n", 189 | "\n", 190 | " if i%1 == 0:\n", 191 | " print(\"Epoch:\", i, \"Loss_Train:\", loss_train, \"Loss_Test:\", loss_test)" 192 | ], 193 | "execution_count": 0, 194 | "outputs": [] 195 | }, 196 | { 197 | "cell_type": "markdown", 198 | "metadata": { 199 | "id": "rJwwrWTw43rx", 200 | "colab_type": "text" 201 | }, 202 | "source": [ 203 | "## 誤差の推移" 204 | ] 205 | }, 206 | { 207 | "cell_type": "code", 208 | "metadata": { 209 | "id": "OaJx4swE45XI", 210 | "colab_type": "code", 211 | "colab": {} 212 | }, 213 | "source": [ 214 | "import matplotlib.pyplot as plt\n", 215 | "\n", 216 | "plt.plot(range(len(record_loss_train)), record_loss_train, label=\"Train\")\n", 217 | "plt.plot(range(len(record_loss_test)), record_loss_test, label=\"Test\")\n", 218 | "plt.legend()\n", 219 | "\n", 220 | "plt.xlabel(\"Epochs\")\n", 221 | "plt.ylabel(\"Error\")\n", 222 | "plt.show()" 223 | ], 224 | "execution_count": 0, 225 | "outputs": [] 226 | }, 227 | { 228 | "cell_type": "markdown", 229 | "metadata": { 230 | "id": "iMrpac0m4Nct", 231 | "colab_type": "text" 232 | }, 233 | "source": [ 234 | "## 正解率" 235 | ] 236 | }, 237 | { 238 | "cell_type": "code", 239 | "metadata": { 240 | "id": "IRkGCYMM_N35", 241 | "colab_type": "code", 242 | "colab": {} 243 | }, 244 | "source": [ 245 | "correct = 0\n", 246 | "total = 0\n", 247 | "for i, (x, t) in enumerate(test_loader):\n", 248 | " x, t = x.cuda(), t.cuda() # GPU対応\n", 249 | " x = x.view(-1, img_size*img_size)\n", 250 | " y = net(x)\n", 251 | " correct += (y.argmax(1) == t).sum().item()\n", 252 | " total += len(x)\n", 253 | "print(\"正解率:\", str(correct/total*100) + \"%\")" 254 | ], 255 | "execution_count": 0, 256 | "outputs": [] 257 | }, 258 | { 259 | "cell_type": "markdown", 260 | "metadata": { 261 | "id": "maAJN2wa0l1D", 262 | "colab_type": "text" 263 | }, 264 | "source": [ 265 | "# 解答例\n", 266 | "以下は、どうしても手がかりがないときのみ参考にしましょう。" 267 | ] 268 | }, 269 | { 270 | "cell_type": "code", 271 | "metadata": { 272 | "id": "rQagvzyDmDA5", 273 | "colab_type": "code", 274 | "colab": {} 275 | }, 276 | "source": [ 277 | "import torch\n", 278 | "from torchvision.datasets import MNIST\n", 279 | "from torchvision import transforms\n", 280 | "from torch.utils.data import DataLoader\n", 281 | "\n", 282 | "# 訓練データを取得\n", 283 | "mnist_train = MNIST(\"./data\", \n", 284 | " train=True, download=True,\n", 285 | " transform=transforms.ToTensor())\n", 286 | "# テストデータの取得\n", 287 | "mnist_test = MNIST(\"./data\",\n", 288 | " train=False, download=True,\n", 289 | " transform=transforms.ToTensor())\n", 290 | "print(\"訓練データの数:\", len(mnist_train), \"テストデータの数:\", len(mnist_test))\n", 291 | "\n", 292 | "# DataLoaderの設定\n", 293 | "img_size = 28\n", 294 | "batch_size = 128\n", 295 | "# ------- 以下にコードを書く -------\n", 296 | "train_loader = DataLoader(mnist_train, \n", 297 | " batch_size=batch_size,\n", 298 | " shuffle=True)\n", 299 | "test_loader = DataLoader(mnist_test,\n", 300 | " batch_size=batch_size,\n", 301 | " shuffle=False)\n", 302 | "# ------- ここまで -------" 303 | ], 304 | "execution_count": 0, 305 | "outputs": [] 306 | }, 307 | { 308 | "cell_type": "code", 309 | "metadata": { 310 | "id": "gYHIvyIijc5S", 311 | "colab_type": "code", 312 | "colab": {} 313 | }, 314 | "source": [ 315 | "from torch import optim\n", 316 | "import time\n", 317 | "\n", 318 | "# 交差エントロピー誤差関数\n", 319 | "loss_fnc = nn.CrossEntropyLoss()\n", 320 | "\n", 321 | "# SGD\n", 322 | "optimizer = optim.SGD(net.parameters(), lr=0.01)\n", 323 | "\n", 324 | "# 損失のログ\n", 325 | "record_loss_train = []\n", 326 | "record_loss_test = []\n", 327 | "\n", 328 | "# 学習\n", 329 | "for i in range(10): # 10エポック学習\n", 330 | " net.train() # 訓練モード\n", 331 | " loss_train = 0\n", 332 | " for j, (x, t) in enumerate(train_loader): # ← 左にfor文のコードを追記\n", 333 | " x, t = x.cuda(), t.cuda() # GPU対応\n", 334 | " y = net(x)\n", 335 | " loss = loss_fnc(y, t)\n", 336 | " loss_train += loss.item()\n", 337 | " optimizer.zero_grad()\n", 338 | " loss.backward()\n", 339 | " optimizer.step()\n", 340 | " loss_train /= j+1\n", 341 | " record_loss_train.append(loss_train)\n", 342 | "\n", 343 | " net.eval() # 評価モード\n", 344 | " loss_test = 0\n", 345 | " for j, (x, t) in enumerate(test_loader): # ← 左にfor文のコードを追記\n", 346 | " x, t = x.cuda(), t.cuda()\n", 347 | " y = net(x)\n", 348 | " loss = loss_fnc(y, t)\n", 349 | " loss_test += loss.item()\n", 350 | " loss_test /= j+1\n", 351 | " record_loss_test.append(loss_test)\n", 352 | "\n", 353 | " if i%1 == 0:\n", 354 | " print(\"Epoch:\", i, \"Loss_Train:\", loss_train, \"Loss_Test:\", loss_test)" 355 | ], 356 | "execution_count": 0, 357 | "outputs": [] 358 | } 359 | ] 360 | } -------------------------------------------------------------------------------- /lecture4/cnn.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "cnn.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [], 9 | "toc_visible": true, 10 | "authorship_tag": "ABX9TyP1JUkF4cGqlrgSjejGCxlS", 11 | "include_colab_link": true 12 | }, 13 | "kernelspec": { 14 | "name": "python3", 15 | "display_name": "Python 3" 16 | }, 17 | "accelerator": "GPU" 18 | }, 19 | "cells": [ 20 | { 21 | "cell_type": "markdown", 22 | "metadata": { 23 | "id": "view-in-github", 24 | "colab_type": "text" 25 | }, 26 | "source": [ 27 | "\"Open" 28 | ] 29 | }, 30 | { 31 | "cell_type": "markdown", 32 | "metadata": { 33 | "id": "Niaz8_W6OX34", 34 | "colab_type": "text" 35 | }, 36 | "source": [ 37 | "# CNNの実装\n", 38 | "PyTorchを使って、畳み込みニューラルネットワーク(CNN)を実装します。 \n", 39 | "CNN自体はCNNの層を追加するのみで実装可能なのですが、今回はデータ拡張とドロップアウトの実装も行います。\n" 40 | ] 41 | }, 42 | { 43 | "cell_type": "markdown", 44 | "metadata": { 45 | "id": "jpMObJX-c6CW", 46 | "colab_type": "text" 47 | }, 48 | "source": [ 49 | "## CIFAR-10\n", 50 | "torchvision.datasetsを使い、CIFAR-10を読み込みます。 \n", 51 | "CIFARは、約6万枚の画像にラベルをつけたたデータセットです。 \n", 52 | "以下のコードでは、CIFAR-10を読み込み、ランダムな25枚の画像を表示します。" 53 | ] 54 | }, 55 | { 56 | "cell_type": "code", 57 | "metadata": { 58 | "id": "CbolmAveUtJ4", 59 | "colab_type": "code", 60 | "colab": {} 61 | }, 62 | "source": [ 63 | "from torchvision.datasets import CIFAR10\n", 64 | "import torchvision.transforms as transforms\n", 65 | "from torch.utils.data import DataLoader\n", 66 | "import numpy as np\n", 67 | "import matplotlib.pyplot as plt\n", 68 | "\n", 69 | "cifar10_data = CIFAR10(root=\"./data\",\n", 70 | " train=False,download=True,\n", 71 | " transform=transforms.ToTensor())\n", 72 | "cifar10_classes = np.array([\"airplane\", \"automobile\", \"bird\", \"cat\", \"deer\",\n", 73 | " \"dog\", \"frog\", \"horse\", \"ship\", \"truck\"])\n", 74 | "print(\"データの数:\", len(cifar10_data))\n", 75 | "\n", 76 | "n_image = 25 # 表示する画像の数\n", 77 | "cifar10_loader = DataLoader(cifar10_data, batch_size=n_image, shuffle=True)\n", 78 | "dataiter = iter(cifar10_loader) # イテレータ\n", 79 | "images, labels = dataiter.next() # 最初のバッチを取り出す\n", 80 | "\n", 81 | "plt.figure(figsize=(10,10)) # 画像の表示サイズ\n", 82 | "for i in range(n_image):\n", 83 | " plt.subplot(5,5,i+1)\n", 84 | " plt.imshow(np.transpose(images[i], (1, 2, 0))) # チャンネルを一番後ろに\n", 85 | " label = cifar10_classes[labels[i]]\n", 86 | " plt.title(label)\n", 87 | " plt.tick_params(labelbottom=False, labelleft=False, bottom=False, left=False) # ラベルとメモリを非表示に\n", 88 | "\n", 89 | "plt.show()" 90 | ], 91 | "execution_count": 0, 92 | "outputs": [] 93 | }, 94 | { 95 | "cell_type": "markdown", 96 | "metadata": { 97 | "id": "24KV93msd3i-", 98 | "colab_type": "text" 99 | }, 100 | "source": [ 101 | "## データ拡張\n", 102 | "torchvision.transformsを使ってデータ拡張を行います。 \n", 103 | "今回は、cifar-10の画像に-30〜30°の回転、および0.8〜1.2倍のリサイズを行います。 \n", 104 | "これらの処理は、バッチを取り出す際に元の画像に対してランダムに加えられます。 \n" 105 | ] 106 | }, 107 | { 108 | "cell_type": "code", 109 | "metadata": { 110 | "id": "TVWgInj2luno", 111 | "colab_type": "code", 112 | "colab": {} 113 | }, 114 | "source": [ 115 | "from torchvision.datasets import CIFAR10\n", 116 | "import torchvision.transforms as transforms\n", 117 | "from torch.utils.data import DataLoader\n", 118 | "import numpy as np\n", 119 | "import matplotlib.pyplot as plt\n", 120 | "\n", 121 | "transform = transforms.Compose([transforms.RandomAffine([-30, 30], scale=(0.8, 1.2)), # 回転とリサイズ\n", 122 | " transforms.ToTensor()])\n", 123 | "cifar10_data = CIFAR10(root=\"./data\",\n", 124 | " train=False,download=True,\n", 125 | " transform=transform)\n", 126 | "cifar10_classes = np.array([\"airplane\", \"automobile\", \"bird\", \"cat\", \"deer\",\n", 127 | " \"dog\", \"frog\", \"horse\", \"ship\", \"truck\"])\n", 128 | "print(\"データの数:\", len(cifar10_data))\n", 129 | "\n", 130 | "n_image = 25 # 表示する画像の数\n", 131 | "cifar10_loader = DataLoader(cifar10_data, batch_size=n_image, shuffle=True)\n", 132 | "dataiter = iter(cifar10_loader) # イテレータ\n", 133 | "images, labels = dataiter.next() # 最初のバッチを取り出す\n", 134 | "\n", 135 | "plt.figure(figsize=(10,10)) # 画像の表示サイズ\n", 136 | "for i in range(n_image):\n", 137 | " plt.subplot(5,5,i+1)\n", 138 | " plt.imshow(np.transpose(images[i], (1, 2, 0))) # チャンネルを一番後ろに\n", 139 | " label = cifar10_classes[labels[i]]\n", 140 | " plt.title(label)\n", 141 | " plt.tick_params(labelbottom=False, labelleft=False, bottom=False, left=False) # ラベルとメモリを非表示に\n", 142 | "\n", 143 | "plt.show()" 144 | ], 145 | "execution_count": 0, 146 | "outputs": [] 147 | }, 148 | { 149 | "cell_type": "markdown", 150 | "metadata": { 151 | "id": "vsncPqQ-gZJr", 152 | "colab_type": "text" 153 | }, 154 | "source": [ 155 | "## データの前処理\n", 156 | "ここからCNNを実装します。 \n", 157 | "データ拡張として、回転とリサイズ、および左右反転を行います。 \n", 158 | "また、学習が効率的になるように入力の平均値を0、標準偏差を1にします(標準化)。 \n", 159 | "DataLoaderは、訓練データ、テストデータそれぞれで設定しますが、テストデータにはミニバッチ法を適用しないのでバッチサイズは元データのサンプル数にします。" 160 | ] 161 | }, 162 | { 163 | "cell_type": "code", 164 | "metadata": { 165 | "id": "7t3NRHjhKyC0", 166 | "colab_type": "code", 167 | "colab": {} 168 | }, 169 | "source": [ 170 | "from torchvision.datasets import CIFAR10\n", 171 | "import torchvision.transforms as transforms\n", 172 | "from torch.utils.data import DataLoader\n", 173 | "\n", 174 | "affine = transforms.RandomAffine([-15, 15], scale=(0.8, 1.2)) # 回転とリサイズ\n", 175 | "flip = transforms.RandomHorizontalFlip(p=0.5) # 左右反転\n", 176 | "normalize = transforms.Normalize((0.0, 0.0, 0.0), (1.0, 1.0, 1.0)) # 平均値を0、標準偏差を1に\n", 177 | "to_tensor = transforms.ToTensor()\n", 178 | "\n", 179 | "transform_train = transforms.Compose([affine, flip, to_tensor, normalize])\n", 180 | "transform_test = transforms.Compose([to_tensor, normalize])\n", 181 | "cifar10_train = CIFAR10(\"./data\", train=True, download=True, transform=transform_train)\n", 182 | "cifar10_test = CIFAR10(\"./data\", train=False, download=True, transform=transform_test)\n", 183 | "\n", 184 | "# DataLoaderの設定\n", 185 | "batch_size = 64\n", 186 | "train_loader = DataLoader(cifar10_train, batch_size=batch_size, shuffle=True)\n", 187 | "test_loader = DataLoader(cifar10_test, batch_size=len(cifar10_test), shuffle=False)" 188 | ], 189 | "execution_count": 0, 190 | "outputs": [] 191 | }, 192 | { 193 | "cell_type": "markdown", 194 | "metadata": { 195 | "id": "FalXNYaJPkoE", 196 | "colab_type": "text" 197 | }, 198 | "source": [ 199 | "## モデルの構築\n", 200 | "`nn.Module`モジュールを継承したクラスとして、モデルを構築します。 \n", 201 | "今回は、過学習を抑制するためにドロップアウトを導入します。 " 202 | ] 203 | }, 204 | { 205 | "cell_type": "code", 206 | "metadata": { 207 | "id": "SuqqZmsh_jNK", 208 | "colab_type": "code", 209 | "colab": {} 210 | }, 211 | "source": [ 212 | "import torch.nn as nn\n", 213 | "import torch.nn.functional as F\n", 214 | "\n", 215 | "class Net(nn.Module):\n", 216 | " def __init__(self):\n", 217 | " super().__init__()\n", 218 | " self.conv1 = nn.Conv2d(3, 6, 5) # 畳み込み層:(入力チャンネル数, フィルタ数、フィルタサイズ)\n", 219 | " self.pool = nn.MaxPool2d(2, 2) # プーリング層:(領域のサイズ, ストライド)\n", 220 | " self.conv2 = nn.Conv2d(6, 16, 5)\n", 221 | " self.fc1 = nn.Linear(16*5*5, 256) # 全結合層\n", 222 | " self.dropout = nn.Dropout(p=0.5) # ドロップアウト:(p=ドロップアウト率)\n", 223 | " self.fc2 = nn.Linear(256, 10)\n", 224 | "\n", 225 | " def forward(self, x):\n", 226 | " x = self.pool(F.relu(self.conv1(x)))\n", 227 | " x = self.pool(F.relu(self.conv2(x)))\n", 228 | " x = x.view(-1, 16*5*5)\n", 229 | " x = F.relu(self.fc1(x))\n", 230 | " x = self.dropout(x)\n", 231 | " x = self.fc2(x)\n", 232 | " return x\n", 233 | "\n", 234 | "net = Net()\n", 235 | "net.cuda() # GPU対応\n", 236 | "print(net)" 237 | ], 238 | "execution_count": 0, 239 | "outputs": [] 240 | }, 241 | { 242 | "cell_type": "markdown", 243 | "metadata": { 244 | "id": "qsW5zCKhQE9p", 245 | "colab_type": "text" 246 | }, 247 | "source": [ 248 | "## 学習\n", 249 | "モデルを訓練します。 \n", 250 | "DataLoaderを使い、ミニバッチを取り出して訓練および評価を行います。 \n", 251 | "今回は、評価時にミニバッチ法は使わず、テストデータ全体を使って一度に誤差を計算します。 \n", 252 | "学習には時間がかかりますので、編集→ノートブックの設定のハードウェアアクセラレーターでGPUを選択しましょう。\n" 253 | ] 254 | }, 255 | { 256 | "cell_type": "code", 257 | "metadata": { 258 | "id": "u6zwN3nArbGC", 259 | "colab_type": "code", 260 | "colab": {} 261 | }, 262 | "source": [ 263 | "from torch import optim\n", 264 | "\n", 265 | "# 交差エントロピー誤差関数\n", 266 | "loss_fnc = nn.CrossEntropyLoss()\n", 267 | "\n", 268 | "# 最適化アルゴリズム\n", 269 | "optimizer = optim.Adam(net.parameters())\n", 270 | "\n", 271 | "# 損失のログ\n", 272 | "record_loss_train = []\n", 273 | "record_loss_test = []\n", 274 | "\n", 275 | "# 学習\n", 276 | "x_test, t_test = iter(test_loader).next()\n", 277 | "x_test, t_test = x_test.cuda(), t_test.cuda()\n", 278 | "for i in range(20): # 20エポック学習\n", 279 | " net.train() # 訓練モード\n", 280 | " loss_train = 0\n", 281 | " for j, (x, t) in enumerate(train_loader): # ミニバッチ(x, t)を取り出す\n", 282 | " x, t = x.cuda(), t.cuda() # GPU対応\n", 283 | " y = net(x)\n", 284 | " loss = loss_fnc(y, t)\n", 285 | " loss_train += loss.item()\n", 286 | " optimizer.zero_grad()\n", 287 | " loss.backward()\n", 288 | " optimizer.step()\n", 289 | " loss_train /= j+1\n", 290 | " record_loss_train.append(loss_train)\n", 291 | "\n", 292 | " net.eval() # 評価モード\n", 293 | " y_test = net(x_test)\n", 294 | " loss_test = loss_fnc(y_test, t_test).item()\n", 295 | " record_loss_test.append(loss_test)\n", 296 | "\n", 297 | " if i%1 == 0:\n", 298 | " print(\"Epoch:\", i, \"Loss_Train:\", loss_train, \"Loss_Test:\", loss_test)" 299 | ], 300 | "execution_count": 0, 301 | "outputs": [] 302 | }, 303 | { 304 | "cell_type": "markdown", 305 | "metadata": { 306 | "id": "rJwwrWTw43rx", 307 | "colab_type": "text" 308 | }, 309 | "source": [ 310 | "## 誤差の推移\n", 311 | "訓練データ、テストデータで誤差の推移をグラフ表示します。 " 312 | ] 313 | }, 314 | { 315 | "cell_type": "code", 316 | "metadata": { 317 | "id": "OaJx4swE45XI", 318 | "colab_type": "code", 319 | "colab": {} 320 | }, 321 | "source": [ 322 | "import matplotlib.pyplot as plt\n", 323 | "\n", 324 | "plt.plot(range(len(record_loss_train)), record_loss_train, label=\"Train\")\n", 325 | "plt.plot(range(len(record_loss_test)), record_loss_test, label=\"Test\")\n", 326 | "plt.legend()\n", 327 | "\n", 328 | "plt.xlabel(\"Epochs\")\n", 329 | "plt.ylabel(\"Error\")\n", 330 | "plt.show()" 331 | ], 332 | "execution_count": 0, 333 | "outputs": [] 334 | }, 335 | { 336 | "cell_type": "markdown", 337 | "metadata": { 338 | "id": "iMrpac0m4Nct", 339 | "colab_type": "text" 340 | }, 341 | "source": [ 342 | "## 正解率\n", 343 | "モデルの性能を把握するため、テストデータ使い正解率を測定します。 " 344 | ] 345 | }, 346 | { 347 | "cell_type": "code", 348 | "metadata": { 349 | "id": "IRkGCYMM_N35", 350 | "colab_type": "code", 351 | "colab": {} 352 | }, 353 | "source": [ 354 | "correct = 0\n", 355 | "total = 0\n", 356 | "net.eval() # 評価モード\n", 357 | "for i, (x, t) in enumerate(test_loader):\n", 358 | " x, t = x.cuda(), t.cuda() # GPU対応\n", 359 | " y = net(x)\n", 360 | " correct += (y.argmax(1) == t).sum().item()\n", 361 | " total += len(x)\n", 362 | "print(\"正解率:\", str(correct/total*100) + \"%\")" 363 | ], 364 | "execution_count": 0, 365 | "outputs": [] 366 | }, 367 | { 368 | "cell_type": "markdown", 369 | "metadata": { 370 | "id": "LrRAJzwD4zpN", 371 | "colab_type": "text" 372 | }, 373 | "source": [ 374 | "## 訓練済みのモデルを使った予測\n", 375 | "訓練済みのモデルを使ってみましょう。 \n", 376 | "画像を入力し、モデルが機能していることを確かめます。" 377 | ] 378 | }, 379 | { 380 | "cell_type": "code", 381 | "metadata": { 382 | "id": "Pdy9nPckTDik", 383 | "colab_type": "code", 384 | "colab": {} 385 | }, 386 | "source": [ 387 | "cifar10_loader = DataLoader(cifar10_test, batch_size=1, shuffle=True)\n", 388 | "dataiter = iter(cifar10_loader)\n", 389 | "images, labels = dataiter.next() # サンプルを1つだけ取り出す\n", 390 | "\n", 391 | "plt.imshow(np.transpose(images[0], (1, 2, 0))) # チャンネルを一番後ろに\n", 392 | "plt.tick_params(labelbottom=False, labelleft=False, bottom=False, left=False) # ラベルとメモリを非表示に\n", 393 | "plt.show()\n", 394 | "\n", 395 | "net.eval() # 評価モード\n", 396 | "x, t = images.cuda(), labels.cuda() # GPU対応\n", 397 | "y = net(x)\n", 398 | "print(\"正解:\", cifar10_classes[labels[0]],\n", 399 | " \"予測結果:\", cifar10_classes[y.argmax().item()])" 400 | ], 401 | "execution_count": 0, 402 | "outputs": [] 403 | } 404 | ] 405 | } -------------------------------------------------------------------------------- /lecture4/exercise.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "exercise.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [], 9 | "toc_visible": true, 10 | "authorship_tag": "ABX9TyOh/sBj5jvoGU7U5d6pgQvY", 11 | "include_colab_link": true 12 | }, 13 | "kernelspec": { 14 | "name": "python3", 15 | "display_name": "Python 3" 16 | }, 17 | "accelerator": "GPU" 18 | }, 19 | "cells": [ 20 | { 21 | "cell_type": "markdown", 22 | "metadata": { 23 | "id": "view-in-github", 24 | "colab_type": "text" 25 | }, 26 | "source": [ 27 | "\"Open" 28 | ] 29 | }, 30 | { 31 | "cell_type": "markdown", 32 | "metadata": { 33 | "id": "Niaz8_W6OX34", 34 | "colab_type": "text" 35 | }, 36 | "source": [ 37 | "# 演習\n", 38 | "新たなデータ拡張を追加し、CNNのモデルを構築しましょう。 \n" 39 | ] 40 | }, 41 | { 42 | "cell_type": "markdown", 43 | "metadata": { 44 | "id": "24KV93msd3i-", 45 | "colab_type": "text" 46 | }, 47 | "source": [ 48 | "## 領域のランダムな消去\n", 49 | "新たにデータ拡張を追加します。 \n", 50 | "transforms.RandomErasingにより、画像の領域がランダムに消去されます。 \n", 51 | "https://pytorch.org/docs/stable/torchvision/transforms.html#torchvision.transforms.RandomErasing\n" 52 | ] 53 | }, 54 | { 55 | "cell_type": "code", 56 | "metadata": { 57 | "id": "TVWgInj2luno", 58 | "colab_type": "code", 59 | "colab": {} 60 | }, 61 | "source": [ 62 | "from torchvision.datasets import CIFAR10\n", 63 | "import torchvision.transforms as transforms\n", 64 | "from torch.utils.data import DataLoader\n", 65 | "import numpy as np\n", 66 | "import matplotlib.pyplot as plt\n", 67 | "\n", 68 | "transform = transforms.Compose([\n", 69 | " transforms.RandomAffine([-30, 30], scale=(0.8, 1.2)), # 回転とリサイズ\n", 70 | " transforms.ToTensor(),\n", 71 | " transforms.RandomErasing(p=0.5)]) # 確率0.5でランダムに領域を消去\n", 72 | "cifar10_data = CIFAR10(root=\"./data\",\n", 73 | " train=False,download=True,\n", 74 | " transform=transform)\n", 75 | "cifar10_classes = np.array([\"airplane\", \"automobile\", \"bird\", \"cat\", \"deer\",\n", 76 | " \"dog\", \"frog\", \"horse\", \"ship\", \"truck\"])\n", 77 | "print(\"データの数:\", len(cifar10_data))\n", 78 | "\n", 79 | "n_image = 25 # 表示する画像の数\n", 80 | "cifar10_loader = DataLoader(cifar10_data, batch_size=n_image, shuffle=True)\n", 81 | "dataiter = iter(cifar10_loader) # イテレータ\n", 82 | "images, labels = dataiter.next() # 最初のバッチを取り出す\n", 83 | "\n", 84 | "plt.figure(figsize=(10,10)) # 画像の表示サイズ\n", 85 | "for i in range(n_image):\n", 86 | " plt.subplot(5,5,i+1)\n", 87 | " plt.imshow(np.transpose(images[i], (1, 2, 0))) # チャンネルを一番後ろに\n", 88 | " label = cifar10_classes[labels[i]]\n", 89 | " plt.title(label)\n", 90 | " plt.tick_params(labelbottom=False, labelleft=False, bottom=False, left=False) # ラベルとメモリを非表示に\n", 91 | "\n", 92 | "plt.show()" 93 | ], 94 | "execution_count": 0, 95 | "outputs": [] 96 | }, 97 | { 98 | "cell_type": "markdown", 99 | "metadata": { 100 | "id": "vsncPqQ-gZJr", 101 | "colab_type": "text" 102 | }, 103 | "source": [ 104 | "## データの前処理\n", 105 | "ここからCNNを実装していきます。 \n", 106 | "以下のセルにコードを追記し、データ拡張の一環としてtransforms.RandomErasingによるランダムな画像領域の消去を実装しましょう。" 107 | ] 108 | }, 109 | { 110 | "cell_type": "code", 111 | "metadata": { 112 | "id": "7t3NRHjhKyC0", 113 | "colab_type": "code", 114 | "colab": {} 115 | }, 116 | "source": [ 117 | "from torchvision.datasets import CIFAR10\n", 118 | "import torchvision.transforms as transforms\n", 119 | "from torch.utils.data import DataLoader\n", 120 | "\n", 121 | "affine = transforms.RandomAffine([-15, 15], scale=(0.8, 1.2)) # 回転とリサイズ\n", 122 | "flip = transforms.RandomHorizontalFlip(p=0.5) # 左右反転\n", 123 | "normalize = transforms.Normalize((0.0, 0.0, 0.0), (1.0, 1.0, 1.0)) # 平均値を0、標準偏差を1に\n", 124 | "to_tensor = transforms.ToTensor()\n", 125 | "erase = # ← 左にコードを追記\n", 126 | "\n", 127 | "transform_train = transforms.Compose([affine, flip, to_tensor, normalize, erase])\n", 128 | "transform_test = transforms.Compose([to_tensor, normalize])\n", 129 | "cifar10_train = CIFAR10(\"./data\", train=True, download=True, transform=transform_train)\n", 130 | "cifar10_test = CIFAR10(\"./data\", train=False, download=True, transform=transform_test)\n", 131 | "\n", 132 | "# DataLoaderの設定\n", 133 | "batch_size = 64\n", 134 | "train_loader = DataLoader(cifar10_train, batch_size=batch_size, shuffle=True)\n", 135 | "test_loader = DataLoader(cifar10_test, batch_size=len(cifar10_test), shuffle=False)" 136 | ], 137 | "execution_count": 0, 138 | "outputs": [] 139 | }, 140 | { 141 | "cell_type": "markdown", 142 | "metadata": { 143 | "id": "FalXNYaJPkoE", 144 | "colab_type": "text" 145 | }, 146 | "source": [ 147 | "## モデルの構築\n", 148 | "以下のセルで、forwardメソッドの内部にコードを記述しCNNのモデルを構築しましょう。" 149 | ] 150 | }, 151 | { 152 | "cell_type": "code", 153 | "metadata": { 154 | "id": "SuqqZmsh_jNK", 155 | "colab_type": "code", 156 | "colab": {} 157 | }, 158 | "source": [ 159 | "import torch.nn as nn\n", 160 | "import torch.nn.functional as F\n", 161 | "\n", 162 | "class Net(nn.Module):\n", 163 | " def __init__(self):\n", 164 | " super().__init__()\n", 165 | " self.conv1 = nn.Conv2d(3, 8, 5) # 畳み込み層:(入力チャンネル数, フィルタ数、フィルタサイズ)\n", 166 | " self.pool = nn.MaxPool2d(2, 2) # プーリング層:(領域のサイズ, ストライド)\n", 167 | " self.conv2 = nn.Conv2d(8, 32, 5)\n", 168 | " self.fc1 = nn.Linear(32*5*5, 256) # 全結合層\n", 169 | " self.dropout = nn.Dropout(p=0.5) # ドロップアウト:(p=ドロップアウト率)\n", 170 | " self.fc2 = nn.Linear(256, 10)\n", 171 | "\n", 172 | " def forward(self, x):\n", 173 | " # ------- 以下にコードを書く -------\n", 174 | "\n", 175 | "\n", 176 | "\n", 177 | "\n", 178 | "\n", 179 | "\n", 180 | " # ------- ここまで -------\n", 181 | " return x\n", 182 | "\n", 183 | "net = Net()\n", 184 | "net.cuda() # GPU対応\n", 185 | "print(net)" 186 | ], 187 | "execution_count": 0, 188 | "outputs": [] 189 | }, 190 | { 191 | "cell_type": "markdown", 192 | "metadata": { 193 | "id": "qsW5zCKhQE9p", 194 | "colab_type": "text" 195 | }, 196 | "source": [ 197 | "## 学習\n", 198 | "モデルを訓練します。 \n", 199 | "エラーが発生せず、学習に伴い訓練誤差とテスト誤差が共に減少することを確認しましょう。 \n", 200 | "学習には時間がかかりますので、編集→ノートブックの設定のハードウェアアクセラレーターでGPUを選択しましょう。\n" 201 | ] 202 | }, 203 | { 204 | "cell_type": "code", 205 | "metadata": { 206 | "id": "u6zwN3nArbGC", 207 | "colab_type": "code", 208 | "colab": {} 209 | }, 210 | "source": [ 211 | "from torch import optim\n", 212 | "\n", 213 | "# 交差エントロピー誤差関数\n", 214 | "loss_fnc = nn.CrossEntropyLoss()\n", 215 | "\n", 216 | "# 最適化アルゴリズム\n", 217 | "optimizer = optim.Adam(net.parameters())\n", 218 | "\n", 219 | "# 損失のログ\n", 220 | "record_loss_train = []\n", 221 | "record_loss_test = []\n", 222 | "\n", 223 | "# 学習\n", 224 | "x_test, t_test = iter(test_loader).next()\n", 225 | "x_test, t_test = x_test.cuda(), t_test.cuda()\n", 226 | "for i in range(20): # 20エポック学習\n", 227 | " net.train() # 訓練モード\n", 228 | " loss_train = 0\n", 229 | " for j, (x, t) in enumerate(train_loader): # ミニバッチ(x, t)を取り出す\n", 230 | " x, t = x.cuda(), t.cuda() # GPU対応\n", 231 | " y = net(x)\n", 232 | " loss = loss_fnc(y, t)\n", 233 | " loss_train += loss.item()\n", 234 | " optimizer.zero_grad()\n", 235 | " loss.backward()\n", 236 | " optimizer.step()\n", 237 | " loss_train /= j+1\n", 238 | " record_loss_train.append(loss_train)\n", 239 | "\n", 240 | " net.eval() # 評価モード\n", 241 | " y_test = net(x_test)\n", 242 | " loss_test = loss_fnc(y_test, t_test).item()\n", 243 | " record_loss_test.append(loss_test)\n", 244 | "\n", 245 | " if i%1 == 0:\n", 246 | " print(\"Epoch:\", i, \"Loss_Train:\", loss_train, \"Loss_Test:\", loss_test)" 247 | ], 248 | "execution_count": 0, 249 | "outputs": [] 250 | }, 251 | { 252 | "cell_type": "markdown", 253 | "metadata": { 254 | "id": "rJwwrWTw43rx", 255 | "colab_type": "text" 256 | }, 257 | "source": [ 258 | "## 誤差の推移\n", 259 | "訓練データ、テストデータで誤差の推移をグラフ表示します。 " 260 | ] 261 | }, 262 | { 263 | "cell_type": "code", 264 | "metadata": { 265 | "id": "OaJx4swE45XI", 266 | "colab_type": "code", 267 | "colab": {} 268 | }, 269 | "source": [ 270 | "import matplotlib.pyplot as plt\n", 271 | "\n", 272 | "plt.plot(range(len(record_loss_train)), record_loss_train, label=\"Train\")\n", 273 | "plt.plot(range(len(record_loss_test)), record_loss_test, label=\"Test\")\n", 274 | "plt.legend()\n", 275 | "\n", 276 | "plt.xlabel(\"Epochs\")\n", 277 | "plt.ylabel(\"Error\")\n", 278 | "plt.show()" 279 | ], 280 | "execution_count": 0, 281 | "outputs": [] 282 | }, 283 | { 284 | "cell_type": "markdown", 285 | "metadata": { 286 | "id": "iMrpac0m4Nct", 287 | "colab_type": "text" 288 | }, 289 | "source": [ 290 | "## 正解率\n", 291 | "モデルの性能を把握するため、テストデータ使い正解率を測定します。 " 292 | ] 293 | }, 294 | { 295 | "cell_type": "code", 296 | "metadata": { 297 | "id": "IRkGCYMM_N35", 298 | "colab_type": "code", 299 | "colab": {} 300 | }, 301 | "source": [ 302 | "correct = 0\n", 303 | "total = 0\n", 304 | "net.eval() # 評価モード\n", 305 | "for i, (x, t) in enumerate(test_loader):\n", 306 | " x, t = x.cuda(), t.cuda() # GPU対応\n", 307 | " y = net(x)\n", 308 | " correct += (y.argmax(1) == t).sum().item()\n", 309 | " total += len(x)\n", 310 | "print(\"正解率:\", str(correct/total*100) + \"%\")" 311 | ], 312 | "execution_count": 0, 313 | "outputs": [] 314 | }, 315 | { 316 | "cell_type": "markdown", 317 | "metadata": { 318 | "id": "LrRAJzwD4zpN", 319 | "colab_type": "text" 320 | }, 321 | "source": [ 322 | "## 訓練済みのモデルを使った予測\n", 323 | "画像を入力し、モデルが機能していることを確かめます。" 324 | ] 325 | }, 326 | { 327 | "cell_type": "code", 328 | "metadata": { 329 | "id": "Pdy9nPckTDik", 330 | "colab_type": "code", 331 | "colab": {} 332 | }, 333 | "source": [ 334 | "cifar10_loader = DataLoader(cifar10_test, batch_size=1, shuffle=True)\n", 335 | "dataiter = iter(cifar10_loader)\n", 336 | "images, labels = dataiter.next() # サンプルを1つだけ取り出す\n", 337 | "\n", 338 | "plt.imshow(np.transpose(images[0], (1, 2, 0))) # チャンネルを一番後ろに\n", 339 | "plt.tick_params(labelbottom=False, labelleft=False, bottom=False, left=False) # ラベルとメモリを非表示に\n", 340 | "plt.show()\n", 341 | "\n", 342 | "net.eval() # 評価モード\n", 343 | "x, t = images.cuda(), labels.cuda() # GPU対応\n", 344 | "y = net(x)\n", 345 | "print(\"正解:\", cifar10_classes[labels[0]],\n", 346 | " \"予測結果:\", cifar10_classes[y.argmax().item()])" 347 | ], 348 | "execution_count": 0, 349 | "outputs": [] 350 | }, 351 | { 352 | "cell_type": "markdown", 353 | "metadata": { 354 | "id": "VEBDnUbHZ21y", 355 | "colab_type": "text" 356 | }, 357 | "source": [ 358 | "# 解答例\n", 359 | "以下は、どうしても手がかりがないときのみ参考にしましょう。" 360 | ] 361 | }, 362 | { 363 | "cell_type": "code", 364 | "metadata": { 365 | "id": "JTHeygFKscPI", 366 | "colab_type": "code", 367 | "colab": {} 368 | }, 369 | "source": [ 370 | "from torchvision.datasets import CIFAR10\n", 371 | "import torchvision.transforms as transforms\n", 372 | "from torch.utils.data import DataLoader\n", 373 | "\n", 374 | "affine = transforms.RandomAffine([-15, 15], scale=(0.8, 1.2)) # 回転とリサイズ\n", 375 | "flip = transforms.RandomHorizontalFlip(p=0.5) # 左右反転\n", 376 | "normalize = transforms.Normalize((0.0, 0.0, 0.0), (1.0, 1.0, 1.0)) # 平均値を0、標準偏差を1に\n", 377 | "to_tensor = transforms.ToTensor()\n", 378 | "erase = transforms.RandomErasing(p=0.5) # ← 左にコードを追記\n", 379 | "\n", 380 | "transform_train = transforms.Compose([affine, flip, to_tensor, normalize, erase])\n", 381 | "transform_test = transforms.Compose([to_tensor, normalize])\n", 382 | "cifar10_train = CIFAR10(\"./data\", train=True, download=True, transform=transform_train)\n", 383 | "cifar10_test = CIFAR10(\"./data\", train=False, download=True, transform=transform_test)\n", 384 | "\n", 385 | "# DataLoaderの設定\n", 386 | "batch_size = 64\n", 387 | "train_loader = DataLoader(cifar10_train, batch_size=batch_size, shuffle=True)\n", 388 | "test_loader = DataLoader(cifar10_test, batch_size=len(cifar10_test), shuffle=False)" 389 | ], 390 | "execution_count": 0, 391 | "outputs": [] 392 | }, 393 | { 394 | "cell_type": "code", 395 | "metadata": { 396 | "id": "ZbtDEl0GscZK", 397 | "colab_type": "code", 398 | "colab": {} 399 | }, 400 | "source": [ 401 | "import torch.nn as nn\n", 402 | "import torch.nn.functional as F\n", 403 | "\n", 404 | "class Net(nn.Module):\n", 405 | " def __init__(self):\n", 406 | " super().__init__()\n", 407 | " self.conv1 = nn.Conv2d(3, 8, 5) # 畳み込み層:(入力チャンネル数, フィルタ数、フィルタサイズ)\n", 408 | " self.pool = nn.MaxPool2d(2, 2) # プーリング層:(領域のサイズ, ストライド)\n", 409 | " self.conv2 = nn.Conv2d(8, 32, 5)\n", 410 | " self.fc1 = nn.Linear(32*5*5, 256) # 全結合層\n", 411 | " self.dropout = nn.Dropout(p=0.5) # ドロップアウト:(p=ドロップアウト率)\n", 412 | " self.fc2 = nn.Linear(256, 10)\n", 413 | "\n", 414 | " def forward(self, x):\n", 415 | " # ------- 以下にコードを書く -------\n", 416 | " x = self.pool(F.relu(self.conv1(x)))\n", 417 | " x = self.pool(F.relu(self.conv2(x)))\n", 418 | " x = x.view(-1, 32*5*5)\n", 419 | " x = F.relu(self.fc1(x))\n", 420 | " x = self.dropout(x)\n", 421 | " x = self.fc2(x)\n", 422 | " # ------- ここまで -------\n", 423 | " return x\n", 424 | "\n", 425 | "net = Net()\n", 426 | "net.cuda() # GPU対応\n", 427 | "print(net)" 428 | ], 429 | "execution_count": 0, 430 | "outputs": [] 431 | } 432 | ] 433 | } -------------------------------------------------------------------------------- /lecture5/exercise.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "exercise.ipynb ", 7 | "provenance": [], 8 | "collapsed_sections": [], 9 | "authorship_tag": "ABX9TyN51sbW3YKnL4X3KKU0qU+i", 10 | "include_colab_link": true 11 | }, 12 | "kernelspec": { 13 | "name": "python3", 14 | "display_name": "Python 3" 15 | }, 16 | "accelerator": "GPU" 17 | }, 18 | "cells": [ 19 | { 20 | "cell_type": "markdown", 21 | "metadata": { 22 | "id": "view-in-github", 23 | "colab_type": "text" 24 | }, 25 | "source": [ 26 | "\"Open" 27 | ] 28 | }, 29 | { 30 | "cell_type": "markdown", 31 | "metadata": { 32 | "id": "Niaz8_W6OX34", 33 | "colab_type": "text" 34 | }, 35 | "source": [ 36 | "# 演習\n", 37 | "RNNの層にGRUを使用して、画像の生成を行いましょう。 \n", 38 | "GRUを使用したモデルのクラスを記述します。\n" 39 | ] 40 | }, 41 | { 42 | "cell_type": "markdown", 43 | "metadata": { 44 | "id": "vvRgf3-j2k76", 45 | "colab_type": "text" 46 | }, 47 | "source": [ 48 | "## データの前処理\n", 49 | "画像データをRNNに適した形に整えます。 " 50 | ] 51 | }, 52 | { 53 | "cell_type": "code", 54 | "metadata": { 55 | "id": "bUcJiVtDV7Ad", 56 | "colab_type": "code", 57 | "colab": {} 58 | }, 59 | "source": [ 60 | "import torch\n", 61 | "from torchvision.datasets import FashionMNIST\n", 62 | "import torchvision.transforms as transforms\n", 63 | "from torch.utils.data import DataLoader\n", 64 | "import numpy as np\n", 65 | "import matplotlib.pyplot as plt\n", 66 | "\n", 67 | "img_size = 28\n", 68 | "n_time = 14 # 時系列の数\n", 69 | "n_in = img_size # 入力層のニューロン数\n", 70 | "n_mid = 256 # 中間層のニューロン数\n", 71 | "n_out = img_size # 出力層のニューロン数\n", 72 | "n_sample_in_img = img_size-n_time # 1枚の画像中のサンプル数\n", 73 | "\n", 74 | "fmnist_data = FashionMNIST(root=\"./data\",\n", 75 | " train=True,download=True,\n", 76 | " transform=transforms.ToTensor())\n", 77 | "dataloader = DataLoader(fmnist_data, batch_size=len(fmnist_data), shuffle=False)\n", 78 | "dataiter = iter(dataloader) # イテレータ\n", 79 | "train_imgs, labels = dataiter.next() # データを取り出す\n", 80 | "train_imgs = train_imgs.reshape(-1, img_size, img_size)\n", 81 | "\n", 82 | "n_sample = len(train_imgs) * n_sample_in_img # サンプル数\n", 83 | "\n", 84 | "input_data = np.zeros((n_sample, n_time, n_in)) # 入力\n", 85 | "correct_data = np.zeros((n_sample, n_out)) # 正解\n", 86 | "for i in range(len(train_imgs)):\n", 87 | " for j in range(n_sample_in_img):\n", 88 | " sample_id = i*n_sample_in_img + j\n", 89 | " input_data[sample_id] = train_imgs[i, j:j+n_time]\n", 90 | " correct_data[sample_id] = train_imgs[i, j+n_time]\n", 91 | "\n", 92 | "input_data = torch.tensor(input_data, dtype=torch.float) # テンソルに変換\n", 93 | "correct_data = torch.tensor(correct_data, dtype=torch.float)\n", 94 | "dataset = torch.utils.data.TensorDataset(input_data, correct_data) # データセットの作成\n", 95 | "\n", 96 | "train_loader = DataLoader(dataset, batch_size=128, shuffle=True) # DataLoaderの設定" 97 | ], 98 | "execution_count": 0, 99 | "outputs": [] 100 | }, 101 | { 102 | "cell_type": "markdown", 103 | "metadata": { 104 | "id": "d8pnaugFDnLN", 105 | "colab_type": "text" 106 | }, 107 | "source": [ 108 | "## テスト用のデータ\n", 109 | "今回は、訓練済みのモデルが機能することを確かめるために使用します。" 110 | ] 111 | }, 112 | { 113 | "cell_type": "code", 114 | "metadata": { 115 | "id": "xISsKRTAp7QG", 116 | "colab_type": "code", 117 | "colab": {} 118 | }, 119 | "source": [ 120 | "n_disp = 10 # 生成し表示する画像の数\n", 121 | "\n", 122 | "disp_data = FashionMNIST(root=\"./data\",\n", 123 | " train=False,download=True,\n", 124 | " transform=transforms.ToTensor())\n", 125 | "disp_loader = DataLoader(disp_data, batch_size=n_disp, shuffle=False)\n", 126 | "dataiter = iter(disp_loader) # イテレータ\n", 127 | "disp_imgs, labels = dataiter.next() # データを取り出す\n", 128 | "disp_imgs = disp_imgs.reshape(-1, img_size, img_size)" 129 | ], 130 | "execution_count": 0, 131 | "outputs": [] 132 | }, 133 | { 134 | "cell_type": "markdown", 135 | "metadata": { 136 | "id": "NyLBjYjr3RXu", 137 | "colab_type": "text" 138 | }, 139 | "source": [ 140 | "## 画像生成用の関数\n", 141 | "以下の関数は、オリジナルの画像`disp_imgs`と、この画像の上半分をもとに下半分を生成した`gen_imgs`を並べて表示します。 " 142 | ] 143 | }, 144 | { 145 | "cell_type": "code", 146 | "metadata": { 147 | "id": "dFmq4Oy6apUC", 148 | "colab_type": "code", 149 | "colab": {} 150 | }, 151 | "source": [ 152 | "def generate_images():\n", 153 | " # オリジナルの画像\n", 154 | " print(\"Original:\")\n", 155 | " plt.figure(figsize=(20, 2))\n", 156 | " for i in range(n_disp):\n", 157 | " ax = plt.subplot(1, n_disp, i+1)\n", 158 | " plt.imshow(disp_imgs[i], cmap=\"Greys_r\", vmin=0.0, vmax=1.0)\n", 159 | " ax.get_xaxis().set_visible(False) # 軸を非表示に\n", 160 | " ax.get_yaxis().set_visible(False)\n", 161 | " plt.show()\n", 162 | "\n", 163 | " # 下半分をRNNにより生成した画像\n", 164 | " print(\"Generated:\")\n", 165 | " gen_imgs = disp_imgs.clone()\n", 166 | " plt.figure(figsize=(20, 2))\n", 167 | " for i in range(n_disp):\n", 168 | " for j in range(n_sample_in_img):\n", 169 | " x = gen_imgs[i, j:j+n_time].reshape(1, n_time, img_size)\n", 170 | " x = x.cuda() # GPU対応\n", 171 | " gen_imgs[i, j+n_time] = net(x)[0]\n", 172 | " ax = plt.subplot(1, n_disp, i+1)\n", 173 | " plt.imshow(gen_imgs[i].detach(), cmap=\"Greys_r\", vmin=0.0, vmax=1.0)\n", 174 | " ax.get_xaxis().set_visible(False) # 軸を非表示に\n", 175 | " ax.get_yaxis().set_visible(False)\n", 176 | " plt.show()" 177 | ], 178 | "execution_count": 0, 179 | "outputs": [] 180 | }, 181 | { 182 | "cell_type": "markdown", 183 | "metadata": { 184 | "id": "FalXNYaJPkoE", 185 | "colab_type": "text" 186 | }, 187 | "source": [ 188 | "## モデルの構築\n", 189 | "以下のセルで、Netクラスの内部にコードを記述しGRUを使ったRNNのモデルを構築しましょう。 \n", 190 | "GRUの実装方法は、以下の公式ドキュメントが詳しいです。 \n", 191 | "https://pytorch.org/docs/stable/nn.html#gru" 192 | ] 193 | }, 194 | { 195 | "cell_type": "code", 196 | "metadata": { 197 | "id": "SuqqZmsh_jNK", 198 | "colab_type": "code", 199 | "colab": {} 200 | }, 201 | "source": [ 202 | "import torch.nn as nn\n", 203 | "import torch.nn.functional as F\n", 204 | "\n", 205 | "class Net(nn.Module):\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 | "net = Net()\n", 223 | "net.cuda() # GPU対応\n", 224 | "print(net)" 225 | ], 226 | "execution_count": 0, 227 | "outputs": [] 228 | }, 229 | { 230 | "cell_type": "markdown", 231 | "metadata": { 232 | "id": "qsW5zCKhQE9p", 233 | "colab_type": "text" 234 | }, 235 | "source": [ 236 | "## 学習\n", 237 | "モデルを訓練します。 \n", 238 | "学習には時間がかかりますので、編集→ノートブックの設定のハードウェアアクセラレーターでGPUを選択しましょう。" 239 | ] 240 | }, 241 | { 242 | "cell_type": "code", 243 | "metadata": { 244 | "id": "u6zwN3nArbGC", 245 | "colab_type": "code", 246 | "colab": {} 247 | }, 248 | "source": [ 249 | "from torch import optim\n", 250 | "\n", 251 | "# 交差エントロピー誤差関数\n", 252 | "loss_fnc = nn.MSELoss()\n", 253 | "\n", 254 | "# 最適化アルゴリズム\n", 255 | "optimizer = optim.Adam(net.parameters()) # 学習率は0.01\n", 256 | "\n", 257 | "# 損失のログ\n", 258 | "record_loss_train = []\n", 259 | "\n", 260 | "# 学習\n", 261 | "for i in range(25): # 25エポック学習\n", 262 | " net.train() # 訓練モード\n", 263 | " loss_train = 0\n", 264 | " for j, (x, t) in enumerate(train_loader): # ミニバッチ(x, t)を取り出す\n", 265 | " x, t = x.cuda(), t.cuda() # GPU対応\n", 266 | " y = net(x)\n", 267 | " loss = loss_fnc(y, t)\n", 268 | " loss_train += loss.item()\n", 269 | " optimizer.zero_grad()\n", 270 | " loss.backward()\n", 271 | " optimizer.step()\n", 272 | " loss_train /= j+1\n", 273 | " record_loss_train.append(loss_train)\n", 274 | "\n", 275 | " if i%1 == 0:\n", 276 | " print(\"Epoch:\", i, \"Loss_Train:\", loss_train)\n", 277 | " generate_images()" 278 | ], 279 | "execution_count": 0, 280 | "outputs": [] 281 | }, 282 | { 283 | "cell_type": "markdown", 284 | "metadata": { 285 | "id": "rJwwrWTw43rx", 286 | "colab_type": "text" 287 | }, 288 | "source": [ 289 | "## 誤差の推移\n", 290 | "誤差の推移をグラフ表示します。 " 291 | ] 292 | }, 293 | { 294 | "cell_type": "code", 295 | "metadata": { 296 | "id": "OaJx4swE45XI", 297 | "colab_type": "code", 298 | "colab": {} 299 | }, 300 | "source": [ 301 | "import matplotlib.pyplot as plt\n", 302 | "\n", 303 | "plt.plot(range(len(record_loss_train)), record_loss_train, label=\"Train\")\n", 304 | "plt.legend()\n", 305 | "\n", 306 | "plt.xlabel(\"Epochs\")\n", 307 | "plt.ylabel(\"Error\")\n", 308 | "plt.show()" 309 | ], 310 | "execution_count": 0, 311 | "outputs": [] 312 | }, 313 | { 314 | "cell_type": "markdown", 315 | "metadata": { 316 | "id": "xBNiERnQxexU", 317 | "colab_type": "text" 318 | }, 319 | "source": [ 320 | "# 解答例\n", 321 | "以下は、どうしても手がかりがないときのみ参考にしましょう。" 322 | ] 323 | }, 324 | { 325 | "cell_type": "code", 326 | "metadata": { 327 | "id": "NQDXjjVS3ppJ", 328 | "colab_type": "code", 329 | "colab": {} 330 | }, 331 | "source": [ 332 | "import torch.nn as nn\n", 333 | "import torch.nn.functional as F\n", 334 | "\n", 335 | "class Net(nn.Module):\n", 336 | " # ------- 以下にコードを書く -------\n", 337 | " def __init__(self):\n", 338 | " super().__init__()\n", 339 | " self.rnn = nn.GRU( # GRU層\n", 340 | " input_size=n_in, # 入力サイズ\n", 341 | " hidden_size=n_mid, # ニューロン数\n", 342 | " batch_first=True, # 入力を (バッチサイズ, 時系列の数, 入力の数) にする\n", 343 | " )\n", 344 | " self.fc = nn.Linear(n_mid, n_out) # 全結合層\n", 345 | "\n", 346 | " def forward(self, x):\n", 347 | " y_rnn, h = self.rnn(x, None) # hは次の時刻に渡される値\n", 348 | " y = self.fc(y_rnn[:, -1, :]) # yは最後の時刻の出力\n", 349 | " return y\n", 350 | " # ------- ここまで -------\n", 351 | "\n", 352 | "net = Net()\n", 353 | "net.cuda() # GPU対応\n", 354 | "print(net)" 355 | ], 356 | "execution_count": 0, 357 | "outputs": [] 358 | } 359 | ] 360 | } -------------------------------------------------------------------------------- /lecture5/image_generation.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "image_generation.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [], 9 | "authorship_tag": "ABX9TyP2+3Tx8Fs/SZHWqlxT6h7n", 10 | "include_colab_link": true 11 | }, 12 | "kernelspec": { 13 | "name": "python3", 14 | "display_name": "Python 3" 15 | }, 16 | "accelerator": "GPU" 17 | }, 18 | "cells": [ 19 | { 20 | "cell_type": "markdown", 21 | "metadata": { 22 | "id": "view-in-github", 23 | "colab_type": "text" 24 | }, 25 | "source": [ 26 | "\"Open" 27 | ] 28 | }, 29 | { 30 | "cell_type": "markdown", 31 | "metadata": { 32 | "id": "Niaz8_W6OX34", 33 | "colab_type": "text" 34 | }, 35 | "source": [ 36 | "# RNNによる画像生成\n", 37 | "画像を時系列のデータと捉えることで、RNNにより画像を生成することが可能になります。 \n", 38 | "今回は、画像データを使ってRNNを訓練し、画像の上半分をもとに画像の下半分を生成します。 \n", 39 | "RNNの層にはLSTMを使用します。 \n" 40 | ] 41 | }, 42 | { 43 | "cell_type": "markdown", 44 | "metadata": { 45 | "colab_type": "text", 46 | "id": "LoISGl864sy9" 47 | }, 48 | "source": [ 49 | "## Fashion-MNIST\n", 50 | "torchvision.datasetsを使い、Fashion-MNISTを読み込みます。 \n", 51 | "Fashion-MNISTは、6万枚のファッションアイテム画像にラベルをつけたたデータセットです。 \n", 52 | "以下のコードでは、Fashion-MNISTを読み込み、ランダムな25枚の画像を表示します。" 53 | ] 54 | }, 55 | { 56 | "cell_type": "code", 57 | "metadata": { 58 | "colab_type": "code", 59 | "id": "sQ1S5UNy-rpY", 60 | "colab": {} 61 | }, 62 | "source": [ 63 | "from torchvision.datasets import FashionMNIST\n", 64 | "import torchvision.transforms as transforms\n", 65 | "from torch.utils.data import DataLoader\n", 66 | "import numpy as np\n", 67 | "import matplotlib.pyplot as plt\n", 68 | "\n", 69 | "fmnist_data = FashionMNIST(root=\"./data\",\n", 70 | " train=True,download=True,\n", 71 | " transform=transforms.ToTensor())\n", 72 | "fmnist_classes = np.array([\"T-shirt/top\", \"Trouser\", \"Pullover\", \"Dress\", \"Coat\",\n", 73 | " \"Sandal\", \"Shirt\", \"Sneaker\", \"Bag\", \"Ankle boot\"])\n", 74 | "print(\"データの数:\", len(fmnist_data))\n", 75 | "\n", 76 | "n_image = 25 # 表示する画像の数\n", 77 | "fmnist_loader = DataLoader(fmnist_data, batch_size=n_image, shuffle=True)\n", 78 | "dataiter = iter(fmnist_loader) # イテレータ\n", 79 | "images, labels = dataiter.next() # 最初のバッチを取り出す\n", 80 | "\n", 81 | "img_size = 28\n", 82 | "plt.figure(figsize=(10,10)) # 画像の表示サイズ\n", 83 | "for i in range(n_image):\n", 84 | " plt.subplot(5,5,i+1)\n", 85 | " plt.imshow(images[i].reshape(img_size, img_size), cmap=\"Greys_r\")\n", 86 | " label = fmnist_classes[labels[i]]\n", 87 | " plt.title(label)\n", 88 | " plt.tick_params(labelbottom=False, labelleft=False, bottom=False, left=False) # ラベルとメモリを非表示に\n", 89 | "\n", 90 | "plt.show()" 91 | ], 92 | "execution_count": 0, 93 | "outputs": [] 94 | }, 95 | { 96 | "cell_type": "markdown", 97 | "metadata": { 98 | "id": "vvRgf3-j2k76", 99 | "colab_type": "text" 100 | }, 101 | "source": [ 102 | "## データの前処理\n", 103 | "画像データをRNNに適した形に整えます。 \n", 104 | "画像を時系列データに変換しますが、正解は時系列の次の行にします。 " 105 | ] 106 | }, 107 | { 108 | "cell_type": "code", 109 | "metadata": { 110 | "id": "bUcJiVtDV7Ad", 111 | "colab_type": "code", 112 | "colab": {} 113 | }, 114 | "source": [ 115 | "import torch\n", 116 | "from torch.utils.data import DataLoader\n", 117 | "\n", 118 | "n_time = 14 # 時系列の数\n", 119 | "n_in = img_size # 入力層のニューロン数\n", 120 | "n_mid = 256 # 中間層のニューロン数\n", 121 | "n_out = img_size # 出力層のニューロン数\n", 122 | "n_sample_in_img = img_size-n_time # 1枚の画像中のサンプル数\n", 123 | "\n", 124 | "dataloader = DataLoader(fmnist_data, batch_size=len(fmnist_data), shuffle=False)\n", 125 | "dataiter = iter(dataloader) # イテレータ\n", 126 | "train_imgs, labels = dataiter.next() # データを取り出す\n", 127 | "train_imgs = train_imgs.reshape(-1, img_size, img_size)\n", 128 | "\n", 129 | "n_sample = len(train_imgs) * n_sample_in_img # サンプル数\n", 130 | "\n", 131 | "input_data = np.zeros((n_sample, n_time, n_in)) # 入力\n", 132 | "correct_data = np.zeros((n_sample, n_out)) # 正解\n", 133 | "for i in range(len(train_imgs)):\n", 134 | " for j in range(n_sample_in_img):\n", 135 | " sample_id = i*n_sample_in_img + j\n", 136 | " input_data[sample_id] = train_imgs[i, j:j+n_time]\n", 137 | " correct_data[sample_id] = train_imgs[i, j+n_time]\n", 138 | "\n", 139 | "input_data = torch.tensor(input_data, dtype=torch.float) # テンソルに変換\n", 140 | "correct_data = torch.tensor(correct_data, dtype=torch.float)\n", 141 | "dataset = torch.utils.data.TensorDataset(input_data, correct_data) # データセットの作成\n", 142 | "\n", 143 | "train_loader = DataLoader(dataset, batch_size=128, shuffle=True) # DataLoaderの設定" 144 | ], 145 | "execution_count": 0, 146 | "outputs": [] 147 | }, 148 | { 149 | "cell_type": "markdown", 150 | "metadata": { 151 | "id": "d8pnaugFDnLN", 152 | "colab_type": "text" 153 | }, 154 | "source": [ 155 | "## テスト用のデータ\n", 156 | "今回は、訓練済みのモデルが機能することを確かめるために使用します。" 157 | ] 158 | }, 159 | { 160 | "cell_type": "code", 161 | "metadata": { 162 | "id": "xISsKRTAp7QG", 163 | "colab_type": "code", 164 | "colab": {} 165 | }, 166 | "source": [ 167 | "n_disp = 10 # 生成し表示する画像の数\n", 168 | "\n", 169 | "disp_data = FashionMNIST(root=\"./data\",\n", 170 | " train=False,download=True,\n", 171 | " transform=transforms.ToTensor())\n", 172 | "disp_loader = DataLoader(disp_data, batch_size=n_disp, shuffle=False)\n", 173 | "dataiter = iter(disp_loader) # イテレータ\n", 174 | "disp_imgs, labels = dataiter.next() # データを取り出す\n", 175 | "disp_imgs = disp_imgs.reshape(-1, img_size, img_size)" 176 | ], 177 | "execution_count": 0, 178 | "outputs": [] 179 | }, 180 | { 181 | "cell_type": "markdown", 182 | "metadata": { 183 | "id": "NyLBjYjr3RXu", 184 | "colab_type": "text" 185 | }, 186 | "source": [ 187 | "## 画像生成用の関数\n", 188 | "以下の関数は、オリジナルの画像`disp_imgs`と、この画像の上半分をもとに下半分を生成した`gen_imgs`を並べて表示します。 \n", 189 | "最初は画像の上半分をシードにして新たな行を生成しますが、次はその新たな行を含む直近の時系列からさらに次の行を生成します。 \n", 190 | "これを繰り返すことで、下半分の画像が生成されます。 " 191 | ] 192 | }, 193 | { 194 | "cell_type": "code", 195 | "metadata": { 196 | "id": "dFmq4Oy6apUC", 197 | "colab_type": "code", 198 | "colab": {} 199 | }, 200 | "source": [ 201 | "def generate_images():\n", 202 | " # オリジナルの画像\n", 203 | " print(\"Original:\")\n", 204 | " plt.figure(figsize=(20, 2))\n", 205 | " for i in range(n_disp):\n", 206 | " ax = plt.subplot(1, n_disp, i+1)\n", 207 | " plt.imshow(disp_imgs[i], cmap=\"Greys_r\", vmin=0.0, vmax=1.0)\n", 208 | " ax.get_xaxis().set_visible(False) # 軸を非表示に\n", 209 | " ax.get_yaxis().set_visible(False)\n", 210 | " plt.show()\n", 211 | "\n", 212 | " # 下半分をRNNにより生成した画像\n", 213 | " print(\"Generated:\")\n", 214 | " gen_imgs = disp_imgs.clone()\n", 215 | " plt.figure(figsize=(20, 2))\n", 216 | " for i in range(n_disp):\n", 217 | " for j in range(n_sample_in_img):\n", 218 | " x = gen_imgs[i, j:j+n_time].reshape(1, n_time, img_size)\n", 219 | " x = x.cuda() # GPU対応\n", 220 | " gen_imgs[i, j+n_time] = net(x)[0]\n", 221 | " ax = plt.subplot(1, n_disp, i+1)\n", 222 | " plt.imshow(gen_imgs[i].detach(), cmap=\"Greys_r\", vmin=0.0, vmax=1.0)\n", 223 | " ax.get_xaxis().set_visible(False) # 軸を非表示に\n", 224 | " ax.get_yaxis().set_visible(False)\n", 225 | " plt.show()" 226 | ], 227 | "execution_count": 0, 228 | "outputs": [] 229 | }, 230 | { 231 | "cell_type": "markdown", 232 | "metadata": { 233 | "id": "FalXNYaJPkoE", 234 | "colab_type": "text" 235 | }, 236 | "source": [ 237 | "## モデルの構築\n", 238 | "`nn.Module`モジュールを継承したクラスとして、モデルを構築します。 \n", 239 | "LSTMは`nn.LSTM`を使って実装することができます。" 240 | ] 241 | }, 242 | { 243 | "cell_type": "code", 244 | "metadata": { 245 | "id": "SuqqZmsh_jNK", 246 | "colab_type": "code", 247 | "colab": {} 248 | }, 249 | "source": [ 250 | "import torch.nn as nn\n", 251 | "import torch.nn.functional as F\n", 252 | "\n", 253 | "class Net(nn.Module):\n", 254 | " def __init__(self):\n", 255 | " super().__init__()\n", 256 | " self.rnn = nn.LSTM( # LSTM層\n", 257 | " input_size=n_in, # 入力サイズ\n", 258 | " hidden_size=n_mid, # ニューロン数\n", 259 | " batch_first=True, # 入力を (バッチサイズ, 時系列の数, 入力の数) にする\n", 260 | " )\n", 261 | " self.fc = nn.Linear(n_mid, n_out) # 全結合層\n", 262 | "\n", 263 | " def forward(self, x):\n", 264 | " y_rnn, (h, c) = self.rnn(x, None) # hは次の時刻に渡される値、 cは記憶セル\n", 265 | " y = self.fc(y_rnn[:, -1, :]) # yは最後の時刻の出力\n", 266 | " return y\n", 267 | "\n", 268 | "net = Net()\n", 269 | "net.cuda() # GPU対応\n", 270 | "print(net)" 271 | ], 272 | "execution_count": 0, 273 | "outputs": [] 274 | }, 275 | { 276 | "cell_type": "markdown", 277 | "metadata": { 278 | "id": "qsW5zCKhQE9p", 279 | "colab_type": "text" 280 | }, 281 | "source": [ 282 | "## 学習\n", 283 | "モデルを訓練します。 \n", 284 | "DataLoaderを使い、ミニバッチを取り出して訓練および評価を行います。 \n", 285 | "学習中、一定のエポック間隔ごとに誤差の表示と画像の生成が行われます。 \n", 286 | "学習には時間がかかりますので、編集→ノートブックの設定のハードウェアアクセラレーターでGPUを選択しましょう。" 287 | ] 288 | }, 289 | { 290 | "cell_type": "code", 291 | "metadata": { 292 | "id": "u6zwN3nArbGC", 293 | "colab_type": "code", 294 | "colab": {} 295 | }, 296 | "source": [ 297 | "from torch import optim\n", 298 | "\n", 299 | "# 交差エントロピー誤差関数\n", 300 | "loss_fnc = nn.MSELoss()\n", 301 | "\n", 302 | "# 最適化アルゴリズム\n", 303 | "optimizer = optim.Adam(net.parameters()) # 学習率は0.01\n", 304 | "\n", 305 | "# 損失のログ\n", 306 | "record_loss_train = []\n", 307 | "\n", 308 | "# 学習\n", 309 | "for i in range(25): # 25エポック学習\n", 310 | " net.train() # 訓練モード\n", 311 | " loss_train = 0\n", 312 | " for j, (x, t) in enumerate(train_loader): # ミニバッチ(x, t)を取り出す\n", 313 | " x, t = x.cuda(), t.cuda() # GPU対応\n", 314 | " y = net(x)\n", 315 | " loss = loss_fnc(y, t)\n", 316 | " loss_train += loss.item()\n", 317 | " optimizer.zero_grad()\n", 318 | " loss.backward()\n", 319 | " optimizer.step()\n", 320 | " loss_train /= j+1\n", 321 | " record_loss_train.append(loss_train)\n", 322 | "\n", 323 | " if i%1 == 0:\n", 324 | " print(\"Epoch:\", i, \"Loss_Train:\", loss_train)\n", 325 | " generate_images()" 326 | ], 327 | "execution_count": 0, 328 | "outputs": [] 329 | }, 330 | { 331 | "cell_type": "markdown", 332 | "metadata": { 333 | "id": "rJwwrWTw43rx", 334 | "colab_type": "text" 335 | }, 336 | "source": [ 337 | "## 誤差の推移\n", 338 | "誤差の推移をグラフ表示します。 " 339 | ] 340 | }, 341 | { 342 | "cell_type": "code", 343 | "metadata": { 344 | "id": "OaJx4swE45XI", 345 | "colab_type": "code", 346 | "colab": {} 347 | }, 348 | "source": [ 349 | "import matplotlib.pyplot as plt\n", 350 | "\n", 351 | "plt.plot(range(len(record_loss_train)), record_loss_train, label=\"Train\")\n", 352 | "plt.legend()\n", 353 | "\n", 354 | "plt.xlabel(\"Epochs\")\n", 355 | "plt.ylabel(\"Error\")\n", 356 | "plt.show()" 357 | ], 358 | "execution_count": 0, 359 | "outputs": [] 360 | }, 361 | { 362 | "cell_type": "markdown", 363 | "metadata": { 364 | "id": "iMrpac0m4Nct", 365 | "colab_type": "text" 366 | }, 367 | "source": [ 368 | "滑らかに誤差が減少していることが確認できます。" 369 | ] 370 | } 371 | ] 372 | } -------------------------------------------------------------------------------- /lecture5/simple_rnn.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "colab_type": "text", 7 | "id": "view-in-github" 8 | }, 9 | "source": [ 10 | "\"Open" 11 | ] 12 | }, 13 | { 14 | "cell_type": "markdown", 15 | "metadata": { 16 | "colab_type": "text", 17 | "id": "Niaz8_W6OX34" 18 | }, 19 | "source": [ 20 | "# シンプルなRNNの実装\n", 21 | "PyTorchを使って、シンプルな再帰型ニューラルネットワーク(RNN)を実装します。 \n", 22 | "RNNにノイズ付きサインカーブを学習させて、1つ先の未来を予測することによる曲線の描画を行います。\n" 23 | ] 24 | }, 25 | { 26 | "cell_type": "markdown", 27 | "metadata": { 28 | "colab_type": "text", 29 | "id": "LoISGl864sy9" 30 | }, 31 | "source": [ 32 | "## 訓練用データの作成\n", 33 | "まずは、サインカーブに乱数でノイズを加えてRNNに用いる訓練用のデータを作成します。" 34 | ] 35 | }, 36 | { 37 | "cell_type": "code", 38 | "execution_count": null, 39 | "metadata": { 40 | "colab": {}, 41 | "colab_type": "code", 42 | "id": "sQ1S5UNy-rpY" 43 | }, 44 | "outputs": [], 45 | "source": [ 46 | "import numpy as np\n", 47 | "import matplotlib.pyplot as plt\n", 48 | "\n", 49 | "sin_x = np.linspace(-2*np.pi, 2*np.pi) # -2πから2πまで\n", 50 | "sin_y = np.sin(sin_x) + 0.1*np.random.randn(len(sin_x)) # sin関数に乱数でノイズを加える\n", 51 | "plt.plot(sin_x, sin_y)\n", 52 | "plt.show()" 53 | ] 54 | }, 55 | { 56 | "cell_type": "markdown", 57 | "metadata": { 58 | "colab_type": "text", 59 | "id": "NyLBjYjr3RXu" 60 | }, 61 | "source": [ 62 | "このようなノイズ付きサインカーブの一部を切り取って入力の時系列とし、次の値を予測するようにRNNを訓練します。 \n", 63 | "sin波自体は単純な時系列データですが、このようなsin波をニューラルネットワークで学習することができれば、例えば音声認識などに応用することも可能です。 \n", 64 | "今回の扱う対象はシンプルですが、現実社会で広く応用が可能することができます。" 65 | ] 66 | }, 67 | { 68 | "cell_type": "markdown", 69 | "metadata": { 70 | "colab_type": "text", 71 | "id": "vvRgf3-j2k76" 72 | }, 73 | "source": [ 74 | "## データの前処理\n", 75 | "入力、正解データをRNNに適した形に整えます。 \n", 76 | "時系列から次の値を予測できるように、時系列を入力として正解はその1つ後の値とします。 " 77 | ] 78 | }, 79 | { 80 | "cell_type": "code", 81 | "execution_count": null, 82 | "metadata": { 83 | "colab": {}, 84 | "colab_type": "code", 85 | "id": "dFmq4Oy6apUC" 86 | }, 87 | "outputs": [], 88 | "source": [ 89 | "import torch\n", 90 | "from torch.utils.data import DataLoader\n", 91 | "\n", 92 | "n_time = 10 # 時系列の数\n", 93 | "n_sample = len(sin_x)-n_time # サンプル数\n", 94 | "\n", 95 | "input_data = np.zeros((n_sample, n_time, 1)) # 入力\n", 96 | "correct_data = np.zeros((n_sample, 1)) # 正解\n", 97 | "for i in range(n_sample):\n", 98 | " input_data[i] = sin_y[i:i+n_time].reshape(-1, 1)\n", 99 | " correct_data[i] = sin_y[i+n_time:i+n_time+1] # 正解は入力よりも一つ後\n", 100 | "\n", 101 | "input_data = torch.tensor(input_data, dtype=torch.float) # テンソルに変換\n", 102 | "correct_data = torch.tensor(correct_data, dtype=torch.float)\n", 103 | "dataset = torch.utils.data.TensorDataset(input_data, correct_data) # データセットの作成\n", 104 | "\n", 105 | "train_loader = DataLoader(dataset, batch_size=8, shuffle=True) # DataLoaderの設定" 106 | ] 107 | }, 108 | { 109 | "cell_type": "markdown", 110 | "metadata": { 111 | "colab_type": "text", 112 | "id": "FalXNYaJPkoE" 113 | }, 114 | "source": [ 115 | "## モデルの構築\n", 116 | "`nn.Module`モジュールを継承したクラスとして、モデルを構築します。 \n", 117 | "RNNは`nn.RNN`を使って実装することができます。" 118 | ] 119 | }, 120 | { 121 | "cell_type": "code", 122 | "execution_count": null, 123 | "metadata": { 124 | "colab": {}, 125 | "colab_type": "code", 126 | "id": "SuqqZmsh_jNK" 127 | }, 128 | "outputs": [], 129 | "source": [ 130 | "import torch.nn as nn\n", 131 | "import torch.nn.functional as F\n", 132 | "\n", 133 | "class Net(nn.Module):\n", 134 | " def __init__(self):\n", 135 | " super().__init__()\n", 136 | " self.rnn = nn.RNN( # RNN層\n", 137 | " input_size=1, # 入力サイズ\n", 138 | " hidden_size=64, # ニューロン数\n", 139 | " batch_first=True, # 入力を (バッチサイズ, 時系列の数, 入力の数) にする\n", 140 | " )\n", 141 | " self.fc = nn.Linear(64, 1) # 全結合層\n", 142 | "\n", 143 | " def forward(self, x):\n", 144 | " y_rnn, h = self.rnn(x, None) # hは次の時刻に渡される値、 Noneでその初期値が0に\n", 145 | " y = self.fc(y_rnn[:, -1, :]) # yは最後の時刻の出力\n", 146 | " return y\n", 147 | "\n", 148 | "net = Net()\n", 149 | "print(net)" 150 | ] 151 | }, 152 | { 153 | "cell_type": "markdown", 154 | "metadata": { 155 | "colab_type": "text", 156 | "id": "qsW5zCKhQE9p" 157 | }, 158 | "source": [ 159 | "## 学習\n", 160 | "モデルを訓練します。 \n", 161 | "DataLoaderを使い、ミニバッチを取り出して訓練および評価を行います。 \n", 162 | "訓練したモデルを使い、直近の時系列を使った予測結果を次々と時系列に加えていくことにより、曲線が生成されます。 \n", 163 | "学習が進むとともに次第にサインカーブが生成されるようになりますが、曲線は一定のエポック間隔でグラフとして描画されます。 " 164 | ] 165 | }, 166 | { 167 | "cell_type": "code", 168 | "execution_count": null, 169 | "metadata": { 170 | "colab": {}, 171 | "colab_type": "code", 172 | "id": "u6zwN3nArbGC" 173 | }, 174 | "outputs": [], 175 | "source": [ 176 | "from torch import optim\n", 177 | "\n", 178 | "# 平均二乗誤差関数\n", 179 | "loss_fnc = nn.MSELoss()\n", 180 | "\n", 181 | "# 最適化アルゴリズム\n", 182 | "optimizer = optim.SGD(net.parameters(), lr=0.01) # 学習率は0.01\n", 183 | "\n", 184 | "# 損失のログ\n", 185 | "record_loss_train = []\n", 186 | "\n", 187 | "# 学習\n", 188 | "for i in range(50): # 50エポック学習\n", 189 | " net.train() # 訓練モード\n", 190 | " loss_train = 0\n", 191 | " for j, (x, t) in enumerate(train_loader): # ミニバッチ(x, t)を取り出す\n", 192 | " y = net(x)\n", 193 | " loss = loss_fnc(y, t)\n", 194 | " loss_train += loss.item()\n", 195 | " optimizer.zero_grad()\n", 196 | " loss.backward()\n", 197 | " optimizer.step()\n", 198 | " loss_train /= j+1\n", 199 | " record_loss_train.append(loss_train)\n", 200 | "\n", 201 | " if i%2 == 0:\n", 202 | " print(\"Epoch:\", i, \"Loss_Train:\", loss_train)\n", 203 | " predicted = list(input_data[0].reshape(-1)) # 最初の入力\n", 204 | " for i in range(n_sample):\n", 205 | " x = torch.tensor(predicted[-n_time:]) # 直近の時系列を取り出す\n", 206 | " x = x.reshape(1, n_time, 1) # (バッチサイズ, 時系列の数, 入力の数)\n", 207 | " y = net(x)\n", 208 | " predicted.append(y[0].item()) # 予測結果をpredictedに追加する\n", 209 | "\n", 210 | " plt.plot(range(len(sin_y)), sin_y, label=\"Correct\")\n", 211 | " plt.plot(range(len(predicted)), predicted, label=\"Predicted\")\n", 212 | " plt.legend()\n", 213 | " plt.show()\n", 214 | " " 215 | ] 216 | }, 217 | { 218 | "cell_type": "markdown", 219 | "metadata": { 220 | "colab_type": "text", 221 | "id": "rJwwrWTw43rx" 222 | }, 223 | "source": [ 224 | "## 誤差の推移\n", 225 | "訓練データ、テストデータで誤差の推移をグラフ表示します。 " 226 | ] 227 | }, 228 | { 229 | "cell_type": "code", 230 | "execution_count": null, 231 | "metadata": { 232 | "colab": {}, 233 | "colab_type": "code", 234 | "id": "OaJx4swE45XI" 235 | }, 236 | "outputs": [], 237 | "source": [ 238 | "import matplotlib.pyplot as plt\n", 239 | "\n", 240 | "plt.plot(range(len(record_loss_train)), record_loss_train, label=\"Train\")\n", 241 | "plt.legend()\n", 242 | "\n", 243 | "plt.xlabel(\"Epochs\")\n", 244 | "plt.ylabel(\"Error\")\n", 245 | "plt.show()" 246 | ] 247 | }, 248 | { 249 | "cell_type": "markdown", 250 | "metadata": { 251 | "colab_type": "text", 252 | "id": "iMrpac0m4Nct" 253 | }, 254 | "source": [ 255 | "滑らかに誤差が減少していることが確認できます。" 256 | ] 257 | } 258 | ], 259 | "metadata": { 260 | "colab": { 261 | "authorship_tag": "ABX9TyPEtjK7A8DPxbWUXkqmaSUU", 262 | "collapsed_sections": [], 263 | "include_colab_link": true, 264 | "name": "simple_rnn.ipynb", 265 | "provenance": [] 266 | }, 267 | "kernelspec": { 268 | "display_name": "Python 3 (ipykernel)", 269 | "language": "python", 270 | "name": "python3" 271 | }, 272 | "language_info": { 273 | "codemirror_mode": { 274 | "name": "ipython", 275 | "version": 3 276 | }, 277 | "file_extension": ".py", 278 | "mimetype": "text/x-python", 279 | "name": "python", 280 | "nbconvert_exporter": "python", 281 | "pygments_lexer": "ipython3", 282 | "version": "3.9.6" 283 | } 284 | }, 285 | "nbformat": 4, 286 | "nbformat_minor": 4 287 | } 288 | -------------------------------------------------------------------------------- /lecture6/classifier/Procfile: -------------------------------------------------------------------------------- 1 | web: gunicorn classifier:app --log-file - -------------------------------------------------------------------------------- /lecture6/classifier/classifier.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, request, redirect, url_for, render_template, Markup 2 | from werkzeug.utils import secure_filename 3 | 4 | import torch 5 | import torch.nn as nn 6 | import torch.nn.functional as F 7 | import torchvision.transforms as transforms 8 | 9 | import os 10 | import shutil 11 | from PIL import Image 12 | import numpy as np 13 | 14 | UPLOAD_FOLDER = "./static/images/" 15 | ALLOWED_EXTENSIONS = {"png", "jpg", "jpeg", "gif"} 16 | 17 | labels = ["飛行機", "自動車", "鳥", "猫", "鹿", "犬", "カエル", "馬", "船", "トラック"] 18 | n_class = len(labels) 19 | img_size = 32 20 | n_result = 3 # 上位3つの結果を表示 21 | 22 | app = Flask(__name__) 23 | app.config["UPLOAD_FOLDER"] = UPLOAD_FOLDER 24 | 25 | 26 | class Net(nn.Module): 27 | def __init__(self): 28 | super().__init__() 29 | self.conv1 = nn.Conv2d(3, 6, 5) 30 | self.pool = nn.MaxPool2d(2, 2) 31 | self.conv2 = nn.Conv2d(6, 16, 5) 32 | self.fc1 = nn.Linear(16*5*5, 256) 33 | self.dropout = nn.Dropout(p=0.5) 34 | self.fc2 = nn.Linear(256, 10) 35 | 36 | def forward(self, x): 37 | x = self.pool(F.relu(self.conv1(x))) 38 | x = self.pool(F.relu(self.conv2(x))) 39 | x = x.view(-1, 16*5*5) 40 | x = F.relu(self.fc1(x)) 41 | x = self.dropout(x) 42 | x = self.fc2(x) 43 | return x 44 | 45 | 46 | def allowed_file(filename): 47 | return "." in filename and filename.rsplit(".", 1)[1].lower() in ALLOWED_EXTENSIONS 48 | 49 | 50 | @app.route("/", methods=["GET", "POST"]) 51 | def index(): 52 | return render_template("index.html") 53 | 54 | 55 | @app.route("/result", methods=["GET", "POST"]) 56 | def result(): 57 | if request.method == "POST": 58 | # ファイルの存在と形式を確認 59 | if "file" not in request.files: 60 | print("File doesn't exist!") 61 | return redirect(url_for("index")) 62 | file = request.files["file"] 63 | if not allowed_file(file.filename): 64 | print(file.filename + ": File not allowed!") 65 | return redirect(url_for("index")) 66 | 67 | # ファイルの保存 68 | if os.path.isdir(UPLOAD_FOLDER): 69 | shutil.rmtree(UPLOAD_FOLDER) 70 | os.mkdir(UPLOAD_FOLDER) 71 | filename = secure_filename(file.filename) # ファイル名を安全なものに 72 | filepath = os.path.join(UPLOAD_FOLDER, filename) 73 | file.save(filepath) 74 | 75 | # 画像の読み込み 76 | image = Image.open(filepath) 77 | image = image.convert("RGB") 78 | image = image.resize((img_size, img_size)) 79 | 80 | normalize = transforms.Normalize( 81 | (0.0, 0.0, 0.0), (1.0, 1.0, 1.0)) # 平均値を0、標準偏差を1に 82 | to_tensor = transforms.ToTensor() 83 | transform = transforms.Compose([to_tensor, normalize]) 84 | 85 | x = transform(image) 86 | x = x.reshape(1, 3, img_size, img_size) 87 | 88 | # 予測 89 | net = Net() 90 | net.load_state_dict(torch.load( 91 | "model_cnn.pth", map_location=torch.device("cpu"))) 92 | net.eval() # 評価モード 93 | 94 | y = net(x) 95 | y = F.softmax(y, dim=1)[0] 96 | sorted_idx = torch.argsort(-y) # 降順でソート 97 | result = "" 98 | for i in range(n_result): 99 | idx = sorted_idx[i].item() 100 | ratio = y[idx].item() 101 | label = labels[idx] 102 | result += "

" + str(round(ratio*100, 1)) + \ 103 | "%の確率で" + label + "です。

" 104 | return render_template("result.html", result=Markup(result), filepath=filepath) 105 | else: 106 | return redirect(url_for("index")) 107 | 108 | 109 | if __name__ == "__main__": 110 | app.run(debug=True) 111 | -------------------------------------------------------------------------------- /lecture6/classifier/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask==1.1.2 2 | Jinja2==2.11.2 3 | Werkzeug==1.0.1 4 | gunicorn==20.0.4 5 | numpy==1.18.1 6 | Pillow==7.1.2 7 | http://download.pytorch.org/whl/cpu/torch-1.3.1%2Bcpu-cp37-cp37m-linux_x86_64.whl 8 | torchvision==0.4.2 9 | -------------------------------------------------------------------------------- /lecture6/classifier/runtime.txt: -------------------------------------------------------------------------------- 1 | python-3.7.7 -------------------------------------------------------------------------------- /lecture6/classifier/static/images/truck.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yukinaga/lecture_pytorch/22e7a1d5dab29937fa4d2f574ee1ef1b58fbd065/lecture6/classifier/static/images/truck.jpg -------------------------------------------------------------------------------- /lecture6/classifier/templates/index.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block content %} 3 |
4 |
5 |

画像分類

6 |
7 | 8 | 9 |
10 |
11 |
12 | {% endblock %} -------------------------------------------------------------------------------- /lecture6/classifier/templates/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 画像分類 7 | 8 | 24 | 25 | 26 | {% block content %} 27 | {% endblock %} 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /lecture6/classifier/templates/result.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block content %} 3 |
4 |
5 |

判定結果

6 | {{result}} 7 |

8 |
9 | 10 |
11 |
12 |
13 | {% endblock %} -------------------------------------------------------------------------------- /lecture6/train_cnn.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "train_cnn.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [], 9 | "toc_visible": true, 10 | "authorship_tag": "ABX9TyOJ+KINLtonDAWtNCBRK2dD", 11 | "include_colab_link": true 12 | }, 13 | "kernelspec": { 14 | "name": "python3", 15 | "display_name": "Python 3" 16 | }, 17 | "accelerator": "GPU" 18 | }, 19 | "cells": [ 20 | { 21 | "cell_type": "markdown", 22 | "metadata": { 23 | "id": "view-in-github", 24 | "colab_type": "text" 25 | }, 26 | "source": [ 27 | "\"Open" 28 | ] 29 | }, 30 | { 31 | "cell_type": "markdown", 32 | "metadata": { 33 | "id": "Niaz8_W6OX34", 34 | "colab_type": "text" 35 | }, 36 | "source": [ 37 | "# モデルの訓練\n", 38 | "画像識別アプリで使用する、CNNのモデルを訓練し保存します。 \n", 39 | "今回は訓練データにCIFAR-10を使用します。 \n" 40 | ] 41 | }, 42 | { 43 | "cell_type": "markdown", 44 | "metadata": { 45 | "id": "vsncPqQ-gZJr", 46 | "colab_type": "text" 47 | }, 48 | "source": [ 49 | "## データの前処理\n", 50 | "CIFAR-10を読み込んで、データ拡張とともにDataLoaderの設定を行います。 " 51 | ] 52 | }, 53 | { 54 | "cell_type": "code", 55 | "metadata": { 56 | "id": "7t3NRHjhKyC0", 57 | "colab_type": "code", 58 | "colab": {} 59 | }, 60 | "source": [ 61 | "from torchvision.datasets import CIFAR10\n", 62 | "import torchvision.transforms as transforms\n", 63 | "from torch.utils.data import DataLoader\n", 64 | "\n", 65 | "affine = transforms.RandomAffine([-15, 15], scale=(0.8, 1.2)) # 回転とリサイズ\n", 66 | "flip = transforms.RandomHorizontalFlip(p=0.5) # 左右反転\n", 67 | "normalize = transforms.Normalize((0.0, 0.0, 0.0), (1.0, 1.0, 1.0)) # 平均値を0、標準偏差を1に\n", 68 | "to_tensor = transforms.ToTensor()\n", 69 | "\n", 70 | "transform_train = transforms.Compose([affine, flip, to_tensor, normalize])\n", 71 | "transform_test = transforms.Compose([to_tensor, normalize])\n", 72 | "cifar10_train = CIFAR10(\"./data\", train=True, download=True, transform=transform_train)\n", 73 | "cifar10_test = CIFAR10(\"./data\", train=False, download=True, transform=transform_test)\n", 74 | "\n", 75 | "# DataLoaderの設定\n", 76 | "batch_size = 64\n", 77 | "train_loader = DataLoader(cifar10_train, batch_size=batch_size, shuffle=True)\n", 78 | "test_loader = DataLoader(cifar10_test, batch_size=len(cifar10_test), shuffle=False)" 79 | ], 80 | "execution_count": 0, 81 | "outputs": [] 82 | }, 83 | { 84 | "cell_type": "markdown", 85 | "metadata": { 86 | "id": "FalXNYaJPkoE", 87 | "colab_type": "text" 88 | }, 89 | "source": [ 90 | "## モデルの構築\n", 91 | "`nn.Module`モジュールを継承したクラスとして、CNNのモデルを構築します。 " 92 | ] 93 | }, 94 | { 95 | "cell_type": "code", 96 | "metadata": { 97 | "id": "SuqqZmsh_jNK", 98 | "colab_type": "code", 99 | "colab": {} 100 | }, 101 | "source": [ 102 | "import torch.nn as nn\n", 103 | "import torch.nn.functional as F\n", 104 | "\n", 105 | "class Net(nn.Module):\n", 106 | " def __init__(self):\n", 107 | " super().__init__()\n", 108 | " self.conv1 = nn.Conv2d(3, 6, 5) # 畳み込み層:(入力チャンネル数, フィルタ数、フィルタサイズ)\n", 109 | " self.pool = nn.MaxPool2d(2, 2) # プーリング層:(領域のサイズ, ストライド)\n", 110 | " self.conv2 = nn.Conv2d(6, 16, 5)\n", 111 | " self.fc1 = nn.Linear(16*5*5, 256) # 全結合層\n", 112 | " self.dropout = nn.Dropout(p=0.5) # ドロップアウト:(p=ドロップアウト率)\n", 113 | " self.fc2 = nn.Linear(256, 10)\n", 114 | "\n", 115 | " def forward(self, x):\n", 116 | " x = self.pool(F.relu(self.conv1(x)))\n", 117 | " x = self.pool(F.relu(self.conv2(x)))\n", 118 | " x = x.view(-1, 16*5*5)\n", 119 | " x = F.relu(self.fc1(x))\n", 120 | " x = self.dropout(x)\n", 121 | " x = self.fc2(x)\n", 122 | " return x\n", 123 | "\n", 124 | "net = Net()\n", 125 | "net.cuda() # GPU対応\n", 126 | "print(net)" 127 | ], 128 | "execution_count": 0, 129 | "outputs": [] 130 | }, 131 | { 132 | "cell_type": "markdown", 133 | "metadata": { 134 | "id": "qsW5zCKhQE9p", 135 | "colab_type": "text" 136 | }, 137 | "source": [ 138 | "## 学習\n", 139 | "モデルを訓練します。 \n", 140 | "学習には時間がかかりますので、編集→ノートブックの設定のハードウェアアクセラレーターでGPUを選択しましょう。\n" 141 | ] 142 | }, 143 | { 144 | "cell_type": "code", 145 | "metadata": { 146 | "id": "u6zwN3nArbGC", 147 | "colab_type": "code", 148 | "colab": {} 149 | }, 150 | "source": [ 151 | "from torch import optim\n", 152 | "\n", 153 | "# 交差エントロピー誤差関数\n", 154 | "loss_fnc = nn.CrossEntropyLoss()\n", 155 | "\n", 156 | "# 最適化アルゴリズム\n", 157 | "optimizer = optim.Adam(net.parameters())\n", 158 | "\n", 159 | "# 損失のログ\n", 160 | "record_loss_train = []\n", 161 | "record_loss_test = []\n", 162 | "\n", 163 | "# 学習\n", 164 | "x_test, t_test = iter(test_loader).next()\n", 165 | "x_test, t_test = x_test.cuda(), t_test.cuda()\n", 166 | "for i in range(20): # 20エポック学習\n", 167 | " net.train() # 訓練モード\n", 168 | " loss_train = 0\n", 169 | " for j, (x, t) in enumerate(train_loader): # ミニバッチ(x, t)を取り出す\n", 170 | " x, t = x.cuda(), t.cuda() # GPU対応\n", 171 | " y = net(x)\n", 172 | " loss = loss_fnc(y, t)\n", 173 | " loss_train += loss.item()\n", 174 | " optimizer.zero_grad()\n", 175 | " loss.backward()\n", 176 | " optimizer.step()\n", 177 | " loss_train /= j+1\n", 178 | " record_loss_train.append(loss_train)\n", 179 | "\n", 180 | " net.eval() # 評価モード\n", 181 | " y_test = net(x_test)\n", 182 | " loss_test = loss_fnc(y_test, t_test).item()\n", 183 | " record_loss_test.append(loss_test)\n", 184 | "\n", 185 | " if i%1 == 0:\n", 186 | " print(\"Epoch:\", i, \"Loss_Train:\", loss_train, \"Loss_Test:\", loss_test)" 187 | ], 188 | "execution_count": 0, 189 | "outputs": [] 190 | }, 191 | { 192 | "cell_type": "markdown", 193 | "metadata": { 194 | "id": "rJwwrWTw43rx", 195 | "colab_type": "text" 196 | }, 197 | "source": [ 198 | "## 誤差の推移\n", 199 | "訓練データ、テストデータで誤差の推移をグラフ表示します。 " 200 | ] 201 | }, 202 | { 203 | "cell_type": "code", 204 | "metadata": { 205 | "id": "OaJx4swE45XI", 206 | "colab_type": "code", 207 | "colab": {} 208 | }, 209 | "source": [ 210 | "import matplotlib.pyplot as plt\n", 211 | "\n", 212 | "plt.plot(range(len(record_loss_train)), record_loss_train, label=\"Train\")\n", 213 | "plt.plot(range(len(record_loss_test)), record_loss_test, label=\"Test\")\n", 214 | "plt.legend()\n", 215 | "\n", 216 | "plt.xlabel(\"Epochs\")\n", 217 | "plt.ylabel(\"Error\")\n", 218 | "plt.show()" 219 | ], 220 | "execution_count": 0, 221 | "outputs": [] 222 | }, 223 | { 224 | "cell_type": "markdown", 225 | "metadata": { 226 | "id": "iMrpac0m4Nct", 227 | "colab_type": "text" 228 | }, 229 | "source": [ 230 | "## 正解率\n", 231 | "モデルの性能を把握するため、テストデータ使い正解率を測定します。 " 232 | ] 233 | }, 234 | { 235 | "cell_type": "code", 236 | "metadata": { 237 | "id": "IRkGCYMM_N35", 238 | "colab_type": "code", 239 | "colab": {} 240 | }, 241 | "source": [ 242 | "correct = 0\n", 243 | "total = 0\n", 244 | "net.eval() # 評価モード\n", 245 | "for i, (x, t) in enumerate(test_loader):\n", 246 | " x, t = x.cuda(), t.cuda() # GPU対応\n", 247 | " y = net(x)\n", 248 | " correct += (y.argmax(1) == t).sum().item()\n", 249 | " total += len(x)\n", 250 | "print(\"正解率:\", str(correct/total*100) + \"%\")" 251 | ], 252 | "execution_count": 0, 253 | "outputs": [] 254 | }, 255 | { 256 | "cell_type": "markdown", 257 | "metadata": { 258 | "id": "LrRAJzwD4zpN", 259 | "colab_type": "text" 260 | }, 261 | "source": [ 262 | "## モデルの保存\n", 263 | "訓練済みモデルのパラメータを保存します。 \n", 264 | "`state_dict()`によりモデルの各パラメータが取得できるので、これを保存します。" 265 | ] 266 | }, 267 | { 268 | "cell_type": "code", 269 | "metadata": { 270 | "id": "Pdy9nPckTDik", 271 | "colab_type": "code", 272 | "colab": {} 273 | }, 274 | "source": [ 275 | "import torch\n", 276 | "\n", 277 | "# state_dict()の表示\n", 278 | "for key in net.state_dict():\n", 279 | " print(key, \": \", net.state_dict()[key].size())\n", 280 | "print(net.state_dict()[\"conv1.weight\"][0]) #  パラメータの一部を表示\n", 281 | "\n", 282 | "# 保存\n", 283 | "torch.save(net.state_dict(), \"model_cnn.pth\") " 284 | ], 285 | "execution_count": 0, 286 | "outputs": [] 287 | }, 288 | { 289 | "cell_type": "markdown", 290 | "metadata": { 291 | "id": "stRWVWyGJwYN", 292 | "colab_type": "text" 293 | }, 294 | "source": [ 295 | "## モデルの読み込み\n", 296 | "保存したパラメータを読み込み、モデルに設定します。 \n", 297 | "`torch.load()`で`map_location`にCPUを指定することで、GPUで訓練したモデルをCPUで使用することが可能になります。 \n" 298 | ] 299 | }, 300 | { 301 | "cell_type": "code", 302 | "metadata": { 303 | "id": "pfHfzp_fBgHw", 304 | "colab_type": "code", 305 | "colab": {} 306 | }, 307 | "source": [ 308 | "# 読み込み\n", 309 | "net_loaded = Net()\n", 310 | "net_loaded.load_state_dict(torch.load(\"model_cnn.pth\", map_location=torch.device(\"cpu\"))) #CPU対応\n", 311 | "net_loaded.eval() # 評価モード\n", 312 | "\n", 313 | "# state_dict()の表示\n", 314 | "for key in net_loaded.state_dict():\n", 315 | " print(key, \": \", net.state_dict()[key].size())\n", 316 | "print(net_loaded.state_dict()[\"conv1.weight\"][0]) #  パラメータの一部を表示" 317 | ], 318 | "execution_count": 0, 319 | "outputs": [] 320 | }, 321 | { 322 | "cell_type": "markdown", 323 | "metadata": { 324 | "id": "N8hAIcYLJnA1", 325 | "colab_type": "text" 326 | }, 327 | "source": [ 328 | "モデルの各パラメータを保存し、読み込むことができました。" 329 | ] 330 | } 331 | ] 332 | } -------------------------------------------------------------------------------- /python_basic/01_python_basic_1.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "kernelspec": { 6 | "display_name": "Python 3", 7 | "language": "python", 8 | "name": "python3" 9 | }, 10 | "language_info": { 11 | "codemirror_mode": { 12 | "name": "ipython", 13 | "version": 3 14 | }, 15 | "file_extension": ".py", 16 | "mimetype": "text/x-python", 17 | "name": "python", 18 | "nbconvert_exporter": "python", 19 | "pygments_lexer": "ipython3", 20 | "version": "3.5.4" 21 | }, 22 | "colab": { 23 | "name": "01_python_basic_1.ipynb", 24 | "provenance": [], 25 | "collapsed_sections": [], 26 | "include_colab_link": true 27 | } 28 | }, 29 | "cells": [ 30 | { 31 | "cell_type": "markdown", 32 | "metadata": { 33 | "id": "view-in-github", 34 | "colab_type": "text" 35 | }, 36 | "source": [ 37 | "\"Open" 38 | ] 39 | }, 40 | { 41 | "cell_type": "markdown", 42 | "metadata": { 43 | "id": "QK1qtAbx7DCH", 44 | "colab_type": "text" 45 | }, 46 | "source": [ 47 | "# Pythonの基礎1\n", 48 | "本講座で必要な範囲の、Pythonの文法を解説します。 \n", 49 | "Pythonの文法についてさらに詳しく知りたい方は、他のウェブサイトや書籍などを参考にしてください。" 50 | ] 51 | }, 52 | { 53 | "cell_type": "markdown", 54 | "metadata": { 55 | "id": "ofKdJbhN7DCI", 56 | "colab_type": "text" 57 | }, 58 | "source": [ 59 | "## ●変数と型\n", 60 | "Pythonでは、変数を使用する前に何らかの記述をする必要ありません。 \n", 61 | "以下のように、値を代入するところから記述を始めることができます。 " 62 | ] 63 | }, 64 | { 65 | "cell_type": "code", 66 | "metadata": { 67 | "id": "h7HH2NJB7DCJ", 68 | "colab_type": "code", 69 | "colab": {} 70 | }, 71 | "source": [ 72 | "a = 123" 73 | ], 74 | "execution_count": 0, 75 | "outputs": [] 76 | }, 77 | { 78 | "cell_type": "markdown", 79 | "metadata": { 80 | "id": "jd_BuH8D7DCM", 81 | "colab_type": "text" 82 | }, 83 | "source": [ 84 | "Pythonは、変数に対して型の明示は不要です。 \n", 85 | "例えば、整数型の変数に文字列を代入すれば、それは文字列型の変数になります。 \n", 86 | "Pythonの主な型を以下に示します。" 87 | ] 88 | }, 89 | { 90 | "cell_type": "code", 91 | "metadata": { 92 | "id": "C0gx76OP7DCN", 93 | "colab_type": "code", 94 | "colab": {} 95 | }, 96 | "source": [ 97 | "a = 123 # 整数型(int)\n", 98 | "b = 123.456 # 浮動小数点型(float)\n", 99 | "c = \"Hello World!\" # 文字列型(str)\n", 100 | "d = True # 論理型(bool)\n", 101 | "e = [1, 2, 3] # リスト型(list)" 102 | ], 103 | "execution_count": 0, 104 | "outputs": [] 105 | }, 106 | { 107 | "cell_type": "markdown", 108 | "metadata": { 109 | "id": "eJckxxVj7DCP", 110 | "colab_type": "text" 111 | }, 112 | "source": [ 113 | "\\#はコメントを表し、同じ行のそれ以降はコードとして認識されることはありません。\n", 114 | "\n", 115 | "また、bool型の値は数値として扱うことができます。 \n", 116 | "`True`は1で`False`は0として扱われます。 \n", 117 | "以下の例では、`True`と`False`を足していますが、結果は0と1の和の1になります。" 118 | ] 119 | }, 120 | { 121 | "cell_type": "code", 122 | "metadata": { 123 | "id": "RlCGnHGH7DCP", 124 | "colab_type": "code", 125 | "colab": {} 126 | }, 127 | "source": [ 128 | "a = True; b = False\n", 129 | "print(a+b)" 130 | ], 131 | "execution_count": 0, 132 | "outputs": [] 133 | }, 134 | { 135 | "cell_type": "markdown", 136 | "metadata": { 137 | "id": "TL8PNWR07DCR", 138 | "colab_type": "text" 139 | }, 140 | "source": [ 141 | "Pythonでは、上記のように`;`(セミコロン)で区切ることで、一行内に複数の処理を書くことができます。 \n", 142 | "\n", 143 | "また、浮動小数点型の値は指数表記が可能です。以下のように`e`を用いて小数を表記することができます。" 144 | ] 145 | }, 146 | { 147 | "cell_type": "code", 148 | "metadata": { 149 | "id": "evGs7Cue7DCS", 150 | "colab_type": "code", 151 | "colab": {} 152 | }, 153 | "source": [ 154 | "1.2e5 # 1.2x10の5乗 120000\n", 155 | "1.2e-5 # 1.2x10の-5乗 0.000012" 156 | ], 157 | "execution_count": 0, 158 | "outputs": [] 159 | }, 160 | { 161 | "cell_type": "markdown", 162 | "metadata": { 163 | "id": "AioPKJ3q7DCU", 164 | "colab_type": "text" 165 | }, 166 | "source": [ 167 | "## ●演算子\n", 168 | "Pythonの演算子を紹介します。" 169 | ] 170 | }, 171 | { 172 | "cell_type": "code", 173 | "metadata": { 174 | "id": "hYmGSfid7DCU", 175 | "colab_type": "code", 176 | "colab": {} 177 | }, 178 | "source": [ 179 | "a = 3; b = 4\n", 180 | "\n", 181 | "c = a + b # 足し算\n", 182 | "print(c) \n", 183 | "\n", 184 | "d = a < b # 比較(小さいかどうか)\n", 185 | "print(d)\n", 186 | "\n", 187 | "e = 3 < 4 and 4 < 5 # 論理和\n", 188 | "print(e)" 189 | ], 190 | "execution_count": 0, 191 | "outputs": [] 192 | }, 193 | { 194 | "cell_type": "markdown", 195 | "metadata": { 196 | "id": "D4BOaxpW7DCW", 197 | "colab_type": "text" 198 | }, 199 | "source": [ 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 | "|論理演算子| and | 両者を満たす |\n", 218 | "|| or | どちらか片方を満たす |\n", 219 | "|| not | 満たさない |\n", 220 | "||||" 221 | ] 222 | }, 223 | { 224 | "cell_type": "markdown", 225 | "metadata": { 226 | "id": "BBT3UlBN7DCX", 227 | "colab_type": "text" 228 | }, 229 | "source": [ 230 | "## ●リスト\n", 231 | "リストは、複数の値をまとめて扱う場合に使用します。 \n", 232 | "リストは全体を`[]`で囲み、各要素は`,`で区切ります。 \n", 233 | "Pythonのリストはどのような型の値でも格納することができ、リストの中にリストを格納することもできます。 \n", 234 | "リストの各要素へのアクセスはインデックスを使い、要素の追加や入れ替えなどが可能です。 " 235 | ] 236 | }, 237 | { 238 | "cell_type": "code", 239 | "metadata": { 240 | "id": "Qi_hyR077DCY", 241 | "colab_type": "code", 242 | "colab": {} 243 | }, 244 | "source": [ 245 | "a = [1, 2, 3, 4, 5] # リストの作成\n", 246 | "\n", 247 | "b = a[2] # 3番目の要素を取得\n", 248 | "print(b)\n", 249 | "\n", 250 | "a.append(6) # 末尾に要素を追加する\n", 251 | "print(a)\n", 252 | "\n", 253 | "a[2] = 7 # 要素の入れ替え\n", 254 | "print(a)" 255 | ], 256 | "execution_count": 0, 257 | "outputs": [] 258 | }, 259 | { 260 | "cell_type": "markdown", 261 | "metadata": { 262 | "id": "33Tx-KRc7DCZ", 263 | "colab_type": "text" 264 | }, 265 | "source": [ 266 | "## ●タプル\n", 267 | "タプルはリストと同じく複数の値をまとめて扱いたいときに利用しますが、要素の追加や削除、入れ替えなどはできません。 \n", 268 | "タプルは全体を`()`で囲み、各要素は`,`で区切ります。 \n", 269 | "要素を変更する予定が無い場合は、リストよりもタプルを使用する方がベターです。 " 270 | ] 271 | }, 272 | { 273 | "cell_type": "code", 274 | "metadata": { 275 | "id": "uMW9UFiP7DCa", 276 | "colab_type": "code", 277 | "colab": {} 278 | }, 279 | "source": [ 280 | "a = (1, 2, 3, 4, 5) # タプルの作成\n", 281 | "\n", 282 | "b = a[2] # 3番目の要素を取得\n", 283 | "print(b)" 284 | ], 285 | "execution_count": 0, 286 | "outputs": [] 287 | }, 288 | { 289 | "cell_type": "markdown", 290 | "metadata": { 291 | "id": "KrLdlqyL7DCc", 292 | "colab_type": "text" 293 | }, 294 | "source": [ 295 | "要素が1つだけのタプルは、以下のように要素の直後に`,`が必要です。" 296 | ] 297 | }, 298 | { 299 | "cell_type": "code", 300 | "metadata": { 301 | "id": "yYM0zYcJ7DCc", 302 | "colab_type": "code", 303 | "colab": {} 304 | }, 305 | "source": [ 306 | "(3,)" 307 | ], 308 | "execution_count": 0, 309 | "outputs": [] 310 | }, 311 | { 312 | "cell_type": "markdown", 313 | "metadata": { 314 | "id": "c-QGdMhd7DCe", 315 | "colab_type": "text" 316 | }, 317 | "source": [ 318 | "リストやタプルの要素は、以下のようにしてまとめて変数に代入することが可能です。" 319 | ] 320 | }, 321 | { 322 | "cell_type": "code", 323 | "metadata": { 324 | "id": "9RrDK9fF7DCf", 325 | "colab_type": "code", 326 | "colab": {} 327 | }, 328 | "source": [ 329 | "a = [1, 2, 3]\n", 330 | "a1, a2, a3 = a\n", 331 | "print(a1, a2, a3)\n", 332 | "\n", 333 | "b = (4, 5, 6)\n", 334 | "b1, b2, b3 = b\n", 335 | "print(b1, b2, b3) " 336 | ], 337 | "execution_count": 0, 338 | "outputs": [] 339 | }, 340 | { 341 | "cell_type": "markdown", 342 | "metadata": { 343 | "id": "NkynT8abLLvF", 344 | "colab_type": "text" 345 | }, 346 | "source": [ 347 | "## ●辞書\n", 348 | "辞書は、キーと値の組合せでデータを格納します。  \n", 349 | "以下は、Pythonの辞書を扱う例です。 \n", 350 | "文字列をキーとして辞書を作成し、値の取得や入れ替え、要素の追加を行なっています。" 351 | ] 352 | }, 353 | { 354 | "cell_type": "code", 355 | "metadata": { 356 | "id": "_Mrxui8mLQ5P", 357 | "colab_type": "code", 358 | "outputId": "d6d8e8dd-713b-4386-b64c-fe3384c8282b", 359 | "colab": { 360 | "base_uri": "https://localhost:8080/", 361 | "height": 68 362 | } 363 | }, 364 | "source": [ 365 | "a = {\"Artificial\":1, \"Intelligence\":2} # 辞書の作成\n", 366 | "print(a[\"Artificial\"]) # \"Apple\"のキーを持つ値を取得\n", 367 | "\n", 368 | "a[\"Intelligence\"] = 7 # 要素の入れ替え\n", 369 | "print(a[\"Intelligence\"])\n", 370 | "\n", 371 | "a[\"ML\"] = 3 # 要素の追加\n", 372 | "print(a)" 373 | ], 374 | "execution_count": 0, 375 | "outputs": [ 376 | { 377 | "output_type": "stream", 378 | "text": [ 379 | "1\n", 380 | "7\n", 381 | "{'Artificial': 1, 'Intelligence': 7, 'ML': 3}\n" 382 | ], 383 | "name": "stdout" 384 | } 385 | ] 386 | }, 387 | { 388 | "cell_type": "markdown", 389 | "metadata": { 390 | "id": "G81yoB67NkfO", 391 | "colab_type": "text" 392 | }, 393 | "source": [ 394 | "## ●セット \n", 395 | "セットはリストと似ていますが、重複した値の要素をもつことができません。 \n", 396 | "タプルと異なり、要素の追加や削除が可能です。" 397 | ] 398 | }, 399 | { 400 | "cell_type": "code", 401 | "metadata": { 402 | "id": "gEUH0JJhOasI", 403 | "colab_type": "code", 404 | "outputId": "6864fdbc-b331-481f-b4bf-fd92002029fe", 405 | "colab": { 406 | "base_uri": "https://localhost:8080/", 407 | "height": 85 408 | } 409 | }, 410 | "source": [ 411 | "a = [1, 1, 2, 3, 4, 4, 5, 5, 5] # リスト\n", 412 | "print(a)\n", 413 | "\n", 414 | "b = set(a) # セットに変換\n", 415 | "print(b)\n", 416 | "\n", 417 | "b.add(6) # 値を追加\n", 418 | "print(b)\n", 419 | "\n", 420 | "b.remove(3) # 値を削除\n", 421 | "print(b)" 422 | ], 423 | "execution_count": 0, 424 | "outputs": [ 425 | { 426 | "output_type": "stream", 427 | "text": [ 428 | "[1, 1, 2, 3, 4, 4, 5, 5, 5]\n", 429 | "{1, 2, 3, 4, 5}\n", 430 | "{1, 2, 3, 4, 5, 6}\n", 431 | "{1, 2, 4, 5, 6}\n" 432 | ], 433 | "name": "stdout" 434 | } 435 | ] 436 | }, 437 | { 438 | "cell_type": "markdown", 439 | "metadata": { 440 | "id": "vOkphdpi7DCh", 441 | "colab_type": "text" 442 | }, 443 | "source": [ 444 | "## ●if文 \n", 445 | "分岐にはif文を用います。 \n", 446 | "ifの条件が満たされていなければ、elifの条件が上から順番に判定されます。 \n", 447 | "これらの条件がすべて満たされていなければ、else内の処理が実行されます。 \n", 448 | "\n", 449 | "多くのプログラミング言語では分岐や関数のブロックを表すために{ }を使用しますが、Pythonではブロックの範囲を行頭のインデントで表します。 \n", 450 | "すなわち、インデントしていない行が出現したら、その直前にブロックは終了していることになります。 \n", 451 | "インデントには、半角スペース4つを用いることが多いです。" 452 | ] 453 | }, 454 | { 455 | "cell_type": "code", 456 | "metadata": { 457 | "id": "mgzqzezO7DCh", 458 | "colab_type": "code", 459 | "colab": {} 460 | }, 461 | "source": [ 462 | "a = 7\n", 463 | "if a < 12:\n", 464 | " print(\"Good morning!\")\n", 465 | "elif a < 17:\n", 466 | " print(\"Good afternoon!\")\n", 467 | "elif a < 21:\n", 468 | " print(\"Good evening!\")\n", 469 | "else:\n", 470 | " print(\"Good night!\")" 471 | ], 472 | "execution_count": 0, 473 | "outputs": [] 474 | }, 475 | { 476 | "cell_type": "markdown", 477 | "metadata": { 478 | "id": "4ikn14Eq7DCj", 479 | "colab_type": "text" 480 | }, 481 | "source": [ 482 | "## ●for文\n", 483 | "指定した回数ループするためにはfor文を用います。 \n", 484 | "ループする範囲を指定するためには、リストやrangeをin演算子とともに用います。 \n", 485 | "\n", 486 | "rangeの使い方は次のとおりです。[ ]で囲まれた引数は省略可能です。\n", 487 | "\n", 488 | "```\n", 489 | "range([開始番号,] 終了番号[, ステップ数])\n", 490 | "```\n", 491 | "\n", 492 | "例えばrange(3)は、0から2までの範囲になります。" 493 | ] 494 | }, 495 | { 496 | "cell_type": "code", 497 | "metadata": { 498 | "id": "qf8iaf9V7DCj", 499 | "colab_type": "code", 500 | "colab": {} 501 | }, 502 | "source": [ 503 | "for a in [4, 7, 10]: # リストを使ったループ\n", 504 | " print(a)\n", 505 | " \n", 506 | "for a in range(3): # rangeを使ったループ\n", 507 | " print(a)" 508 | ], 509 | "execution_count": 0, 510 | "outputs": [] 511 | }, 512 | { 513 | "cell_type": "markdown", 514 | "metadata": { 515 | "id": "FKQ9lg_NFEoJ", 516 | "colab_type": "text" 517 | }, 518 | "source": [ 519 | "## ●while文\n", 520 | "ある条件を満たしている間ループするためには、while文を用います。" 521 | ] 522 | }, 523 | { 524 | "cell_type": "code", 525 | "metadata": { 526 | "id": "vFVOuNokFKV3", 527 | "colab_type": "code", 528 | "outputId": "0da3887c-ad88-4133-de44-6617c67b1ee3", 529 | "colab": { 530 | "base_uri": "https://localhost:8080/", 531 | "height": 68 532 | } 533 | }, 534 | "source": [ 535 | "a = 0\n", 536 | "while a < 3: # aが3より小さい間ループ\n", 537 | " print(a)\n", 538 | " a += 1" 539 | ], 540 | "execution_count": 0, 541 | "outputs": [ 542 | { 543 | "output_type": "stream", 544 | "text": [ 545 | "0\n", 546 | "1\n", 547 | "2\n" 548 | ], 549 | "name": "stdout" 550 | } 551 | ] 552 | }, 553 | { 554 | "cell_type": "markdown", 555 | "metadata": { 556 | "id": "jdyK90d_GJzn", 557 | "colab_type": "text" 558 | }, 559 | "source": [ 560 | "## ●内包表記\n", 561 | "内容表記は、リストの要素を操作した上で、新しいリストを作成するための記法です。 \n", 562 | "通常、そのような処理はforやwhileによるループを使用しますが、内包表記を用いると、簡潔に記述することができます。 \n", 563 | "内包表記は、以下の形式で記述します。 \n", 564 | "\n", 565 | "```\n", 566 | "新たなリスト = [ 要素への処理 for 要素 in リスト] \n", 567 | "```\n", 568 | "\n", 569 | "リスト内の要素を1つ1つ取り出して、要素への処理を実行した上で新しいリストを作成します。" 570 | ] 571 | }, 572 | { 573 | "cell_type": "code", 574 | "metadata": { 575 | "id": "qncEVtHrHNkM", 576 | "colab_type": "code", 577 | "outputId": "47ef09bd-4ae9-4b21-9d33-fd2e8c843beb", 578 | "colab": { 579 | "base_uri": "https://localhost:8080/", 580 | "height": 34 581 | } 582 | }, 583 | "source": [ 584 | "a = [1, 2, 3, 4, 5, 6]\n", 585 | "b = [c*3+1 for c in a] # aの要素を3倍して1を足し新たなリストを作る\n", 586 | "print(b)" 587 | ], 588 | "execution_count": 0, 589 | "outputs": [ 590 | { 591 | "output_type": "stream", 592 | "text": [ 593 | "[4, 7, 10, 13, 16, 19]\n" 594 | ], 595 | "name": "stdout" 596 | } 597 | ] 598 | } 599 | ] 600 | } -------------------------------------------------------------------------------- /python_basic/02_python_basic_2.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "kernelspec": { 6 | "display_name": "Python 3", 7 | "language": "python", 8 | "name": "python3" 9 | }, 10 | "language_info": { 11 | "codemirror_mode": { 12 | "name": "ipython", 13 | "version": 3 14 | }, 15 | "file_extension": ".py", 16 | "mimetype": "text/x-python", 17 | "name": "python", 18 | "nbconvert_exporter": "python", 19 | "pygments_lexer": "ipython3", 20 | "version": "3.5.4" 21 | }, 22 | "colab": { 23 | "name": "02_python_basic_2.ipynb", 24 | "provenance": [], 25 | "include_colab_link": true 26 | } 27 | }, 28 | "cells": [ 29 | { 30 | "cell_type": "markdown", 31 | "metadata": { 32 | "id": "view-in-github", 33 | "colab_type": "text" 34 | }, 35 | "source": [ 36 | "\"Open" 37 | ] 38 | }, 39 | { 40 | "cell_type": "markdown", 41 | "metadata": { 42 | "id": "ewg_pUrO-m3m", 43 | "colab_type": "text" 44 | }, 45 | "source": [ 46 | "# Pythonの基礎2\n", 47 | "Pythonの基礎として、関数やクラスについて解説します。" 48 | ] 49 | }, 50 | { 51 | "cell_type": "markdown", 52 | "metadata": { 53 | "id": "BxlxFRAm-m3o", 54 | "colab_type": "text" 55 | }, 56 | "source": [ 57 | "## ●関数\n", 58 | "関数を用いることで、複数行の処理をまとめることができます。 \n", 59 | "関数はdefのあとに関数名を記述し、()の中に引数を記述します。 \n", 60 | "returnのあとの値が返り値になります。 " 61 | ] 62 | }, 63 | { 64 | "cell_type": "code", 65 | "metadata": { 66 | "id": "xftbx6T4-m3p", 67 | "colab_type": "code", 68 | "colab": {} 69 | }, 70 | "source": [ 71 | "def add(a, b): # 関数の定義\n", 72 | " c = a + b\n", 73 | " return c\n", 74 | "\n", 75 | "print(add(3, 4)) # 関数の実行" 76 | ], 77 | "execution_count": 0, 78 | "outputs": [] 79 | }, 80 | { 81 | "cell_type": "markdown", 82 | "metadata": { 83 | "id": "L8xd1JMv-m3s", 84 | "colab_type": "text" 85 | }, 86 | "source": [ 87 | "引数にはデフォルト値を設定できます。 \n", 88 | "デフォルト値を設定すると、関数を呼び出す際にその引数を省略できます。 \n", 89 | "以下の例では、第2引数にデフォルト値が設定されています。 " 90 | ] 91 | }, 92 | { 93 | "cell_type": "code", 94 | "metadata": { 95 | "id": "-Tnd7UjE-m3t", 96 | "colab_type": "code", 97 | "colab": {} 98 | }, 99 | "source": [ 100 | "def add(a, b=4): # 第2引数にデフォルト値を設定\n", 101 | " c = a + b\n", 102 | " return c\n", 103 | "\n", 104 | "print(add(3)) # 第2引数は指定しない" 105 | ], 106 | "execution_count": 0, 107 | "outputs": [] 108 | }, 109 | { 110 | "cell_type": "markdown", 111 | "metadata": { 112 | "id": "WDX63lI8-m3v", 113 | "colab_type": "text" 114 | }, 115 | "source": [ 116 | "また、`*`(アスタリスク)を付けたタプルを用いて、複数の引数を一度に渡すことができます。" 117 | ] 118 | }, 119 | { 120 | "cell_type": "code", 121 | "metadata": { 122 | "id": "uzH_ICO3-m3w", 123 | "colab_type": "code", 124 | "colab": {} 125 | }, 126 | "source": [ 127 | "def add(a, b ,c):\n", 128 | " d = a + b + c\n", 129 | " print(d)\n", 130 | "\n", 131 | "e = (1, 2, 3)\n", 132 | "add(*e) # 複数の引数を一度に渡す" 133 | ], 134 | "execution_count": 0, 135 | "outputs": [] 136 | }, 137 | { 138 | "cell_type": "markdown", 139 | "metadata": { 140 | "id": "DtAbWNWw-m3y", 141 | "colab_type": "text" 142 | }, 143 | "source": [ 144 | "## ●変数のスコープ\n", 145 | "関数内で定義された変数がローカル変数、関数外で定義された変数がグローバル変数です。 \n", 146 | "ローカル変数は同じ関数内からのみ参照できますが、グローバル変数はどこからでも参照できます。 " 147 | ] 148 | }, 149 | { 150 | "cell_type": "code", 151 | "metadata": { 152 | "id": "3pD2XU7t-m3y", 153 | "colab_type": "code", 154 | "colab": {} 155 | }, 156 | "source": [ 157 | "a = 123 # グローバル変数\n", 158 | "\n", 159 | "def showNum():\n", 160 | " b = 456 # ローカル変数\n", 161 | " print(a, b)\n", 162 | " \n", 163 | "showNum()" 164 | ], 165 | "execution_count": 0, 166 | "outputs": [] 167 | }, 168 | { 169 | "cell_type": "markdown", 170 | "metadata": { 171 | "id": "j4BL7N5d-m30", 172 | "colab_type": "text" 173 | }, 174 | "source": [ 175 | "Pythonでは、関数内でグローバル変数に値を代入しようとすると、新しいローカル変数とみなされます。 \n", 176 | "以下の例では、関数内でグローバル変数aに値を代入しても、グローバル変数aの値は変わっていません。" 177 | ] 178 | }, 179 | { 180 | "cell_type": "code", 181 | "metadata": { 182 | "id": "7KOGz1gM-m31", 183 | "colab_type": "code", 184 | "colab": {} 185 | }, 186 | "source": [ 187 | "a = 123\n", 188 | "\n", 189 | "def setLocal():\n", 190 | " a = 456 # aはローカル変数とみなされる\n", 191 | " print(\"Local:\", a)\n", 192 | " \n", 193 | "setLocal()\n", 194 | "print(\"Global:\", a)" 195 | ], 196 | "execution_count": 0, 197 | "outputs": [] 198 | }, 199 | { 200 | "cell_type": "markdown", 201 | "metadata": { 202 | "id": "pPidAnqa-m33", 203 | "colab_type": "text" 204 | }, 205 | "source": [ 206 | "グローバル変数の値を変更するためには、`global`を用いて、変数がローカルではないことを明記する必要があります。 " 207 | ] 208 | }, 209 | { 210 | "cell_type": "code", 211 | "metadata": { 212 | "id": "ppg619df-m33", 213 | "colab_type": "code", 214 | "colab": {} 215 | }, 216 | "source": [ 217 | "a = 123\n", 218 | "\n", 219 | "def setGlobal():\n", 220 | " global a # nonlocalでも可\n", 221 | " a = 456\n", 222 | " print(\"Global:\", a)\n", 223 | " \n", 224 | "setGlobal()\n", 225 | "print(\"Global:\", a)" 226 | ], 227 | "execution_count": 0, 228 | "outputs": [] 229 | }, 230 | { 231 | "cell_type": "markdown", 232 | "metadata": { 233 | "id": "zG9VcO-6-m35", 234 | "colab_type": "text" 235 | }, 236 | "source": [ 237 | "## ●クラス\n", 238 | "Pythonでは、オブジェクト指向プログラミングが可能です。 \n", 239 | "オブジェクト指向は、オブジェクト同士の相互作用として、システムの振る舞いをとらえる考え方です。 \n", 240 | "\n", 241 | "オブジェクト指向には、クラスとインスタンスという概念があります。 \n", 242 | "クラスは設計図のようなもので、インスタンスは実体です。 \n", 243 | "クラスから複数のインスタンスを生成することができます。 \n", 244 | "クラスとインスタンスを総称して、オブジェクトといいます。 \n", 245 | "\n", 246 | "Pythonでクラスを定義するためには、`class`の表記を用います。 \n", 247 | "クラスを用いると、複数のメソッドをまとめることができます。 \n", 248 | "メソッドは関数に似ており、defで記述を開始します。 \n", 249 | "\n", 250 | "以下の例では、`Calc`クラス内に`__init__`メソッド、`add`メソッド、`multiply`メソッドが実装されています。" 251 | ] 252 | }, 253 | { 254 | "cell_type": "code", 255 | "metadata": { 256 | "id": "h9YW6LdV-m36", 257 | "colab_type": "code", 258 | "colab": {} 259 | }, 260 | "source": [ 261 | "class Calc:\n", 262 | " def __init__(self, a):\n", 263 | " self.a = a\n", 264 | " \n", 265 | " def add(self, b):\n", 266 | " print(self.a + b)\n", 267 | " \n", 268 | " def multiply(self, b):\n", 269 | " print(self.a * b)" 270 | ], 271 | "execution_count": 0, 272 | "outputs": [] 273 | }, 274 | { 275 | "cell_type": "markdown", 276 | "metadata": { 277 | "id": "f83MEU1X-m38", 278 | "colab_type": "text" 279 | }, 280 | "source": [ 281 | "Pythonのメソッドは引数として`self`を受け取るという特徴があります。 \n", 282 | "このselfを用いて、インスタンス変数にアクセスすることができます。 \n", 283 | "インスタンス変数は、クラスからインスタンスを生成し、そちらの方でアクセスする変数です。 \n", 284 | "\n", 285 | " `__init__`は特殊なメソッドで、コンストラクタと呼ばれています。 \n", 286 | " このメソッドで、インスタンスの初期設定を行います。 \n", 287 | " 上記のクラスでは、`self.a = a`で引数として受け取った値をインスタンス変数`a`に代入します。\n", 288 | "\n", 289 | "`add`メソッドと`multiply`メソッドでは、引数として受け取った値をインスタンス変数`a`と演算しています。 \n", 290 | "このように、一度メソッドで値が代入されたインスタンス変数は、同じインスタンスのどのメソッドからでも`self`を用いてアクセスすることができます。 \n", 291 | "\n", 292 | "上記のクラスCalcから、以下のようにインスタンスを生成しメソッドを呼び出すことができます。 \n", 293 | "この場合、`Calc(3)`でインスタンスを生成し、変数`calc`に代入しています。 " 294 | ] 295 | }, 296 | { 297 | "cell_type": "code", 298 | "metadata": { 299 | "id": "9le-T7MT-m39", 300 | "colab_type": "code", 301 | "colab": {} 302 | }, 303 | "source": [ 304 | "calc = Calc(3)\n", 305 | "calc.add(4)\n", 306 | "calc.multiply(4)" 307 | ], 308 | "execution_count": 0, 309 | "outputs": [] 310 | }, 311 | { 312 | "cell_type": "markdown", 313 | "metadata": { 314 | "id": "ZHSv1Cbd-m3-", 315 | "colab_type": "text" 316 | }, 317 | "source": [ 318 | "初期化時に3という値をインスタンスに渡し、addメソッドとmultiplyメソッドを呼び出します。 \n", 319 | "実行すると、4+3と4x3、それぞれの計算結果を得ることができます。 \n", 320 | "\n", 321 | "また、クラスには継承という概念があります。 \n", 322 | "クラスを継承することで、既存のクラスを引き継いで新たなクラスを定義することができます。 \n", 323 | "以下の例では、`Calc`クラスを継承して`CalcPlus`クラスを定義しています。 " 324 | ] 325 | }, 326 | { 327 | "cell_type": "code", 328 | "metadata": { 329 | "id": "b-oYXKYp-m3_", 330 | "colab_type": "code", 331 | "colab": {} 332 | }, 333 | "source": [ 334 | "class CalcPlus(Calc): # Calcを継承\n", 335 | " def subtract(self, b):\n", 336 | " print(self.a - b)\n", 337 | " \n", 338 | " def divide(self, b):\n", 339 | " print(self.a / b)" 340 | ], 341 | "execution_count": 0, 342 | "outputs": [] 343 | }, 344 | { 345 | "cell_type": "markdown", 346 | "metadata": { 347 | "id": "JlIMbpKY-m4B", 348 | "colab_type": "text" 349 | }, 350 | "source": [ 351 | "`subtract`メソッドと、`divide`メソッドが新たに追加されています。 \n", 352 | "それでは、CalcPlusメソッドからインスタンスを生成し、メソッドを呼び出してみましょう。 " 353 | ] 354 | }, 355 | { 356 | "cell_type": "code", 357 | "metadata": { 358 | "id": "nwLyVgWt-m4B", 359 | "colab_type": "code", 360 | "colab": {} 361 | }, 362 | "source": [ 363 | "calc_plus = CalcPlus(3)\n", 364 | "calc_plus.add(4)\n", 365 | "calc_plus.multiply(4)\n", 366 | "calc_plus.subtract(4)\n", 367 | "calc_plus.divide(4)" 368 | ], 369 | "execution_count": 0, 370 | "outputs": [] 371 | }, 372 | { 373 | "cell_type": "markdown", 374 | "metadata": { 375 | "id": "V5zjFafp-m4D", 376 | "colab_type": "text" 377 | }, 378 | "source": [ 379 | "継承元の`Calc`クラスで定義されたメソッドも、これを継承した`CalcPlus`クラスで定義されたメソッドも、同じように呼び出すことができます。 \n", 380 | "このようなクラスの継承を利用すれば、複数のクラスの共通部分を継承元のクラスにまとめることができます。 " 381 | ] 382 | }, 383 | { 384 | "cell_type": "markdown", 385 | "metadata": { 386 | "id": "PFRFL6hTN7Dg", 387 | "colab_type": "text" 388 | }, 389 | "source": [ 390 | "## ●\\_\\_call\\_\\_メソッド\n", 391 | "\\_\\_init\\_\\_の他に、\\_\\_call\\_\\_という特殊なメソッドがあります。 \n", 392 | "このメソッドをクラス内に実装すると、インスタンス名からメソッドを呼び出すことができます。\n" 393 | ] 394 | }, 395 | { 396 | "cell_type": "code", 397 | "metadata": { 398 | "id": "9L_WQzkLOu5q", 399 | "colab_type": "code", 400 | "colab": {} 401 | }, 402 | "source": [ 403 | "class Hello:\n", 404 | " def __init__(self, name):\n", 405 | " self.name = name\n", 406 | "\n", 407 | " def __call__(self):\n", 408 | " print(\"Hello \" + self.name + \"!\")\n", 409 | "\n", 410 | "h = Hello(\"AI\")\n", 411 | "h() # インスタンス名hを使って__call__メソッドを呼ぶ\n", 412 | "\n", 413 | "Hello(\"AI\")() # 上に同じ" 414 | ], 415 | "execution_count": 0, 416 | "outputs": [] 417 | } 418 | ] 419 | } -------------------------------------------------------------------------------- /python_basic/03_numpy.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "kernelspec": { 6 | "display_name": "Python 3", 7 | "language": "python", 8 | "name": "python3" 9 | }, 10 | "language_info": { 11 | "codemirror_mode": { 12 | "name": "ipython", 13 | "version": 3 14 | }, 15 | "file_extension": ".py", 16 | "mimetype": "text/x-python", 17 | "name": "python", 18 | "nbconvert_exporter": "python", 19 | "pygments_lexer": "ipython3", 20 | "version": "3.5.4" 21 | }, 22 | "colab": { 23 | "name": "03_numpy.ipynb", 24 | "provenance": [], 25 | "collapsed_sections": [], 26 | "include_colab_link": true 27 | } 28 | }, 29 | "cells": [ 30 | { 31 | "cell_type": "markdown", 32 | "metadata": { 33 | "id": "view-in-github", 34 | "colab_type": "text" 35 | }, 36 | "source": [ 37 | "\"Open" 38 | ] 39 | }, 40 | { 41 | "cell_type": "markdown", 42 | "metadata": { 43 | "id": "8PEI59mRTLnr", 44 | "colab_type": "text" 45 | }, 46 | "source": [ 47 | "# NumPyの基礎\n", 48 | "NumPyはPythonの拡張モジュールで、シンプルな表記で効率的なデータの操作を可能にします。 \n", 49 | "多次元配列を強力にサポートし、内部はC言語で実装されているため高速に動作します。 \n", 50 | "NumPyには様々な機能があるのですが、ここでは本講座で使用する範囲のみ解説します。" 51 | ] 52 | }, 53 | { 54 | "cell_type": "markdown", 55 | "metadata": { 56 | "id": "5e9PIBU6TLnt", 57 | "colab_type": "text" 58 | }, 59 | "source": [ 60 | "## ●Numpyの導入" 61 | ] 62 | }, 63 | { 64 | "cell_type": "markdown", 65 | "metadata": { 66 | "id": "eG_cxnskTLnt", 67 | "colab_type": "text" 68 | }, 69 | "source": [ 70 | "Pythonでは、importの記述によりモジュールを導入することができます。 \n", 71 | "NumPyはモジュールなので、NumPyを使用するためには、コードの先頭に例えば以下のように記述します。 " 72 | ] 73 | }, 74 | { 75 | "cell_type": "code", 76 | "metadata": { 77 | "id": "CWUJW65XTLnu", 78 | "colab_type": "code", 79 | "colab": {} 80 | }, 81 | "source": [ 82 | "import numpy as np" 83 | ], 84 | "execution_count": 0, 85 | "outputs": [] 86 | }, 87 | { 88 | "cell_type": "markdown", 89 | "metadata": { 90 | "id": "7Flpz0G1TLnx", 91 | "colab_type": "text" 92 | }, 93 | "source": [ 94 | "asを使うことでモジュールに別の名前をつけることができます。 \n", 95 | "このように記述すると、これ以降npという名前でNumPyのモジュールを扱うことができます。 " 96 | ] 97 | }, 98 | { 99 | "cell_type": "markdown", 100 | "metadata": { 101 | "id": "Lfd5_xOHTLnx", 102 | "colab_type": "text" 103 | }, 104 | "source": [ 105 | "## ●Numpyの配列\n", 106 | "\n", 107 | "人工知能の計算にはベクトルや行列を多用しますが、これらを表現するのにNumPyの配列を用います。 \n", 108 | "ベクトルや行列についてはのちのセクションで改めて解説しますが、ここではとりあえずNumPyの配列とは数値が折り重なって並んだもの、と考えていただければ十分です。 \n", 109 | "以降、単に配列と呼ぶ場合はNumPyの配列を指すことにします。 \n", 110 | "\n", 111 | "NumPyの配列は、NumPyのarray関数を使うことでPythonのリストから簡単に作ることができます。 " 112 | ] 113 | }, 114 | { 115 | "cell_type": "code", 116 | "metadata": { 117 | "id": "S4WV4FcFTLny", 118 | "colab_type": "code", 119 | "outputId": "0576fca6-b604-4477-dcd6-0299a09a8827", 120 | "colab": { 121 | "base_uri": "https://localhost:8080/", 122 | "height": 34 123 | } 124 | }, 125 | "source": [ 126 | "import numpy as np\n", 127 | "\n", 128 | "a = np.array([0, 1, 2, 3, 4, 5]) # PythonのリストからNumPyの配列を作る\n", 129 | "print(a) " 130 | ], 131 | "execution_count": 0, 132 | "outputs": [ 133 | { 134 | "output_type": "stream", 135 | "text": [ 136 | "[0 1 2 3 4 5]\n" 137 | ], 138 | "name": "stdout" 139 | } 140 | ] 141 | }, 142 | { 143 | "cell_type": "markdown", 144 | "metadata": { 145 | "id": "9WPpjCzCTLn1", 146 | "colab_type": "text" 147 | }, 148 | "source": [ 149 | "このような配列が折り重なった、2次元の配列を作ることもできます。 \n", 150 | "2次元配列は、要素がリストであるリスト(2重のリスト)から作ります。" 151 | ] 152 | }, 153 | { 154 | "cell_type": "code", 155 | "metadata": { 156 | "id": "cbm07F22TLn2", 157 | "colab_type": "code", 158 | "outputId": "c20be0de-6290-4536-a6c6-ff44b89c91ee", 159 | "colab": { 160 | "base_uri": "https://localhost:8080/", 161 | "height": 51 162 | } 163 | }, 164 | "source": [ 165 | "import numpy as np\n", 166 | "\n", 167 | "b = np.array([[0, 1, 2], [3, 4, 5]]) # 2重のリストからNumPyの2次元配列を作る\n", 168 | "print(b)" 169 | ], 170 | "execution_count": 0, 171 | "outputs": [ 172 | { 173 | "output_type": "stream", 174 | "text": [ 175 | "[[0 1 2]\n", 176 | " [3 4 5]]\n" 177 | ], 178 | "name": "stdout" 179 | } 180 | ] 181 | }, 182 | { 183 | "cell_type": "markdown", 184 | "metadata": { 185 | "id": "0GJVCigITLn4", 186 | "colab_type": "text" 187 | }, 188 | "source": [ 189 | "同様に、3次元の配列も作ることができます。 \n", 190 | "3次元配列は2次元の配列がさらに折り重なったもので、3重のリストから作ります。" 191 | ] 192 | }, 193 | { 194 | "cell_type": "code", 195 | "metadata": { 196 | "id": "4p3lrbpbTLn5", 197 | "colab_type": "code", 198 | "outputId": "a6c81311-9dbb-4107-d3ca-c47fae89a0f6", 199 | "colab": { 200 | "base_uri": "https://localhost:8080/", 201 | "height": 102 202 | } 203 | }, 204 | "source": [ 205 | "import numpy as np\n", 206 | "\n", 207 | "c = np.array([[[0, 1, 2], [3, 4, 5]], [[5, 4, 3], [2, 1, 0]]]) # 3重のリストからNumPyの3次元配列を作る\n", 208 | "print(c)" 209 | ], 210 | "execution_count": 0, 211 | "outputs": [ 212 | { 213 | "output_type": "stream", 214 | "text": [ 215 | "[[[0 1 2]\n", 216 | " [3 4 5]]\n", 217 | "\n", 218 | " [[5 4 3]\n", 219 | " [2 1 0]]]\n" 220 | ], 221 | "name": "stdout" 222 | } 223 | ] 224 | }, 225 | { 226 | "cell_type": "markdown", 227 | "metadata": { 228 | "id": "RyoE4NnoTLn7", 229 | "colab_type": "text" 230 | }, 231 | "source": [ 232 | "## ●配列の演算\n", 233 | "\n", 234 | "以下の例では、配列と数値の間で演算を行なっています。 \n", 235 | "この場合、配列の各要素と数値の間で演算が行われます。" 236 | ] 237 | }, 238 | { 239 | "cell_type": "code", 240 | "metadata": { 241 | "id": "M9b6D0t2TLn8", 242 | "colab_type": "code", 243 | "outputId": "0b9ab7fe-2643-4072-f07a-8df6c99141aa", 244 | "colab": { 245 | "base_uri": "https://localhost:8080/", 246 | "height": 153 247 | } 248 | }, 249 | "source": [ 250 | "import numpy as np\n", 251 | "\n", 252 | "a = np.array([[0, 1, 2], [3, 4, 5]]) # 2次元配列\n", 253 | "\n", 254 | "print(a) \n", 255 | "print()\n", 256 | "print(a + 3) # 各要素に3を足す\n", 257 | "print()\n", 258 | "print(a * 3) # 各要素に3をかける" 259 | ], 260 | "execution_count": 0, 261 | "outputs": [ 262 | { 263 | "output_type": "stream", 264 | "text": [ 265 | "[[0 1 2]\n", 266 | " [3 4 5]]\n", 267 | "\n", 268 | "[[3 4 5]\n", 269 | " [6 7 8]]\n", 270 | "\n", 271 | "[[ 0 3 6]\n", 272 | " [ 9 12 15]]\n" 273 | ], 274 | "name": "stdout" 275 | } 276 | ] 277 | }, 278 | { 279 | "cell_type": "markdown", 280 | "metadata": { 281 | "id": "ETHgZASbTLn-", 282 | "colab_type": "text" 283 | }, 284 | "source": [ 285 | "また、以下は配列同士の演算の例です。 \n", 286 | "この場合は同じ位置の各要素同士で演算が行われます。 " 287 | ] 288 | }, 289 | { 290 | "cell_type": "code", 291 | "metadata": { 292 | "id": "f-P72aAATLn_", 293 | "colab_type": "code", 294 | "outputId": "19ac6c0a-0268-4ff1-8be9-8f7952e6e7f1", 295 | "colab": { 296 | "base_uri": "https://localhost:8080/", 297 | "height": 204 298 | } 299 | }, 300 | "source": [ 301 | "b = np.array([[0, 1, 2], [3, 4, 5]]) # 2次元配列\n", 302 | "c = np.array([[2, 0, 1], [5, 3, 4]]) # 2次元配列\n", 303 | "\n", 304 | "print(b)\n", 305 | "print()\n", 306 | "print(c)\n", 307 | "print()\n", 308 | "print(b + c)\n", 309 | "print()\n", 310 | "print(b * c)" 311 | ], 312 | "execution_count": 0, 313 | "outputs": [ 314 | { 315 | "output_type": "stream", 316 | "text": [ 317 | "[[0 1 2]\n", 318 | " [3 4 5]]\n", 319 | "\n", 320 | "[[2 0 1]\n", 321 | " [5 3 4]]\n", 322 | "\n", 323 | "[[2 1 3]\n", 324 | " [8 7 9]]\n", 325 | "\n", 326 | "[[ 0 0 2]\n", 327 | " [15 12 20]]\n" 328 | ], 329 | "name": "stdout" 330 | } 331 | ] 332 | }, 333 | { 334 | "cell_type": "markdown", 335 | "metadata": { 336 | "id": "jtTr0asBTLoA", 337 | "colab_type": "text" 338 | }, 339 | "source": [ 340 | "ブロードキャストという機能により、特定の条件を満たしていれば形状の異なる配列同士でも演算が可能です。" 341 | ] 342 | }, 343 | { 344 | "cell_type": "code", 345 | "metadata": { 346 | "id": "6lDdx3tRTLoB", 347 | "colab_type": "code", 348 | "outputId": "30ea980f-173c-43dc-a5e6-1ac16c132cea", 349 | "colab": { 350 | "base_uri": "https://localhost:8080/", 351 | "height": 51 352 | } 353 | }, 354 | "source": [ 355 | "d = np.array([[1, 1],\n", 356 | " [1, 1]]) # 2次元配列\n", 357 | "e = np.array([1, 2]) # 1次元配列\n", 358 | "\n", 359 | "print(d + e)" 360 | ], 361 | "execution_count": 0, 362 | "outputs": [ 363 | { 364 | "output_type": "stream", 365 | "text": [ 366 | "[[2 3]\n", 367 | " [2 3]]\n" 368 | ], 369 | "name": "stdout" 370 | } 371 | ] 372 | }, 373 | { 374 | "cell_type": "markdown", 375 | "metadata": { 376 | "id": "U0i_YVmnTLoD", 377 | "colab_type": "text" 378 | }, 379 | "source": [ 380 | "ブロードキャストの厳密なルールは少々複雑で、全て記述すると長くなってしまうので、今回は必要最小限の解説としました。" 381 | ] 382 | }, 383 | { 384 | "cell_type": "markdown", 385 | "metadata": { 386 | "id": "_MgpaIvqTLoE", 387 | "colab_type": "text" 388 | }, 389 | "source": [ 390 | "## ●形状の変換\n", 391 | "NumPyのshapeメソッドにより、配列の形状を得ることができます。 " 392 | ] 393 | }, 394 | { 395 | "cell_type": "code", 396 | "metadata": { 397 | "id": "2A-NU9z1TLoE", 398 | "colab_type": "code", 399 | "outputId": "c273712d-ccb0-4d51-eaf2-0619ef518632", 400 | "colab": { 401 | "base_uri": "https://localhost:8080/", 402 | "height": 34 403 | } 404 | }, 405 | "source": [ 406 | "import numpy as np\n", 407 | "\n", 408 | "a = np.array([[0, 1, 2],\n", 409 | " [3, 4, 5]])\n", 410 | "\n", 411 | "print(a.shape)" 412 | ], 413 | "execution_count": 0, 414 | "outputs": [ 415 | { 416 | "output_type": "stream", 417 | "text": [ 418 | "(2, 3)\n" 419 | ], 420 | "name": "stdout" 421 | } 422 | ] 423 | }, 424 | { 425 | "cell_type": "markdown", 426 | "metadata": { 427 | "id": "PsdkpN7UTLoG", 428 | "colab_type": "text" 429 | }, 430 | "source": [ 431 | "reshapeメソッドを使うと、配列の形状を変換することができます。 \n", 432 | "以下の例では、要素数が8の1次元配列を 形状が(2, 4)の2次元配列に変換しています。 " 433 | ] 434 | }, 435 | { 436 | "cell_type": "code", 437 | "metadata": { 438 | "id": "onsdEGMSTLoH", 439 | "colab_type": "code", 440 | "outputId": "2056a9a1-c137-4603-c64e-976d7aa37e87", 441 | "colab": { 442 | "base_uri": "https://localhost:8080/", 443 | "height": 51 444 | } 445 | }, 446 | "source": [ 447 | "b = np.array([0, 1, 2, 3, 4, 5, 6, 7]) # 配列の作成\n", 448 | "c = b.reshape(2, 4) # (2, 4)の2次元配列に変換\n", 449 | "print(c)" 450 | ], 451 | "execution_count": 0, 452 | "outputs": [ 453 | { 454 | "output_type": "stream", 455 | "text": [ 456 | "[[0 1 2 3]\n", 457 | " [4 5 6 7]]\n" 458 | ], 459 | "name": "stdout" 460 | } 461 | ] 462 | }, 463 | { 464 | "cell_type": "markdown", 465 | "metadata": { 466 | "id": "99Rq7OhTTLoJ", 467 | "colab_type": "text" 468 | }, 469 | "source": [ 470 | "reshapeの引数を-1にすることで、どのような形状の配列でも1次元配列に変換することができます。" 471 | ] 472 | }, 473 | { 474 | "cell_type": "code", 475 | "metadata": { 476 | "id": "_YZ2URRNTLoJ", 477 | "colab_type": "code", 478 | "outputId": "f43ab497-a591-4d60-f98e-139ba3e225d4", 479 | "colab": { 480 | "base_uri": "https://localhost:8080/", 481 | "height": 34 482 | } 483 | }, 484 | "source": [ 485 | "d = np.array([[[0, 1, 2],\n", 486 | " [3, 4, 5]],\n", 487 | " \n", 488 | " [[5, 4, 3],\n", 489 | " [2, 1, 0]]]) # 3重のリストからNumPyの3次元配列を作る\n", 490 | "\n", 491 | "\n", 492 | "e = d.reshape(-1)\n", 493 | "print(e)" 494 | ], 495 | "execution_count": 0, 496 | "outputs": [ 497 | { 498 | "output_type": "stream", 499 | "text": [ 500 | "[0 1 2 3 4 5 5 4 3 2 1 0]\n" 501 | ], 502 | "name": "stdout" 503 | } 504 | ] 505 | }, 506 | { 507 | "cell_type": "markdown", 508 | "metadata": { 509 | "id": "neEBCIjkTLoL", 510 | "colab_type": "text" 511 | }, 512 | "source": [ 513 | "## ●要素へのアクセス" 514 | ] 515 | }, 516 | { 517 | "cell_type": "markdown", 518 | "metadata": { 519 | "id": "DFpo1tr0TLoM", 520 | "colab_type": "text" 521 | }, 522 | "source": [ 523 | "配列の各要素へのアクセスは、リストの場合と同様にインデックスを利用します。 \n", 524 | "一次元配列の場合、以下のように`[ ]`内にインデックスを指定することで、要素を取り出すことができます。" 525 | ] 526 | }, 527 | { 528 | "cell_type": "code", 529 | "metadata": { 530 | "id": "oZNEQLbjTLoM", 531 | "colab_type": "code", 532 | "outputId": "3a19f81f-3c81-41a9-cc8b-816ce75e8a33", 533 | "colab": { 534 | "base_uri": "https://localhost:8080/", 535 | "height": 34 536 | } 537 | }, 538 | "source": [ 539 | "import numpy as np\n", 540 | "\n", 541 | "a = np.array([0, 1, 2, 3, 4, 5])\n", 542 | "print(a[2])" 543 | ], 544 | "execution_count": 0, 545 | "outputs": [ 546 | { 547 | "output_type": "stream", 548 | "text": [ 549 | "2\n" 550 | ], 551 | "name": "stdout" 552 | } 553 | ] 554 | }, 555 | { 556 | "cell_type": "markdown", 557 | "metadata": { 558 | "id": "UF8HmYGYTLoO", 559 | "colab_type": "text" 560 | }, 561 | "source": [ 562 | "この場合は、先頭から0,1,2...とインデックスをつけた場合の、インデックスが2要素を取り出しています。 \n", 563 | "また、リストの場合と同様に、インデックスを指定して要素を入れ替えることができます。" 564 | ] 565 | }, 566 | { 567 | "cell_type": "code", 568 | "metadata": { 569 | "id": "c-vfLZ49TLoP", 570 | "colab_type": "code", 571 | "outputId": "0c125d3f-7180-4ad5-d400-4aeb7b12e6ae", 572 | "colab": { 573 | "base_uri": "https://localhost:8080/", 574 | "height": 34 575 | } 576 | }, 577 | "source": [ 578 | "a[2] = 9\n", 579 | "print(a)" 580 | ], 581 | "execution_count": 0, 582 | "outputs": [ 583 | { 584 | "output_type": "stream", 585 | "text": [ 586 | "[0 1 9 3 4 5]\n" 587 | ], 588 | "name": "stdout" 589 | } 590 | ] 591 | }, 592 | { 593 | "cell_type": "markdown", 594 | "metadata": { 595 | "id": "xGQ4gl3nTLoR", 596 | "colab_type": "text" 597 | }, 598 | "source": [ 599 | "この場合は、インデックスが2の要素を9に置き換えています。 \n", 600 | "\n", 601 | "2次元配列の場合、要素を取り出す際にはインデックスを縦横で2つ指定します。 \n", 602 | "`,`(カンマ)区切りでインデックスを並べることも、インデックスを入れた`[ ]`を2つ並べることもできます。 " 603 | ] 604 | }, 605 | { 606 | "cell_type": "code", 607 | "metadata": { 608 | "id": "oLGquZxlTLoS", 609 | "colab_type": "code", 610 | "outputId": "cdd1bbe5-c1ef-4e9a-8bfa-b4949ba6acc0", 611 | "colab": { 612 | "base_uri": "https://localhost:8080/", 613 | "height": 34 614 | } 615 | }, 616 | "source": [ 617 | "b = np.array([[0, 1, 2],\n", 618 | " [3, 4, 5]])\n", 619 | "\n", 620 | "print(b[1, 2]) # b[1][2]と同じ" 621 | ], 622 | "execution_count": 0, 623 | "outputs": [ 624 | { 625 | "output_type": "stream", 626 | "text": [ 627 | "5\n" 628 | ], 629 | "name": "stdout" 630 | } 631 | ] 632 | }, 633 | { 634 | "cell_type": "markdown", 635 | "metadata": { 636 | "id": "e78N2fZLTLoU", 637 | "colab_type": "text" 638 | }, 639 | "source": [ 640 | "縦のインデックスが1、横のインデックスが2の要素を取り出すことができました。 \n", 641 | "要素を入れ替える際も、同様にインデックスを2つ指定します。" 642 | ] 643 | }, 644 | { 645 | "cell_type": "code", 646 | "metadata": { 647 | "id": "5lyArOvLTLoU", 648 | "colab_type": "code", 649 | "outputId": "911c1c30-61cf-4ebf-a609-ef38defd57e0", 650 | "colab": { 651 | "base_uri": "https://localhost:8080/", 652 | "height": 51 653 | } 654 | }, 655 | "source": [ 656 | "b[1, 2] = 9\n", 657 | "\n", 658 | "print(b)" 659 | ], 660 | "execution_count": 0, 661 | "outputs": [ 662 | { 663 | "output_type": "stream", 664 | "text": [ 665 | "[[0 1 2]\n", 666 | " [3 4 9]]\n" 667 | ], 668 | "name": "stdout" 669 | } 670 | ] 671 | }, 672 | { 673 | "cell_type": "markdown", 674 | "metadata": { 675 | "id": "uw-3SmU2TLoW", 676 | "colab_type": "text" 677 | }, 678 | "source": [ 679 | "2つのインデックスで指定した要素が入れ替わりました。 \n", 680 | "3次元以上の配列の場合も同様に、インデックスを複数指定することで要素にアクセスすることができます。" 681 | ] 682 | }, 683 | { 684 | "cell_type": "markdown", 685 | "metadata": { 686 | "id": "lL0W945_TLoX", 687 | "colab_type": "text" 688 | }, 689 | "source": [ 690 | "## ●関数と配列\n", 691 | "\n", 692 | "関数の引数や返り値としてNumPyの配列を使うことができます。 \n", 693 | "以下の関数`my_func`は、引数として配列を受け取り、返り値として配列を返しています。" 694 | ] 695 | }, 696 | { 697 | "cell_type": "code", 698 | "metadata": { 699 | "id": "Z4ZAV9uPTLoY", 700 | "colab_type": "code", 701 | "outputId": "53608082-4a9a-4fcf-aa68-32439eb8bd75", 702 | "colab": { 703 | "base_uri": "https://localhost:8080/", 704 | "height": 51 705 | } 706 | }, 707 | "source": [ 708 | "import numpy as np\n", 709 | "\n", 710 | "def my_func(x):\n", 711 | " y = x * 2 + 1\n", 712 | " return y\n", 713 | "\n", 714 | "a = np.array([[0, 1, 2],\n", 715 | " [3, 4, 5]]) # 2次元配列\n", 716 | "b = my_func(a) # 引数として配列を渡す\n", 717 | "\n", 718 | "print(b)" 719 | ], 720 | "execution_count": 0, 721 | "outputs": [ 722 | { 723 | "output_type": "stream", 724 | "text": [ 725 | "[[ 1 3 5]\n", 726 | " [ 7 9 11]]\n" 727 | ], 728 | "name": "stdout" 729 | } 730 | ] 731 | }, 732 | { 733 | "cell_type": "markdown", 734 | "metadata": { 735 | "id": "35WMwtyMTLob", 736 | "colab_type": "text" 737 | }, 738 | "source": [ 739 | "## ●NumPyの様々な機能\n", 740 | "\n", 741 | "sumにより合計、averageにより平均、maxにより最大値、minにより最小値を得ることができます。" 742 | ] 743 | }, 744 | { 745 | "cell_type": "code", 746 | "metadata": { 747 | "id": "I1S-WU0RTLoc", 748 | "colab_type": "code", 749 | "outputId": "d5197b9b-3f30-4e6f-e120-f6bfb9643683", 750 | "colab": { 751 | "base_uri": "https://localhost:8080/", 752 | "height": 85 753 | } 754 | }, 755 | "source": [ 756 | "import numpy as np\n", 757 | "\n", 758 | "a = np.array([[0, 1, 2],\n", 759 | " [3, 4, 5]]) # 2次元配列\n", 760 | "\n", 761 | "print(np.sum(a))\n", 762 | "print(np.average(a))\n", 763 | "print(np.max(a))\n", 764 | "print(np.min(a))" 765 | ], 766 | "execution_count": 0, 767 | "outputs": [ 768 | { 769 | "output_type": "stream", 770 | "text": [ 771 | "15\n", 772 | "2.5\n", 773 | "5\n", 774 | "0\n" 775 | ], 776 | "name": "stdout" 777 | } 778 | ] 779 | }, 780 | { 781 | "cell_type": "markdown", 782 | "metadata": { 783 | "id": "JaroffHQTLoe", 784 | "colab_type": "text" 785 | }, 786 | "source": [ 787 | "引数にaxisを指定すると、特定の方向で演算を行うことができます。" 788 | ] 789 | }, 790 | { 791 | "cell_type": "code", 792 | "metadata": { 793 | "id": "rBNNXI20TLof", 794 | "colab_type": "code", 795 | "outputId": "3ab5cb3c-dd93-487f-ea32-b0e939ccf00c", 796 | "colab": { 797 | "base_uri": "https://localhost:8080/", 798 | "height": 51 799 | } 800 | }, 801 | "source": [ 802 | "import numpy as np\n", 803 | "\n", 804 | "b = np.array([[0, 1, 2],\n", 805 | " [3, 4, 5]]) # 2次元配列\n", 806 | "\n", 807 | "print(np.sum(b, axis=0)) # 縦方向で合計\n", 808 | "print(np.sum(b, axis=1)) # 横方向で合計" 809 | ], 810 | "execution_count": 0, 811 | "outputs": [ 812 | { 813 | "output_type": "stream", 814 | "text": [ 815 | "[3 5 7]\n", 816 | "[ 3 12]\n" 817 | ], 818 | "name": "stdout" 819 | } 820 | ] 821 | } 822 | ] 823 | } -------------------------------------------------------------------------------- /python_basic/04_matplotlib.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "kernelspec": { 6 | "display_name": "Python 3", 7 | "language": "python", 8 | "name": "python3" 9 | }, 10 | "language_info": { 11 | "codemirror_mode": { 12 | "name": "ipython", 13 | "version": 3 14 | }, 15 | "file_extension": ".py", 16 | "mimetype": "text/x-python", 17 | "name": "python", 18 | "nbconvert_exporter": "python", 19 | "pygments_lexer": "ipython3", 20 | "version": "3.6.7" 21 | }, 22 | "colab": { 23 | "name": "04_matplotlib.ipynb", 24 | "provenance": [], 25 | "collapsed_sections": [], 26 | "include_colab_link": true 27 | } 28 | }, 29 | "cells": [ 30 | { 31 | "cell_type": "markdown", 32 | "metadata": { 33 | "id": "view-in-github", 34 | "colab_type": "text" 35 | }, 36 | "source": [ 37 | "\"Open" 38 | ] 39 | }, 40 | { 41 | "cell_type": "markdown", 42 | "metadata": { 43 | "id": "8kW_qXJVTjic", 44 | "colab_type": "text" 45 | }, 46 | "source": [ 47 | "# matplotlibの基礎\n", 48 | "グラフの描画や画像の表示、簡単なアニメーションの作成などを行うことができます。 " 49 | ] 50 | }, 51 | { 52 | "cell_type": "markdown", 53 | "metadata": { 54 | "id": "0mu15tSKTjid", 55 | "colab_type": "text" 56 | }, 57 | "source": [ 58 | "## ●matplotlibのインポート\n", 59 | "グラフを描画するためには、matplotlibのpyplotというモジュールをインポートします。 \n", 60 | "pyplotはグラフの描画をサポートします。 \n", 61 | "データにはNumPyの配列を使いますので、NumPyもインポートします。 " 62 | ] 63 | }, 64 | { 65 | "cell_type": "code", 66 | "metadata": { 67 | "id": "we7B75pyTjid", 68 | "colab_type": "code", 69 | "colab": {} 70 | }, 71 | "source": [ 72 | "import numpy as np\n", 73 | "import matplotlib.pyplot as plt" 74 | ], 75 | "execution_count": 0, 76 | "outputs": [] 77 | }, 78 | { 79 | "cell_type": "markdown", 80 | "metadata": { 81 | "id": "bgdKW1W2Tjih", 82 | "colab_type": "text" 83 | }, 84 | "source": [ 85 | "## ●linspace関数\n", 86 | "\n", 87 | "matplotlibでグラフを描画する際に、NumPyのlinspace関数がよく使われます。 \n", 88 | "linspace関数は、ある区間を50に等間隔で区切ってNumPyの配列にします。 \n", 89 | "この配列を、グラフの横軸の値としてよく使います。 " 90 | ] 91 | }, 92 | { 93 | "cell_type": "code", 94 | "metadata": { 95 | "id": "qM9-iLYqTjih", 96 | "colab_type": "code", 97 | "colab": {} 98 | }, 99 | "source": [ 100 | "import numpy as np\n", 101 | "\n", 102 | "x = np.linspace(-5, 5) # -5から5まで50に区切る\n", 103 | "\n", 104 | "print(x)\n", 105 | "print(len(x)) # xの要素数" 106 | ], 107 | "execution_count": 0, 108 | "outputs": [] 109 | }, 110 | { 111 | "cell_type": "markdown", 112 | "metadata": { 113 | "id": "aIhyp2e0Tjij", 114 | "colab_type": "text" 115 | }, 116 | "source": [ 117 | "この配列を使って、連続に変化する横軸の値を擬似的に表現します。" 118 | ] 119 | }, 120 | { 121 | "cell_type": "markdown", 122 | "metadata": { 123 | "id": "z95B1-4gTjik", 124 | "colab_type": "text" 125 | }, 126 | "source": [ 127 | "## ●グラフの描画\n", 128 | "\n", 129 | "例として、pyplotを使って直線を描画します。 \n", 130 | "NumPyのlinspace関数でx座標のデータを配列として生成し、これに値をかけてy座標とします。 \n", 131 | "そして、pyplotのplotで、x座標、y座標のデータをプロットし、showでグラフを表示します。 " 132 | ] 133 | }, 134 | { 135 | "cell_type": "code", 136 | "metadata": { 137 | "id": "9ZvIXOLNTjil", 138 | "colab_type": "code", 139 | "colab": {} 140 | }, 141 | "source": [ 142 | "import numpy as np\n", 143 | "import matplotlib.pyplot as plt\n", 144 | "\n", 145 | "x = np.linspace(-5, 5) # -5から5まで\n", 146 | "y = 2 * x # xに2をかけてy座標とする\n", 147 | "\n", 148 | "plt.plot(x, y)\n", 149 | "plt.show()" 150 | ], 151 | "execution_count": 0, 152 | "outputs": [] 153 | }, 154 | { 155 | "cell_type": "markdown", 156 | "metadata": { 157 | "id": "mBVPsou-Tjin", 158 | "colab_type": "text" 159 | }, 160 | "source": [ 161 | "## ●グラフの装飾\n", 162 | "軸のラベルやグラフのタイトル、凡例などを表示し、線のスタイルを変更してリッチなグラフにしましょう。" 163 | ] 164 | }, 165 | { 166 | "cell_type": "code", 167 | "metadata": { 168 | "id": "OLs9cslOTjio", 169 | "colab_type": "code", 170 | "colab": {} 171 | }, 172 | "source": [ 173 | "import numpy as np\n", 174 | "import matplotlib.pyplot as plt\n", 175 | "\n", 176 | "x = np.linspace(-5, 5)\n", 177 | "y_1 = 2 * x\n", 178 | "y_2 = 3 * x\n", 179 | "\n", 180 | "# 軸のラベル\n", 181 | "plt.xlabel(\"x value\")\n", 182 | "plt.ylabel(\"y value\")\n", 183 | "\n", 184 | "# グラフのタイトル\n", 185 | "plt.title(\"My Graph\")\n", 186 | "\n", 187 | "# プロット 凡例と線のスタイルを指定\n", 188 | "plt.plot(x, y_1, label=\"y1\")\n", 189 | "plt.plot(x, y_2, label=\"y2\", linestyle=\"dashed\")\n", 190 | "plt.legend() # 凡例を表示\n", 191 | "\n", 192 | "plt.show()" 193 | ], 194 | "execution_count": 0, 195 | "outputs": [] 196 | }, 197 | { 198 | "cell_type": "markdown", 199 | "metadata": { 200 | "id": "Em77a0SYTjiq", 201 | "colab_type": "text" 202 | }, 203 | "source": [ 204 | "## ●散布図の表示\n", 205 | "scatter関数により散布図を表示することができます。 \n", 206 | "以下のコードでは、x座標、y座標から散布図を描画しています。 " 207 | ] 208 | }, 209 | { 210 | "cell_type": "code", 211 | "metadata": { 212 | "id": "pIJ6Wmc5Tjir", 213 | "colab_type": "code", 214 | "colab": {} 215 | }, 216 | "source": [ 217 | "import numpy as np\n", 218 | "import matplotlib.pyplot as plt\n", 219 | "\n", 220 | "x = np.array([1.2, 2.4, 0.0, 1.4, 1.5])\n", 221 | "y = np.array([2.4, 1.4, 1.0, 0.1, 1.7])\n", 222 | "\n", 223 | "plt.scatter(x, y) # 散布図のプロット\n", 224 | "plt.show()" 225 | ], 226 | "execution_count": 0, 227 | "outputs": [] 228 | }, 229 | { 230 | "cell_type": "markdown", 231 | "metadata": { 232 | "id": "_ihx7HjdTjit", 233 | "colab_type": "text" 234 | }, 235 | "source": [ 236 | "## ●画像の表示\n", 237 | "pyplotのimshow関数は、配列を画像として表示することができます。 \n", 238 | "以下のコードは、配列を画像として表示するサンプルです。" 239 | ] 240 | }, 241 | { 242 | "cell_type": "code", 243 | "metadata": { 244 | "id": "oCpZKjYcTjit", 245 | "colab_type": "code", 246 | "colab": {} 247 | }, 248 | "source": [ 249 | "import numpy as np\n", 250 | "import matplotlib.pyplot as plt\n", 251 | "\n", 252 | "img = np.array([[0, 1, 2, 3],\n", 253 | " [4, 5, 6, 7],\n", 254 | " [8, 9, 10,11],\n", 255 | " [12,13,14,15]])\n", 256 | "\n", 257 | "plt.imshow(img, \"gray\") # グレースケールで表示\n", 258 | "plt.colorbar() # カラーバーの表示\n", 259 | "plt.show()" 260 | ], 261 | "execution_count": 0, 262 | "outputs": [] 263 | }, 264 | { 265 | "cell_type": "markdown", 266 | "metadata": { 267 | "id": "TM2PRUnyTjiv", 268 | "colab_type": "text" 269 | }, 270 | "source": [ 271 | "この場合、0が黒、15が白を表し、その間の値はこれらの中間色を表します。 \n", 272 | "カラーバーを表示することもできます。" 273 | ] 274 | } 275 | ] 276 | } --------------------------------------------------------------------------------